NTSC/PAL selection (+ auto detect)

This commit is contained in:
Sour 2019-03-14 15:25:35 -04:00
parent 58af2b136f
commit 45f0f77d6b
11 changed files with 178 additions and 18 deletions

View file

@ -186,7 +186,6 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
_memoryManager->Initialize(shared_from_this());
_cpu.reset(new Cpu(this));
_memoryManager->IncrementMasterClockValue<170>();
_rewindManager.reset(new RewindManager(shared_from_this()));
_notificationManager->RegisterNotificationListener(_rewindManager);
@ -199,6 +198,9 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
//_debugger.reset();
//GetDebugger();
//}
UpdateRegion();
_memoryManager->IncrementMasterClockValue<170>();
_paused = false;
_notificationManager->SendNotification(ConsoleNotificationType::GameLoaded);
@ -215,6 +217,38 @@ RomInfo Console::GetRomInfo()
}
}
uint32_t Console::GetMasterClockRate()
{
return _masterClockRate;
}
ConsoleRegion Console::GetRegion()
{
return _region;
}
void Console::UpdateRegion()
{
switch(_settings->GetEmulationConfig().Region) {
case ConsoleRegion::Auto:
{
uint8_t destCode = _cart->GetRomInfo().Header.DestinationCode;
if((destCode >= 0x02 && destCode <= 0x0C) || destCode == 0x11) {
_region = ConsoleRegion::Pal;
} else {
_region = ConsoleRegion::Ntsc;
}
break;
}
default:
case ConsoleRegion::Ntsc: _region = ConsoleRegion::Ntsc; break;
case ConsoleRegion::Pal: _region = ConsoleRegion::Pal; break;
}
_masterClockRate = _region == ConsoleRegion::Pal ? 21281370 : 21477270;
}
double Console::GetFrameDelay()
{
uint32_t emulationSpeed = _settings->GetEmulationSpeed();
@ -222,7 +256,12 @@ double Console::GetFrameDelay()
if(emulationSpeed == 0) {
frameDelay = 0;
} else {
frameDelay = 16.63926405550947 / (emulationSpeed / 100.0);
UpdateRegion();
switch(_region) {
case ConsoleRegion::Ntsc: frameDelay = 16.63926405550947; break;
case ConsoleRegion::Pal: frameDelay = 19.99720882631146; break;
}
frameDelay /= (emulationSpeed / 100.0);
}
return frameDelay;
}

View file

@ -25,6 +25,7 @@ class RewindManager;
enum class MemoryOperationType;
enum class SnesMemoryType;
enum class EventType;
enum class ConsoleRegion;
class Console : public std::enable_shared_from_this<Console>
{
@ -58,7 +59,11 @@ private:
atomic<bool> _stopFlag;
atomic<bool> _paused;
ConsoleRegion _region;
uint32_t _masterClockRate;
double GetFrameDelay();
void UpdateRegion();
void WaitForLock();
void WaitForPauseEnd();
@ -77,6 +82,8 @@ public:
void LoadRom(VirtualFile romFile, VirtualFile patchFile);
RomInfo GetRomInfo();
uint32_t GetMasterClockRate();
ConsoleRegion GetRegion();
ConsoleLock AcquireLock();
void Lock();

View file

@ -117,7 +117,10 @@ void Ppu::Exec()
} else if(_scanline == 240 && _frameCount & 0x01 && !_screenInterlace) {
//"In non-interlace mode scanline 240 of every other frame (those with $213f.7=1) is only 1360 cycles."
_cycle++;
} else if((_scanline == 262 && (!_screenInterlace || (_frameCount & 0x01))) || _scanline == 263) {
} else if(
(_console->GetRegion() == ConsoleRegion::Ntsc && ((_scanline == 262 && (!_screenInterlace || (_frameCount & 0x01))) || _scanline == 263)) ||
(_console->GetRegion() == ConsoleRegion::Pal && ((_scanline == 312 && (!_screenInterlace || (_frameCount & 0x01))) || _scanline == 313))
) {
//"Frames are 262 scanlines in non-interlace mode, while in interlace mode frames with $213f.7=0 are 263 scanlines"
_regs->SetNmiFlag(false);
_scanline = 0;
@ -1257,7 +1260,7 @@ uint8_t Ppu::Read(uint16_t addr)
((_frameCount & 0x01) ? 0x80 : 0) |
(_locationLatched ? 0x40 : 0) |
(_ppu2OpenBus & 0x20) |
//TODO (_isPal ? 0x10 : 0)
(_console->GetRegion() == ConsoleRegion::Pal ? 0x10 : 0) |
0x02 //PPU (5c78) chip version
);

View file

