NSF: Allow rewinding in NSF player

This commit is contained in:
Sour 2018-12-26 11:24:08 -05:00
parent 6c27a273b2
commit d6d188282c
22 changed files with 124 additions and 49 deletions

View file

@ -589,7 +589,7 @@ void Console::ResetComponents(bool softReset)
_debugHud->ClearScreen();
_memoryManager->Reset(softReset);
if(!_settings->CheckFlag(EmulationFlags::DisablePpuReset) || !softReset) {
if(!_settings->CheckFlag(EmulationFlags::DisablePpuReset) || !softReset || NsfMapper::GetInstance()) {
_ppu->Reset();
}
_apu->Reset(softReset);

View file

@ -39,7 +39,7 @@ void NsfMapper::InitMapper()
_namcoAudio.reset(new Namco163Audio(_console));
_sunsoftAudio.reset(new Sunsoft5bAudio(_console));
SetCpuMemoryMapping(0x3F00, 0x3FFF, GetWorkRam() + 0x2000, MemoryAccessType::Read);
SetCpuMemoryMapping(0x3F00, 0x3FFF, PrgMemoryType::WorkRam, 0x2000, MemoryAccessType::Read);
memcpy(GetWorkRam() + 0x2000, _nsfBios, 0x100);
//Clear all register settings
@ -92,7 +92,7 @@ void NsfMapper::InitMapper(RomData& romData)
if(_nsfHeader.SoundChips & NsfSoundChips::MMC5) {
AddRegisterRange(0x5000, 0x5015, MemoryOperation::Write); //Registers
AddRegisterRange(0x5205, 0x5206, MemoryOperation::Any); //Multiplication
SetCpuMemoryMapping(0x5C00, 0x5FFF, GetWorkRam() + 0x3000, MemoryAccessType::ReadWrite); //Exram
SetCpuMemoryMapping(0x5C00, 0x5FFF, PrgMemoryType::WorkRam, 0x3000, MemoryAccessType::ReadWrite); //Exram
}
if(_nsfHeader.SoundChips & NsfSoundChips::VRC6) {
@ -477,4 +477,22 @@ NsfHeader NsfMapper::GetNsfHeader()
ConsoleFeatures NsfMapper::GetAvailableFeatures()
{
return ConsoleFeatures::Nsf;
}
void NsfMapper::StreamState(bool saving)
{
BaseMapper::StreamState(saving);
SnapshotInfo mmc5Audio { _mmc5Audio.get() };
SnapshotInfo vrc6Audio { _vrc6Audio.get() };
SnapshotInfo vrc7Audio { _vrc7Audio.get() };
SnapshotInfo fdsAudio { _fdsAudio.get() };
SnapshotInfo namcoAudio { _namcoAudio.get() };
SnapshotInfo sunsoftAudio { _sunsoftAudio.get() };
Stream(
_model, _needInit, _irqEnabled, _irqReloadValue, _irqCounter, _irqStatus, _debugIrqStatus, _mmc5MultiplierValues[0], _mmc5MultiplierValues[1],
_trackEndCounter, _trackFadeCounter, _fadeLength, _silenceDetectDelay, _trackEnded, _allowSilenceDetection, _hasBankSwitching, _ntscSpeed,
_palSpeed, _dendySpeed, _songNumber, mmc5Audio, vrc6Audio, vrc7Audio, fdsAudio, namcoAudio, sunsoftAudio
);
}

View file

@ -106,6 +106,8 @@ protected:
uint32_t GetWorkRamPageSize() override { return 0x1000; }
bool AllowRegisterRead() override { return true; }
void StreamState(bool saving) override;
void InitMapper() override;
void InitMapper(RomData& romData) override;
void Reset(bool softReset) override;

View file

@ -6,8 +6,3 @@
void NsfPpu::DrawPixel()
{
}
void NsfPpu::SendFrame()
{
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::PpuFrameDone);
}

View file

@ -6,7 +6,6 @@ class NsfPpu : public PPU
{
protected:
void DrawPixel() override;
void SendFrame() override;
public:
using PPU::PPU;

View file

@ -203,7 +203,7 @@ void ShortcutKeyHandler::CheckMappedKeys()
}
}
if(!isNetplayClient && !MovieManager::Recording() && !settings->CheckFlag(NsfPlayerEnabled)) {
if(!isNetplayClient && !MovieManager::Recording()) {
shared_ptr<RewindManager> rewindManager = _console->GetRewindManager();
if(rewindManager) {
if(DetectKeyPress(EmulatorShortcut::ToggleRewind)) {

View file

@ -69,6 +69,10 @@
this.tlpRepeatShuffle = new System.Windows.Forms.TableLayoutPanel();
this.picRepeat = new System.Windows.Forms.PictureBox();
this.picShuffle = new System.Windows.Forms.PictureBox();
this.tmrUpdate = new System.Windows.Forms.Timer(this.components);
this.panel4 = new System.Windows.Forms.Panel();
this.lblRewinding = new System.Windows.Forms.Label();
this.lblRewindIcon = new System.Windows.Forms.Label();
this.tlpMain.SuspendLayout();
this.tlpNsfInfo.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
@ -83,6 +87,7 @@
this.tlpRepeatShuffle.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picRepeat)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picShuffle)).BeginInit();
this.panel4.SuspendLayout();
this.SuspendLayout();
//
// tlpMain
@ -514,18 +519,20 @@
//
this.tableLayoutPanel4.ColumnCount = 1;
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Controls.Add(this.panel3, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.panel4, 0, 2);
this.tableLayoutPanel4.Controls.Add(this.panel2, 0, 0);
this.tableLayoutPanel4.Controls.Add(this.panel1, 0, 1);
this.tableLayoutPanel4.Controls.Add(this.panel3, 0, 3);
this.tableLayoutPanel4.Location = new System.Drawing.Point(5, 5);
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
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());
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel4.Size = new System.Drawing.Size(121, 60);
this.tableLayoutPanel4.Size = new System.Drawing.Size(121, 85);
this.tableLayoutPanel4.TabIndex = 13;
//
// panel3
@ -534,7 +541,7 @@
this.panel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.panel3.Controls.Add(this.lblSlowMotion);
this.panel3.Controls.Add(this.lblSlowMotionIcon);
this.panel3.Location = new System.Drawing.Point(0, 36);
this.panel3.Location = new System.Drawing.Point(0, 54);
this.panel3.Margin = new System.Windows.Forms.Padding(0);
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size(79, 18);
@ -629,6 +636,47 @@
this.picShuffle.TabStop = false;
this.picShuffle.Click += new System.EventHandler(this.picShuffle_Click);
//
// tmrUpdate
//
this.tmrUpdate.Enabled = true;
this.tmrUpdate.Interval = 250;
this.tmrUpdate.Tick += new System.EventHandler(this.tmrUpdate_Tick);
//
// panel4
//
this.panel4.AutoSize = true;
this.panel4.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.panel4.Controls.Add(this.lblRewinding);
this.panel4.Controls.Add(this.lblRewindIcon);
this.panel4.Location = new System.Drawing.Point(0, 36);
this.panel4.Margin = new System.Windows.Forms.Padding(0);
this.panel4.Name = "panel4";
this.panel4.Size = new System.Drawing.Size(71, 18);
this.panel4.TabIndex = 3;
//
// lblRewinding
//
this.lblRewinding.AutoSize = true;
this.lblRewinding.ForeColor = System.Drawing.Color.DarkOrange;
this.lblRewinding.Location = new System.Drawing.Point(14, 4);
this.lblRewinding.Margin = new System.Windows.Forms.Padding(0);
this.lblRewinding.Name = "lblRewinding";
this.lblRewinding.Size = new System.Drawing.Size(57, 13);
this.lblRewinding.TabIndex = 11;
this.lblRewinding.Text = "Rewinding";
//
// lblRewindIcon
//
this.lblRewindIcon.AutoSize = true;
this.lblRewindIcon.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblRewindIcon.ForeColor = System.Drawing.Color.DarkOrange;
this.lblRewindIcon.Location = new System.Drawing.Point(0, 0);
this.lblRewindIcon.Margin = new System.Windows.Forms.Padding(0);
this.lblRewindIcon.Name = "lblRewindIcon";
this.lblRewindIcon.Size = new System.Drawing.Size(17, 18);
this.lblRewindIcon.TabIndex = 12;
this.lblRewindIcon.Text = "«";
//
// ctrlNsfPlayer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -662,6 +710,8 @@
this.tlpRepeatShuffle.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.picRepeat)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picShuffle)).EndInit();
this.panel4.ResumeLayout(false);
this.panel4.PerformLayout();
this.ResumeLayout(false);
}
@ -709,5 +759,9 @@
private System.Windows.Forms.PictureBox picShuffle;
private System.Windows.Forms.PictureBox picRepeat;
private System.Windows.Forms.Panel pnlBackground;
private System.Windows.Forms.Timer tmrUpdate;
private System.Windows.Forms.Panel panel4;
private System.Windows.Forms.Label lblRewinding;
private System.Windows.Forms.Label lblRewindIcon;
}
}

