diff --git a/Core/AviRecorder.cpp b/Core/AviRecorder.cpp index 8bb23573..ef6a2196 100644 --- a/Core/AviRecorder.cpp +++ b/Core/AviRecorder.cpp @@ -1,6 +1,8 @@ #include "stdafx.h" #include "AviRecorder.h" #include "MessageManager.h" +#include "Console.h" +#include "EmulationSettings.h" AviRecorder::AviRecorder() { @@ -23,18 +25,28 @@ AviRecorder::~AviRecorder() } } -bool AviRecorder::StartRecording(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, uint32_t fps, uint32_t audioSampleRate, uint32_t compressionLevel) +uint32_t AviRecorder::GetFps() +{ + if(Console::GetModel() == NesModel::NTSC) { + return EmulationSettings::CheckFlag(EmulationFlags::IntegerFpsMode) ? 60000000 : 60098812; + } else { + return EmulationSettings::CheckFlag(EmulationFlags::IntegerFpsMode) ? 50000000 : 50006978; + } +} + +bool AviRecorder::StartRecording(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, uint32_t compressionLevel) { if(!_recording) { _outputFile = filename; _sampleRate = audioSampleRate; _width = width; _height = height; + _fps = GetFps(); _frameBufferLength = height * width * bpp; _frameBuffer = new uint8_t[_frameBufferLength]; _aviWriter.reset(new AviWriter()); - if(!_aviWriter->StartWrite(filename, codec, width, height, bpp, fps, audioSampleRate, compressionLevel)) { + if(!_aviWriter->StartWrite(filename, codec, width, height, bpp, _fps, audioSampleRate, compressionLevel)) { _aviWriter.reset(); return false; } @@ -76,7 +88,7 @@ void AviRecorder::StopRecording() void AviRecorder::AddFrame(void* frameBuffer, uint32_t width, uint32_t height) { if(_recording) { - if(_width != width || _height != height) { + if(_width != width || _height != height || _fps != GetFps()) { StopRecording(); } else { auto lock = _lock.AcquireSafe(); diff --git a/Core/AviRecorder.h b/Core/AviRecorder.h index e9d4e786..0f3c46db 100644 --- a/Core/AviRecorder.h +++ b/Core/AviRecorder.h @@ -22,14 +22,17 @@ private: uint32_t _frameBufferLength; uint32_t _sampleRate; + uint32_t _fps; uint32_t _width; uint32_t _height; + uint32_t GetFps(); + public: AviRecorder(); virtual ~AviRecorder(); - bool StartRecording(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, uint32_t fps, uint32_t audioSampleRate, uint32_t compressionLevel); + bool StartRecording(string filename, VideoCodec codec, uint32_t width, uint32_t height, uint32_t bpp, uint32_t audioSampleRate, uint32_t compressionLevel); void StopRecording(); void AddFrame(void* frameBuffer, uint32_t width, uint32_t height); diff --git a/Core/Console.cpp b/Core/Console.cpp index bc7d3e83..37b7ddb2 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -531,9 +531,9 @@ double Console::GetFrameDelay() //60.1fps (NTSC), 50.01fps (PAL/Dendy) switch(_model) { default: - case NesModel::NTSC: frameDelay = 16.63926405550947; break; + case NesModel::NTSC: frameDelay = EmulationSettings::CheckFlag(EmulationFlags::IntegerFpsMode) ? 16.6666666666666666667 : 16.63926405550947; break; case NesModel::PAL: - case NesModel::Dendy: frameDelay = 19.99720920217466; break; + case NesModel::Dendy: frameDelay = EmulationSettings::CheckFlag(EmulationFlags::IntegerFpsMode) ? 20 : 19.99720920217466; break; } frameDelay /= (double)emulationSpeed / 100.0; } diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index 7eca929c..c9758b65 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -71,6 +71,8 @@ enum EmulationFlags : uint64_t NsfRepeat = 0x800000000000, NsfShuffle = 0x1000000000000, + IntegerFpsMode = 0x2000000000000, + ForceMaxSpeed = 0x4000000000000000, ConsoleMode = 0x8000000000000000, }; diff --git a/Core/SoundMixer.cpp b/Core/SoundMixer.cpp index 45e4bc16..9db2a944 100644 --- a/Core/SoundMixer.cpp +++ b/Core/SoundMixer.cpp @@ -181,6 +181,15 @@ void SoundMixer::UpdateRates(bool forceUpdate) newRate = (uint32_t)(newRate * (double)EmulationSettings::GetOverclockRate() / 100); } + if(EmulationSettings::CheckFlag(EmulationFlags::IntegerFpsMode)) { + //Adjust sample rate when running at 60.0 fps instead of 60.1 + if(_model == NesModel::NTSC) { + newRate = (uint32_t)(newRate * 60.0 / 60.0988118623484); + } else { + newRate = (uint32_t)(newRate * 50.0 / 50.00697796826829); + } + } + if(_clockRate != newRate || forceUpdate) { _clockRate = newRate; blip_set_rates(_blipBufLeft, _clockRate, _sampleRate); diff --git a/Core/VideoRenderer.cpp b/Core/VideoRenderer.cpp index 99591e89..c769c259 100644 --- a/Core/VideoRenderer.cpp +++ b/Core/VideoRenderer.cpp @@ -92,7 +92,7 @@ void VideoRenderer::StartRecording(string filename, VideoCodec codec, uint32_t c shared_ptr recorder(new AviRecorder()); FrameInfo frameInfo = VideoDecoder::GetInstance()->GetFrameInfo(); - if(recorder->StartRecording(filename, codec, frameInfo.Width, frameInfo.Height, frameInfo.BitsPerPixel, 60098814, EmulationSettings::GetSampleRate(), compressionLevel)) { + if(recorder->StartRecording(filename, codec, frameInfo.Width, frameInfo.Height, frameInfo.BitsPerPixel, EmulationSettings::GetSampleRate(), compressionLevel)) { _aviRecorder = recorder; } } diff --git a/GUI.NET/Config/VideoInfo.cs b/GUI.NET/Config/VideoInfo.cs index bb052657..c8027519 100644 --- a/GUI.NET/Config/VideoInfo.cs +++ b/GUI.NET/Config/VideoInfo.cs @@ -23,6 +23,7 @@ namespace Mesen.GUI.Config [MinMax(0.1, 5.0)] public double CustomAspectRatio = 1.0; public bool VerticalSync = false; public bool UseHdPacks = false; + public bool IntegerFpsMode = false; public string PaletteData; [MinMax(-100, 100)] public Int32 Brightness = 0; @@ -66,6 +67,7 @@ namespace Mesen.GUI.Config InteropEmu.SetFlag(EmulationFlags.ShowFPS, videoInfo.ShowFPS); InteropEmu.SetFlag(EmulationFlags.VerticalSync, videoInfo.VerticalSync); InteropEmu.SetFlag(EmulationFlags.UseHdPacks, videoInfo.UseHdPacks); + InteropEmu.SetFlag(EmulationFlags.IntegerFpsMode, videoInfo.IntegerFpsMode); InteropEmu.SetFlag(EmulationFlags.DisableBackground, videoInfo.DisableBackground); InteropEmu.SetFlag(EmulationFlags.DisableSprites, videoInfo.DisableSprites); diff --git a/GUI.NET/Dependencies/resources.ca.xml b/GUI.NET/Dependencies/resources.ca.xml index 47cab131..8f52488a 100644 --- a/GUI.NET/Dependencies/resources.ca.xml +++ b/GUI.NET/Dependencies/resources.ca.xml @@ -243,6 +243,7 @@ General Escala: Filtre: + Enable integer FPS mode (e.g: run at 60 fps instead of 60.1) Activa la sincronització vertical Relació d'aspecte: Relació personalitzada: diff --git a/GUI.NET/Dependencies/resources.es.xml b/GUI.NET/Dependencies/resources.es.xml index cb8054c3..78b6519e 100644 --- a/GUI.NET/Dependencies/resources.es.xml +++ b/GUI.NET/Dependencies/resources.es.xml @@ -243,6 +243,7 @@ General Escala: Filtro: + Enable integer FPS mode (e.g: run at 60 fps instead of 60.1) Activar la sincronización vertical Formato de imagen: Relación personalizada: diff --git a/GUI.NET/Dependencies/resources.fr.xml b/GUI.NET/Dependencies/resources.fr.xml index 22bf9ff9..e3f24329 100644 --- a/GUI.NET/Dependencies/resources.fr.xml +++ b/GUI.NET/Dependencies/resources.fr.xml @@ -245,6 +245,7 @@ Général Échelle : Filtre : + Activer le mode 60.0/50.0 FPS (au lieu du 60.1/50.1 FPS normalement utilisé) Activer la synchronisation verticale Format d'image : Ratio personalisé : diff --git a/GUI.NET/Dependencies/resources.ja.xml b/GUI.NET/Dependencies/resources.ja.xml index 51aba2f5..b0e2dacc 100644 --- a/GUI.NET/Dependencies/resources.ja.xml +++ b/GUI.NET/Dependencies/resources.ja.xml @@ -247,6 +247,7 @@ 全般 画面サイズ: 画面エフェクト: + 60.0 fpsモードを有効にする (普段の60.1fpsに対して) バイリニア補間を有効にする 垂直同期を有効にする 画面アスペクト: diff --git a/GUI.NET/Dependencies/resources.pt.xml b/GUI.NET/Dependencies/resources.pt.xml index f7be0ec8..3850c788 100644 --- a/GUI.NET/Dependencies/resources.pt.xml +++ b/GUI.NET/Dependencies/resources.pt.xml @@ -243,6 +243,7 @@ Geral Escala: Filtro: + Enable integer FPS mode (e.g: run at 60 fps instead of 60.1) Ativar a sincronização vertical Formato de imagem: Proporção personalizada: diff --git a/GUI.NET/Dependencies/resources.ru.xml b/GUI.NET/Dependencies/resources.ru.xml index 5948bf6e..016f73e0 100644 --- a/GUI.NET/Dependencies/resources.ru.xml +++ b/GUI.NET/Dependencies/resources.ru.xml @@ -245,6 +245,7 @@ Общие Размер : Фильтр : + Enable integer FPS mode (e.g: run at 60 fps instead of 60.1) Включить вертикальную синхронизацию Соотношение сторон : Custom ratio: diff --git a/GUI.NET/Dependencies/resources.uk.xml b/GUI.NET/Dependencies/resources.uk.xml index d91901fc..34c6ecaf 100644 --- a/GUI.NET/Dependencies/resources.uk.xml +++ b/GUI.NET/Dependencies/resources.uk.xml @@ -245,6 +245,7 @@ Загальнi Розмір : Фiльтр : + Enable integer FPS mode (e.g: run at 60 fps instead of 60.1) Включити вертикальну синхронізацію Співвідношення сторін : Користувацьке співвідношення: diff --git a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs index 3d344a7a..883e23f8 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs +++ b/GUI.NET/Forms/Config/frmVideoConfig.Designer.cs @@ -124,6 +124,7 @@ namespace Mesen.GUI.Forms.Config this.mnuPaletteSonyCxa2025As = new System.Windows.Forms.ToolStripMenuItem(); this.mnuPaletteUnsaturated = new System.Windows.Forms.ToolStripMenuItem(); this.mnuPaletteYuv = new System.Windows.Forms.ToolStripMenuItem(); + this.chkIntegerFpsMode = new System.Windows.Forms.CheckBox(); this.tlpMain.SuspendLayout(); this.flowLayoutPanel7.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.picHdNesTooltip)).BeginInit(); @@ -170,16 +171,18 @@ namespace Mesen.GUI.Forms.Config this.tlpMain.Controls.Add(this.lblVideoScale, 0, 0); this.tlpMain.Controls.Add(this.chkVerticalSync, 0, 3); this.tlpMain.Controls.Add(this.lblDisplayRatio, 0, 1); - this.tlpMain.Controls.Add(this.flowLayoutPanel7, 0, 2); + this.tlpMain.Controls.Add(this.flowLayoutPanel7, 0, 4); this.tlpMain.Controls.Add(this.nudScale, 1, 0); this.tlpMain.Controls.Add(this.flowLayoutPanel6, 1, 1); - this.tlpMain.Controls.Add(this.chkFullscreenForceIntegerScale, 0, 4); - this.tlpMain.Controls.Add(this.chkShowFps, 0, 5); + this.tlpMain.Controls.Add(this.chkFullscreenForceIntegerScale, 0, 5); + this.tlpMain.Controls.Add(this.chkShowFps, 0, 6); + this.tlpMain.Controls.Add(this.chkIntegerFpsMode, 0, 2); this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill; this.tlpMain.Location = new System.Drawing.Point(3, 3); this.tlpMain.Margin = new System.Windows.Forms.Padding(0); this.tlpMain.Name = "tlpMain"; - this.tlpMain.RowCount = 7; + this.tlpMain.RowCount = 8; + this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle()); @@ -228,7 +231,7 @@ namespace Mesen.GUI.Forms.Config this.flowLayoutPanel7.Controls.Add(this.chkUseHdPacks); this.flowLayoutPanel7.Controls.Add(this.picHdNesTooltip); this.flowLayoutPanel7.Dock = System.Windows.Forms.DockStyle.Fill; - this.flowLayoutPanel7.Location = new System.Drawing.Point(0, 46); + this.flowLayoutPanel7.Location = new System.Drawing.Point(0, 92); this.flowLayoutPanel7.Margin = new System.Windows.Forms.Padding(0); this.flowLayoutPanel7.Name = "flowLayoutPanel7"; this.flowLayoutPanel7.Size = new System.Drawing.Size(521, 23); @@ -364,7 +367,7 @@ namespace Mesen.GUI.Forms.Config this.chkFullscreenForceIntegerScale.Anchor = System.Windows.Forms.AnchorStyles.Left; this.chkFullscreenForceIntegerScale.AutoSize = true; this.tlpMain.SetColumnSpan(this.chkFullscreenForceIntegerScale, 2); - this.chkFullscreenForceIntegerScale.Location = new System.Drawing.Point(3, 95); + this.chkFullscreenForceIntegerScale.Location = new System.Drawing.Point(3, 118); this.chkFullscreenForceIntegerScale.Name = "chkFullscreenForceIntegerScale"; this.chkFullscreenForceIntegerScale.Size = new System.Drawing.Size(289, 17); this.chkFullscreenForceIntegerScale.TabIndex = 23; @@ -376,7 +379,7 @@ namespace Mesen.GUI.Forms.Config this.chkShowFps.Anchor = System.Windows.Forms.AnchorStyles.Left; this.chkShowFps.AutoSize = true; this.tlpMain.SetColumnSpan(this.chkShowFps, 2); - this.chkShowFps.Location = new System.Drawing.Point(3, 118); + this.chkShowFps.Location = new System.Drawing.Point(3, 141); this.chkShowFps.Name = "chkShowFps"; this.chkShowFps.Size = new System.Drawing.Size(76, 17); this.chkShowFps.TabIndex = 9; @@ -1456,6 +1459,18 @@ namespace Mesen.GUI.Forms.Config this.mnuPaletteYuv.Text = "YUV v3 (by FirebrandX)"; this.mnuPaletteYuv.Click += new System.EventHandler(this.mnuPaletteYuv_Click); // + // chkIntegerFpsMode + // + this.chkIntegerFpsMode.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.chkIntegerFpsMode.AutoSize = true; + this.tlpMain.SetColumnSpan(this.chkIntegerFpsMode, 2); + this.chkIntegerFpsMode.Location = new System.Drawing.Point(3, 49); + this.chkIntegerFpsMode.Name = "chkIntegerFpsMode"; + this.chkIntegerFpsMode.Size = new System.Drawing.Size(295, 17); + this.chkIntegerFpsMode.TabIndex = 24; + this.chkIntegerFpsMode.Text = "Enable integer FPS mode (e.g: run at 60 fps instead of 60.1)"; + this.chkIntegerFpsMode.UseVisualStyleBackColor = true; + // // frmVideoConfig // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -1615,5 +1630,6 @@ namespace Mesen.GUI.Forms.Config private System.Windows.Forms.CheckBox chkFullscreenForceIntegerScale; private System.Windows.Forms.CheckBox chkShowColorIndexes; private Debugger.ctrlPaletteDisplay ctrlPaletteDisplay; + private System.Windows.Forms.CheckBox chkIntegerFpsMode; } } \ No newline at end of file diff --git a/GUI.NET/Forms/Config/frmVideoConfig.cs b/GUI.NET/Forms/Config/frmVideoConfig.cs index 1353146c..a93816b1 100644 --- a/GUI.NET/Forms/Config/frmVideoConfig.cs +++ b/GUI.NET/Forms/Config/frmVideoConfig.cs @@ -29,7 +29,8 @@ namespace Mesen.GUI.Forms.Config AddBinding("UseBilinearInterpolation", chkBilinearInterpolation); AddBinding("VerticalSync", chkVerticalSync); AddBinding("UseHdPacks", chkUseHdPacks); - + AddBinding("IntegerFpsMode", chkIntegerFpsMode); + AddBinding("VideoScale", nudScale); AddBinding("AspectRatio", cboAspectRatio); AddBinding("CustomAspectRatio", nudCustomRatio); diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 02546dd9..a187a4be 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -1238,6 +1238,8 @@ namespace Mesen.GUI NsfRepeat = 0x800000000000, NsfShuffle = 0x1000000000000, + IntegerFpsMode = 0x2000000000000, + ForceMaxSpeed = 0x4000000000000000, ConsoleMode = 0x8000000000000000, }