Added a very poorly implemented PAL/NTSC toggle

This commit is contained in:
2026-05-17 15:02:31 +01:00
parent f1140fa115
commit 1730687009
8 changed files with 78 additions and 56 deletions

View File

@@ -5,6 +5,7 @@ namespace Core.Video
{ {
public class SmsVdp public class SmsVdp
{ {
public bool IsPalRegion { get; set; } = false;
// The VDP's private memory! The CPU cannot touch these arrays directly. // The VDP's private memory! The CPU cannot touch these arrays directly.
public byte[] VRAM { get; private set; } = new byte[0x4000]; // 16KB Video RAM public byte[] VRAM { get; private set; } = new byte[0x4000]; // 16KB Video RAM
public byte[] CRAM { get; private set; } = new byte[0x20]; // 32 Bytes Color Palette public byte[] CRAM { get; private set; } = new byte[0x20]; // 32 Bytes Color Palette
@@ -104,19 +105,17 @@ namespace Core.Video
public byte ReadVCounter() public byte ReadVCounter()
{ {
// NTSC Hardware Quirk: The Master System outputs 262 lines, if (IsPalRegion)
// but an 8-bit register can only hold a maximum value of 255!
// To prevent a hardware overflow to 0, the silicon jumps backward during VBlank.
if (_currentScanline <= 218) // 0xDA
{ {
return (byte)_currentScanline; // PAL Math: 313 lines. Counts 0 to 242, jumps to 186 (0xBA), counts to 255.
if (_currentScanline <= 242) return (byte)_currentScanline;
else return (byte)(_currentScanline - 57);
} }
else else
{ {
// At scanline 219, the counter jumps back to 213 (0xD5). // NTSC Math: 262 lines. Counts 0 to 218, jumps to 213 (0xD5), counts to 255.
// It then counts up to exactly 255 (0xFF) at the end of the frame. if (_currentScanline <= 218) return (byte)_currentScanline;
return (byte)(_currentScanline - 6); else return (byte)(_currentScanline - 6);
} }
} }
public byte ReadHCounter() public byte ReadHCounter()
@@ -174,7 +173,9 @@ namespace Core.Video
// 3. MOVE TO THE NEXT LINE // 3. MOVE TO THE NEXT LINE
_currentScanline++; _currentScanline++;
if (_currentScanline > 261) int maxLines = IsPalRegion ? 313 : 262;
if (_currentScanline > maxLines -1)
{ {
_currentScanline = 0; _currentScanline = 0;
} }

View File

@@ -50,9 +50,10 @@
<None Remove="ROMS\Gangster Town %28UE%29 [!].sms" /> <None Remove="ROMS\Gangster Town %28UE%29 [!].sms" />
<None Remove="ROMS\Gauntlet %28UE%29 [!].sms" /> <None Remove="ROMS\Gauntlet %28UE%29 [!].sms" />
<None Remove="ROMS\Ghost House %28UE%29 [!].sms" /> <None Remove="ROMS\Ghost House %28UE%29 [!].sms" />
<None Remove="ROMS\Ghouls %27n Ghosts %28UE%29 [!].sms" /> <None Remove="ROMS\Ghouls %27n Ghosts %28USA%29.sms" />
<None Remove="ROMS\Global Defense %28UE%29 [!].sms" /> <None Remove="ROMS\Global Defense %28UE%29 [!].sms" />
<None Remove="ROMS\Golden Axe %28UE%29 [!].sms" /> <None Remove="ROMS\Golden Axe %28UE%29 [!].sms" />
<None Remove="ROMS\Golden Axe Warrior.sav" />
<None Remove="ROMS\Golden Axe Warrior.sms" /> <None Remove="ROMS\Golden Axe Warrior.sms" />
<None Remove="ROMS\Great Baseball %28UE%29 [!].sms" /> <None Remove="ROMS\Great Baseball %28UE%29 [!].sms" />
<None Remove="ROMS\Great Basketball %28UE%29 [!].sms" /> <None Remove="ROMS\Great Basketball %28UE%29 [!].sms" />
@@ -73,7 +74,8 @@
<None Remove="ROMS\Mortal Kombat %28UE%29 [!].sms" /> <None Remove="ROMS\Mortal Kombat %28UE%29 [!].sms" />
<None Remove="ROMS\Mortal Kombat 2 %28UE%29 [!].sms" /> <None Remove="ROMS\Mortal Kombat 2 %28UE%29 [!].sms" />
<None Remove="ROMS\Mortal Kombat 3 %28UE%29 [!].sms" /> <None Remove="ROMS\Mortal Kombat 3 %28UE%29 [!].sms" />
<None Remove="ROMS\OutRun %28UE%29 [!].sms" /> <None Remove="ROMS\Olympic Gold - Barcelona %2792 %28Europe%29.sms" />
<None Remove="ROMS\OutRun %28USA%29.sms" />
<None Remove="ROMS\Paperboy %28UE%29 [!].sms" /> <None Remove="ROMS\Paperboy %28UE%29 [!].sms" />
<None Remove="ROMS\Parlour Games %28UE%29 [!].sms" /> <None Remove="ROMS\Parlour Games %28UE%29 [!].sms" />
<None Remove="ROMS\Phantasy Star %28UE%29 [!].sms" /> <None Remove="ROMS\Phantasy Star %28UE%29 [!].sms" />
@@ -88,7 +90,7 @@
<None Remove="ROMS\Sonic 2.sms" /> <None Remove="ROMS\Sonic 2.sms" />
<None Remove="ROMS\Sonic Chaos %28UE%29 [!].sms" /> <None Remove="ROMS\Sonic Chaos %28UE%29 [!].sms" />
<None Remove="ROMS\Sonic.sms" /> <None Remove="ROMS\Sonic.sms" />
<None Remove="ROMS\Space Harrier %28UE%29 [!].sms" /> <None Remove="ROMS\Space Harrier %28USA%29.sms" />
<None Remove="ROMS\Speedball %28UE%29 %28Virgin%29 [!].sms" /> <None Remove="ROMS\Speedball %28UE%29 %28Virgin%29 [!].sms" />
<None Remove="ROMS\Star Wars %28UE%29 [!].sms" /> <None Remove="ROMS\Star Wars %28UE%29 [!].sms" />
<None Remove="ROMS\Street Fighter 2 %28Brazil%29 [!].sms" /> <None Remove="ROMS\Street Fighter 2 %28Brazil%29 [!].sms" />
@@ -188,15 +190,14 @@
<EmbeddedResource Include="ROMS\Ghost House (UE) [!].sms"> <EmbeddedResource Include="ROMS\Ghost House (UE) [!].sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="ROMS\Ghouls 'n Ghosts (UE) [!].sms"> <EmbeddedResource Include="ROMS\Ghouls 'n Ghosts (USA).sms" />
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="ROMS\Global Defense (UE) [!].sms"> <EmbeddedResource Include="ROMS\Global Defense (UE) [!].sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="ROMS\Golden Axe (UE) [!].sms"> <EmbeddedResource Include="ROMS\Golden Axe (UE) [!].sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="ROMS\Golden Axe Warrior.sav" />
<EmbeddedResource Include="ROMS\Golden Axe Warrior.sms"> <EmbeddedResource Include="ROMS\Golden Axe Warrior.sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
@@ -257,9 +258,8 @@
<EmbeddedResource Include="ROMS\Mortal Kombat 3 (UE) [!].sms"> <EmbeddedResource Include="ROMS\Mortal Kombat 3 (UE) [!].sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="ROMS\OutRun (UE) [!].sms"> <EmbeddedResource Include="ROMS\Olympic Gold - Barcelona '92 (Europe).sms" />
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <EmbeddedResource Include="ROMS\OutRun (USA).sms" />
</EmbeddedResource>
<EmbeddedResource Include="ROMS\Paperboy (UE) [!].sms"> <EmbeddedResource Include="ROMS\Paperboy (UE) [!].sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
@@ -302,9 +302,7 @@
<EmbeddedResource Include="ROMS\Sonic.sms"> <EmbeddedResource Include="ROMS\Sonic.sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="ROMS\Space Harrier (UE) [!].sms"> <EmbeddedResource Include="ROMS\Space Harrier (USA).sms" />
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="ROMS\Speedball (UE) (Virgin) [!].sms"> <EmbeddedResource Include="ROMS\Speedball (UE) (Virgin) [!].sms">
<CopyToOutputDirectory>Never</CopyToOutputDirectory> <CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>

View File

@@ -39,10 +39,11 @@
vRAMViewerToolStripMenuItem = new ToolStripMenuItem(); vRAMViewerToolStripMenuItem = new ToolStripMenuItem();
machineToolStripMenuItem = new ToolStripMenuItem(); machineToolStripMenuItem = new ToolStripMenuItem();
resetToolStripMenuItem = new ToolStripMenuItem(); resetToolStripMenuItem = new ToolStripMenuItem();
helpToolStripMenuItem = new ToolStripMenuItem();
aboutToolStripMenuItem = new ToolStripMenuItem();
saveStateToolStripMenuItem = new ToolStripMenuItem(); saveStateToolStripMenuItem = new ToolStripMenuItem();
loadStateToolStripMenuItem = new ToolStripMenuItem(); loadStateToolStripMenuItem = new ToolStripMenuItem();
helpToolStripMenuItem = new ToolStripMenuItem();
aboutToolStripMenuItem = new ToolStripMenuItem();
pALRegionToolStripMenuItem = new ToolStripMenuItem();
menuStrip1.SuspendLayout(); menuStrip1.SuspendLayout();
SuspendLayout(); SuspendLayout();
// //
@@ -52,7 +53,8 @@
menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, viewToolStripMenuItem, machineToolStripMenuItem, helpToolStripMenuItem }); menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, viewToolStripMenuItem, machineToolStripMenuItem, helpToolStripMenuItem });
menuStrip1.Location = new Point(0, 0); menuStrip1.Location = new Point(0, 0);
menuStrip1.Name = "menuStrip1"; menuStrip1.Name = "menuStrip1";
menuStrip1.Size = new Size(791, 33); menuStrip1.Padding = new Padding(5, 2, 0, 2);
menuStrip1.Size = new Size(633, 28);
menuStrip1.TabIndex = 2; menuStrip1.TabIndex = 2;
menuStrip1.Text = "menuStrip1"; menuStrip1.Text = "menuStrip1";
// //
@@ -60,34 +62,34 @@
// //
fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { openToolStripMenuItem, exitToolStripMenuItem }); fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { openToolStripMenuItem, exitToolStripMenuItem });
fileToolStripMenuItem.Name = "fileToolStripMenuItem"; fileToolStripMenuItem.Name = "fileToolStripMenuItem";
fileToolStripMenuItem.Size = new Size(54, 29); fileToolStripMenuItem.Size = new Size(46, 24);
fileToolStripMenuItem.Text = "File"; fileToolStripMenuItem.Text = "File";
// //
// openToolStripMenuItem // openToolStripMenuItem
// //
openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, selectROMToolStripMenuItem1 }); openToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { includedToolStripMenuItem, selectROMToolStripMenuItem1 });
openToolStripMenuItem.Name = "openToolStripMenuItem"; openToolStripMenuItem.Name = "openToolStripMenuItem";
openToolStripMenuItem.Size = new Size(158, 34); openToolStripMenuItem.Size = new Size(224, 26);
openToolStripMenuItem.Text = "Open"; openToolStripMenuItem.Text = "Open";
// //
// includedToolStripMenuItem // includedToolStripMenuItem
// //
includedToolStripMenuItem.Name = "includedToolStripMenuItem"; includedToolStripMenuItem.Name = "includedToolStripMenuItem";
includedToolStripMenuItem.Size = new Size(218, 34); includedToolStripMenuItem.Size = new Size(178, 26);
includedToolStripMenuItem.Text = "Included"; includedToolStripMenuItem.Text = "Included";
includedToolStripMenuItem.Click += includedToolStripMenuItem_Click; includedToolStripMenuItem.Click += includedToolStripMenuItem_Click;
// //
// selectROMToolStripMenuItem1 // selectROMToolStripMenuItem1
// //
selectROMToolStripMenuItem1.Name = "selectROMToolStripMenuItem1"; selectROMToolStripMenuItem1.Name = "selectROMToolStripMenuItem1";
selectROMToolStripMenuItem1.Size = new Size(218, 34); selectROMToolStripMenuItem1.Size = new Size(178, 26);
selectROMToolStripMenuItem1.Text = "Select ROM..."; selectROMToolStripMenuItem1.Text = "Select ROM...";
selectROMToolStripMenuItem1.Click += selectROMToolStripMenuItem_Click; selectROMToolStripMenuItem1.Click += selectROMToolStripMenuItem_Click;
// //
// exitToolStripMenuItem // exitToolStripMenuItem
// //
exitToolStripMenuItem.Name = "exitToolStripMenuItem"; exitToolStripMenuItem.Name = "exitToolStripMenuItem";
exitToolStripMenuItem.Size = new Size(158, 34); exitToolStripMenuItem.Size = new Size(224, 26);
exitToolStripMenuItem.Text = "Exit"; exitToolStripMenuItem.Text = "Exit";
exitToolStripMenuItem.Click += exitToolStripMenuItem_Click; exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
// //
@@ -95,72 +97,81 @@
// //
viewToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { debuggerToolStripMenuItem, vRAMViewerToolStripMenuItem }); viewToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { debuggerToolStripMenuItem, vRAMViewerToolStripMenuItem });
viewToolStripMenuItem.Name = "viewToolStripMenuItem"; viewToolStripMenuItem.Name = "viewToolStripMenuItem";
viewToolStripMenuItem.Size = new Size(65, 29); viewToolStripMenuItem.Size = new Size(55, 24);
viewToolStripMenuItem.Text = "View"; viewToolStripMenuItem.Text = "View";
// //
// debuggerToolStripMenuItem // debuggerToolStripMenuItem
// //
debuggerToolStripMenuItem.Name = "debuggerToolStripMenuItem"; debuggerToolStripMenuItem.Name = "debuggerToolStripMenuItem";
debuggerToolStripMenuItem.Size = new Size(221, 34); debuggerToolStripMenuItem.Size = new Size(182, 26);
debuggerToolStripMenuItem.Text = "Debugger"; debuggerToolStripMenuItem.Text = "Debugger";
debuggerToolStripMenuItem.Click += debuggerToolStripMenuItem_Click; debuggerToolStripMenuItem.Click += debuggerToolStripMenuItem_Click;
// //
// vRAMViewerToolStripMenuItem // vRAMViewerToolStripMenuItem
// //
vRAMViewerToolStripMenuItem.Name = "vRAMViewerToolStripMenuItem"; vRAMViewerToolStripMenuItem.Name = "vRAMViewerToolStripMenuItem";
vRAMViewerToolStripMenuItem.Size = new Size(221, 34); vRAMViewerToolStripMenuItem.Size = new Size(182, 26);
vRAMViewerToolStripMenuItem.Text = "VRAM Viewer"; vRAMViewerToolStripMenuItem.Text = "VRAM Viewer";
vRAMViewerToolStripMenuItem.Click += vramViewerToolStripMenuItem_Click; vRAMViewerToolStripMenuItem.Click += vramViewerToolStripMenuItem_Click;
// //
// machineToolStripMenuItem // machineToolStripMenuItem
// //
machineToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { resetToolStripMenuItem, saveStateToolStripMenuItem, loadStateToolStripMenuItem }); machineToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { resetToolStripMenuItem, saveStateToolStripMenuItem, loadStateToolStripMenuItem, pALRegionToolStripMenuItem });
machineToolStripMenuItem.Name = "machineToolStripMenuItem"; machineToolStripMenuItem.Name = "machineToolStripMenuItem";
machineToolStripMenuItem.Size = new Size(94, 29); machineToolStripMenuItem.Size = new Size(79, 24);
machineToolStripMenuItem.Text = "Machine"; machineToolStripMenuItem.Text = "Machine";
// //
// resetToolStripMenuItem // resetToolStripMenuItem
// //
resetToolStripMenuItem.Name = "resetToolStripMenuItem"; resetToolStripMenuItem.Name = "resetToolStripMenuItem";
resetToolStripMenuItem.Size = new Size(270, 34); resetToolStripMenuItem.Size = new Size(224, 26);
resetToolStripMenuItem.Text = "Reset"; resetToolStripMenuItem.Text = "Reset";
resetToolStripMenuItem.Click += resetToolStripMenuItem_Click; resetToolStripMenuItem.Click += resetToolStripMenuItem_Click;
// //
// helpToolStripMenuItem
//
helpToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { aboutToolStripMenuItem });
helpToolStripMenuItem.Name = "helpToolStripMenuItem";
helpToolStripMenuItem.Size = new Size(65, 29);
helpToolStripMenuItem.Text = "Help";
//
// aboutToolStripMenuItem
//
aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
aboutToolStripMenuItem.Size = new Size(164, 34);
aboutToolStripMenuItem.Text = "About";
//
// saveStateToolStripMenuItem // saveStateToolStripMenuItem
// //
saveStateToolStripMenuItem.Name = "saveStateToolStripMenuItem"; saveStateToolStripMenuItem.Name = "saveStateToolStripMenuItem";
saveStateToolStripMenuItem.Size = new Size(270, 34); saveStateToolStripMenuItem.Size = new Size(224, 26);
saveStateToolStripMenuItem.Text = "Save State"; saveStateToolStripMenuItem.Text = "Save State";
saveStateToolStripMenuItem.Click += saveStateToolStripMenuItem_Click; saveStateToolStripMenuItem.Click += saveStateToolStripMenuItem_Click;
// //
// loadStateToolStripMenuItem // loadStateToolStripMenuItem
// //
loadStateToolStripMenuItem.Name = "loadStateToolStripMenuItem"; loadStateToolStripMenuItem.Name = "loadStateToolStripMenuItem";
loadStateToolStripMenuItem.Size = new Size(270, 34); loadStateToolStripMenuItem.Size = new Size(224, 26);
loadStateToolStripMenuItem.Text = "Load State"; loadStateToolStripMenuItem.Text = "Load State";
loadStateToolStripMenuItem.Click += loadStateToolStripMenuItem_Click; loadStateToolStripMenuItem.Click += loadStateToolStripMenuItem_Click;
// //
// helpToolStripMenuItem
//
helpToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { aboutToolStripMenuItem });
helpToolStripMenuItem.Name = "helpToolStripMenuItem";
helpToolStripMenuItem.Size = new Size(55, 24);
helpToolStripMenuItem.Text = "Help";
//
// aboutToolStripMenuItem
//
aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
aboutToolStripMenuItem.Size = new Size(133, 26);
aboutToolStripMenuItem.Text = "About";
//
// pALRegionToolStripMenuItem
//
pALRegionToolStripMenuItem.Checked = true;
pALRegionToolStripMenuItem.CheckOnClick = true;
pALRegionToolStripMenuItem.CheckState = CheckState.Checked;
pALRegionToolStripMenuItem.Name = "pALRegionToolStripMenuItem";
pALRegionToolStripMenuItem.Size = new Size(224, 26);
pALRegionToolStripMenuItem.Text = "PAL Region?";
pALRegionToolStripMenuItem.Click += pALRegionToolStripMenuItem_Click;
//
// ParsonsForm1 // ParsonsForm1
// //
AutoScaleDimensions = new SizeF(10F, 25F); AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(791, 622); ClientSize = new Size(633, 498);
Controls.Add(menuStrip1); Controls.Add(menuStrip1);
MainMenuStrip = menuStrip1; MainMenuStrip = menuStrip1;
Margin = new Padding(4);
Name = "ParsonsForm1"; Name = "ParsonsForm1";
Text = "Form1"; Text = "Form1";
FormClosing += ParsonsForm1_FormClosing; FormClosing += ParsonsForm1_FormClosing;
@@ -186,5 +197,6 @@
private ToolStripMenuItem vRAMViewerToolStripMenuItem; private ToolStripMenuItem vRAMViewerToolStripMenuItem;
private ToolStripMenuItem saveStateToolStripMenuItem; private ToolStripMenuItem saveStateToolStripMenuItem;
private ToolStripMenuItem loadStateToolStripMenuItem; private ToolStripMenuItem loadStateToolStripMenuItem;
private ToolStripMenuItem pALRegionToolStripMenuItem;
} }
} }