View file

@ -15,7 +15,6 @@ namespace Mesen.GUI.Controls
public partial class ctrlNsfPlayer : BaseControl
{
private List<ComboboxItem> _trackList = new List<ComboboxItem>();
private int _frameCount = 0;
private bool _fastForwarding = false;
private UInt32 _originalSpeed = 100;
private bool _disableShortcutKeys = false;
@ -112,31 +111,18 @@ namespace Mesen.GUI.Controls
trkVolume.Value = (int)ConfigManager.Config.AudioInfo.MasterVolume;
}
public void ResetCount()
{
_frameCount = 0;
this.BeginInvoke((MethodInvoker)(() => this.UpdateTimeDisplay(_frameCount)));
}
public void CountFrame()
{
_frameCount++;
if(_frameCount % 30 == 0) {
this.BeginInvoke((MethodInvoker)(() => this.UpdateTimeDisplay(_frameCount)));
}
}
private void UpdateTimeDisplay(int frameCount)
private void UpdateTimeDisplay()
{
if(!InteropEmu.IsNsf()) {
_frameCount = 0;
return;
}
UInt32 elapsedFrames = InteropEmu.NsfGetFrameCount();
NsfHeader header = InteropEmu.NsfGetHeader();
int currentTrack = InteropEmu.NsfGetCurrentTrack();
TimeSpan time = TimeSpan.FromSeconds((double)frameCount / ((header.Flags & 0x01) == 0x01 ? 50.006978 : 60.098812));
TimeSpan time = TimeSpan.FromSeconds((double)elapsedFrames / ((header.Flags & 0x01) == 0x01 ? 50.006978 : 60.098812));
string label = time.ToString(time.TotalHours < 1 ? @"mm\:ss" : @"hh\:mm\:ss");
TimeSpan trackTime = GetTrackLength(header, currentTrack);
@ -150,6 +136,7 @@ namespace Mesen.GUI.Controls
}
lblRecording.Visible = lblRecordingDot.Visible = InteropEmu.WaveIsRecording();
lblRewinding.Visible = lblRewindIcon.Visible = InteropEmu.IsRewinding();
lblFastForward.Visible = lblFastForwardIcon.Visible = InteropEmu.GetEmulationSpeed() > 100 || InteropEmu.GetEmulationSpeed() == 0 || InteropEmu.CheckFlag(EmulationFlags.Turbo);
lblSlowMotion.Visible = lblSlowMotionIcon.Visible = InteropEmu.GetEmulationSpeed() < 100 && InteropEmu.GetEmulationSpeed() > 0 && !InteropEmu.CheckFlag(EmulationFlags.Turbo);
@ -211,6 +198,7 @@ namespace Mesen.GUI.Controls
} else {
if(InteropEmu.IsNsf()) {
UpdateTrackDisplay();
UpdateTimeDisplay();
toolTip.SetToolTip(btnNext, ResourceHelper.GetMessage("NsfNextTrack"));
@ -259,7 +247,6 @@ namespace Mesen.GUI.Controls
newTrack = (InteropEmu.NsfGetCurrentTrack() + 1) % trackCount;
}
InteropEmu.NsfSelectTrack((byte)newTrack);
_frameCount = 0;
}
}
@ -267,7 +254,9 @@ namespace Mesen.GUI.Controls
{
int soundCount = InteropEmu.NsfGetHeader().TotalSongs;
int currentTrack = InteropEmu.NsfGetCurrentTrack();
if(_frameCount < 120) {
UInt32 elapsedFrames = InteropEmu.NsfGetFrameCount();
if(elapsedFrames < 120) {
//Reload current track if it has been playing for more than 2 seconds
currentTrack--;
if(currentTrack < 0) {
@ -275,7 +264,6 @@ namespace Mesen.GUI.Controls
}
}
InteropEmu.NsfSelectTrack((byte)currentTrack);
_frameCount = 0;
}
private void trkVolume_ValueChanged(object sender, EventArgs e)
@ -405,7 +393,6 @@ namespace Mesen.GUI.Controls
int currentTrack = InteropEmu.NsfGetCurrentTrack();
if(currentTrack != cboTrack.SelectedIndex) {
InteropEmu.NsfSelectTrack((byte)cboTrack.SelectedIndex);
_frameCount = 0;
}
}
@ -436,6 +423,11 @@ namespace Mesen.GUI.Controls
this.tlpNsfInfo.MouseMove -= value;
}
}
private void tmrUpdate_Tick(object sender, EventArgs e)
{
UpdateTimeDisplay();
}
}
public class ComboboxItem

