GBCHawk: adjust PPU

This commit is contained in:
alyosha-tas 2018-05-04 15:45:18 -04:00
parent e29b741bd4
commit b3647c6e05
3 changed files with 86 additions and 81 deletions

View File

@ -57,8 +57,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902
public const ushort RD_F = 42; // special read case to pop value into F public const ushort RD_F = 42; // special read case to pop value into F
public const ushort EI_RETI = 43; // reti has no delay in interrupt enable public const ushort EI_RETI = 43; // reti has no delay in interrupt enable
public const ushort INT_GET = 44; public const ushort INT_GET = 44;
public const ushort GBC_INTERRUPT = 45; public const ushort HALT_CHK = 45; // when in halt mode, actually check I Flag here
public const ushort HALT_CHK = 46; // when in halt mode, actually check I Flag here
public LR35902() public LR35902()
{ {
@ -294,13 +293,6 @@ namespace BizHawk.Emulation.Common.Components.LR35902
if (is_GBC) if (is_GBC)
{ {
// call the interrupt processor after 4 extra cycles // call the interrupt processor after 4 extra cycles
/*
cur_instr = new ushort[]
{IDLE,
IDLE,
IDLE,
GBC_INTERRUPT };
*/
if (!Halt_bug_3) if (!Halt_bug_3)
{ {
INTERRUPT_GBC_NOP(); INTERRUPT_GBC_NOP();
@ -309,6 +301,7 @@ namespace BizHawk.Emulation.Common.Components.LR35902
{ {
INTERRUPT_(); INTERRUPT_();
Halt_bug_3 = false; Halt_bug_3 = false;
Console.WriteLine("Hit this");
} }
} }
else else
@ -502,11 +495,6 @@ namespace BizHawk.Emulation.Common.Components.LR35902
Regs[cur_instr[instr_pntr++]] = INT_vectors[int_src]; Regs[cur_instr[instr_pntr++]] = INT_vectors[int_src];
break; break;
case GBC_INTERRUPT:
// only used when exiting HALT from GBC, an extra NOP is added to avoid HALT bug
INTERRUPT_();
instr_pntr = 0;
break;
case HALT_CHK: case HALT_CHK:
I_use = FlagI; I_use = FlagI;
if (Halt_bug_2 && I_use) if (Halt_bug_2 && I_use)

View File

@ -134,7 +134,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
break; break;
case 0xFF45: // LYC case 0xFF45: // LYC
LYC = value; LYC = value;
if (LY != LYC) { STAT &= 0xFB; } if (LCDC.Bit(7))
{
if (LY != LYC) { STAT &= 0xFB; }
else { STAT |= 0x4; }
}
break; break;
case 0xFF46: // DMA case 0xFF46: // DMA
DMA_addr = value; DMA_addr = value;
@ -346,24 +350,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
cycle = 0; cycle = 0;
LY += LY_inc; LY_actual = LY;
no_scan = false;
// here is where LY = LYC gets cleared (but only if LY isnt 0 as that's a special case no_scan = false;
if (LY_inc == 1)
{
LYC_INT = false;
STAT &= 0xFB;
}
if (LY == 0 && LY_inc == 0) if (LY == 0 && LY_inc == 0)
{ {
LY_inc = 1; LY_inc = 1;
Core.in_vblank = false; Core.in_vblank = false;
VBL_INT = false;
if (STAT.Bit(3)) { HBL_INT = true; }
STAT &= 0xFC;
// special note here, the y coordiate of the window is kept if the window is deactivated // special note here, the y coordiate of the window is kept if the window is deactivated
// meaning it will pick up where it left off if re-enabled later // meaning it will pick up where it left off if re-enabled later
@ -387,6 +381,34 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
} }
if (cycle == 452)
{
LY += LY_inc;
// here is where LY = LYC gets cleared (but only if LY isnt 0 as that's a special case)
if (LY_inc == 1)
{
LYC_INT = false;
STAT &= 0xFB;
}
else
{
VBL_INT = false;
if (STAT.Bit(3)) { HBL_INT = true; }
STAT &= 0xFC;
}
Core.cpu.LY = LY;
}
if ((LY == 153) && (cycle == 0))
{
LY = 0;
LY_inc = 0;
}
// exit vblank if LCD went from off to on // exit vblank if LCD went from off to on
if (LCD_was_off) if (LCD_was_off)
{ {
@ -406,21 +428,21 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
// the VBL stat is continuously asserted // the VBL stat is continuously asserted
if ((LY >= 144)) if ((LY_actual >= 144))
{ {
if (STAT.Bit(4)) if (STAT.Bit(4))
{ {
if ((cycle >= 4) && (LY == 144)) if ((cycle >= 0) && (LY_actual == 144))
{ {
VBL_INT = true; VBL_INT = true;
} }
else if (LY > 144) else if (LY_actual > 144)
{ {
VBL_INT = true; VBL_INT = true;
} }
} }
if ((cycle == 0) && (LY == 144)) { if ((cycle == 0) && (LY_actual == 144)) {
HBL_INT = false; HBL_INT = false;
@ -432,16 +454,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
Core.REG_FF0F |= 0x01; Core.REG_FF0F |= 0x01;
} }
if ((LY >= 144) && (cycle == 4)) if ((LY_actual >= 144) && (cycle == 0))
{ {
// a special case of OAM mode 2 IRQ assertion, even though PPU Mode still is 1 // a special case of OAM mode 2 IRQ assertion, even though PPU Mode still is 1
if (STAT.Bit(5)) { OAM_INT = true; } if (STAT.Bit(5)) { OAM_INT = true; }
} }
if ((LY == 153) && (cycle == 8)) if ((LY_actual == 153) && (cycle == 4))
{ {
LY = 0; LY_actual = 0;
LY_inc = 0;
Core.cpu.LY = LY; Core.cpu.LY = LY;
} }
} }
@ -454,12 +475,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// there is no mode 2 (presumably it missed the trigger) // there is no mode 2 (presumably it missed the trigger)
// mode 3 is very short, probably in some self test mode before turning on? // mode 3 is very short, probably in some self test mode before turning on?
if (cycle == 8) if (cycle == 4)
{ {
LYC_INT = false; if (LY != LYC)
STAT &= 0xFB; {
LYC_INT = false;
STAT &= 0xFB;
}
if (LY == LYC) if ((LY == LYC) && !STAT.Bit(2))
{ {
// set STAT coincidence FLAG and interrupt flag if it is enabled // set STAT coincidence FLAG and interrupt flag if it is enabled
STAT |= 0x04; STAT |= 0x04;
@ -467,7 +491,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
} }
if (cycle == 84) if (cycle == 80)
{ {
STAT &= 0xFC; STAT &= 0xFC;
@ -480,7 +504,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
VRAM_access_write = false; VRAM_access_write = false;
} }
if (cycle == 256) if (cycle == 252)
{ {
STAT &= 0xFC; STAT &= 0xFC;
OAM_INT = false; OAM_INT = false;
@ -495,9 +519,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
else else
{ {
if (cycle < 80) if (cycle < 76)
{ {
if (cycle == 4) if (cycle == 0)
{ {
// apparently, writes can make it to OAM one cycle longer then reads // apparently, writes can make it to OAM one cycle longer then reads
OAM_access_write = false; OAM_access_write = false;
@ -511,12 +535,18 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
// here OAM scanning is performed // here OAM scanning is performed
OAM_scan(cycle); OAM_scan(cycle + 4);
} }
else if (cycle >= 80 && LY < 144) else if (cycle >= 76 && LY_actual < 144)
{ {
if (cycle == 76)
{
OAM_access_read = false;
OAM_access_write = true;
VRAM_access_read = false;
}
if (cycle == 84) if (cycle == 80)
{ {
STAT &= 0xFC; STAT &= 0xFC;
STAT |= 0x03; STAT |= 0x03;
@ -526,20 +556,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
// render the screen and handle hblank // render the screen and handle hblank
render(cycle - 80); render(cycle - 76);
} }
} }
if (cycle >= 452)
{
OAM_access_read = false;
OAM_scan(cycle - 452);
}
} }
if ((LY_inc == 0)) if ((LY_inc == 0))
{ {
if (cycle == 12) if (cycle == 8)
{ {
LYC_INT = false; LYC_INT = false;
STAT &= 0xFB; STAT &= 0xFB;
// Special case of LY = LYC // Special case of LY = LYC
if (LY == LYC) if ((LY == LYC) && !STAT.Bit(2))
{ {
// set STAT coincidence FLAG and interrupt flag if it is enabled // set STAT coincidence FLAG and interrupt flag if it is enabled
STAT |= 0x04; STAT |= 0x04;
@ -550,13 +586,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (STAT.Bit(5)) { OAM_INT = true; } if (STAT.Bit(5)) { OAM_INT = true; }
} }
if (cycle == 92) { OAM_INT = false; } if (cycle == 88) { OAM_INT = false; }
} }
// here LY=LYC will be asserted // here LY=LYC will be asserted
if ((cycle == 4) && (LY != 0)) if ((cycle == 0) && (LY_actual != 0))
{ {
if (LY == LYC) if ((LY == LYC) && !STAT.Bit(2))
{ {
// set STAT coincidence FLAG and interrupt flag if it is enabled // set STAT coincidence FLAG and interrupt flag if it is enabled
STAT |= 0x04; STAT |= 0x04;
@ -568,7 +604,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
} }
else else
{ {
STAT &= 0xF8; STAT &= 0xFC;
VBL_INT = LYC_INT = HBL_INT = OAM_INT = false; VBL_INT = LYC_INT = HBL_INT = OAM_INT = false;
@ -577,6 +613,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
LCD_was_off = true; LCD_was_off = true;
LY = 0; LY = 0;
LY_actual = 0;
Core.cpu.LY = LY; Core.cpu.LY = LY;
cycle = 0; cycle = 0;
@ -610,10 +647,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// i.e. just keeping track of the lowest x-value sprite // i.e. just keeping track of the lowest x-value sprite
if (render_cycle == 0) if (render_cycle == 0)
{ {
OAM_access_read = false;
OAM_access_write = true;
VRAM_access_read = false;
// window X is latched for the scanline, mid-line changes have no effect // window X is latched for the scanline, mid-line changes have no effect
window_x_latch = window_x; window_x_latch = window_x;
@ -628,6 +661,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
fetch_sprite_01 = false; fetch_sprite_01 = false;
fetch_sprite_4 = false; fetch_sprite_4 = false;
going_to_fetch = false; going_to_fetch = false;
first_fetch = true;
no_sprites = false; no_sprites = false;
evaled_sprites = 0; evaled_sprites = 0;
@ -811,7 +845,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (pixel_counter == 160) if (pixel_counter == 160)
{ {
read_case = 8; read_case = 8;
hbl_countdown = 7; hbl_countdown = 5;
} }
} }
else if ((render_counter >= render_offset) && (pixel_counter < 0)) else if ((render_counter >= render_offset) && (pixel_counter < 0))
@ -1136,7 +1170,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (going_to_fetch) if (going_to_fetch)
{ {
going_to_fetch = false; going_to_fetch = false;
sprite_fetch_counter = 0; sprite_fetch_counter = first_fetch ? 2 : 0;
first_fetch = false;
if (fetch_sprite_01) if (fetch_sprite_01)
{ {
@ -1375,8 +1410,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// TODO: maybe stat mode 2 flags are set at cycle 0 on visible scanlines? // TODO: maybe stat mode 2 flags are set at cycle 0 on visible scanlines?
if (OAM_cycle == 0) if (OAM_cycle == 0)
{ {
OAM_access_read = false;
OAM_scan_index = 0; OAM_scan_index = 0;
SL_sprites_index = 0; SL_sprites_index = 0;
write_sprite = 0; write_sprite = 0;

View File

@ -78,7 +78,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (LCDC.Bit(7)) if (LCDC.Bit(7))
{ {
if (LY != LYC) { STAT &= 0xFB; } if (LY != LYC) { STAT &= 0xFB; }
else { STAT |= 0x4; /*if (STAT.Bit(6)) { LYC_INT = true; } */} else { STAT |= 0x4; }
} }
break; break;
case 0xFF46: // DMA case 0xFF46: // DMA
@ -302,15 +302,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// here mode 2 will be set to true and interrupts fired if enabled // here mode 2 will be set to true and interrupts fired if enabled
STAT &= 0xFC; STAT &= 0xFC;
STAT |= 0x2; STAT |= 0x2;
if (STAT.Bit(5)) if (STAT.Bit(5)) { OAM_INT = true; }
{
OAM_INT = true;
}
HBL_INT = false; HBL_INT = false;
} }
// here OAM scanning is performed // here OAM scanning is performed
OAM_scan(cycle + 4); OAM_scan(cycle + 4);
} }
@ -398,19 +394,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// assert the STAT IRQ line if the line went from zero to 1 // assert the STAT IRQ line if the line went from zero to 1
stat_line = VBL_INT | LYC_INT | HBL_INT | OAM_INT; stat_line = VBL_INT | LYC_INT | HBL_INT | OAM_INT;
/*
if (stat_line) {
Console.Write("OAM: ");
Console.Write(OAM_INT);
Console.Write(" LYC: ");
Console.Write(LYC_INT);
Console.Write(" VBL: ");
Console.Write(VBL_INT);
Console.Write(" HBL: ");
Console.Write(HBL_INT);
Console.WriteLine(Core.cpu.TotalExecutedCycles);
}
*/
if (stat_line && !stat_line_old) if (stat_line && !stat_line_old)
{ {
if (Core.REG_FFFF.Bit(1)) { Core.cpu.FlagI = true; } if (Core.REG_FFFF.Bit(1)) { Core.cpu.FlagI = true; }