Improve PPU timings in CGB revision 0 to C. These revisions are no longer marked as experimental.

This commit is contained in:
Lior Halphon
2024-07-08 00:00:27 +03:00
parent a4525c3336
commit c3e3fb91cc
6 changed files with 75 additions and 99 deletions

View File

@@ -455,10 +455,10 @@
<font key="font" metaFont="menu"/> <font key="font" metaFont="menu"/>
<menu key="menu" autoenablesItems="NO" id="bbF-hB-Hv7"> <menu key="menu" autoenablesItems="NO" id="bbF-hB-Hv7">
<items> <items>
<menuItem title="CPU CGB 0 (Experimental)" tag="512" id="2Uk-u3-6Gw"/> <menuItem title="CPU CGB 0" tag="512" id="2Uk-u3-6Gw"/>
<menuItem title="CPU CGB A (Experimental)" tag="513" id="axv-yk-RWM"/> <menuItem title="CPU CGB A" tag="513" id="axv-yk-RWM"/>
<menuItem title="CPU CGB B (Experimental)" tag="514" id="NtJ-oo-IM2"/> <menuItem title="CPU CGB B" tag="514" id="NtJ-oo-IM2"/>
<menuItem title="CPU CGB C (Experimental)" tag="515" id="9YL-u8-12z"/> <menuItem title="CPU CGB C" tag="515" id="9YL-u8-12z"/>
<menuItem title="CPU CGB D" tag="516" id="c76-oF-fkU"/> <menuItem title="CPU CGB D" tag="516" id="c76-oF-fkU"/>
<menuItem title="CPU CGB E" state="on" tag="517" id="3lF-1Q-2SS"/> <menuItem title="CPU CGB E" state="on" tag="517" id="3lF-1Q-2SS"/>
</items> </items>

View File

