lynx: controllers and frame timing fix
This commit is contained in:
parent
dec35ed67c
commit
bacbaa2bec
|
@ -22,6 +22,20 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||||
public static extern void Reset(IntPtr s);
|
public static extern void Reset(IntPtr s);
|
||||||
|
|
||||||
[DllImport(dllname, CallingConvention = cc)]
|
[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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,10 +80,12 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||||
case 0x80000: pagesize0 = 0x800; break;
|
case 0x80000: pagesize0 = 0x800; break;
|
||||||
|
|
||||||
case 0x30000: pagesize0 = 0x200; pagesize1 = 0x100; break;
|
case 0x30000: pagesize0 = 0x200; pagesize1 = 0x100; break;
|
||||||
|
case 0x50000: pagesize0 = 0x400; pagesize1 = 0x100; break;
|
||||||
case 0x60000: pagesize0 = 0x400; pagesize1 = 0x200; 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 0xc0000: pagesize0 = 0x800; pagesize1 = 0x400; break;
|
||||||
case 0x100000: pagesize0 = 0x800; pagesize1 = 0x800; break;
|
case 0x100000: pagesize0 = 0x800; pagesize1 = 0x800; break;
|
||||||
|
|
||||||
}
|
}
|
||||||
Console.WriteLine("Auto-guessed banking options {0} {1}", pagesize0, pagesize1);
|
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);
|
Core = LibLynx.Create(realfile, realfile.Length, bios, bios.Length, pagesize0, pagesize1, false);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// ...
|
CoreComm.VsyncNum = 16000000; // 16.00 mhz refclock
|
||||||
|
CoreComm.VsyncDen = 16 * 105 * 159;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -103,14 +106,12 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||||
public void FrameAdvance(bool render, bool rendersound = true)
|
public void FrameAdvance(bool render, bool rendersound = true)
|
||||||
{
|
{
|
||||||
Frame++;
|
Frame++;
|
||||||
|
|
||||||
if (Controller["Power"])
|
if (Controller["Power"])
|
||||||
LibLynx.Reset(Core);
|
LibLynx.Reset(Core);
|
||||||
|
|
||||||
int samples = soundbuff.Length;
|
int samples = soundbuff.Length;
|
||||||
LibLynx.Advance(Core, 0, videobuff, soundbuff, ref samples);
|
LibLynx.Advance(Core, GetButtons(), videobuff, soundbuff, ref samples);
|
||||||
numsamp = samples;
|
numsamp = samples / 2; // sound provider wants number of sample pairs
|
||||||
Console.WriteLine(numsamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Frame { get; private set; }
|
public int Frame { get; private set; }
|
||||||
|
@ -156,9 +157,31 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||||
|
|
||||||
#region Controller
|
#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; }
|
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
|
#endregion
|
||||||
|
|
||||||
#region savestates
|
#region savestates
|
||||||
|
@ -239,7 +262,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||||
|
|
||||||
#region SoundProvider
|
#region SoundProvider
|
||||||
|
|
||||||
short[] soundbuff = new short[1000000]; // todo: make this smaller once frame loop is resolved
|
short[] soundbuff = new short[2048];
|
||||||
int numsamp;
|
int numsamp;
|
||||||
|
|
||||||
public ISoundProvider SoundProvider { get { return null; } }
|
public ISoundProvider SoundProvider { get { return null; } }
|
||||||
|
|
|
@ -406,7 +406,6 @@ uint32 CMikie::DisplayRenderLine()
|
||||||
{
|
{
|
||||||
uint32 work_done=0;
|
uint32 work_done=0;
|
||||||
|
|
||||||
if(!mpDisplayCurrent) return 0;
|
|
||||||
if(!mDISPCTL_DMAEnable) return 0;
|
if(!mDISPCTL_DMAEnable) return 0;
|
||||||
// if(mLynxLine&0x80000000) return 0;
|
// if(mLynxLine&0x80000000) return 0;
|
||||||
|
|
||||||
|
|
|
@ -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
|
// this check needs to occur at least once every 250 million cycles or better
|
||||||
mMikie->CheckWrap();
|
mMikie->CheckWrap();
|
||||||
|
|
||||||
|
|
||||||
SetButtonData(buttons);
|
SetButtonData(buttons);
|
||||||
|
|
||||||
uint32 start = gSystemCycleCount;
|
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
|
// audio start frame
|
||||||
mMikie->startTS = start;
|
mMikie->startTS = start;
|
||||||
|
|
||||||
mMikie->mpDisplayCurrent = vbuff;
|
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 (gSystemCycleCount < target)
|
||||||
while (mMikie->mpDisplayCurrent && gSystemCycleCount - start < 200000)
|
//while (mMikie->mpDisplayCurrent && gSystemCycleCount - start < 800000)
|
||||||
// while (gSystemCycleCount - start < 700000) // what's the magic significance?
|
|
||||||
{
|
{
|
||||||
Update();
|
Update(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// total cycles executed is now gSystemCycleCount - start
|
// total cycles executed is now gSystemCycleCount - start
|
||||||
mMikie->mikbuf.end_frame((gSystemCycleCount - start) >> 2);
|
frameoverflow = gSystemCycleCount - target;
|
||||||
sbuffsize = mMikie->mikbuf.read_samples(sbuff, sbuffsize) / 2;
|
|
||||||
|
|
||||||
|
mMikie->mikbuf.end_frame((gSystemCycleCount - start) >> 2);
|
||||||
|
sbuffsize = mMikie->mikbuf.read_samples(sbuff, sbuffsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ public:
|
||||||
public:
|
public:
|
||||||
void Reset() MDFN_COLD;
|
void Reset() MDFN_COLD;
|
||||||
|
|
||||||
inline void Update()
|
inline void Update(uint32 targetclock)
|
||||||
{
|
{
|
||||||
// Only update if there is a predicted timer event
|
// Only update if there is a predicted timer event
|
||||||
if(gSystemCycleCount >= gNextTimerEvent)
|
if(gSystemCycleCount >= gNextTimerEvent)
|
||||||
|
@ -135,7 +135,7 @@ public:
|
||||||
// If the CPU is asleep then skip to the next timer event
|
// If the CPU is asleep then skip to the next timer event
|
||||||
if(gSystemCPUSleep)
|
if(gSystemCPUSleep)
|
||||||
{
|
{
|
||||||
gSystemCycleCount=gNextTimerEvent;
|
gSystemCycleCount = std::min(gNextTimerEvent, targetclock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,11 +192,9 @@ public:
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
void SetButtonData(uint32 data) {mSusie->SetButtonData(data);};
|
void SetButtonData(uint32 data) {mSusie->SetButtonData(data);};
|
||||||
uint32 GetButtonData() {return mSusie->GetButtonData();};
|
uint32 GetButtonData() {return mSusie->GetButtonData();};
|
||||||
void SetCycleBreakpoint(uint32 breakpoint) {mCycleCountBreakpoint=breakpoint;};
|
|
||||||
uint8* GetRamPointer() {return mRam->GetRamPointer();};
|
uint8* GetRamPointer() {return mRam->GetRamPointer();};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint32 mCycleCountBreakpoint;
|
|
||||||
CLynxBase *mMemoryHandlers[SYSTEM_SIZE];
|
CLynxBase *mMemoryHandlers[SYSTEM_SIZE];
|
||||||
CCart *mCart;
|
CCart *mCart;
|
||||||
CRom *mRom;
|
CRom *mRom;
|
||||||
|
@ -210,11 +208,13 @@ public:
|
||||||
uint32 gSuzieDoneTime;
|
uint32 gSuzieDoneTime;
|
||||||
uint32 gSystemCycleCount;
|
uint32 gSystemCycleCount;
|
||||||
uint32 gNextTimerEvent;
|
uint32 gNextTimerEvent;
|
||||||
//uint32 gCPUBootAddress;
|
|
||||||
uint32 gSystemIRQ;
|
uint32 gSystemIRQ;
|
||||||
uint32 gSystemNMI;
|
uint32 gSystemNMI;
|
||||||
uint32 gSystemCPUSleep;
|
uint32 gSystemCPUSleep;
|
||||||
uint32 gSystemHalt;
|
uint32 gSystemHalt;
|
||||||
|
|
||||||
|
// frame overflow detection
|
||||||
|
int frameoverflow;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue