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:
nattthebear 2017-06-04 21:13:48 -04:00
parent 87ce1086cb
commit d7b8464a9b
5 changed files with 212 additions and 27 deletions

View File

@ -1150,6 +1150,7 @@
<Compile Include="Consoles\Sega\Saturn\LibSaturnus.cs" /> <Compile Include="Consoles\Sega\Saturn\LibSaturnus.cs" />
<Compile Include="Consoles\Sega\Saturn\LibYabause.cs" /> <Compile Include="Consoles\Sega\Saturn\LibYabause.cs" />
<Compile Include="Consoles\Sega\Saturn\Saturnus.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.cs" />
<Compile Include="Consoles\Sega\Saturn\Yabause.IDriveLight.cs"> <Compile Include="Consoles\Sega\Saturn\Yabause.IDriveLight.cs">
<DependentUpon>Yabause.cs</DependentUpon> <DependentUpon>Yabause.cs</DependentUpon>

View File

@ -26,7 +26,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Track public struct Track
{ {
public int Address; public int Adr;
public int Control; public int Control;
public int Lba; public int Lba;
public int Valid; public int Valid;
@ -44,14 +44,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
[FieldOffset(8)] [FieldOffset(8)]
public IntPtr Pixels; public IntPtr Pixels;
[FieldOffset(16)] [FieldOffset(16)]
public long MasterCycles; public IntPtr Controllers;
[FieldOffset(24)] [FieldOffset(24)]
public int SoundBufMaxSize; public long MasterCycles;
[FieldOffset(28)]
public int SoundBufSize;
[FieldOffset(32)] [FieldOffset(32)]
public int Width; public int SoundBufMaxSize;
[FieldOffset(36)] [FieldOffset(36)]
public int SoundBufSize;
[FieldOffset(40)]
public int Width;
[FieldOffset(44)]
public int Height; public int Height;
}; };
@ -76,5 +78,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
public abstract void SetDisk(int disk, bool open); public abstract void SetDisk(int disk, bool open);
[BizImport(CC)] [BizImport(CC)]
public abstract void FrameAdvance([In, Out]FrameAdvanceInfo f); public abstract void FrameAdvance([In, Out]FrameAdvanceInfo f);
[BizImport(CC)]
public abstract void SetupInput(int[] portdevices, int[] multitaps);
} }
} }

View File

