From 90d9474530f13d9cd93172e445a3551867d4c514 Mon Sep 17 00:00:00 2001 From: nattthebear Date: Wed, 7 Jun 2017 18:56:44 -0400 Subject: [PATCH] Saturnus: Lag detection and input callbacks --- .../Consoles/Sega/Saturn/LibSaturnus.cs | 8 +++++++- .../Consoles/Sega/Saturn/Saturnus.cs | 13 ++++++++++++- waterbox/ss/bizhawk.cpp | 13 +++++++++++-- waterbox/ss/defs.h | 5 +++-- waterbox/ss/smpc.cpp | 5 +++++ waterbox/ss/ss.cpp | 3 +-- 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/LibSaturnus.cs b/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/LibSaturnus.cs index df9f6e25e1..aa7b73b53d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/LibSaturnus.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/LibSaturnus.cs @@ -56,7 +56,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn [FieldOffset(44)] public int Height; [FieldOffset(48)] - public int ResetPushed; + public short ResetPushed; + [FieldOffset(50)] + public short InputLagged; }; [UnmanagedFunctionPointer(CC)] @@ -67,6 +69,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn public delegate void CDTOCCallback(int disk, [In, Out]TOC toc); [UnmanagedFunctionPointer(CC)] public delegate void CDSectorCallback(int disk, int lba, IntPtr dest); + [UnmanagedFunctionPointer(CC)] + public delegate void InputCallback(); [BizImport(CC)] public abstract void SetFirmwareCallbacks(FirmwareSizeCallback sizecallback, FirmwareDataCallback datacallback); @@ -82,5 +86,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn public abstract void FrameAdvance([In, Out]FrameAdvanceInfo f); [BizImport(CC)] public abstract void SetupInput(int[] portdevices, int[] multitaps); + [BizImport(CC)] + public abstract void SetInputCallback(InputCallback callback); } } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs b/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs index ee2d55b613..cb6fc9e57f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/Saturn/Saturnus.cs @@ -101,6 +101,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn DriveLightOn = false; if (controller.IsPressed("Power")) _core.HardReset(); + SetInputCallback(); fixed (short* _sp = _soundBuffer) fixed (int* _vp = _videoBuffer) @@ -112,11 +113,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn SoundBufMaxSize = _soundBuffer.Length / 2, Pixels = (IntPtr)_vp, Controllers = (IntPtr)_cp, - ResetPushed = controller.IsPressed("Reset") ? 1 : 0 + ResetPushed = (short)(controller.IsPressed("Reset") ? 1 : 0) }; _core.FrameAdvance(info); Frame++; + IsLagFrame = info.InputLagged != 0; + if (IsLagFrame) + LagCount++; _numSamples = info.SoundBufSize; BufferWidth = info.Width; BufferHeight = info.Height; @@ -158,6 +162,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn private LibSaturnus.FirmwareDataCallback _firmwareDataCallback; private LibSaturnus.CDTOCCallback _cdTocCallback; private LibSaturnus.CDSectorCallback _cdSectorCallback; + private LibSaturnus.InputCallback _inputCallback; private void InitCallbacks() { @@ -165,6 +170,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn _firmwareDataCallback = FirmwareData; _cdTocCallback = CDTOCCallback; _cdSectorCallback = CDSectorCallback; + _inputCallback = InputCallbacks.Call; } private void SetFirmwareCallbacks() @@ -175,10 +181,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn { _core.SetCDCallbacks(_cdTocCallback, _cdSectorCallback); } + private void SetInputCallback() + { + _core.SetInputCallback(InputCallbacks.Count > 0 ? _inputCallback : null); + } private void ClearAllCallbacks() { _core.SetFirmwareCallbacks(null, null); _core.SetCDCallbacks(null, null); + _core.SetInputCallback(null); } private string TranslateFirmwareName(string filename) diff --git a/waterbox/ss/bizhawk.cpp b/waterbox/ss/bizhawk.cpp index 77166e3c83..0c2ec1531a 100644 --- a/waterbox/ss/bizhawk.cpp +++ b/waterbox/ss/bizhawk.cpp @@ -154,7 +154,8 @@ struct FrameAdvanceInfo int32 Width; int32 Height; - int32 ResetPushed; + int16 ResetPushed; + int16 InputLagged; // Set by the system emulation code every frame, to denote the horizontal and vertical offsets of the image, and the size // of the image. If the emulated system sets the elements of LineWidths, then the width(w) of this structure @@ -169,6 +170,7 @@ struct FrameAdvanceInfo }; static uint8 ControllerInput[12 * 32]; +bool InputLagged; EXPORT void FrameAdvance(FrameAdvanceInfo &f) { @@ -182,10 +184,11 @@ EXPORT void FrameAdvance(FrameAdvanceInfo &f) e.SoundBufMaxSize = f.SoundBufMaxSize; memcpy(ControllerInput, f.Controllers, sizeof(ControllerInput)); IsResetPushed = f.ResetPushed; - + InputLagged = true; Emulate(&e); f.SoundBufSize = e.SoundBufSize; f.MasterCycles = e.MasterCycles; + f.InputLagged = InputLagged; int w = 256; for (int i = 0; i < e.h; i++) @@ -225,6 +228,12 @@ EXPORT void SetupInput(const int* portdevices, const int* multitaps) SMPC_SetInput(i, DeviceNames[portdevices[i]], ControllerInput + i * 32); } +void (*InputCallback)(); +EXPORT void SetInputCallback(void (*callback)()) +{ + InputCallback = callback; +} + // if (BackupRAM_Dirty)SaveBackupRAM(); // if (CART_GetClearNVDirty())SaveCartNV(); diff --git a/waterbox/ss/defs.h b/waterbox/ss/defs.h index 44b283aa49..2e0b5ca6ce 100644 --- a/waterbox/ss/defs.h +++ b/waterbox/ss/defs.h @@ -315,5 +315,6 @@ extern bool setting_ss_correct_aspect; extern bool setting_ss_h_overscan; extern bool setting_ss_h_blend; extern bool setting_ss_region_autodetect; -extern bool setting_ss_input_sport1_multitap; -extern bool setting_ss_input_sport0_multitap; + +extern bool InputLagged; +extern void (*InputCallback)(); diff --git a/waterbox/ss/smpc.cpp b/waterbox/ss/smpc.cpp index 1a6de88e1b..b61874b380 100644 --- a/waterbox/ss/smpc.cpp +++ b/waterbox/ss/smpc.cpp @@ -989,6 +989,11 @@ sscpu_timestamp_t SMPC_Update(sscpu_timestamp_t timestamp) if(IREG[1] & 0x8) { + InputLagged = false; + if (InputCallback) + InputCallback(); + + #define JR_WAIT(cond) { SMPC_WAIT_UNTIL_COND((cond) || PendingVB); if(PendingVB) { SS_DBGTI(SS_DBG_SMPC, "[SMPC] abortjr wait"); goto AbortJR; } } #define JR_EAT(n) { SMPC_EAT_CLOCKS(n); if(PendingVB) { SS_DBGTI(SS_DBG_SMPC, "[SMPC] abortjr eat"); goto AbortJR; } } #define JR_WRNYB(val) \ diff --git a/waterbox/ss/ss.cpp b/waterbox/ss/ss.cpp index b284968f85..13ee8bcc11 100644 --- a/waterbox/ss/ss.cpp +++ b/waterbox/ss/ss.cpp @@ -1018,8 +1018,7 @@ static bool MDFN_COLD InitCommon(const unsigned cart_type, const unsigned smpc_a MDFN_printf("\n"); for (unsigned sp = 0; sp < 2; sp++) { - bool sv = sp ? setting_ss_input_sport1_multitap : setting_ss_input_sport0_multitap; - SMPC_SetMultitap(sp, sv); + SMPC_SetMultitap(sp, false); MDFN_printf(_("Multitap on Saturn Port %u: %s\n"), sp + 1, sv ? _("Enabled") : _("Disabled")); }