Let the core handle boot ROM selection

This commit is contained in:
Lior Halphon 2020-01-29 20:29:30 +02:00
parent 99d2c0258c
commit 48d3504de7
4 changed files with 92 additions and 20 deletions

View File

@ -74,8 +74,15 @@ enum model {
topMargin:(unsigned) topMargin bottomMargin: (unsigned) bottomMargin topMargin:(unsigned) topMargin bottomMargin: (unsigned) bottomMargin
exposure:(unsigned) exposure; exposure:(unsigned) exposure;
- (void) gotNewSample:(GB_sample_t *)sample; - (void) gotNewSample:(GB_sample_t *)sample;
- (void) loadBootROM:(GB_boot_rom_t)type;
@end @end
static void boot_rom_load(GB_gameboy_t *gb, GB_boot_rom_t type)
{
Document *self = (__bridge Document *)GB_get_user_data(gb);
[self loadBootROM: type];
}
static void vblank(GB_gameboy_t *gb) static void vblank(GB_gameboy_t *gb)
{ {
Document *self = (__bridge Document *)GB_get_user_data(gb); Document *self = (__bridge Document *)GB_get_user_data(gb);
@ -209,6 +216,7 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample)
{ {
GB_init(&gb, [self internalModel]); GB_init(&gb, [self internalModel]);
GB_set_user_data(&gb, (__bridge void *)(self)); GB_set_user_data(&gb, (__bridge void *)(self));
GB_set_boot_rom_load_callback(&gb, (GB_boot_rom_load_callback_t)boot_rom_load);
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank); GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
GB_set_log_callback(&gb, (GB_log_callback_t) consoleLog); GB_set_log_callback(&gb, (GB_log_callback_t) consoleLog);
GB_set_input_callback(&gb, (GB_input_callback_t) consoleInput); GB_set_input_callback(&gb, (GB_input_callback_t) consoleInput);
@ -340,15 +348,19 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample)
GB_debugger_set_disabled(&gb, false); GB_debugger_set_disabled(&gb, false);
} }
- (void) loadBootROM - (void) loadBootROM: (GB_boot_rom_t)type
{ {
static NSString * const boot_names[] = {@"dmg_boot", @"cgb_boot", @"agb_boot", @"sgb_boot"}; static NSString *const names[] = {
if ([self internalModel] == GB_MODEL_SGB2) { [GB_BOOT_ROM_DMG0] = @"dmg0_boot",
GB_load_boot_rom(&gb, [[self bootROMPathForName:@"sgb2_boot"] UTF8String]); [GB_BOOT_ROM_DMG] = @"dmg_boot",
} [GB_BOOT_ROM_MGB] = @"mgb_boot",
else { [GB_BOOT_ROM_SGB] = @"sgb_boot",
GB_load_boot_rom(&gb, [[self bootROMPathForName:boot_names[current_model - 1]] UTF8String]); [GB_BOOT_ROM_SGB2] = @"sgb2_boot",
} [GB_BOOT_ROM_CGB0] = @"cgb0_boot",
[GB_BOOT_ROM_CGB] = @"cgb_boot",
[GB_BOOT_ROM_AGB] = @"agb_boot",
};
GB_load_boot_rom(&gb, [[self bootROMPathForName:names[type]] UTF8String]);
} }
- (IBAction)reset:(id)sender - (IBAction)reset:(id)sender
@ -360,8 +372,6 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample)
current_model = (enum model)[sender tag]; current_model = (enum model)[sender tag];
} }
[self loadBootROM];
if (!modelsChanging && [sender tag] == MODEL_NONE) { if (!modelsChanging && [sender tag] == MODEL_NONE) {
GB_reset(&gb); GB_reset(&gb);
} }

View File

