Correct OAM interrupt behavior
This commit is contained in:
parent
da00e240e5
commit
b7555e9976
@ -242,23 +242,19 @@ void palette_changed(GB_gameboy_t *gb, bool background_palette, unsigned char in
|
|||||||
|
|
||||||
void display_run(GB_gameboy_t *gb)
|
void display_run(GB_gameboy_t *gb)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
Display controller bug: For some reason, the OAM STAT interrupt is called, as expected, for LY = 0..143.
|
||||||
|
However, it is also called from LY = 144.
|
||||||
|
|
||||||
<del>Display controller bug: For some reason, the OAM STAT interrupt is called, as expected, for LY = 0..143.
|
See http://forums.nesdev.com/viewtopic.php?f=20&t=13727
|
||||||
However, it is also called from LY = 151! (The last LY is 153! Wonder why is it 151...).</del>
|
|
||||||
|
|
||||||
Todo: This discussion in NESDev proves this theory incorrect:
|
|
||||||
http://forums.nesdev.com/viewtopic.php?f=20&t=13727
|
|
||||||
Seems like there was a bug in one of my test ROMs.
|
|
||||||
This behavior needs to be corrected.
|
|
||||||
*/
|
*/
|
||||||
unsigned char last_mode = gb->io_registers[GB_IO_STAT] & 3;
|
unsigned char last_mode = gb->io_registers[GB_IO_STAT] & 3;
|
||||||
|
|
||||||
if (gb->display_cycles >= LCDC_PERIOD) {
|
if (gb->display_cycles >= LCDC_PERIOD) {
|
||||||
/* VBlank! */
|
/* VBlank! */
|
||||||
gb->display_cycles -= LCDC_PERIOD;
|
gb->display_cycles -= LCDC_PERIOD;
|
||||||
gb->ly151_bug_oam = false;
|
gb->ly144_bug_oam = false;
|
||||||
gb->ly151_bug_hblank = false;
|
gb->ly144_bug_hblank = false;
|
||||||
display_vblank(gb);
|
display_vblank(gb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,22 +306,25 @@ void display_run(GB_gameboy_t *gb)
|
|||||||
gb->io_registers[GB_IO_IF] |= 1;
|
gb->io_registers[GB_IO_IF] |= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LY = 151 interrupt bug
|
// LY = 144 interrupt bug
|
||||||
if (gb->io_registers[GB_IO_LY] == 151) {
|
if (gb->io_registers[GB_IO_LY] == 144) {
|
||||||
if (gb->display_cycles % 456 < 80) { // Mode 2
|
if (gb->display_cycles % 456 < 80) { // Mode 2
|
||||||
if (gb->io_registers[GB_IO_STAT] & 0x20 && !gb->ly151_bug_oam) { /* User requests an interrupt on Mode 2 */
|
if (gb->io_registers[GB_IO_STAT] & 0x20 && !gb->ly144_bug_oam) { /* User requests an interrupt on Mode 2 */
|
||||||
gb->io_registers[GB_IO_IF] |= 2;
|
gb->io_registers[GB_IO_IF] |= 2;
|
||||||
}
|
}
|
||||||
gb->ly151_bug_oam = true;
|
gb->ly144_bug_oam = true;
|
||||||
}
|
}
|
||||||
if (gb->display_cycles % 456 < 80 + 172) { /* Mode 3 */
|
if (gb->display_cycles % 456 < 80 + 172) { /* Mode 3 */
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
}
|
}
|
||||||
else { /* Mode 0 */
|
else { /* Mode 0 */
|
||||||
if (gb->io_registers[GB_IO_STAT] & 8 && !gb->ly151_bug_hblank) { /* User requests an interrupt on Mode 0 */
|
if (gb->io_registers[GB_IO_STAT] & 8 && !gb->ly144_bug_hblank) { /* User requests an interrupt on Mode 0 */
|
||||||
|
/*
|
||||||
|
Todo: Verify if this actually happens.
|
||||||
gb->io_registers[GB_IO_IF] |= 2;
|
gb->io_registers[GB_IO_IF] |= 2;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
gb->ly151_bug_hblank = true;
|
gb->ly144_bug_hblank = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,8 +216,8 @@ typedef struct GB_gameboy_s{
|
|||||||
unsigned char sprite_palletes_data[0x40];
|
unsigned char sprite_palletes_data[0x40];
|
||||||
uint32_t background_palletes_rgb[0x20];
|
uint32_t background_palletes_rgb[0x20];
|
||||||
uint32_t sprite_palletes_rgb[0x20];
|
uint32_t sprite_palletes_rgb[0x20];
|
||||||
bool ly151_bug_oam;
|
bool ly144_bug_oam;
|
||||||
bool ly151_bug_hblank;
|
bool ly144_bug_hblank;
|
||||||
signed short previous_lcdc_x;
|
signed short previous_lcdc_x;
|
||||||
signed short line_x_bias;
|
signed short line_x_bias;
|
||||||
bool effective_window_enabled;
|
bool effective_window_enabled;
|
||||||
|
Loading…
Reference in New Issue
Block a user