From 6a3cd371d01e5d253b0ab999da53d87ac84ab7cc Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 3 Jun 2020 20:54:06 +0300 Subject: [PATCH 01/41] Fix potential memory corruption when execution malformed ROMs --- Core/mbc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/mbc.c b/Core/mbc.c index 72073f6..ba5055f 100644 --- a/Core/mbc.c +++ b/Core/mbc.c @@ -135,7 +135,10 @@ void GB_configure_cart(GB_gameboy_t *gb) static const unsigned ram_sizes[256] = {0, 0x800, 0x2000, 0x8000, 0x20000, 0x10000}; gb->mbc_ram_size = ram_sizes[gb->rom[0x149]]; } - gb->mbc_ram = malloc(gb->mbc_ram_size); + + if (gb->mbc_ram_size) { + gb->mbc_ram = malloc(gb->mbc_ram_size); + } /* Todo: Some games assume unintialized MBC RAM is 0xFF. It this true for all cartridges types? */ memset(gb->mbc_ram, 0xFF, gb->mbc_ram_size); From b7a9039e50426d80f136403c95e85f23aad11ea3 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 3 Jun 2020 21:06:47 +0300 Subject: [PATCH 02/41] Sanitize SDL preferences for cross-version stability --- SDL/main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/SDL/main.c b/SDL/main.c index f75e3aa..3df369f 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -671,7 +671,19 @@ int main(int argc, char **argv) if (prefs_file) { fread(&configuration, 1, sizeof(configuration), prefs_file); fclose(prefs_file); + + /* Sanitize for stability */ + configuration.color_correction_mode %= GB_COLOR_CORRECTION_REDUCE_CONTRAST +1; + configuration.scaling_mode %= GB_SDL_SCALING_MAX; + configuration.blending_mode %= GB_FRAME_BLENDING_MODE_ACCURATE + 1; + configuration.highpass_mode %= GB_HIGHPASS_MAX; + configuration.model %= MODEL_MAX; + configuration.sgb_revision %= SGB_MAX; + configuration.dmg_palette %= 3; + configuration.border_mode %= GB_BORDER_ALWAYS + 1; + configuration.rumble_mode %= GB_RUMBLE_ALL_GAMES + 1; } + if (configuration.model >= MODEL_MAX) { configuration.model = MODEL_CGB; } From ef203cf0e5b6dd1e9ee5da47b0827b0ef132fa02 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 3 Jun 2020 21:18:09 +0300 Subject: [PATCH 03/41] Update version to 0.13.1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1c6b01a..4b9c291 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ ifeq ($(MAKECMDGOALS),) MAKECMDGOALS := $(DEFAULT) endif -VERSION := 0.13 +VERSION := 0.13.1 export VERSION CONF ?= debug SDL_AUDIO_DRIVER ?= sdl From c07588e3bd7db8f2bfe9e483046ba6856d23fd1e Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 5 Jun 2020 02:10:05 +0300 Subject: [PATCH 04/41] Console auto complete --- Cocoa/Document.m | 5 + Cocoa/GBTerminalTextFieldCell.h | 3 +- Cocoa/GBTerminalTextFieldCell.m | 40 ++++++- Core/debugger.c | 194 ++++++++++++++++++++++++++++++-- Core/debugger.h | 2 +- 5 files changed, 231 insertions(+), 13 deletions(-) diff --git a/Cocoa/Document.m b/Cocoa/Document.m index 035c0e2..095cfe3 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -8,6 +8,7 @@ #include "GBMemoryByteArray.h" #include "GBWarningPopover.h" #include "GBCheatWindowController.h" +#include "GBTerminalTextFieldCell.h" /* Todo: The general Objective-C coding style conflicts with SameBoy's. This file needs a cleanup. */ /* Todo: Split into category files! This is so messy!!! */ @@ -546,6 +547,7 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) self.debuggerSideViewInput.textColor = [NSColor whiteColor]; self.debuggerSideViewInput.defaultParagraphStyle = paragraph_style; [self.debuggerSideViewInput setString:@"registers\nbacktrace\n"]; + ((GBTerminalTextFieldCell *)self.consoleInput.cell).gb = &gb; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSideView) name:NSTextDidChangeNotification @@ -1008,6 +1010,9 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) [debugger_input_queue removeObjectAtIndex:0]; } [has_debugger_input unlockWithCondition:[debugger_input_queue count] != 0]; + if ((id)input == [NSNull null]) { + return NULL; + } return input? strdup([input UTF8String]): NULL; } diff --git a/Cocoa/GBTerminalTextFieldCell.h b/Cocoa/GBTerminalTextFieldCell.h index eae02e5..484e0c3 100644 --- a/Cocoa/GBTerminalTextFieldCell.h +++ b/Cocoa/GBTerminalTextFieldCell.h @@ -1,5 +1,6 @@ #import +#include @interface GBTerminalTextFieldCell : NSTextFieldCell - +@property GB_gameboy_t *gb; @end diff --git a/Cocoa/GBTerminalTextFieldCell.m b/Cocoa/GBTerminalTextFieldCell.m index e95e785..c1ed203 100644 --- a/Cocoa/GBTerminalTextFieldCell.m +++ b/Cocoa/GBTerminalTextFieldCell.m @@ -2,6 +2,7 @@ #import "GBTerminalTextFieldCell.h" @interface GBTerminalTextView : NSTextView +@property GB_gameboy_t *gb; @end @implementation GBTerminalTextFieldCell @@ -12,10 +13,12 @@ - (NSTextView *)fieldEditorForView:(NSView *)controlView { if (field_editor) { + field_editor.gb = self.gb; return field_editor; } field_editor = [[GBTerminalTextView alloc] init]; [field_editor setFieldEditor:YES]; + field_editor.gb = self.gb; return field_editor; } @@ -26,6 +29,8 @@ NSMutableOrderedSet *lines; NSUInteger current_line; bool reverse_search_mode; + NSRange auto_complete_range; + uintptr_t auto_complete_context; } - (instancetype)init @@ -170,6 +175,7 @@ -(void)setSelectedRanges:(NSArray *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag { reverse_search_mode = false; + auto_complete_context = 0; [super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag]; } @@ -188,6 +194,38 @@ [attributes setObject:color forKey:NSForegroundColorAttributeName]; [[[NSAttributedString alloc] initWithString:@"Reverse search..." attributes:attributes] drawAtPoint:NSMakePoint(2, 0)]; } - } + +/* Todo: lazy design, make it use a delegate instead of having a gb reference*/ + +- (void)insertTab:(id)sender +{ + if (auto_complete_context == 0) { + NSRange selection = self.selectedRange; + if (selection.length) { + [self delete:nil]; + } + auto_complete_range = NSMakeRange(selection.location, 0); + } + char *substring = strdup([self.string substringToIndex:auto_complete_range.location].UTF8String); + uintptr_t context = auto_complete_context; + char *completion = GB_debugger_complete_substring(self.gb, substring, &context); + free(substring); + if (completion) { + NSString *ns_completion = @(completion); + free(completion); + if (!ns_completion) { + goto error; + } + self.selectedRange = auto_complete_range; + auto_complete_range.length = ns_completion.length; + [self replaceCharactersInRange:self.selectedRange withString:ns_completion]; + auto_complete_context = context; + return; + } +error: + auto_complete_context = context; + NSBeep(); +} + @end diff --git a/Core/debugger.c b/Core/debugger.c index 34144df..038f76f 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -689,6 +689,7 @@ exit: struct debugger_command_s; typedef bool debugger_command_imp_t(GB_gameboy_t *gb, char *arguments, char *modifiers, const struct debugger_command_s *command); +typedef char *debugger_completer_imp_t(GB_gameboy_t *gb, const char *string, uintptr_t *context); typedef struct debugger_command_s { const char *command; @@ -697,6 +698,8 @@ typedef struct debugger_command_s { const char *help_string; // Null if should not appear in help const char *arguments_format; // For usage message const char *modifiers_format; // For usage message + debugger_completer_imp_t *argument_completer; + debugger_completer_imp_t *modifiers_completer; } debugger_command_t; static const char *lstrip(const char *str) @@ -832,6 +835,19 @@ static bool registers(GB_gameboy_t *gb, char *arguments, char *modifiers, const return true; } +static char *on_off_completer(GB_gameboy_t *gb, const char *string, uintptr_t *context) +{ + size_t length = strlen(string); + const char *suggestions[] = {"on", "off"}; + while (*context < sizeof(suggestions) / sizeof(suggestions[0])) { + if (memcmp(string, suggestions[*context], length) == 0) { + return strdup(suggestions[(*context)++] + length); + } + (*context)++; + } + return NULL; +} + /* Enable or disable software breakpoints */ static bool softbreak(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command) { @@ -873,6 +889,65 @@ static uint16_t find_breakpoint(GB_gameboy_t *gb, value_t addr) return (uint16_t) min; } +static inline bool is_legal_symbol_char(char c) +{ + if (c >= '0' && c <= '9') return true; + if (c >= 'A' && c <= 'Z') return true; + if (c >= 'a' && c <= 'z') return true; + if (c == '_') return true; + if (c == '.') return true; + return false; +} + +static char *symbol_completer(GB_gameboy_t *gb, const char *string, uintptr_t *_context) +{ + const char *symbol_prefix = string; + while (*string) { + if (!is_legal_symbol_char(*string)) { + symbol_prefix = string + 1; + } + string++; + } + + if (*symbol_prefix == '$') { + return NULL; + } + + struct { + uint16_t bank; + uint32_t symbol; + } *context = (void *)_context; + + + size_t length = strlen(symbol_prefix); + while (context->bank < 0x200) { + if (gb->bank_symbols[context->bank] == NULL || + context->symbol >= gb->bank_symbols[context->bank]->n_symbols) { + context->bank++; + context->symbol = 0; + continue; + } + const char *candidate = gb->bank_symbols[context->bank]->symbols[context->symbol++].name; + if (memcmp(symbol_prefix, candidate, length) == 0) { + return strdup(candidate + length); + } + } + return NULL; +} + +static char *j_completer(GB_gameboy_t *gb, const char *string, uintptr_t *context) +{ + size_t length = strlen(string); + const char *suggestions[] = {"j"}; + while (*context < sizeof(suggestions) / sizeof(suggestions[0])) { + if (memcmp(string, suggestions[*context], length) == 0) { + return strdup(suggestions[(*context)++] + length); + } + (*context)++; + } + return NULL; +} + static bool breakpoint(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command) { bool is_jump_to = true; @@ -1040,6 +1115,19 @@ static uint16_t find_watchpoint(GB_gameboy_t *gb, value_t addr) return (uint16_t) min; } +static char *rw_completer(GB_gameboy_t *gb, const char *string, uintptr_t *context) +{ + size_t length = strlen(string); + const char *suggestions[] = {"r", "rw", "w"}; + while (*context < sizeof(suggestions) / sizeof(suggestions[0])) { + if (memcmp(string, suggestions[*context], length) == 0) { + return strdup(suggestions[(*context)++] + length); + } + (*context)++; + } + return NULL; +} + static bool watch(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command) { if (strlen(lstrip(arguments)) == 0) { @@ -1277,6 +1365,19 @@ static bool should_break(GB_gameboy_t *gb, uint16_t addr, bool jump_to) return _should_break(gb, full_addr, jump_to); } +static char *format_completer(GB_gameboy_t *gb, const char *string, uintptr_t *context) +{ + size_t length = strlen(string); + const char *suggestions[] = {"a", "b", "d", "o", "x"}; + while (*context < sizeof(suggestions) / sizeof(suggestions[0])) { + if (memcmp(string, suggestions[*context], length) == 0) { + return strdup(suggestions[(*context)++] + length); + } + (*context)++; + } + return NULL; +} + static bool print(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command) { if (strlen(lstrip(arguments)) == 0) { @@ -1740,6 +1841,19 @@ static bool apu(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugg return true; } +static char *wave_completer(GB_gameboy_t *gb, const char *string, uintptr_t *context) +{ + size_t length = strlen(string); + const char *suggestions[] = {"c", "f", "l"}; + while (*context < sizeof(suggestions) / sizeof(suggestions[0])) { + if (memcmp(string, suggestions[*context], length) == 0) { + return strdup(suggestions[(*context)++] + length); + } + (*context)++; + } + return NULL; +} + static bool wave(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugger_command_t *command) { if (strlen(lstrip(arguments)) || (modifiers && !strchr("fcl", modifiers[0]))) { @@ -1787,7 +1901,7 @@ static const debugger_command_t commands[] = { {"finish", 1, finish, "Run until the current function returns"}, {"backtrace", 2, backtrace, "Displays the current call stack"}, {"bt", 2, }, /* Alias */ - {"sld", 3, stack_leak_detection, "Like finish, but stops if a stack leak is detected (Experimental)"}, + {"sld", 3, stack_leak_detection, "Like finish, but stops if a stack leak is detected"}, {"ticks", 2, ticks, "Displays the number of CPU ticks since the last time 'ticks' was" HELP_NEWLINE "used"}, {"registers", 1, registers, "Print values of processor registers and other important registers"}, @@ -1796,30 +1910,33 @@ static const debugger_command_t commands[] = { {"apu", 3, apu, "Displays information about the current state of the audio chip"}, {"wave", 3, wave, "Prints a visual representation of the wave RAM." HELP_NEWLINE "Modifiers can be used for a (f)ull print (the default)," HELP_NEWLINE - "a more (c)ompact one, or a one-(l)iner", "", "(f|c|l)"}, + "a more (c)ompact one, or a one-(l)iner", "", "(f|c|l)", .modifiers_completer = wave_completer}, {"lcd", 3, lcd, "Displays information about the current state of the LCD controller"}, {"palettes", 3, palettes, "Displays the current CGB palettes"}, - {"softbreak", 2, softbreak, "Enables or disables software breakpoints", "(on|off)"}, + {"softbreak", 2, softbreak, "Enables or disables software breakpoints", "(on|off)", .argument_completer = on_off_completer}, {"breakpoint", 1, breakpoint, "Add a new breakpoint at the specified address/expression" HELP_NEWLINE "Can also modify the condition of existing breakpoints." HELP_NEWLINE "If the j modifier is used, the breakpoint will occur just before" HELP_NEWLINE "jumping to the target.", - "[ if ]", "j"}, - {"delete", 2, delete, "Delete a breakpoint by its address, or all breakpoints", "[]"}, + "[ if ]", "j", + .argument_completer = symbol_completer, .modifiers_completer = j_completer}, + {"delete", 2, delete, "Delete a breakpoint by its address, or all breakpoints", "[]", .argument_completer = symbol_completer}, {"watch", 1, watch, "Add a new watchpoint at the specified address/expression." HELP_NEWLINE "Can also modify the condition and type of existing watchpoints." HELP_NEWLINE "Default watchpoint type is write-only.", - "[ if ]", "(r|w|rw)"}, - {"unwatch", 3, unwatch, "Delete a watchpoint by its address, or all watchpoints", "[]"}, + "[ if ]", "(r|w|rw)", + .argument_completer = symbol_completer, .modifiers_completer = rw_completer + }, + {"unwatch", 3, unwatch, "Delete a watchpoint by its address, or all watchpoints", "[]", .argument_completer = symbol_completer}, {"list", 1, list, "List all set breakpoints and watchpoints"}, {"print", 1, print, "Evaluate and print an expression" HELP_NEWLINE "Use modifier to format as an address (a, default) or as a number in" HELP_NEWLINE "decimal (d), hexadecimal (x), octal (o) or binary (b).", - "", "format"}, + "", "format", .argument_completer = symbol_completer, .modifiers_completer = format_completer}, {"eval", 2, }, /* Alias */ - {"examine", 2, examine, "Examine values at address", "", "count"}, + {"examine", 2, examine, "Examine values at address", "", "count", .argument_completer = symbol_completer}, {"x", 1, }, /* Alias */ - {"disassemble", 1, disassemble, "Disassemble instructions at address", "", "count"}, + {"disassemble", 1, disassemble, "Disassemble instructions at address", "", "count", .argument_completer = symbol_completer}, {"help", 1, help, "List available commands or show help for the specified command", "[]"}, @@ -2075,6 +2192,63 @@ bool GB_debugger_execute_command(GB_gameboy_t *gb, char *input) } } +/* Returns true if debugger waits for more commands */ +char *GB_debugger_complete_substring(GB_gameboy_t *gb, char *input, uintptr_t *context) +{ + char *command_string = input; + char *arguments = strchr(input, ' '); + if (arguments) { + /* Actually "split" the string. */ + arguments[0] = 0; + arguments++; + } + + char *modifiers = strchr(command_string, '/'); + if (modifiers) { + /* Actually "split" the string. */ + modifiers[0] = 0; + modifiers++; + } + + const debugger_command_t *command = find_command(command_string); + if (command && command->implementation == help && arguments) { + command_string = arguments; + arguments = NULL; + } + + /* No commands and no modifiers, complete the command */ + if (!arguments && !modifiers) { + size_t length = strlen(command_string); + if (*context >= sizeof(commands) / sizeof(commands[0])) { + return NULL; + } + for (const debugger_command_t *command = &commands[*context]; command->command; command++) { + (*context)++; + if (memcmp(command->command, command_string, length) == 0) { /* Is a substring? */ + return strdup(command->command + length); + } + } + return NULL; + } + + if (command) { + if (arguments) { + if (command->argument_completer) { + return command->argument_completer(gb, arguments, context); + } + return NULL; + } + + if (modifiers) { + if (command->modifiers_completer) { + return command->modifiers_completer(gb, modifiers, context); + } + return NULL; + } + } + return NULL; +} + typedef enum { JUMP_TO_NONE, JUMP_TO_BREAK, diff --git a/Core/debugger.h b/Core/debugger.h index b6a12d9..0678b30 100644 --- a/Core/debugger.h +++ b/Core/debugger.h @@ -34,7 +34,7 @@ bool /* Returns true if debugger waits for more commands. Not relevant for non-G void #endif GB_debugger_execute_command(GB_gameboy_t *gb, char *input); /* Destroys input. */ - +char *GB_debugger_complete_substring(GB_gameboy_t *gb, char *input, uintptr_t *context); /* Destroys input, result requires free */ void GB_debugger_load_symbol_file(GB_gameboy_t *gb, const char *path); const char *GB_debugger_name_for_address(GB_gameboy_t *gb, uint16_t addr); From 4a51f5c95698ad3df8bae22acd01e4e60a74de80 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Tue, 9 Jun 2020 20:09:50 +0300 Subject: [PATCH 05/41] Cherry-picking libretro memory map bugfix (Closes #227, #205). Fixing libretro build with modern macOS SDKs. --- Makefile | 2 +- libretro/libretro.c | 81 ++++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index 4b9c291..587f2f8 100644 --- a/Makefile +++ b/Makefile @@ -390,7 +390,7 @@ $(OBJ)/BootROMs/SameBoyLogo.pb12: $(OBJ)/BootROMs/SameBoyLogo.2bpp $(PB12_COMPRE $(realpath $(PB12_COMPRESS)) < $< > $@ $(PB12_COMPRESS): BootROMs/pb12.c - $(CC) $(LDFLAGS) $(CFLAGS) -Wall -Werror $< -o $@ + cc -Wall -Werror $< -o $@ $(BIN)/BootROMs/agb_boot.bin: BootROMs/cgb_boot.asm $(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm diff --git a/libretro/libretro.c b/libretro/libretro.c index a7d6432..24514d4 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -389,47 +389,12 @@ static void boot_rom_load(GB_gameboy_t *gb, GB_boot_rom_t type) } } -static void init_for_current_model(unsigned id) +static void retro_set_memory_maps(void) { - unsigned i = id; - enum model effective_model; - - effective_model = model[i]; - if (effective_model == MODEL_AUTO) { - effective_model = auto_model; - } - - - if (GB_is_inited(&gameboy[i])) { - GB_switch_model_and_reset(&gameboy[i], libretro_to_internal_model[effective_model]); - } - else { - GB_init(&gameboy[i], libretro_to_internal_model[effective_model]); - } - - GB_set_boot_rom_load_callback(&gameboy[i], boot_rom_load); - - /* When running multiple devices they are assumed to use the same resolution */ - - GB_set_pixels_output(&gameboy[i], - (uint32_t *)(frame_buf + GB_get_screen_width(&gameboy[0]) * GB_get_screen_height(&gameboy[0]) * i)); - GB_set_rgb_encode_callback(&gameboy[i], rgb_encode); - GB_set_sample_rate(&gameboy[i], AUDIO_FREQUENCY); - GB_apu_set_sample_callback(&gameboy[i], audio_callback); - GB_set_rumble_callback(&gameboy[i], rumble_callback); - - /* todo: attempt to make these more generic */ - GB_set_vblank_callback(&gameboy[0], (GB_vblank_callback_t) vblank1); - if (emulated_devices == 2) { - GB_set_vblank_callback(&gameboy[1], (GB_vblank_callback_t) vblank2); - if (link_cable_emulation) { - set_link_cable_state(true); - } - } - struct retro_memory_descriptor descs[11]; size_t size; uint16_t bank; + unsigned i; /* todo: add netplay awareness for this so achievements can be granted on the respective client */ @@ -489,6 +454,45 @@ static void init_for_current_model(unsigned id) mmaps.descriptors = descs; mmaps.num_descriptors = sizeof(descs) / sizeof(descs[0]); environ_cb(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &mmaps); +} + +static void init_for_current_model(unsigned id) +{ + unsigned i = id; + enum model effective_model; + + effective_model = model[i]; + if (effective_model == MODEL_AUTO) { + effective_model = auto_model; + } + + + if (GB_is_inited(&gameboy[i])) { + GB_switch_model_and_reset(&gameboy[i], libretro_to_internal_model[effective_model]); + } + else { + GB_init(&gameboy[i], libretro_to_internal_model[effective_model]); + } + + GB_set_boot_rom_load_callback(&gameboy[i], boot_rom_load); + + /* When running multiple devices they are assumed to use the same resolution */ + + GB_set_pixels_output(&gameboy[i], + (uint32_t *)(frame_buf + GB_get_screen_width(&gameboy[0]) * GB_get_screen_height(&gameboy[0]) * i)); + GB_set_rgb_encode_callback(&gameboy[i], rgb_encode); + GB_set_sample_rate(&gameboy[i], AUDIO_FREQUENCY); + GB_apu_set_sample_callback(&gameboy[i], audio_callback); + GB_set_rumble_callback(&gameboy[i], rumble_callback); + + /* todo: attempt to make these more generic */ + GB_set_vblank_callback(&gameboy[0], (GB_vblank_callback_t) vblank1); + if (emulated_devices == 2) { + GB_set_vblank_callback(&gameboy[1], (GB_vblank_callback_t) vblank2); + if (link_cable_emulation) { + set_link_cable_state(true); + } + } /* Let's be extremely nitpicky about how devices and descriptors are set */ if (emulated_devices == 1 && (model[0] == MODEL_SGB || model[0] == MODEL_SGB2)) { @@ -1070,6 +1074,9 @@ bool retro_load_game(const struct retro_game_info *info) } check_variables(); + + retro_set_memory_maps(); + return true; } From edf77624087f09decd3656adf71bc0400a17af06 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 10 Jun 2020 01:10:11 +0300 Subject: [PATCH 06/41] Improved Dark Mode support, improved Hex Fiend's general system-native appearance --- Cocoa/Document.m | 1 - Cocoa/Document.xib | 22 +++++------ Cocoa/GBColorCell.m | 8 +++- Cocoa/GBPreferencesWindow.m | 20 ++++++++++ Cocoa/Joypad~dark.png | Bin 0 -> 6244 bytes Cocoa/Joypad~dark@2x.png | Bin 0 -> 7175 bytes Cocoa/NSImageNamedDarkSupport.m | 42 ++++++++++++++++++++ Cocoa/Preferences.xib | 10 ++--- Cocoa/Speaker~dark.png | Bin 0 -> 4562 bytes Cocoa/Speaker~dark@2x.png | Bin 0 -> 5992 bytes HexFiend/HFFunctions.h | 2 +- HexFiend/HFLineCountingRepresenter.m | 10 ++--- HexFiend/HFLineCountingView.m | 56 ++++++++++----------------- HexFiend/HFRepresenterTextView.m | 18 ++++++--- HexFiend/HFStatusBarRepresenter.m | 44 +++++---------------- HexFiend/HFTextRepresenter.m | 12 ++++-- 16 files changed, 141 insertions(+), 104 deletions(-) create mode 100644 Cocoa/Joypad~dark.png create mode 100644 Cocoa/Joypad~dark@2x.png create mode 100644 Cocoa/NSImageNamedDarkSupport.m create mode 100644 Cocoa/Speaker~dark.png create mode 100644 Cocoa/Speaker~dark@2x.png diff --git a/Cocoa/Document.m b/Cocoa/Document.m index 095cfe3..fdb7d97 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -647,7 +647,6 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp) { hex_controller = [[HFController alloc] init]; [hex_controller setBytesPerColumn:1]; - [hex_controller setFont:[NSFont userFixedPitchFontOfSize:12]]; [hex_controller setEditMode:HFOverwriteMode]; [hex_controller setByteArray:[[GBMemoryByteArray alloc] initWithDocument:self]]; diff --git a/Cocoa/Document.xib b/Cocoa/Document.xib index 81ce018..e2b0ca6 100644 --- a/Cocoa/Document.xib +++ b/Cocoa/Document.xib @@ -116,7 +116,7 @@ - + @@ -153,7 +153,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -339,7 +339,7 @@ - + @@ -505,9 +505,9 @@ - + - + @@ -640,7 +640,7 @@ - + @@ -649,7 +649,7 @@ - + @@ -800,7 +800,7 @@ @@ -970,7 +977,7 @@ - + @@ -1069,6 +1076,7 @@ + From 4f42f4f718ec17c38c729b1fa9d9906effa88e36 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Thu, 11 Jun 2020 00:38:53 +0300 Subject: [PATCH 10/41] Minor layout fixes --- Cocoa/Document.xib | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cocoa/Document.xib b/Cocoa/Document.xib index c13c9dd..1197c0f 100644 --- a/Cocoa/Document.xib +++ b/Cocoa/Document.xib @@ -243,9 +243,9 @@ - + - + @@ -903,7 +903,7 @@