diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs index f2202adf2e..e4a99ba946 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/LibLynx.cs @@ -22,6 +22,20 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx public static extern void Reset(IntPtr s); [DllImport(dllname, CallingConvention = cc)] - public static extern void Advance(IntPtr s, int buttons, int[] vbuff, short[] sbuff, ref int sbuffsize); + public static extern void Advance(IntPtr s, Buttons buttons, int[] vbuff, short[] sbuff, ref int sbuffsize); + + [Flags] + public enum Buttons : ushort + { + Up = 0x0080, + Down = 0x0040, + Left = 0x0010, + Right = 0x0020, + Option_1 = 0x008, + Option_2 = 0x004, + B = 0x002, + A = 0x001, + Pause = 0x100, + } } } diff --git a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs index a4d5f84d13..9188271150 100644 --- a/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs +++ b/BizHawk.Emulation.Cores/Consoles/Atari/lynx/Lynx.cs @@ -80,10 +80,12 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx case 0x80000: pagesize0 = 0x800; break; case 0x30000: pagesize0 = 0x200; pagesize1 = 0x100; break; + case 0x50000: pagesize0 = 0x400; pagesize1 = 0x100; break; case 0x60000: pagesize0 = 0x400; pagesize1 = 0x200; break; + case 0x90000: pagesize0 = 0x800; pagesize1 = 0x100; break; + case 0xa0000: pagesize0 = 0x800; pagesize1 = 0x200; break; case 0xc0000: pagesize0 = 0x800; pagesize1 = 0x400; break; case 0x100000: pagesize0 = 0x800; pagesize1 = 0x800; break; - } Console.WriteLine("Auto-guessed banking options {0} {1}", pagesize0, pagesize1); } @@ -91,7 +93,8 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx Core = LibLynx.Create(realfile, realfile.Length, bios, bios.Length, pagesize0, pagesize1, false); try { - // ... + CoreComm.VsyncNum = 16000000; // 16.00 mhz refclock + CoreComm.VsyncDen = 16 * 105 * 159; } catch { @@ -103,14 +106,12 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx public void FrameAdvance(bool render, bool rendersound = true) { Frame++; - if (Controller["Power"]) LibLynx.Reset(Core); int samples = soundbuff.Length; - LibLynx.Advance(Core, 0, videobuff, soundbuff, ref samples); - numsamp = samples; - Console.WriteLine(numsamp); + LibLynx.Advance(Core, GetButtons(), videobuff, soundbuff, ref samples); + numsamp = samples / 2; // sound provider wants number of sample pairs } public int Frame { get; private set; } @@ -156,9 +157,31 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx #region Controller - public ControllerDefinition ControllerDefinition { get { return NullEmulator.NullController; } } + private static readonly ControllerDefinition LynxTroller = new ControllerDefinition + { + Name = "Lynx Controller", + BoolButtons = { "Up", "Down", "Left", "Right", "A", "B", "Option 1", "Option 2", "Pause", "Power" }, + }; + + public ControllerDefinition ControllerDefinition { get { return LynxTroller; } } public IController Controller { get; set; } + LibLynx.Buttons GetButtons() + { + LibLynx.Buttons ret = 0; + if (Controller["A"]) ret |= LibLynx.Buttons.A; + if (Controller["B"]) ret |= LibLynx.Buttons.B; + if (Controller["Up"]) ret |= LibLynx.Buttons.Up; + if (Controller["Down"]) ret |= LibLynx.Buttons.Down; + if (Controller["Left"]) ret |= LibLynx.Buttons.Left; + if (Controller["Right"]) ret |= LibLynx.Buttons.Right; + if (Controller["Pause"]) ret |= LibLynx.Buttons.Pause; + if (Controller["Option 1"]) ret |= LibLynx.Buttons.Option_1; + if (Controller["Option 2"]) ret |= LibLynx.Buttons.Option_2; + + return ret; + } + #endregion #region savestates @@ -239,7 +262,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx #region SoundProvider - short[] soundbuff = new short[1000000]; // todo: make this smaller once frame loop is resolved + short[] soundbuff = new short[2048]; int numsamp; public ISoundProvider SoundProvider { get { return null; } } diff --git a/lynx/mikie.cpp b/lynx/mikie.cpp index ffa710a07c..a56d9b93f1 100644 --- a/lynx/mikie.cpp +++ b/lynx/mikie.cpp @@ -406,7 +406,6 @@ uint32 CMikie::DisplayRenderLine() { uint32 work_done=0; - if(!mpDisplayCurrent) return 0; if(!mDISPCTL_DMAEnable) return 0; // if(mLynxLine&0x80000000) return 0; diff --git a/lynx/system.cpp b/lynx/system.cpp index e8ba339ed4..833806806d 100644 --- a/lynx/system.cpp +++ b/lynx/system.cpp @@ -158,27 +158,31 @@ void CSystem::Advance(int buttons, uint32 *vbuff, int16 *sbuff, int &sbuffsize) // this check needs to occur at least once every 250 million cycles or better mMikie->CheckWrap(); - SetButtonData(buttons); uint32 start = gSystemCycleCount; + // nominal timer values are div16 for prescalar, 158 for line timer, and 104 for frame timer + // reloads are actually +1 due to the way the hardware works + // so this is a frame, theoretically + uint32 target = gSystemCycleCount + 16 * 105 * 159 - frameoverflow; + // audio start frame mMikie->startTS = start; mMikie->mpDisplayCurrent = vbuff; - // go to next frame end, or no more than 200,000 cycles to avoid exploding the output buffer (was set at 60ms limit) - while (mMikie->mpDisplayCurrent && gSystemCycleCount - start < 200000) - // while (gSystemCycleCount - start < 700000) // what's the magic significance? + while (gSystemCycleCount < target) + //while (mMikie->mpDisplayCurrent && gSystemCycleCount - start < 800000) { - Update(); + Update(target); } // total cycles executed is now gSystemCycleCount - start - mMikie->mikbuf.end_frame((gSystemCycleCount - start) >> 2); - sbuffsize = mMikie->mikbuf.read_samples(sbuff, sbuffsize) / 2; + frameoverflow = gSystemCycleCount - target; + mMikie->mikbuf.end_frame((gSystemCycleCount - start) >> 2); + sbuffsize = mMikie->mikbuf.read_samples(sbuff, sbuffsize); } diff --git a/lynx/system.h b/lynx/system.h index a3ce564eca..5e4e5a8989 100644 --- a/lynx/system.h +++ b/lynx/system.h @@ -121,10 +121,10 @@ public: public: void Reset() MDFN_COLD; - inline void Update() + inline void Update(uint32 targetclock) { // Only update if there is a predicted timer event - if(gSystemCycleCount>=gNextTimerEvent) + if(gSystemCycleCount >= gNextTimerEvent) { mMikie->Update(); } @@ -135,7 +135,7 @@ public: // If the CPU is asleep then skip to the next timer event if(gSystemCPUSleep) { - gSystemCycleCount=gNextTimerEvent; + gSystemCycleCount = std::min(gNextTimerEvent, targetclock); } } @@ -192,11 +192,9 @@ public: // Miscellaneous void SetButtonData(uint32 data) {mSusie->SetButtonData(data);}; uint32 GetButtonData() {return mSusie->GetButtonData();}; - void SetCycleBreakpoint(uint32 breakpoint) {mCycleCountBreakpoint=breakpoint;}; uint8* GetRamPointer() {return mRam->GetRamPointer();}; public: - uint32 mCycleCountBreakpoint; CLynxBase *mMemoryHandlers[SYSTEM_SIZE]; CCart *mCart; CRom *mRom; @@ -210,11 +208,13 @@ public: uint32 gSuzieDoneTime; uint32 gSystemCycleCount; uint32 gNextTimerEvent; - //uint32 gCPUBootAddress; uint32 gSystemIRQ; uint32 gSystemNMI; uint32 gSystemCPUSleep; uint32 gSystemHalt; + + // frame overflow detection + int frameoverflow; }; #endif diff --git a/output/dll/bizlynx.dll b/output/dll/bizlynx.dll index 517969ff97..853ba30faf 100644 Binary files a/output/dll/bizlynx.dll and b/output/dll/bizlynx.dll differ