View file

@ -123,4 +123,7 @@
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>154, 17</value>
</metadata>
<metadata name="tmrUpdate.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>244, 17</value>
</metadata>
</root>

View file

@ -115,6 +115,7 @@
<Control ID="lblSoundChips">Xip de so</Control>
<Control ID="lblRecording">REC</Control>
<Control ID="lblSlowMotion">Càmera lenta</Control>
<Control ID="lblRewinding">Rewinding</Control>
<Control ID="lblFastForward">Avanç ràpid</Control>
</Form>
<Form ID="frmLogWindow" Title="Finestra del registre">

View file

@ -115,6 +115,7 @@
<Control ID="lblSoundChips">Sound Chips:</Control>
<Control ID="lblRecording">REC</Control>
<Control ID="lblSlowMotion">Slow Motion</Control>
<Control ID="lblRewinding">Rewinding</Control>
<Control ID="lblFastForward">Fast Forward</Control>
</Form>
<Form ID="frmLogWindow" Title="Log Window">

View file

@ -114,6 +114,7 @@
<Control ID="lblSoundChips">Chip de audio</Control>
<Control ID="lblRecording">REC</Control>
<Control ID="lblSlowMotion">Cámara lenta</Control>
<Control ID="lblRewinding">Rewinding</Control>
<Control ID="lblFastForward">Avance rápido</Control>
</Form>
<Form ID="frmLogWindow" Title="Ventana del registro">