@ -20,6 +20,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
private Disc[] _disks; private Disc[] _disks;
private DiscSectorReader[] _diskReaders; private DiscSectorReader[] _diskReaders;
private bool _isPal; private bool _isPal;
private SaturnusControllerDeck _controllerDeck;
public Saturnus(CoreComm comm, IEnumerable<Disc> disks) public Saturnus(CoreComm comm, IEnumerable<Disc> disks)
{ {
@ -45,10 +46,18 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
SetFirmwareCallbacks(); SetFirmwareCallbacks();
SetCdCallbacks(); SetCdCallbacks();
if (!_core.Init(_disks.Length)) if (!_core.Init(_disks.Length))
throw new InvalidOperationException("Core rejected the disks!"); throw new InvalidOperationException("Core rejected the disks!");
ClearAllCallbacks(); 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(); _exe.Seal();
SetCdCallbacks(); SetCdCallbacks();
_core.SetDisk(0, false); _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) public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true)
{ {
if (controller.IsPressed("Power"))
_core.HardReset();
fixed (short* _sp = _soundBuffer) fixed (short* _sp = _soundBuffer)
fixed (int* _vp = _videoBuffer) fixed (int* _vp = _videoBuffer)
fixed (byte* _cp = _controllerDeck.Poll(controller))
{ {
var info = new LibSaturnus.FrameAdvanceInfo var info = new LibSaturnus.FrameAdvanceInfo
{ {
SoundBuf = (IntPtr)_sp, SoundBuf = (IntPtr)_sp,
SoundBufMaxSize = _soundBuffer.Length / 2, SoundBufMaxSize = _soundBuffer.Length / 2,
Pixels = (IntPtr)_vp Pixels = (IntPtr)_vp,
Controllers = (IntPtr)_cp
}; };
_core.FrameAdvance(info); _core.FrameAdvance(info);
@ -101,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
public string SystemId { get { return "SAT"; } } public string SystemId { get { return "SAT"; } }
public bool DeterministicEmulation { get; private set; } public bool DeterministicEmulation { get; private set; }
public CoreComm CoreComm { get; } public CoreComm CoreComm { get; }
public ControllerDefinition ControllerDefinition => NullController.Instance.Definition; public ControllerDefinition ControllerDefinition { get; }
#region Callbacks #region Callbacks
@ -176,7 +190,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
t.DiskType = (int)tin.Session1Format; t.DiskType = (int)tin.Session1Format;
for (int i = 0; i < 101; i++) 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].Lba = tin.TOCItems[i].LBA;
t.Tracks[i].Control = (int)tin.TOCItems[i].Control; t.Tracks[i].Control = (int)tin.TOCItems[i].Control;
t.Tracks[i].Valid = tin.TOCItems[i].Exists ? 1 : 0; 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) private void CDSectorCallback(int disk, int lba, IntPtr dest)
{ {
Console.WriteLine("servicing " + lba);
var buff = new byte[2448]; var buff = new byte[2448];
_diskReaders[disk].ReadLBA_2448(lba, buff, 0); _diskReaders[disk].ReadLBA_2448(lba, buff, 0);
Marshal.Copy(buff, 0, dest, 2448); Marshal.Copy(buff, 0, dest, 2448);

View File

@ -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;
}
}
}

View File

@ -9,10 +9,10 @@
#define EXPORT extern "C" ECL_EXPORT #define EXPORT extern "C" ECL_EXPORT
using namespace MDFN_IEN_SS; using namespace MDFN_IEN_SS;
static int32 (*FirmwareSizeCallback)(const char* filename); static int32 (*FirmwareSizeCallback)(const char *filename);
static void (*FirmwareDataCallback)(const char* filename, uint8* dest); 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); int32 length = FirmwareSizeCallback(filename);
auto buffer = new uint8[length]; auto buffer = new uint8[length];
@ -24,7 +24,7 @@ std::unique_ptr<MemoryStream> GetFirmware(const char* filename)
return ms; 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; FirmwareSizeCallback = sizecallback;
FirmwareDataCallback = datacallback; FirmwareDataCallback = datacallback;
@ -37,7 +37,7 @@ struct FrontendTOC
int32 DiskType; int32 DiskType;
struct struct
{ {
int32 Address; int32 Adr;
int32 Control; int32 Control;
int32 Lba; int32 Lba;
int32 Valid; int32 Valid;
@ -55,7 +55,7 @@ EXPORT void SetCDCallbacks(void (*toccallback)(int disk, FrontendTOC *dest), voi
class MyCDIF : public CDIF class MyCDIF : public CDIF
{ {
private: private:
int disk; int disk;
public: public:
@ -68,10 +68,10 @@ class MyCDIF : public CDIF
disc_toc.disc_type = t.DiskType; disc_toc.disc_type = t.DiskType;
for (int i = 0; i < 101; i++) 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].control = t.Tracks[i].Control;
disc_toc.tracks[i].lba = t.Tracks[i].Lba; 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 std::vector<CDIF *> CDInterfaces;
static uint32* FrameBuffer; static uint32 *FrameBuffer;
static uint8 IsResetPushed; // 1 or 0 static uint8 IsResetPushed; // 1 or 0
namespace MDFN_IEN_SS namespace MDFN_IEN_SS
@ -100,7 +100,7 @@ extern bool LoadCD(std::vector<CDIF *> *CDInterfaces);
} }
EXPORT bool Init(int numDisks) EXPORT bool Init(int numDisks)
{ {
FrameBuffer = (uint32*)alloc_invisible(1024 * 1024); FrameBuffer = (uint32 *)alloc_invisible(1024 * 1024);
for (int i = 0; i < numDisks; i++) for (int i = 0; i < numDisks; i++)
CDInterfaces.push_back(new MyCDIF(i)); CDInterfaces.push_back(new MyCDIF(i));
auto ret = LoadCD(&CDInterfaces); auto ret = LoadCD(&CDInterfaces);
@ -140,9 +140,11 @@ extern void Emulate(EmulateSpecStruct *espec_arg);
struct FrameAdvanceInfo struct FrameAdvanceInfo
{ {
int16* SoundBuf; int16 *SoundBuf;
uint32* Pixels; uint32 *Pixels;
uint8* Controllers;
int64 MasterCycles; int64 MasterCycles;
@ -164,7 +166,9 @@ struct FrameAdvanceInfo
// bool InterlaceField; // bool InterlaceField;
}; };
EXPORT void FrameAdvance(FrameAdvanceInfo& f) static uint8 ControllerInput[12 * 32];
EXPORT void FrameAdvance(FrameAdvanceInfo &f)
{ {
EmulateSpecStruct e; EmulateSpecStruct e;
int32 LineWidths[1024]; int32 LineWidths[1024];
@ -173,6 +177,8 @@ EXPORT void FrameAdvance(FrameAdvanceInfo& f)
e.LineWidths = LineWidths; e.LineWidths = LineWidths;
e.SoundBuf = f.SoundBuf; e.SoundBuf = f.SoundBuf;
e.SoundBufMaxSize = f.SoundBufMaxSize; e.SoundBufMaxSize = f.SoundBufMaxSize;
memcpy(ControllerInput, f.Controllers, sizeof(ControllerInput));
Emulate(&e); Emulate(&e);
f.SoundBufSize = e.SoundBufSize; f.SoundBufSize = e.SoundBufSize;
f.MasterCycles = e.MasterCycles; f.MasterCycles = e.MasterCycles;
@ -181,8 +187,8 @@ EXPORT void FrameAdvance(FrameAdvanceInfo& f)
for (int i = 0; i < e.h; i++) for (int i = 0; i < e.h; i++)
w = std::max(w, LineWidths[i]); w = std::max(w, LineWidths[i]);
const uint32* src = FrameBuffer; const uint32 *src = FrameBuffer;
uint32* dst = f.Pixels; uint32 *dst = f.Pixels;
const int srcp = 1024; const int srcp = 1024;
const int dstp = w; const int dstp = w;
src += e.y * srcp + e.x; src += e.y * srcp + e.x;
@ -195,6 +201,26 @@ EXPORT void FrameAdvance(FrameAdvanceInfo& f)
f.Height = e.h; 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) /*void VDP2REND_SetGetVideoParams(MDFNGI* gi, const bool caspect, const int sls, const int sle, const bool show_h_overscan, const bool dohblend)
{ {
CorrectAspect = caspect; 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); VDP2REND_SetGetVideoParams(gi, caspect, sls, sle, show_h_overscan, dohblend);
}*/ }*/
// if (BackupRAM_Dirty)SaveBackupRAM(); // if (BackupRAM_Dirty)SaveBackupRAM();
// if (CART_GetClearNVDirty())SaveCartNV(); // if (CART_GetClearNVDirty())SaveCartNV();