BSNESv115+: Some general cleanup, remove nonfunctional msu1 code

This commit is contained in:
Morilli 2022-03-25 07:16:00 +01:00
parent b0a2c76d72
commit da2a20e55b
8 changed files with 52 additions and 174 deletions

Binary file not shown.

View File

@ -57,9 +57,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
public abstract int snes_serialized_size();
[BizImport(CallingConvention.Cdecl)]
public abstract void snes_load_cartridge_normal(string baseRomPath, byte[] romData, int romSize);
public abstract void snes_load_cartridge_normal(byte[] romData, int romSize);
[BizImport(CallingConvention.Cdecl)]
public abstract void snes_load_cartridge_super_gameboy(string baseRomPath, byte[] romData, byte[] sgbRomData, ulong mergedRomSizes);
public abstract void snes_load_cartridge_super_gameboy(byte[] romData, byte[] sgbRomData, int romSize, int sgbRomSize);
[BizImport(CallingConvention.Cdecl)]
public abstract void snes_get_cpu_registers(ref BsnesApi.CpuRegisters registers);
@ -115,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
Filename = "bsnes.wbx",
Path = dllPath,
SbrkHeapSizeKB = 12 * 1024,
InvisibleHeapSizeKB = 136 * 1024, // TODO: Roms get saved here and in mmap, consider consolidating?
InvisibleHeapSizeKB = 140 * 1024, // TODO: Roms get saved here and in mmap, consider consolidating?
MmapHeapSizeKB = 33 * 1024, // TODO: check whether this needs to be larger; it depends on the rom size
PlainHeapSizeKB = 1 * 1024,
SealedHeapSizeKB = 0,

View File

@ -67,7 +67,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
public int Frame { get; private set; }
public string SystemId { get; }
public string SystemId => VSystemID.Raw.SNES;
public bool DeterministicEmulation => true;
public void ResetCounters()

View File