View file

@ -115,6 +115,7 @@
<Control ID="lblSoundChips">Puces audio</Control>
<Control ID="lblRecording">ENR</Control>
<Control ID="lblSlowMotion">Ralenti</Control>
<Control ID="lblRewinding">Rembobinage</Control>
<Control ID="lblFastForward">Avance rapide</Control>
</Form>
<Form ID="frmLogWindow" Title="Fenêtre de log">

View file

@ -116,6 +116,7 @@
<Control ID="lblSoundChips">音源チップ</Control>
<Control ID="lblRecording">録音中</Control>
<Control ID="lblSlowMotion">スローモーション</Control>
<Control ID="lblRewinding">巻き戻し</Control>
<Control ID="lblFastForward">早送り</Control>
</Form>
<Form ID="frmLogWindow" Title="ログウィンドウ">

View file

@ -115,6 +115,7 @@
<Control ID="lblSoundChips">Chip de áudio</Control>
<Control ID="lblRecording">REC</Control>
<Control ID="lblSlowMotion">Câmera lenta</Control>
<Control ID="lblRewinding">Rewinding</Control>
<Control ID="lblFastForward">Acelerar</Control>
</Form>
<Form ID="frmLogWindow" Title="Janela de relatório">

View file

@ -114,6 +114,7 @@
<Control ID="lblSoundChips">Звуковые чипы</Control>
<Control ID="lblRecording">REC</Control>
<Control ID="lblSlowMotion">Slow Motion</Control>
<Control ID="lblRewinding">Rewinding</Control>
<Control ID="lblFastForward">Fast Forward</Control>
</Form>
<Form ID="frmLogWindow" Title="Лог">