@ -228,12 +228,21 @@ enum class RamPowerOnState
Random = 2
};
enum class ConsoleRegion
{
Auto = 0,
Ntsc = 1,
Pal = 2
};
struct EmulationConfig
{
uint32_t EmulationSpeed = 100;
uint32_t TurboSpeed = 300;
uint32_t RewindSpeed = 100;
ConsoleRegion Region = ConsoleRegion::Auto;
bool AllowInvalidInput = false;
bool EnableRandomPowerOnState = false;

View file

@ -32,7 +32,7 @@ int Spc::GetSpcTime()
{
uint64_t currentClock = _console->GetMemoryManager()->GetMasterClock();
uint64_t elapsedClocks = currentClock - _startFrameMasterClock;
return (int)(elapsedClocks * 1024000 / 21477000);
return (int)(elapsedClocks * 1024000 / _console->GetMasterClockRate());
}
uint8_t Spc::Read(uint16_t addr)
@ -53,7 +53,7 @@ void Spc::ProcessEndFrame()
_console->GetSoundMixer()->PlayAudioBuffer(_soundBuffer, sampleCount / 2);
_spc->set_output(_soundBuffer, Spc::SampleBufferSize >> 1);
uint64_t remainder = (_console->GetMemoryManager()->GetMasterClock() - _startFrameMasterClock) * 1024000 % 21477000 / 1024000;
uint64_t remainder = (_console->GetMemoryManager()->GetMasterClock() - _startFrameMasterClock) * 1024000 % _console->GetMasterClockRate() / 1024000;
_startFrameMasterClock = _console->GetMemoryManager()->GetMasterClock() - remainder;
}

View file

@ -14,6 +14,8 @@ namespace Mesen.GUI.Config
[MinMax(0, 5000)] public UInt32 TurboSpeed = 300;
[MinMax(0, 5000)] public UInt32 RewindSpeed = 100;
public ConsoleRegion Region = ConsoleRegion.Auto;
[MarshalAs(UnmanagedType.I1)] public bool AllowInvalidInput = false;
[MarshalAs(UnmanagedType.I1)] public bool EnableMapperRandomPowerOnState = false;
@ -28,6 +30,13 @@ namespace Mesen.GUI.Config
}
}
public enum ConsoleRegion
{
Auto = 0,
Ntsc = 1,
Pal = 2
}
public enum RamPowerOnState
{
AllZeros = 0,

View file

@ -143,7 +143,14 @@ namespace Mesen.GUI.Emulation
}
}
}
public void SetRegion(ConsoleRegion region)
{
ConfigManager.Config.Emulation.Region = region;
ConfigManager.Config.Emulation.ApplyConfig();
ConfigManager.ApplyChanges();
}
public void SetVideoFilter(VideoFilterType filter)
{
ConfigManager.Config.Video.VideoFilter = filter;

View file

@ -42,6 +42,8 @@
this.flowLayoutPanel10 = new System.Windows.Forms.FlowLayoutPanel();
this.nudRewindSpeed = new Mesen.GUI.Controls.MesenNumericUpDown();
this.lblRewindSpeedHint = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.cboRegion = new System.Windows.Forms.ComboBox();
this.tabMain.SuspendLayout();
this.tpgGeneral.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
@ -82,16 +84,19 @@
this.tableLayoutPanel4.ColumnCount = 2;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.label1, 0, 3);
this.tableLayoutPanel4.Controls.Add(this.flowLayoutPanel9, 1, 1);
this.tableLayoutPanel4.Controls.Add(this.lblTurboSpeed, 0, 1);
this.tableLayoutPanel4.Controls.Add(this.flowLayoutPanel6, 1, 0);
this.tableLayoutPanel4.Controls.Add(this.lblEmulationSpeed, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.lblRewindSpeed, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.flowLayoutPanel10, 1, 2);
this.tableLayoutPanel4.Controls.Add(this.cboRegion, 1, 3);
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 3);
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
this.tableLayoutPanel4.RowCount = 4;
this.tableLayoutPanel4.RowCount = 5;
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
@ -285,6 +290,25 @@
this.lblRewindSpeedHint.TabIndex = 2;
this.lblRewindSpeedHint.Text = "% (0 = Maximum speed)";
//
// label1
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(3, 88);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(44, 13);
this.label1.TabIndex = 17;
this.label1.Text = "Region:";
//
// cboRegion
//
this.cboRegion.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboRegion.FormattingEnabled = true;
this.cboRegion.Location = new System.Drawing.Point(114, 84);
this.cboRegion.Name = "cboRegion";
this.cboRegion.Size = new System.Drawing.Size(121, 21);
this.cboRegion.TabIndex = 18;
//
// frmEmulationConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -331,5 +355,7 @@
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel10;
private Controls.MesenNumericUpDown nudRewindSpeed;
private System.Windows.Forms.Label lblRewindSpeedHint;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ComboBox cboRegion;
}
}

