GBHawk: Sachen work

This commit is contained in:
alyosha-tas 2017-11-22 21:38:56 -05:00
parent b2bc602398
commit 9faae458af
6 changed files with 424 additions and 3 deletions

View File

@ -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" />

View File

@ -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)

View File

@ -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")
{

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}