BizHawk/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs

191 lines
5.6 KiB
C#
Raw Normal View History

2017-07-02 17:47:43 +00:00
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox;
2017-07-03 00:46:01 +00:00
using BizHawk.Emulation.DiscSystem;
2017-07-02 17:47:43 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
2017-07-03 00:46:01 +00:00
using System.Runtime.InteropServices;
2017-07-02 17:47:43 +00:00
using System.Text;
using System.Threading.Tasks;
2017-07-03 00:46:01 +00:00
using System.IO;
2017-07-02 17:47:43 +00:00
namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
{
[CoreAttributes("PicoDrive", "notaz", true, true,
2017-07-02 17:47:43 +00:00
"0e352905c7aa80b166933970abbcecfce96ad64e", "https://github.com/notaz/picodrive", false)]
public class PicoDrive : WaterboxCore, IDriveLight, IRegionable
2017-07-02 17:47:43 +00:00
{
private LibPicoDrive _core;
2017-07-03 00:46:01 +00:00
private LibPicoDrive.CDReadCallback _cdcallback;
private Disc _cd;
private DiscSectorReader _cdReader;
private bool _isPal;
2017-07-02 17:47:43 +00:00
[CoreConstructor("GEN")]
public PicoDrive(CoreComm comm, GameInfo game, byte[] rom, bool deterministic)
:this(comm, game, rom, null, deterministic)
2017-07-03 00:46:01 +00:00
{ }
public PicoDrive(CoreComm comm, GameInfo game, Disc cd, bool deterministic)
:this(comm, game, null, cd, deterministic)
2017-07-03 00:46:01 +00:00
{ }
private PicoDrive(CoreComm comm, GameInfo game, byte[] rom, Disc cd, bool deterministic)
2017-07-02 17:47:43 +00:00
: base(comm, new Configuration
{
MaxSamples = 2048,
DefaultWidth = 320,
DefaultHeight = 224,
MaxWidth = 320,
MaxHeight = 480,
SystemId = "GEN"
})
{
var biosg = comm.CoreFileProvider.GetFirmware("32X", "G", false);
var biosm = comm.CoreFileProvider.GetFirmware("32X", "M", false);
var bioss = comm.CoreFileProvider.GetFirmware("32X", "S", false);
var has32xBios = biosg != null && biosm != null && bioss != null;
if (deterministic && !has32xBios)
throw new InvalidOperationException("32X BIOS files are required for deterministic mode");
deterministic |= has32xBios;
2017-07-02 17:47:43 +00:00
_core = PreInit<LibPicoDrive>(new PeRunnerOptions
{
Filename = "picodrive.wbx",
SbrkHeapSizeKB = 64,
SealedHeapSizeKB = 18 * 1024,
InvisibleHeapSizeKB = 1024,
MmapHeapSizeKB = 4096,
PlainHeapSizeKB = 64,
2017-07-02 17:47:43 +00:00
});
if (has32xBios)
{
_exe.AddReadonlyFile(biosg, "32x.g");
_exe.AddReadonlyFile(biosm, "32x.m");
_exe.AddReadonlyFile(bioss, "32x.s");
Console.WriteLine("Using supplied 32x BIOS files");
}
2017-07-03 00:46:01 +00:00
if (cd != null)
{
_exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_EU", true), "cd.eu");
_exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_US", true), "cd.us");
_exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_JP", true), "cd.jp");
_exe.AddReadonlyFile(gpgx.GPGX.GetCDData(cd), "toc");
2017-07-03 00:46:01 +00:00
_cd = cd;
_cdReader = new DiscSectorReader(_cd);
_cdcallback = CDRead;
_core.SetCDReadCallback(_cdcallback);
DriveLightEnabled = true;
}
else
{
_exe.AddReadonlyFile(rom, "romfile.md");
}
if (!_core.Init(cd != null, game["32X"]))
2017-07-03 00:46:01 +00:00
throw new InvalidOperationException("Core rejected the file!");
2017-07-03 00:46:01 +00:00
if (cd != null)
{
_exe.RemoveReadonlyFile("cd.eu");
_exe.RemoveReadonlyFile("cd.us");
_exe.RemoveReadonlyFile("cd.jp");
_exe.RemoveReadonlyFile("toc");
_core.SetCDReadCallback(null);
}
else
{
_exe.RemoveReadonlyFile("romfile.md");
}
if (has32xBios)
{
_exe.RemoveReadonlyFile("32x.g");
_exe.RemoveReadonlyFile("32x.m");
_exe.RemoveReadonlyFile("32x.s");
}
2017-07-02 17:47:43 +00:00
PostInit();
ControllerDefinition = PicoDriveController;
DeterministicEmulation = deterministic;
2017-07-03 00:46:01 +00:00
_core.SetCDReadCallback(_cdcallback);
2017-07-09 15:56:18 +00:00
_isPal = _core.IsPal();
VsyncNumerator = _isPal ? 53203424 : 53693175;
VsyncDenominator = _isPal ? 3420 * 313 : 3420 * 262;
2017-07-02 17:47:43 +00:00
}
public bool Is32xActive => _core.Is32xActive();
2017-07-09 15:56:18 +00:00
public static readonly ControllerDefinition PicoDriveController = new ControllerDefinition
{
Name = "PicoDrive Genesis Controller",
BoolButtons =
{
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 A", "P1 B", "P1 C", "P1 Start", "P1 X", "P1 Y", "P1 Z", "P1 Mode",
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 A", "P2 B", "P2 C", "P2 Start", "P2 X", "P2 Y", "P2 Z", "P2 Mode",
"Power", "Reset"
}
};
private static readonly string[] ButtonOrders =
{
"P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 B", "P1 C", "P1 A", "P1 Start", "P1 Z", "P1 Y", "P1 X", "P1 Mode",
"P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 B", "P2 C", "P2 A", "P2 Start", "P2 Z", "P2 Y", "P2 X", "P2 Mode",
"Power", "Reset"
};
2017-07-02 17:47:43 +00:00
protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound)
{
var b = 0;
var v = 1;
foreach (var s in ButtonOrders)
{
if (controller.IsPressed(s))
b |= v;
v <<= 1;
}
2017-07-03 00:46:01 +00:00
DriveLightOn = false;
return new LibPicoDrive.FrameInfo { Buttons = b };
2017-07-02 17:47:43 +00:00
}
2017-07-03 00:46:01 +00:00
private void CDRead(int lba, IntPtr dest, bool audio)
{
if (audio)
{
byte[] data = new byte[2352];
if (lba < _cd.Session1.LeadoutLBA && lba >= _cd.Session1.Tracks[2].LBA)
2017-07-03 00:46:01 +00:00
{
_cdReader.ReadLBA_2352(lba, data, 0);
}
Marshal.Copy(data, 0, dest, 2352);
}
else
{
byte[] data = new byte[2048];
_cdReader.ReadLBA_2048(lba, data, 0);
Marshal.Copy(data, 0, dest, 2048);
DriveLightOn = true;
}
}
protected override void LoadStateBinaryInternal(BinaryReader reader)
{
_core.SetCDReadCallback(_cdcallback);
}
#region IDriveLight
public bool DriveLightEnabled { get; private set; }
public bool DriveLightOn { get; private set; }
#endregion
#region IRegionable
public DisplayType Region => _isPal ? DisplayType.PAL : DisplayType.NTSC;
#endregion
2017-07-02 17:47:43 +00:00
}
}