View file

@ -25,6 +25,7 @@ namespace Mesen.GUI.Forms.Config
AddBinding(nameof(EmulationConfig.EmulationSpeed), nudEmulationSpeed);
AddBinding(nameof(EmulationConfig.TurboSpeed), nudTurboSpeed);
AddBinding(nameof(EmulationConfig.RewindSpeed), nudRewindSpeed);
AddBinding(nameof(EmulationConfig.Region), cboRegion);
}
protected override void OnApply()

View file

@ -122,6 +122,11 @@
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
this.pnlRenderer = new System.Windows.Forms.Panel();
this.mnuRegion = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRegionAuto = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRegionNtsc = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRegionPal = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuMain.SuspendLayout();
this.pnlRenderer.SuspendLayout();
this.SuspendLayout();
@ -271,6 +276,7 @@
this.mnuEmulationSpeed,
this.mnuVideoScale,
this.mnuVideoFilter,
this.mnuRegion,
this.toolStripMenuItem4,
this.mnuAudioConfig,
this.mnuInputConfig,
@ -299,7 +305,7 @@
this.mnuShowFPS});
this.mnuEmulationSpeed.Image = global::Mesen.GUI.Properties.Resources.Speed;
this.mnuEmulationSpeed.Name = "mnuEmulationSpeed";
this.mnuEmulationSpeed.Size = new System.Drawing.Size(135, 22);
this.mnuEmulationSpeed.Size = new System.Drawing.Size(152, 22);
this.mnuEmulationSpeed.Text = "Speed";
this.mnuEmulationSpeed.DropDownOpening += new System.EventHandler(this.mnuEmulationSpeed_DropDownOpening);
//
@ -387,7 +393,7 @@
this.mnuFullscreen});
this.mnuVideoScale.Image = global::Mesen.GUI.Properties.Resources.Fullscreen;
this.mnuVideoScale.Name = "mnuVideoScale";
this.mnuVideoScale.Size = new System.Drawing.Size(135, 22);
this.mnuVideoScale.Size = new System.Drawing.Size(152, 22);
this.mnuVideoScale.Text = "Video Size";
this.mnuVideoScale.DropDownOpening += new System.EventHandler(this.mnuVideoScale_DropDownOpening);
//
@ -473,7 +479,7 @@
this.mnuBilinearInterpolation});
this.mnuVideoFilter.Image = global::Mesen.GUI.Properties.Resources.VideoFilter;
this.mnuVideoFilter.Name = "mnuVideoFilter";
this.mnuVideoFilter.Size = new System.Drawing.Size(135, 22);
this.mnuVideoFilter.Size = new System.Drawing.Size(152, 22);
this.mnuVideoFilter.Text = "Video Filter";
this.mnuVideoFilter.DropDownOpening += new System.EventHandler(this.mnuVideoFilter_DropDownOpening);
//
@ -654,13 +660,13 @@
// toolStripMenuItem4
//
this.toolStripMenuItem4.Name = "toolStripMenuItem4";
this.toolStripMenuItem4.Size = new System.Drawing.Size(132, 6);
this.toolStripMenuItem4.Size = new System.Drawing.Size(149, 6);
//
// mnuAudioConfig
//
this.mnuAudioConfig.Image = global::Mesen.GUI.Properties.Resources.Audio;
this.mnuAudioConfig.Name = "mnuAudioConfig";
this.mnuAudioConfig.Size = new System.Drawing.Size(135, 22);
this.mnuAudioConfig.Size = new System.Drawing.Size(152, 22);
this.mnuAudioConfig.Text = "Audio";
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click);
//
@ -668,7 +674,7 @@
//
this.mnuInputConfig.Image = global::Mesen.GUI.Properties.Resources.Controller;
this.mnuInputConfig.Name = "mnuInputConfig";
this.mnuInputConfig.Size = new System.Drawing.Size(135, 22);
this.mnuInputConfig.Size = new System.Drawing.Size(152, 22);
this.mnuInputConfig.Text = "Input";
this.mnuInputConfig.Click += new System.EventHandler(this.mnuInputConfig_Click);
//
@ -676,7 +682,7 @@
//
this.mnuVideoConfig.Image = global::Mesen.GUI.Properties.Resources.VideoOptions;
this.mnuVideoConfig.Name = "mnuVideoConfig";
this.mnuVideoConfig.Size = new System.Drawing.Size(135, 22);
this.mnuVideoConfig.Size = new System.Drawing.Size(152, 22);
this.mnuVideoConfig.Text = "Video";
this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
//
@ -684,20 +690,20 @@
//
this.mnuEmulationConfig.Image = global::Mesen.GUI.Properties.Resources.DipSwitches;
this.mnuEmulationConfig.Name = "mnuEmulationConfig";
this.mnuEmulationConfig.Size = new System.Drawing.Size(135, 22);
this.mnuEmulationConfig.Size = new System.Drawing.Size(152, 22);
this.mnuEmulationConfig.Text = "Emulation";
this.mnuEmulationConfig.Click += new System.EventHandler(this.mnuEmulationConfig_Click);
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(132, 6);
this.toolStripMenuItem3.Size = new System.Drawing.Size(149, 6);
//
// mnuPreferences
//
this.mnuPreferences.Image = global::Mesen.GUI.Properties.Resources.Settings;
this.mnuPreferences.Name = "mnuPreferences";
this.mnuPreferences.Size = new System.Drawing.Size(135, 22);
this.mnuPreferences.Size = new System.Drawing.Size(152, 22);
this.mnuPreferences.Text = "Preferences";
this.mnuPreferences.Click += new System.EventHandler(this.mnuPreferences_Click);
//
@ -797,6 +803,7 @@
//
// mnuCheckForUpdates
//
this.mnuCheckForUpdates.Image = global::Mesen.GUI.Properties.Resources.Update;
this.mnuCheckForUpdates.Name = "mnuCheckForUpdates";
this.mnuCheckForUpdates.Size = new System.Drawing.Size(170, 22);
this.mnuCheckForUpdates.Text = "Check for updates";
@ -838,6 +845,42 @@
this.pnlRenderer.Size = new System.Drawing.Size(512, 448);
this.pnlRenderer.TabIndex = 2;
//
// mnuRegion
//
this.mnuRegion.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuRegionAuto,
this.toolStripMenuItem1,
this.mnuRegionNtsc,
this.mnuRegionPal});
this.mnuRegion.Image = global::Mesen.GUI.Properties.Resources.WebBrowser;
this.mnuRegion.Name = "mnuRegion";
this.mnuRegion.Size = new System.Drawing.Size(152, 22);
this.mnuRegion.Text = "Region";
this.mnuRegion.DropDownOpening += new System.EventHandler(this.mnuRegion_DropDownOpening);
//
// mnuRegionAuto
//
this.mnuRegionAuto.Name = "mnuRegionAuto";
this.mnuRegionAuto.Size = new System.Drawing.Size(152, 22);
this.mnuRegionAuto.Text = "Auto";
//
// mnuRegionNtsc
//
this.mnuRegionNtsc.Name = "mnuRegionNtsc";
this.mnuRegionNtsc.Size = new System.Drawing.Size(152, 22);
this.mnuRegionNtsc.Text = "NTSC";
//
// mnuRegionPal
//
this.mnuRegionPal.Name = "mnuRegionPal";
this.mnuRegionPal.Size = new System.Drawing.Size(152, 22);
this.mnuRegionPal.Text = "PAL";
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(149, 6);
//
// frmMain
//
this.AllowDrop = true;
@ -954,5 +997,10 @@
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem10;
private System.Windows.Forms.ToolStripMenuItem mnuEmulationConfig;
private System.Windows.Forms.ToolStripMenuItem mnuInputConfig;
private System.Windows.Forms.ToolStripMenuItem mnuRegion;
private System.Windows.Forms.ToolStripMenuItem mnuRegionAuto;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem mnuRegionNtsc;
private System.Windows.Forms.ToolStripMenuItem mnuRegionPal;
}
}

View file

@ -157,6 +157,10 @@ namespace Mesen.GUI.Forms
mnuXBRZ6xFilter.Click += (s, e) => { _shortcuts.SetVideoFilter(VideoFilterType.xBRZ6x); };
mnuBilinearInterpolation.Click += (s, e) => { _shortcuts.ToggleBilinearInterpolation(); };
mnuRegionAuto.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Auto); };
mnuRegionNtsc.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Ntsc); };
mnuRegionPal.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Pal); };
}
private void UpdateViewerSize(ScreenSize screenSize)
@ -368,5 +372,12 @@ namespace Mesen.GUI.Forms
{
SaveStateManager.UpdateStateMenu(mnuSaveState, true);
}
private void mnuRegion_DropDownOpening(object sender, EventArgs e)
{
mnuRegionAuto.Checked = ConfigManager.Config.Emulation.Region == ConsoleRegion.Auto;
mnuRegionNtsc.Checked = ConfigManager.Config.Emulation.Region == ConsoleRegion.Ntsc;
mnuRegionPal.Checked = ConfigManager.Config.Emulation.Region == ConsoleRegion.Pal;
}
}
}