BizHawk/BizHawk.Emulation.Cores/Consoles/Belogic/Uzem.cs

157 lines
3.8 KiB
C#

using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BizHawk.Emulation.Cores.Consoles.Belogic
{
[Core("uzem", "David Etherton", true, true, "", "", false)]
public class Uzem : WaterboxCore
{
private LibUzem _uze;
private bool _mouseEnabled;
[CoreConstructor("UZE")]
public Uzem(CoreComm comm, byte[] rom)
:base(comm, new Configuration
{
DefaultWidth = 720,
DefaultHeight = 224,
MaxWidth = 720,
MaxHeight = 224,
MaxSamples = 4096,
SystemId = "UZE",
DefaultFpsNumerator = 28618182,
DefaultFpsDenominator = 476840
})
{
_uze = PreInit<LibUzem>(new PeRunnerOptions
{
Filename = "uzem.wbx",
SbrkHeapSizeKB = 20,
SealedHeapSizeKB = 4,
InvisibleHeapSizeKB = 4,
MmapHeapSizeKB = 4,
PlainHeapSizeKB = 4,
});
_exe.AddReadonlyFile(rom, "romfile");
if (!_uze.Init())
throw new InvalidOperationException("Core rejected the rom!");
_mouseEnabled = _uze.MouseEnabled();
_exe.RemoveReadonlyFile("romfile");
PostInit();
}
private static readonly ControllerDefinition TwoPads = new ControllerDefinition
{
Name = "SNES Controller",
BoolButtons =
{
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 Select", "P1 Start", "P1 X", "P1 A", "P1 B", "P1 Y", "P1 L", "P1 R",
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 Select", "P2 Start", "P2 X", "P2 A", "P2 B", "P2 Y", "P2 L", "P2 R",
"Power"
}
};
private static readonly ControllerDefinition Mouse = new ControllerDefinition
{
Name = "SNES Controller",
BoolButtons =
{
"P1 Mouse Left", "P1 Mouse Right", "Power"
},
FloatControls =
{
"P1 Mouse X", "P1 Mouse Y"
},
FloatRanges =
{
new[] { -127f, 0f, 127f },
new[] { -127f, 0f, 127f }
}
};
private static readonly string[] PadBits =
{
"B", "Y", "Select", "Start", "Up", "Down", "Left", "Right", "A", "X", "L", "R"
};
private static int EncodePad(IController c, int p)
{
int ret = unchecked((int)0xffff0000);
int val = 1;
int idx = 0;
foreach (var s in PadBits)
{
if (c.IsPressed("P" + p + " " + PadBits[idx++]))
ret |= val;
val <<= 1;
}
return ret;
}
private static int EncodeDelta(float value)
{
int v = (int)value;
if (v > 127)
v = 127;
if (v < -127)
v = -127;
int ret = 0;
if (v < 0)
{
ret |= 1;
v = -v;
}
int mask = 64;
int bit = 2;
while (mask != 0)
{
if ((v & mask) != 0)
ret |= bit;
mask >>= 1;
bit <<= 1;
}
return ret;
}
public override ControllerDefinition ControllerDefinition => _mouseEnabled ? Mouse : TwoPads;
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
{
var ret = new LibUzem.FrameInfo();
if (_mouseEnabled)
{
ret.ButtonsP1 = EncodeDelta(controller.GetFloat("P1 Mouse X")) << 24
| EncodeDelta(controller.GetFloat("P1 Mouse Y")) << 16
| 0x8000;
if (controller.IsPressed("P1 Mouse Left"))
ret.ButtonsP1 |= 0x200;
if (controller.IsPressed("P1 Mouse Right"))
ret.ButtonsP1 |= 0x100;
}
else
{
ret.ButtonsP1 = EncodePad(controller, 1);
ret.ButtonsP2 = EncodePad(controller, 2);
}
if (controller.IsPressed("Power"))
ret.ButtonsConsole = 1;
return ret;
}
// with the high clockrate and full software signal generation, horizontal resolution is
// very variable. in practice, 240 wide, 360 wide, and 180 wide are what you'll see...
public override int VirtualWidth => 619;
public override int VirtualHeight => 448;
}
}