diff --git a/.gitignore b/.gitignore
index fd8eb11..541ec7e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,8 @@
+*~
+*.swp
2048*
*.o
*.core
+hello.efi
+hello.so
+tags
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..5d7dfa6
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,40 @@
+ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
+
+C_FILES := $(wildcard *.c)
+MERGE_FILE := merge_std.c
+FILTERED_C_FILES := $(filter-out gfx%.c merge%.c highscore%.c, $(C_FILES)) $(MERGE_FILE) gfx_uefi.c highscore_uefi.c
+
+OBJS = $(FILTERED_C_FILES:.c=.o)
+TARGET = 2048.efi
+
+EFIINC = /usr/include/efi
+EFIINCS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
+LIB = /usr/lib
+EFILIB = /usr/lib
+EFI_CRT_OBJS = $(EFILIB)/crt0-efi-$(ARCH).o
+EFI_LDS = $(EFILIB)/elf_$(ARCH)_efi.lds
+
+#CFLAGS = -nostdinc $(EFIINCS) -fno-stack-protector -fpic
+CFLAGS = $(EFIINCS) -fno-stack-protector -fpic \
+ -fshort-wchar -mno-red-zone -Wall
+CFLAGS += -DINVERT_COLORS -O2
+
+ifeq ($(ARCH),x86_64)
+ CFLAGS += -DEFI_FUNCTION_WRAPPER
+endif
+
+LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \
+ -Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)
+
+all: $(TARGET)
+
+2048.so: $(OBJS)
+ ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi
+
+%.efi: %.so
+ objcopy -j .text -j .sdata -j .data -j .dynamic \
+ -j .dynsym -j .rel -j .rela -j .reloc \
+ --target=efi-app-$(ARCH) $^ $@
+
+clean:
+ rm -f *.o 2048.efi 2048.so
diff --git a/src/Rand.c b/src/Rand.c
new file mode 100644
index 0000000..7447494
--- /dev/null
+++ b/src/Rand.c
@@ -0,0 +1,68 @@
+/*-
+ * Portions Copyright (c) 2010, Intel Corporation. All rights reserved.
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+//__FBSDID("$FreeBSD: src/lib/libc/stdlib/rand.c,v 1.17.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $");
+//#include
+#include
+
+#include
+
+static UINT32 next = 1;
+
+/** Compute a pseudo-random number.
+ *
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * without overflowing 31 bits:
+ * (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+**/
+int
+rand()
+{
+ INT32 hi, lo, x;
+
+ /* Can't be initialized with 0, so use another value. */
+ if (next == 0)
+ next = 123459876;
+ hi = next / 127773;
+ lo = next % 127773;
+ x = 16807 * lo - 2836 * hi;
+ if (x < 0)
+ x += 0x7fffffff;
+ return ((next = x) % ((UINT32)RAND_MAX + 1));
+}
+
+void
+srand(unsigned int seed)
+{
+ next = (UINT32)seed;
+}
diff --git a/src/engine.c b/src/engine.c
index 0afc777..8a2d7c2 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -5,6 +5,9 @@
#include "engine.h"
#include "highscore.h"
+#include
+#include
+
/* Utilize block counter to improve some of the functions so they can run
* quicker */
@@ -213,23 +216,26 @@ static int digits_ceiling(unsigned int n)
/* Return NULL if we couldn't allocate space for the gamestate. initializating the
* gamestate will parse the options internally, so any caller should pass argc and argv
* through this function */
-struct gamestate* gamestate_init(int argc, char **argv)
+struct gamestate* gamestate_init(int argc, CHAR16 **argv)
{
+ EFI_TIME Time;
+
struct gameoptions *opt = gameoptions_default();
if (!opt) return NULL;
if (argc != 0) parse_options(opt, argc, argv);
- srand(time(NULL));
+ uefi_call_wrapper(ST->RuntimeServices->GetTime, 2, &Time, NULL);
+ srand(Time.Day*24*3600+Time.Hour*3600+Time.Minute*60+Time.Second+Time.Nanosecond);
- struct gamestate *g = malloc(sizeof(struct gamestate));
+ struct gamestate *g = AllocatePool(sizeof(struct gamestate));
if (!g) goto gamestate_alloc_fail;
g->gridsize = opt->grid_width * opt->grid_height;
- g->grid_data_ptr = calloc(g->gridsize, sizeof(int));
+ g->grid_data_ptr = AllocateZeroPool(g->gridsize*sizeof(int));
if (!g->grid_data_ptr) goto grid_data_alloc_fail;
- g->grid = malloc(opt->grid_height * sizeof(int*));
+ g->grid = AllocatePool(opt->grid_height * sizeof(int*));
if (!g->grid) goto grid_alloc_fail;
/* Switch to two allocation version */
@@ -260,9 +266,9 @@ struct gamestate* gamestate_init(int argc, char **argv)
return g;
grid_alloc_fail:
- free(g->grid_data_ptr);
+ FreePool(g->grid_data_ptr);
grid_data_alloc_fail:
- free(g);
+ FreePool(g);
gamestate_alloc_fail:
return NULL;
}
@@ -285,7 +291,7 @@ void gamestate_clear(struct gamestate *g)
{
highscore_save(g);
gameoptions_destroy(g->opts);
- free(g->grid_data_ptr); /* Free grid data */
- free(g->grid); /* Free pointers to data slots */
- free(g);
+ FreePool(g->grid_data_ptr); /* Free grid data */
+ FreePool(g->grid); /* Free pointers to data slots */
+ FreePool(g);
}
diff --git a/src/engine.h b/src/engine.h
index 0d50fad..5f589e3 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -40,6 +40,6 @@ int gamestate_end_condition(struct gamestate*);
void gamestate_new_block(struct gamestate*);
int gamestate_tick(struct gfx_state*, struct gamestate*, int, void (*callback)(struct gfx_state*, struct gamestate*));
void gamestate_clear(struct gamestate*);
-struct gamestate* gamestate_init(int argc, char **argv);
+struct gamestate* gamestate_init(int argc, CHAR16 **argv);
#endif
diff --git a/src/gfx_uefi.c b/src/gfx_uefi.c
new file mode 100644
index 0000000..1115f86
--- /dev/null
+++ b/src/gfx_uefi.c
@@ -0,0 +1,193 @@
+#include "gfx.h"
+#include "merge.h"
+
+#include
+#include
+
+#define NUMBER_OF_COLORS 7
+
+#define iterate(n, expression)\
+ do {\
+ int i;\
+ for (i = 0; i < n; ++i) { expression; }\
+ } while (0)
+
+static void print_pos(INTN Row, INTN Column, CHAR16 *str)
+{
+ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, Column, Row);
+ uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, str);
+}
+
+struct gfx_state {
+ INTN window_height, window_width;
+};
+
+INTN uefi_color_array[] = {
+#ifdef INVERT_COLORS
+ EFI_BLACK | EFI_BACKGROUND_RED,
+ EFI_BLACK | EFI_BACKGROUND_GREEN,
+ EFI_BLACK | EFI_BACKGROUND_BROWN,
+ EFI_BLACK | EFI_BACKGROUND_BLUE,
+ EFI_BLACK | EFI_BACKGROUND_MAGENTA,
+ EFI_BLACK | EFI_BACKGROUND_CYAN,
+ EFI_BLACK | EFI_BACKGROUND_LIGHTGRAY,
+#else
+ EFI_RED | EFI_BACKGROUND_BLACK,
+ EFI_GREEN | EFI_BACKGROUND_BLACK,
+ EFI_YELLOW | EFI_BACKGROUND_BLACK,
+ EFI_BLUE | EFI_BACKGROUND_BLACK,
+ EFI_MAGENTA | EFI_BACKGROUND_BLACK,
+ EFI_CYAN | EFI_BACKGROUND_BLACK,
+ EFI_WHITE | EFI_BACKGROUND_BLACK,
+#endif
+};
+
+struct gfx_state* gfx_init(struct gamestate *g)
+{
+ struct gfx_state *s = AllocatePool(sizeof(struct gfx_state));
+ if (!s) return NULL;
+
+ uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+ uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &s->window_width, &s->window_height);
+ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0);
+ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, false);
+
+ s->window_height = g->opts->grid_height * (g->print_width + 2) + 3;
+ s->window_width = g->opts->grid_width * (g->print_width + 2) + 1;
+
+ return s;
+}
+
+void gfx_draw(struct gfx_state *s, struct gamestate *g)
+{
+ if (g->score_last) {
+ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0);
+ Print(L"Score: %ld (+%ld) \n", g->score, g->score_last);
+ } else {
+ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0);
+ Print(L"Score: %ld \n", g->score);
+ }
+
+ if (g->score >= g->score_high)
+ g->score_high = g->score;
+
+ Print(L" Hi: %ld\n", g->score_high);
+
+ //wattron(s->window, A_DIM);
+ Print(L"%c", BOXDRAW_DOWN_RIGHT);
+ iterate(g->opts->grid_width * (g->print_width + 2) + 1 - 2, Print(L"%c", (i+g->print_width+3) % (g->print_width+2) ? BOXDRAW_HORIZONTAL : BOXDRAW_DOWN_HORIZONTAL));
+ Print(L"%c", BOXDRAW_DOWN_LEFT);
+ //wattroff(s->window, A_DIM);
+
+ int x, y,
+ xpos = 0,
+ ypos = 3;
+
+ for (y = 0; y < g->opts->grid_height; ++y, ++ypos, xpos = 0) {
+ //wattron(s->window, A_DIM);
+ print_pos(ypos, xpos++, L"");
+ Print(L"%c", BOXDRAW_VERTICAL);
+ //wattroff(s->window, A_DIM);
+
+ for (x = 0; x < g->opts->grid_width; ++x) {
+ if (g->grid[x][y]) {
+ if (g->opts->enable_color) {
+ UINTN attr = uefi_color_array[g->grid[x][y] % NUMBER_OF_COLORS];
+ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, attr);
+ }
+ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, xpos, ypos);
+ Print(L"%-*ld", g->print_width, merge_value(g->grid[x][y]));
+ print_pos(ypos, xpos + g->print_width, L" ");
+ if (g->opts->enable_color) {
+ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
+ }
+
+ //wattron(s->window, A_DIM);
+ print_pos(ypos, xpos + g->print_width + 1, L"");
+ Print(L"%c", BOXDRAW_VERTICAL);
+ //wattroff(s->window, A_DIM);
+ }
+ else {
+ //wattron(s->window, A_DIM);
+ iterate(g->print_width + 1, Print(L" "));
+ Print(L"%c", BOXDRAW_VERTICAL);
+ //wattroff(s->window, A_DIM);
+ }
+
+ xpos += (g->print_width + 2);
+ }
+ }
+
+ Print(L"\n");
+ //wattron(s->window, A_DIM);
+ Print(L"%c", BOXDRAW_UP_RIGHT);
+ iterate(g->opts->grid_width * (g->print_width + 2) + 1 - 2, Print(L"%c", (i+g->print_width+3) % (g->print_width+2) ? BOXDRAW_HORIZONTAL : BOXDRAW_UP_HORIZONTAL));
+ Print(L"%c", BOXDRAW_UP_LEFT);
+ //wattroff(s->window, A_DIM);
+ Print(L"\n");
+}
+
+int gfx_getch(struct gfx_state *s)
+{
+ EFI_INPUT_KEY Key;
+
+ Pause();
+ uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
+
+ /* Flush buffer */
+ //nodelay(s->window, TRUE);
+ //while (wgetch(s->window) != ERR);
+ //nodelay(s->window, FALSE);
+
+ switch (Key.ScanCode)
+ {
+ case SCAN_UP:
+ return INPUT_UP;
+ break;
+ case SCAN_DOWN:
+ return INPUT_DOWN;
+ break;
+ case SCAN_RIGHT:
+ return INPUT_RIGHT;
+ break;
+ case SCAN_LEFT:
+ return INPUT_LEFT;
+ break;
+
+ default:
+ return Key.UnicodeChar;
+ break;
+
+ }
+}
+
+#define EFI_TIMER_PERIOD_MILLISECONDS(Milliseconds) MultU64x32((UINT64)(Milliseconds), 10000)
+
+void gfx_sleep(int ms)
+{
+ EFI_STATUS Status;
+ EFI_EVENT TimerEvent;
+ UINTN Index;
+
+ Status = uefi_call_wrapper(BS->CreateEvent, 5, EFI_EVENT_TIMER, 0, NULL, NULL, &TimerEvent);
+ if(EFI_ERROR(Status)) {
+ return;
+ }
+
+ Status = uefi_call_wrapper(BS->SetTimer, 3, TimerEvent, TimerRelative, EFI_TIMER_PERIOD_MILLISECONDS(ms));
+ if(EFI_ERROR(Status)) {
+ return;
+ }
+
+ Status = uefi_call_wrapper(BS->WaitForEvent, 3, 1, &TimerEvent, &Index);
+ if(EFI_ERROR(Status)) {
+ return;
+ }
+ Status = uefi_call_wrapper(BS->CloseEvent, TimerEvent);
+}
+
+void gfx_destroy(struct gfx_state *s)
+{
+ FreePool(s);
+ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, true);
+}
diff --git a/src/highscore_uefi.c b/src/highscore_uefi.c
new file mode 100644
index 0000000..aa46830
--- /dev/null
+++ b/src/highscore_uefi.c
@@ -0,0 +1,69 @@
+#include "engine.h"
+
+#include
+#include
+
+EFI_GUID EFI_2048_GUID =
+ { 0x6F633F38, 0x2169, 0x42FF, {0xA2, 0x1D, 0x66, 0x34, 0x65, 0xCF, 0x3C, 0x71} };
+CHAR16 *hs_file_name = L"highscore";
+
+void highscore_reset(void)
+{
+ EFI_INPUT_KEY Key;
+ EFI_STATUS Status;
+
+ Print(L"Are you sure you want to reset your scores? Y(es) or N(o)\n");
+
+ while (1) {
+ Pause();
+ Status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
+ if (EFI_ERROR(Status))
+ return;
+
+ if (Key.ScanCode == 0x00) {
+ if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') {
+ goto reset_scores;
+ } else if (Key.UnicodeChar == 'n' || Key.UnicodeChar == 'N') {
+ return;
+ }
+ }
+
+ Print(L"Please enter Y or N\n");
+ }
+
+reset_scores:;
+ LibDeleteVariable(hs_file_name, &EFI_2048_GUID);
+}
+
+long highscore_load(struct gamestate *g)
+{
+ long result = 0;
+ long *result_ptr;
+ size_t result_size;
+
+ result_ptr = LibGetVariableAndSize(hs_file_name, &EFI_2048_GUID, &result_size);
+ if (result_ptr != NULL) {
+ if(result_size == sizeof(result)) {
+ result = *result_ptr;
+ }
+ FreePool(result_ptr);
+ }
+
+ if (g) g->score_high = result;
+ return result;
+}
+
+void highscore_save(struct gamestate *g)
+{
+ EFI_STATUS Status;
+
+ /* Someone could make their own merge rules for highscores and this could be meaningless,
+ * howeverhighscores are in plaintext, so that isn't that much of a concern */
+ if (g->score < g->score_high || g->opts->grid_width != 4 ||
+ g->opts->grid_height != 4 || g->opts->ai == true)
+ return;
+
+ Status = LibSetNVVariable(hs_file_name, &EFI_2048_GUID, sizeof(g->score), &g->score);
+ if (EFI_ERROR(Status))
+ Print(L"save: Failed to write highscore file\n");
+}
diff --git a/src/main.c b/src/main.c
index 794f1cf..147239b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,12 +1,12 @@
-#include
#include
#include "ai.h"
#include "engine.h"
#include "gfx.h"
-#include
-#include
#include
+#include
+#include
+
void draw_then_sleep(struct gfx_state *s, struct gamestate *g)
{
gfx_draw(s, g);
@@ -14,6 +14,7 @@ void draw_then_sleep(struct gfx_state *s, struct gamestate *g)
gfx_sleep(160 / g->opts->grid_width);
}
+#if 0
char *targetDir(char *env, char *path)
{
char *dir;
@@ -24,14 +25,21 @@ char *targetDir(char *env, char *path)
strcat(dir,path);
return dir;
}
+#endif
-int main(int argc, char **argv)
+EFI_STATUS
+EFIAPI
+efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
+ INTN argc;
+ CHAR16 **argv;
+ InitializeLib(ImageHandle, SystemTable);
+ argc = GetShellArgcArgv(ImageHandle, &argv);
- setlocale (LC_ALL, "");
- bindtextdomain ("gfx_terminal", targetDir("PWD","/18n/"));
- textdomain ("gfx_terminal");
+ //setlocale (LC_ALL, "");
+ //bindtextdomain ("gfx_terminal", targetDir("PWD","/18n/"));
+ //textdomain ("gfx_terminal");
struct gamestate *g = gamestate_init(argc, argv);
if (!g) {
@@ -108,7 +116,7 @@ get_new_key:;
gfx_destroy(s);
}
- printf("%ld\n", g->score);
+ Print(L"%ld\n", g->score);
gamestate_clear(g);
- return 0;
+ return EFI_SUCCESS;
}
diff --git a/src/options.c b/src/options.c
index 053f498..37ec64f 100644
--- a/src/options.c
+++ b/src/options.c
@@ -1,19 +1,20 @@
-#include
-#include
#include
#include "highscore.h"
#include "options.h"
+#include
+#include
+
void print_usage(void)
{
- printf("usage: 2048 [-cCaAiIrh] [-s SIZE] [-b RATE]\n");
+ Print(L"usage: 2048 [-c] [-C] [-a] [-A] [-i] [-I] [-r] [-h] [-H] [-s SIZE] [-b RATE]\n");
}
/* Initial game options */
struct gameoptions* gameoptions_default(void)
{
- struct gameoptions *opt = malloc(sizeof(struct gameoptions));
+ struct gameoptions *opt = AllocatePool(sizeof(struct gameoptions));
if (!opt) return NULL;
opt->grid_height = DEFAULT_GRID_HEIGHT;
@@ -30,14 +31,18 @@ struct gameoptions* gameoptions_default(void)
void gameoptions_destroy(struct gameoptions *opt)
{
- free(opt);
+ FreePool(opt);
}
-struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv)
+struct gameoptions* parse_options(struct gameoptions *opt, int argc, CHAR16 **argv)
{
- int c;
- while ((c = getopt(argc, argv, "aArcCiIhHs:b:")) != -1) {
- switch (c) {
+ argc--; argv++; /* skip program name */
+ while (argc > 0) {
+ if(argv[0][0] != '-' || argv[0][1] == '\0' || argv[0][2] != '\0') {
+ print_usage();
+ Exit(EFI_INVALID_PARAMETER, 0, NULL);
+ }
+ switch (argv[0][1]) {
case 'a':
opt->animate = true;
break;
@@ -60,25 +65,36 @@ struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv
break;
case 's':;
/* Stick with square for now */
- int optint = strtol(optarg, NULL, 10);
+ if(argc < 2) {
+ print_usage();
+ Exit(EFI_INVALID_PARAMETER, 0, NULL);
+ }
+ int optint = Atoi(argv[1]);
if (optint < CONSTRAINT_GRID_MAX && optint > CONSTRAINT_GRID_MIN) {
opt->grid_height = optint;
opt->grid_width = optint;
}
+ argc--; argv++;
break;
case 'b':
- opt->spawn_rate = strtol(optarg, NULL, 10);
+ if(argc < 2) {
+ print_usage();
+ Exit(EFI_INVALID_PARAMETER, 0, NULL);
+ }
+ opt->spawn_rate = Atoi(argv[1]);
+ argc--; argv++;
break;
case 'r':
highscore_reset();
- exit(0);
+ Exit(EFI_SUCCESS, 0, NULL);
case 'h':
print_usage();
- exit(0);
+ Exit(EFI_SUCCESS, 0, NULL);
case 'H':
- printf("%ld\n", highscore_load(NULL));
- exit(0);
+ Print(L"%ld\n", highscore_load(NULL));
+ Exit(EFI_SUCCESS, 0, NULL);
}
+ argc--; argv++;
}
return opt;
diff --git a/src/options.h b/src/options.h
index 2126cd3..ecbd732 100644
--- a/src/options.h
+++ b/src/options.h
@@ -3,6 +3,7 @@
#include
#include
+#include
#define CONSTRAINT_GRID_MIN 4
#define CONSTRAINT_GRID_MAX 20
@@ -27,7 +28,7 @@ struct gameoptions {
};
void print_usage(void);
-struct gameoptions* parse_options(struct gameoptions*, int, char**);
+struct gameoptions* parse_options(struct gameoptions*, int, CHAR16**);
struct gameoptions* gameoptions_default(void);
void gameoptions_destroy(struct gameoptions *opt);
diff --git a/src/qemu.sh b/src/qemu.sh
new file mode 100755
index 0000000..06c645e
--- /dev/null
+++ b/src/qemu.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if [ ! -e OVMF_VARS.fd ]; then
+ cp /usr/share/OVMF/OVMF_VARS.fd .
+fi
+#qemu-system-x86_64 -bios /usr/share/qemu/OVMF.fd -net none -hda fat:rw:.
+#qemu-system-x86_64 -pflash ~/devel/edk2/Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd -net none -hda fat:rw:.
+qemu-system-x86_64 -drive if=pflash,format=raw,readonly,file=/usr/share/OVMF/OVMF_CODE.fd \
+ -drive if=pflash,format=raw,file=OVMF_VARS.fd \
+ -net none -hda fat:rw:.
diff --git a/src/startup.nsh b/src/startup.nsh
new file mode 100644
index 0000000..b5db7f9
--- /dev/null
+++ b/src/startup.nsh
@@ -0,0 +1,2 @@
+fs0:
+2048 -c