diff --git a/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs b/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs index b11b63f292..b03586b41b 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs @@ -46,14 +46,21 @@ namespace BizHawk.Emulation.Cores.Computers.MSX /// Get Video data /// /// opaque state pointer - /// controller data for player 1 - /// controller data for player 2 - /// length of romdata in bytes - /// Mapper number to load core with - /// 0 on success, negative value on failure. + /// where to send video to [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void MSX_get_video(IntPtr core, int[] videobuf); + /// + /// Get Video data + /// + /// opaque state pointer + /// where to send left audio to + /// where to send right audio to + /// number of left samples + /// number of right samples + [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern uint MSX_get_audio(IntPtr core, uint[] aud_buf_L, uint[] aud_buf_R, ref uint n_samp_L, ref uint n_samp_R); + #endregion #region Memory Domain Functions diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs index dcf2e50b35..be091dfe4b 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs @@ -15,9 +15,6 @@ namespace BizHawk.Emulation.Cores.Computers.MSX } } - // not savestated variables - int s_L, s_R; - public bool FrameAdvance(IController controller, bool render, bool rendersound) { _controller = controller; @@ -78,13 +75,14 @@ namespace BizHawk.Emulation.Cores.Computers.MSX #region Audio - public BlipBuffer blip_L = new BlipBuffer(4096); - public BlipBuffer blip_R = new BlipBuffer(4096); - const int blipbuffsize = 4096; + public BlipBuffer blip_L = new BlipBuffer(4500); + public BlipBuffer blip_R = new BlipBuffer(4500); - public uint sampleclock; - public int old_s_L = 0; - public int old_s_R = 0; + public uint[] Aud_L = new uint [9000]; + public uint[] Aud_R = new uint[9000]; + public uint num_samp_L, num_samp_R; + + const int blipbuffsize = 4500; public bool CanProvideAsync { get { return false; } } @@ -108,23 +106,32 @@ namespace BizHawk.Emulation.Cores.Computers.MSX public void GetSamplesSync(out short[] samples, out int nsamp) { - blip_L.EndFrame(sampleclock); - blip_R.EndFrame(sampleclock); + uint f_clock = LibMSX.MSX_get_audio(MSX_Pntr, Aud_L, Aud_R, ref num_samp_L, ref num_samp_R); + + for (int i = 0; i < num_samp_L;i++) + { + blip_L.AddDelta(Aud_L[i * 2], (int)Aud_L[i * 2 + 1]); + } + + for (int i = 0; i < num_samp_R; i++) + { + blip_R.AddDelta(Aud_R[i * 2], (int)Aud_R[i * 2 + 1]); + } + + blip_L.EndFrame(f_clock); + blip_R.EndFrame(f_clock); nsamp = Math.Max(Math.Max(blip_L.SamplesAvailable(), blip_R.SamplesAvailable()), 1); samples = new short[nsamp * 2]; blip_L.ReadSamplesLeft(samples, nsamp); blip_R.ReadSamplesRight(samples, nsamp); - - sampleclock = 0; } public void DiscardSamples() { blip_L.Clear(); blip_R.Clear(); - sampleclock = 0; } #endregion diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs index 463167b7ad..06a3f664b0 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IStatable.cs @@ -50,10 +50,6 @@ namespace BizHawk.Emulation.Cores.Computers.MSX ser.BeginSection("MSX"); - ser.Sync(nameof(sampleclock), ref sampleclock); - ser.Sync(nameof(old_s_L), ref old_s_L); - ser.Sync(nameof(old_s_R), ref old_s_R); - if (SaveRAM != null) { ser.Sync(nameof(SaveRAM), ref SaveRAM, false); diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs index 74e64e6089..83216bbd44 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.cs @@ -10,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX isPorted: false, isReleased: false)] [ServiceNotApplicable(typeof(IDriveLight))] - public partial class MSX : IEmulator, IVideoProvider, ISaveRam, IStatable, IInputPollable, IRegionable, ISettable + public partial class MSX : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable, IRegionable, ISettable { [CoreConstructor("MSX")] public MSX(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) @@ -46,8 +46,6 @@ namespace BizHawk.Emulation.Cores.Computers.MSX StringBuilder new_header = new StringBuilder(Header_Length); LibMSX.MSX_getheader(MSX_Pntr, new_header, Header_Length); - - Console.WriteLine(Header_Length + " " + Disasm_Length + " " + Reg_String_Length); Tracer = new TraceBuffer { Header = new_header.ToString() }; diff --git a/libHawk/MSXHawk/MSXHawk/Core.h b/libHawk/MSXHawk/MSXHawk/Core.h index d590d9377b..8a4d4ecaec 100644 --- a/libHawk/MSXHawk/MSXHawk/Core.h +++ b/libHawk/MSXHawk/MSXHawk/Core.h @@ -41,6 +41,11 @@ namespace MSXHawk int scanlinesPerFrame = 262; vdp.SpriteLimit = true; + + psg.num_samples_L = 0; + psg.num_samples_R = 0; + psg.sampleclock = 0; + for (int i = 0; i < scanlinesPerFrame; i++) { vdp.ScanLine = i; @@ -55,24 +60,6 @@ namespace MSXHawk cpu.ExecuteOne(); psg.generate_sound(); - /* - s_L = psg.current_sample_L; - s_R = psg.current_sample_R; - - if (s_L != old_s_L) - { - blip_L.AddDelta(sampleclock, s_L - old_s_L); - old_s_L = s_L; - } - - if (s_R != old_s_R) - { - blip_R.AddDelta(sampleclock, s_R - old_s_R); - old_s_R = s_R; - } - - sampleclock++; - */ } if (vdp.ScanLine == scanlinesPerFrame - 1) @@ -81,11 +68,7 @@ namespace MSXHawk //vdp.ProcessOverscan(); } } - /* - while (cpu.TotalExecutedCycles < 211936) { - cpu.ExecuteOne(); - } - */ + return MemMap.lagged; } @@ -101,6 +84,23 @@ namespace MSXHawk } } + uint32_t GetAudio(uint32_t* dest_L, uint32_t* dest_R, uint32_t* n_samp_L, uint32_t* n_samp_R) + { + uint32_t* src_L = psg.samples_L; + uint32_t* dst_L = dest_L; + + std::memcpy(dst_L, src_L, sizeof uint32_t * psg.num_samples_L * 2); + n_samp_L[0] = psg.num_samples_L; + + uint32_t* src_R = psg.samples_R; + uint32_t* dst_R = dest_R; + + std::memcpy(dst_R, src_R, sizeof uint32_t * psg.num_samples_R * 2); + n_samp_R[0] = psg.num_samples_R; + + return psg.sampleclock; + } + #pragma region Memory Domain Functions uint8_t GetSysBus(uint32_t addr) diff --git a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp index 6d9cb22c9e..8480c4f676 100644 --- a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp +++ b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp @@ -42,10 +42,12 @@ MSXHAWK_EXPORT void MSX_get_video(MSXCore* p, uint32_t* dest) p->GetVideo(dest); } -// set tracer callback -MSXHAWK_EXPORT void MSX_settracecallback(MSXCore* p, void (*callback)(int)) { - p->SetTraceCallback(callback); +// send audio data to external audio provider +MSXHAWK_EXPORT uint32_t MSX_get_audio(MSXCore* p, uint32_t* dest_L, uint32_t* dest_R, uint32_t* n_samp_L, uint32_t* n_samp_R) +{ + return p->GetAudio(dest_L, dest_R, n_samp_L, n_samp_R); } + #pragma endregion #pragma region Memory Domain Functions @@ -62,6 +64,11 @@ MSXHAWK_EXPORT uint8_t MSX_getvram(MSXCore* p, uint32_t addr) { #pragma region Tracer +// set tracer callback +MSXHAWK_EXPORT void MSX_settracecallback(MSXCore* p, void (*callback)(int)) { + p->SetTraceCallback(callback); +} + // return the cpu trace header length MSXHAWK_EXPORT int MSX_getheaderlength(MSXCore* p) { return p->GetHeaderLength(); diff --git a/libHawk/MSXHawk/MSXHawk/PSG.h b/libHawk/MSXHawk/MSXHawk/PSG.h index c0c6f5fc30..9dbedcef63 100644 --- a/libHawk/MSXHawk/MSXHawk/PSG.h +++ b/libHawk/MSXHawk/MSXHawk/PSG.h @@ -12,6 +12,13 @@ namespace MSXHawk public: uint32_t current_sample_L; uint32_t current_sample_R; + uint32_t old_sample_L; + uint32_t old_sample_R; + uint32_t sampleclock; + uint32_t num_samples_L; + uint32_t num_samples_R; + uint32_t samples_L[9000] = {}; + uint32_t samples_R[9000] = {}; SN76489sms() { @@ -256,7 +263,25 @@ namespace MSXHawk current_sample_R += (C_R ? (C_up ? LogScale[Chan_vol[2]] * 42 : 0) : 0); current_sample_R += (noise_R ? (noise_bit ? LogScale[Chan_vol[3]] * 42 : 0) : 0); + + if ((current_sample_L != old_sample_L) && (num_samples_L < 4500)) + { + samples_L[num_samples_L * 2] = sampleclock; + samples_L[num_samples_L * 2 + 1] = current_sample_L - old_sample_L; + num_samples_L++; + old_sample_L = current_sample_L; + } + + if ((current_sample_R != old_sample_R) && (num_samples_R < 4500)) + { + samples_R[num_samples_R * 2] = sampleclock; + samples_R[num_samples_R * 2 + 1] = current_sample_R - old_sample_R; + num_samples_R++; + old_sample_R = current_sample_R; + } } + + sampleclock++; } }; } \ No newline at end of file