Atari 2600 - some progress on the AR mapper (Super charger), but still doesn't work
This commit is contained in:
parent
09daa3f939
commit
dba0d25a5c
|
@ -18,16 +18,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
public M6532 M6532 { get; private set; }
|
public M6532 M6532 { get; private set; }
|
||||||
|
|
||||||
public int LastAddress;
|
public int LastAddress;
|
||||||
public int NumberOfDistinctAddresses;
|
public int DistinctAccessCount;
|
||||||
|
|
||||||
public byte BaseReadMemory(ushort addr)
|
public byte BaseReadMemory(ushort addr)
|
||||||
{
|
{
|
||||||
if (addr != LastAddress)
|
|
||||||
{
|
|
||||||
NumberOfDistinctAddresses++;
|
|
||||||
LastAddress = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = (ushort)(addr & 0x1FFF);
|
addr = (ushort)(addr & 0x1FFF);
|
||||||
if ((addr & 0x1080) == 0)
|
if ((addr & 0x1080) == 0)
|
||||||
{
|
{
|
||||||
|
@ -62,7 +56,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
{
|
{
|
||||||
if (addr != LastAddress)
|
if (addr != LastAddress)
|
||||||
{
|
{
|
||||||
NumberOfDistinctAddresses++;
|
DistinctAccessCount++;
|
||||||
LastAddress = addr;
|
LastAddress = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +77,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
|
|
||||||
public byte ReadMemory(ushort addr)
|
public byte ReadMemory(ushort addr)
|
||||||
{
|
{
|
||||||
|
if (addr != LastAddress)
|
||||||
|
{
|
||||||
|
DistinctAccessCount++;
|
||||||
|
LastAddress = addr;
|
||||||
|
}
|
||||||
|
|
||||||
_mapper.Bit13 = addr.Bit(13);
|
_mapper.Bit13 = addr.Bit(13);
|
||||||
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF));
|
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF));
|
||||||
CoreComm.MemoryCallbackSystem.CallRead(addr);
|
CoreComm.MemoryCallbackSystem.CallRead(addr);
|
||||||
|
@ -99,6 +99,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
|
|
||||||
public void WriteMemory(ushort addr, byte value)
|
public void WriteMemory(ushort addr, byte value)
|
||||||
{
|
{
|
||||||
|
if (addr != LastAddress)
|
||||||
|
{
|
||||||
|
DistinctAccessCount++;
|
||||||
|
LastAddress = addr;
|
||||||
|
}
|
||||||
|
|
||||||
_mapper.WriteMemory((ushort)(addr & 0x1FFF), value);
|
_mapper.WriteMemory((ushort)(addr & 0x1FFF), value);
|
||||||
|
|
||||||
CoreComm.MemoryCallbackSystem.CallWrite(addr);
|
CoreComm.MemoryCallbackSystem.CallWrite(addr);
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
/**
|
/**
|
||||||
This is the cartridge class for Arcadia (aka Starpath) Supercharger
|
This is the cartridge class for Arcadia (aka Starpath) Supercharger
|
||||||
|
@ -36,28 +40,50 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
// TODO: var names, savestates, hard reset, dispose, cart ram
|
// TODO: var names, savestates, hard reset, dispose, cart ram
|
||||||
public mAR(Atari2600 core)
|
public mAR(Atari2600 core)
|
||||||
{
|
{
|
||||||
|
// TODO: clean this stuff up
|
||||||
|
/*****************************************/
|
||||||
|
int size = core.Rom.Length;
|
||||||
|
mySize = core.Rom.Length < 8448 ? 8448 : core.Rom.Length; //8448 or Rom size, whichever is bigger
|
||||||
|
|
||||||
|
myNumberOfLoadImages = (byte)(mySize / 8448);
|
||||||
|
|
||||||
|
// TODO: why are we making a redundant copy?
|
||||||
|
myLoadedImages = new ByteBuffer(mySize);
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
myLoadedImages[i] = core.Rom[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < 8448)
|
||||||
|
{
|
||||||
|
for (int i = size; i < mySize; i++)
|
||||||
|
{
|
||||||
|
myLoadedImages[i] = DefaultHeader[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*****************************************/
|
||||||
|
|
||||||
Core = core;
|
Core = core;
|
||||||
InitializeRom();
|
InitializeRom();
|
||||||
BankConfiguration(0);
|
BankConfiguration(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _bank2k;
|
private ByteBuffer myImage = new ByteBuffer(8192);
|
||||||
//private ByteBuffer _ram = new ByteBuffer(6144);
|
private IntBuffer myImageOffsets = new IntBuffer(2);
|
||||||
ByteBuffer myImage = new ByteBuffer(8192);
|
private bool myWritePending = false;
|
||||||
private IntBuffer _imageOffsets = new IntBuffer(2);
|
private int myNumberOfDistinctAccesses = 0;
|
||||||
private bool _writePending = false;
|
private bool myWriteEnabled = false;
|
||||||
int myNumberOfDistinctAccesses = 0;
|
private byte myDataHoldRegister;
|
||||||
bool myWriteEnabled = false;
|
private byte myNumberOfLoadImages;
|
||||||
byte myDataHoldRegister;
|
private ByteBuffer myLoadedImages;
|
||||||
|
private byte[] myHeader = new byte[256];
|
||||||
// Indicates if the ROM's power is on or off
|
private bool myPower; // Indicates if the ROM's power is on or off
|
||||||
private bool myPower;
|
private int myPowerRomCycle; // Indicates when the power was last turned on
|
||||||
|
private int mySize;
|
||||||
// Indicates when the power was last turned on
|
|
||||||
int myPowerRomCycle;
|
|
||||||
|
|
||||||
private ulong _elapsedCycles;
|
private ulong _elapsedCycles;
|
||||||
|
|
||||||
|
#region SuperCharger Data
|
||||||
|
|
||||||
private readonly byte[] DummyRomCode = {
|
private readonly byte[] DummyRomCode = {
|
||||||
0xa5, 0xfa, 0x85, 0x80, 0x4c, 0x18, 0xf8, 0xff,
|
0xa5, 0xfa, 0x85, 0x80, 0x4c, 0x18, 0xf8, 0xff,
|
||||||
0xff, 0xff, 0x78, 0xd8, 0xa0, 0x00, 0xa2, 0x00,
|
0xff, 0xff, 0x78, 0xd8, 0xa0, 0x00, 0xa2, 0x00,
|
||||||
|
@ -133,6 +159,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
public override void ClockCpu()
|
public override void ClockCpu()
|
||||||
{
|
{
|
||||||
_elapsedCycles++;
|
_elapsedCycles++;
|
||||||
|
@ -141,68 +169,62 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
|
|
||||||
private byte ReadMem(ushort addr, bool peek)
|
private byte ReadMem(ushort addr, bool peek)
|
||||||
{
|
{
|
||||||
if (!peek)
|
if (addr < 0x1000) { if (peek) { return base.PeekMemory(addr); } else { return base.ReadMemory(addr); } }
|
||||||
|
|
||||||
|
/*---------------------------*/
|
||||||
|
|
||||||
|
if (addr == 0x1850 && myImageOffsets[1] == (3 << 11))
|
||||||
{
|
{
|
||||||
Address(addr);
|
LoadIntoRam(Core.MemoryDomains["System Bus"].PeekByte(0x80)); // Get load that's being accessed (BIOS places load number at 0x80) // TODO: a better way to do this
|
||||||
|
return myImage[(addr & 0x7FF) + myImageOffsets[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr < 0x1000)
|
if (myWritePending && // Cancel any pending write if more than 5 distinct accesses have occurred // TODO: Modify to handle when the distinct counter wraps around...
|
||||||
|
(Core.DistinctAccessCount > myNumberOfDistinctAccesses + 5))
|
||||||
{
|
{
|
||||||
return base.ReadMemory(addr);
|
myWritePending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr == 0x1850 && _imageOffsets[1] == (3 << 11))
|
/*---------------------------*/
|
||||||
{
|
|
||||||
/// TODO: weird stuff goes here
|
|
||||||
///
|
|
||||||
return myImage[(addr & 0x7FF) + _imageOffsets[1]];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!((addr & 0x0F00) > 0) && (!myWriteEnabled || !myWritePending))
|
||||||
// Cancel any pending write if more than 5 distinct accesses have occurred
|
|
||||||
// TODO: Modify to handle when the distinct counter wraps around...
|
|
||||||
if (_writePending &&
|
|
||||||
(Core.NumberOfDistinctAddresses > myNumberOfDistinctAccesses + 5))
|
|
||||||
{
|
|
||||||
_writePending = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!((addr & 0x0F00) > 0) && (!myWriteEnabled || !_writePending))
|
|
||||||
{
|
{
|
||||||
myDataHoldRegister = (byte)addr;
|
myDataHoldRegister = (byte)addr;
|
||||||
myNumberOfDistinctAccesses = Core.NumberOfDistinctAddresses;
|
addrThatChangedDataHoldRegister = addr;
|
||||||
_writePending = true;
|
myNumberOfDistinctAccesses = Core.DistinctAccessCount;
|
||||||
|
myWritePending = true;
|
||||||
}
|
}
|
||||||
|
else if ((addr & 0x1FFF) == 0x1FF8) // Is the bank configuration hotspot being accessed?
|
||||||
// Is the bank configuration hotspot being accessed?
|
|
||||||
else if (addr == 0x1FF8)
|
|
||||||
{
|
{
|
||||||
// Yes, so handle the bank configuration
|
myWritePending = false;
|
||||||
_writePending = false;
|
|
||||||
BankConfiguration(myDataHoldRegister);
|
BankConfiguration(myDataHoldRegister);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if (myWriteEnabled && myWritePending &&
|
||||||
else if (myWriteEnabled &&
|
Core.DistinctAccessCount == (myNumberOfDistinctAccesses + 5))
|
||||||
_writePending &&
|
|
||||||
Core.NumberOfDistinctAddresses == (myNumberOfDistinctAccesses + 5))
|
|
||||||
{
|
{
|
||||||
if ((addr & 0x800) == 0)
|
if ((addr & 0x800) == 0)
|
||||||
{
|
{
|
||||||
// TODO
|
var test1 = addr & 0x07FF;
|
||||||
|
myImage[(addr & 0x07FF) + myImage[0]] = myDataHoldRegister;
|
||||||
}
|
}
|
||||||
else if (_imageOffsets[1] != (3 << 11)) // Don't poke Rom
|
else if (myImageOffsets[1] != (3 << 11)) // Don't poke Rom
|
||||||
{
|
{
|
||||||
// TODO
|
var test2 = addr & 0x07FF;
|
||||||
|
myImage[(addr & 0x07FF) + myImageOffsets[1]] = myDataHoldRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
_writePending = false;
|
myWritePending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempVal = (addr & 0x07FF) + _imageOffsets[((addr & 0x800) > 0) ? 1 : 0];
|
/*---------------------------*/
|
||||||
return myImage[(addr & 0x07FF) + _imageOffsets[((addr & 0x800) > 0) ? 1 : 0]];
|
|
||||||
|
return myImage[(addr & 0x07FF) + myImageOffsets[((addr & 0x800) > 0) ? 1 : 0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temp hacks
|
||||||
|
bool written = false;
|
||||||
|
ushort addrThatChangedDataHoldRegister;
|
||||||
|
|
||||||
public override byte ReadMemory(ushort addr)
|
public override byte ReadMemory(ushort addr)
|
||||||
{
|
{
|
||||||
|
@ -214,15 +236,54 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
return ReadMem(addr, true);
|
return ReadMem(addr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Address(ushort addr)
|
public override void WriteMemory(ushort addr, byte value)
|
||||||
{
|
{
|
||||||
if (addr == 0x1FF8)
|
if (myWritePending && (Core.DistinctAccessCount > myNumberOfDistinctAccesses + 5))
|
||||||
{
|
{
|
||||||
_bank2k = 0;
|
int xxxx = 0;
|
||||||
}
|
}
|
||||||
else if (addr == 0x1FF9)
|
|
||||||
|
|
||||||
|
if (addr < 0x1000)
|
||||||
{
|
{
|
||||||
_bank2k = 1;
|
base.WriteMemory(addr, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myWritePending && (Core.DistinctAccessCount > myNumberOfDistinctAccesses + 5))
|
||||||
|
{
|
||||||
|
myWritePending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the data hold register being set?
|
||||||
|
if (!((addr & 0x0F00) > 0) && (!myWriteEnabled || !myWritePending))
|
||||||
|
{
|
||||||
|
myDataHoldRegister = (byte)addr;
|
||||||
|
myNumberOfDistinctAccesses = Core.DistinctAccessCount;
|
||||||
|
myWritePending = true;
|
||||||
|
}
|
||||||
|
// Is the bank configuration hotspot being accessed?
|
||||||
|
else if ((addr & 0x1FFF) == 0x1FF8)
|
||||||
|
{
|
||||||
|
// Yes, so handle bank configuration
|
||||||
|
myWritePending = false;
|
||||||
|
BankConfiguration(myDataHoldRegister);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle poke if writing enabled
|
||||||
|
else if (myWriteEnabled && myWritePending &&
|
||||||
|
(Core.DistinctAccessCount == (myNumberOfDistinctAccesses + 5)))
|
||||||
|
{
|
||||||
|
if ((addr & 0x0800) == 0)
|
||||||
|
{
|
||||||
|
myImage[(addr & 0x07FF) + myImageOffsets[0]] = myDataHoldRegister;
|
||||||
|
}
|
||||||
|
else if (myImageOffsets[1] != (3 << 11)) // Can't poke to ROM
|
||||||
|
{
|
||||||
|
myImage[(addr & 0x07FF) + myImageOffsets[1]] = myDataHoldRegister;
|
||||||
|
}
|
||||||
|
|
||||||
|
myWritePending = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,48 +343,138 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||||
// p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're
|
// p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're
|
||||||
// wanting to access the ROM for multiloads. Otherwise set to 1.
|
// wanting to access the ROM for multiloads. Otherwise set to 1.
|
||||||
|
|
||||||
_bank2k = configuration & 0x1F; // remember for the bank() method
|
//_bank2k = configuration & 0x1F; // remember for the bank() method
|
||||||
myPower = !((configuration & 0x01) > 0);
|
myPower = !((configuration & 0x01) > 0);
|
||||||
if (myPower)
|
if (myPower)
|
||||||
{
|
{
|
||||||
myPowerRomCycle = (int)_elapsedCycles;
|
myPowerRomCycle = (int)_elapsedCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myWriteEnabled = (configuration & 0x02) > 0;
|
||||||
|
|
||||||
switch ((configuration >> 2) & 0x07)
|
switch ((configuration >> 2) & 0x07)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
_imageOffsets[0] = 2 << 11;
|
myImageOffsets[0] = 2 << 11;
|
||||||
_imageOffsets[1] = 3 << 11;
|
myImageOffsets[1] = 3 << 11;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
_imageOffsets[0] = 0;
|
myImageOffsets[0] = 0;
|
||||||
_imageOffsets[1] = 3 << 11;
|
myImageOffsets[1] = 3 << 11;
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
_imageOffsets[0] = 2 << 11;
|
myImageOffsets[0] = 2 << 11;
|
||||||
_imageOffsets[1] = 0;
|
myImageOffsets[1] = 0;
|
||||||
break;
|
break;
|
||||||
case 0x03:
|
case 0x03:
|
||||||
_imageOffsets[0] = 0;
|
myImageOffsets[0] = 0;
|
||||||
_imageOffsets[1] = 2 << 11;
|
myImageOffsets[1] = 2 << 11;
|
||||||
break;
|
break;
|
||||||
case 0x04:
|
case 0x04:
|
||||||
_imageOffsets[0] = 2 << 11;
|
myImageOffsets[0] = 2 << 11;
|
||||||
_imageOffsets[1] = 3 << 11;
|
myImageOffsets[1] = 3 << 11;
|
||||||
break;
|
break;
|
||||||
case 0x05:
|
case 0x05:
|
||||||
_imageOffsets[0] = 1 << 11;
|
myImageOffsets[0] = 1 << 11;
|
||||||
_imageOffsets[1] = 3 << 11;
|
myImageOffsets[1] = 3 << 11;
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
_imageOffsets[0] = 2 << 11;
|
myImageOffsets[0] = 2 << 11;
|
||||||
_imageOffsets[1] = 1 << 11;
|
myImageOffsets[1] = 1 << 11;
|
||||||
break;
|
break;
|
||||||
case 0x07:
|
case 0x07:
|
||||||
_imageOffsets[0] = 1 << 11;
|
myImageOffsets[0] = 1 << 11;
|
||||||
_imageOffsets[1] = 2 << 11;
|
myImageOffsets[1] = 2 << 11;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadIntoRam(byte load)
|
||||||
|
{
|
||||||
|
ushort image;
|
||||||
|
|
||||||
|
for (image = 0; image < myNumberOfLoadImages; image++)
|
||||||
|
{
|
||||||
|
if (myLoadedImages[(image * 8448) + 8192 + 5] == load)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
myHeader[i] = myLoadedImages[(image * 8448) + 8192 + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Checksum(myHeader.Take(8).ToArray()) != 0x55)
|
||||||
|
{
|
||||||
|
Console.WriteLine("WARNING: The Supercharger header checksum is invalid...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: verify the load's header
|
||||||
|
|
||||||
|
// Load all of the pages from the load
|
||||||
|
bool invalidPageChecksumSeen = false;
|
||||||
|
for (int j = 0; j < myHeader[3]; j++)
|
||||||
|
{
|
||||||
|
int bank = myHeader[16 + j] & 0x03;
|
||||||
|
int page = (myHeader[16 + j] >> 2) & 0x07;
|
||||||
|
var src = myLoadedImages.Arr.Skip((image * 8448) + (j * 256)).Take(256).ToArray();
|
||||||
|
byte sum = (byte)(Checksum(src) + myHeader[16 + j] + myHeader[64 + j]);
|
||||||
|
|
||||||
|
if (!invalidPageChecksumSeen && (sum != 0x55))
|
||||||
|
{
|
||||||
|
Console.WriteLine("WARNING: Some Supercharger page checksums are invalid...");
|
||||||
|
invalidPageChecksumSeen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bank < 3)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < src.Length; k++)
|
||||||
|
{
|
||||||
|
myImage[(bank * 2048) + (page * 256) + k] = src[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: is this the correct Write to do?
|
||||||
|
base.WriteMemory(0xFE, myHeader[0]);
|
||||||
|
base.WriteMemory(0xFF, myHeader[1]);
|
||||||
|
base.WriteMemory(0x80, myHeader[2]);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteToFile() // TODO: Delete me
|
||||||
|
{
|
||||||
|
// A hack for now, because this byte is different than in stella
|
||||||
|
if (myImage[6426] != 85)
|
||||||
|
{
|
||||||
|
myImage[6425] = 85;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!written)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < myImage.Len; i++)
|
||||||
|
{
|
||||||
|
sb.Append(((int)(myImage[i])).ToString()).AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText("C:\\Repos\\bizlog.log", sb.ToString());
|
||||||
|
|
||||||
|
written = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte Checksum(byte[] s)
|
||||||
|
{
|
||||||
|
byte sum = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < s.Count(); i++)
|
||||||
|
{
|
||||||
|
sum += s[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue