-Made Intellicart its own class.
-Separated cartridge logic into a separate ICart named Cartridge.cs. -Made WriteMemory return a bool to match ICart.Write. It currently returns true if either the cart or the core responded. TODO: Parse the vanilla Intellivision ROM, which will hopefully include the read / writability of the data segments. adelikat seems to think that I just need to send the bytes to $5000, but I'm not convinced.
This commit is contained in:
parent
a5262488c7
commit
80a0f8f75b
|
@ -114,6 +114,7 @@
|
|||
<Compile Include="Consoles\GB\Input.cs" />
|
||||
<Compile Include="Consoles\GB\MemoryMap.cs" />
|
||||
<Compile Include="Consoles\GB\GB.cs" />
|
||||
<Compile Include="Consoles\Intellivision\Cartridge.cs" />
|
||||
<Compile Include="Consoles\Intellivision\Intellicart.cs" />
|
||||
<Compile Include="Consoles\Intellivision\Intellivision.cs" />
|
||||
<Compile Include="Consoles\Intellivision\MemoryMap.cs" />
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace BizHawk.Emulation.CPUs.CP1610
|
|||
public int PendingCycles;
|
||||
|
||||
public Func<ushort, ushort> ReadMemory;
|
||||
public Action<ushort, ushort> WriteMemory;
|
||||
public Func<ushort, ushort, bool> WriteMemory;
|
||||
|
||||
private static bool logging = true;
|
||||
private static StreamWriter log;
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Intellivision
|
||||
{
|
||||
public sealed class Cartridge : ICart
|
||||
{
|
||||
private ushort[] Data = new ushort[56320];
|
||||
|
||||
public int Parse(byte[] Rom)
|
||||
{
|
||||
// TODO: Actually parse the ROM.
|
||||
return 1;
|
||||
}
|
||||
|
||||
public ushort? Read(ushort addr)
|
||||
{
|
||||
// TODO: Check if address is RAM / ROM.
|
||||
switch (addr & 0xF000)
|
||||
{
|
||||
case 0x0000:
|
||||
if (addr <= 0x03FF)
|
||||
break;
|
||||
if (addr <= 0x04FF)
|
||||
// OK on all but Intellivision 2.
|
||||
return Data[addr & 0x00FF];
|
||||
else if (addr <= 0x06FF)
|
||||
return Data[addr & 0x02FF];
|
||||
else if (addr <= 0x0CFF)
|
||||
// OK if no Intellivoice.
|
||||
return Data[addr & 0x08FF];
|
||||
else
|
||||
return Data[addr & 0x0BFF];
|
||||
case 0x2000:
|
||||
// OK if no ECS.
|
||||
return Data[(addr & 0x0FFF) + 0x0C00];
|
||||
case 0x4000:
|
||||
if (addr <= 0x47FF)
|
||||
// OK if no ECS.
|
||||
return Data[(addr & 0x07FF) + 0x1C00];
|
||||
else if (addr == 0x4800)
|
||||
return Data[0x2400];
|
||||
else
|
||||
return Data[(addr & 0x0FFF) + 0x1C00];
|
||||
case 0x5000:
|
||||
case 0x6000:
|
||||
if (addr <= 0x5014)
|
||||
return Data[(addr & 0x0014) + 0x2C00];
|
||||
else
|
||||
return Data[(addr & 0x1FFF) + 0x2C00];
|
||||
case 0x7000:
|
||||
if (addr == 0x7000)
|
||||
// OK if no ECS.
|
||||
return Data[0x04C00];
|
||||
else if (addr <= 0x77FF)
|
||||
// OK if no ECS.
|
||||
return Data[(addr & 0x07FF) + 0x4C00];
|
||||
else
|
||||
// OK if no ECS.
|
||||
return Data[(addr & 0x0FFF) + 0x4C00];
|
||||
case 0x8000:
|
||||
// OK. Avoid STIC alias at $8000-$803F.
|
||||
return Data[(addr & 0x0FFF) + 0x5C00];
|
||||
case 0x9000:
|
||||
case 0xA000:
|
||||
case 0xB000:
|
||||
if (addr <= 0xB7FF)
|
||||
return Data[(addr & 0x27FF) + 0x6C00];
|
||||
else
|
||||
return Data[(addr & 0x2FFF) + 0x6C00];
|
||||
case 0xC000:
|
||||
// OK. Avoid STIC alias at $C000-$C03F.
|
||||
return Data[(addr & 0x0FFF) + 0x9C00];
|
||||
case 0xD000:
|
||||
return Data[(addr & 0x0FFF) + 0xAC00];
|
||||
case 0xE000:
|
||||
// OK if no ECS.
|
||||
return Data[(addr & 0x0FFF) + 0xBC00];
|
||||
case 0xF000:
|
||||
if (addr <= 0xF7FF)
|
||||
return Data[(addr & 0x07FF) + 0xCC00];
|
||||
else
|
||||
return Data[(addr & 0x0FFF) + 0xCC00];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool Write(ushort addr, ushort value)
|
||||
{
|
||||
// TODO: Check if address is RAM / ROM.
|
||||
switch (addr & 0xF000)
|
||||
{
|
||||
case 0x0000:
|
||||
if (addr <= 0x03FF)
|
||||
break;
|
||||
if (addr <= 0x04FF)
|
||||
{
|
||||
// OK on all but Intellivision 2.
|
||||
Data[addr & 0x00FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x06FF)
|
||||
{
|
||||
Data[addr & 0x02FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x0CFF)
|
||||
{
|
||||
// OK if no Intellivoice.
|
||||
Data[addr & 0x08FF] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data[addr & 0x0BFF] = value;
|
||||
return true;
|
||||
}
|
||||
case 0x2000:
|
||||
// OK if no ECS.
|
||||
Data[(addr & 0x0FFF) + 0x0C00] = value;
|
||||
return true;
|
||||
case 0x4000:
|
||||
if (addr <= 0x47FF)
|
||||
{
|
||||
// OK if no ECS.
|
||||
Data[(addr & 0x07FF) + 0x1C00] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr == 0x4800)
|
||||
{
|
||||
// OK only if boot ROM at $7000.
|
||||
Data[0x2400] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data[(addr & 0x0FFF) + 0x1C00] = value;
|
||||
return true;
|
||||
}
|
||||
case 0x5000:
|
||||
case 0x6000:
|
||||
if (addr <= 0x5014)
|
||||
{
|
||||
// OK only if boot ROM at $4800 or $7000.
|
||||
Data[(addr & 0x0014) + 0x2C00] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data[(addr & 0x1FFF) + 0x2C00] = value;
|
||||
return true;
|
||||
}
|
||||
case 0x7000:
|
||||
if (addr == 0x7000)
|
||||
{
|
||||
// RAM at $7000 confuses EXEC boot sequence.
|
||||
Data[0x04C00] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x77FF)
|
||||
{
|
||||
// OK if no ECS.
|
||||
Data[(addr & 0x07FF) + 0x4C00] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not map RAM here due to GRAM alias.
|
||||
Data[(addr & 0x0FFF) + 0x4C00] = value;
|
||||
return true;
|
||||
}
|
||||
case 0x8000:
|
||||
// OK. Avoid STIC alias at $8000-$803F.
|
||||
Data[(addr & 0x0FFF) + 0x5C00] = value;
|
||||
return true;
|
||||
case 0x9000:
|
||||
case 0xA000:
|
||||
case 0xB000:
|
||||
if (addr <= 0xB7FF)
|
||||
{
|
||||
Data[(addr & 0x27FF) + 0x6C00] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not map RAM here due to GRAM alias.
|
||||
Data[(addr & 0x2FFF) + 0x6C00] = value;
|
||||
return true;
|
||||
}
|
||||
case 0xC000:
|
||||
// OK. Avoid STIC alias at $C000-$C03F.
|
||||
Data[(addr & 0x0FFF) + 0x9C00] = value;
|
||||
return true;
|
||||
case 0xD000:
|
||||
Data[(addr & 0x0FFF) + 0xAC00] = value;
|
||||
return true;
|
||||
case 0xE000:
|
||||
// OK if no ECS.
|
||||
Data[(addr & 0x0FFF) + 0xBC00] = value;
|
||||
return true;
|
||||
case 0xF000:
|
||||
if (addr <= 0xF7FF)
|
||||
{
|
||||
Data[(addr & 0x07FF) + 0xCC00] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not map RAM here due to GRAM alias.
|
||||
Data[(addr & 0x0FFF) + 0xCC00] = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@ using System.Text;
|
|||
|
||||
namespace BizHawk.Emulation.Consoles.Intellivision
|
||||
{
|
||||
public sealed partial class Intellivision : ICart
|
||||
public sealed class Intellicart : ICart
|
||||
{
|
||||
private ushort[] Intellicart = new ushort[65536];
|
||||
private ushort[] Data = new ushort[65536];
|
||||
private bool[][] MemoryAttributes = new bool[32][];
|
||||
private ushort[][] FineAddresses = new ushort[32][];
|
||||
|
||||
|
@ -52,12 +52,12 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
return (ushort)((crc << 8) ^ CRC16_table[(crc >> 8) ^ data]);
|
||||
}
|
||||
|
||||
public int Parse()
|
||||
public int Parse(byte[] Rom)
|
||||
{
|
||||
int offset = 0;
|
||||
// Check to see if the header is valid.
|
||||
if (Rom[offset++] != 0xA8 || Rom[offset++] != (0xFF ^ Rom[offset++]))
|
||||
throw new ArgumentException();
|
||||
return -1;
|
||||
ushort crc, expected;
|
||||
// Parse for data segments.
|
||||
for (int segment = 0; segment < Rom[1]; segment++)
|
||||
|
@ -69,9 +69,8 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
crc = UpdateCRC16(crc, upper_end);
|
||||
ushort start = (ushort)(upper_start << 8);
|
||||
ushort end = (ushort)((upper_end << 8) | 0xFF);
|
||||
// This range is invalid if it starts at a higher range than it ends.
|
||||
if (end < start)
|
||||
throw new ArgumentException();
|
||||
throw new ArgumentException("Ranges can't start higher than they end.");
|
||||
for (int addr = start; addr <= end; addr++)
|
||||
{
|
||||
ushort data;
|
||||
|
@ -80,12 +79,11 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
crc = UpdateCRC16(crc, high);
|
||||
crc = UpdateCRC16(crc, low);
|
||||
data = (ushort)((high << 8) | low);
|
||||
Intellicart[addr] = data;
|
||||
Data[addr] = data;
|
||||
}
|
||||
expected = (ushort)((Rom[offset++] << 8) | Rom[offset++]);
|
||||
// Check if there is an invalid CRC.
|
||||
if (expected != crc)
|
||||
throw new ArgumentException();
|
||||
throw new ArgumentException("Invalid CRC.");
|
||||
}
|
||||
// Parse for memory attributes.
|
||||
for (int range = 0; range < 32; range++)
|
||||
|
@ -117,9 +115,8 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
int range_start = range * 2048;
|
||||
ushort start = (ushort)((((Rom[index] >> 4) & 0x07) << 8) + range_start);
|
||||
ushort end = (ushort)((((Rom[index]) & 0x07) << 8) + 0xFF + range_start);
|
||||
// This range is invalid if it starts at a higher range than it ends.
|
||||
if (end < start)
|
||||
throw new ArgumentException();
|
||||
throw new ArgumentException("Ranges can't start higher than they end.");
|
||||
FineAddresses[range] = new ushort[2];
|
||||
FineAddresses[range][0] = start;
|
||||
FineAddresses[range][1] = end;
|
||||
|
@ -130,20 +127,20 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
expected = (ushort)((Rom[offset++] << 8) | (Rom[offset++] & 0xFF));
|
||||
// Check if there is an invalid CRC for the memory attributes / fine addresses.
|
||||
if (expected != crc)
|
||||
throw new ArgumentException();
|
||||
throw new ArgumentException("Invalid CRC.");
|
||||
return offset;
|
||||
}
|
||||
|
||||
public ushort? ReadCart(ushort addr)
|
||||
public ushort? Read(ushort addr)
|
||||
{
|
||||
int range = addr / 2048;
|
||||
bool[] attributes = MemoryAttributes[range];
|
||||
if (attributes[0] && addr >= FineAddresses[range][0] && addr <= FineAddresses[range][1])
|
||||
return Intellicart[addr];
|
||||
return Data[addr];
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool WriteCart(ushort addr, ushort value)
|
||||
public bool Write(ushort addr, ushort value)
|
||||
{
|
||||
int range = addr / 2048;
|
||||
bool[] attributes = MemoryAttributes[range];
|
||||
|
@ -154,7 +151,7 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
value &= 0xFF;
|
||||
if (attributes[3])
|
||||
throw new NotImplementedException("Bank-switched memory attribute not implemented.");
|
||||
Intellicart[addr] = value;
|
||||
Data[addr] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
GameInfo Game;
|
||||
|
||||
CP1610 Cpu;
|
||||
ICart Cart;
|
||||
|
||||
public void LoadExecutive_ROM()
|
||||
{
|
||||
|
@ -42,7 +43,12 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
Game = game;
|
||||
LoadExecutive_ROM();
|
||||
LoadGraphics_ROM();
|
||||
Parse();
|
||||
Cart = new Intellicart();
|
||||
if (Cart.Parse(Rom) == -1)
|
||||
{
|
||||
Cart = new Cartridge();
|
||||
Cart.Parse(Rom);
|
||||
}
|
||||
|
||||
Cpu = new CP1610();
|
||||
Cpu.ReadMemory = ReadMemory;
|
||||
|
|
|
@ -8,17 +8,6 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
public sealed partial class Intellivision
|
||||
{
|
||||
private const string INVALID = "Invalid memory address.";
|
||||
private const string UNOCCUPIED = "Unoccupied memory address.";
|
||||
private const string UNOCCUPIED_CART_READ = "Unoccupied memory address available to cartridge not mapped as"
|
||||
+ " readable.";
|
||||
private const string UNOCCUPIED_CART_WRITE = "Unoccupied memory address available to cartridge not mapped as"
|
||||
+ " writable.";
|
||||
private const string READ_ONLY_STIC = "This STIC Register alias is read-only.";
|
||||
private const string READ_ONLY_EXEC = "Executive ROM is read-only.";
|
||||
private const string READ_ONLY_GROM = "Graphics ROM is read-only.";
|
||||
private const string WRITE_ONLY_STIC = "This STIC Register alias is write-only.";
|
||||
private const string GARBAGE = "Memory address contains a garbage value, perhaps only in the Intellivision II.";
|
||||
private const string INTV2_EXEC = "Additional EXEC ROM, Intellivision II only.";
|
||||
|
||||
private ushort[] STIC_Registers = new ushort[64];
|
||||
private ushort[] Scratchpad_RAM = new ushort[240];
|
||||
|
@ -27,12 +16,11 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
private ushort[] Executive_ROM = new ushort[4096]; // TODO: Intellivision II support?
|
||||
private ushort[] Graphics_ROM = new ushort[2048];
|
||||
private ushort[] Graphics_RAM = new ushort[512];
|
||||
private ushort[] Cartridge = new ushort[56320]; // TODO: Resize as cartridge mapping grows.
|
||||
|
||||
public ushort ReadMemory(ushort addr)
|
||||
{
|
||||
ushort? cart = ReadCart(addr);
|
||||
ushort core;
|
||||
ushort? cart = Cart.Read(addr);
|
||||
ushort? core = null;
|
||||
switch (addr & 0xF000)
|
||||
{
|
||||
case 0x0000:
|
||||
|
@ -43,7 +31,8 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
// TODO: OK only during VBlank Period 2.
|
||||
core = STIC_Registers[addr & 0x003F];
|
||||
else if (addr <= 0x00FF)
|
||||
throw new ArgumentException(UNOCCUPIED);
|
||||
// Unoccupied.
|
||||
break;
|
||||
else if (addr <= 0x01EF)
|
||||
core = Scratchpad_RAM[addr & 0x00EF];
|
||||
else if (addr <= 0x01FF)
|
||||
|
@ -51,44 +40,15 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
else if (addr <= 0x035F)
|
||||
core = System_RAM[addr & 0x015F];
|
||||
else if (addr <= 0x03FF)
|
||||
// TODO: Intellivision II support?
|
||||
throw new ArgumentException(GARBAGE);
|
||||
// TODO: Garbage values for Intellivision II.
|
||||
break;
|
||||
else if (addr <= 0x04FF)
|
||||
// TODO: Actually map cartridge (on all but Intellivision II) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
// TODO: Intellivision II support?
|
||||
throw new ArgumentException(INTV2_EXEC);
|
||||
else
|
||||
core = Cartridge[addr & 0x00FF];
|
||||
else if (addr <= 0x06FF)
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[addr & 0x02FF];
|
||||
else if (addr <= 0x0CFF)
|
||||
// TODO: Actually map cartridge (only if no Intellivoice) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[addr & 0x08FF];
|
||||
else
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[addr & 0x0BFF];
|
||||
// TODO: Additional EXEC ROM for Intellivision II.
|
||||
break;
|
||||
break;
|
||||
case 0x1000:
|
||||
core = Executive_ROM[addr & 0x0FFF];
|
||||
break;
|
||||
case 0x2000:
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0x0C00];
|
||||
break;
|
||||
case 0x3000:
|
||||
if (addr <= 0x37FF)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
|
@ -109,667 +69,269 @@ namespace BizHawk.Emulation.Consoles.Intellivision
|
|||
case 0x4000:
|
||||
if (addr <= 0x403F)
|
||||
{
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (true)
|
||||
{
|
||||
if (addr == 0x4021)
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
if (addr == 0x4021)
|
||||
// TODO: Switch into Color Stack mode.
|
||||
core = STIC_Registers[0x0021];
|
||||
else
|
||||
throw new ArgumentException(WRITE_ONLY_STIC);
|
||||
}
|
||||
else
|
||||
core = Cartridge[(addr & 0x003F) + 0x1C00];
|
||||
}
|
||||
else if (addr <= 0x47FF)
|
||||
{
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x07FF) + 0x1C00];
|
||||
}
|
||||
else if (addr == 0x4800)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[0x2400];
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0x1C00];
|
||||
}
|
||||
break;
|
||||
case 0x5000:
|
||||
case 0x6000:
|
||||
if (addr <= 0x5014)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0014) + 0x2C00];
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x1FFF) + 0x2C00];
|
||||
// TODO: Switch into Color Stack mode.
|
||||
core = STIC_Registers[0x0021];
|
||||
}
|
||||
break;
|
||||
case 0x7000:
|
||||
if (addr == 0x7000)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (confuses EXEC boot sequence) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[0x04C00];
|
||||
}
|
||||
else if (addr <= 0x77FF)
|
||||
{
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x07FF) + 0x4C00];
|
||||
}
|
||||
if (addr <= 0x77FF)
|
||||
// Available to cartridges.
|
||||
break;
|
||||
else if (addr <= 0x79FF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x09FF) + 0x4C00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else if (addr <= 0x7BFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0BFF) + 0x4C00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else if (addr <= 0x7DFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0DFF) + 0x4C00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0x4C00];
|
||||
}
|
||||
break;
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
case 0x8000:
|
||||
if (addr <= 0x803F)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (true)
|
||||
{
|
||||
if (addr == 0x8021)
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
if (addr == 0x8021)
|
||||
// TODO: Switch into Color Stack mode.
|
||||
core = STIC_Registers[0x0021];
|
||||
else
|
||||
throw new ArgumentException(WRITE_ONLY_STIC);
|
||||
}
|
||||
else
|
||||
core = Cartridge[(addr & 0x003F) + 0x5C00];
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0x5C00];
|
||||
// TODO: Switch into Color Stack mode.
|
||||
core = STIC_Registers[0x0021];
|
||||
}
|
||||
break;
|
||||
case 0x9000:
|
||||
case 0xA000:
|
||||
case 0xB000:
|
||||
if (addr <= 0xB7FF)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x27FF) + 0x6C00];
|
||||
}
|
||||
// Available to cartridges.
|
||||
break;
|
||||
else if (addr <= 0xB9FF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x29FF) + 0x6C00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else if (addr <= 0xBBFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x2BFF) + 0x6C00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else if (addr <= 0xBDFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x2DFF) + 0x6C00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x2FFF) + 0x6C00];
|
||||
}
|
||||
break;
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
case 0xC000:
|
||||
if (addr <= 0xC03F)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (true)
|
||||
{
|
||||
if (addr == 0xC021)
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
if (addr == 0xC021)
|
||||
// TODO: Switch into Color Stack mode.
|
||||
core = STIC_Registers[0x0021];
|
||||
else
|
||||
throw new ArgumentException(WRITE_ONLY_STIC);
|
||||
}
|
||||
else
|
||||
core = Cartridge[(addr & 0x003F) + 0x9C00];
|
||||
// TODO: Switch into Color Stack mode.
|
||||
core = STIC_Registers[0x0021];
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0x9C00];
|
||||
}
|
||||
break;
|
||||
case 0xD000:
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0xAC00];
|
||||
break;
|
||||
case 0xE000:
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0xBC00];
|
||||
break;
|
||||
case 0xF000:
|
||||
if (addr <= 0xF7FF)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x07FF) + 0xCC00];
|
||||
}
|
||||
// Available to cartridges.
|
||||
break;
|
||||
else if (addr <= 0xF9FF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x09FF) + 0xCC00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else if (addr <= 0xFBFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0BFF) + 0xCC00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else if (addr <= 0xFDFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0DFF) + 0xCC00];
|
||||
}
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
else
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_READ);
|
||||
else
|
||||
core = Cartridge[(addr & 0x0FFF) + 0xCC00];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException(INVALID);
|
||||
// Write-only Graphics RAM.
|
||||
break;
|
||||
}
|
||||
/*
|
||||
TODO: Fix Intellicart hook.
|
||||
if (cart != null)
|
||||
return (ushort)cart;
|
||||
*/
|
||||
return core;
|
||||
else if (core == null)
|
||||
throw new ArgumentException(INVALID);
|
||||
return (ushort)core;
|
||||
}
|
||||
|
||||
public void WriteMemory(ushort addr, ushort value)
|
||||
public bool WriteMemory(ushort addr, ushort value)
|
||||
{
|
||||
WriteCart(addr, value);
|
||||
bool cart = Cart.Write(addr, value);
|
||||
switch (addr & 0xF000)
|
||||
{
|
||||
case 0x0000:
|
||||
if (addr <= 0x003F)
|
||||
{
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
STIC_Registers[addr] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x007F)
|
||||
throw new ArgumentException(READ_ONLY_STIC);
|
||||
// Read-only STIC.
|
||||
break;
|
||||
else if (addr <= 0x00FF)
|
||||
throw new ArgumentException(UNOCCUPIED);
|
||||
// Unoccupied.
|
||||
break;
|
||||
else if (addr <= 0x01EF)
|
||||
{
|
||||
Scratchpad_RAM[addr & 0x00EF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x01FF)
|
||||
{
|
||||
PSG_Registers[addr & 0x000F] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x035F)
|
||||
{
|
||||
System_RAM[addr & 0x015F] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x03FF)
|
||||
// TODO: Intellivision II support?
|
||||
throw new ArgumentException(GARBAGE);
|
||||
// Read-only garbage values for Intellivision II.
|
||||
break;
|
||||
else if (addr <= 0x04FF)
|
||||
// TODO: Actually map cartridge (on all but Intellivision II) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
// TODO: Intellivision II support?
|
||||
throw new ArgumentException(INTV2_EXEC);
|
||||
else
|
||||
Cartridge[addr & 0x00FF] = value;
|
||||
else if (addr <= 0x06FF)
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[addr & 0x02FF] = value;
|
||||
else if (addr <= 0x0CFF)
|
||||
// TODO: Actually map cartridge (only if no Intellivoice) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[addr & 0x08FF] = value;
|
||||
else
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[addr & 0x0BFF] = value;
|
||||
// Read-only additional EXEC ROM for Intellivision II.
|
||||
break;
|
||||
break;
|
||||
case 0x1000:
|
||||
throw new ArgumentException(READ_ONLY_EXEC);
|
||||
case 0x2000:
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0x0C00] = value;
|
||||
// Read-only Executive ROM.
|
||||
break;
|
||||
case 0x3000:
|
||||
if (addr <= 0x37FF)
|
||||
throw new ArgumentException(READ_ONLY_GROM);
|
||||
// Read-only Graphics ROM.
|
||||
break;
|
||||
else if (addr <= 0x39FF)
|
||||
{
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x3BFF)
|
||||
{
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x3DFF)
|
||||
{
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case 0x4000:
|
||||
if (addr <= 0x403F)
|
||||
{
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
STIC_Registers[addr & 0x003F] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x003F) + 0x1C00] = value;
|
||||
}
|
||||
else if (addr <= 0x47FF)
|
||||
{
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x07FF) + 0x1C00] = value;
|
||||
}
|
||||
else if (addr == 0x4800)
|
||||
{
|
||||
// TODO: Actually map cartridge (only if boot ROM at $7000) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[0x2400] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0x1C00] = value;
|
||||
}
|
||||
break;
|
||||
case 0x5000:
|
||||
case 0x6000:
|
||||
if (addr <= 0x5014)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map (only if boot ROM at $4800 or $7000) cartridge RAM / ROM to decide which path to
|
||||
take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x0014) + 0x2C00] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x1FFF) + 0x2C00] = value;
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
STIC_Registers[addr & 0x003F] = value;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 0x7000:
|
||||
if (addr == 0x7000)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (confuses EXEC boot sequence) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[0x04C00] = value;
|
||||
}
|
||||
else if (addr <= 0x77FF)
|
||||
{
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x07FF) + 0x4C00] = value;
|
||||
}
|
||||
if (addr <= 0x77FF)
|
||||
// Available to cartridges.
|
||||
break;
|
||||
else if (addr <= 0x79FF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x09FF) + 0x4C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x7BFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x0BFF) + 0x4C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0x7DFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x0DFF) + 0x4C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge (only if no ECS) RAM (Do not because of GRAM alias) / ROM to decide
|
||||
which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0x4C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 0x8000:
|
||||
if (addr <= 0x803F)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
STIC_Registers[addr & 0x003F] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x003F) + 0x5C00] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0x5C00] = value;
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
STIC_Registers[addr & 0x003F] = value;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 0x9000:
|
||||
case 0xA000:
|
||||
case 0xB000:
|
||||
if (addr <= 0xB7FF)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x27FF) + 0x6C00] = value;
|
||||
}
|
||||
// Available to cartridges.
|
||||
break;
|
||||
else if (addr <= 0xB9FF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x29FF) + 0x6C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0xBBFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x2BFF) + 0x6C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0xBDFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x2DFF) + 0x6C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x2FFF) + 0x6C00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 0xC000:
|
||||
if (addr <= 0x803F)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
STIC_Registers[addr & 0x003F] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x003F) + 0x9C00] = value;
|
||||
// TODO: OK only during VBlank Period 1.
|
||||
STIC_Registers[addr & 0x003F] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0x9C00] = value;
|
||||
}
|
||||
break;
|
||||
case 0xD000:
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0xAC00] = value;
|
||||
break;
|
||||
case 0xE000:
|
||||
// TODO: Actually map cartridge (only if no ECS) RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0xBC00] = value;
|
||||
break;
|
||||
case 0xF000:
|
||||
if (addr <= 0xF7FF)
|
||||
{
|
||||
// TODO: Actually map cartridge RAM / ROM to decide which path to take.
|
||||
if (false)
|
||||
throw new ArgumentException(UNOCCUPIED_CART_WRITE);
|
||||
else
|
||||
Cartridge[(addr & 0x07FF) + 0xCC00] = value;
|
||||
}
|
||||
// Available to cartridges.
|
||||
break;
|
||||
else if (addr <= 0xF9FF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x09FF) + 0xCC00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0xFBFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x0BFF) + 0xCC00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else if (addr <= 0xFDFF)
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x0DFF) + 0xCC00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
TODO: Actually map cartridge RAM (Do not because of GRAM alias) / ROM to decide which path to take.
|
||||
*/
|
||||
if (true)
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
else
|
||||
Cartridge[(addr & 0x0FFF) + 0xCC00] = value;
|
||||
// TODO: OK only during VBlank Period 2.
|
||||
Graphics_RAM[addr & 0x01FF] = value;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException(INVALID);
|
||||
}
|
||||
return cart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ namespace BizHawk
|
|||
{
|
||||
public interface ICart
|
||||
{
|
||||
ushort? ReadCart(ushort addr);
|
||||
bool WriteCart(ushort addr, ushort value);
|
||||
int Parse(byte[] Rom);
|
||||
ushort? Read(ushort addr);
|
||||
bool Write(ushort addr, ushort value);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue