support bsnes xml files and super road blaster MSU-1 game

This commit is contained in:
zeromus 2013-04-24 22:09:11 +00:00
parent f3a8cee8bc
commit df99f36464
7 changed files with 114 additions and 41 deletions

View File

@ -261,16 +261,18 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
public override int Read(byte[] buffer, int offset, int count)
{
if (buffer.Length < offset + count) throw new IndexOutOfRangeException();
fixed (byte* pbuffer = &buffer[offset])
buf.Read((IntPtr)pbuffer, count);
if(buffer.Length != 0)
fixed (byte* pbuffer = &buffer[offset])
buf.Read((IntPtr)pbuffer, count);
return count;
}
public override void Write(byte[] buffer, int offset, int count)
{
if (buffer.Length < offset + count) throw new IndexOutOfRangeException();
fixed (byte* pbuffer = &buffer[offset])
buf.Write((IntPtr)pbuffer, count);
if(buffer.Length != 0)
fixed (byte* pbuffer = &buffer[offset])
buf.Write((IntPtr)pbuffer, count);
}
}
@ -646,11 +648,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
return ret;
}
public bool snes_load_cartridge_normal(string rom_xml, byte[] rom_data)
public bool snes_load_cartridge_normal(byte[] rom_xml, byte[] rom_data)
{
WritePipeMessage(eMessage.eMessage_snes_load_cartridge_normal);
WritePipeString(rom_xml ?? "");
WritePipeBlob(rom_data);
WritePipeBlob(rom_xml ?? new byte[0]);
WritePipeBlob(rom_data ?? new byte[0]);
//not a very obvious order.. because we do tons of work immediately after the last param goes down and need to answer messages
WaitForCompletion();
bool ret = brPipe.ReadBoolean();

View File

@ -9,6 +9,8 @@
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Collections.Generic;
using System.Runtime.InteropServices;
@ -101,15 +103,36 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
string snes_path_request(int slot, string hint)
{
//heres how to get MSU-1 working:
//if (hint == "msu1.rom") return @"c:\roms\SuperRoadBlaster\SuperRoadBlaster.msu";
//if (Path.GetExtension(hint).ToLower() == ".pcm")
// return Path.Combine(@"c:\roms\SuperRoadBlaster\", hint);
//to do this accurately, we should be loading the xml file.
//perhaps, if we do that, bsnes will be asking us for the correct paths. at the very least, we could parse the xml ourselves and return the correct thing for msu1.rom
//every rom requests msu1.rom... why? who knows.
//also handle msu-1 pcm files here
bool is_msu1_rom = hint == "msu1.rom";
bool is_msu1_pcm = Path.GetExtension(hint).ToLower() == ".pcm";
if (is_msu1_rom || is_msu1_pcm)
{
//well, check if we have an msu-1 xml
if (romxml != null && romxml["cartridge"] != null && romxml["cartridge"]["msu1"] != null)
{
var msu1 = romxml["cartridge"]["msu1"];
if (is_msu1_rom && msu1["rom"].Attributes["name"] != null)
return CoreComm.AcquireSubfilePath(msu1["rom"].Attributes["name"].Value);
if (is_msu1_pcm)
{
//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 CoreComm.AcquireSubfilePath(child.Attributes["name"].Value);
}
}
}
//every rom requests this byuu homemade rom
if (hint == "msu1.rom") return "";
//not found.. what to do? (every rom will get here when msu1.rom is requested)
return "";
}
//build romfilename
string test = Path.Combine(CoreComm.SNES_FirmwaresPath ?? "", hint);
@ -143,6 +166,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
}
public LibsnesApi api;
System.Xml.XmlDocument romxml;
public LibsnesCore(CoreComm comm)
{
@ -155,7 +179,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
LibsnesApi.snes_trace_t tracecb;
LibsnesApi.snes_audio_sample_t soundcb;
public void Load(GameInfo game, byte[] romData, byte[] sgbRomData, bool DeterministicEmulation)
public void Load(GameInfo game, byte[] romData, byte[] sgbRomData, bool DeterministicEmulation, byte[] xmlData)
{
ScanlineHookManager = new MyScanlineHookManager(this);
@ -181,12 +205,13 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
InitAudio();
//strip header
if ((romData.Length & 0x7FFF) == 512)
{
var newData = new byte[romData.Length - 512];
Array.Copy(romData, 512, newData, 0, newData.Length);
romData = newData;
}
if(romData != null)
if ((romData.Length & 0x7FFF) == 512)
{
var newData = new byte[romData.Length - 512];
Array.Copy(romData, 512, newData, 0, newData.Length);
romData = newData;
}
if (game["SGB"])
{
@ -197,8 +222,22 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
}
else
{
//we may need to get some information out of the cart, even during the following bootup/load process
if (xmlData != null)
{
romxml = new System.Xml.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 :/
if (romxml["cartridge"] != null && romxml["cartridge"]["rom"] != null)
romData = File.ReadAllBytes(CoreComm.AcquireSubfilePath(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 = "SNES";
if (!api.snes_load_cartridge_normal(null, romData))
if (!api.snes_load_cartridge_normal(xmlData, romData))
throw new Exception("snes_load_cartridge_normal() failed");
}
@ -822,14 +861,15 @@ namespace BizHawk.Emulation.Consoles.Nintendo.SNES
{
MemoryDomains = new List<MemoryDomain>();
var romDomain = new MemoryDomain("CARTROM", romData.Length, Endian.Little,
(addr) => romData[addr],
(addr, value) => romData[addr] = value);
if (romData != null)
{
var romDomain = new MemoryDomain("CARTROM", romData.Length, Endian.Little,
(addr) => romData[addr],
(addr, value) => romData[addr] = value);
MemoryDomains.Add(romDomain);
}
MainMemory = MakeMemoryDomain("WRAM", LibsnesApi.SNES_MEMORY.WRAM, Endian.Little);
MemoryDomains.Add(romDomain);
//someone needs to comprehensively address these in SGB mode, and go hook them up in the gameboy core
if (!IsSGB)

View File

@ -1,4 +1,6 @@
using System.Text;
using System;
using System.IO;
using System.Text;
namespace BizHawk
{
public class CoreComm
@ -15,6 +17,8 @@ namespace BizHawk
public string SNES_FirmwaresPath;
public string C64_FirmwaresPath;
public Func<string, string> AcquireSubfilePath;
public string SNES_ExePath;
public string SNES_Profile;
public bool SNES_UseRingBuffer;

View File

@ -1793,7 +1793,7 @@ namespace BizHawk.MultiClient
if (path == null) return false;
using (var file = new HawkFile())
{
string[] romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL" };
string[] romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML" };
//lets not use this unless we need to
//file.NonArchiveExtensions = romExtensions;
@ -1927,6 +1927,17 @@ namespace BizHawk.MultiClient
rom = new RomGame(file);
game = rom.GameInfo;
bool isXml = false;
//right now, xml is always snes.
//later, we may need to inspect the XML ourselves to dispatch it to the correct system (if any other systems ever use xml...)
if (file.Extension.ToLower() == ".xml")
{
game.System = "SNES";
isXml = true;
}
RETRY:
switch (game.System)
{
@ -1934,9 +1945,20 @@ namespace BizHawk.MultiClient
{
game.System = "SNES";
nextComm.SNES_ExePath = SNES_Prepare(Global.Config.SNESProfile);
//this isnt completely correct. might need to deal with the archive somehow.
//once done, code should be factored out to be useful in other platforms as well
//BUT!!! right now bsnes needs to open the file itself. lame.
//nextComm.AcquireSubfile = (subpath) =>
// File.OpenRead(Path.Combine(Path.GetDirectoryName(path),subpath));
nextComm.AcquireSubfilePath = (subpath) =>
Path.Combine(Path.GetDirectoryName(path),subpath);
var snes = new LibsnesCore(nextComm);
nextEmulator = snes;
snes.Load(game, rom.FileData, null, deterministicemulation);
byte[] romData = isXml?null:rom.FileData;
byte[] xmlData = isXml?rom.FileData:null;
snes.Load(game, romData, null, deterministicemulation, xmlData);
}
break;
case "SMS":
@ -2081,7 +2103,7 @@ namespace BizHawk.MultiClient
var snes = new LibsnesCore(nextComm);
nextEmulator = snes;
game.FirmwareHash = Util.BytesToHexString(System.Security.Cryptography.SHA1.Create().ComputeHash(sgbrom));
snes.Load(game, rom.FileData, sgbrom, deterministicemulation);
snes.Load(game, rom.FileData, sgbrom, deterministicemulation, null);
}
}
//}
@ -3596,11 +3618,11 @@ namespace BizHawk.MultiClient
if (INTERIM)
{
ofd.Filter = FormatFilter(
"Rom Files", "*.nes;*.fds;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.cue;*.exe;*.gb;*.gbc;*.gen;*.md;*.col;.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.sgb;%ARCH%",
"Rom Files", "*.nes;*.fds;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.cue;*.exe;*.gb;*.gbc;*.gen;*.md;*.col;.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.sgb;*.xml;%ARCH%",
"Music Files", "*.psf;*.sid",
"Disc Images", "*.cue",
"NES", "*.nes;*.fds;%ARCH%",
"Super NES", "*.smc;*.sfc;%ARCH%",
"Super NES", "*.smc;*.sfc;*.xml;%ARCH%",
"Master System", "*.sms;*.gg;*.sg;%ARCH%",
"PC Engine", "*.pce;*.sgx;*.cue;%ARCH%",
"TI-83", "*.rom;%ARCH%",
@ -3621,10 +3643,10 @@ namespace BizHawk.MultiClient
else
{
ofd.Filter = FormatFilter(
"Rom Files", "*.nes;*.fds;*.sms;*.gg;*.sg;*.gb;*.gbc;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.smc;*.sfc;*.a26;*.a78;*.col;*.rom;*.cue;*.sgb;%ARCH%",
"Rom Files", "*.nes;*.fds;*.sms;*.gg;*.sg;*.gb;*.gbc;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.smc;*.sfc;*.a26;*.a78;*.col;*.rom;*.cue;*.sgb;*.xml;%ARCH%",
"Disc Images", "*.cue",
"NES", "*.nes;*.fds;%ARCH%",
"Super NES", "*.smc;*.sfc;%ARCH%",
"Super NES", "*.smc;*.sfc;*.xml;%ARCH%",
"Gameboy", "*.gb;*.gbc;*.sgb;%ARCH%",
"Master System", "*.sms;*.gg;*.sg;%ARCH%",
"PC Engine", "*.pce;*.sgx;*.cue;%ARCH%",

View File

@ -507,11 +507,16 @@ void RunMessageLoop()
case eMessage_snes_load_cartridge_normal:
{
std::string xml = ReadPipeString();
Blob rom_data = ReadPipeBlob();
Blob xml = ReadPipeBlob();
xml.push_back(0); //make sure the xml is null terminated
const char* xmlptr = NULL;
if(xml != "") xmlptr = xml.c_str();
bool ret = snes_load_cartridge_normal(xmlptr,(unsigned char*)&rom_data[0],rom_data.size());
if(xml.size() != 1) xmlptr = &xml[0];
Blob rom_data = ReadPipeBlob();
const unsigned char* rom_ptr = NULL;
if(rom_data.size() != 0) rom_ptr = (unsigned char*)&rom_data[0];
bool ret = snes_load_cartridge_normal(xmlptr,rom_ptr,rom_data.size());
WritePipe(eMessage_Complete);
WritePipe((char)(ret?1:0));
break;