GBHawk: Sachen work
This commit is contained in:
parent
b2bc602398
commit
9faae458af
|
@ -582,6 +582,8 @@
|
|||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\GBA\VBARegisterHelper.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBHawk\Audio.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBHawk\Mappers\Mapper_Sachen_MMC2.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBHawk\Mappers\Mapper_Sachen_MMC1.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBHawk\SerialPort.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBHawk\GBHawk.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBHawk\GBHawk.IDebuggable.cs" />
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
private byte PeekSystemBus(long addr)
|
||||
{
|
||||
ushort addr2 = (ushort)(addr & 0xFFFF);
|
||||
return ReadMemory(addr2);
|
||||
return PeekMemory(addr2);
|
||||
}
|
||||
|
||||
private void PokeSystemBus(long addr, byte value)
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
{
|
||||
ReadMemory = ReadMemory,
|
||||
WriteMemory = WriteMemory,
|
||||
PeekMemory = ReadMemory,
|
||||
PeekMemory = PeekMemory,
|
||||
DummyReadMemory = ReadMemory,
|
||||
OnExecFetch = ExecFetch
|
||||
};
|
||||
|
@ -138,7 +138,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
audio.Reset();
|
||||
serialport.Reset();
|
||||
|
||||
cpu.SetCallbacks(ReadMemory, ReadMemory, ReadMemory, WriteMemory);
|
||||
cpu.SetCallbacks(ReadMemory, PeekMemory, PeekMemory, WriteMemory);
|
||||
|
||||
_vidbuffer = new int[VirtualWidth * VirtualHeight];
|
||||
}
|
||||
|
@ -184,6 +184,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
case 0xFE: mapper = new MapperHuC3(); mppr = "HuC3"; break;
|
||||
case 0xFF: mapper = new MapperHuC1(); mppr = "HuC1"; break;
|
||||
|
||||
// Bootleg mappers
|
||||
// NOTE: Sachen mapper selection does not account for scrambling, so if another bootleg mapper
|
||||
// identifies itself as 0x31, this will need to be modified
|
||||
case 0x31: mapper = new MapperSachen2(); mppr = "Schn2"; break;
|
||||
|
||||
case 0x4:
|
||||
case 0x7:
|
||||
case 0xA:
|
||||
|
@ -197,6 +202,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
case 0x21:
|
||||
default:
|
||||
// mapper not implemented
|
||||
Console.WriteLine(header[0x47]);
|
||||
throw new Exception("Mapper not implemented");
|
||||
break;
|
||||
|
||||
|
@ -236,6 +242,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
break;
|
||||
}
|
||||
|
||||
// Sachen maper not known to have RAM
|
||||
if ((mppr == "Schn1") || (mppr == "Schn2"))
|
||||
{
|
||||
cart_RAM = null;
|
||||
}
|
||||
|
||||
// mbc2 carts have built in RAM
|
||||
if (mppr == "MBC2")
|
||||
{
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
using BizHawk.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||
{
|
||||
// Sachen Bootleg Mapper
|
||||
// NOTE: Normally, locked mode is disabled after 31 rises of A15
|
||||
// this occurs when the Boot Rom is loading the nintendo logo into VRAM
|
||||
// instead of tracking that in the main memory map where it will just slow things down for no reason
|
||||
// we'll clear the 'locked' flag when the last byte of the logo is read
|
||||
class MapperSachen1 : MapperBase
|
||||
{
|
||||
public int ROM_bank;
|
||||
public bool locked;
|
||||
public int ROM_mask;
|
||||
public int ROM_bank_mask;
|
||||
public int BASE_ROM_Bank;
|
||||
public bool reg_access;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
ROM_bank = 1;
|
||||
ROM_mask = Core._rom.Length / 0x4000 - 1;
|
||||
BASE_ROM_Bank = 0;
|
||||
ROM_bank_mask = 0xFF;
|
||||
locked = true;
|
||||
reg_access = false;
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
{
|
||||
if (addr < 0x4000)
|
||||
{
|
||||
ushort t_addr = addr;
|
||||
|
||||
// header is scrambled
|
||||
if ((addr >= 0x100) && (addr < 0x200))
|
||||
{
|
||||
int temp0 = (addr & 1);
|
||||
int temp1 = (addr & 2);
|
||||
int temp4 = (addr & 0x10);
|
||||
int temp6 = (addr & 0x40);
|
||||
|
||||
temp0 = temp0 << 6;
|
||||
temp1 = temp1 << 3;
|
||||
temp4 = temp4 >> 3;
|
||||
temp6 = temp6 >> 6;
|
||||
|
||||
addr &= 0x1AC;
|
||||
addr |= (ushort)(temp0 | temp1 | temp4 | temp6);
|
||||
}
|
||||
|
||||
if (locked) { addr |= 0x80; }
|
||||
|
||||
if (t_addr == 0x133)
|
||||
{
|
||||
locked = false;
|
||||
Console.WriteLine("cleared");
|
||||
}
|
||||
|
||||
return Core._rom[addr + BASE_ROM_Bank * 0x4000];
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return Core._rom[(addr - 0x4000) + ROM_bank * 0x4000];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
public override byte PeekMemory(ushort addr)
|
||||
{
|
||||
if (addr < 0x4000)
|
||||
{
|
||||
ushort t_addr = addr;
|
||||
|
||||
// header is scrambled
|
||||
if ((addr >= 0x100) && (addr < 0x200))
|
||||
{
|
||||
int temp0 = (addr & 1);
|
||||
int temp1 = (addr & 2);
|
||||
int temp4 = (addr & 0x10);
|
||||
int temp6 = (addr & 0x40);
|
||||
|
||||
temp0 = temp0 << 6;
|
||||
temp1 = temp1 << 3;
|
||||
temp4 = temp4 >> 3;
|
||||
temp6 = temp6 >> 6;
|
||||
|
||||
addr &= 0x1AC;
|
||||
addr |= (ushort)(temp0 | temp1 | temp4 | temp6);
|
||||
}
|
||||
|
||||
if (locked) { addr |= 0x80; }
|
||||
|
||||
return Core._rom[addr + BASE_ROM_Bank * 0x4000];
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return Core._rom[(addr - 0x4000) + ROM_bank * 0x4000];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
if (addr < 0x2000)
|
||||
{
|
||||
if (reg_access)
|
||||
{
|
||||
BASE_ROM_Bank = value;
|
||||
}
|
||||
}
|
||||
else if (addr < 0x4000)
|
||||
{
|
||||
ROM_bank = (value > 0) ? value : 1;
|
||||
|
||||
if ((value & 0x30) == 0x30)
|
||||
{
|
||||
reg_access = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_access = false;
|
||||
}
|
||||
}
|
||||
else if (addr < 0x6000)
|
||||
{
|
||||
if (reg_access)
|
||||
{
|
||||
ROM_bank_mask = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void PokeMemory(ushort addr, byte value)
|
||||
{
|
||||
WriteMemory(addr, value);
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
ser.Sync("ROM_Bank", ref ROM_bank);
|
||||
ser.Sync("ROM_Mask", ref ROM_mask);
|
||||
ser.Sync("locked", ref locked);
|
||||
ser.Sync("ROM_bank_mask", ref ROM_bank_mask);
|
||||
ser.Sync("BASE_ROM_Bank", ref BASE_ROM_Bank);
|
||||
ser.Sync("reg_access", ref reg_access);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
using BizHawk.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||
{
|
||||
// Sachen Bootleg Mapper
|
||||
// NOTE: Normally, locked mode is disabled after 31 rises of A15
|
||||
// this occurs when the Boot Rom is loading the nintendo logo into VRAM
|
||||
// instead of tracking that in the main memory map where it will just slow things down for no reason
|
||||
// we'll clear the 'locked' flag when the last byte of the logo is read
|
||||
class MapperSachen2 : MapperBase
|
||||
{
|
||||
public int ROM_bank;
|
||||
public bool locked;
|
||||
public int ROM_mask;
|
||||
public int ROM_bank_mask;
|
||||
public int BASE_ROM_Bank;
|
||||
public bool reg_access;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
ROM_bank = 1;
|
||||
ROM_mask = Core._rom.Length / 0x4000 - 1;
|
||||
BASE_ROM_Bank = 0;
|
||||
ROM_bank_mask = 0;
|
||||
locked = false;
|
||||
reg_access = false;
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
{
|
||||
if (addr < 0x4000)
|
||||
{
|
||||
ushort t_addr = addr;
|
||||
|
||||
// header is scrambled
|
||||
if ((addr >= 0x100) && (addr < 0x200))
|
||||
{
|
||||
int temp0 = (addr & 1);
|
||||
int temp1 = (addr & 2);
|
||||
int temp4 = (addr & 0x10);
|
||||
int temp6 = (addr & 0x40);
|
||||
|
||||
temp0 = temp0 << 6;
|
||||
temp1 = temp1 << 3;
|
||||
temp4 = temp4 >> 3;
|
||||
temp6 = temp6 >> 6;
|
||||
|
||||
addr &= 0x1AC;
|
||||
addr |= (ushort)(temp0 | temp1 | temp4 | temp6);
|
||||
}
|
||||
|
||||
if (locked) { addr |= 0x80; }
|
||||
|
||||
if (t_addr == 0x133)
|
||||
{
|
||||
if ((Core.GB_bios_register & 0x1) == 0) { locked ^= true; }
|
||||
}
|
||||
|
||||
return Core._rom[addr + BASE_ROM_Bank * 0x4000];
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
int temp_bank = (ROM_bank & ~ROM_bank_mask) | (ROM_bank_mask & BASE_ROM_Bank);
|
||||
temp_bank &= ROM_mask;
|
||||
|
||||
return Core._rom[(addr - 0x4000) + temp_bank * 0x4000];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
public override byte PeekMemory(ushort addr)
|
||||
{
|
||||
if (addr < 0x4000)
|
||||
{
|
||||
ushort t_addr = addr;
|
||||
|
||||
// header is scrambled
|
||||
if ((addr >= 0x100) && (addr < 0x200))
|
||||
{
|
||||
int temp0 = (addr & 1);
|
||||
int temp1 = (addr & 2);
|
||||
int temp4 = (addr & 0x10);
|
||||
int temp6 = (addr & 0x40);
|
||||
|
||||
temp0 = temp0 << 6;
|
||||
temp1 = temp1 << 3;
|
||||
temp4 = temp4 >> 3;
|
||||
temp6 = temp6 >> 6;
|
||||
|
||||
addr &= 0x1AC;
|
||||
addr |= (ushort)(temp0 | temp1 | temp4 | temp6);
|
||||
}
|
||||
|
||||
if (locked) { addr |= 0x80; }
|
||||
|
||||
return Core._rom[addr + BASE_ROM_Bank * 0x4000];
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return Core._rom[(addr - 0x4000) + ROM_bank * 0x4000];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteMemory(ushort addr, byte value)
|
||||
{
|
||||
if (addr < 0x2000)
|
||||
{
|
||||
if (reg_access)
|
||||
{
|
||||
BASE_ROM_Bank = value;
|
||||
}
|
||||
}
|
||||
else if (addr < 0x4000)
|
||||
{
|
||||
ROM_bank = (value > 0) ? (value) : 1;
|
||||
|
||||
if ((value & 0x30) == 0x30)
|
||||
{
|
||||
reg_access = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_access = false;
|
||||
}
|
||||
}
|
||||
else if (addr < 0x6000)
|
||||
{
|
||||
if (reg_access)
|
||||
{
|
||||
ROM_bank_mask = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void PokeMemory(ushort addr, byte value)
|
||||
{
|
||||
WriteMemory(addr, value);
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
ser.Sync("ROM_Bank", ref ROM_bank);
|
||||
ser.Sync("ROM_Mask", ref ROM_mask);
|
||||
ser.Sync("locked", ref locked);
|
||||
ser.Sync("ROM_bank_mask", ref ROM_bank_mask);
|
||||
ser.Sync("BASE_ROM_Bank", ref BASE_ROM_Bank);
|
||||
ser.Sync("reg_access", ref reg_access);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -206,5 +206,96 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
|||
Write_Registers(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
public byte PeekMemory(ushort addr)
|
||||
{
|
||||
if (ppu.DMA_start)
|
||||
{
|
||||
if ((addr >= 0xFE00) && (addr < 0xFEA0) && ppu.DMA_OAM_access)
|
||||
{
|
||||
return OAM[addr - 0xFE00];
|
||||
}
|
||||
else if ((addr >= 0xFF80))
|
||||
{
|
||||
return ZP_RAM[addr - 0xFF80];
|
||||
}
|
||||
else if ((addr >= 0xE000) && (addr < 0xFE00))
|
||||
{
|
||||
return RAM[addr - 0xE000]; // some of gekkio's tests require this to be accessible during DMA
|
||||
}
|
||||
else if (addr < 0x4000)
|
||||
{
|
||||
return mapper.PeekMemory(addr); // some of gekkio's tests require this to be accessible during DMA
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
if (addr < 0x100)
|
||||
{
|
||||
// return Either BIOS ROM or Game ROM
|
||||
if ((GB_bios_register & 0x1) == 0)
|
||||
{
|
||||
return _bios[addr]; // Return BIOS
|
||||
}
|
||||
else
|
||||
{
|
||||
return mapper.PeekMemory(addr);
|
||||
}
|
||||
}
|
||||
else if (addr < 0x8000)
|
||||
{
|
||||
return mapper.PeekMemory(addr);
|
||||
}
|
||||
else if (addr < 0x9800)
|
||||
{
|
||||
if (ppu.VRAM_access_read) { return CHR_RAM[addr - 0x8000]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0x9C00)
|
||||
{
|
||||
if (ppu.VRAM_access_read) { return BG_map_1[addr - 0x9800]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0xA000)
|
||||
{
|
||||
if (ppu.VRAM_access_read) { return BG_map_2[addr - 0x9C00]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0xC000)
|
||||
{
|
||||
return mapper.PeekMemory(addr);
|
||||
}
|
||||
else if (addr < 0xE000)
|
||||
{
|
||||
return RAM[addr - 0xC000];
|
||||
}
|
||||
else if (addr < 0xFE00)
|
||||
{
|
||||
return RAM[addr - 0xE000];
|
||||
}
|
||||
else if (addr < 0xFEA0)
|
||||
{
|
||||
if (ppu.OAM_access_read) { return OAM[addr - 0xFE00]; }
|
||||
else { return 0xFF; }
|
||||
}
|
||||
else if (addr < 0xFF00)
|
||||
{
|
||||
// unmapped memory, returns 0xFF
|
||||
return 0xFF;
|
||||
}
|
||||
else if (addr < 0xFF80)
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
else if (addr < 0xFFFF)
|
||||
{
|
||||
return ZP_RAM[addr - 0xFF80];
|
||||
}
|
||||
else
|
||||
{
|
||||
return Read_Registers(addr);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue