Update SGX with new timing & support frameskip... huge success!

100% SGX compatibility (not that this is difficult)
This commit is contained in:
beirich 2011-07-20 03:57:41 +00:00
parent 47def064fa
commit 3bedad1e95
5 changed files with 139 additions and 78 deletions

View File

@ -9,44 +9,41 @@ General:
Right now the emulator is simply displaying a framebuffer. Eventually, we will do an update that emulates NTSC. Right now the emulator is simply displaying a framebuffer. Eventually, we will do an update that emulates NTSC.
But for now we're letting this be. There's no intermediate step between emulating a framebuffer and emulating a TV. But for now we're letting this be. There's no intermediate step between emulating a framebuffer and emulating a TV.
Air Zonk - Seems OK now - previous problem game Air Zonk - OK now - previous problem game
Battle Ace - Some gfx glitches Cadash - Req HBlank hack to eliminate minor visual artifact
Cadash - Minor raster issue. Timing sensitive game.
Chase HQ - Press start -"O" sprite gets left on screen. probably timing on SATB DMA Chase HQ - Press start -"O" sprite gets left on screen. probably timing on SATB DMA
Coryoon - Seems OK now - previous problem game Coryoon - OK now - previous problem game
Cross Wiber - Minor; Raster on wrong line Cross Wiber - Minor; Raster on wrong line
Davis Cup Tennis - Some timing issue, splash screen is too slow Dungeon Explorer - OK now - previous problem game
Dungeon Explorer - Seems OK now - previous problem game Lode Runner - OK now - previous problem game
Legend of Hero Ton- Slight gfx- check top of screen
Lode Runner - Seems OK now - previous problem game
Madoo Granzort - Graphics issues because SGX VPC renderer is not using new frame timing
MML Demo - Echo channels are too loud (equal volume!) MML Demo - Echo channels are too loud (equal volume!)
Outrun - Seems OK now - previous problem game Outrun - Req HBlank hack to eliminate visual artifact
Power Drift - Timing glitch... starting new game runs slower than it should
Power Tennis - Elaborate intro screen doesnt display right
Sinistron - Much less bad raster effect errors now
Tiger Road - On second level, sprites should be getting masked from the top status area somehow Tiger Road - On second level, sprites should be getting masked from the top status area somehow
=================================== ===================================
Games that need TV Emulation (to varying degrees) Games that need TV Emulation (to varying degrees)
=================================== ===================================
Greater degrees:
Final Blaster - Intro does crazy shit with video modes; not sure what if anything to do about it Final Blaster - Intro does crazy shit with video modes; not sure what if anything to do about it
Griffon - Screen goes black because game changes video mode mid-frame Griffon - Screen goes black because game changes video mode mid-frame
=================================== Lesser degrees:
Games with 'Frame Too Tall' issues:
===================================
Aero Blaster - Bottom of Screen extends too many lines - like 3 extra or so Aero Blaster - Bottom of Screen extends too many lines - like 3 extra or so
Alice - Screen too tall; glitches when scrolling up, but in pcejin also, Alice - Screen too tall; glitches when scrolling up, but in pcejin also,
but not ootake; ergo probably a timing artifact but not ootake; ergo probably a timing artifact
Dead Moon - Screen is too tall Dead Moon - Screen is too tall
Jack Nicholas Golf- Some screens are too tall and reveal bad gfx below the intended visible screen Jack Nicholas Golf- Some screens are too tall and reveal bad gfx below the intended visible screen
Legend of Hero Ton- Slight gfx issue on top of screen
Madoo Granzort - Screen ~5 pixels too tall
Metal Stoker - Tearing when scrolling vertically at bottom of screen - screen too tall? Metal Stoker - Tearing when scrolling vertically at bottom of screen - screen too tall?
Side Arms - Screen is like 4 pixels too tall Side Arms - Screen is like 4 pixels too tall
===================================
Stuff I Fixed That's Not In Other Docs: Stuff I Fixed That's Not In Other Docs:
===================================
+ Street Fighter II special mapper + Street Fighter II special mapper
+ Populous has special SaveRAM, 32k starting at page $40. + Populous has special SaveRAM, 32k starting at page $40.

View File