@ -878,6 +878,36 @@ static void reset_ram(GB_gameboy_t *gb)
} }
} }
static void request_boot_rom(GB_gameboy_t *gb)
{
if (gb->boot_rom_load_callback) {
GB_boot_rom_t type = 0;
switch (gb->model) {
case GB_MODEL_DMG_B:
type = GB_BOOT_ROM_DMG;
break;
case GB_MODEL_SGB_NTSC:
case GB_MODEL_SGB_PAL:
case GB_MODEL_SGB_NTSC_NO_SFC:
case GB_MODEL_SGB_PAL_NO_SFC:
type = GB_BOOT_ROM_SGB;
break;
case GB_MODEL_SGB2:
case GB_MODEL_SGB2_NO_SFC:
type = GB_BOOT_ROM_SGB2;
break;
case GB_MODEL_CGB_C:
case GB_MODEL_CGB_E:
type = GB_BOOT_ROM_CGB;
break;
case GB_MODEL_AGB:
type = GB_BOOT_ROM_AGB;
break;
}
gb->boot_rom_load_callback(gb, type);
}
}
void GB_reset(GB_gameboy_t *gb) void GB_reset(GB_gameboy_t *gb)
{ {
uint32_t mbc_ram_size = gb->mbc_ram_size; uint32_t mbc_ram_size = gb->mbc_ram_size;
@ -948,6 +978,7 @@ void GB_reset(GB_gameboy_t *gb)
} }
gb->magic = state_magic(); gb->magic = state_magic();
request_boot_rom(gb);
} }
void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model) void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model)
@ -1093,3 +1124,9 @@ void GB_set_icd_vreset_callback(GB_gameboy_t *gb, GB_icd_vreset_callback_t callb
{ {
gb->icd_vreset_callback = callback; gb->icd_vreset_callback = callback;
} }
void GB_set_boot_rom_load_callback(GB_gameboy_t *gb, GB_boot_rom_load_callback_t callback)
{
gb->boot_rom_load_callback = callback;
request_boot_rom(gb);
}

View File

@ -229,6 +229,17 @@ typedef enum {
GB_LOG_UNDERLINE_MASK = GB_LOG_DASHED_UNDERLINE | GB_LOG_UNDERLINE GB_LOG_UNDERLINE_MASK = GB_LOG_DASHED_UNDERLINE | GB_LOG_UNDERLINE
} GB_log_attributes; } GB_log_attributes;
typedef enum {
GB_BOOT_ROM_DMG0,
GB_BOOT_ROM_DMG,
GB_BOOT_ROM_MGB,
GB_BOOT_ROM_SGB,
GB_BOOT_ROM_SGB2,
GB_BOOT_ROM_CGB0,
GB_BOOT_ROM_CGB,
GB_BOOT_ROM_AGB,
} GB_boot_rom_t;
#ifdef GB_INTERNAL #ifdef GB_INTERNAL
#define LCDC_PERIOD 70224 #define LCDC_PERIOD 70224
#define CPU_FREQUENCY 0x400000 #define CPU_FREQUENCY 0x400000
@ -259,6 +270,7 @@ typedef void (*GB_joyp_write_callback_t)(GB_gameboy_t *gb, uint8_t value);
typedef void (*GB_icd_pixel_callback_t)(GB_gameboy_t *gb, uint8_t row); typedef void (*GB_icd_pixel_callback_t)(GB_gameboy_t *gb, uint8_t row);
typedef void (*GB_icd_hreset_callback_t)(GB_gameboy_t *gb); typedef void (*GB_icd_hreset_callback_t)(GB_gameboy_t *gb);
typedef void (*GB_icd_vreset_callback_t)(GB_gameboy_t *gb); typedef void (*GB_icd_vreset_callback_t)(GB_gameboy_t *gb);
typedef void (*GB_boot_rom_load_callback_t)(GB_gameboy_t *gb, GB_boot_rom_t type);
typedef struct { typedef struct {
bool state; bool state;
@ -553,6 +565,7 @@ struct GB_gameboy_internal_s {
GB_icd_vreset_callback_t icd_hreset_callback; GB_icd_vreset_callback_t icd_hreset_callback;
GB_icd_vreset_callback_t icd_vreset_callback; GB_icd_vreset_callback_t icd_vreset_callback;
GB_read_memory_callback_t read_memory_callback; GB_read_memory_callback_t read_memory_callback;
GB_boot_rom_load_callback_t boot_rom_load_callback;
/* IR */ /* IR */
long cycles_since_ir_change; // In 8MHz units long cycles_since_ir_change; // In 8MHz units
@ -706,6 +719,8 @@ void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callb
void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback); void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback);
void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback); void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback);
void GB_set_update_input_hint_callback(GB_gameboy_t *gb, GB_update_input_hint_callback_t callback); void GB_set_update_input_hint_callback(GB_gameboy_t *gb, GB_update_input_hint_callback_t callback);
/* Called when a new boot ROM is needed. The callback should call GB_load_boot_rom or GB_load_boot_rom_from_buffer */
void GB_set_boot_rom_load_callback(GB_gameboy_t *gb, GB_boot_rom_load_callback_t callback);
void GB_set_palette(GB_gameboy_t *gb, const GB_palette_t *palette); void GB_set_palette(GB_gameboy_t *gb, const GB_palette_t *palette);

View File

@ -445,6 +445,24 @@ static bool handle_pending_command(void)
return false; return false;
} }
static void load_boot_rom(GB_gameboy_t *gb, GB_boot_rom_t type)
{
bool error = false;
start_capturing_logs();
static const char *const names[] = {
[GB_BOOT_ROM_DMG0] = "dmg0_boot.bin",
[GB_BOOT_ROM_DMG] = "dmg_boot.bin",
[GB_BOOT_ROM_MGB] = "mgb_boot.bin",
[GB_BOOT_ROM_SGB] = "sgb_boot.bin",
[GB_BOOT_ROM_SGB2] = "sgb2_boot.bin",
[GB_BOOT_ROM_CGB0] = "cgb0_boot.bin",
[GB_BOOT_ROM_CGB] = "cgb_boot.bin",
[GB_BOOT_ROM_AGB] = "agb_boot.bin",
};
GB_load_boot_rom(gb, resource_path(names[type]));
end_capturing_logs(true, error);
}
static void run(void) static void run(void)
{ {
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
@ -470,6 +488,7 @@ restart:
else { else {
GB_init(&gb, model); GB_init(&gb, model);
GB_set_boot_rom_load_callback(&gb, load_boot_rom);
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank); GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
GB_set_pixels_output(&gb, active_pixel_buffer); GB_set_pixels_output(&gb, active_pixel_buffer);
GB_set_rgb_encode_callback(&gb, rgb_encode); GB_set_rgb_encode_callback(&gb, rgb_encode);
@ -490,15 +509,6 @@ restart:
bool error = false; bool error = false;
start_capturing_logs();
const char * const boot_roms[] = {"dmg_boot.bin", "cgb_boot.bin", "agb_boot.bin", "sgb_boot.bin"};
const char *boot_rom = boot_roms[configuration.model];
if (configuration.model == MODEL_SGB && configuration.sgb_revision == SGB_2) {
boot_rom = "sgb2_boot.bin";
}
error = GB_load_boot_rom(&gb, resource_path(boot_rom));
end_capturing_logs(true, error);
start_capturing_logs(); start_capturing_logs();
error = GB_load_rom(&gb, filename); error = GB_load_rom(&gb, filename);
end_capturing_logs(true, error); end_capturing_logs(true, error);