mirror of https://github.com/bsnes-emu/bsnes.git
Replaced the is_cgb bool with a more future compatible model enum. Removed the GB_init_cgb API and replaced it with an extended GB_init and GB_switch_model_and_reset APIs that now receive a model parameter. Increased the struct version.
This commit is contained in:
parent
c286203640
commit
45c73e0175
|
@ -18,6 +18,13 @@ enum model {
|
|||
MODEL_AGB,
|
||||
};
|
||||
|
||||
static const GB_model_t cocoa_to_internal_model[] =
|
||||
{
|
||||
[MODEL_DMG] = GB_MODEL_DMG_B,
|
||||
[MODEL_CGB] = GB_MODEL_CGB_E,
|
||||
[MODEL_AGB] = GB_MODEL_AGB
|
||||
};
|
||||
|
||||
@interface Document ()
|
||||
{
|
||||
/* NSTextViews freeze the entire app if they're modified too often and too quickly.
|
||||
|
@ -137,21 +144,22 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height,
|
|||
- (void) initDMG
|
||||
{
|
||||
current_model = MODEL_DMG;
|
||||
GB_init(&gb);
|
||||
GB_init(&gb, cocoa_to_internal_model[current_model]);
|
||||
[self initCommon];
|
||||
GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:@"dmg_boot" ofType:@"bin"] UTF8String]);
|
||||
}
|
||||
|
||||
- (void) initCGB
|
||||
{
|
||||
GB_init_cgb(&gb);
|
||||
[self initCommon];
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateAGB"]) {
|
||||
current_model = MODEL_AGB;
|
||||
GB_init(&gb, cocoa_to_internal_model[current_model]);
|
||||
GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:@"agb_boot" ofType:@"bin"] UTF8String]);
|
||||
}
|
||||
else {
|
||||
current_model = MODEL_CGB;
|
||||
GB_init(&gb, cocoa_to_internal_model[current_model]);
|
||||
GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:@"cgb_boot" ofType:@"bin"] UTF8String]);
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +258,7 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height,
|
|||
}
|
||||
else {
|
||||
current_model = (enum model)[sender tag];
|
||||
GB_switch_model_and_reset(&gb, current_model != MODEL_DMG);
|
||||
GB_switch_model_and_reset(&gb, cocoa_to_internal_model[current_model]);
|
||||
static NSString * const boot_names[] = {@"dmg_boot", @"cgb_boot", @"agb_boot"};
|
||||
GB_load_boot_rom(&gb, [[[NSBundle mainBundle] pathForResource:boot_names[current_model - 1] ofType:@"bin"] UTF8String]);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
break;
|
||||
case GBMemoryVRAM:
|
||||
bank_backup = gb->cgb_vram_bank;
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
gb->cgb_vram_bank = self.selectedBank;
|
||||
}
|
||||
addr += 0x8000;
|
||||
|
@ -66,7 +66,7 @@
|
|||
break;
|
||||
case GBMemoryRAM:
|
||||
bank_backup = gb->cgb_ram_bank;
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
gb->cgb_ram_bank = self.selectedBank;
|
||||
}
|
||||
addr += 0xC000;
|
||||
|
@ -127,7 +127,7 @@
|
|||
break;
|
||||
case GBMemoryVRAM:
|
||||
bank_backup = gb->cgb_vram_bank;
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
gb->cgb_vram_bank = self.selectedBank;
|
||||
}
|
||||
addr += 0x8000;
|
||||
|
@ -139,7 +139,7 @@
|
|||
break;
|
||||
case GBMemoryRAM:
|
||||
bank_backup = gb->cgb_ram_bank;
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
gb->cgb_ram_bank = self.selectedBank;
|
||||
}
|
||||
addr += 0xC000;
|
||||
|
|
10
Core/apu.c
10
Core/apu.c
|
@ -468,7 +468,7 @@ uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg)
|
|||
};
|
||||
|
||||
if (reg >= GB_IO_WAV_START && reg <= GB_IO_WAV_END && gb->apu.is_active[GB_WAVE]) {
|
||||
if (!gb->is_cgb && !gb->apu.wave_channel.wave_form_just_read) {
|
||||
if (!GB_is_cgb(gb) && !gb->apu.wave_channel.wave_form_just_read) {
|
||||
return 0xFF;
|
||||
}
|
||||
reg = GB_IO_WAV_START + gb->apu.wave_channel.current_sample_index / 2;
|
||||
|
@ -479,7 +479,7 @@ uint8_t GB_apu_read(GB_gameboy_t *gb, uint8_t reg)
|
|||
|
||||
void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
|
||||
{
|
||||
if (!gb->apu.global_enable && reg != GB_IO_NR52 && (gb->is_cgb ||
|
||||
if (!gb->apu.global_enable && reg != GB_IO_NR52 && (GB_is_cgb(gb) ||
|
||||
(
|
||||
reg != GB_IO_NR11 &&
|
||||
reg != GB_IO_NR21 &&
|
||||
|
@ -491,7 +491,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
|
|||
}
|
||||
|
||||
if (reg >= GB_IO_WAV_START && reg <= GB_IO_WAV_END && gb->apu.is_active[GB_WAVE]) {
|
||||
if (!gb->is_cgb && !gb->apu.wave_channel.wave_form_just_read) {
|
||||
if (!GB_is_cgb(gb) && !gb->apu.wave_channel.wave_form_just_read) {
|
||||
return;
|
||||
}
|
||||
reg = GB_IO_WAV_START + gb->apu.wave_channel.current_sample_index / 2;
|
||||
|
@ -533,7 +533,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
|
|||
gb->apu.global_enable = false;
|
||||
}
|
||||
|
||||
if (!gb->is_cgb && (value & 0x80)) {
|
||||
if (!GB_is_cgb(gb) && (value & 0x80)) {
|
||||
GB_apu_write(gb, GB_IO_NR11, old_nrx1[0]);
|
||||
GB_apu_write(gb, GB_IO_NR21, old_nrx1[1]);
|
||||
GB_apu_write(gb, GB_IO_NR31, old_nrx1[2]);
|
||||
|
@ -694,7 +694,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
|
|||
if ((value & 0x80)) {
|
||||
/* DMG bug: wave RAM gets corrupted if the channel is retriggerred 1 cycle before the APU
|
||||
reads from it. */
|
||||
if (!gb->is_cgb &&
|
||||
if (!GB_is_cgb(gb) &&
|
||||
gb->apu.is_active[GB_WAVE] &&
|
||||
gb->apu.wave_channel.sample_countdown == 0 &&
|
||||
gb->apu.wave_channel.enable) {
|
||||
|
|
|
@ -112,7 +112,7 @@ static inline void switch_banking_state(GB_gameboy_t *gb, uint16_t bank)
|
|||
gb->mbc_rom_bank = bank;
|
||||
gb->mbc_ram_bank = bank;
|
||||
gb->mbc_ram_enable = true;
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
gb->cgb_ram_bank = bank & 7;
|
||||
gb->cgb_vram_bank = bank & 1;
|
||||
if (gb->cgb_ram_bank == 0) {
|
||||
|
@ -1462,7 +1462,7 @@ static bool palettes(GB_gameboy_t *gb, char *arguments, char *modifiers, const d
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
GB_log(gb, "Not available on a DMG.\n");
|
||||
return true;
|
||||
}
|
||||
|
@ -1495,7 +1495,7 @@ static bool lcd(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugg
|
|||
}
|
||||
GB_log(gb, "LCDC:\n");
|
||||
GB_log(gb, " LCD enabled: %s\n",(gb->io_registers[GB_IO_LCDC] & 128)? "Enabled" : "Disabled");
|
||||
GB_log(gb, " %s: %s\n", gb->is_cgb? (gb->cgb_mode? "Sprite priority flags" : "Background and Window") : "Background",
|
||||
GB_log(gb, " %s: %s\n", GB_is_cgb(gb)? (gb->cgb_mode? "Sprite priority flags" : "Background and Window") : "Background",
|
||||
(gb->io_registers[GB_IO_LCDC] & 1)? "Enabled" : "Disabled");
|
||||
GB_log(gb, " Objects: %s\n", (gb->io_registers[GB_IO_LCDC] & 2)? "Enabled" : "Disabled");
|
||||
GB_log(gb, " Object size: %s\n", (gb->io_registers[GB_IO_LCDC] & 4)? "8x16" : "8x8");
|
||||
|
|
|
@ -113,7 +113,7 @@ typedef struct __attribute__((packed)) {
|
|||
static bool window_enabled(GB_gameboy_t *gb)
|
||||
{
|
||||
if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) {
|
||||
if (!gb->cgb_mode && gb->is_cgb) {
|
||||
if (!gb->cgb_mode && GB_is_cgb(gb)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ uint32_t GB_convert_rgb15(GB_gameboy_t *gb, uint16_t color)
|
|||
|
||||
void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index)
|
||||
{
|
||||
if (!gb->rgb_encode_callback || !gb->is_cgb) return;
|
||||
if (!gb->rgb_encode_callback || !GB_is_cgb(gb)) return;
|
||||
uint8_t *palette_data = background_palette? gb->background_palettes_data : gb->sprite_palettes_data;
|
||||
uint16_t color = palette_data[index & ~1] | (palette_data[index | 1] << 8);
|
||||
|
||||
|
@ -213,7 +213,7 @@ void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index
|
|||
void GB_set_color_correction_mode(GB_gameboy_t *gb, GB_color_correction_mode_t mode)
|
||||
{
|
||||
gb->color_correction_mode = mode;
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
for (unsigned i = 0; i < 32; i++) {
|
||||
GB_palette_changed(gb, false, i * 2);
|
||||
GB_palette_changed(gb, true, i * 2);
|
||||
|
@ -236,7 +236,7 @@ void GB_STAT_update(GB_gameboy_t *gb)
|
|||
|
||||
bool previous_interrupt_line = gb->stat_interrupt_line;
|
||||
/* Set LY=LYC bit */
|
||||
if (gb->ly_for_comparison != (uint16_t)-1 || !gb->is_cgb) {
|
||||
if (gb->ly_for_comparison != (uint16_t)-1 || !GB_is_cgb(gb)) {
|
||||
if (gb->ly_for_comparison == gb->io_registers[GB_IO_LYC]) {
|
||||
gb->lyc_interrupt_line = true;
|
||||
gb->io_registers[GB_IO_STAT] |= 4;
|
||||
|
@ -362,7 +362,7 @@ static void render_pixel_if_possible(GB_gameboy_t *gb)
|
|||
bg_enabled = false;
|
||||
}
|
||||
}
|
||||
if (!gb->is_cgb && gb->in_window) {
|
||||
if (!GB_is_cgb(gb) && gb->in_window) {
|
||||
bg_enabled = true;
|
||||
}
|
||||
|
||||
|
@ -434,7 +434,7 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
|
|||
|
||||
/* Todo: Verified for DMG (Tested: SGB2), CGB timing is wrong. */
|
||||
uint8_t y = fetcher_y(gb);
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
/* This value is cached on the CGB, so it cannot be used to mix tiles together */
|
||||
/* Todo: This is NOT true on CGB-B! This is likely the case for all CGBs prior to D.
|
||||
Currently, SameBoy is emulating CGB-E, but if other revisions are added in the future
|
||||
|
@ -442,7 +442,7 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
|
|||
gb->fetcher_y = y;
|
||||
}
|
||||
gb->current_tile = gb->vram[map + gb->fetcher_x + y / 8 * 32];
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
/* The CGB actually accesses both the tile index AND the attributes in the same T-cycle.
|
||||
This probably means the CGB has a 16-bit data bus for the VRAM. */
|
||||
gb->current_tile_attributes = gb->vram[map + gb->fetcher_x + y / 8 * 32 + 0x2000];
|
||||
|
@ -456,7 +456,7 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
|
|||
case GB_FETCHER_GET_TILE_DATA_LOWER: {
|
||||
uint8_t y_flip = 0;
|
||||
uint16_t tile_address = 0;
|
||||
uint8_t y = gb->is_cgb? gb->fetcher_y : fetcher_y(gb);
|
||||
uint8_t y = GB_is_cgb(gb)? gb->fetcher_y : fetcher_y(gb);
|
||||
|
||||
/* Todo: Verified for DMG (Tested: SGB2), CGB timing is wrong. */
|
||||
if (gb->io_registers[GB_IO_LCDC] & 0x10) {
|
||||
|
@ -483,7 +483,7 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb)
|
|||
bit mid-fetching causes a glitched mixing of the two, in comparison to the
|
||||
more logical DMG version. */
|
||||
uint16_t tile_address = 0;
|
||||
uint8_t y = gb->is_cgb? gb->fetcher_y : fetcher_y(gb);
|
||||
uint8_t y = GB_is_cgb(gb)? gb->fetcher_y : fetcher_y(gb);
|
||||
|
||||
if (gb->io_registers[GB_IO_LCDC] & 0x10) {
|
||||
tile_address = gb->current_tile * 0x10;
|
||||
|
@ -571,7 +571,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
GB_SLEEP(gb, display, 23, 1);
|
||||
}
|
||||
|
||||
|
@ -593,9 +593,9 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
gb->io_registers[GB_IO_STAT] |= 3;
|
||||
gb->mode_for_interrupt = 3;
|
||||
gb->oam_read_blocked = true;
|
||||
gb->vram_read_blocked = !gb->is_cgb;
|
||||
gb->vram_read_blocked = !GB_is_cgb(gb);
|
||||
gb->oam_write_blocked = true;
|
||||
gb->vram_write_blocked = !gb->is_cgb;
|
||||
gb->vram_write_blocked = !GB_is_cgb(gb);
|
||||
GB_STAT_update(gb);
|
||||
|
||||
gb->cycles_for_line += 2;
|
||||
|
@ -634,7 +634,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
while (true) {
|
||||
/* Lines 0 - 143 */
|
||||
for (; gb->current_line < LINES; gb->current_line++) {
|
||||
gb->oam_write_blocked = gb->is_cgb;
|
||||
gb->oam_write_blocked = GB_is_cgb(gb);
|
||||
gb->accessed_oam_row = 0;
|
||||
GB_SLEEP(gb, display, 6, 3);
|
||||
gb->io_registers[GB_IO_LY] = gb->current_line;
|
||||
|
@ -647,7 +647,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
gb->mode_for_interrupt = 2;
|
||||
gb->io_registers[GB_IO_STAT] &= ~3;
|
||||
}
|
||||
else if (!gb->is_cgb) {
|
||||
else if (!GB_is_cgb(gb)) {
|
||||
gb->io_registers[GB_IO_STAT] &= ~3;
|
||||
}
|
||||
GB_STAT_update(gb);
|
||||
|
@ -665,19 +665,19 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
gb->n_visible_objs = 0;
|
||||
|
||||
for (gb->oam_search_index = 0; gb->oam_search_index < 40; gb->oam_search_index++) {
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
add_object_from_index(gb, gb->oam_search_index);
|
||||
/* The CGB does not care about the accessed OAM row as there's no OAM bug*/
|
||||
}
|
||||
GB_SLEEP(gb, display, 8, 2);
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
add_object_from_index(gb, gb->oam_search_index);
|
||||
gb->accessed_oam_row = (gb->oam_search_index & ~1) * 4 + 8;
|
||||
}
|
||||
if (gb->oam_search_index == 37) {
|
||||
gb->vram_read_blocked = !gb->is_cgb;
|
||||
gb->vram_read_blocked = !GB_is_cgb(gb);
|
||||
gb->vram_write_blocked = false;
|
||||
gb->oam_write_blocked = gb->is_cgb;
|
||||
gb->oam_write_blocked = GB_is_cgb(gb);
|
||||
GB_STAT_update(gb);
|
||||
}
|
||||
}
|
||||
|
@ -719,7 +719,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
gb->n_visible_objs--;
|
||||
}
|
||||
while (gb->n_visible_objs != 0 &&
|
||||
(gb->io_registers[GB_IO_LCDC] & 2 || gb->is_cgb) &&
|
||||
(gb->io_registers[GB_IO_LCDC] & 2 || GB_is_cgb(gb)) &&
|
||||
gb->obj_comperators[gb->n_visible_objs - 1] == (uint8_t)(gb->position_in_line + 8)) {
|
||||
|
||||
while (gb->fetcher_state < 5) {
|
||||
|
@ -864,17 +864,17 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
gb->io_registers[GB_IO_LY] = 153;
|
||||
gb->ly_for_comparison = -1;
|
||||
GB_STAT_update(gb);
|
||||
GB_SLEEP(gb, display, 14, gb->is_cgb? 4: 6);
|
||||
GB_SLEEP(gb, display, 14, GB_is_cgb(gb)? 4: 6);
|
||||
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
gb->io_registers[GB_IO_LY] = 0;
|
||||
}
|
||||
gb->ly_for_comparison = 153;
|
||||
GB_STAT_update(gb);
|
||||
GB_SLEEP(gb, display, 15, gb->is_cgb? 4: 2);
|
||||
GB_SLEEP(gb, display, 15, GB_is_cgb(gb)? 4: 2);
|
||||
|
||||
gb->io_registers[GB_IO_LY] = 0;
|
||||
gb->ly_for_comparison = gb->is_cgb? 153 : -1;
|
||||
gb->ly_for_comparison = GB_is_cgb(gb)? 153 : -1;
|
||||
GB_STAT_update(gb);
|
||||
GB_SLEEP(gb, display, 16, 4);
|
||||
|
||||
|
@ -896,7 +896,7 @@ void GB_draw_tileset(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette
|
|||
uint32_t none_palette[4];
|
||||
uint32_t *palette = NULL;
|
||||
|
||||
switch (gb->is_cgb? palette_type : GB_PALETTE_NONE) {
|
||||
switch (GB_is_cgb(gb)? palette_type : GB_PALETTE_NONE) {
|
||||
default:
|
||||
case GB_PALETTE_NONE:
|
||||
none_palette[0] = gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF);
|
||||
|
@ -915,7 +915,7 @@ void GB_draw_tileset(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette
|
|||
|
||||
for (unsigned y = 0; y < 192; y++) {
|
||||
for (unsigned x = 0; x < 256; x++) {
|
||||
if (x >= 128 && !gb->is_cgb) {
|
||||
if (x >= 128 && !GB_is_cgb(gb)) {
|
||||
*(dest++) = gb->background_palettes_rgb[0];
|
||||
continue;
|
||||
}
|
||||
|
@ -947,7 +947,7 @@ void GB_draw_tilemap(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette
|
|||
uint32_t *palette = NULL;
|
||||
uint16_t map = 0x1800;
|
||||
|
||||
switch (gb->is_cgb? palette_type : GB_PALETTE_NONE) {
|
||||
switch (GB_is_cgb(gb)? palette_type : GB_PALETTE_NONE) {
|
||||
case GB_PALETTE_NONE:
|
||||
none_palette[0] = gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF);
|
||||
none_palette[1] = gb->rgb_encode_callback(gb, 0xAA, 0xAA, 0xAA);
|
||||
|
@ -1048,7 +1048,7 @@ uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest, uint8_t *sprite_h
|
|||
uint16_t vram_address = dest[i].tile * 0x10;
|
||||
uint8_t flags = dest[i].flags;
|
||||
uint8_t palette = gb->cgb_mode? (flags & 7) : ((flags & 0x10)? 1 : 0);
|
||||
if (gb->is_cgb && (flags & 0x8)) {
|
||||
if (GB_is_cgb(gb) && (flags & 0x8)) {
|
||||
vram_address += 0x2000;
|
||||
}
|
||||
|
||||
|
|
47
Core/gb.c
47
Core/gb.c
|
@ -90,11 +90,18 @@ static char *default_async_input_callback(GB_gameboy_t *gb)
|
|||
}
|
||||
#endif
|
||||
|
||||
void GB_init(GB_gameboy_t *gb)
|
||||
void GB_init(GB_gameboy_t *gb, GB_model_t model)
|
||||
{
|
||||
memset(gb, 0, sizeof(*gb));
|
||||
gb->ram = malloc(gb->ram_size = 0x2000);
|
||||
gb->vram = malloc(gb->vram_size = 0x2000);
|
||||
gb->model = model;
|
||||
if (GB_is_cgb(gb)) {
|
||||
gb->ram = malloc(gb->ram_size = 0x2000 * 8);
|
||||
gb->vram = malloc(gb->vram_size = 0x2000 * 2);
|
||||
}
|
||||
else {
|
||||
gb->ram = malloc(gb->ram_size = 0x2000);
|
||||
gb->vram = malloc(gb->vram_size = 0x2000);
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEBUGGER
|
||||
gb->input_callback = default_input_callback;
|
||||
|
@ -106,21 +113,9 @@ void GB_init(GB_gameboy_t *gb)
|
|||
GB_reset(gb);
|
||||
}
|
||||
|
||||
void GB_init_cgb(GB_gameboy_t *gb)
|
||||
GB_model_t GB_get_model(GB_gameboy_t *gb)
|
||||
{
|
||||
memset(gb, 0, sizeof(*gb));
|
||||
gb->ram = malloc(gb->ram_size = 0x2000 * 8);
|
||||
gb->vram = malloc(gb->vram_size = 0x2000 * 2);
|
||||
gb->is_cgb = true;
|
||||
|
||||
#ifndef DISABLE_DEBUGGER
|
||||
gb->input_callback = default_input_callback;
|
||||
gb->async_input_callback = default_async_input_callback;
|
||||
#endif
|
||||
gb->cartridge_type = &GB_cart_defs[0]; // Default cartridge type
|
||||
gb->clock_multiplier = 1.0;
|
||||
|
||||
GB_reset(gb);
|
||||
return gb->model;
|
||||
}
|
||||
|
||||
void GB_free(GB_gameboy_t *gb)
|
||||
|
@ -339,7 +334,7 @@ void GB_set_async_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback)
|
|||
|
||||
void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback)
|
||||
{
|
||||
if (!gb->rgb_encode_callback && !gb->is_cgb) {
|
||||
if (!gb->rgb_encode_callback && !GB_is_cgb(gb)) {
|
||||
gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] =
|
||||
callback(gb, 0xFF, 0xFF, 0xFF);
|
||||
gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] =
|
||||
|
@ -424,7 +419,7 @@ bool GB_is_inited(GB_gameboy_t *gb)
|
|||
|
||||
bool GB_is_cgb(GB_gameboy_t *gb)
|
||||
{
|
||||
return gb->is_cgb;
|
||||
return ((gb->model) & GB_MODEL_FAMILY_MASK) == GB_MODEL_CGB_FAMILY;
|
||||
}
|
||||
|
||||
void GB_set_turbo_mode(GB_gameboy_t *gb, bool on, bool no_frame_skip)
|
||||
|
@ -451,7 +446,7 @@ void GB_set_user_data(GB_gameboy_t *gb, void *data)
|
|||
void GB_reset(GB_gameboy_t *gb)
|
||||
{
|
||||
uint32_t mbc_ram_size = gb->mbc_ram_size;
|
||||
bool cgb = gb->is_cgb;
|
||||
bool cgb = GB_is_cgb(gb);
|
||||
memset(gb, 0, (size_t)GB_GET_SECTION((GB_gameboy_t *) 0, unsaved));
|
||||
gb->version = GB_STRUCT_VERSION;
|
||||
|
||||
|
@ -466,7 +461,7 @@ void GB_reset(GB_gameboy_t *gb)
|
|||
gb->vram_size = 0x2000 * 2;
|
||||
memset(gb->vram, 0, gb->vram_size);
|
||||
|
||||
gb->is_cgb = true;
|
||||
gb->model = GB_MODEL_CGB_E;
|
||||
gb->cgb_mode = true;
|
||||
}
|
||||
else {
|
||||
|
@ -491,16 +486,17 @@ void GB_reset(GB_gameboy_t *gb)
|
|||
gb->io_registers[GB_IO_SC] = 0x7E;
|
||||
|
||||
/* These are not deterministic, but 00 (CGB) and FF (DMG) are the most common initial values by far */
|
||||
gb->io_registers[GB_IO_DMA] = gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = gb->is_cgb? 0x00 : 0xFF;
|
||||
gb->io_registers[GB_IO_DMA] = gb->io_registers[GB_IO_OBP0] = gb->io_registers[GB_IO_OBP1] = GB_is_cgb(gb)? 0x00 : 0xFF;
|
||||
|
||||
gb->accessed_oam_row = -1;
|
||||
|
||||
gb->magic = (uintptr_t)'SAME';
|
||||
}
|
||||
|
||||
void GB_switch_model_and_reset(GB_gameboy_t *gb, bool is_cgb)
|
||||
void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model)
|
||||
{
|
||||
if (is_cgb) {
|
||||
gb->model = model;
|
||||
if (GB_is_cgb(gb)) {
|
||||
gb->ram = realloc(gb->ram, gb->ram_size = 0x2000 * 8);
|
||||
gb->vram = realloc(gb->vram, gb->vram_size = 0x2000 * 2);
|
||||
}
|
||||
|
@ -508,7 +504,6 @@ void GB_switch_model_and_reset(GB_gameboy_t *gb, bool is_cgb)
|
|||
gb->ram = realloc(gb->ram, gb->ram_size = 0x2000);
|
||||
gb->vram = realloc(gb->vram, gb->vram_size = 0x2000);
|
||||
}
|
||||
gb->is_cgb = is_cgb;
|
||||
GB_rewind_free(gb);
|
||||
GB_reset(gb);
|
||||
}
|
||||
|
@ -553,7 +548,7 @@ void *GB_get_direct_access(GB_gameboy_t *gb, GB_direct_access_t access, size_t *
|
|||
*bank = 0;
|
||||
return &gb->io_registers;
|
||||
case GB_DIRECT_ACCESS_BOOTROM:
|
||||
*size = gb->is_cgb? sizeof(gb->boot_rom) : 0x100;
|
||||
*size = GB_is_cgb(gb)? sizeof(gb->boot_rom) : 0x100;
|
||||
*bank = 0;
|
||||
return &gb->boot_rom;
|
||||
case GB_DIRECT_ACCESS_OAM:
|
||||
|
|
37
Core/gb.h
37
Core/gb.h
|
@ -20,7 +20,34 @@
|
|||
#include "z80_cpu.h"
|
||||
#include "symbol_hash.h"
|
||||
|
||||
#define GB_STRUCT_VERSION 12
|
||||
#define GB_STRUCT_VERSION 13
|
||||
|
||||
typedef enum {
|
||||
#ifdef GB_INTERNAL
|
||||
GB_MODEL_FAMILY_MASK = 0xF00,
|
||||
GB_MODEL_DMG_FAMILY = 0x000,
|
||||
#endif
|
||||
// GB_MODEL_DMG_0 = 0x000,
|
||||
// GB_MODEL_DMG_A = 0x001,
|
||||
GB_MODEL_DMG_B = 0x002,
|
||||
// GB_MODEL_DMG_C = 0x003,
|
||||
// GB_MODEL_SGB = 0x004,
|
||||
#ifdef GB_INTERNAL
|
||||
GB_MODEL_MGB_FAMILY = 0x100,
|
||||
#endif
|
||||
// GB_MODEL_MGB = 0x100,
|
||||
// GB_MODEL_SGB2 = 0x101,
|
||||
#ifdef GB_INTERNAL
|
||||
GB_MODEL_CGB_FAMILY = 0x200,
|
||||
#endif
|
||||
// GB_MODEL_CGB_0 = 0x200,
|
||||
// GB_MODEL_CGB_A = 0x201,
|
||||
// GB_MODEL_CGB_B = 0x202,
|
||||
// GB_MODEL_CGB_C = 0x203,
|
||||
// GB_MODEL_CGB_D = 0x204,
|
||||
GB_MODEL_CGB_E = 0x205,
|
||||
GB_MODEL_AGB = 0x206,
|
||||
} GB_model_t;
|
||||
|
||||
enum {
|
||||
GB_REGISTER_AF,
|
||||
|
@ -261,8 +288,8 @@ struct GB_gameboy_internal_s {
|
|||
uint8_t cgb_ram_bank;
|
||||
|
||||
/* CPU and General Hardware Flags*/
|
||||
GB_model_t model;
|
||||
bool cgb_mode;
|
||||
bool is_cgb;
|
||||
bool cgb_double_speed;
|
||||
bool halted;
|
||||
bool stopped;
|
||||
|
@ -547,13 +574,13 @@ struct GB_gameboy_s {
|
|||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#endif
|
||||
|
||||
void GB_init(GB_gameboy_t *gb);
|
||||
void GB_init_cgb(GB_gameboy_t *gb);
|
||||
void GB_init(GB_gameboy_t *gb, GB_model_t model);
|
||||
bool GB_is_inited(GB_gameboy_t *gb);
|
||||
bool GB_is_cgb(GB_gameboy_t *gb);
|
||||
GB_model_t GB_get_model(GB_gameboy_t *gb);
|
||||
void GB_free(GB_gameboy_t *gb);
|
||||
void GB_reset(GB_gameboy_t *gb);
|
||||
void GB_switch_model_and_reset(GB_gameboy_t *gb, bool is_cgb);
|
||||
void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model);
|
||||
|
||||
/* Returns the time passed, in 4MHz ticks. */
|
||||
uint8_t GB_run(GB_gameboy_t *gb);
|
||||
|
|
|
@ -24,7 +24,7 @@ static GB_bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr)
|
|||
return GB_BUS_MAIN;
|
||||
}
|
||||
if (addr < 0xFE00) {
|
||||
return gb->is_cgb? GB_BUS_RAM : GB_BUS_MAIN;
|
||||
return GB_is_cgb(gb)? GB_BUS_RAM : GB_BUS_MAIN;
|
||||
}
|
||||
return GB_BUS_INTERNAL;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ static uint8_t bitwise_glitch_read_increase(uint8_t a, uint8_t b, uint8_t c, uin
|
|||
|
||||
void GB_trigger_oam_bug(GB_gameboy_t *gb, uint16_t address)
|
||||
{
|
||||
if (gb->is_cgb) return;
|
||||
if (GB_is_cgb(gb)) return;
|
||||
|
||||
if (address >= 0xFE00 && address < 0xFF00) {
|
||||
if (gb->accessed_oam_row != 0xff && gb->accessed_oam_row >= 8) {
|
||||
|
@ -65,7 +65,7 @@ void GB_trigger_oam_bug(GB_gameboy_t *gb, uint16_t address)
|
|||
|
||||
void GB_trigger_oam_bug_read(GB_gameboy_t *gb, uint16_t address)
|
||||
{
|
||||
if (gb->is_cgb) return;
|
||||
if (GB_is_cgb(gb)) return;
|
||||
|
||||
if (address >= 0xFE00 && address < 0xFF00) {
|
||||
if (gb->accessed_oam_row != 0xff && gb->accessed_oam_row >= 8) {
|
||||
|
@ -86,7 +86,7 @@ void GB_trigger_oam_bug_read(GB_gameboy_t *gb, uint16_t address)
|
|||
|
||||
void GB_trigger_oam_bug_read_increase(GB_gameboy_t *gb, uint16_t address)
|
||||
{
|
||||
if (gb->is_cgb) return;
|
||||
if (GB_is_cgb(gb)) return;
|
||||
|
||||
if (address >= 0xFE00 && address < 0xFF00) {
|
||||
if (gb->accessed_oam_row != 0xff && gb->accessed_oam_row >= 0x20 && gb->accessed_oam_row < 0x98) {
|
||||
|
@ -119,7 +119,7 @@ static uint8_t read_rom(GB_gameboy_t *gb, uint16_t addr)
|
|||
return gb->boot_rom[addr];
|
||||
}
|
||||
|
||||
if (addr >= 0x200 && addr < 0x900 && gb->is_cgb && !gb->boot_rom_finished) {
|
||||
if (addr >= 0x200 && addr < 0x900 && GB_is_cgb(gb) && !gb->boot_rom_finished) {
|
||||
return gb->boot_rom[addr];
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
}
|
||||
|
||||
if (gb->oam_read_blocked) {
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
if (addr < 0xFEA0) {
|
||||
if (gb->accessed_oam_row == 0) {
|
||||
gb->oam[(addr & 0xf8)] =
|
||||
|
@ -249,7 +249,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
if ((gb->io_registers[GB_IO_STAT] & 0x3) >= 2) { /* Seems to be disabled in Modes 2 and 3 */
|
||||
return 0xFF;
|
||||
}
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
return (addr & 0xF0) | ((addr >> 4) & 0xF);
|
||||
}
|
||||
}
|
||||
|
@ -275,11 +275,11 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
return gb->io_registers[GB_IO_DMG_EMULATION_INDICATION] | 0xFE;
|
||||
|
||||
case GB_IO_PCM_12:
|
||||
if (!gb->is_cgb) return 0xFF;
|
||||
if (!GB_is_cgb(gb)) return 0xFF;
|
||||
return (gb->apu.is_active[GB_SQUARE_2] ? (gb->apu.samples[GB_SQUARE_2] << 4) : 0) |
|
||||
(gb->apu.is_active[GB_SQUARE_1] ? (gb->apu.samples[GB_SQUARE_1]) : 0);
|
||||
case GB_IO_PCM_34:
|
||||
if (!gb->is_cgb) return 0xFF;
|
||||
if (!GB_is_cgb(gb)) return 0xFF;
|
||||
return (gb->apu.is_active[GB_NOISE] ? (gb->apu.samples[GB_NOISE] << 4) : 0) |
|
||||
(gb->apu.is_active[GB_WAVE] ? (gb->apu.samples[GB_WAVE]) : 0);
|
||||
case GB_IO_JOYP:
|
||||
|
@ -314,7 +314,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
}
|
||||
return gb->cgb_ram_bank | ~0x7;
|
||||
case GB_IO_VBK:
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
return 0xFF;
|
||||
}
|
||||
return gb->cgb_vram_bank | ~0x1;
|
||||
|
@ -322,7 +322,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
/* Todo: It seems that a CGB in DMG mode can access BGPI and OBPI, but not BGPD and OBPD? */
|
||||
case GB_IO_BGPI:
|
||||
case GB_IO_OBPI:
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
return 0xFF;
|
||||
}
|
||||
return gb->io_registers[addr & 0xFF] | 0x40;
|
||||
|
@ -357,11 +357,11 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
}
|
||||
case GB_IO_UNKNOWN2:
|
||||
case GB_IO_UNKNOWN3:
|
||||
return gb->is_cgb? gb->io_registers[addr & 0xFF] : 0xFF;
|
||||
return GB_is_cgb(gb)? gb->io_registers[addr & 0xFF] : 0xFF;
|
||||
case GB_IO_UNKNOWN4:
|
||||
return gb->cgb_mode? gb->io_registers[addr & 0xFF] : 0xFF;
|
||||
case GB_IO_UNKNOWN5:
|
||||
return gb->is_cgb? gb->io_registers[addr & 0xFF] | 0x8F : 0xFF;
|
||||
return GB_is_cgb(gb)? gb->io_registers[addr & 0xFF] | 0x8F : 0xFF;
|
||||
default:
|
||||
if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) {
|
||||
return GB_apu_read(gb, addr & 0xFF);
|
||||
|
@ -531,7 +531,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
return;
|
||||
}
|
||||
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
if (addr < 0xFEA0) {
|
||||
gb->oam[addr & 0xFF] = value;
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
/* TODO: Probably completely wrong in double speed mode */
|
||||
|
||||
/* TODO: This hack is disgusting */
|
||||
if (gb->display_state == 29 && gb->is_cgb) {
|
||||
if (gb->display_state == 29 && GB_is_cgb(gb)) {
|
||||
gb->ly_for_comparison = 153;
|
||||
GB_STAT_update(gb);
|
||||
gb->ly_for_comparison = 0;
|
||||
|
@ -609,14 +609,14 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
|
||||
/* These are the states when LY changes, let the display routine call GB_STAT_update for use
|
||||
so it correctly handles T-cycle accurate LYC writes */
|
||||
if (!gb->is_cgb || (
|
||||
if (!GB_is_cgb(gb) || (
|
||||
gb->display_state != 6 &&
|
||||
gb->display_state != 26 &&
|
||||
gb->display_state != 15 &&
|
||||
gb->display_state != 16)) {
|
||||
|
||||
/* More hacks to make LYC write conflicts work */
|
||||
if (gb->display_state == 14 && gb->is_cgb) {
|
||||
if (gb->display_state == 14 && GB_is_cgb(gb)) {
|
||||
gb->ly_for_comparison = 153;
|
||||
GB_STAT_update(gb);
|
||||
gb->ly_for_comparison = -1;
|
||||
|
@ -691,7 +691,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
return;
|
||||
|
||||
case GB_IO_DMG_EMULATION:
|
||||
if (gb->is_cgb && !gb->boot_rom_finished) {
|
||||
if (GB_is_cgb(gb) && !gb->boot_rom_finished) {
|
||||
gb->cgb_mode = value != 4; /* The real "contents" of this register aren't quite known yet. */
|
||||
}
|
||||
return;
|
||||
|
@ -728,7 +728,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
|
||||
case GB_IO_BGPI:
|
||||
case GB_IO_OBPI:
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
return;
|
||||
}
|
||||
gb->io_registers[addr & 0xFF] = value;
|
||||
|
@ -823,7 +823,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
return;
|
||||
|
||||
case GB_IO_RP: {
|
||||
if (!gb->is_cgb) {
|
||||
if (!GB_is_cgb(gb)) {
|
||||
return;
|
||||
}
|
||||
if ((value & 1) != (gb->io_registers[GB_IO_RP] & 1)) {
|
||||
|
|
|
@ -77,7 +77,7 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
assert(gb->pending_cycles);
|
||||
GB_conflict_t conflict = GB_CONFLICT_READ_OLD;
|
||||
if ((addr & 0xFF80) == 0xFF00) {
|
||||
conflict = (gb->is_cgb? cgb_conflict_map : dmg_conflict_map)[addr & 0x7F];
|
||||
conflict = (GB_is_cgb(gb)? cgb_conflict_map : dmg_conflict_map)[addr & 0x7F];
|
||||
}
|
||||
switch (conflict) {
|
||||
case GB_CONFLICT_READ_OLD:
|
||||
|
@ -158,7 +158,7 @@ static void cycle_no_access(GB_gameboy_t *gb)
|
|||
|
||||
static void cycle_oam_bug(GB_gameboy_t *gb, uint8_t register_id)
|
||||
{
|
||||
if (gb->is_cgb) {
|
||||
if (GB_is_cgb(gb)) {
|
||||
/* Slight optimization */
|
||||
gb->pending_cycles += 4;
|
||||
return;
|
||||
|
@ -1381,14 +1381,14 @@ void GB_cpu_run(GB_gameboy_t *gb)
|
|||
return;
|
||||
}
|
||||
|
||||
if (gb->halted && !gb->is_cgb && !gb->just_halted) {
|
||||
if (gb->halted && !GB_is_cgb(gb) && !gb->just_halted) {
|
||||
GB_advance_cycles(gb, 2);
|
||||
}
|
||||
|
||||
uint8_t interrupt_queue = gb->interrupt_enable & gb->io_registers[GB_IO_IF] & 0x1F;
|
||||
|
||||
if (gb->halted) {
|
||||
GB_advance_cycles(gb, (gb->is_cgb || gb->just_halted) ? 4 : 2);
|
||||
GB_advance_cycles(gb, (GB_is_cgb(gb) || gb->just_halted) ? 4 : 2);
|
||||
}
|
||||
gb->just_halted = false;
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ static uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
|
|||
int get_image_for_rom(const char *filename, const char *boot_path, uint32_t *output, uint8_t *cgb_flag)
|
||||
{
|
||||
GB_gameboy_t gb;
|
||||
GB_init_cgb(&gb);
|
||||
GB_init(&gb, GB_MODEL_CGB_E);
|
||||
if (GB_load_boot_rom(&gb, boot_path)) {
|
||||
GB_free(&gb);
|
||||
return 1;
|
||||
|
|
22
SDL/main.c
22
SDL/main.c
|
@ -26,13 +26,19 @@ static bool paused = false;
|
|||
static uint32_t pixel_buffer_1[160*144], pixel_buffer_2[160*144];
|
||||
static uint32_t *active_pixel_buffer = pixel_buffer_1, *previous_pixel_buffer = pixel_buffer_2;
|
||||
|
||||
|
||||
static char *filename = NULL;
|
||||
static bool should_free_filename = false;
|
||||
static char *battery_save_path_ptr;
|
||||
|
||||
SDL_AudioDeviceID device_id;
|
||||
|
||||
static const GB_model_t sdl_to_internal_model[] =
|
||||
{
|
||||
[MODEL_DMG] = GB_MODEL_DMG_B,
|
||||
[MODEL_CGB] = GB_MODEL_CGB_E,
|
||||
[MODEL_AGB] = GB_MODEL_AGB
|
||||
};
|
||||
|
||||
void set_filename(const char *new_filename, bool new_should_free)
|
||||
{
|
||||
if (filename && should_free_filename) {
|
||||
|
@ -364,15 +370,10 @@ static void run(void)
|
|||
pending_command = GB_SDL_NO_COMMAND;
|
||||
restart:
|
||||
if (GB_is_inited(&gb)) {
|
||||
GB_switch_model_and_reset(&gb, configuration.model != MODEL_DMG);
|
||||
GB_switch_model_and_reset(&gb, sdl_to_internal_model[configuration.model]);
|
||||
}
|
||||
else {
|
||||
if (configuration.model == MODEL_DMG) {
|
||||
GB_init(&gb);
|
||||
}
|
||||
else {
|
||||
GB_init_cgb(&gb);
|
||||
}
|
||||
GB_init(&gb, sdl_to_internal_model[configuration.model]);
|
||||
|
||||
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
|
||||
GB_set_pixels_output(&gb, active_pixel_buffer);
|
||||
|
@ -454,7 +455,7 @@ int main(int argc, char **argv)
|
|||
|
||||
signal(SIGINT, debugger_interrupt);
|
||||
|
||||
SDL_Init( SDL_INIT_EVERYTHING );
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
|
@ -527,6 +528,9 @@ int main(int argc, char **argv)
|
|||
fread(&configuration, 1, sizeof(configuration), prefs_file);
|
||||
fclose(prefs_file);
|
||||
}
|
||||
if (configuration.model >= MODEL_MAX) {
|
||||
configuration.model = MODEL_CGB;
|
||||
}
|
||||
|
||||
atexit(save_configuration);
|
||||
|
||||
|
|
|
@ -295,14 +295,14 @@ int main(int argc, char **argv)
|
|||
fprintf(stderr, "Testing ROM %s\n", filename);
|
||||
|
||||
if (dmg) {
|
||||
GB_init(&gb);
|
||||
GB_init(&gb, GB_MODEL_DMG_B);
|
||||
if (GB_load_boot_rom(&gb, boot_rom_path? boot_rom_path : executable_relative_path("dmg_boot.bin"))) {
|
||||
perror("Failed to load boot ROM");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GB_init_cgb(&gb);
|
||||
GB_init(&gb, GB_MODEL_CGB_E);
|
||||
if (GB_load_boot_rom(&gb, boot_rom_path? boot_rom_path : executable_relative_path("cgb_boot.bin"))) {
|
||||
perror("Failed to load boot ROM");
|
||||
exit(1);
|
||||
|
|
|
@ -52,6 +52,13 @@ enum model {
|
|||
MODEL_AUTO
|
||||
};
|
||||
|
||||
static const GB_model_t libretro_to_internal_model[] =
|
||||
{
|
||||
[MODEL_DMG] = GB_MODEL_DMG_B,
|
||||
[MODEL_CGB] = GB_MODEL_CGB_E,
|
||||
[MODEL_AGB] = GB_MODEL_AGB
|
||||
};
|
||||
|
||||
enum screen_layout {
|
||||
LAYOUT_TOP_DOWN,
|
||||
LAYOUT_LEFT_RIGHT
|
||||
|
@ -317,15 +324,11 @@ static void init_for_current_model(void)
|
|||
|
||||
for (i = 0; i < emulated_devices; i++)
|
||||
{
|
||||
if (GB_is_inited(&gameboy[i]))
|
||||
GB_switch_model_and_reset(&gameboy[i], effective_model[i] != MODEL_DMG);
|
||||
|
||||
else
|
||||
{
|
||||
if (effective_model[i] == MODEL_DMG)
|
||||
GB_init(&gameboy[i]);
|
||||
else
|
||||
GB_init_cgb(&gameboy[i]);
|
||||
if (GB_is_inited(&gameboy[i])) {
|
||||
GB_switch_model_and_reset(&gameboy[i], libretro_to_internal_model[effective_model[i]]);
|
||||
}
|
||||
else {
|
||||
GB_init(&gameboy[i], libretro_to_internal_model[effective_model[i]]);
|
||||
}
|
||||
const char *model_name = (const char *[]){"dmg", "cgb", "agb"}[effective_model[i]];
|
||||
const unsigned char *boot_code = (const unsigned char *[]){dmg_boot, cgb_boot, agb_boot}[effective_model[i]];
|
||||
|
|
Loading…
Reference in New Issue