saturnus: start working on controller hook up. there's something wrong with the CD stuff though, and games don't work
This commit is contained in:
parent
87ce1086cb
commit
d7b8464a9b
|
@ -1150,6 +1150,7 @@
|
|||
<Compile Include="Consoles\Sega\Saturn\LibSaturnus.cs" />
|
||||
<Compile Include="Consoles\Sega\Saturn\LibYabause.cs" />
|
||||
<Compile Include="Consoles\Sega\Saturn\Saturnus.cs" />
|
||||
<Compile Include="Consoles\Sega\Saturn\SaturnusControllerDeck.cs" />
|
||||
<Compile Include="Consoles\Sega\Saturn\Yabause.cs" />
|
||||
<Compile Include="Consoles\Sega\Saturn\Yabause.IDriveLight.cs">
|
||||
<DependentUpon>Yabause.cs</DependentUpon>
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Track
|
||||
{
|
||||
public int Address;
|
||||
public int Adr;
|
||||
public int Control;
|
||||
public int Lba;
|
||||
public int Valid;
|
||||
|
@ -44,14 +44,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
[FieldOffset(8)]
|
||||
public IntPtr Pixels;
|
||||
[FieldOffset(16)]
|
||||
public long MasterCycles;
|
||||
public IntPtr Controllers;
|
||||
[FieldOffset(24)]
|
||||
public int SoundBufMaxSize;
|
||||
[FieldOffset(28)]
|
||||
public int SoundBufSize;
|
||||
public long MasterCycles;
|
||||
[FieldOffset(32)]
|
||||
public int Width;
|
||||
public int SoundBufMaxSize;
|
||||
[FieldOffset(36)]
|
||||
public int SoundBufSize;
|
||||
[FieldOffset(40)]
|
||||
public int Width;
|
||||
[FieldOffset(44)]
|
||||
public int Height;
|
||||
};
|
||||
|
||||
|
@ -76,5 +78,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
public abstract void SetDisk(int disk, bool open);
|
||||
[BizImport(CC)]
|
||||
public abstract void FrameAdvance([In, Out]FrameAdvanceInfo f);
|
||||
[BizImport(CC)]
|
||||
public abstract void SetupInput(int[] portdevices, int[] multitaps);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
private Disc[] _disks;
|
||||
private DiscSectorReader[] _diskReaders;
|
||||
private bool _isPal;
|
||||
private SaturnusControllerDeck _controllerDeck;
|
||||
|
||||
public Saturnus(CoreComm comm, IEnumerable<Disc> disks)
|
||||
{
|
||||
|
@ -45,10 +46,18 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
|
||||
SetFirmwareCallbacks();
|
||||
SetCdCallbacks();
|
||||
|
||||
if (!_core.Init(_disks.Length))
|
||||
throw new InvalidOperationException("Core rejected the disks!");
|
||||
ClearAllCallbacks();
|
||||
|
||||
_controllerDeck = new SaturnusControllerDeck(new[] { false, false },
|
||||
new[] { SaturnusControllerDeck.Device.Gamepad, SaturnusControllerDeck.Device.None },
|
||||
_core);
|
||||
ControllerDefinition = _controllerDeck.Definition;
|
||||
ControllerDefinition.Name = "Saturn Controller";
|
||||
ControllerDefinition.BoolButtons.Add("Power");
|
||||
ControllerDefinition.BoolButtons.Add("Reset"); // not yet hooked up
|
||||
|
||||
_exe.Seal();
|
||||
SetCdCallbacks();
|
||||
_core.SetDisk(0, false);
|
||||
|
@ -56,14 +65,19 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
|
||||
public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true)
|
||||
{
|
||||
if (controller.IsPressed("Power"))
|
||||
_core.HardReset();
|
||||
|
||||
fixed (short* _sp = _soundBuffer)
|
||||
fixed (int* _vp = _videoBuffer)
|
||||
fixed (int* _vp = _videoBuffer)
|
||||
fixed (byte* _cp = _controllerDeck.Poll(controller))
|
||||
{
|
||||
var info = new LibSaturnus.FrameAdvanceInfo
|
||||
{
|
||||
SoundBuf = (IntPtr)_sp,
|
||||
SoundBufMaxSize = _soundBuffer.Length / 2,
|
||||
Pixels = (IntPtr)_vp
|
||||
Pixels = (IntPtr)_vp,
|
||||
Controllers = (IntPtr)_cp
|
||||
};
|
||||
|
||||
_core.FrameAdvance(info);
|
||||
|
@ -101,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
public string SystemId { get { return "SAT"; } }
|
||||
public bool DeterministicEmulation { get; private set; }
|
||||
public CoreComm CoreComm { get; }
|
||||
public ControllerDefinition ControllerDefinition => NullController.Instance.Definition;
|
||||
public ControllerDefinition ControllerDefinition { get; }
|
||||
|
||||
#region Callbacks
|
||||
|
||||
|
@ -176,7 +190,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
t.DiskType = (int)tin.Session1Format;
|
||||
for (int i = 0; i < 101; i++)
|
||||
{
|
||||
t.Tracks[i].Address = 1; // ????
|
||||
t.Tracks[i].Adr = 1; // ????
|
||||
t.Tracks[i].Lba = tin.TOCItems[i].LBA;
|
||||
t.Tracks[i].Control = (int)tin.TOCItems[i].Control;
|
||||
t.Tracks[i].Valid = tin.TOCItems[i].Exists ? 1 : 0;
|
||||
|
@ -184,6 +198,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
|||
}
|
||||
private void CDSectorCallback(int disk, int lba, IntPtr dest)
|
||||
{
|
||||
Console.WriteLine("servicing " + lba);
|
||||
var buff = new byte[2448];
|
||||
_diskReaders[disk].ReadLBA_2448(lba, buff, 0);
|
||||
Marshal.Copy(buff, 0, dest, 2448);
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
using BizHawk.Emulation.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
|
||||
{
|
||||
public class SaturnusControllerDeck
|
||||
{
|
||||
private const int DataSize = 32;
|
||||
|
||||
private static readonly Type[] Implementors =
|
||||
{
|
||||
typeof(None),
|
||||
typeof(Gamepad),
|
||||
typeof(None),
|
||||
typeof(None),
|
||||
typeof(None),
|
||||
typeof(None),
|
||||
typeof(None),
|
||||
typeof(None)
|
||||
};
|
||||
|
||||
private readonly IDevice[] _devices;
|
||||
private readonly ControlDefUnMerger[] _unmerger;
|
||||
private readonly byte[] _data;
|
||||
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
public SaturnusControllerDeck(bool[] multitap, Device[] devices, LibSaturnus core)
|
||||
{
|
||||
int count = 2 + multitap.Count(b => b) * 5;
|
||||
|
||||
int[] dev = new int[12];
|
||||
int[] mt = new int[2];
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
dev[i] = (int)(i < count ? devices[i] : Device.None);
|
||||
for (int i = 0; i < 2; i++)
|
||||
mt[i] = multitap[i] ? 1 : 0;
|
||||
|
||||
core.SetupInput(dev, mt);
|
||||
|
||||
_devices = dev.Take(count)
|
||||
.Select(i => Activator.CreateInstance(Implementors[i]))
|
||||
.Cast<IDevice>()
|
||||
.ToArray();
|
||||
_data = new byte[count * DataSize];
|
||||
|
||||
List<ControlDefUnMerger> cdum;
|
||||
Definition = ControllerDefinitionMerger.GetMerged(_devices.Select(d => d.Definition),
|
||||
out cdum);
|
||||
_unmerger = cdum.ToArray();
|
||||
}
|
||||
|
||||
public byte[] Poll(IController controller)
|
||||
{
|
||||
for (int i = 0, offset = 0; i < _devices.Length; i++, offset += DataSize)
|
||||
_devices[i].Update(_unmerger[i].UnMerge(controller), _data, offset);
|
||||
return _data;
|
||||
}
|
||||
|
||||
public enum Device
|
||||
{
|
||||
None,
|
||||
Gamepad,
|
||||
ThreeDeePad,
|
||||
Mouse,
|
||||
Wheel,
|
||||
Mission,
|
||||
DualMission,
|
||||
Keyboard
|
||||
}
|
||||
|
||||
private interface IDevice
|
||||
{
|
||||
void Update(IController controller, byte[] dest, int offset);
|
||||
ControllerDefinition Definition { get; }
|
||||
}
|
||||
|
||||
private class None : IDevice
|
||||
{
|
||||
private static readonly ControllerDefinition NoneDefition = new ControllerDefinition();
|
||||
public ControllerDefinition Definition => NoneDefition;
|
||||
public void Update(IController controller, byte[] dest, int offset)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private abstract class ButtonedDevice : IDevice
|
||||
{
|
||||
protected ButtonedDevice()
|
||||
{
|
||||
Definition = new ControllerDefinition
|
||||
{
|
||||
BoolButtons = ButtonNames.Where(s => s != null).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract string[] ButtonNames { get; }
|
||||
public ControllerDefinition Definition { get; }
|
||||
|
||||
public virtual void Update(IController controller, byte[] dest, int offset)
|
||||
{
|
||||
byte data = 0;
|
||||
int pos = 0;
|
||||
int bit = 0;
|
||||
for (int i = 0; i < ButtonNames.Length; i++)
|
||||
{
|
||||
if (ButtonNames[i] != null && controller.IsPressed(ButtonNames[i]))
|
||||
data |= (byte)(1 << bit);
|
||||
if (++bit == 8)
|
||||
{
|
||||
bit = 0;
|
||||
dest[offset + pos++] = data;
|
||||
data = 0;
|
||||
}
|
||||
}
|
||||
if (bit != 0)
|
||||
dest[offset] = data;
|
||||
}
|
||||
}
|
||||
|
||||
private class Gamepad : ButtonedDevice
|
||||
{
|
||||
private static readonly string[] _buttonNames =
|
||||
{
|
||||
"0Z", "0Y", "0X", "0R",
|
||||
"0Up", "0Down", "0Left", "0Right",
|
||||
"0B", "0C", "0A", "0Start",
|
||||
null,null, null, "0L"
|
||||
};
|
||||
|
||||
protected override string[] ButtonNames => _buttonNames;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,10 +9,10 @@
|
|||
#define EXPORT extern "C" ECL_EXPORT
|
||||
using namespace MDFN_IEN_SS;
|
||||
|
||||
static int32 (*FirmwareSizeCallback)(const char* filename);
|
||||
static void (*FirmwareDataCallback)(const char* filename, uint8* dest);
|
||||
static int32 (*FirmwareSizeCallback)(const char *filename);
|
||||
static void (*FirmwareDataCallback)(const char *filename, uint8 *dest);
|
||||
|
||||
std::unique_ptr<MemoryStream> GetFirmware(const char* filename)
|
||||
std::unique_ptr<MemoryStream> GetFirmware(const char *filename)
|
||||
{
|
||||
int32 length = FirmwareSizeCallback(filename);
|
||||
auto buffer = new uint8[length];
|
||||
|
@ -24,7 +24,7 @@ std::unique_ptr<MemoryStream> GetFirmware(const char* filename)
|
|||
return ms;
|
||||
}
|
||||
|
||||
EXPORT void SetFirmwareCallbacks(int32 (*sizecallback)(const char *filename), void (*datacallback)(const char* filename, uint8* dest))
|
||||
EXPORT void SetFirmwareCallbacks(int32 (*sizecallback)(const char *filename), void (*datacallback)(const char *filename, uint8 *dest))
|
||||
{
|
||||
FirmwareSizeCallback = sizecallback;
|
||||
FirmwareDataCallback = datacallback;
|
||||
|
@ -37,7 +37,7 @@ struct FrontendTOC
|
|||
int32 DiskType;
|
||||
struct
|
||||
{
|
||||
int32 Address;
|
||||
int32 Adr;
|
||||
int32 Control;
|
||||
int32 Lba;
|
||||
int32 Valid;
|
||||
|
@ -55,7 +55,7 @@ EXPORT void SetCDCallbacks(void (*toccallback)(int disk, FrontendTOC *dest), voi
|
|||
|
||||
class MyCDIF : public CDIF
|
||||
{
|
||||
private:
|
||||
private:
|
||||
int disk;
|
||||
|
||||
public:
|
||||
|
@ -68,10 +68,10 @@ class MyCDIF : public CDIF
|
|||
disc_toc.disc_type = t.DiskType;
|
||||
for (int i = 0; i < 101; i++)
|
||||
{
|
||||
disc_toc.tracks[i].adr = t.Tracks[i].Address;
|
||||
disc_toc.tracks[i].adr = t.Tracks[i].Adr;
|
||||
disc_toc.tracks[i].control = t.Tracks[i].Control;
|
||||
disc_toc.tracks[i].lba = t.Tracks[i].Lba;
|
||||
disc_toc.tracks[i].valid = t.Tracks[i].Valid;
|
||||
disc_toc.tracks[i].valid = t.Tracks[i].Valid;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ class MyCDIF : public CDIF
|
|||
};
|
||||
|
||||
static std::vector<CDIF *> CDInterfaces;
|
||||
static uint32* FrameBuffer;
|
||||
static uint32 *FrameBuffer;
|
||||
static uint8 IsResetPushed; // 1 or 0
|
||||
|
||||
namespace MDFN_IEN_SS
|
||||
|
@ -100,7 +100,7 @@ extern bool LoadCD(std::vector<CDIF *> *CDInterfaces);
|
|||
}
|
||||
EXPORT bool Init(int numDisks)
|
||||
{
|
||||
FrameBuffer = (uint32*)alloc_invisible(1024 * 1024);
|
||||
FrameBuffer = (uint32 *)alloc_invisible(1024 * 1024);
|
||||
for (int i = 0; i < numDisks; i++)
|
||||
CDInterfaces.push_back(new MyCDIF(i));
|
||||
auto ret = LoadCD(&CDInterfaces);
|
||||
|
@ -140,9 +140,11 @@ extern void Emulate(EmulateSpecStruct *espec_arg);
|
|||
|
||||
struct FrameAdvanceInfo
|
||||
{
|
||||
int16* SoundBuf;
|
||||
int16 *SoundBuf;
|
||||
|
||||
uint32* Pixels;
|
||||
uint32 *Pixels;
|
||||
|
||||
uint8* Controllers;
|
||||
|
||||
int64 MasterCycles;
|
||||
|
||||
|
@ -164,7 +166,9 @@ struct FrameAdvanceInfo
|
|||
// bool InterlaceField;
|
||||
};
|
||||
|
||||
EXPORT void FrameAdvance(FrameAdvanceInfo& f)
|
||||
static uint8 ControllerInput[12 * 32];
|
||||
|
||||
EXPORT void FrameAdvance(FrameAdvanceInfo &f)
|
||||
{
|
||||
EmulateSpecStruct e;
|
||||
int32 LineWidths[1024];
|
||||
|
@ -173,6 +177,8 @@ EXPORT void FrameAdvance(FrameAdvanceInfo& f)
|
|||
e.LineWidths = LineWidths;
|
||||
e.SoundBuf = f.SoundBuf;
|
||||
e.SoundBufMaxSize = f.SoundBufMaxSize;
|
||||
memcpy(ControllerInput, f.Controllers, sizeof(ControllerInput));
|
||||
|
||||
Emulate(&e);
|
||||
f.SoundBufSize = e.SoundBufSize;
|
||||
f.MasterCycles = e.MasterCycles;
|
||||
|
@ -181,8 +187,8 @@ EXPORT void FrameAdvance(FrameAdvanceInfo& f)
|
|||
for (int i = 0; i < e.h; i++)
|
||||
w = std::max(w, LineWidths[i]);
|
||||
|
||||
const uint32* src = FrameBuffer;
|
||||
uint32* dst = f.Pixels;
|
||||
const uint32 *src = FrameBuffer;
|
||||
uint32 *dst = f.Pixels;
|
||||
const int srcp = 1024;
|
||||
const int dstp = w;
|
||||
src += e.y * srcp + e.x;
|
||||
|
@ -195,6 +201,26 @@ EXPORT void FrameAdvance(FrameAdvanceInfo& f)
|
|||
f.Height = e.h;
|
||||
}
|
||||
|
||||
static const char *DeviceNames[] =
|
||||
{
|
||||
"none",
|
||||
"gamepad",
|
||||
"3dpad",
|
||||
"mouse",
|
||||
"wheel",
|
||||
"mission",
|
||||
"dmission",
|
||||
"keyboard"
|
||||
};
|
||||
|
||||
EXPORT void SetupInput(const int* portdevices, const int* multitaps)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
SMPC_SetMultitap(i, multitaps[i]);
|
||||
for (int i = 0; i < 12; i++)
|
||||
SMPC_SetInput(i, DeviceNames[portdevices[i]], ControllerInput + i * 32);
|
||||
}
|
||||
|
||||
/*void VDP2REND_SetGetVideoParams(MDFNGI* gi, const bool caspect, const int sls, const int sle, const bool show_h_overscan, const bool dohblend)
|
||||
{
|
||||
CorrectAspect = caspect;
|
||||
|
@ -241,7 +267,6 @@ void SetGetVideoParams(MDFNGI* gi, const bool caspect, const int sls, const int
|
|||
VDP2REND_SetGetVideoParams(gi, caspect, sls, sle, show_h_overscan, dohblend);
|
||||
}*/
|
||||
|
||||
|
||||
// if (BackupRAM_Dirty)SaveBackupRAM();
|
||||
// if (CART_GetClearNVDirty())SaveCartNV();
|
||||
|
||||
|
|
Loading…
Reference in New Issue