Automatic model selection in the Cocoa and SDL frontends, closes #648

This commit is contained in:
Lior Halphon
2024-08-25 14:36:48 +03:00
parent f0bab07f26
commit b6c6b9ed54
8 changed files with 189 additions and 106 deletions

View File

@@ -6,6 +6,18 @@
#import "GBOSDView.h" #import "GBOSDView.h"
#import "GBDebuggerButton.h" #import "GBDebuggerButton.h"
enum model {
MODEL_NONE,
MODEL_DMG,
MODEL_CGB,
MODEL_AGB,
MODEL_SGB,
MODEL_MGB,
MODEL_AUTO,
MODEL_QUICK_RESET = -1,
};
@class GBCheatWindowController; @class GBCheatWindowController;
@class GBPaletteView; @class GBPaletteView;
@class GBObjectView; @class GBObjectView;

View File

@@ -48,16 +48,6 @@
/* Todo: The general Objective-C coding style conflicts with SameBoy's. This file needs a cleanup. */ /* 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!!! */ /* Todo: Split into category files! This is so messy!!! */
enum model {
MODEL_NONE,
MODEL_DMG,
MODEL_CGB,
MODEL_AGB,
MODEL_SGB,
MODEL_MGB,
MODEL_QUICK_RESET = -1,
};
@interface Document () @interface Document ()
@property GBAudioClient *audioClient; @property GBAudioClient *audioClient;
@@ -100,6 +90,7 @@ enum model {
bool _logToSideView; bool _logToSideView;
bool _shouldClearSideView; bool _shouldClearSideView;
enum model _currentModel; enum model _currentModel;
bool _usesAutoModel;
bool _rewind; bool _rewind;
bool _modelsChanging; bool _modelsChanging;
@@ -263,6 +254,7 @@ static void debuggerReloadCallback(GB_gameboy_t *gb)
case MODEL_NONE: case MODEL_NONE:
case MODEL_QUICK_RESET: case MODEL_QUICK_RESET:
case MODEL_AUTO:
case MODEL_CGB: case MODEL_CGB:
return (GB_model_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBCGBModel"]; return (GB_model_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBCGBModel"];
@@ -677,15 +669,46 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
GB_load_boot_rom(&_gb, [path UTF8String]); GB_load_boot_rom(&_gb, [path UTF8String]);
} }
- (enum model)bestModelForROM
{
uint8_t *rom = GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, NULL, NULL);
if (!rom) return MODEL_CGB;
if (rom[0x143] & 0x80) { // Has CGB features
return MODEL_CGB;
}
if (rom[0x146] == 3) { // Has SGB features
return MODEL_SGB;
}
if (rom[0x14B] == 1) { // Nintendo-licensed (most likely has boot ROM palettes)
return MODEL_CGB;
}
if (rom[0x14B] == 0x33 &&
rom[0x144] == '0' &&
rom[0x145] == '1') { // Ditto
return MODEL_CGB;
}
return MODEL_DMG;
}
- (IBAction)reset:(id)sender - (IBAction)reset:(id)sender
{ {
[self stop]; [self stop];
size_t old_width = GB_get_screen_width(&_gb); size_t old_width = GB_get_screen_width(&_gb);
if ([sender tag] != MODEL_NONE) { if ([sender tag] > MODEL_NONE) {
/* User explictly selected a model, save the preference */
_currentModel = (enum model)[sender tag]; _currentModel = (enum model)[sender tag];
_usesAutoModel = _currentModel == MODEL_AUTO;
[[NSUserDefaults standardUserDefaults] setInteger:_currentModel forKey:@"GBEmulatedModel"];
} }
/* Reload the ROM, SAV and SYM files */
[self loadROM];
if ([sender tag] == MODEL_QUICK_RESET) { if ([sender tag] == MODEL_QUICK_RESET) {
GB_quick_reset(&_gb); GB_quick_reset(&_gb);
} }
@@ -699,16 +722,6 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
[self updateMinSize]; [self updateMinSize];
if ([sender tag] > MODEL_NONE) {
/* User explictly selected a model, save the preference */
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_DMG forKey:@"EmulateDMG"];
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_SGB forKey:@"EmulateSGB"];
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_AGB forKey:@"EmulateAGB"];
[[NSUserDefaults standardUserDefaults] setBool:_currentModel == MODEL_MGB forKey:@"EmulateMGB"];
}
/* Reload the ROM, SAV and SYM files */
[self loadROM];
[self start]; [self start];
@@ -871,19 +884,10 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
[self observeStandardDefaultsKey:@"GBVolume" withBlock:^(id newValue) { [self observeStandardDefaultsKey:@"GBVolume" withBlock:^(id newValue) {
weakSelf->_volume = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBVolume"]; weakSelf->_volume = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBVolume"];
}]; }];
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateDMG"]) {
_currentModel = MODEL_DMG; _currentModel = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBEmulatedModel"];
} _usesAutoModel = _currentModel == MODEL_AUTO;
else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateSGB"]) {
_currentModel = MODEL_SGB;
}
else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateMGB"]) {
_currentModel = MODEL_MGB;
}
else {
_currentModel = [[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateAGB"]? MODEL_AGB : MODEL_CGB;
}
[self initCommon]; [self initCommon];
self.view.gb = &_gb; self.view.gb = &_gb;
@@ -1125,7 +1129,7 @@ static bool is_path_writeable(const char *path)
return true; return true;
} }
- (int) loadROM - (int)loadROM
{ {
__block int ret = 0; __block int ret = 0;
NSString *fileName = self.romPath; NSString *fileName = self.romPath;
@@ -1177,6 +1181,9 @@ static bool is_path_writeable(const char *path)
[GBWarningPopover popoverWithContents:rom_warnings onWindow:self.mainWindow]; [GBWarningPopover popoverWithContents:rom_warnings onWindow:self.mainWindow];
} }
_fileModificationTime = [[NSFileManager defaultManager] attributesOfItemAtPath:fileName error:nil][NSFileModificationDate]; _fileModificationTime = [[NSFileManager defaultManager] attributesOfItemAtPath:fileName error:nil][NSFileModificationDate];
if (_usesAutoModel) {
_currentModel = [self bestModelForROM];
}
return ret; return ret;
} }
@@ -1250,7 +1257,7 @@ static bool is_path_writeable(const char *path)
return !GB_debugger_is_stopped(&_gb); return !GB_debugger_is_stopped(&_gb);
} }
else if ([anItem action] == @selector(reset:) && anItem.tag != MODEL_NONE && anItem.tag != MODEL_QUICK_RESET) { else if ([anItem action] == @selector(reset:) && anItem.tag != MODEL_NONE && anItem.tag != MODEL_QUICK_RESET) {
[(NSMenuItem *)anItem setState:anItem.tag == _currentModel]; [(NSMenuItem *)anItem setState:(anItem.tag == _currentModel) || (anItem.tag == MODEL_AUTO && _usesAutoModel)];
} }
else if ([anItem action] == @selector(interrupt:)) { else if ([anItem action] == @selector(interrupt:)) {
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]) { if (![[NSUserDefaults standardUserDefaults] boolForKey:@"DeveloperMode"]) {

View File

@@ -83,6 +83,8 @@ static uint32_t color_to_int(NSColor *color)
@"GBJoyConAutoPair": @YES, @"GBJoyConAutoPair": @YES,
@"GBJoyConsDefaultsToHorizontal": @YES, @"GBJoyConsDefaultsToHorizontal": @YES,
@"GBEmulatedModel": @(MODEL_AUTO),
// Default themes // Default themes
@"GBThemes": @{ @"GBThemes": @{
@"Desert": @{ @"Desert": @{

View File

@@ -218,6 +218,50 @@
<action selector="togglePause:" target="-1" id="osW-wt-QAa"/> <action selector="togglePause:" target="-1" id="osW-wt-QAa"/>
</connections> </connections>
</menuItem> </menuItem>
<menuItem title="Emulated Model" id="Cip-1S-4Zp">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Emulated Model" id="MtH-V4-vUi">
<items>
<menuItem title="Pick Automatically" tag="6" id="GXg-yH-3dl">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="ao2-FI-kk1"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="Nyl-zW-Uez"/>
<menuItem title="Game Boy" tag="1" id="g7C-LA-VAr">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="rxG-cz-s1S"/>
</connections>
</menuItem>
<menuItem title="Game Boy Pocket/Light" tag="5" id="1bM-CT-hoW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="U7l-BM-kB1"/>
</connections>
</menuItem>
<menuItem title="Super Game Boy" tag="4" id="vc7-yy-ARW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="E4M-QG-ua9"/>
</connections>
</menuItem>
<menuItem title="Game Boy Color" tag="2" id="hdG-Bl-8nJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xAz-cr-0u2"/>
</connections>
</menuItem>
<menuItem title="Game Boy Advance" tag="3" id="7jw-B1-tf5">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xQk-4e-kd7"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="QIS-av-Byy"/> <menuItem isSeparatorItem="YES" id="QIS-av-Byy"/>
<menuItem title="Save State" id="Hdz-ut-okE"> <menuItem title="Save State" id="Hdz-ut-okE">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
@@ -360,37 +404,6 @@
<action selector="copyScreenshot:" target="-1" id="XJC-EB-HNl"/> <action selector="copyScreenshot:" target="-1" id="XJC-EB-HNl"/>
</connections> </connections>
</menuItem> </menuItem>
<menuItem isSeparatorItem="YES" id="zk7-gf-LXN"/>
<menuItem title="Game Boy" tag="1" id="g7C-LA-VAr">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="rxG-cz-s1S"/>
</connections>
</menuItem>
<menuItem title="Game Boy Pocket/Light" tag="5" id="1bM-CT-hoW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="U7l-BM-kB1"/>
</connections>
</menuItem>
<menuItem title="Super Game Boy" tag="4" id="vc7-yy-ARW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="E4M-QG-ua9"/>
</connections>
</menuItem>
<menuItem title="Game Boy Color" tag="2" id="hdG-Bl-8nJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xAz-cr-0u2"/>
</connections>
</menuItem>
<menuItem title="Game Boy Advance" tag="3" id="7jw-B1-tf5">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="xQk-4e-kd7"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="DPb-Sh-5tg"/> <menuItem isSeparatorItem="YES" id="DPb-Sh-5tg"/>
<menuItem title="Start Audio Recording…" keyEquivalent="A" id="1UK-8n-QPP"> <menuItem title="Start Audio Recording…" keyEquivalent="A" id="1UK-8n-QPP">
<connections> <connections>

View File

@@ -43,7 +43,7 @@ configuration_t configuration =
.scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR, .scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR,
.blending_mode = GB_FRAME_BLENDING_MODE_ACCURATE, .blending_mode = GB_FRAME_BLENDING_MODE_ACCURATE,
.rewind_length = 60 * 2, .rewind_length = 60 * 2,
.model = MODEL_CGB, .model = MODEL_AUTO,
.volume = 100, .volume = 100,
.rumble_mode = GB_RUMBLE_CARTRIDGE_ONLY, .rumble_mode = GB_RUMBLE_CARTRIDGE_ONLY,
.default_scale = 2, .default_scale = 2,

View File

@@ -83,6 +83,7 @@ typedef struct {
MODEL_AGB, MODEL_AGB,
MODEL_SGB, MODEL_SGB,
MODEL_MGB, MODEL_MGB,
MODEL_AUTO,
MODEL_MAX, MODEL_MAX,
} model; } model;

View File

@@ -933,26 +933,35 @@ static void enter_help_menu(unsigned index)
static void cycle_model(unsigned index) static void cycle_model(unsigned index)
{ {
switch (configuration.model) {
configuration.model++; case MODEL_DMG: configuration.model = MODEL_MGB; break;
if (configuration.model == MODEL_MAX) { case MODEL_MGB: configuration.model = MODEL_SGB; break;
configuration.model = 0; case MODEL_SGB: configuration.model = MODEL_CGB; break;
case MODEL_CGB: configuration.model = MODEL_AGB; break;
case MODEL_AGB: configuration.model = MODEL_AUTO; break;
case MODEL_AUTO: configuration.model = MODEL_DMG; break;
default: configuration.model = MODEL_AUTO;
} }
pending_command = GB_SDL_RESET_COMMAND; pending_command = GB_SDL_RESET_COMMAND;
} }
static void cycle_model_backwards(unsigned index) static void cycle_model_backwards(unsigned index)
{ {
if (configuration.model == 0) { switch (configuration.model) {
configuration.model = MODEL_MAX; case MODEL_MGB: configuration.model = MODEL_DMG; break;
case MODEL_SGB: configuration.model = MODEL_MGB; break;
case MODEL_CGB: configuration.model = MODEL_SGB; break;
case MODEL_AGB: configuration.model = MODEL_CGB; break;
case MODEL_AUTO: configuration.model = MODEL_AGB; break;
case MODEL_DMG: configuration.model = MODEL_AUTO; break;
default: configuration.model = MODEL_AUTO;
} }
configuration.model--;
pending_command = GB_SDL_RESET_COMMAND; pending_command = GB_SDL_RESET_COMMAND;
} }
static const char *current_model_string(unsigned index) static const char *current_model_string(unsigned index)
{ {
return GB_inline_const(const char *[], {"Game Boy", "Game Boy Color", "Game Boy Advance", "Super Game Boy", "Game Boy Pocket"}) return GB_inline_const(const char *[], {"Game Boy", "Game Boy Color", "Game Boy Advance", "Super Game Boy", "Game Boy Pocket", "Pick Automatically"})
[configuration.model]; [configuration.model];
} }

View File

@@ -134,24 +134,21 @@ static void log_capture_callback(GB_gameboy_t *gb, const char *string, GB_log_at
captured_log[current_len + len_to_add] = 0; captured_log[current_len + len_to_add] = 0;
} }
static void start_capturing_logs(void) static void *start_capturing_logs(void)
{ {
if (captured_log != NULL) { void *previous = captured_log;
free(captured_log);
}
captured_log = malloc(1); captured_log = malloc(1);
captured_log[0] = 0; captured_log[0] = 0;
GB_set_log_callback(&gb, log_capture_callback); GB_set_log_callback(&gb, log_capture_callback);
return previous;
} }
static const char *end_capturing_logs(bool show_popup, bool should_exit, uint32_t popup_flags, const char *title) static void end_capturing_logs(bool show_popup, bool should_exit, uint32_t popup_flags, const char *title, void *previous)
{ {
GB_set_log_callback(&gb, console_supported? log_callback : NULL); if (!previous) {
if (captured_log[0] == 0) { GB_set_log_callback(&gb, console_supported? log_callback : NULL);
free(captured_log);
captured_log = NULL;
} }
else { if (captured_log[0] != 0) {
if (show_popup) { if (show_popup) {
SDL_ShowSimpleMessageBox(popup_flags, title, captured_log, window); SDL_ShowSimpleMessageBox(popup_flags, title, captured_log, window);
} }
@@ -159,7 +156,8 @@ static const char *end_capturing_logs(bool show_popup, bool should_exit, uint32_
exit(1); exit(1);
} }
} }
return captured_log; free(captured_log);
captured_log = previous;
} }
static void update_palette(void) static void update_palette(void)
@@ -620,7 +618,7 @@ static bool handle_pending_command(void)
save_extension[2] += command_parameter; save_extension[2] += command_parameter;
replace_extension(filename, strlen(filename), save_path, save_extension); replace_extension(filename, strlen(filename), save_path, save_extension);
start_capturing_logs(); void *previous = start_capturing_logs();
bool success; bool success;
if (pending_command == GB_SDL_LOAD_STATE_COMMAND) { if (pending_command == GB_SDL_LOAD_STATE_COMMAND) {
int result = GB_load_state(&gb, save_path); int result = GB_load_state(&gb, save_path);
@@ -639,25 +637,28 @@ static bool handle_pending_command(void)
end_capturing_logs(true, end_capturing_logs(true,
false, false,
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR, success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
success? "Notice" : "Error"); success? "Notice" : "Error",
previous);
if (success) { if (success) {
show_osd_text(pending_command == GB_SDL_LOAD_STATE_COMMAND? "State loaded" : "State saved"); show_osd_text(pending_command == GB_SDL_LOAD_STATE_COMMAND? "State loaded" : "State saved");
} }
return false; return false;
} }
case GB_SDL_LOAD_STATE_FROM_FILE_COMMAND: case GB_SDL_LOAD_STATE_FROM_FILE_COMMAND: {
start_capturing_logs(); void *previous = start_capturing_logs();
bool success = GB_load_state(&gb, dropped_state_file) == 0; bool success = GB_load_state(&gb, dropped_state_file) == 0;
end_capturing_logs(true, end_capturing_logs(true,
false, false,
success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR, success? SDL_MESSAGEBOX_INFORMATION : SDL_MESSAGEBOX_ERROR,
success? "Notice" : "Error"); success? "Notice" : "Error",
previous);
SDL_free(dropped_state_file); SDL_free(dropped_state_file);
if (success) { if (success) {
show_osd_text("State loaded"); show_osd_text("State loaded");
} }
return false; return false;
}
case GB_SDL_NO_COMMAND: case GB_SDL_NO_COMMAND:
return false; return false;
@@ -697,18 +698,20 @@ static void load_boot_rom(GB_gameboy_t *gb, GB_boot_rom_t type)
use_built_in = GB_load_boot_rom(gb, path); use_built_in = GB_load_boot_rom(gb, path);
} }
if (use_built_in) { if (use_built_in) {
start_capturing_logs(); void *previous = start_capturing_logs();
if (GB_load_boot_rom(gb, resource_path(names[type]))) { if (GB_load_boot_rom(gb, resource_path(names[type]))) {
if (type == GB_BOOT_ROM_CGB_E) { if (type == GB_BOOT_ROM_CGB_E) {
end_capturing_logs(false, false, 0, NULL, previous);
load_boot_rom(gb, GB_BOOT_ROM_CGB); load_boot_rom(gb, GB_BOOT_ROM_CGB);
return; return;
} }
if (type == GB_BOOT_ROM_AGB_0) { if (type == GB_BOOT_ROM_AGB_0) {
end_capturing_logs(false, false, 0, NULL, previous);
load_boot_rom(gb, GB_BOOT_ROM_AGB); load_boot_rom(gb, GB_BOOT_ROM_AGB);
return; return;
} }
} }
end_capturing_logs(true, false, SDL_MESSAGEBOX_ERROR, "Error"); end_capturing_logs(true, false, SDL_MESSAGEBOX_ERROR, "Error", previous);
} }
} }
@@ -752,13 +755,34 @@ static void debugger_reload_callback(GB_gameboy_t *gb)
GB_reset(gb); GB_reset(gb);
} }
static void run(void) static GB_model_t model_to_use(void)
{ {
SDL_ShowCursor(SDL_DISABLE); typeof(configuration.model) gui_model = configuration.model;
GB_model_t model; if (gui_model == MODEL_AUTO) {
pending_command = GB_SDL_NO_COMMAND; uint8_t *rom = GB_get_direct_access(&gb, GB_DIRECT_ACCESS_ROM, NULL, NULL);
restart: if (!rom) {
model = (GB_model_t []) gui_model = MODEL_CGB;
}
else if (rom[0x143] & 0x80) { // Has CGB features
gui_model = MODEL_CGB;
}
else if (rom[0x146] == 3) { // Has SGB features
gui_model = MODEL_SGB;
}
else if (rom[0x14B] == 1) { // Nintendo-licensed (most likely has boot ROM palettes)
gui_model = MODEL_CGB;
}
else if (rom[0x14B] == 0x33 &&
rom[0x144] == '0' &&
rom[0x145] == '1') { // Ditto
gui_model = MODEL_CGB;
}
else {
gui_model = MODEL_DMG;
}
}
return (GB_model_t [])
{ {
[MODEL_DMG] = GB_MODEL_DMG_B, [MODEL_DMG] = GB_MODEL_DMG_B,
[MODEL_CGB] = GB_MODEL_CGB_0 + configuration.cgb_revision, [MODEL_CGB] = GB_MODEL_CGB_0 + configuration.cgb_revision,
@@ -770,7 +794,16 @@ restart:
[SGB_PAL] = GB_MODEL_SGB_PAL, [SGB_PAL] = GB_MODEL_SGB_PAL,
[SGB_2] = GB_MODEL_SGB2, [SGB_2] = GB_MODEL_SGB2,
}[configuration.sgb_revision], }[configuration.sgb_revision],
}[configuration.model]; }[gui_model];
}
static void run(void)
{
SDL_ShowCursor(SDL_DISABLE);
GB_model_t model;
pending_command = GB_SDL_NO_COMMAND;
restart:;
model = model_to_use();
if (GB_is_inited(&gb)) { if (GB_is_inited(&gb)) {
if (doing_hot_swap) { if (doing_hot_swap) {
@@ -819,7 +852,7 @@ restart:
bool error = false; bool error = false;
GB_debugger_clear_symbols(&gb); GB_debugger_clear_symbols(&gb);
start_capturing_logs(); void *previous = start_capturing_logs();
size_t path_length = strlen(filename); size_t path_length = strlen(filename);
char extension[4] = {0,}; char extension[4] = {0,};
if (path_length > 4) { if (path_length > 4) {
@@ -840,6 +873,11 @@ restart:
else { else {
GB_load_rom(&gb, filename); GB_load_rom(&gb, filename);
} }
GB_model_t updated_model = model_to_use(); // Could change after loading ROM with auto setting
if (model != updated_model) {
model = updated_model;
GB_switch_model_and_reset(&gb, model);
}
/* Configure battery */ /* Configure battery */
char battery_save_path[path_length + 5]; /* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */ char battery_save_path[path_length + 5]; /* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */
@@ -856,7 +894,7 @@ restart:
replace_extension(filename, path_length, cheat_path, ".cht"); replace_extension(filename, path_length, cheat_path, ".cht");
GB_load_cheats(&gb, cheat_path); GB_load_cheats(&gb, cheat_path);
end_capturing_logs(true, error, SDL_MESSAGEBOX_WARNING, "Warning"); end_capturing_logs(true, error, SDL_MESSAGEBOX_WARNING, "Warning", previous);
static char start_text[64]; static char start_text[64];
static char title[17]; static char title[17];
@@ -958,14 +996,15 @@ static void handle_model_option(const char *model_string)
GB_model_t model; GB_model_t model;
const char *description; const char *description;
} name_to_model[] = { } name_to_model[] = {
{"auto", -1, "Pick automatically"},
{"dmg-b", GB_MODEL_DMG_B, "Game Boy, DMG-CPU B"}, {"dmg-b", GB_MODEL_DMG_B, "Game Boy, DMG-CPU B"},
{"dmg", GB_MODEL_DMG_B, "Alias of dmg-b"}, {"dmg", GB_MODEL_DMG_B, "Alias of dmg-b"},
{"sgb-ntsc", GB_MODEL_SGB_NTSC, "Super Game Boy (NTSC)"}, {"sgb-ntsc", GB_MODEL_SGB_NTSC, "Super Game Boy (NTSC)"},
{"sgb-pal", GB_MODEL_SGB_PAL, "Super Game Boy (PAL"}, {"sgb-pal", GB_MODEL_SGB_PAL, "Super Game Boy (PAL)"},
{"sgb2", GB_MODEL_SGB2, "Super Game Boy 2"}, {"sgb2", GB_MODEL_SGB2, "Super Game Boy 2"},
{"sgb", GB_MODEL_SGB, "Alias of sgb-ntsc"}, {"sgb", GB_MODEL_SGB, "Alias of sgb-ntsc"},
{"mgb", GB_MODEL_MGB, "Game Boy Pocket/Light"}, {"mgb", GB_MODEL_MGB, "Game Boy Pocket/Light"},
{"cgb-0", GB_MODEL_CGB_0, "Game Boy Color, CPU CGB 0"}, {"cgb-0", GB_MODEL_CGB_0, "Game Boy Color, CPU CGB"},
{"cgb-a", GB_MODEL_CGB_A, "Game Boy Color, CPU CGB A"}, {"cgb-a", GB_MODEL_CGB_A, "Game Boy Color, CPU CGB A"},
{"cgb-b", GB_MODEL_CGB_B, "Game Boy Color, CPU CGB B"}, {"cgb-b", GB_MODEL_CGB_B, "Game Boy Color, CPU CGB B"},
{"cgb-c", GB_MODEL_CGB_C, "Game Boy Color, CPU CGB C"}, {"cgb-c", GB_MODEL_CGB_C, "Game Boy Color, CPU CGB C"},
@@ -1028,6 +1067,7 @@ static void handle_model_option(const char *model_string)
break; break;
default: default:
configuration.model = MODEL_AUTO;
break; break;
} }
} }
@@ -1093,7 +1133,6 @@ int main(int argc, char **argv)
configuration.default_scale %= GB_SDL_DEFAULT_SCALE_MAX + 1; configuration.default_scale %= GB_SDL_DEFAULT_SCALE_MAX + 1;
configuration.blending_mode %= GB_FRAME_BLENDING_MODE_ACCURATE + 1; configuration.blending_mode %= GB_FRAME_BLENDING_MODE_ACCURATE + 1;
configuration.highpass_mode %= GB_HIGHPASS_MAX; configuration.highpass_mode %= GB_HIGHPASS_MAX;
configuration.model %= MODEL_MAX;
configuration.sgb_revision %= SGB_MAX; configuration.sgb_revision %= SGB_MAX;
configuration.dmg_palette %= 5; configuration.dmg_palette %= 5;
if (configuration.dmg_palette) { if (configuration.dmg_palette) {