View file

@ -114,6 +114,7 @@
<Control ID="lblSoundChips">Звукові чіпи</Control>
<Control ID="lblRecording">REC</Control>
<Control ID="lblSlowMotion">Сповільнений Рух</Control>
<Control ID="lblRewinding">Rewinding</Control>
<Control ID="lblFastForward">Перемотування Вперед</Control>
</Form>
<Form ID="frmLogWindow" Title="Лог">

View file

@ -118,6 +118,7 @@
<Control ID="lblSoundChips">声音芯片:</Control>
<Control ID="lblRecording">正在录音</Control>
<Control ID="lblSlowMotion">慢放</Control>
<Control ID="lblRewinding">Rewinding</Control>
<Control ID="lblFastForward">快进</Control>
</Form>
<Form ID="frmLogWindow" Title="日志窗口">

View file

@ -137,7 +137,7 @@ namespace Mesen.GUI.Forms
ResourceHelper.UpdateEmuLanguage();
ResourceHelper.ApplyResources(this);
UpdateMenus();
InitializeNsfMode(true);
InitializeNsfMode();
ctrlRecentGames.UpdateGameInfo();
TopMost = ConfigManager.Config.PreferenceInfo.AlwaysOnTop;
FormBorderStyle = ConfigManager.Config.PreferenceInfo.DisableMouseResize ? FormBorderStyle.Fixed3D : FormBorderStyle.Sizable;

View file

