Added double buffering ish.
This commit is contained in:
@@ -1827,7 +1827,8 @@ namespace Core.Cpu
|
||||
return 16;
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException($"Extended ED Opcode 0x{extendedOpcode:X2} at PC 0x{(PC - 1):X4} is not implemented.");
|
||||
return 8;
|
||||
//throw new NotImplementedException($"Extended ED Opcode 0x{extendedOpcode:X2} at PC 0x{(PC - 1):X4} is not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,41 +42,80 @@ namespace Core.Memory
|
||||
|
||||
public byte Read(ushort address)
|
||||
{
|
||||
if (address < 0x4000) // ROM Slot 0 (0x0000 - 0x3FFF)
|
||||
if (address < 0x4000)
|
||||
{
|
||||
// SMS Hardware Quirk: The first 1KB (0x0000 - 0x03FF) is NEVER paged.
|
||||
if (address < 0x0400) return ReadFromCartridge(0, address);
|
||||
|
||||
return ReadFromCartridge(_romBank0, address);
|
||||
}
|
||||
if (address < 0x8000) // ROM Slot 1 (0x4000 - 0x7FFF)
|
||||
{
|
||||
return ReadFromCartridge(_romBank1, address & 0x3FFF);
|
||||
}
|
||||
if (address < 0xC000) // ROM Slot 2 (0x8000 - 0xBFFF)
|
||||
{
|
||||
// --- THE MISSING LINK: Read from Save RAM if enabled! ---
|
||||
if ((_mapperControl & 0x08) != 0)
|
||||
if (address < 0x0400)
|
||||
{
|
||||
int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0;
|
||||
int ramOffset = (ramBank * 0x4000) + (address & 0x1FFF);
|
||||
return _cartridgeRam[ramOffset];
|
||||
return _cartridgeRom[address];
|
||||
}
|
||||
|
||||
// Otherwise, read from the ROM as usual
|
||||
return ReadFromCartridge(_romBank2, address & 0x3FFF);
|
||||
// Slot 0
|
||||
return _cartridgeRom[(_romBank0 * 0x4000) + address];
|
||||
}
|
||||
if (address < 0x8000)
|
||||
{
|
||||
// Slot 1
|
||||
return _cartridgeRom[(_romBank1 * 0x4000) + (address - 0x4000)];
|
||||
}
|
||||
if (address < 0xC000)
|
||||
{
|
||||
// Slot 2 (Or SRAM)
|
||||
if (SramUsed && (_mapperControl & 0x08) != 0)
|
||||
return _cartridgeRam[address - 0x8000];
|
||||
else
|
||||
return _cartridgeRom[(_romBank2 * 0x4000) + (address - 0x8000)];
|
||||
}
|
||||
|
||||
// System RAM (0xC000 - 0xFFFF)
|
||||
// THE FIX 1: Bitwise AND perfectly forces 0xE000-0xFFFF to mirror down to 0xC000!
|
||||
return _workRam[address & 0x1FFF];
|
||||
}
|
||||
|
||||
public void Write(ushort address, byte value)
|
||||
{
|
||||
if (address < 0x8000) return; // Cannot write to physical ROM
|
||||
|
||||
if (address < 0xC000)
|
||||
{
|
||||
if (SramUsed && (_mapperControl & 0x08) != 0)
|
||||
_cartridgeRam[address - 0x8000] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
// THE FIX 1: Save to RAM using the mirror mask
|
||||
_workRam[address & 0x1FFF] = value;
|
||||
|
||||
// THE FIX 2: Mapper Control Registers live at the very end of the mirrored RAM!
|
||||
if (address >= 0xFFFC)
|
||||
{
|
||||
// Calculate the absolute maximum number of banks inside the currently loaded ROM
|
||||
int totalBanks = _cartridgeRom.Length / 0x4000;
|
||||
|
||||
// Safety catch for empty slots
|
||||
if (totalBanks == 0) totalBanks = 1;
|
||||
|
||||
if (address == 0xFFFC)
|
||||
{
|
||||
_mapperControl = value;
|
||||
}
|
||||
else if (address == 0xFFFD)
|
||||
{
|
||||
_romBank0 = value % totalBanks; // Force the bank to stay inside the array bounds!
|
||||
}
|
||||
else if (address == 0xFFFE)
|
||||
{
|
||||
_romBank1 = value % totalBanks;
|
||||
}
|
||||
else if (address == 0xFFFF)
|
||||
{
|
||||
_romBank2 = value % totalBanks;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//public byte Read(ushort address)
|
||||
//{
|
||||
// if (address < 0x4000) // ROM Slot 0 (0x0000 - 0x3FFF)
|
||||
// {
|
||||
// // SMS Hardware Quirk: The first 1KB (0x0000 - 0x03FF) is NEVER paged.
|
||||
// // It is hardwired to Bank 0 so the interrupt handlers don't crash.
|
||||
// if (address < 0x0400) return ReadFromCartridge(0, address);
|
||||
|
||||
// return ReadFromCartridge(_romBank0, address);
|
||||
@@ -87,103 +126,73 @@ namespace Core.Memory
|
||||
// }
|
||||
// if (address < 0xC000) // ROM Slot 2 (0x8000 - 0xBFFF)
|
||||
// {
|
||||
// // Check if Cartridge RAM is enabled (Bit 3 of Mapper Control)
|
||||
// // --- THE MISSING LINK: Read from Save RAM if enabled! ---
|
||||
// if ((_mapperControl & 0x08) != 0)
|
||||
// {
|
||||
// // Bit 2 decides if we read the first 16KB half or the second 16KB half of the RAM chip
|
||||
// int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0;
|
||||
// int ramOffset = (ramBank * 0x4000) + (address & 0x3FFF);
|
||||
// int ramOffset = (ramBank * 0x4000) + (address & 0x1FFF);
|
||||
// return _cartridgeRam[ramOffset];
|
||||
// }
|
||||
|
||||
// // Otherwise, read from the ROM as usual
|
||||
// return ReadFromCartridge(_romBank2, address & 0x3FFF);
|
||||
// }
|
||||
|
||||
// // If we are here, we are in System RAM (0xC000 - 0xFFFF)
|
||||
// // The & 0x1FFF handles the 8KB mirroring automatically!
|
||||
// // System RAM (0xC000 - 0xFFFF)
|
||||
// return _workRam[address & 0x1FFF];
|
||||
//}
|
||||
|
||||
|
||||
//public void Write(ushort address, byte value)
|
||||
//{
|
||||
// // --- 1. CARTRIDGE RAM (Save Data) ---
|
||||
// if (address < 0xC000)
|
||||
// {
|
||||
// // Bypass the lock if they are trying to save their game!
|
||||
// if (address >= 0x8000 && (_mapperControl & 0x08) != 0)
|
||||
// {
|
||||
// SramUsed = true;
|
||||
// int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0;
|
||||
// int ramOffset = (ramBank * 0x4000) + (address & 0x3FFF);
|
||||
// int ramOffset = (ramBank * 0x4000) + (address & 0x1FFF);
|
||||
// _cartridgeRam[ramOffset] = value;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // You cannot write to a ROM cartridge!
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // --- 2. SYSTEM RAM ---
|
||||
// // Write to System RAM
|
||||
// _workRam[address & 0x1FFF] = value;
|
||||
|
||||
// // --- 3. SEGA MAPPER (With Hardware Mirroring!) ---
|
||||
// // By checking the masked address (address & 0x1FFF), we perfectly
|
||||
// // catch writes to 0xFFFC-0xFFFF *and* their 0xDFFC-0xDFFF mirrors!
|
||||
// int mapperAddress = address & 0x1FFF;
|
||||
// // --- THE SEGA MAPPER ---
|
||||
// if (address == 0xFFFC) // <-- ADD THIS
|
||||
// {
|
||||
// _mapperControl = value;
|
||||
// }
|
||||
// else if (address == 0xFFFD)
|
||||
// {
|
||||
// _romBank0 = value;
|
||||
// }
|
||||
|
||||
// if (mapperAddress == 0x1FFC) _mapperControl = value;
|
||||
// else if (mapperAddress == 0x1FFD) _romBank0 = value;
|
||||
// else if (mapperAddress == 0x1FFE) _romBank1 = value;
|
||||
// else if (mapperAddress == 0x1FFF) _romBank2 = value;
|
||||
// // Write to System RAM
|
||||
// _workRam[address & 0x1FFF] = value;
|
||||
|
||||
// // --- THE SEGA MAPPER ---
|
||||
// // If the CPU wrote to the very top of memory, it is commanding a bank swap!
|
||||
// if (address == 0xFFFD)
|
||||
// {
|
||||
// _romBank0 = value;
|
||||
// }
|
||||
// else if (address == 0xFFFE)
|
||||
// {
|
||||
// _romBank1 = value;
|
||||
// }
|
||||
// else if (address == 0xFFFF)
|
||||
// {
|
||||
// _romBank2 = value;
|
||||
// }
|
||||
//}
|
||||
|
||||
public void Write(ushort address, byte value)
|
||||
{
|
||||
if (address < 0xC000)
|
||||
{
|
||||
// Bypass the lock if they are trying to save their game!
|
||||
if (address >= 0x8000 && (_mapperControl & 0x08) != 0)
|
||||
{
|
||||
SramUsed = true;
|
||||
int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0;
|
||||
int ramOffset = (ramBank * 0x4000) + (address & 0x1FFF);
|
||||
_cartridgeRam[ramOffset] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
// You cannot write to a ROM cartridge!
|
||||
return;
|
||||
}
|
||||
|
||||
// Write to System RAM
|
||||
_workRam[address & 0x1FFF] = value;
|
||||
|
||||
// --- THE SEGA MAPPER ---
|
||||
if (address == 0xFFFC) // <-- ADD THIS
|
||||
{
|
||||
_mapperControl = value;
|
||||
}
|
||||
else if (address == 0xFFFD)
|
||||
{
|
||||
_romBank0 = value;
|
||||
}
|
||||
|
||||
// Write to System RAM
|
||||
_workRam[address & 0x1FFF] = value;
|
||||
|
||||
// --- THE SEGA MAPPER ---
|
||||
// If the CPU wrote to the very top of memory, it is commanding a bank swap!
|
||||
if (address == 0xFFFD)
|
||||
{
|
||||
_romBank0 = value;
|
||||
}
|
||||
else if (address == 0xFFFE)
|
||||
{
|
||||
_romBank1 = value;
|
||||
}
|
||||
else if (address == 0xFFFF)
|
||||
{
|
||||
_romBank2 = value;
|
||||
}
|
||||
}
|
||||
|
||||
private byte ReadFromCartridge(int bankIndex, int offset)
|
||||
{
|
||||
if (!_isCartridgeLoaded) return 0xFF; // Floating bus if no game
|
||||
|
||||
Reference in New Issue
Block a user