Skip to content

Commit

Permalink
[GB] Fix LYC-STAT IRQ timing & VBlank scanline handling
Browse files Browse the repository at this point in the history
  • Loading branch information
shonumi committed Aug 27, 2015
1 parent 29186c8 commit c878372
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions src/dmg/lcd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1185,15 +1185,27 @@ void DMG_LCD::step(int cpu_clock)
lcd_stat.vblank_clock -= 456;
lcd_stat.current_scanline++;

mem->memory_map[REG_LY] = lcd_stat.current_scanline;
scanline_compare();
//By line 153, LCD has actually reached the top of the screen again
//It will sit at Line 0 for 456 before entering Mode 2 properly
//Line 0 STAT-LYC IRQs should be triggered here
if(lcd_stat.current_scanline == 153)
{
lcd_stat.current_scanline = 0;
mem->memory_map[REG_LY] = lcd_stat.current_scanline;
scanline_compare();
}

//After 10 lines, VBlank is done, returns to top screen in Mode 2
if(lcd_stat.current_scanline == 154)
//After sitting on Line 0 for 456 cycles, reset LCD clock, scanline count
else if(lcd_stat.current_scanline == 1)
{
lcd_stat.lcd_clock -= 70224;
lcd_stat.current_scanline = 0;
mem->memory_map[REG_LY] = lcd_stat.current_scanline;
}

//Process Lines 144-152 normally
else
{
mem->memory_map[REG_LY] = lcd_stat.current_scanline;
scanline_compare();
}
Expand Down

1 comment on commit c878372

@shonumi
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a pretty decent fix. LYC-STAT IRQs for Line 0 are actually triggered during VBlank. It seems that Line 153 is technically Line 0. At that time the LCD has reached the top scanline, but it waits 456 cycles (the time it takes to process an entire scanline) before exiting VBlank.

So, that is to say, the timings were off. LYC-STAT IRQs for Line 0 get a sort of head-start before the LCD enters Mode 2 (OAM processing) and before VRAM becomes inaccessible. Several commercial games demonstrate this behavior such as Tomb Raider and Aladdin on the GBC, and Kirby's Dreamland 2 on the DMG (1st scanline of Rick's head didn't work because of this). Others probably rely on this behavior.

Once again, these kind of things are explained absolutely nowhere (maybe in the source code of other emus? certainly not in more formal documentation).

Please sign in to comment.