@ -638,7 +638,7 @@ namespace Mesen.GUI.Forms
VideoInfo.ApplyOverscanConfig();
_currentGame = InteropEmu.GetRomInfo().GetRomName();
InteropEmu.SetNesModel(ConfigManager.Config.Region);
InitializeNsfMode(false, true);
InitializeNsfMode(true);
CheatInfo.ApplyCheats();
GameSpecificInfo.ApplyGameSpecificConfig();
UpdateStateMenu(mnuSaveState, true);
@ -661,12 +661,6 @@ namespace Mesen.GUI.Forms
});
break;
case InteropEmu.ConsoleNotificationType.PpuFrameDone:
if(InteropEmu.IsNsf()) {
this.ctrlNsfPlayer.CountFrame();
}
break;
case InteropEmu.ConsoleNotificationType.GameReset:
InitializeNsfMode();
break;
@ -1386,7 +1380,7 @@ namespace Mesen.GUI.Forms
}
}
private void InitializeNsfMode(bool updateTextOnly = false, bool gameLoaded = false)
private void InitializeNsfMode(bool gameLoaded = false)
{
if(this.InvokeRequired) {
if(InteropEmu.IsNsf()) {
@ -1397,7 +1391,7 @@ namespace Mesen.GUI.Forms
InteropEmu.StopServer();
}
}
this.BeginInvoke((MethodInvoker)(() => this.InitializeNsfMode(updateTextOnly, gameLoaded)));
this.BeginInvoke((MethodInvoker)(() => this.InitializeNsfMode(gameLoaded)));
} else {
if(InteropEmu.IsNsf()) {
this.SetFullscreenState(false);
@ -1415,9 +1409,6 @@ namespace Mesen.GUI.Forms
}
this._isNsfPlayerMode = true;
this.ctrlNsfPlayer.UpdateText();
if(!updateTextOnly) {
this.ctrlNsfPlayer.ResetCount();
}
this.ctrlNsfPlayer.Visible = true;
this.ctrlNsfPlayer.Focus();

View file

@ -146,6 +146,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsNsf();
[DllImport(DLLPath)] public static extern void NsfSelectTrack(Byte trackNumber);
[DllImport(DLLPath)] public static extern Int32 NsfGetCurrentTrack();
[DllImport(DLLPath)] public static extern UInt32 NsfGetFrameCount();
[DllImport(DLLPath, EntryPoint = "NsfGetHeader")] private static extern void NsfGetHeaderWrapper(out NsfHeader header);
[DllImport(DLLPath)] public static extern void NsfSetNsfConfig(Int32 autoDetectSilenceDelay, Int32 moveToNextTrackTime, [MarshalAs(UnmanagedType.I1)]bool disableApuIrqs);
@ -195,6 +196,7 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern UInt32 GetEmulationSpeed();
[DllImport(DLLPath)] public static extern void SetTurboRewindSpeed(UInt32 turboSpeed, UInt32 rewindSpeed);
[DllImport(DLLPath)] public static extern void SetRewindBufferSize(UInt32 seconds);
[DllImport(DLLPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsRewinding();
[DllImport(DLLPath)] public static extern void SetOverclockRate(UInt32 overclockRate, [MarshalAs(UnmanagedType.I1)]bool adjustApu);
[DllImport(DLLPath)] public static extern void SetPpuNmiConfig(UInt32 extraScanlinesBeforeNmi, UInt32 extraScanlineAfterNmi);
[DllImport(DLLPath)] public static extern void SetOverscanDimensions(UInt32 left, UInt32 right, UInt32 top, UInt32 bottom);

View file

@ -629,6 +629,10 @@ namespace InteropEmu {
DllExport uint32_t __stdcall GetEmulationSpeed() { return _settings->GetEmulationSpeed(true); }
DllExport void __stdcall SetTurboRewindSpeed(uint32_t turboSpeed, uint32_t rewindSpeed) { _settings->SetTurboRewindSpeed(turboSpeed, rewindSpeed); }
DllExport void __stdcall SetRewindBufferSize(uint32_t seconds) { _settings->SetRewindBufferSize(seconds); }
DllExport bool __stdcall IsRewinding() {
shared_ptr<RewindManager> rewindManager = _console->GetRewindManager();
return rewindManager ? rewindManager->IsRewinding() : false;
}
DllExport void __stdcall SetOverclockRate(uint32_t overclockRate, bool adjustApu) { _settings->SetOverclockRate(overclockRate, adjustApu); }
DllExport void __stdcall SetPpuNmiConfig(uint32_t extraScanlinesBeforeNmi, uint32_t extraScanlinesAfterNmi) { _settings->SetPpuNmiConfig(extraScanlinesBeforeNmi, extraScanlinesAfterNmi); }
DllExport void __stdcall SetVideoScale(double scale, ConsoleId consoleId) { GetConsoleById(consoleId)->GetSettings()->SetVideoScale(scale); }
@ -667,6 +671,12 @@ namespace InteropEmu {
//NSF functions
DllExport bool __stdcall IsNsf() { return NsfMapper::GetInstance() != nullptr; }
DllExport uint32_t __stdcall NsfGetFrameCount() {
if(NsfMapper::GetInstance()) {
return _console->GetPpu()->GetFrameCount();
}
return 0;
}
DllExport void __stdcall NsfSelectTrack(uint8_t trackNumber) {
if(NsfMapper::GetInstance()) {
NsfMapper::GetInstance()->SelectTrack(trackNumber);