[NES] add SuROM (dragon quest 4) and SoROM/SxROM (other games that are not dragon quest 4)

This commit is contained in:
zeromus 2011-06-12 00:53:14 +00:00
parent 38ca651aab
commit 9ee66226df
3 changed files with 130 additions and 17 deletions

View File

@ -13,6 +13,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//check UNIF for more information.. it may specify board and MMC1 rev independently because boards may have any MMC1 rev
//in that case, we need to capture MMC1 rev in the game database (maybe add a new `chip` parameter)
//TODO - this could be refactored to use more recent techniques (bank regs instead of nested if/then)
//Final Fantasy
//Mega Man 2
//Blaster Master
@ -22,7 +24,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
//Zelda 2
//Castlevania 2
class MMC1
public class MMC1
{
NES.NESBoardBase board;
public MMC1(NES.NESBoardBase board)
@ -76,6 +78,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
prg_mode = 1;
prg_slot = 1;
chr_mode = 1;
mirror = NES.NESBoardBase.EMirrorType.Horizontal;
}
public void Write(int addr, byte value)
@ -165,11 +169,11 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public class SxROM : NES.NESBoardBase
{
//configuration
int prg_mask, chr_mask;
int vram_mask, wram_mask;
protected int prg_mask, chr_mask;
protected int vram_mask, wram_mask;
//state
MMC1 mmc1;
protected MMC1 mmc1;
public override void WritePRG(int addr, byte value)
{
@ -231,8 +235,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
{
if (!Cart.wram_battery) return null;
return WRAM;
//some boards have a wram that is backed-up or not backed-up. need to handle that somehow
//(nestopia splits it into NVWRAM and WRAM but i didnt like that at first.. but it may player better with this architecture)
}
}
@ -245,7 +247,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo
public override bool Configure(NES.EDetectionOrigin origin)
{
//analyze board type
switch (Cart.board_type)
{
case "NES-SAROM": //dragon warrior
@ -307,29 +308,139 @@ namespace BizHawk.Emulation.Consoles.Nintendo
case "HVC-SNROM":
AssertPrg(128, 256); AssertChr(0); AssertVram(8); AssertWram(8);
break;
case "NES-SOROM": //Nobunaga's Ambition
AssertPrg(128, 256); AssertChr(0); AssertVram(8); AssertWram(16);
break;
case "NES-SUROM": //dragon warrior 4
case "HVC-SUROM":
AssertPrg(512); AssertChr(0); AssertVram(8); AssertWram(8);
break;
case "HVC-SXROM": //final fantasy 1& 2
AssertPrg(128, 256, 512); AssertChr(0); AssertVram(8); AssertWram(32);
break;
default:
return false;
}
BaseConfigure();
return true;
}
protected void BaseConfigure()
{
mmc1 = new MMC1(this);
prg_mask = (Cart.prg_size / 16) - 1;
vram_mask = (Cart.vram_size*1024) - 1;
wram_mask = (Cart.wram_size*1024) - 1;
chr_mask = (Cart.chr_size / 8 * 2) - 1;
SetMirrorType(mmc1.mirror);
}
} //class SxROM
class SoROM : SuROM
{
//this uses a CHR bit to select WRAM banks
//TODO - only the latter 8KB is supposed to be battery backed
public override bool Configure(NES.EDetectionOrigin origin)
{
switch (Cart.board_type)
{
case "NES-SOROM": //Nobunaga's Ambition
AssertPrg(128, 256); AssertChr(0); AssertVram(8); AssertWram(16);
break;
default: return false;
}
BaseConfigure();
return true;
}
int Map_WRAM(int addr)
{
//$A000-BFFF: [...R ...C]
// R = PRG-RAM page select
// C = CHR reg 0
//* BUT THIS IS WRONG ??? R IS ONE BIT LOWER !!!??? ?!? *
int chr_bank = mmc1.Get_CHRBank_4K(0);
int ofs = addr & ((8 * 1024) - 1);
int wram_bank_8k = (chr_bank >> 3) & 1;
return (wram_bank_8k << 13) | ofs;
}
public override void WriteWRAM(int addr, byte value)
{
base.WriteWRAM(Map_WRAM(addr), value);
}
public override byte ReadWRAM(int addr)
{
return base.ReadWRAM(Map_WRAM(addr));
}
}
class SXROM : SuROM
{
//SXROM's PRG behaves similar to SuROM (and so inherits from it)
//it also has some WRAM select bits like SoROM
public override bool Configure(NES.EDetectionOrigin origin)
{
switch (Cart.board_type)
{
case "HVC-SXROM": //final fantasy 1& 2
AssertPrg(128, 256, 512); AssertChr(0); AssertVram(8); AssertWram(32);
break;
default: return false;
}
BaseConfigure();
return true;
}
int Map_WRAM(int addr)
{
//$A000-BFFF: [...P RR..]
// P = PRG-ROM 256k block select (just like on SUROM)
// R = PRG-RAM page select (selects 8k @ $6000-7FFF, just like SOROM)
int chr_bank = mmc1.Get_CHRBank_4K(0);
int ofs = addr & ((8 * 1024) - 1);
int wram_bank_8k = (chr_bank >> 2) & 3;
return (wram_bank_8k << 13) | ofs;
}
public override void WriteWRAM(int addr, byte value)
{
base.WriteWRAM(Map_WRAM(addr), value);
}
public override byte ReadWRAM(int addr)
{
return base.ReadWRAM(Map_WRAM(addr));
}
}
class SuROM : SxROM
{
public override bool Configure(NES.EDetectionOrigin origin)
{
//SUROM uses CHR A16 to control the upper address line (PRG A18) of its 512KB PRG ROM.
switch (Cart.board_type)
{
case "NES-SUROM": //dragon warrior 4
case "HVC-SUROM":
AssertPrg(512); AssertChr(0); AssertVram(8); AssertWram(8);
break;
default: return false;
}
BaseConfigure();
return true;
}
public override byte ReadPRG(int addr)
{
int bank = mmc1.Get_PRGBank(addr);
int chr_bank = mmc1.Get_CHRBank_4K(0);
int bank_bit18 = chr_bank >> 4;
bank |= (bank_bit18 << 4);
bank &= prg_mask;
addr = (bank << 14) | (addr & 0x3FFF);
return ROM[addr];
}
}
}

View File

@ -433,6 +433,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
Console.WriteLine("Final game detection results:");
Console.WriteLine(choice);
Console.WriteLine("\"" + game_name + "\"");
Console.WriteLine("Implemented by: class " + boardType.Name);
if (choice.bad)
{
Console.WriteLine("~~ ONE WAY OR ANOTHER, THIS DUMP IS KNOWN TO BE *BAD* ~~");

View File

@ -878,6 +878,7 @@ namespace BizHawk.MultiClient
var writer = new BinaryWriter(new FileStream(path, FileMode.Create, FileAccess.Write));
int len = Util.SaveRamBytesUsed(Global.Emulator.SaveRam);
//int len = Global.Emulator.SaveRam.Length;
writer.Write(Global.Emulator.SaveRam, 0, len);
writer.Close();
}