PCE: Significant VDC timing improvements
This commit is contained in:
parent
e5cb8ec071
commit
50a06e38cd
|
@ -1,71 +1,41 @@
|
|||
======= TurboGrafx compatibility issues =======
|
||||
|
||||
General:
|
||||
+ Noise Channel isn't right. Less obnoxious now, still not happy.
|
||||
+ T Flag implemented for ADC, EOR. Log warning if used by any other instructions.
|
||||
Should probably just do it for the others, but I hate not having a test case.
|
||||
+ Video timing is off.
|
||||
+ Don't have a complete list of instructions affected by T flag. Currently warns if SET precedes an unrecognized instruction.
|
||||
+ Audio volumes are probably wrong.
|
||||
+ LFO is not implemented, though I can't tell.
|
||||
+ Screen is too tall on several games. Obv resolution calculation is not 100% correct.
|
||||
|
||||
Adventure Island - Flicker on title screen sequence - timing?
|
||||
Aero Blaster - Bottom of Screen possibly extends too many lines
|
||||
Agmeda - Very minor timing/gfx glitches esp at bottom of screen
|
||||
Air Zonk - Freezes shortly into a new game
|
||||
Alice - Screen possibly too tall; glitches when scrolling up, but in pcejin also,
|
||||
Aero Blaster - Bottom of Screen extends too many lines - like 3 extra or so
|
||||
Air Zonk - Fully playable, doesn't freeze, but some gfx/timing issues
|
||||
Alice - Screen too tall; glitches when scrolling up, but in pcejin also,
|
||||
but not ootake; ergo probably a timing artifact
|
||||
Andre Panza Kickbx- Doesn't boot. Looks like semi pedigree as Battle Royal.
|
||||
Battle Ace - Some gfx glitches
|
||||
Battle Royale - Doesnt boot
|
||||
Boxy Boy - Freezes when starting game; seems to remain broken even after rewinding (!!)
|
||||
Bravoman - Is currently booting. But has been boot-problematic in the past.
|
||||
Cadash - Camera is all crazy. Very sensitive to interrupt timing and timing in general.
|
||||
Chase HQ - Press start -"O" sprite gets left on screen. probably timing on SATB DMA
|
||||
Chouzetsu Rinjin - Japanese version of Bravoman. Currently working.
|
||||
College Pro Basebl- In startup sequence, sprites are crazy, game goes nuts when starting game
|
||||
Cross Wiber - Minor; Raster on wrong line
|
||||
Cyber Dodge - Minor gfx issues
|
||||
Davis Cup Tennis - Doesnt boot at all right now
|
||||
Davis Cup Tennis - Some timing issue, splash screen is too slow
|
||||
Dead Moon - Screen is too tall
|
||||
Dragon Egg - Doesn't boot at all
|
||||
Dungeon Explorer - Freeze in 'intro' - gfx corruption in-game
|
||||
Fighting Run - Corruption issues
|
||||
Final Blaster - Does crazy shit with video modes; freezes if intro is not skipped
|
||||
Final Solider - Graphics corruption issues - some right at the beginning that might be a good target
|
||||
Ghost Mannor - Game will freeze in some circumstances mid gameplay
|
||||
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
|
||||
Gunboat - Crash / CPU Break (Needs BRAM)
|
||||
Hisou Kihei Serd - Doesn't boot
|
||||
Idol Hanafuda Fan Club - Doesn't boot
|
||||
Impossamole - Gfx issues
|
||||
Jack Nicholas Golf- Doesnt boot basically
|
||||
Legendary Axe - BYR updated on the wrong line of the screen, but playable.
|
||||
Legendary Axe II - Fairly serious corruption issues, but playable now
|
||||
Jack Nicholas Golf- Some screens are too tall and reveal bad gfx below the intended visible screen
|
||||
Legend of Hero Ton- Slight gfx- check top of screen
|
||||
Lode Runner - Freezes in new game
|
||||
Madoo Granzort - Graphics issues because VPC renderer is not using new frame timing
|
||||
Metal Stoker - Tearing when scrolling vertically at bottom of screen - timing
|
||||
Madoo Granzort - Graphics issues because SGX VPC renderer is not using new frame timing
|
||||
Metal Stoker - Tearing when scrolling vertically at bottom of screen - screen too tall?
|
||||
MML Demo - Echo channels are too loud (equal volume!)
|
||||
Naxat Open - Crashes when you start new game
|
||||
NHK Taiga Drama Ta- Sprite flicker and corruption issues
|
||||
Night Creatures - Some gfx glitches
|
||||
Outrun - Raster issues, music slows when paused
|
||||
Paranoia - MAYBE game freeze in like 5th level? not sure, didnt verify.
|
||||
Paranoia - Game hits BREAK on 3rd level. need to investigate
|
||||
Populous - Game freezes on starting new game - *** NEEDS BATTERY SAVERAM ***
|
||||
Power Drift - Timing glitch... starting new game runs slower than it should
|
||||
Power Tennis - Freezes in (elaborate) intro screen. decent target though
|
||||
R-Type - Funky corruption after killing final boss in Stage 8
|
||||
Power Tennis - Elaborate intro screen doesnt display right
|
||||
Raiden - Sprites and BG get out of sync with current timing
|
||||
Rastan Saga 2 - Doesn't boot - lots of invalid reads?
|
||||
Sekikehara - Gfx corruption, some palette problems?
|
||||
Side Arms - Screen is like 4 pixels too tall
|
||||
Sinistron - Raster effect errors
|
||||
Soldier Blade - Freezes about 5 minutes in. Always in the same spot, fortunately. I have a savestate.
|
||||
Soukoban World - J version of Boxy Boy - Same bugs
|
||||
Thunder Blade - After beating the 1st 3d area, game semi-freezes
|
||||
Sinistron - Much less bad raster effect errors now
|
||||
Tiger Road - On second level, sprites should be getting masked from the top status area somehow
|
||||
Valkyrie No Densetsu - Boots now, but with pretty severe issues
|
||||
|
||||
|
||||
Stuff I Fixed That's Not In Other Docs:
|
||||
|
|
|
@ -38,14 +38,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
// PC Engine timings:
|
||||
// 21,477,270 Machine clocks / sec
|
||||
// 7,159,090 Cpu cycles / sec
|
||||
|
||||
// At 60.00 FPS
|
||||
// 357,954 mclks / frame
|
||||
// 119,318 Cpu cycles / frame
|
||||
|
||||
// 263 lines / frame:
|
||||
// 1361 mclks / line
|
||||
// 454 Cpu cycles / line
|
||||
|
||||
public PCEngine(NecSystemType type)
|
||||
{
|
||||
|
@ -108,7 +100,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
public void FrameAdvance(bool render)
|
||||
{
|
||||
Controller.UpdateControls(Frame++);
|
||||
//Log.Note("CPU","======== FRAME {0} =========",Frame);
|
||||
PSG.BeginFrame(Cpu.TotalExecutedCycles);
|
||||
|
||||
if (SuperGrafx)
|
||||
|
|
|
@ -15,10 +15,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
+ BackgroundY is the current offset into the scroll plane. It is set with BYR
|
||||
register at certain sync points and incremented every scanline.
|
||||
Its values range from 0 - $1FF.
|
||||
+ RCRCount is the current offset into the RCR register. It is reset to $40
|
||||
on the first active display line, and incremented every line. Its effective
|
||||
range is $40 - $146.
|
||||
|
||||
*/
|
||||
public int ScanLine;
|
||||
public int BackgroundY;
|
||||
|
@ -27,7 +23,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
private byte[] InterSpritePriorityBuffer = new byte[512];
|
||||
private int latchedDisplayStartLine;
|
||||
private int ActiveLine;
|
||||
private int RCRCount;
|
||||
|
||||
public void ExecFrame(bool render)
|
||||
{
|
||||
|
@ -35,10 +30,16 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
ActiveLine = 0 - latchedDisplayStartLine;
|
||||
ScanLine = 0;
|
||||
|
||||
int HDS = (Registers[HSR] >> 8) & 0x7F;
|
||||
int HDE = (Registers[HDR] >> 8) & 0x7F;
|
||||
int hblankCycles = (HDS + HDE + 2) * 8;
|
||||
//hblankCycles -= 2;
|
||||
int hds = (Registers[HSR] >> 8) & 0x7F;
|
||||
int hde = (Registers[HDR] >> 8) & 0x7F;
|
||||
int vds = Registers[VPR] >> 8;
|
||||
int vsw = Registers[VPR] & 0x1F;
|
||||
|
||||
int VBlankScanline = vds + vsw + Registers[VDW] + 1;
|
||||
if (VBlankScanline > 261)
|
||||
VBlankScanline = 261;
|
||||
|
||||
int hblankCycles = (hds + hde + 2) * 8;
|
||||
|
||||
switch (vce.DotClock)
|
||||
{
|
||||
|
@ -47,7 +48,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
case 2: hblankCycles = (hblankCycles*2)/3; break;
|
||||
}
|
||||
|
||||
for (; ScanLine < 262;)
|
||||
for (; ScanLine < 263;)
|
||||
{
|
||||
//Log.Note("VDC","ScanLine {0} (ActiveLine {1}, RCR {2}, BGY {3})",ScanLine, ActiveLine, RCRCount, BackgroundY);
|
||||
bool InActiveDisplay = false;
|
||||
|
@ -55,35 +56,33 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
InActiveDisplay = true;
|
||||
|
||||
if (ActiveLine == 0)
|
||||
{
|
||||
BackgroundY = Registers[BYR];
|
||||
RCRCount = 0x40;
|
||||
//Console.WriteLine("Latched BYR {0} at scanline {1}",BackgroundY, ScanLine);
|
||||
}
|
||||
|
||||
if ((RCRCount) == (Registers[RCR] & 0x3FF))
|
||||
if (ActiveLine == (Registers[RCR] & 0x3FF) - 0x40)
|
||||
{
|
||||
if (IntRasterCompare)
|
||||
if (RasterCompareInterruptEnabled)
|
||||
{
|
||||
//Log.Note("VDC", "Enter RCR interrupt at scanline {0}",ScanLine);
|
||||
Log.Note("VDC", "Firing RCR interrupt at {0}", ScanLine);
|
||||
StatusByte |= StatusRasterCompare;
|
||||
cpu.IRQ1Assert = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ActiveLine == BufferHeight && IntVerticalBlank)
|
||||
{
|
||||
StatusByte |= StatusVerticalBlanking;
|
||||
cpu.IRQ1Assert = true;
|
||||
}
|
||||
cpu.Execute(hblankCycles);
|
||||
|
||||
|
||||
if (InActiveDisplay && render)
|
||||
RenderScanLine();
|
||||
|
||||
if (ScanLine == VBlankScanline && VBlankInterruptEnabled)
|
||||
{
|
||||
Log.Note("VDC", "Firing VBlank interrupt at {0}", ScanLine);
|
||||
StatusByte |= StatusVerticalBlanking;
|
||||
cpu.IRQ1Assert = true;
|
||||
}
|
||||
|
||||
cpu.Execute(455-hblankCycles);
|
||||
|
||||
if (ScanLine == FrameHeight - 1)
|
||||
if (ScanLine == VBlankScanline)
|
||||
UpdateSpriteAttributeTable();
|
||||
|
||||
if (InActiveDisplay == false && DmaRequested)
|
||||
|
@ -91,7 +90,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
ScanLine++;
|
||||
ActiveLine++;
|
||||
RCRCount++;
|
||||
BackgroundY++;
|
||||
BackgroundY &= 0x01FF;
|
||||
}
|
||||
|
@ -115,7 +113,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
if ((Registers[DCR] & 1) > 0)
|
||||
{
|
||||
Console.WriteLine("FIRING SATB DMA COMPLETION IRQ");
|
||||
Log.Note("VDC","FIRING SATB DMA COMPLETION IRQ");
|
||||
StatusByte |= StatusVramSatDmaComplete;
|
||||
cpu.IRQ1Assert = true;
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
}
|
||||
}
|
||||
|
||||
public bool BackgroundEnabled { get { return (Registers[CR] & 0x80) != 0; } }
|
||||
public bool SpritesEnabled { get { return (Registers[CR] & 0x40) != 0; } }
|
||||
public bool IntVerticalBlank { get { return (Registers[CR] & 0x08) != 0; } }
|
||||
public bool IntRasterCompare { get { return (Registers[CR] & 0x04) != 0; } }
|
||||
public bool IntSpriteOverflow { get { return (Registers[CR] & 0x02) != 0; } }
|
||||
public bool IntSpriteCollision { get { return (Registers[CR] & 0x01) != 0; } }
|
||||
public bool BackgroundEnabled { get { return (Registers[CR] & 0x80) != 0; } }
|
||||
public bool SpritesEnabled { get { return (Registers[CR] & 0x40) != 0; } }
|
||||
public bool VBlankInterruptEnabled { get { return (Registers[CR] & 0x08) != 0; } }
|
||||
public bool RasterCompareInterruptEnabled { get { return (Registers[CR] & 0x04) != 0; } }
|
||||
public bool SpriteOverflowInterruptEnabled { get { return (Registers[CR] & 0x02) != 0; } }
|
||||
public bool SpriteCollisionInterruptEnabled { get { return (Registers[CR] & 0x01) != 0; } }
|
||||
|
||||
public int BatWidth { get { switch((Registers[MWR] >> 4) & 3) { case 0: return 32; case 1: return 64; default: return 128; } } }
|
||||
public int BatHeight { get { return ((Registers[MWR] & 0x40) == 0) ? 32 : 64; } }
|
||||
|
@ -81,6 +81,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
public const byte StatusSpriteOverflow = 0x02;
|
||||
public const byte StatusSprite0Collision = 0x01;
|
||||
|
||||
private const int VramSize = 0x8000;
|
||||
|
||||
private HuC6280 cpu;
|
||||
private VCE vce;
|
||||
|
||||
|
@ -88,6 +90,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
this.cpu = cpu;
|
||||
this.vce = vce;
|
||||
|
||||
Registers[HSR] = 0x00FF;
|
||||
Registers[HDR] = 0x00FF;
|
||||
Registers[VPR] = 0xFFFF;
|
||||
Registers[VCR] = 0xFFFF;
|
||||
ReadBuffer = 0xFFFF;
|
||||
}
|
||||
|
||||
public void WriteVDC(int port, byte value)
|
||||
|
@ -108,37 +116,32 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
{
|
||||
Registers[RegisterLatch] &= 0x00FF;
|
||||
Registers[RegisterLatch] |= (ushort) (value << 8);
|
||||
CompleteMSBWrite();
|
||||
CompleteMSBWrite(RegisterLatch);
|
||||
}
|
||||
}
|
||||
|
||||
private void CompleteMSBWrite()
|
||||
private void CompleteMSBWrite(int register)
|
||||
{
|
||||
switch (RegisterLatch)
|
||||
switch (register)
|
||||
{
|
||||
case MARR: // Memory Address Read Register
|
||||
ReadBuffer = VRAM[Registers[MARR] & 0x7FFF];
|
||||
break;
|
||||
case VWR: // VRAM Write Register
|
||||
if (Registers[MAWR] < 0x8000)
|
||||
if (Registers[MAWR] < VramSize) // Several games attempt to write past the end of VRAM
|
||||
{
|
||||
VRAM[Registers[MAWR] & 0x7FFF] = Registers[VWR];
|
||||
VRAM[Registers[MAWR]] = Registers[VWR];
|
||||
UpdatePatternData((ushort) (Registers[MAWR] & 0x7FFF));
|
||||
UpdateSpriteData((ushort) (Registers[MAWR] & 0x7FFF));
|
||||
}
|
||||
Registers[MAWR] += IncrementWidth;
|
||||
break;
|
||||
case CR:
|
||||
//if (Registers[CR] == 0)
|
||||
//Log.Note("CPU", "****************** WRITE TO CR: {0:X}", Registers[CR]);
|
||||
break;
|
||||
case BXR:
|
||||
Registers[BXR] &= 0x3FF;
|
||||
break;
|
||||
case BYR:
|
||||
Registers[BYR] &= 0x1FF;
|
||||
BackgroundY = Registers[BYR];
|
||||
//Console.WriteLine("Updating BYR to {0} at scanline {1}", BackgroundY, ScanLine);
|
||||
break;
|
||||
case HDR: // Horizontal Display Register - update framebuffer size
|
||||
FrameWidth = RequestedFrameWidth;
|
||||
|
@ -190,7 +193,7 @@ break;
|
|||
case 1: // unused
|
||||
return 0;
|
||||
case 2: // LSB
|
||||
return (byte) (ReadBuffer & 0xFF);
|
||||
return (byte) ReadBuffer;
|
||||
case 3: // MSB
|
||||
retval = (byte)(ReadBuffer >> 8);
|
||||
if (RegisterLatch == VRR)
|
||||
|
@ -221,7 +224,7 @@ break;
|
|||
|
||||
if ((Registers[DCR] & 2) > 0)
|
||||
{
|
||||
Console.WriteLine("FIRE VRAM-VRAM DMA COMPLETE IRQ");
|
||||
Log.Note("Vdc","FIRE VRAM-VRAM DMA COMPLETE IRQ");
|
||||
StatusByte |= StatusVramVramDmaComplete;
|
||||
cpu.IRQ1Assert = true;
|
||||
}
|
||||
|
@ -315,6 +318,9 @@ break;
|
|||
UpdatePatternData(i);
|
||||
UpdateSpriteData(i);
|
||||
}
|
||||
|
||||
CompleteMSBWrite(HDR);
|
||||
CompleteMSBWrite(VDW);
|
||||
}
|
||||
|
||||
public void SaveStateBinary(BinaryWriter writer)
|
||||
|
@ -345,6 +351,9 @@ break;
|
|||
RegisterLatch = reader.ReadByte();
|
||||
ReadBuffer = reader.ReadUInt16();
|
||||
StatusByte = reader.ReadByte();
|
||||
|
||||
CompleteMSBWrite(HDR);
|
||||
CompleteMSBWrite(VDW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
if ((ScanLine + 64) == (VDC1.Registers[6] & 0x3FF))
|
||||
{
|
||||
if (VDC1.IntRasterCompare)
|
||||
if (VDC1.RasterCompareInterruptEnabled)
|
||||
{
|
||||
VDC1.StatusByte |= VDC.StatusRasterCompare;
|
||||
CPU.IRQ1Assert = true;
|
||||
|
@ -161,20 +161,20 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
|
||||
if ((ScanLine + 64) == (VDC2.Registers[6] & 0x3FF))
|
||||
{
|
||||
if (VDC2.IntRasterCompare)
|
||||
if (VDC2.RasterCompareInterruptEnabled)
|
||||
{
|
||||
VDC2.StatusByte |= VDC.StatusRasterCompare;
|
||||
CPU.IRQ1Assert = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ScanLine == 240 && VDC1.IntVerticalBlank)
|
||||
if (ScanLine == 240 && VDC1.VBlankInterruptEnabled)
|
||||
{
|
||||
VDC1.StatusByte |= VDC.StatusVerticalBlanking;
|
||||
CPU.IRQ1Assert = true;
|
||||
}
|
||||
|
||||
if (ScanLine == 240 && VDC2.IntVerticalBlank)
|
||||
if (ScanLine == 240 && VDC2.VBlankInterruptEnabled)
|
||||
{
|
||||
VDC2.StatusByte |= VDC.StatusVerticalBlanking;
|
||||
CPU.IRQ1Assert = true;
|
||||
|
@ -295,7 +295,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
|
|||
if (width == 32)
|
||||
patternNo &= 0x1FE;
|
||||
|
||||
int yofs = 0;
|
||||
int yofs;
|
||||
if (vflip == false)
|
||||
{
|
||||
yofs = (vdc.ScanLine - y) & 15;
|
||||
|
|
Loading…
Reference in New Issue