@@ -429,7 +429,6 @@ void GB_STAT_update(GB_gameboy_t *gb)
bool previous_interrupt_line = gb->stat_interrupt_line; bool previous_interrupt_line = gb->stat_interrupt_line;
/* Set LY=LYC bit */ /* Set LY=LYC bit */
/* TODO: This behavior might not be correct for CGB revisions other than C and E */
if (gb->ly_for_comparison != (uint16_t)-1 || gb->model <= GB_MODEL_CGB_C) { if (gb->ly_for_comparison != (uint16_t)-1 || gb->model <= GB_MODEL_CGB_C) {
if (gb->ly_for_comparison == gb->io_registers[GB_IO_LYC]) { if (gb->ly_for_comparison == gb->io_registers[GB_IO_LYC]) {
gb->lyc_interrupt_line = true; gb->lyc_interrupt_line = true;
@@ -734,11 +733,6 @@ static inline void dma_sync(GB_gameboy_t *gb, unsigned *cycles)
} }
} }
/* All verified CGB timings are based on CGB CPU E. CGB CPUs >= D are known to have
slightly different timings than CPUs <= C.
Todo: Add support to CPU C and older */
static inline uint8_t fetcher_y(GB_gameboy_t *gb) static inline uint8_t fetcher_y(GB_gameboy_t *gb)
{ {
return gb->wx_triggered? gb->window_y : gb->current_line + gb->io_registers[GB_IO_SCY]; return gb->wx_triggered? gb->window_y : gb->current_line + gb->io_registers[GB_IO_SCY];
@@ -1464,7 +1458,6 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force)
GB_STATE(gb, display, 27); GB_STATE(gb, display, 27);
GB_STATE(gb, display, 28); GB_STATE(gb, display, 28);
GB_STATE(gb, display, 29); GB_STATE(gb, display, 29);
GB_STATE(gb, display, 30);
GB_STATE(gb, display, 31); GB_STATE(gb, display, 31);
GB_STATE(gb, display, 32); GB_STATE(gb, display, 32);
GB_STATE(gb, display, 33); GB_STATE(gb, display, 33);
@@ -1538,8 +1531,8 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force)
GB_SLEEP(gb, display, 37, 2); GB_SLEEP(gb, display, 37, 2);
gb->cgb_palettes_blocked = true; gb->cgb_palettes_blocked = true;
gb->cycles_for_line += (GB_is_cgb(gb) && gb->model <= GB_MODEL_CGB_C)? 2 : 3; gb->cycles_for_line += 3;
GB_SLEEP(gb, display, 38, (GB_is_cgb(gb) && gb->model <= GB_MODEL_CGB_C)? 2 : 3); GB_SLEEP(gb, display, 38, 3);
gb->vram_read_blocked = true; gb->vram_read_blocked = true;
gb->vram_write_blocked = true; gb->vram_write_blocked = true;
@@ -1665,12 +1658,8 @@ void GB_display_run(GB_gameboy_t *gb, unsigned cycles, bool force)
GB_STAT_update(gb); GB_STAT_update(gb);
uint8_t idle_cycles = 3; gb->cycles_for_line += 3;
if (GB_is_cgb(gb) && gb->model <= GB_MODEL_CGB_C) { GB_SLEEP(gb, display, 10, 3);
idle_cycles = 2;
}
gb->cycles_for_line += idle_cycles;
GB_SLEEP(gb, display, 10, idle_cycles);
gb->cgb_palettes_blocked = true; gb->cgb_palettes_blocked = true;
gb->cycles_for_line += 2; gb->cycles_for_line += 2;
@@ -1902,11 +1891,6 @@ skip_slow_mode_3:
} }
gb->wx_triggered = false; gb->wx_triggered = false;
if (GB_is_cgb(gb) && gb->model <= GB_MODEL_CGB_C) {
gb->cycles_for_line++;
GB_SLEEP(gb, display, 30, 1);
}
if (!gb->cgb_double_speed) { if (!gb->cgb_double_speed) {
gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] &= ~3;
gb->mode_for_interrupt = 0; gb->mode_for_interrupt = 0;

View File

@@ -205,9 +205,16 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
} }
case GB_CONFLICT_PALETTE_CGB: { case GB_CONFLICT_PALETTE_CGB: {
if (gb->model >= GB_MODEL_CGB_D) {
GB_advance_cycles(gb, gb->pending_cycles - 2); GB_advance_cycles(gb, gb->pending_cycles - 2);
GB_write_memory(gb, addr, value); GB_write_memory(gb, addr, value);
gb->pending_cycles = 6; gb->pending_cycles = 6;
}
else {
GB_advance_cycles(gb, gb->pending_cycles - 1);
GB_write_memory(gb, addr, value);
gb->pending_cycles = 5;
}
break; break;
} }
@@ -263,8 +270,6 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
case GB_CONFLICT_LCDC_CGB: { case GB_CONFLICT_LCDC_CGB: {
uint8_t old = gb->io_registers[GB_IO_LCDC]; uint8_t old = gb->io_registers[GB_IO_LCDC];
if ((~value & old) & GB_LCDC_TILE_SEL) { if ((~value & old) & GB_LCDC_TILE_SEL) {
// TODO: This is different is because my timing is off in CGB ≤ C
if (gb->model > GB_MODEL_CGB_C) {
GB_advance_cycles(gb, gb->pending_cycles); GB_advance_cycles(gb, gb->pending_cycles);
GB_write_memory(gb, addr, value ^ GB_LCDC_TILE_SEL); // Write with the old TILE_SET first GB_write_memory(gb, addr, value ^ GB_LCDC_TILE_SEL); // Write with the old TILE_SET first
gb->tile_sel_glitch = true; gb->tile_sel_glitch = true;
@@ -273,16 +278,6 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
GB_write_memory(gb, addr, value); GB_write_memory(gb, addr, value);
gb->pending_cycles = 3; gb->pending_cycles = 3;
} }
else {
GB_advance_cycles(gb, gb->pending_cycles - 1);
GB_write_memory(gb, addr, value ^ GB_LCDC_TILE_SEL); // Write with the old TILE_SET first
gb->tile_sel_glitch = true;
GB_advance_cycles(gb, 1);
gb->tile_sel_glitch = false;
GB_write_memory(gb, addr, value);
gb->pending_cycles = 4;
}
}
else { else {
GB_advance_cycles(gb, gb->pending_cycles); GB_advance_cycles(gb, gb->pending_cycles);
GB_write_memory(gb, addr, value); GB_write_memory(gb, addr, value);
@@ -292,10 +287,7 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
} }
case GB_CONFLICT_LCDC_CGB_DOUBLE: { case GB_CONFLICT_LCDC_CGB_DOUBLE: {
uint8_t old = gb->io_registers[GB_IO_LCDC]; uint8_t old = gb->io_registers[GB_IO_LCDC];
// TODO: This is wrong for CGB ≤ C for TILE_SEL, BG_EN and BG_MAP. // TODO: Verify for CGB ≤ C for BG_EN and OBJ_EN.
// PPU timings for these models appear to be wrong and it'd make more sense to fix those first than hacking
// around them.
// TODO: This condition is different from single speed mode. Why? What about odd modes? // TODO: This condition is different from single speed mode. Why? What about odd modes?
if ((value ^ old) & GB_LCDC_TILE_SEL) { if ((value ^ old) & GB_LCDC_TILE_SEL) {
GB_advance_cycles(gb, gb->pending_cycles - 2); GB_advance_cycles(gb, gb->pending_cycles - 2);

View File

@@ -982,10 +982,10 @@ static void cycle_cgb_revision_backwards(unsigned index)
static const char *current_cgb_revision_string(unsigned index) static const char *current_cgb_revision_string(unsigned index)
{ {
return GB_inline_const(const char *[], { return GB_inline_const(const char *[], {
"CPU CGB 0 (Exp.)", "CPU CGB 0",
"CPU CGB A (Exp.)", "CPU CGB A",
"CPU CGB B (Exp.)", "CPU CGB B",
"CPU CGB C (Exp.)", "CPU CGB C",
"CPU CGB D", "CPU CGB D",
"CPU CGB E", "CPU CGB E",
}) })

View File

@@ -203,10 +203,10 @@ static NSString const *typeLightTemp = @"typeLightTemp";
@{@"type": typeRadio, @"pref": @"GBSGBModel", @"title": @"Super Game Boy 2", @"value": @(GB_MODEL_SGB2),}, @{@"type": typeRadio, @"pref": @"GBSGBModel", @"title": @"Super Game Boy 2", @"value": @(GB_MODEL_SGB2),},
]), ]),
QUICK_SUBMENU(@"Game Boy Color", @[ QUICK_SUBMENU(@"Game Boy Color", @[
@{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB 0 (Experimental)", @"value": @(GB_MODEL_CGB_0),}, @{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB 0", @"value": @(GB_MODEL_CGB_0),},
@{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB A (Experimental)", @"value": @(GB_MODEL_CGB_A),}, @{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB A", @"value": @(GB_MODEL_CGB_A),},
@{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB B (Experimental)", @"value": @(GB_MODEL_CGB_B),}, @{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB B", @"value": @(GB_MODEL_CGB_B),},
@{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB C (Experimental)", @"value": @(GB_MODEL_CGB_C),}, @{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB C", @"value": @(GB_MODEL_CGB_C),},
@{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB D", @"value": @(GB_MODEL_CGB_D),}, @{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB D", @"value": @(GB_MODEL_CGB_D),},
@{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB E", @"value": @(GB_MODEL_CGB_E),}, @{@"type": typeRadio, @"pref": @"GBCGBModel", @"title": @"CPU CGB E", @"value": @(GB_MODEL_CGB_E),},
]), ]),

View File

@@ -85,10 +85,10 @@ struct retro_core_option_v2_definition option_defs_us[] = {
{ "Auto (SGB)", "Auto Detect DMG/SGB/CGB" }, { "Auto (SGB)", "Auto Detect DMG/SGB/CGB" },
{ "Game Boy", "Game Boy (DMG-CPU B)" }, { "Game Boy", "Game Boy (DMG-CPU B)" },
{ "Game Boy Pocket", "Game Boy Pocket/Light" }, { "Game Boy Pocket", "Game Boy Pocket/Light" },
{ "Game Boy Color 0", "Game Boy Color (CPU CGB 0) (Experimental)" }, { "Game Boy Color 0", "Game Boy Color (CPU CGB 0)" },
{ "Game Boy Color A", "Game Boy Color (CPU CGB A) (Experimental)" }, { "Game Boy Color A", "Game Boy Color (CPU CGB A)" },
{ "Game Boy Color B", "Game Boy Color (CPU CGB B) (Experimental)" }, { "Game Boy Color B", "Game Boy Color (CPU CGB B)" },
{ "Game Boy Color C", "Game Boy Color (CPU CGB C) (Experimental)" }, { "Game Boy Color C", "Game Boy Color (CPU CGB C)" },
{ "Game Boy Color D", "Game Boy Color (CPU CGB D)" }, { "Game Boy Color D", "Game Boy Color (CPU CGB D)" },
{ "Game Boy Color", "Game Boy Color (CPU CGB E)" }, { "Game Boy Color", "Game Boy Color (CPU CGB E)" },
{ "Game Boy Advance", "Game Boy Advance (CPU AGB A)" }, { "Game Boy Advance", "Game Boy Advance (CPU AGB A)" },
@@ -332,10 +332,10 @@ struct retro_core_option_v2_definition option_defs_us[] = {
{ "Auto (SGB)", "Auto Detect DMG/SGB/CGB" }, { "Auto (SGB)", "Auto Detect DMG/SGB/CGB" },
{ "Game Boy", "Game Boy (DMG-CPU B)" }, { "Game Boy", "Game Boy (DMG-CPU B)" },
{ "Game Boy Pocket", "Game Boy Pocket/Light" }, { "Game Boy Pocket", "Game Boy Pocket/Light" },
{ "Game Boy Color 0", "Game Boy Color (CPU CGB 0) (Experimental)" }, { "Game Boy Color 0", "Game Boy Color (CPU CGB 0)" },
{ "Game Boy Color A", "Game Boy Color (CPU CGB A) (Experimental)" }, { "Game Boy Color A", "Game Boy Color (CPU CGB A)" },
{ "Game Boy Color B", "Game Boy Color (CPU CGB B) (Experimental)" }, { "Game Boy Color B", "Game Boy Color (CPU CGB B)" },
{ "Game Boy Color C", "Game Boy Color (CPU CGB C) (Experimental)" }, { "Game Boy Color C", "Game Boy Color (CPU CGB C)" },
{ "Game Boy Color D", "Game Boy Color (CPU CGB D)" }, { "Game Boy Color D", "Game Boy Color (CPU CGB D)" },
{ "Game Boy Color", "Game Boy Color (CPU CGB E)" }, { "Game Boy Color", "Game Boy Color (CPU CGB E)" },
{ "Game Boy Advance", "Game Boy Advance (CPU AGB A)" }, { "Game Boy Advance", "Game Boy Advance (CPU AGB A)" },
@@ -374,10 +374,10 @@ struct retro_core_option_v2_definition option_defs_us[] = {
{ "Auto (SGB)", "Auto Detect DMG/SGB/CGB" }, { "Auto (SGB)", "Auto Detect DMG/SGB/CGB" },
{ "Game Boy", "Game Boy (DMG-CPU B)" }, { "Game Boy", "Game Boy (DMG-CPU B)" },
{ "Game Boy Pocket", "Game Boy Pocket/Light" }, { "Game Boy Pocket", "Game Boy Pocket/Light" },
{ "Game Boy Color 0", "Game Boy Color (CPU CGB 0) (Experimental)" }, { "Game Boy Color 0", "Game Boy Color (CPU CGB 0)" },
{ "Game Boy Color A", "Game Boy Color (CPU CGB A) (Experimental)" }, { "Game Boy Color A", "Game Boy Color (CPU CGB A)" },
{ "Game Boy Color B", "Game Boy Color (CPU CGB B) (Experimental)" }, { "Game Boy Color B", "Game Boy Color (CPU CGB B)" },
{ "Game Boy Color C", "Game Boy Color (CPU CGB C) (Experimental)" }, { "Game Boy Color C", "Game Boy Color (CPU CGB C)" },
{ "Game Boy Color D", "Game Boy Color (CPU CGB D)" }, { "Game Boy Color D", "Game Boy Color (CPU CGB D)" },
{ "Game Boy Color", "Game Boy Color (CPU CGB E)" }, { "Game Boy Color", "Game Boy Color (CPU CGB E)" },
{ "Game Boy Advance", "Game Boy Advance (CPU AGB A)" }, { "Game Boy Advance", "Game Boy Advance (CPU AGB A)" },