diff --git a/Makefile b/Makefile index 55ae505..3377b3f 100644 --- a/Makefile +++ b/Makefile @@ -272,10 +272,9 @@ endif ifeq ($(PLATFORM),windows32) CFLAGS += -IWindows -Drandom=rand --target=x86_64-pc-windows -LDFLAGS += -lmsvcrt -lkernel32 -lcomdlg32 -luser32 -lshell32 -lole32 -ladvapi32 -ldwmapi -lSDL2main -Wl,/MANIFESTFILE:NUL --target=x86_64-pc-windows -v - -SDL_LDFLAGS := -lSDL2 -GL_LDFLAGS := -lopengl32 +LDFLAGS += -lmsvcrt -lkernel32 -Wl,/MANIFESTFILE:NUL --target=x86_64-pc-windows +SDL_LDFLAGS := -lSDL2 -lcomdlg32 -luser32 -lshell32 -lole32 -ladvapi32 -ldwmapi -lSDL2main +GL_LDFLAGS := -lopengl32 ifneq ($(REDIST_XAUDIO),) CFLAGS += -DREDIST_XAUDIO LDFLAGS += -lxaudio2_9redist @@ -326,7 +325,7 @@ LDFLAGS += -Wl,/NODEFAULTLIB:libcmt.lib ifneq ($(USE_MSVCRT_DLL),) CFLAGS += -D_NO_CRT_STDIO_INLINE -DUSE_MSVCRT_DLL $(BIN)/SDL/sameboy.exe: $(OBJ)/Windows/msvcrt.lib -$(BIN)/SDL/sameboy_debugger.exe: $(OBJ)/Windows/msvcrt.lib +$(LIBDIR)/libsameboy.dll: $(OBJ)/Windows/msvcrt.lib endif endif @@ -378,7 +377,7 @@ endif # Define our targets ifeq ($(PLATFORM),windows32) -SDL_TARGET := $(BIN)/SDL/sameboy.exe $(BIN)/SDL/sameboy_debugger.exe $(BIN)/SDL/SDL2.dll +SDL_TARGET := $(BIN)/SDL/sameboy.exe $(BIN)/SDL/SDL2.dll $(BIN)/SDL/sameboy_debugger.txt TESTER_TARGET := $(BIN)/tester/sameboy_tester.exe else SDL_TARGET := $(BIN)/SDL/sameboy @@ -452,15 +451,15 @@ endif $(OBJ)/SDL/%.dep: SDL/% -@$(MKDIR) -p $(dir $@) - $(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@ + $(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -MT $(OBJ)/$^.o -M $^ -o $@ $(OBJ)/OpenDialog/%.dep: OpenDialog/% -@$(MKDIR) -p $(dir $@) - $(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@ + $(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -MT $(OBJ)/$^.o -M $^ -o $@ $(OBJ)/%.dep: % -@$(MKDIR) -p $(dir $@) - $(CC) $(CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@ + $(CC) $(CFLAGS) -MT $(OBJ)/$^.o -M $^ -o $@ # Compilation rules @@ -661,14 +660,18 @@ ifeq ($(CONF), release) $(CODESIGN) $@ endif -# Windows version builds two, one with a console and one without it $(BIN)/SDL/sameboy.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o -@$(MKDIR) -p $(dir $@) $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) -Wl,/subsystem:windows - -$(BIN)/SDL/sameboy_debugger.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o - -@$(MKDIR) -p $(dir $@) - $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) -Wl,/subsystem:console + +$(BIN)/SDL/sameboy_debugger.txt: + echo Looking for sameboy_debugger.exe? > $@ + echo\>> $@ + echo Starting with SameBoy v1.0.1, sameboy.exe and sameboy_debugger.exe >> $@ + echo have been merged into a single executable. You can open a debugger >> $@ + echo console at any time by pressing Ctrl+C to interrupt the currently >> $@ + echo open ROM. Once you're done debugging, you can close the debugger >> $@ + echo console and resume normal execution. >> $@ ifneq ($(USE_WINDRES),) $(OBJ)/%.o: %.rc @@ -894,7 +897,7 @@ $(OBJ)/exports.def: $(OBJ)/exports $(OBJ)/names $(LIBDIR)/libsameboy.dll: $(CORE_OBJECTS) | $(OBJ)/exports.def -@$(MKDIR) -p $(dir $@) - $(CC) $(LDFLAGS) -Wl,-lldmingw -Wl,/def:$(OBJ)/exports.def -shared $(CFLAGS) $^ -o $@ + $(CC) $(LDFLAGS) -Wl,/def:$(OBJ)/exports.def -shared $(CFLAGS) $^ -o $@ # CPPP doesn't like multibyte characters, so we replace the single quote character before processing so it doesn't complain $(INC)/%.h: Core/%.h diff --git a/SDL/console.c b/SDL/console.c index dabda91..ff361a2 100644 --- a/SDL/console.c +++ b/SDL/console.c @@ -17,6 +17,7 @@ #define SGR(x) CSI(x "m") static bool initialized = false; +static bool no_csi = false; typedef struct listent_s listent_t; struct listent_s { @@ -111,12 +112,12 @@ static bool is_term(void) SetConsoleMode(stdin_handle, input_mode); SetConsoleMode(stdout_handle, output_mode); - if (before.dwCursorPosition.X != after.dwCursorPosition.X || before.dwCursorPosition.Y != after.dwCursorPosition.Y) { printf("\r \r"); - return false; + no_csi = true; } + return true; #else return getenv("TERM"); @@ -158,10 +159,12 @@ static unsigned long input_mode, output_mode; static void cleanup(void) { - printf(CSI("!p")); // reset + if (!no_csi) { + printf(CSI("!p")); // reset + } + fflush(stdout); SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), input_mode); SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), output_mode); - fflush(stdout); } static bool initialize(void) @@ -179,10 +182,14 @@ static bool initialize(void) GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &output_mode); once = true; } + if (no_csi) { + initialized = true; + return true; + } SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_VIRTUAL_TERMINAL_INPUT); SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); - printf(CSI("%dB") "\n" CSI("A") ESC("7") CSI("B"), height); + fprintf(stdout, CSI("%dB") "\n" CSI("A") ESC("7") CSI("B"), height); fflush(stdout); initialized = true; @@ -210,7 +217,9 @@ static struct termios terminal; static void cleanup(void) { - printf(CSI("!p")); // reset + if (!no_csi) { + printf(CSI("!p")); // reset + } tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminal); fflush(stdout); } @@ -264,6 +273,8 @@ static bool repeat_empty = false; static bool redraw_prompt(bool force) { + if (no_csi) return true; + if (line.reverse_search) { if (!force) return false; if (line.length == 0) { @@ -525,6 +536,7 @@ restart: static pthread_mutex_t terminal_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t lines_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t lines_cond = PTHREAD_COND_INITIALIZER; +static void (*line_ready_callback)(void) = NULL; static char reverse_search_mainloop(void) { @@ -549,14 +561,6 @@ static char reverse_search_mainloop(void) delete_word(false); redraw_prompt(true); break; -#ifndef _WIN32 - case CTL('Z'): - set_line(""); - raise(SIGSTOP); - initialize(); // Reinitialize - redraw_prompt(true); - break; -#endif case CTL('H'): case 0x7F: // Backspace delete(1, false); @@ -583,6 +587,39 @@ static char reverse_search_mainloop(void) } } +static void no_csi_mainloop(void) +{ + while (true) { + char *expression = NULL; + size_t size = 0; + + errno = 0; + if (getline(&expression, &size, stdin) <= 0) { + if (!errno) { + continue; + } + return; + } + + pthread_mutex_lock(&lines_lock); + if (!expression) { + add_entry(&lines, ""); + } + else { + size_t length = strlen(expression); + if (expression[length - 1] == '\n') { + expression[length - 1] = 0; + } + add_entry(&lines, expression); + free(expression); + } + pthread_cond_signal(&lines_cond); + pthread_mutex_unlock(&lines_lock); + if (line_ready_callback) { + line_ready_callback(); + } + } +} static @@ -593,6 +630,11 @@ void * #endif mainloop(char *(*completer)(const char *substring, uintptr_t *context)) { + if (no_csi) { + no_csi_mainloop(); + return 0; + } + listent_t *history_line = NULL; uintptr_t complete_context = 0; size_t completion_length = 0; @@ -614,6 +656,10 @@ mainloop(char *(*completer)(const char *substring, uintptr_t *context)) else { c = raw_getc(); } + if (c == EOF) { + return 0; + } + pthread_mutex_lock(&terminal_lock); switch (c) { @@ -649,6 +695,9 @@ mainloop(char *(*completer)(const char *substring, uintptr_t *context)) add_entry(&lines, CON_EOF); pthread_cond_signal(&lines_cond); pthread_mutex_unlock(&lines_lock); + if (line_ready_callback) { + line_ready_callback(); + } } break; case CTL('E'): @@ -695,14 +744,6 @@ mainloop(char *(*completer)(const char *substring, uintptr_t *context)) delete_word(false); complete_context = completion_length = 0; break; -#ifndef _WIN32 - case CTL('Z'): - set_line(""); - complete_context = completion_length = 0; - raise(SIGSTOP); - initialize(); // Reinitialize - break; -#endif case '\r': case '\n': pthread_mutex_lock(&lines_lock); @@ -714,6 +755,9 @@ mainloop(char *(*completer)(const char *substring, uintptr_t *context)) } pthread_cond_signal(&lines_cond); pthread_mutex_unlock(&lines_lock); + if (line_ready_callback) { + line_ready_callback(); + } if (line.length) { listent_t *dup = reverse_find(history.last, line.content, true); if (dup) { @@ -811,22 +855,24 @@ mainloop(char *(*completer)(const char *substring, uintptr_t *context)) } break; case '\t': { - char temp = line.content[line.position - completion_length]; - line.content[line.position - completion_length] = 0; - char *completion = completer? completer(line.content, &complete_context) : NULL; - line.content[line.position - completion_length] = temp; - if (completion) { - if (completion_length) { - delete(completion_length, false); + if (!no_csi) { + char temp = line.content[line.position - completion_length]; + line.content[line.position - completion_length] = 0; + char *completion = completer? completer(line.content, &complete_context) : NULL; + line.content[line.position - completion_length] = temp; + if (completion) { + if (completion_length) { + delete(completion_length, false); + } + insert(completion); + completion_length = strlen(completion); + free(completion); } - insert(completion); - completion_length = strlen(completion); - free(completion); + else { + printf("\a"); + } + break; } - else { - printf("\a"); - } - break; } default: if (c >= ' ') { @@ -845,6 +891,12 @@ mainloop(char *(*completer)(const char *substring, uintptr_t *context)) return 0; } + +void CON_set_line_ready_callback(void (*callback)(void)) +{ + line_ready_callback = callback; +} + char *CON_readline(const char *new_prompt) { pthread_mutex_lock(&terminal_lock); @@ -896,8 +948,8 @@ bool CON_start(char *(*completer)(const char *substring, uintptr_t *context)) void CON_attributed_print(const char *string, CON_attributes_t *attributes) { - if (!initialized) { - printf("%s", string); + if (!initialized || no_csi) { + fprintf(stdout, "%s", string); return; } static bool pending_newline = false; @@ -1021,3 +1073,8 @@ void CON_set_repeat_empty(bool repeat) { repeat_empty = repeat; } + +bool CON_no_csi_mode(void) +{ + return no_csi; +} diff --git a/SDL/console.h b/SDL/console.h index d158988..e925b8a 100644 --- a/SDL/console.h +++ b/SDL/console.h @@ -47,3 +47,5 @@ void CON_printf(const char *fmt, ...) __printflike(1, 2); void CON_attributed_printf(const char *fmt, CON_attributes_t *attributes,...) __printflike(1, 3); void CON_set_async_prompt(const char *string); void CON_set_repeat_empty(bool repeat); +void CON_set_line_ready_callback(void (*callback)(void)); +bool CON_no_csi_mode(void); diff --git a/SDL/gui.c b/SDL/gui.c index 61f8af6..80f2e4f 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -14,7 +14,7 @@ #ifdef _WIN32 #include -#include +#include "windows_associations.h" #include #endif diff --git a/SDL/gui.h b/SDL/gui.h index 3438947..980d950 100644 --- a/SDL/gui.h +++ b/SDL/gui.h @@ -34,6 +34,10 @@ enum pending_command { GB_SDL_QUIT_COMMAND, GB_SDL_LOAD_STATE_FROM_FILE_COMMAND, GB_SDL_CART_SWAP_COMMAND, + GB_SDL_DEBUGGER_INTERRUPT_COMMAND, +#ifdef _WIN32 + GB_SDL_HIDE_DEBUGGER_COMMAND, +#endif }; #define GB_SDL_DEFAULT_SCALE_MAX 8 diff --git a/SDL/main.c b/SDL/main.c index 414258d..bf2976b 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -13,12 +13,11 @@ #include "shader.h" #include "audio/audio.h" #include "console.h" - -#ifndef _WIN32 #include -#else + +#ifdef _WIN32 #include -#include +#include "windows_associations.h" #endif static bool stop_on_start = false; @@ -42,6 +41,15 @@ bool uses_gl(void) return gl_context; } +void rerender_screen(void) +{ + render_texture(active_pixel_buffer, configuration.blending_mode? previous_pixel_buffer : NULL); +#ifdef _WIN32 + /* Required for some Windows 10 machines, god knows why */ + render_texture(active_pixel_buffer, configuration.blending_mode? previous_pixel_buffer : NULL); +#endif +} + void set_filename(const char *new_filename, typeof(free) *new_free_function) { if (filename && free_function) { @@ -93,22 +101,74 @@ static void handle_eof(void) static char *input_callback(GB_gameboy_t *gb) { + if (CON_no_csi_mode()) { + fprintf(stdout, "> "); + fflush(stdout); + } +#ifdef _WIN32 + DWORD pid; + GetWindowThreadProcessId(GetForegroundWindow(), &pid); + if (pid == GetCurrentProcessId()) { + BringWindowToTop(GetConsoleWindow()); + } +#endif retry: { - char *ret = CON_readline("Stopped> "); - if (strcmp(ret, CON_EOF) == 0) { - handle_eof(); - free(ret); + CON_set_async_prompt("Stopped> "); + char *ret = CON_readline_async(); + if (!ret) { +#ifdef _WIN32 + HWND window = GetConsoleWindow(); + if (pending_command == GB_SDL_HIDE_DEBUGGER_COMMAND || !window) return strdup("c"); + ShowWindow(window, SW_SHOW); +#endif + SDL_Event event; + SDL_WaitEvent(&event); + switch (event.type) { + case SDL_DISPLAYEVENT: + update_swap_interval(); + break; + + case SDL_WINDOWEVENT: { + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { + update_viewport(); + } + if (event.window.type == SDL_WINDOWEVENT_MOVED +#if SDL_COMPILEDVERSION > 2018 + || event.window.type == SDL_WINDOWEVENT_DISPLAY_CHANGED +#endif + ) { + update_swap_interval(); + } + rerender_screen(); + break; + } + case SDL_QUIT: + pending_command = GB_SDL_QUIT_COMMAND; + return strdup("c"); + case SDL_KEYDOWN: + fputc('\a', stdout); + fflush(stdout); + break; + default: + break; + } goto retry; } - else { + if (strcmp(ret, CON_EOF) == 0) { + free(ret); + handle_eof(); + goto retry; + } + else if (!CON_no_csi_mode()) { CON_attributes_t attributes = {.bold = true}; CON_attributed_printf("> %s\n", &attributes, ret); } + CON_set_async_prompt("> "); return ret; } } -static char *asyc_input_callback(GB_gameboy_t *gb) +static char *async_input_callback(GB_gameboy_t *gb) { retry: { char *ret = CON_readline_async(); @@ -187,6 +247,7 @@ static void open_menu(void) } size_t previous_width = GB_get_screen_width(&gb); run_gui(true); + rerender_screen(); SDL_ShowCursor(SDL_DISABLE); if (audio_playing) { GB_audio_set_paused(false); @@ -204,6 +265,24 @@ static void open_menu(void) } } +static void console_line_ready(void) +{ + static SDL_Event event = { + .type = SDL_USEREVENT + }; + SDL_PushEvent(&event); +} + +static void configure_console(void) +{ + CON_set_async_prompt("> "); + CON_set_repeat_empty(true); + CON_set_line_ready_callback(console_line_ready); + GB_set_log_callback(&gb, log_callback); + GB_set_input_callback(&gb, input_callback); + GB_set_async_input_callback(&gb, async_input_callback); +} + static void handle_events(GB_gameboy_t *gb) { SDL_Event event; @@ -409,8 +488,7 @@ static void handle_events(GB_gameboy_t *gb) } case SDL_SCANCODE_C: if (event.type == SDL_KEYDOWN && (event.key.keysym.mod & KMOD_CTRL)) { - CON_print("^C\a\n"); - GB_debugger_break(gb); + pending_command = GB_SDL_DEBUGGER_INTERRUPT_COMMAND; } break; @@ -594,16 +672,7 @@ static void rumble(GB_gameboy_t *gb, double amp) static void debugger_interrupt(int ignore) { - if (!GB_is_inited(&gb)) exit(0); - /* ^C twice to exit */ - if (GB_debugger_is_stopped(&gb)) { - GB_save_battery(&gb, battery_save_path_ptr); - exit(0); - } - if (console_supported) { - CON_print("^C\n"); - } - GB_debugger_break(&gb); + pending_command = GB_SDL_DEBUGGER_INTERRUPT_COMMAND; } #ifndef _WIN32 @@ -638,6 +707,75 @@ static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) GB_audio_queue_sample(sample); } + +#ifdef _WIN32 +static BOOL windows_console_handler(DWORD signal) +{ + /* + Hack: prevents process termination on console close + https://twitter.com/yo_yo_yo_jbo/status/1904592584326218069 + Thanks JBO! + */ + if (signal == CTRL_C_EVENT) { + /* Only happens in no-csi mode */ + pending_command = GB_SDL_DEBUGGER_INTERRUPT_COMMAND; + TerminateThread(GetCurrentThread(), 0); + } + + pending_command = GB_SDL_HIDE_DEBUGGER_COMMAND; + console_line_ready(); + TerminateThread(GetCurrentThread(), 0); + return false; +} + +static void initialize_windows_console(void) +{ + if (AllocConsole()) { + SetConsoleTitle("SameBoy Debugger Console"); + freopen("CONIN$", "r", stdin); + setvbuf(stdin, NULL, _IONBF, 0); + freopen("CONOUT$", "w", stdout); + setvbuf(stdout, NULL, _IONBF, 0); + freopen("CONOUT$", "w", stderr); + setvbuf(stderr, NULL, _IONBF, 0); + + console_supported = CON_start(completer); + if (console_supported) { + configure_console(); + } + + /* I would set a callback via SetConsoleCtrlHandler, but the function (CtrlRoutine) that + eventually calls our callback takes a lock and doesn't release it (as it expects the + process to exit afterwards). The solution is to take a more violent approach and hook + it instead. */ + +#if defined(__x86_64__) || defined(__i386__) + uint8_t *patch_address = (void *)(GetProcAddress(GetModuleHandleA("KernelBase.dll"), "CtrlRoutine") ?: + GetProcAddress(GetModuleHandleA("Kernel32.dll"), "CtrlRoutine")); +#else + uint8_t *patch_address = NULL; +#endif + if (!patch_address) { + EnableMenuItem(GetSystemMenu(GetConsoleWindow(), false), SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); + } + else { + DWORD old_protection; + VirtualProtect(patch_address, 0x20, PAGE_READWRITE, &old_protection); + if (sizeof(&windows_console_handler) == 8) { + *(patch_address++) = 0x48; // movabs + } + *(patch_address++) = 0xb8; // mov + (*(uintptr_t *)patch_address) = (uintptr_t)&windows_console_handler; + patch_address += sizeof(&windows_console_handler); + // jmp rax/eax + *(patch_address++) = 0xff; + *(patch_address++) = 0xe0; + VirtualProtect(patch_address, 0x20, old_protection, &old_protection); + } + } +} + +#endif static bool doing_hot_swap = false; static bool handle_pending_command(void) @@ -705,6 +843,36 @@ static bool handle_pending_command(void) case GB_SDL_QUIT_COMMAND: GB_save_battery(&gb, battery_save_path_ptr); exit(0); + case GB_SDL_DEBUGGER_INTERRUPT_COMMAND: + if (!GB_is_inited(&gb)) exit(0); + +#ifdef _WIN32 + initialize_windows_console(); +#endif + + /* ^C twice to exit */ + if (GB_debugger_is_stopped(&gb)) { +#ifndef _WIN32 + GB_save_battery(&gb, battery_save_path_ptr); + exit(0); +#else + break; +#endif + } + if (console_supported) { + CON_print("^C\n"); + } + GB_debugger_break(&gb); + break; +#if _WIN32 + case GB_SDL_HIDE_DEBUGGER_COMMAND: + HWND console_window = GetConsoleWindow(); + ShowWindow(console_window, SW_HIDE); + FreeConsole(); + SDL_RaiseWindow(window); + break; +#endif + } return false; } @@ -869,10 +1037,7 @@ restart:; GB_apu_set_sample_callback(&gb, gb_audio_callback); if (console_supported) { - CON_set_async_prompt("> "); - GB_set_log_callback(&gb, log_callback); - GB_set_input_callback(&gb, input_callback); - GB_set_async_input_callback(&gb, asyc_input_callback); + configure_console(); } GB_debugger_set_reload_callback(&gb, debugger_reload_callback); @@ -1106,6 +1271,16 @@ static void handle_model_option(const char *model_string) } } +#ifdef _WIN32 +/* raise is buggy and for some reason not always go through our signal handler, so + let's just place the implementation with a direct call to debugger_interrupt. */ +int raise(int signal) +{ + debugger_interrupt(signal); + return 0; +} +#endif + int main(int argc, char **argv) { #ifdef _WIN32 diff --git a/Windows/associations.c b/SDL/windows_associations.c similarity index 98% rename from Windows/associations.c rename to SDL/windows_associations.c index 768b8c8..f5ee66d 100755 --- a/Windows/associations.c +++ b/SDL/windows_associations.c @@ -1,7 +1,8 @@ +#ifdef _WIN32 #include #include #include -#include "associations.h" +#include "windows_associations.h" static bool set_registry_string(HKEY hive, const char *folder, const char *name, const char *value) { @@ -88,3 +89,4 @@ bool GB_do_windows_association(void) return ret; } +#endif diff --git a/SDL/windows_associations.h b/SDL/windows_associations.h new file mode 100755 index 0000000..d705c1a --- /dev/null +++ b/SDL/windows_associations.h @@ -0,0 +1,5 @@ +#ifndef _WIN32 +#error windows_associations.h included while building for a different platform +#endif +#include +bool GB_do_windows_association(void); diff --git a/Windows/associations.h b/Windows/associations.h deleted file mode 100755 index e1d533d..0000000 --- a/Windows/associations.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -bool GB_do_windows_association(void); diff --git a/Windows/crt.c b/Windows/crt.c index fb7cbdb..23b4f19 100755 --- a/Windows/crt.c +++ b/Windows/crt.c @@ -80,6 +80,11 @@ int _seh_filter_exe(unsigned exception_num, void *exception) return 0; } +int _seh_filter_dll(unsigned ExceptionNum, struct _EXCEPTION_POINTERS *ExceptionPtr) +{ + return 0; +} + void _set_app_type(unsigned type) { } @@ -88,4 +93,13 @@ int _set_new_mode(int new_mode) { return 0; } -#endif \ No newline at end of file + +int _execute_onexit_table(void *Table) +{ + return 0; +} + +void __std_type_info_destroy_list(void *const root_node) +{ +} +#endif diff --git a/Windows/stdio.c b/Windows/stdio.c index b45a01a..2b6d459 100755 --- a/Windows/stdio.c +++ b/Windows/stdio.c @@ -11,4 +11,86 @@ FILE *__acrt_iob_func(unsigned index) return (files[index] = fdopen(index, index == STDIN_FILENO? "r" : "w")); } -#endif \ No newline at end of file +#endif + +#ifndef __MINGW32__ +#ifndef __LIBRETRO__ +int vasprintf(char **str, const char *fmt, va_list args) +{ + size_t size = _vscprintf(fmt, args) + 1; + *str = (char*)malloc(size); + int ret = vsprintf(*str, fmt, args); + if (ret != size - 1) { + free(*str); + *str = NULL; + return -1; + } + return ret; +} + +int asprintf(char **strp, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + int r = vasprintf(strp, fmt, args); + va_end(args); + return r; +} + +#endif +#endif + +/* This code is public domain -- Will Hartung 4/9/09 */ +intptr_t getline(char **lineptr, size_t *n, FILE *stream) +{ + char *bufptr = NULL; + char *p = bufptr; + size_t size; + int c; + + if (lineptr == NULL) { + return -1; + } + if (stream == NULL) { + return -1; + } + if (n == NULL) { + return -1; + } + bufptr = *lineptr; + size = *n; + + errno = 0; + c = fgetc(stream); + if (c == EOF) { + return -1; + } + if (bufptr == NULL) { + bufptr = (char*)malloc(128); + if (bufptr == NULL) { + return -1; + } + size = 128; + } + p = bufptr; + while (c != EOF) { + if ((p - bufptr) > (size - 1)) { + size = size + 128; + bufptr = (char*)realloc(bufptr, size); + if (bufptr == NULL) { + return -1; + } + } + *p++ = c; + if (c == '\n') { + break; + } + c = fgetc(stream); + } + + *p++ = '\0'; + *lineptr = bufptr; + *n = size; + + return p - bufptr - 1; +} diff --git a/Windows/stdio.h b/Windows/stdio.h index b8be393..e2f1c9d 100755 --- a/Windows/stdio.h +++ b/Windows/stdio.h @@ -21,83 +21,12 @@ int access(const char *filename, int mode); #ifndef __MINGW32__ #ifndef __LIBRETRO__ -static inline int vasprintf(char **str, const char *fmt, va_list args) -{ - size_t size = _vscprintf(fmt, args) + 1; - *str = (char*)malloc(size); - int ret = vsprintf(*str, fmt, args); - if (ret != size - 1) { - free(*str); - *str = NULL; - return -1; - } - return ret; -} - -static inline int asprintf(char **strp, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - int r = vasprintf(strp, fmt, args); - va_end(args); - return r; -} - +int vasprintf(char **str, const char *fmt, va_list args); +int asprintf(char **strp, const char *fmt, ...); #endif #endif -/* This code is public domain -- Will Hartung 4/9/09 */ -static inline size_t getline(char **lineptr, size_t *n, FILE *stream) -{ - char *bufptr = NULL; - char *p = bufptr; - size_t size; - int c; - - if (lineptr == NULL) { - return -1; - } - if (stream == NULL) { - return -1; - } - if (n == NULL) { - return -1; - } - bufptr = *lineptr; - size = *n; - - c = fgetc(stream); - if (c == EOF) { - return -1; - } - if (bufptr == NULL) { - bufptr = (char*)malloc(128); - if (bufptr == NULL) { - return -1; - } - size = 128; - } - p = bufptr; - while (c != EOF) { - if ((p - bufptr) > (size - 1)) { - size = size + 128; - bufptr = (char*)realloc(bufptr, size); - if (bufptr == NULL) { - return -1; - } - } - *p++ = c; - if (c == '\n') { - break; - } - c = fgetc(stream); - } - - *p++ = '\0'; - *lineptr = bufptr; - *n = size; - - return p - bufptr - 1; -} +intptr_t getline(char **lineptr, size_t *n, FILE *stream); #define snprintf _snprintf +#define printf(...) fprintf(stdout, __VA_ARGS__)