nyma -- support cd switching

motorcycle shifter, but neutral is before 1st instead of between 1st and second
Yes, I had to rebuild the non cd cores here, and I am sorry
This commit is contained in:
nattthebear 2020-06-08 20:23:50 -04:00
parent 9c875b42f4
commit 11e1019590
11 changed files with 108 additions and 33 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
[BizImport(CC)]
public abstract bool InitCd(int numdisks);
public enum CommandType : short
public enum CommandType : int
{
NONE = 0x00,
RESET = 0x01,
@ -69,26 +69,30 @@ namespace BizHawk.Emulation.Cores.Waterbox
TOGGLE_DIP15,
}
[Flags]
public enum BizhawkFlags : int
{
// skip video output
SkipRendering = 1,
// skip sound output
SkipSoundening = 2,
// render at LCM * LCM instead of raw
RenderConstantSize = 4,
// switch to the previous disk, if possible
PreviousDisk = 8,
// switch to the next disk, if possible
NextDisk = 16
}
[StructLayout(LayoutKind.Sequential)]
public new class FrameInfo : LibWaterboxCore.FrameInfo
{
/// <summary>
/// true to skip video rendering
/// </summary>
public short SkipRendering;
/// <summary>
/// true to skip audion rendering
/// </summary>
public short SkipSoundening;
public BizhawkFlags Flags;
/// <summary>
/// a single command to run at the start of this frame
/// </summary>
public CommandType Command;
/// <summary>
/// True to render to a single framebuffer size (LCM * LCM)
/// </summary>
public short RenderConstantSize;
/// <summary>
/// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long
/// </summary>
public byte* InputPortData;

View File

@ -13,9 +13,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
private readonly byte[] _inputPortData = new byte[16 * 16];
private readonly string _controllerDeckName;
private void InitControls(List<NPortInfoT> allPorts)
private void InitControls(List<NPortInfoT> allPorts, bool hasCds)
{
_controllerAdapter = new ControllerAdapter(allPorts, _syncSettingsActual.PortDevices, ButtonNameOverrides);
_controllerAdapter = new ControllerAdapter(allPorts, _syncSettingsActual.PortDevices, ButtonNameOverrides, hasCds);
_nyma.SetInputDevices(_controllerAdapter.Devices);
ControllerDefinition = _controllerAdapter.Definition;
}
@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// </summary>
public string[] Devices { get; }
public ControllerDefinition Definition { get; }
public ControllerAdapter(List<NPortInfoT> allPorts, IDictionary<int, string> config, IDictionary<string, string> overrides)
public ControllerAdapter(List<NPortInfoT> allPorts, IDictionary<int, string> config, IDictionary<string, string> overrides, bool hasCds)
{
var ret = new ControllerDefinition
{
@ -46,6 +46,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
{ "Power", "System" },
{ "Reset", "System" },
{ "Previous Disk", "System" },
{ "Next Disk", "System" },
}
};
@ -210,6 +212,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
ret.BoolButtons.Add("Power");
ret.BoolButtons.Add("Reset");
if (hasCds)
{
ret.BoolButtons.Add("Previous Disk");
ret.BoolButtons.Add("Next Disk");
}
Definition = ret;
finalDevices.Add(null);
Devices = finalDevices.ToArray();

View File

@ -119,7 +119,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
VsyncDenominator = 1 << 24;
_soundBuffer = new short[22050 * 2];
InitControls(portData);
InitControls(portData, discs?.Length > 0);
_nyma.SetFrontendSettingQuery(null);
if (_disks != null)
_nyma.SetCDCallbacks(null, null);
@ -179,16 +179,26 @@ namespace BizHawk.Emulation.Cores.Waterbox
DriveLightOn = false;
_controllerAdapter.SetBits(controller, _inputPortData);
_frameAdvanceInputLock = GCHandle.Alloc(_inputPortData, GCHandleType.Pinned);
LibNymaCore.BizhawkFlags flags = 0;
if (!render)
flags |= LibNymaCore.BizhawkFlags.SkipRendering;
if (!rendersound)
flags |= LibNymaCore.BizhawkFlags.SkipSoundening;
if (SettingsQuery("nyma.constantfb") != "0")
flags |= LibNymaCore.BizhawkFlags.RenderConstantSize;
if (controller.IsPressed("Previous Disk"))
flags |= LibNymaCore.BizhawkFlags.PreviousDisk;
if (controller.IsPressed("Next Disk"))
flags |= LibNymaCore.BizhawkFlags.NextDisk;
var ret = new LibNymaCore.FrameInfo
{
SkipRendering = (short)(render ? 0 : 1),
SkipSoundening = (short)(rendersound ? 0 : 1),
Flags = flags,
Command = controller.IsPressed("Power")
? LibNymaCore.CommandType.POWER
: controller.IsPressed("Reset")
? LibNymaCore.CommandType.RESET
: LibNymaCore.CommandType.NONE,
RenderConstantSize = (short)(SettingsQuery("nyma.constantfb") != "0" ? 1 : 0),
InputPortData = (byte*)_frameAdvanceInputLock.AddrOfPinnedObject(),
FrontendTime = GetRtcTime(SettingsQuery("nyma.rtcrealtime") != "0"),
};

View File

@ -82,8 +82,6 @@ ECL_EXPORT bool InitRom(const InitData& data)
return true;
}
void StartGameWithCds(int numdisks);
ECL_EXPORT bool InitCd(int numdisks)
{
try
@ -98,15 +96,25 @@ ECL_EXPORT bool InitCd(int numdisks)
return true;
}
enum BizhawkFlags
{
// skip video output
SkipRendering = 1,
// skip sound output
SkipSoundening = 2,
// render at LCM * LCM instead of raw
RenderConstantSize = 4,
// switch to the previous disk, if possible
PreviousDisk = 8,
// switch to the next disk, if possible
NextDisk = 16
};
struct MyFrameInfo: public FrameInfo
{
// true to skip video rendering
int16_t SkipRendering;
int16_t SkipSoundening;
int32_t BizhawkFlags;
// a single MDFN_MSC_* command to run at the start of this frame; 0 if none
int16_t Command;
// true to render LCM * LCM instead of raw
int16_t RenderConstantSize;
int32_t Command;
// raw data for each input port, assumed to be MAX_PORTS * MAX_PORT_DATA long
uint8_t* InputPortData;
int64_t FrontendTime;
@ -116,7 +124,14 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame)
{
FrontendTime = frame.FrontendTime;
LagFlag = true;
EES->skip = frame.SkipRendering;
EES->skip = !!(frame.BizhawkFlags & BizhawkFlags::SkipRendering);
{
auto prev = !!(frame.BizhawkFlags & BizhawkFlags::PreviousDisk);
auto next = !!(frame.BizhawkFlags & BizhawkFlags::NextDisk);
if (prev || next)
SwitchCds(prev, next);
}
if (frame.Command)
Game->DoSimpleCommand(frame.Command);
@ -131,12 +146,12 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame)
EES->SoundFormatChanged = false;
frame.Cycles = EES->MasterCycles;
frame.Lagged = LagFlag;
if (!frame.SkipSoundening)
if (!(frame.BizhawkFlags & BizhawkFlags::SkipSoundening))
{
memcpy(frame.SoundBuffer, EES->SoundBuf, EES->SoundBufSize * 4);
frame.Samples = EES->SoundBufSize;
}
if (!frame.SkipRendering)
if (!(frame.BizhawkFlags & BizhawkFlags::SkipRendering))
{
int h = EES->DisplayRect.h;
int lineStart = EES->DisplayRect.y;
@ -147,7 +162,7 @@ ECL_EXPORT void FrameAdvance(MyFrameInfo& frame)
uint32_t* src = pixels + EES->DisplayRect.x + EES->DisplayRect.y * srcp;
uint32_t* dst = frame.VideoBuffer;
if (!frame.RenderConstantSize || !multiWidth && Game->lcm_width == EES->DisplayRect.w && Game->lcm_height == h)
if (!(frame.BizhawkFlags & BizhawkFlags::RenderConstantSize) || !multiWidth && Game->lcm_width == EES->DisplayRect.w && Game->lcm_height == h)
{
// simple non-resizing blitter
// TODO: What does this do with true multiwidth? Probably not anything good

View File

@ -110,7 +110,6 @@ void StartGameWithCds(int numdisks)
}
MDFNGameInfo->RMD = rmd;
// TODO: Wire up a way for the user to change disks
Mednafen::MDFNGameInfo->SetMedia(
0, // drive: 0 unless there's more than one drive
2, // state: 0 = open, 1 = closed (media absent), 2 = closed (media present)
@ -118,6 +117,39 @@ void StartGameWithCds(int numdisks)
0 // orientation: flip sides on NES FDS. not used elsewhere?
);
}
static bool wasPrev;
static bool wasNext;
static int cd;
void SwitchCds(bool prev, bool next)
{
auto newCd = cd;
if (prev && !wasPrev)
{
newCd = std::max(newCd - 1, -1);
}
if (next && !wasNext)
{
newCd = std::min(newCd + 1, (int)(CDInterfaces->size() - 1));
}
if (newCd != cd)
{
Mednafen::MDFNGameInfo->SetMedia(
0, // drive: 0 unless there's more than one drive
0, // state: 0 = open, 1 = closed (media absent), 2 = closed (media present)
std::max(cd, 0), // media: index into the disk list
0 // orientation: flip sides on NES FDS. not used elsewhere?
);
Mednafen::MDFNGameInfo->SetMedia(
0, // drive: 0 unless there's more than one drive
newCd == -1 ? 0 : 2, // state: 0 = open, 1 = closed (media absent), 2 = closed (media present)
std::max(newCd, 0), // media: index into the disk list
0 // orientation: flip sides on NES FDS. not used elsewhere?
);
}
cd = newCd;
wasPrev = prev;
wasNext = next;
}
// CDInterface::Load pulls in a bunch of things that we do not want, stub them out here
namespace Mednafen

View File

@ -11,3 +11,7 @@ ECL_EXPORT void SetCDCallbacks()
{
abort();
}
void SwitchCds(bool prev, bool next)
{
abort();
}

View File

@ -25,3 +25,6 @@ typedef void (*FrameCallback)();
// The callback may not call any C standard library functions, or otherwise trigger a syscall
// The callback must return before frame advance finishes
void RegisterFrameThreadProc(FrameCallback threadproc);
void StartGameWithCds(int numdisks);
void SwitchCds(bool prev, bool next);