@ -120,6 +120,18 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Cpu.WriteMemory21 = WriteMemoryPopulous; Cpu.WriteMemory21 = WriteMemoryPopulous;
} }
// Ok, yes, HBlankPeriod's only purpose is game-specific hax.
// 1) At least they're not coded directly into the emulator, but instead data-driven.
// 2) The games (2) which have custom HBlankPeriods work without it, the override only
// serves to clean up minor gfx anomalies.
// 3) There's no point in haxing the timing with incorrect values in an attempt to avoid this.
// The proper fix is cycle-accurate/bus-accurate timing. That isn't coming to the C#
// version of this core. Lets just acknolwedge that the timing is imperfect and fix
// it in the least intrusive and most honest way we can.
if (game.GetOptions().ContainsStartsWith("HBlankPeriod"))
VDC1.HBlankCycles = int.Parse(game.GetOptions().GetOptionValue("HBlankPeriod"));
Cpu.ResetPC(); Cpu.ResetPC();
SetupMemoryDomains(); SetupMemoryDomains();
} }
@ -139,7 +151,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
PSG.BeginFrame(Cpu.TotalExecutedCycles); PSG.BeginFrame(Cpu.TotalExecutedCycles);
if (SuperGrafx) if (SuperGrafx)
VPC.ExecFrame(); // TODO supergrafx frameskipping (waiting on a larger update of VPC frame timing, once I get VDC timing correct) VPC.ExecFrame(render);
else else
VDC1.ExecFrame(render); VDC1.ExecFrame(render);

View File

@ -21,10 +21,11 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public int ScanLine; public int ScanLine;
public int BackgroundY; public int BackgroundY;
public int RCRCounter; public int RCRCounter;
private int ActiveLine; public int ActiveLine;
private byte[] PriorityBuffer = new byte[512]; private byte[] PriorityBuffer = new byte[512];
private byte[] InterSpritePriorityBuffer = new byte[512]; private byte[] InterSpritePriorityBuffer = new byte[512];
public int HBlankCycles = 79;
public void ExecFrame(bool render) public void ExecFrame(bool render)
{ {
@ -40,8 +41,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (ScanLine == ActiveDisplayStartLine) if (ScanLine == ActiveDisplayStartLine)
RCRCounter = 0x40; RCRCounter = 0x40;
const int hblankCycles = 79;
if (ScanLine == VBlankLine) if (ScanLine == VBlankLine)
UpdateSpriteAttributeTable(); UpdateSpriteAttributeTable();
@ -54,7 +53,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
cpu.Execute(hblankCycles); cpu.Execute(HBlankCycles);
if (InActiveDisplay) if (InActiveDisplay)
{ {
@ -83,7 +82,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if ((StatusByte & (StatusVerticalBlanking | StatusVramSatDmaComplete)) != 0) if ((StatusByte & (StatusVerticalBlanking | StatusVramSatDmaComplete)) != 0)
cpu.IRQ1Assert = true; cpu.IRQ1Assert = true;
cpu.Execute(455 - hblankCycles - 2); cpu.Execute(455 - HBlankCycles - 2);
if (InActiveDisplay == false && DmaRequested) if (InActiveDisplay == false && DmaRequested)
RunDmaForScanline(); RunDmaForScanline();

View File

@ -10,10 +10,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// Responsible for merging VDC1 and VDC2 data on the SuperGrafx. // Responsible for merging VDC1 and VDC2 data on the SuperGrafx.
// Pretty much all documentation on the SuperGrafx courtesy of Charles MacDonald. // Pretty much all documentation on the SuperGrafx courtesy of Charles MacDonald.
// VPC Frame timing has not been updated with new stuff. I expect Madoo Granzort to be fixed once the timing is updated.
// However, 1) The new frame timing is not working 100% yet, 2) I haven't decided if I want to continue having separate
// rendering in the VPC and the VDC.
public sealed class VPC : IVideoProvider public sealed class VPC : IVideoProvider
{ {
public VDC VDC1; public VDC VDC1;
@ -87,6 +83,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public void LoadStateBinary(BinaryReader reader) public void LoadStateBinary(BinaryReader reader)
{ {
Registers = reader.ReadBytes(7); Registers = reader.ReadBytes(7);
WriteVPC(0x0E, Registers[6]);
} }
public void SaveStateText(TextWriter writer) public void SaveStateText(TextWriter writer)
@ -109,14 +106,19 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
else else
Console.WriteLine("Skipping unrecognized identifier " + args[0]); Console.WriteLine("Skipping unrecognized identifier " + args[0]);
} }
WriteVPC(0x0E, Registers[6]);
} }
// We use a single priority mode for the whole frame. // We use a single priority mode for the whole frame.
// No commercial SGX games really use the 'window' features AFAIK. // No commercial SGX games really use the 'window' features AFAIK.
// And there are no homebrew SGX games I know of. // And there are no homebrew SGX games I know of.
// Maybe we'll emulate it in the native-code version.
private const int RCR = 6;
private const int BXR = 7; private const int BXR = 7;
private const int BYR = 8; private const int BYR = 8;
private const int VDW = 13;
private const int DCR = 15;
private int EffectivePriorityMode = 0; private int EffectivePriorityMode = 0;
@ -127,7 +129,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
private byte[] PriorityBuffer = new byte[512]; private byte[] PriorityBuffer = new byte[512];
private byte[] InterSpritePriorityBuffer = new byte[512]; private byte[] InterSpritePriorityBuffer = new byte[512];
public void ExecFrame() public void ExecFrame(bool render)
{ {
// Determine the effective priority mode. // Determine the effective priority mode.
if (Window1Width < 0x40 && Window2Width < 0x40) if (Window1Width < 0x40 && Window2Width < 0x40)
@ -145,12 +147,33 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
FrameHeight = VDC1.BufferHeight; FrameHeight = VDC1.BufferHeight;
FrameBuffer = VDC1.GetVideoBuffer(); FrameBuffer = VDC1.GetVideoBuffer();
for (int ScanLine = 0; ScanLine < 262; ScanLine++) int ScanLine = 0;
while (true)
{ {
VDC1.ScanLine = ScanLine; VDC1.ScanLine = ScanLine;
VDC2.ScanLine = ScanLine; VDC2.ScanLine = ScanLine;
if ((ScanLine + 64) == (VDC1.Registers[6] & 0x3FF)) int ActiveDisplayStartLine = VDC1.DisplayStartLine;
int VBlankLine = ActiveDisplayStartLine + VDC1.Registers[VDW] + 1;
if (VBlankLine > 261)
VBlankLine = 261;
VDC1.ActiveLine = ScanLine - ActiveDisplayStartLine;
VDC2.ActiveLine = VDC1.ActiveLine;
bool InActiveDisplay = (ScanLine >= ActiveDisplayStartLine) && (ScanLine < VBlankLine);
if (ScanLine == ActiveDisplayStartLine)
{
VDC1.RCRCounter = 0x40;
VDC2.RCRCounter = 0x40;
}
if (ScanLine == VBlankLine)
{
VDC1.UpdateSpriteAttributeTable();
VDC2.UpdateSpriteAttributeTable();
}
if (VDC1.RCRCounter == (VDC1.Registers[RCR] & 0x3FF))
{ {
if (VDC1.RasterCompareInterruptEnabled) if (VDC1.RasterCompareInterruptEnabled)
{ {
@ -159,7 +182,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
if ((ScanLine + 64) == (VDC2.Registers[6] & 0x3FF)) if (VDC2.RCRCounter == (VDC2.Registers[RCR] & 0x3FF))
{ {
if (VDC2.RasterCompareInterruptEnabled) if (VDC2.RasterCompareInterruptEnabled)
{ {
@ -168,34 +191,76 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
} }
if (ScanLine == 240 && VDC1.VBlankInterruptEnabled) CPU.Execute(VDC1.HBlankCycles);
if (InActiveDisplay)
{ {
if (ScanLine == ActiveDisplayStartLine)
{
VDC1.BackgroundY = VDC1.Registers[BYR];
VDC2.BackgroundY = VDC2.Registers[BYR];
}
else
{
VDC1.BackgroundY++;
VDC1.BackgroundY &= 0x01FF;
VDC2.BackgroundY++;
VDC2.BackgroundY &= 0x01FF;
}
if (render) RenderScanLine();
}
if (ScanLine == VBlankLine && VDC1.VBlankInterruptEnabled)
VDC1.StatusByte |= VDC.StatusVerticalBlanking; VDC1.StatusByte |= VDC.StatusVerticalBlanking;
CPU.IRQ1Assert = true;
}
if (ScanLine == 240 && VDC2.VBlankInterruptEnabled) if (ScanLine == VBlankLine && VDC2.VBlankInterruptEnabled)
{
VDC2.StatusByte |= VDC.StatusVerticalBlanking; VDC2.StatusByte |= VDC.StatusVerticalBlanking;
CPU.IRQ1Assert = true;
if (ScanLine == VBlankLine + 4 && VDC1.SatDmaPerformed)
{
VDC1.SatDmaPerformed = false;
if ((VDC1.Registers[DCR] & 1) > 0)
VDC1.StatusByte |= VDC.StatusVramSatDmaComplete;
} }
CPU.Execute(455); if (ScanLine == VBlankLine + 4 && VDC2.SatDmaPerformed)
{
VDC2.SatDmaPerformed = false;
if ((VDC2.Registers[DCR] & 1) > 0)
VDC2.StatusByte |= VDC.StatusVramSatDmaComplete;
}
if (ScanLine < FrameHeight) CPU.Execute(2);
RenderScanLine();
if ((VDC1.StatusByte & (VDC.StatusVerticalBlanking | VDC.StatusVramSatDmaComplete)) != 0)
CPU.IRQ1Assert = true;
if ((VDC2.StatusByte & (VDC.StatusVerticalBlanking | VDC.StatusVramSatDmaComplete)) != 0)
CPU.IRQ1Assert = true;
CPU.Execute(455 - VDC1.HBlankCycles - 2);
if (InActiveDisplay == false && VDC1.DmaRequested)
VDC1.RunDmaForScanline();
if (InActiveDisplay == false && VDC2.DmaRequested)
VDC2.RunDmaForScanline();
VDC1.RCRCounter++;
VDC2.RCRCounter++;
ScanLine++;
if (ScanLine == VCE.NumberOfScanlines)
break;
} }
} }
private void RenderScanLine() private void RenderScanLine()
{ {
if (VDC1.ScanLine == 0) if (VDC1.ActiveLine >= FrameHeight)
{ return;
VDC1.BackgroundY = VDC1.Registers[BYR];
VDC2.BackgroundY = VDC2.Registers[BYR];
}
InitializeScanLine(VDC1.ScanLine); InitializeScanLine(VDC1.ActiveLine);
switch (EffectivePriorityMode) switch (EffectivePriorityMode)
{ {
@ -212,12 +277,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
RenderSpritesScanline(VDC2, 1, 13); RenderSpritesScanline(VDC2, 1, 13);
break; break;
} }
if (VDC1.ScanLine == FrameHeight - 1)
{
VDC1.UpdateSpriteAttributeTable();
VDC2.UpdateSpriteAttributeTable();
}
} }
private void InitializeScanLine(int scanline) private void InitializeScanLine(int scanline)
@ -233,18 +292,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
private void RenderBackgroundScanline(VDC vdc, byte priority) private void RenderBackgroundScanline(VDC vdc, byte priority)
{ {
if (vdc.BackgroundEnabled == false) if (vdc.BackgroundEnabled == false)
{
vdc.BackgroundY++;
vdc.BackgroundY &= 0x01FF;
return; return;
}
int vertLine = vdc.BackgroundY; int vertLine = vdc.BackgroundY;
vertLine %= vdc.BatHeight * 8; vertLine %= vdc.BatHeight * 8;
int yTile = (vertLine / 8); int yTile = (vertLine / 8);
int yOfs = vertLine % 8; int yOfs = vertLine % 8;
vdc.BackgroundY++;
vdc.BackgroundY &= 0x01FF;
int xScroll = vdc.Registers[BXR] & 0x3FF; int xScroll = vdc.Registers[BXR] & 0x3FF;
for (int x = 0; x < FrameWidth; x++) for (int x = 0; x < FrameWidth; x++)
@ -259,7 +312,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
byte c = vdc.PatternBuffer[(tileNo * 64) + (yOfs * 8) + xOfs]; byte c = vdc.PatternBuffer[(tileNo * 64) + (yOfs * 8) + xOfs];
if (c != 0) if (c != 0)
{ {
FrameBuffer[(vdc.ScanLine * FrameWidth) + x] = VCE.Palette[paletteBase + c]; FrameBuffer[(vdc.ActiveLine * FrameWidth) + x] = VCE.Palette[paletteBase + c];
PriorityBuffer[x] = priority; PriorityBuffer[x] = priority;
} }
} }
@ -282,7 +335,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
ushort flags = vdc.SpriteAttributeTable[(i * 4) + 3]; ushort flags = vdc.SpriteAttributeTable[(i * 4) + 3];
int height = heightTable[(flags >> 12) & 3]; int height = heightTable[(flags >> 12) & 3];
if (y + height <= vdc.ScanLine || y > vdc.ScanLine) if (y + height <= vdc.ActiveLine || y > vdc.ActiveLine)
continue; continue;
int patternNo = (((vdc.SpriteAttributeTable[(i * 4) + 2]) >> 1) & 0x1FF); int patternNo = (((vdc.SpriteAttributeTable[(i * 4) + 2]) >> 1) & 0x1FF);
@ -298,11 +351,11 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
int yofs; int yofs;
if (vflip == false) if (vflip == false)
{ {
yofs = (vdc.ScanLine - y) & 15; yofs = (vdc.ActiveLine - y) & 15;
if (height == 32) if (height == 32)
{ {
patternNo &= 0x1FD; patternNo &= 0x1FD;
if (vdc.ScanLine - y >= 16) if (vdc.ActiveLine - y >= 16)
{ {
y += 16; y += 16;
patternNo += 2; patternNo += 2;
@ -311,17 +364,17 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
else if (height == 64) else if (height == 64)
{ {
patternNo &= 0x1F9; patternNo &= 0x1F9;
if (vdc.ScanLine - y >= 48) if (vdc.ActiveLine - y >= 48)
{ {
y += 48; y += 48;
patternNo += 6; patternNo += 6;
} }
else if (vdc.ScanLine - y >= 32) else if (vdc.ActiveLine - y >= 32)
{ {
y += 32; y += 32;
patternNo += 4; patternNo += 4;
} }
else if (vdc.ScanLine - y >= 16) else if (vdc.ActiveLine - y >= 16)
{ {
y += 16; y += 16;
patternNo += 2; patternNo += 2;
@ -330,11 +383,11 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
} }
else // vflip == true else // vflip == true
{ {
yofs = 15 - ((vdc.ScanLine - y) & 15); yofs = 15 - ((vdc.ActiveLine - y) & 15);
if (height == 32) if (height == 32)
{ {
patternNo &= 0x1FD; patternNo &= 0x1FD;
if (vdc.ScanLine - y < 16) if (vdc.ActiveLine - y < 16)
{ {
y += 16; y += 16;
patternNo += 2; patternNo += 2;
@ -343,17 +396,17 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
else if (height == 64) else if (height == 64)
{ {
patternNo &= 0x1F9; patternNo &= 0x1F9;
if (vdc.ScanLine - y < 16) if (vdc.ActiveLine - y < 16)
{ {
y += 48; y += 48;
patternNo += 6; patternNo += 6;
} }
else if (vdc.ScanLine - y < 32) else if (vdc.ActiveLine - y < 32)
{ {
y += 32; y += 32;
patternNo += 4; patternNo += 4;
} }
else if (vdc.ScanLine - y < 48) else if (vdc.ActiveLine - y < 48)
{ {
y += 16; y += 16;
patternNo += 2; patternNo += 2;
@ -373,7 +426,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
byte myPriority = priority ? highPriority : lowPriority; byte myPriority = priority ? highPriority : lowPriority;
if (PriorityBuffer[xs] < myPriority) if (PriorityBuffer[xs] < myPriority)
{ {
FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; FrameBuffer[(vdc.ActiveLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel];
PriorityBuffer[xs] = myPriority; PriorityBuffer[xs] = myPriority;
} }
} }
@ -392,7 +445,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
byte myPriority = priority ? highPriority : lowPriority; byte myPriority = priority ? highPriority : lowPriority;
if (PriorityBuffer[xs] < myPriority) if (PriorityBuffer[xs] < myPriority)
{ {
FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; FrameBuffer[(vdc.ActiveLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel];
PriorityBuffer[xs] = myPriority; PriorityBuffer[xs] = myPriority;
} }
} }
@ -414,7 +467,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
byte myPriority = priority ? highPriority : lowPriority; byte myPriority = priority ? highPriority : lowPriority;
if (PriorityBuffer[xs] < myPriority) if (PriorityBuffer[xs] < myPriority)
{ {
FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; FrameBuffer[(vdc.ActiveLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel];
PriorityBuffer[xs] = myPriority; PriorityBuffer[xs] = myPriority;
} }
} }
@ -432,7 +485,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
byte myPriority = priority ? highPriority : lowPriority; byte myPriority = priority ? highPriority : lowPriority;
if (PriorityBuffer[xs] < myPriority) if (PriorityBuffer[xs] < myPriority)
{ {
FrameBuffer[(vdc.ScanLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel]; FrameBuffer[(vdc.ActiveLine * FrameWidth) + xs] = VCE.Palette[paletteBase + pixel];
PriorityBuffer[xs] = myPriority; PriorityBuffer[xs] = myPriority;
} }
} }

View File

@ -2031,7 +2031,7 @@ C9D7426A Break In PCE
5C4D1991 Bullfight Ring no Haja PCE 5C4D1991 Bullfight Ring no Haja PCE
D233C05A Burning Angels PCE D233C05A Burning Angels PCE
47AFE6D7 Bloody Wolf PCE 47AFE6D7 Bloody Wolf PCE
BB0B3AEF Cadash PCE BB0B3AEF Cadash PCE HBlankPeriod=83
3F9F95A4 CD-ROM System Card V1.00 (J) PCE BRAM 3F9F95A4 CD-ROM System Card V1.00 (J) PCE BRAM
FF2A5EC3 CD-ROM System Card V2.00 (U) PCE BRAM FF2A5EC3 CD-ROM System Card V2.00 (U) PCE BRAM
283B74E0 CD-ROM System Card V2.10 (J) PCE BRAM 283B74E0 CD-ROM System Card V2.10 (J) PCE BRAM
@ -2104,7 +2104,7 @@ BF3E2CC7 Hani in the Sky PCE
9897FA86 Hani on the Road PCE 9897FA86 Hani on the Road PCE
44E7DF53 Hatris PCE 44E7DF53 Hatris PCE
EB923DE5 Heavy Unit PCE EB923DE5 Heavy Unit PCE
1CAB1EE6 Hisou Kihei Serd PCE 1CAB1EE6 Hisou Kihei Serd PCE BRAM
7ACB60C8 Hit the Ice PCE 7ACB60C8 Hit the Ice PCE
B01EE703 Hono no Tataka Tamako Dodge Danpei PCE B01EE703 Hono no Tataka Tamako Dodge Danpei PCE
9EC6FC6C Idol Hanafuda Fan Club PCE 9EC6FC6C Idol Hanafuda Fan Club PCE
@ -2165,7 +2165,7 @@ C159761B Night Creatures PCE
4D3B0BC9 Obocchama Kun PCE 4D3B0BC9 Obocchama Kun PCE
8C565CB6 Ordyne PCE 8C565CB6 Ordyne PCE
5CDB3F5B Outlive PCE 5CDB3F5B Outlive PCE
E203F223 Out Run PCE E203F223 Out Run PCE HBlankPeriod=88
B74EC562 Override PCE B74EC562 Override PCE
7632DB90 P-47 - The Freedom Fighter PCE 7632DB90 P-47 - The Freedom Fighter PCE
D6E30CCD Pac-Land PCE D6E30CCD Pac-Land PCE
@ -2227,7 +2227,7 @@ DDC3E809 Thunder Blade PCE
9107BCC8 Tiger Shark PCE 9107BCC8 Tiger Shark PCE
CFEC1D6A Time Cruise 2 PCE CFEC1D6A Time Cruise 2 PCE
53B7784B Toilet Kids PCE 53B7784B Toilet Kids PCE
FE451C22 Tongueman's Logic PCE FE451C22 D Tongueman's Logic PCE BRAM
72E00BC4 The Tower of Druaga PCE 72E00BC4 The Tower of Druaga PCE
EB045EDF Turrican PCE EB045EDF Turrican PCE
97FE5BCF TV Sports Hockey PCE 97FE5BCF TV Sports Hockey PCE