View File

@@ -113,7 +113,8 @@ namespace Desktop
IsRunning = true; IsRunning = true;
TotalFrameCount = 0; TotalFrameCount = 0;
double TargetFrameTime = 1000.0 / 59.92274; double targetFps = _machine.VideoProcessor.IsPalRegion ? 50.0 : 59.92274;
double TargetFrameTime = 1000.0 / targetFps;
_emulatorTask = Task.Run(() => _emulatorTask = Task.Run(() =>
{ {
@@ -330,7 +331,7 @@ namespace Desktop
private void exitToolStripMenuItem_Click(object sender, EventArgs e) private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{ {
this.Close(); this.Close();
} }
private void Form1_KeyDown(object sender, KeyEventArgs e) private void Form1_KeyDown(object sender, KeyEventArgs e)
@@ -410,5 +411,15 @@ namespace Desktop
// 3. Resume // 3. Resume
StartEmulator(); StartEmulator();
} }
private void pALRegionToolStripMenuItem_Click(object sender, EventArgs e)
{
if (pALRegionToolStripMenuItem.Checked)
_machine.VideoProcessor.IsPalRegion = true;
else _machine.VideoProcessor.IsPalRegion= false;
pALRegionToolStripMenuItem.Checked = !pALRegionToolStripMenuItem.Checked;
}
} }
} }

Binary file not shown.