[NES] ppu fixes and improved rom classification infrastructure
This commit is contained in:
parent
d7ba739b30
commit
4b177ca8d1
|
@ -55,6 +55,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="Consoles\Calculator\TI83.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\NROM.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\BoardDetector.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\NES.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Palettes.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\PPU.cs" />
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
//http://nesdev.parodius.com/bbs/viewtopic.php?p=4571&sid=db4c7e35316cc5d734606dd02f11dccb
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using BizHawk.Emulation.CPUs.M6502;
|
||||
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Nintendo
|
||||
{
|
||||
partial class NES
|
||||
{
|
||||
static class BoardDetector
|
||||
{
|
||||
public static string Detect(RomInfo romInfo)
|
||||
{
|
||||
string key = string.Format("{0} {1} {2}",romInfo.MapperNumber,romInfo.PRG_Size,romInfo.CHR_Size);
|
||||
string board;
|
||||
Table.TryGetValue(key, out board);
|
||||
return board;
|
||||
}
|
||||
|
||||
public static Dictionary<string,string> Table = new Dictionary<string,string>();
|
||||
static BoardDetector()
|
||||
{
|
||||
var sr = new StringReader(ClassifyTable);
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
var parts = line.Split('\t');
|
||||
if (parts.Length < 4) continue;
|
||||
line = line.Replace(parts[0],"");
|
||||
line = line.TrimStart('\t');
|
||||
Table[line] = parts[0];
|
||||
}
|
||||
}
|
||||
//board MAP PRG CHR
|
||||
static string ClassifyTable = @"
|
||||
NROM 0 1 1
|
||||
NROM 0 2 1
|
||||
";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,18 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Nintendo.Boards
|
||||
{
|
||||
public class NROM : NES.NESBoardBase
|
||||
{
|
||||
public virtual void Initialize(NES.RomInfo romInfo, NES nes)
|
||||
{
|
||||
base.Initialize(romInfo, nes);
|
||||
Debug.Assert(romInfo.PRG_Size < 3);
|
||||
}
|
||||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
addr &= (RomInfo.PRG_Size << 14) - 1;
|
||||
return RomInfo.ROM[addr];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,25 +8,53 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
{
|
||||
public partial class NES : IEmulator
|
||||
{
|
||||
//the main rom class that contains all information necessary for the board to operate
|
||||
public class RomInfo
|
||||
{
|
||||
public enum EHeaderType
|
||||
{
|
||||
None, INes
|
||||
}
|
||||
|
||||
public enum EMirrorType
|
||||
{
|
||||
Vertical, Horizontal, Other
|
||||
}
|
||||
|
||||
public EHeaderType HeaderType;
|
||||
public int PRG_Size = -1, CHR_Size = -1, PRAM_Size = -1;
|
||||
public string BoardName;
|
||||
public EMirrorType MirrorType;
|
||||
public bool Battery;
|
||||
|
||||
public int MapperNumber; //it annoys me that this junky mapper number is even in here. it might be nice to wrap this class in something else to contain the MapperNumber
|
||||
|
||||
public string MD5;
|
||||
|
||||
public byte[] ROM, VROM;
|
||||
}
|
||||
|
||||
public interface INESBoard
|
||||
{
|
||||
byte ReadPRG(int addr);
|
||||
byte ReadPPU(int addr);
|
||||
byte ReadPRAM(int addr);
|
||||
void WritePRG(int addr, byte value);
|
||||
void WritePPU(int addr, byte value);
|
||||
void WritePRAM(int addr, byte value);
|
||||
void Initialize(RomInfo romInfo, NES nes);
|
||||
};
|
||||
|
||||
public abstract class NESBoardBase : INESBoard
|
||||
{
|
||||
public void Initialize(RomInfo romInfo, NES nes)
|
||||
public virtual void Initialize(RomInfo romInfo, NES nes)
|
||||
{
|
||||
this.RomInfo = romInfo;
|
||||
this.NES = nes;
|
||||
switch (romInfo.Mirroring)
|
||||
switch (romInfo.MirrorType)
|
||||
{
|
||||
case 0: SetMirroring(0, 0, 1, 1); break;
|
||||
case 1: SetMirroring(0, 1, 0, 1); break;
|
||||
case RomInfo.EMirrorType.Horizontal: SetMirroring(0, 0, 1, 1); break;
|
||||
case RomInfo.EMirrorType.Vertical: SetMirroring(0, 1, 0, 1); break;
|
||||
default: SetMirroring(-1, -1, -1, -1); break; //crash!
|
||||
}
|
||||
}
|
||||
|
@ -42,10 +70,21 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
mirroring[3] = d;
|
||||
}
|
||||
|
||||
int ApplyMirroring(int addr)
|
||||
{
|
||||
int block = (addr >> 10) & 3;
|
||||
block = mirroring[block];
|
||||
int ofs = addr & 0x3FF;
|
||||
return (block << 10) | ofs | 0x2000;
|
||||
}
|
||||
|
||||
|
||||
public virtual byte ReadPRG(int addr) { return RomInfo.ROM[addr];}
|
||||
public virtual void WritePRG(int addr, byte value) { }
|
||||
|
||||
public virtual void WritePRAM(int addr, byte value) { }
|
||||
public virtual byte ReadPRAM(int addr) { return 0xFF; }
|
||||
|
||||
|
||||
public virtual void WritePPU(int addr, byte value)
|
||||
{
|
||||
|
@ -54,10 +93,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
}
|
||||
else
|
||||
{
|
||||
int block = (addr >> 10) & 3;
|
||||
block = mirroring[block];
|
||||
int ofs = addr & 0x3FF;
|
||||
NES.ppu.NTARAM[(block << 10) | ofs] = value;
|
||||
NES.ppu.ppu_defaultWrite(ApplyMirroring(addr), value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,10 +105,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
}
|
||||
else
|
||||
{
|
||||
int block = (addr >> 10)&3;
|
||||
block = mirroring[block];
|
||||
int ofs = addr & 0x3FF;
|
||||
return NES.ppu.NTARAM[(block << 10) | ofs];
|
||||
return NES.ppu.ppu_defaultRead(ApplyMirroring(addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -438,9 +471,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
return input;
|
||||
}
|
||||
|
||||
public class RomInfo
|
||||
public class RomHeaderInfo
|
||||
{
|
||||
public int MapperNo, Mirroring, Num_PRG_Banks, Num_CHR_Banks;
|
||||
public int MapperNo, Mirroring, Num_PRG_Banks, Num_CHR_Banks, Num_PRAM_Banks;
|
||||
public bool Battery;
|
||||
public byte[] ROM, VROM;
|
||||
}
|
||||
|
||||
|
@ -486,15 +520,25 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
public RomInfo Analyze()
|
||||
{
|
||||
var ret = new RomInfo();
|
||||
ret.MapperNo = (ROM_type>>4);
|
||||
ret.MapperNo|=(ROM_type2&0xF0);
|
||||
ret.Mirroring = (ROM_type&1);
|
||||
if((ROM_type&8)!=0) ret.Mirroring=2;
|
||||
ret.Num_PRG_Banks = ROM_size;
|
||||
if (ret.Num_PRG_Banks == 0)
|
||||
ret.Num_PRG_Banks = 256;
|
||||
ret.Num_CHR_Banks = VROM_size;
|
||||
|
||||
ret.MapperNumber = (ROM_type>>4);
|
||||
ret.MapperNumber |= (ROM_type2 & 0xF0);
|
||||
int mirroring = (ROM_type&1);
|
||||
if((ROM_type&8)!=0) mirroring=2;
|
||||
if (mirroring == 0) ret.MirrorType = RomInfo.EMirrorType.Horizontal;
|
||||
else if (mirroring == 1) ret.MirrorType = RomInfo.EMirrorType.Vertical;
|
||||
else ret.MirrorType = RomInfo.EMirrorType.Other;
|
||||
ret.PRG_Size = ROM_size;
|
||||
if (ret.PRG_Size == 0)
|
||||
ret.PRG_Size = 256;
|
||||
ret.CHR_Size = VROM_size;
|
||||
ret.Battery = (ROM_type & 2) != 0;
|
||||
|
||||
fixed (iNES_HEADER* self = &this) ret.PRAM_Size = self->reserve[0];
|
||||
//0 is supposed to mean 1 (for compatibility, as this is an extension to original iNES format)
|
||||
//but we're not worrying about that for now)
|
||||
|
||||
Console.WriteLine("iNES header: map:{0}, mirror:{1}, PRG:{2}, CHR:{3}, PRAM:{4}, bat:{5}", ret.MapperNumber, ret.MirrorType, ret.PRG_Size, ret.CHR_Size, ret.PRAM_Size, ret.Battery ? 1 : 0);
|
||||
|
||||
//fceux calls uppow2(PRG_Banks) here, and also ups the chr size as well
|
||||
//then it does something complicated that i don't understand with making sure it doesnt read too much data
|
||||
//fceux only allows this condition for mappers in the list "not_power2" which is only 228
|
||||
|
@ -503,20 +547,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
}
|
||||
}
|
||||
|
||||
INESBoard Classify(RomInfo info)
|
||||
{
|
||||
//you may think that this should be table driven.. but im not so sure.
|
||||
//i think this should be a backstop eventually, with other classification happening from the game database.
|
||||
//if the gamedatabase has an exact answer for a game then the board can be determined..
|
||||
//otherwise we might try to find a general case handler below.
|
||||
|
||||
if (info.MapperNo == 0 && info.Num_CHR_Banks == 1 && info.Num_PRG_Banks == 2 && info.Mirroring == 1) return new Boards.NROM();
|
||||
return null;
|
||||
}
|
||||
const bool ENABLE_DB = true;
|
||||
|
||||
public unsafe void LoadGame(IGame game)
|
||||
{
|
||||
byte[] file = game.GetRomData();
|
||||
byte[] file = game.GetFileData();
|
||||
if (file.Length < 16) throw new InvalidOperationException("Alleged NES rom too small to be anything useful");
|
||||
fixed (byte* bfile = &file[0])
|
||||
{
|
||||
|
@ -524,14 +559,59 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
if (!header->CheckID()) throw new InvalidOperationException("iNES header not found");
|
||||
header->Cleanup();
|
||||
|
||||
romInfo = header->Analyze();
|
||||
board = Classify(romInfo);
|
||||
//now that we know we have an iNES header, we can try to ignore it.
|
||||
string hash;
|
||||
using (var md5 = System.Security.Cryptography.MD5.Create())
|
||||
{
|
||||
md5.TransformFinalBlock(file, 16, file.Length - 16);
|
||||
hash = Util.BytesToHexString(md5.Hash);
|
||||
}
|
||||
Console.WriteLine("headerless rom hash: {0}", hash);
|
||||
|
||||
GameInfo gi = null;
|
||||
if (ENABLE_DB) gi = Database.CheckDatabase(hash);
|
||||
else Console.WriteLine("database check disabled");
|
||||
|
||||
if (gi == null)
|
||||
{
|
||||
romInfo = header->Analyze();
|
||||
string board = BoardDetector.Detect(romInfo);
|
||||
if (board == null)
|
||||
throw new InvalidOperationException("Couldn't detect board type");
|
||||
romInfo.BoardName = board;
|
||||
Console.WriteLine("board detected as " + board);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("found game in database: {0}", gi.Name);
|
||||
romInfo = new RomInfo();
|
||||
romInfo.MD5 = hash;
|
||||
var dict = gi.ParseOptionsDictionary();
|
||||
if (dict.ContainsKey("board"))
|
||||
romInfo.BoardName = dict["board"];
|
||||
switch (dict["mirror"])
|
||||
{
|
||||
case "V": romInfo.MirrorType = RomInfo.EMirrorType.Vertical; break;
|
||||
case "H": romInfo.MirrorType = RomInfo.EMirrorType.Horizontal; break;
|
||||
}
|
||||
if (dict.ContainsKey("PRG"))
|
||||
romInfo.PRG_Size = int.Parse(dict["PRG"]);
|
||||
if (dict.ContainsKey("CHR"))
|
||||
romInfo.CHR_Size = int.Parse(dict["CHR"]);
|
||||
}
|
||||
|
||||
//construct board (todo)
|
||||
switch (romInfo.BoardName)
|
||||
{
|
||||
case "NROM": board = new Boards.NROM(); break;
|
||||
}
|
||||
|
||||
if (board == null) throw new InvalidOperationException("Couldn't classify NES rom");
|
||||
board.Initialize(romInfo, this);
|
||||
|
||||
//we're going to go ahead and copy these out, just in case we need to pad them alter
|
||||
romInfo.ROM = new byte[romInfo.Num_PRG_Banks * 16 * 1024];
|
||||
romInfo.VROM = new byte[romInfo.Num_CHR_Banks * 8 * 1024];
|
||||
romInfo.ROM = new byte[romInfo.PRG_Size * 16 * 1024];
|
||||
romInfo.VROM = new byte[romInfo.CHR_Size * 8 * 1024];
|
||||
Array.Copy(file, 16, romInfo.ROM, 0, romInfo.ROM.Length);
|
||||
Array.Copy(file, 16 + romInfo.ROM.Length, romInfo.VROM, 0, romInfo.VROM.Length);
|
||||
}
|
||||
|
@ -539,4 +619,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
HardReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//todo
|
||||
//http://blog.ntrq.net/?p=428
|
||||
//cpu bus junk bits
|
|
@ -13,16 +13,32 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
{
|
||||
partial class PPU
|
||||
{
|
||||
//when the ppu issues a write it goes through here and into the game board
|
||||
void ppubus_write(int addr, byte value)
|
||||
{
|
||||
nes.board.WritePPU(addr, value);
|
||||
}
|
||||
|
||||
//when the ppu issues a read it goes through here and into the game board
|
||||
byte ppubus_read(int addr)
|
||||
{
|
||||
return nes.board.ReadPPU(addr);
|
||||
}
|
||||
|
||||
//boards may not respond to a read, in which case this will get called. please apply mirroring logic beforehand
|
||||
public byte ppu_defaultRead(int addr)
|
||||
{
|
||||
addr &= 0x7FF;
|
||||
return NTARAM[addr];
|
||||
}
|
||||
|
||||
//boards may not respond to a write, in which case this will get called. please apply mirroring logic beforehand
|
||||
public void ppu_defaultWrite(int addr, byte value)
|
||||
{
|
||||
addr &= 0x7FF;
|
||||
NTARAM[addr] = value;
|
||||
}
|
||||
|
||||
enum PPUPHASE {
|
||||
VBL, BG, OBJ
|
||||
};
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
public fixed byte oam[4];
|
||||
public fixed byte patterns[2];
|
||||
public byte index;
|
||||
byte pad;
|
||||
public byte present;
|
||||
}
|
||||
|
||||
//TODO - check flashing sirens in werewolf
|
||||
|
@ -249,34 +249,40 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
//look for sprites (was supposed to run concurrent with bg rendering)
|
||||
oamcounts[scanslot] = 0;
|
||||
oamcount = 0;
|
||||
if (sl == 0xb1)
|
||||
{
|
||||
int zzz = 9;
|
||||
}
|
||||
int spriteHeight = reg_2000.obj_size_16 ? 16 : 8;
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
fixed (TempOAM* oam = &oams[scanslot, i])
|
||||
oam->present = 0;
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
int spr = i * 4;
|
||||
if (yp >= OAM[spr] && yp < OAM[spr] + spriteHeight)
|
||||
{
|
||||
//if we already have maxsprites, then this new one causes an overflow,
|
||||
//set the flag and bail out.
|
||||
if (oamcount >= 8 && reg_2001.PPUON)
|
||||
if (yp >= OAM[spr] && yp < OAM[spr] + spriteHeight)
|
||||
{
|
||||
Reg2002_objoverflow = true;
|
||||
if (SPRITELIMIT)
|
||||
break;
|
||||
}
|
||||
//if we already have maxsprites, then this new one causes an overflow,
|
||||
//set the flag and bail out.
|
||||
if (oamcount >= 8 && reg_2001.PPUON)
|
||||
{
|
||||
Reg2002_objoverflow = true;
|
||||
if (SPRITELIMIT)
|
||||
break;
|
||||
}
|
||||
|
||||
//just copy some bytes into the internal sprite buffer
|
||||
for (int j = 0; j < 4; j++)
|
||||
//just copy some bytes into the internal sprite buffer
|
||||
fixed (TempOAM* oam = &oams[scanslot, oamcount])
|
||||
oam->oam[j] = OAM[spr + j];
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
oam->oam[j] = OAM[spr + j];
|
||||
oam->present = 1;
|
||||
}
|
||||
|
||||
//note that we stuff the oam index into [6].
|
||||
//i need to turn this into a struct so we can have fewer magic numbers
|
||||
oams[scanslot, oamcount].index = (byte)i;
|
||||
oamcount++;
|
||||
//note that we stuff the oam index into [6].
|
||||
//i need to turn this into a struct so we can have fewer magic numbers
|
||||
oams[scanslot, oamcount].index = (byte)i;
|
||||
oamcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
oamcounts[scanslot] = oamcount;
|
||||
|
@ -303,11 +309,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
//fetch sprite patterns
|
||||
for (int s = 0; s < MAXSPRITES; s++)
|
||||
{
|
||||
if (sl == 0x9E && s == 1)
|
||||
{
|
||||
int zzz = 9;
|
||||
}
|
||||
|
||||
//if we have hit our eight sprite pattern and we dont have any more sprites, then bail
|
||||
if (s == oamcount && s >= 8)
|
||||
break;
|
||||
|
@ -327,17 +328,24 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
int patternNumber = oam->oam[1];
|
||||
int patternAddress;
|
||||
|
||||
//create deterministic dummy fetch pattern
|
||||
if (oam->present==0)
|
||||
{
|
||||
patternNumber = 0;
|
||||
line = 0;
|
||||
}
|
||||
|
||||
//8x16 sprite handling:
|
||||
if (reg_2000.obj_size_16)
|
||||
{
|
||||
int bank = (patternNumber & 1) << 12;
|
||||
patternNumber = patternNumber & ~1;
|
||||
patternNumber |= (line >> 3);
|
||||
patternNumber |= (line >> 3)&1;
|
||||
patternAddress = (patternNumber << 4) | bank;
|
||||
}
|
||||
else
|
||||
{
|
||||
patternAddress = (patternNumber << 4) | (reg_2000.obj_pattern_hi << 9);
|
||||
patternAddress = (patternNumber << 4) | (reg_2000.obj_pattern_hi << 12);
|
||||
}
|
||||
|
||||
//offset into the pattern for the current line.
|
||||
|
@ -347,6 +355,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
|
||||
//garbage nametable fetches
|
||||
//reset the scroll counter, happens at cycle 304
|
||||
//TODO - compact this logic
|
||||
if (realSprite)
|
||||
{
|
||||
if ((sl == 0) && reg_2001.PPUON)
|
||||
|
|
|
@ -25,12 +25,32 @@ namespace BizHawk
|
|||
return new string[0];
|
||||
return MetaData.Split(';').Where(opt => string.IsNullOrEmpty(opt) == false).ToArray();
|
||||
}
|
||||
|
||||
public Dictionary<string, string> ParseOptionsDictionary()
|
||||
{
|
||||
var ret = new Dictionary<string, string>();
|
||||
foreach (var opt in GetOptions())
|
||||
{
|
||||
var parts = opt.Split('=');
|
||||
var key = parts[0];
|
||||
var value = parts.Length > 1 ? parts[1] : "";
|
||||
ret[key] = value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Database
|
||||
{
|
||||
private static Dictionary<string, GameInfo> db = new Dictionary<string, GameInfo>();
|
||||
|
||||
public static GameInfo CheckDatabase(string hash)
|
||||
{
|
||||
GameInfo ret = null;
|
||||
db.TryGetValue(hash, out ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void LoadDatabase(string path)
|
||||
{
|
||||
using (var reader = new StreamReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
|
||||
|
@ -46,7 +66,7 @@ namespace BizHawk
|
|||
string[] items = line.Split('\t');
|
||||
|
||||
var Game = new GameInfo();
|
||||
Game.hash = items[0];
|
||||
Game.hash = items[0].ToUpper();
|
||||
Game.Name = items[2];
|
||||
Game.System = items[3];
|
||||
Game.MetaData = items.Length >= 6 ? items[5] : null;
|
||||
|
@ -61,13 +81,14 @@ namespace BizHawk
|
|||
|
||||
public static GameInfo GetGameInfo(byte[] RomData, string fileName)
|
||||
{
|
||||
GameInfo ret;
|
||||
string hash = string.Format("{0:X8}", CRC32.Calculate(RomData));
|
||||
if (db.ContainsKey(hash))
|
||||
return db[hash];
|
||||
if (db.TryGetValue(hash, out ret))
|
||||
return ret;
|
||||
|
||||
hash = Util.BytesToHexString(System.Security.Cryptography.MD5.Create().ComputeHash(RomData));
|
||||
if (db.ContainsKey(hash))
|
||||
return db[hash];
|
||||
if (db.TryGetValue(hash, out ret))
|
||||
return ret;
|
||||
|
||||
// rom is not in database. make some best-guesses
|
||||
var Game = new GameInfo();
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace BizHawk
|
|||
}
|
||||
}
|
||||
|
||||
public byte[] GetFileData() { return null; }
|
||||
|
||||
public byte[] GetRomData()
|
||||
{
|
||||
return RomData;
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace BizHawk
|
|||
return output;
|
||||
}
|
||||
|
||||
public byte[] GetFileData() { return null; }
|
||||
public byte[] GetRomData()
|
||||
{
|
||||
return RomData;
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace BizHawk
|
|||
public interface IGame
|
||||
{
|
||||
byte[] GetRomData();
|
||||
byte[] GetFileData();
|
||||
IList<string> GetOptions();
|
||||
string Name { get; }
|
||||
}
|
||||
|
|
|
@ -317,7 +317,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="config\ControllerImages\NESController.PNG" />
|
||||
<Content Include="gamedb.txt" />
|
||||
<Content Include="output\gamedb.txt" />
|
||||
<None Include="images\Refresh.bmp" />
|
||||
<None Include="images\TruncateFromRW.png" />
|
||||
<None Include="images\TruncateFromFile.png" />
|
||||
|
|
|
@ -12,12 +12,13 @@ namespace BizHawk.MultiClient
|
|||
try
|
||||
{
|
||||
var file = new FileInfo(filepath);
|
||||
using (var reader = file.OpenText())
|
||||
{
|
||||
var s = new JsonSerializer();
|
||||
var r = new JsonReader(reader);
|
||||
config = (T) s.Deserialize(r, typeof (T));
|
||||
}
|
||||
if(file.Exists)
|
||||
using (var reader = file.OpenText())
|
||||
{
|
||||
var s = new JsonSerializer();
|
||||
var r = new JsonReader(reader);
|
||||
config = (T) s.Deserialize(r, typeof (T));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return config;
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace BizHawk.MultiClient
|
|||
public class RomGame : IGame
|
||||
{
|
||||
public byte[] RomData;
|
||||
public byte[] FileData;
|
||||
public string System;
|
||||
|
||||
private string name;
|
||||
|
@ -24,22 +25,17 @@ namespace BizHawk.MultiClient
|
|||
|
||||
var stream = file.GetStream();
|
||||
|
||||
if (file.Extension == "NES")
|
||||
{
|
||||
RomData = Util.ReadAllBytes(stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
int header = (int)(stream.Length % BankSize);
|
||||
stream.Position = header;
|
||||
int length = (int)stream.Length - header;
|
||||
FileData = Util.ReadAllBytes(stream);
|
||||
|
||||
RomData = new byte[length];
|
||||
stream.Read(RomData, 0, length);
|
||||
int header = (int)(stream.Length % BankSize);
|
||||
stream.Position = header;
|
||||
int length = (int)stream.Length - header;
|
||||
|
||||
if (file.Extension == "SMD")
|
||||
RomData = DeInterleaveSMD(RomData);
|
||||
}
|
||||
RomData = new byte[length];
|
||||
stream.Read(RomData, 0, length);
|
||||
|
||||
if (file.Extension == "SMD")
|
||||
RomData = DeInterleaveSMD(RomData);
|
||||
|
||||
var info = Database.GetGameInfo(RomData, file.FullName);
|
||||
name = info.Name;
|
||||
|
@ -105,6 +101,7 @@ namespace BizHawk.MultiClient
|
|||
}
|
||||
|
||||
public byte[] GetRomData() { return RomData; }
|
||||
public byte[] GetFileData() { return FileData; }
|
||||
public IList<string> GetOptions() { return options; }
|
||||
public string Name { get { return name; } }
|
||||
|
||||
|
|
|
@ -2257,3 +2257,16 @@ B486A8ED Dai Makai Mura SGX
|
|||
1F041166 Madoo Granzort SGX
|
||||
|
||||
D4448D09BBFDE687C04F9E3310E023AB ti83_1.rom TI83 initPC=6ce
|
||||
|
||||
8E3630186E35D477231BF8FD50E54CDD Super Mario Bros. (U) NES board=NROM;mirror=V;PRG=2;CHR=1
|
||||
1457475741846A01399DC663135A60C1 Balloon Fight (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
|
||||
576AB245B4F04C670AC312AB0D441697 Baseball (UE) NES board=NROM;mirror=H;PRG=1;CHR=1
|
||||
0F9C8D3D3099C70368411F6DF9EF49C1 Bomberman (U) NES board=NROM;mirror=V;PRG=1;CHR=1
|
||||
D2C42603A8EC74F51265C085AE26B9BB Burger Time (U) NES board=NROM;mirror=H;PRG=1;CHR=1
|
||||
EEBA6EF8992074C5EBBDF0ECD9468E10 Clu Clu Land (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
|
||||
E36BC14876DA0E25C4EE2BBA193002C4 Defender 2 (U) NES board=NROM;mirror=V;PRG=1;CHR=1
|
||||
A2B5BDDB4C7A5A39C8FAC13E64494C9A Donkey Kong 3 (JUE) board=NROM;mirror=V;PRG=1;CHR=1
|
||||
6D4A94C344463E562344249E18E9B99F Donkey Kong (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
|
||||
8B7C1E5B55A9E5FA23E895DF2D682914 Donkey Kong Jr (JU) NES board=NROM;mirror=H;PRG=1;CHR=1
|
||||
1CA706896A8D4F2A2B5480D941130A4A Donkey Kong Jr Math (U) NES board=NROM;mirror=V;PRG=1;CHR=1
|
||||
FA382374EB4A93A719064CA6C5A4E78C Duck Hunt (JUE) NES board=NROM;mirror=V;PRG=1;CHR=1
|
||||
|
|
Loading…
Reference in New Issue