@ -4,6 +4,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
{
public partial class BsnesCore : IRegionable
{
private readonly BsnesApi.SNES_REGION _region;
public DisplayType Region => _region == BsnesApi.SNES_REGION.NTSC
? DisplayType.NTSC
: DisplayType.PAL;

View File

@ -1,8 +1,5 @@
using System;
using System.Linq;
using System.Xml;
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components.W65816;
@ -15,31 +12,22 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
[ServiceNotApplicable(new[] { typeof(IDriveLight) })]
public unsafe partial class BsnesCore : IEmulator, IDebuggable, IVideoProvider, ISaveRam, IStatable, IInputPollable, IRegionable, ISettable<BsnesCore.SnesSettings, BsnesCore.SnesSyncSettings>
{
private BsnesApi.SNES_REGION _region;
[CoreConstructor(VSystemID.Raw.SGB)]
[CoreConstructor(VSystemID.Raw.SNES)]
public BsnesCore(GameInfo game, byte[] rom, CoreComm comm,
SnesSettings settings, SnesSyncSettings syncSettings)
:this(game, rom, null, null, comm, settings, syncSettings)
{}
public BsnesCore(GameInfo game, byte[] romData, byte[] xmlData, string baseRomPath, CoreComm comm,
SnesSettings settings, SnesSyncSettings syncSettings)
public BsnesCore(CoreLoadParameters<SnesSettings, SnesSyncSettings> loadParameters)
{
_baseRomPath = baseRomPath;
var ser = new BasicServiceProvider(this);
ServiceProvider = ser;
CoreComm = comm;
CoreComm = loadParameters.Comm;
_settings = loadParameters.Settings ?? new SnesSettings();
_syncSettings = loadParameters.SyncSettings ?? new SnesSyncSettings();
IsSGB = loadParameters.Game.System == VSystemID.Raw.SGB;
byte[] sgbRomData = null;
_settings = settings ?? new SnesSettings();
_syncSettings = syncSettings ?? new SnesSyncSettings();
if (game.System == VSystemID.Raw.SGB)
if (IsSGB)
{
if ((romData[0x143] & 0xc0) == 0xc0)
if ((loadParameters.Roms[0].RomData[0x143] & 0xc0) == 0xc0)
{
throw new CGBNotSupportedException();
}
@ -48,7 +36,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("SNES", "Rom_SGB2"), "SGB2 Rom is required for SGB2 emulation.")
: CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("SNES", "Rom_SGB"), "SGB1 Rom is required for SGB1 emulation.");
game.FirmwareHash = SHA1Checksum.ComputeDigestHex(sgbRomData);
loadParameters.Game.FirmwareHash = SHA1Checksum.ComputeDigestHex(sgbRomData);
}
BsnesApi.SnesCallbacks callbacks = new()
@ -70,7 +58,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
_controllers = new BsnesControllers(_syncSettings);
generate_palette();
// TODO: massive random hack till waterboxhost gets fixed to support 5+ args
BsnesApi.SnesInitData snesInitData = new()
{
entropy = _syncSettings.Entropy,
@ -87,52 +74,19 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
InitAudio();
ser.Register<ISoundProvider>(_resampler);
if (game.System == VSystemID.Raw.SGB)
if (IsSGB)
{
IsSGB = true;
SystemId = VSystemID.Raw.SNES;
ser.Register<IBoardInfo>(new SGBBoardInfo());
_currLoadParams = new LoadParams
{
type = LoadParamType.SuperGameBoy,
baseRomPath = baseRomPath,
romData = sgbRomData,
sgbRomData = romData
};
Api.core.snes_load_cartridge_super_gameboy(sgbRomData, loadParameters.Roms[0].RomData,
sgbRomData!.Length, loadParameters.Roms[0].RomData.Length);
}
else
{
// we may need to get some information out of the cart, even during the following bootup/load process
if (xmlData != null)
{
_romxml = new XmlDocument();
_romxml.Load(new MemoryStream(xmlData));
// bsnes wont inspect the xml to load the necessary sfc file.
// so, we have to do that here and pass it in as the romData :/
// TODO: uhh i have no idea what the xml is or whether this below code is needed
if (_romxml["cartridge"]?["rom"] != null)
{
romData = File.ReadAllBytes(PathSubfile(_romxml["cartridge"]["rom"].Attributes["name"].Value));
}
else
{
throw new Exception("Could not find rom file specification in xml file. Please check the integrity of your xml file");
}
}
SystemId = VSystemID.Raw.SNES;
_currLoadParams = new LoadParams
{
type = LoadParamType.Normal,
baseRomPath = baseRomPath,
romData = romData
};
Api.core.snes_load_cartridge_normal(loadParameters.Roms[0].RomData, loadParameters.Roms[0].RomData.Length);
}
LoadCurrent();
_region = Api.core.snes_get_region();
if (_region == BsnesApi.SNES_REGION.NTSC)
{
@ -159,16 +113,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
private CoreComm CoreComm { get; }
private readonly string _baseRomPath;
private string PathSubfile(string fname) => Path.Combine(_baseRomPath, fname);
private readonly BsnesControllers _controllers;
private readonly ITraceable _tracer;
private readonly XmlDocument _romxml;
private IController _controller;
private readonly LoadParams _currLoadParams;
private SpeexResampler _resampler;
private bool _disposed;
@ -183,44 +131,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
private string snes_path_request(int slot, string hint, bool required)
{
// TODO: this msu1 handling code is outdated and needs to be remade from someone with knowledge.
// every rom requests msu1.rom... why? who knows.
// also handle msu-1 pcm files here
bool isMsu1Rom = hint == "msu1/data.rom";
bool isMsu1Pcm = Path.GetExtension(hint).ToLower() == ".pcm";
if (isMsu1Rom || isMsu1Pcm)
{
// well, check if we have an msu-1 xml
if (_romxml?["cartridge"]?["msu1"] != null)
{
var msu1 = _romxml["cartridge"]["msu1"];
if (isMsu1Rom && msu1["rom"]?.Attributes["name"] != null)
{
return PathSubfile(msu1["rom"].Attributes["name"].Value);
}
if (isMsu1Pcm)
{
// return @"D:\roms\snes\SuperRoadBlaster\SuperRoadBlaster-1.pcm";
// return "";
int wantsTrackNumber = int.Parse(hint.Replace("track-", "").Replace(".pcm", ""));
wantsTrackNumber++;
string wantsTrackString = wantsTrackNumber.ToString();
foreach (var child in msu1.ChildNodes.Cast<XmlNode>())
{
if (child.Name == "track" && child.Attributes["number"].Value == wantsTrackString)
{
return PathSubfile(child.Attributes["name"].Value);
}
}
}
}
// not found.. what to do? (every rom will get here when msu1.rom is requested)
return "";
}
// not MSU-1. ok.
if (hint == "save.ram")
{
// core asked for saveram, but the interface isn't designed to be able to handle this.
@ -252,7 +162,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
string ret = "";
FirmwareID fwid = new(firmwareSystem, firmwareId);
const string MISSING_FIRMWARE_MSG = "Game may function incorrectly without the requested firmware.";
var data = required
byte[] data = required
? CoreComm.CoreFileProvider.GetFirmwareOrThrow(fwid, MISSING_FIRMWARE_MSG)
: CoreComm.CoreFileProvider.GetFirmware(fwid, MISSING_FIRMWARE_MSG);
if (data != null)
@ -267,30 +177,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
return ret;
}
private enum LoadParamType
{
Normal, SuperGameBoy
}
private struct LoadParams
{
public LoadParamType type;
public string baseRomPath;
public byte[] romData;
public byte[] sgbRomData;
}
private void LoadCurrent()
{
if (_currLoadParams.type == LoadParamType.Normal)
Api.core.snes_load_cartridge_normal(_currLoadParams.baseRomPath, _currLoadParams.romData, _currLoadParams.romData.Length);
else
Api.core.snes_load_cartridge_super_gameboy(_currLoadParams.baseRomPath, _currLoadParams.romData,
_currLoadParams.sgbRomData, (ulong) _currLoadParams.romData.Length << 32 | (uint)_currLoadParams.sgbRomData.Length);
_region = Api.core.snes_get_region();
}
/// <param name="port">0 or 1, corresponding to L and R physical ports on the snes</param>
/// <param name="index">meaningless for most controllers. for multitap, 0-3 for which multitap controller</param>
/// <param name="id">button ID enum; in the case of a regular controller, this corresponds to shift register position</param>

View File

@ -197,10 +197,8 @@ EXPORT void snes_unserialize(const uint8_t* data, int size)
}
EXPORT void snes_load_cartridge_normal(
const char* base_rom_path, const uint8_t* rom_data, int rom_size
const uint8_t* rom_data, int rom_size
) {
program->superFamicom.location = base_rom_path;
program->superFamicom.raw_data.resize(rom_size);
memcpy(program->superFamicom.raw_data.data(), rom_data, rom_size);
@ -209,12 +207,8 @@ EXPORT void snes_load_cartridge_normal(
// TODO: merged_rom_sizes is bad, fix this
EXPORT void snes_load_cartridge_super_gameboy(
const char* base_rom_path, const uint8_t* rom_data, const uint8_t* sgb_rom_data, uint64_t merged_rom_sizes
const uint8_t* rom_data, const uint8_t* sgb_rom_data, int rom_size, int sgb_rom_size
) {
int rom_size = merged_rom_sizes >> 32;
int sgb_rom_size = merged_rom_sizes & 0xffffffff;
program->superFamicom.location = base_rom_path;
program->superFamicom.raw_data.resize(rom_size);
memcpy(program->superFamicom.raw_data.data(), rom_data, rom_size);
@ -292,8 +286,8 @@ uint8_t* snes_get_effective_saveram(int* ram_size) {
return cartridge.ram.data();
}
EXPORT int snes_get_region(void) {
return Region::PAL();
EXPORT System::Region snes_get_region(void) {
return SuperFamicom::system.region();
}
EXPORT char snes_get_mapper(void) {

View File

@ -8,7 +8,7 @@ typedef void (*snes_audio_sample_t)(int16_t left, int16_t right);
typedef int16_t (*snes_input_poll_t)(int port, int index, int id);
typedef void (*snes_controller_latch_t)(void);
typedef void (*snes_no_lag_t)(bool sgb_poll);
typedef char* (*snes_path_request_t)(int slot, const char* hint, int required);
typedef char* (*snes_path_request_t)(int slot, const char* hint, bool required);
typedef void (*snes_trace_t)(const char* disassembly, const char* register_info);
typedef void (*snes_read_hook_t)(uint32_t address);
typedef void (*snes_write_hook_t)(uint32_t address, uint8_t value);

View File

@ -28,7 +28,6 @@ struct Program : Emulator::Platform
auto execHook(uint address) -> void override;
auto load() -> void;
auto loadFile(string location) -> vector<uint8_t>;
auto loadSuperFamicom() -> bool;
auto loadGameBoy() -> bool;
auto loadBSMemory() -> bool;
@ -46,10 +45,7 @@ struct Program : Emulator::Platform
public:
struct Game {
explicit operator bool() const { return (bool)location; }
string option;
string location;
string manifest;
Markup::Node document;
boolean patched;
@ -94,25 +90,25 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
shared_pointer<vfs::file> result;
if (name == "ipl.rom" && mode == vfs::file::mode::read) {
if (name == "ipl.rom" && mode == File::Read) {
result = vfs::memory::file::open(iplrom, sizeof(iplrom));
}
if (name == "boards.bml" && mode == vfs::file::mode::read) {
if (name == "boards.bml" && mode == File::Read) {
result = vfs::memory::file::open(Boards, sizeof(Boards));
}
if (id == 1) { //Super Famicom
if (name == "manifest.bml" && mode == vfs::file::mode::read) {
if (name == "manifest.bml" && mode == File::Read) {
result = vfs::memory::file::open(superFamicom.manifest.data<uint8_t>(), superFamicom.manifest.size());
}
else if (name == "program.rom" && mode == vfs::file::mode::read) {
else if (name == "program.rom" && mode == File::Read) {
result = vfs::memory::file::open(superFamicom.program.data(), superFamicom.program.size());
}
else if (name == "data.rom" && mode == vfs::file::mode::read) {
else if (name == "data.rom" && mode == File::Read) {
result = vfs::memory::file::open(superFamicom.data.data(), superFamicom.data.size());
}
else if (name == "expansion.rom" && mode == vfs::file::mode::read) {
else if (name == "expansion.rom" && mode == File::Read) {
result = vfs::memory::file::open(superFamicom.expansion.data(), superFamicom.expansion.size());
}
else {
@ -120,10 +116,10 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
}
}
else if (id == 2) { //Game Boy
if (name == "manifest.bml" && mode == vfs::file::mode::read) {
if (name == "manifest.bml" && mode == File::Read) {
result = vfs::memory::file::open(gameBoy.manifest.data<uint8_t>(), gameBoy.manifest.size());
}
else if (name == "program.rom" && mode == vfs::file::mode::read) {
else if (name == "program.rom" && mode == File::Read) {
result = vfs::memory::file::open(gameBoy.program.data(), gameBoy.program.size());
}
else {
@ -131,10 +127,10 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
}
}
else if (id == 3) { //BS Memory
if (name == "manifest.bml" && mode == vfs::file::mode::read) {
if (name == "manifest.bml" && mode == File::Read) {
result = vfs::memory::file::open(bsMemory.manifest.data<uint8_t>(), bsMemory.manifest.size());
}
else if (name == "program.rom" && mode == vfs::file::mode::read) {
else if (name == "program.rom" && mode == File::Read) {
result = vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
}
else if(name == "program.flash") {
@ -154,12 +150,12 @@ auto Program::openFileSuperFamicom(string name, vfs::file::mode mode, bool requi
// TODO: the original bsnes code handles a lot more paths; *.data.ram, time.rtc and download.ram
// I believe none of these can currently be correctly served by bizhawk and I therefor ignore them here
// This should probably be changed? Not sure how much can break from not having them
if(name == "msu1/data.rom" || name.match("msu1/track*.pcm") || name == "save.ram")
if(name == "save.ram")
{
return vfs::fs::file::open(snesCallbacks.snes_path_request(ID::SuperFamicom, name, required), mode);
}
if(name == "arm6.program.rom" && mode == vfs::file::mode::read) {
if(name == "arm6.program.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0x28000) {
return vfs::memory::file::open(&superFamicom.firmware.data()[0x00000], 0x20000);
}
@ -168,18 +164,18 @@ auto Program::openFileSuperFamicom(string name, vfs::file::mode mode, bool requi
}
}
if(name == "arm6.data.rom" && mode == vfs::file::mode::read) {
if(name == "arm6.data.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0x28000) {
return vfs::memory::file::open(&superFamicom.firmware.data()[0x20000], 0x08000);
}
if(auto memory = superFamicom.document["game/board/memory(type=ROM,content=Data,architecture=ARM6)"]) {
auto file = vfs::fs::file::open(snesCallbacks.snes_path_request(ID::SuperFamicom, memory["identifier"].text().downcase(), required), mode);
if (file) file->seek(0x20000, vfs::file::index::absolute);
if (file) file->seek(0x20000);
return file;
}
}
if(name == "hg51bs169.data.rom" && mode == vfs::file::mode::read) {
if(name == "hg51bs169.data.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0xc00) {
return vfs::memory::file::open(superFamicom.firmware.data(), superFamicom.firmware.size());
}
@ -188,7 +184,7 @@ auto Program::openFileSuperFamicom(string name, vfs::file::mode mode, bool requi
}
}
if(name == "lr35902.boot.rom" && mode == vfs::file::mode::read) {
if(name == "lr35902.boot.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0x100) {
return vfs::memory::file::open(superFamicom.firmware.data(), superFamicom.firmware.size());
}
@ -197,7 +193,7 @@ auto Program::openFileSuperFamicom(string name, vfs::file::mode mode, bool requi
}
}
if(name == "upd7725.program.rom" && mode == vfs::file::mode::read) {
if(name == "upd7725.program.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0x2000) {
return vfs::memory::file::open(&superFamicom.firmware.data()[0x0000], 0x1800);
}
@ -207,18 +203,18 @@ auto Program::openFileSuperFamicom(string name, vfs::file::mode mode, bool requi
}
}
if(name == "upd7725.data.rom" && mode == vfs::file::mode::read) {
if(name == "upd7725.data.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0x2000) {
return vfs::memory::file::open(&superFamicom.firmware.data()[0x1800], 0x0800);
}
if(auto memory = superFamicom.document["game/board/memory(type=ROM,content=Data,architecture=uPD7725)"]) {
auto file = vfs::fs::file::open(snesCallbacks.snes_path_request(ID::SuperFamicom, memory["identifier"].text().downcase(), required), mode);
if (file) file->seek(0x1800, vfs::file::index::absolute);
if (file) file->seek(0x1800);
return file;
}
}
if(name == "upd96050.program.rom" && mode == vfs::file::mode::read) {
if(name == "upd96050.program.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0xd000) {
return vfs::memory::file::open(&superFamicom.firmware.data()[0x0000], 0xc000);
}
@ -228,13 +224,13 @@ auto Program::openFileSuperFamicom(string name, vfs::file::mode mode, bool requi
}
}
if(name == "upd96050.data.rom" && mode == vfs::file::mode::read) {
if(name == "upd96050.data.rom" && mode == File::Read) {
if(superFamicom.firmware.size() == 0xd000) {
return vfs::memory::file::open(&superFamicom.firmware.data()[0xc000], 0x1000);
}
if(auto memory = superFamicom.document["game/board/memory(type=ROM,content=Data,architecture=uPD96050)"]) {
auto file = vfs::fs::file::open(snesCallbacks.snes_path_request(ID::SuperFamicom, memory["identifier"].text().downcase(), required), mode);
if (file) file->seek(0xc000, vfs::file::index::absolute);
if (file) file->seek(0xc000);
return file;
}
}
@ -355,12 +351,11 @@ auto Program::load(uint id, string name, string type, vector<string> options) ->
auto Program::loadSuperFamicom() -> bool
{
vector<uint8_t>& rom = superFamicom.raw_data;
fprintf(stderr, "location: \"%s\"\n", superFamicom.location.data());
fprintf(stderr, "rom size: %ld\n", rom.size());
if(rom.size() < 0x8000) return false;
auto heuristics = Heuristics::SuperFamicom(rom, superFamicom.location);
auto heuristics = Heuristics::SuperFamicom(rom, "");
superFamicom.title = heuristics.title();
switch (regionOverride) {
@ -397,7 +392,7 @@ auto Program::loadSuperFamicom() -> bool
auto Program::loadGameBoy() -> bool {
if (gameBoy.program.size() < 0x4000) return false;
auto heuristics = Heuristics::GameBoy(gameBoy.program, gameBoy.location);
auto heuristics = Heuristics::GameBoy(gameBoy.program, "");
gameBoy.manifest = heuristics.manifest();
gameBoy.document = BML::unserialize(gameBoy.manifest);
@ -408,7 +403,7 @@ auto Program::loadGameBoy() -> bool {
auto Program::loadBSMemory() -> bool {
if (bsMemory.program.size() < 0x8000) return false;
auto heuristics = Heuristics::BSMemory(bsMemory.program, gameBoy.location);
auto heuristics = Heuristics::BSMemory(bsMemory.program, "");
bsMemory.manifest = heuristics.manifest();
bsMemory.document = BML::unserialize(bsMemory.manifest);