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);
|
||||
|
||||
[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 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; } }
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue