mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-20 01:44:34 +00:00
184 lines
6.1 KiB
C#
184 lines
6.1 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace Contralto.CPU
|
|
{
|
|
/// <summary>
|
|
/// Maintains a set of Control ROM images dumped from real Alto hardware.
|
|
/// </summary>
|
|
static class ControlROM
|
|
{
|
|
static ControlROM()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
private static void Init()
|
|
{
|
|
if (Configuration.SystemType == SystemType.AltoI)
|
|
{
|
|
LoadConstants(_constantRomsAltoI, true);
|
|
LoadACSource(_acSourceRoms, true);
|
|
}
|
|
else
|
|
{
|
|
LoadConstants(_constantRomsAltoII, false);
|
|
LoadACSource(_acSourceRoms, true);
|
|
}
|
|
}
|
|
|
|
public static ushort[] ConstantROM
|
|
{
|
|
get { return _constantRom; }
|
|
}
|
|
|
|
public static byte[] ACSourceROM
|
|
{
|
|
get { return _acSourceRom; }
|
|
}
|
|
|
|
private static void LoadConstants(RomFile[] romInfo, bool flip)
|
|
{
|
|
_constantRom = new ushort[256];
|
|
|
|
foreach (RomFile file in romInfo)
|
|
{
|
|
//
|
|
// Each file contains 256 bytes, each byte containing one nybble in the low 4 bits.
|
|
//
|
|
using (FileStream fs = new FileStream(file.Filename, FileMode.Open, FileAccess.Read))
|
|
{
|
|
int length = (int)fs.Length;
|
|
if (length != 256)
|
|
{
|
|
throw new InvalidOperationException("ROM file should be 256 bytes in length");
|
|
}
|
|
|
|
byte[] data = new byte[fs.Length];
|
|
fs.Read(data, 0, (int)fs.Length);
|
|
|
|
// OR in the data
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
if (flip)
|
|
{
|
|
_constantRom[file.StartingAddress + i] |= (ushort)((DataMapConstantRom(~data[AddressMapConstantRom(i)]) & 0xf) << file.BitPosition);
|
|
}
|
|
else
|
|
{
|
|
_constantRom[file.StartingAddress + i] |= (ushort)((DataMapConstantRom(data[AddressMapConstantRom(i)]) & 0xf) << file.BitPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// And invert all bits
|
|
for (int i = 0; i < _constantRom.Length; i++)
|
|
{
|
|
_constantRom[i] = (ushort)((~_constantRom[i]) & 0xffff);
|
|
}
|
|
}
|
|
|
|
private static void LoadACSource(RomFile romInfo, bool reverseBits)
|
|
{
|
|
_acSourceRom = new byte[256];
|
|
|
|
using (FileStream fs = new FileStream(romInfo.Filename, FileMode.Open, FileAccess.Read))
|
|
{
|
|
int length = (int)fs.Length;
|
|
if (length != 256)
|
|
{
|
|
throw new InvalidOperationException("ROM file should be 256 bytes in length");
|
|
}
|
|
byte[] data = new byte[fs.Length];
|
|
fs.Read(data, 0, (int)fs.Length);
|
|
|
|
// Copy in the data, modifying the address as required.
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
if (reverseBits)
|
|
{
|
|
_acSourceRom[i] = (byte)((~DataMapConstantRom(data[AddressMapACSourceRom(i)])) & 0xf);
|
|
}
|
|
else
|
|
{
|
|
_acSourceRom[i] = (byte)((~data[AddressMapACSourceRom(i)]) & 0xf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static int AddressMapConstantRom(int address)
|
|
{
|
|
// Descramble the address bits as they are in no sane order.
|
|
// (See 05a_AIM.pdf, pg. 5 (Page 9 of the orginal docs))
|
|
int[] addressMapping = { 7, 2, 1, 0, 3, 4, 5, 6 };
|
|
|
|
int mappedAddress = 0;
|
|
|
|
for (int i = 0; i < addressMapping.Length; i++)
|
|
{
|
|
if ((address & (1 << i)) != 0)
|
|
{
|
|
mappedAddress |= (1 << (addressMapping[i]));
|
|
}
|
|
}
|
|
return mappedAddress;
|
|
}
|
|
|
|
private static int DataMapConstantRom(int data)
|
|
{
|
|
// Reverse bits 0-4.
|
|
int mappedData = 0;
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
if ((data & (1 << i)) != 0)
|
|
{
|
|
mappedData |= (1 << (3-i));
|
|
}
|
|
}
|
|
|
|
return mappedData;
|
|
}
|
|
|
|
private static int AddressMapACSourceRom(int data)
|
|
{
|
|
// Reverse bits 0-7.
|
|
int mappedData = 0;
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if ((data & (1 << i)) != 0)
|
|
{
|
|
mappedData |= (1 << (7 - i));
|
|
}
|
|
}
|
|
|
|
// And invert data lines
|
|
return (~mappedData) & 0xff;
|
|
}
|
|
|
|
private static RomFile[] _constantRomsAltoI =
|
|
{
|
|
new RomFile(Configuration.GetAltoIRomPath("c0_23.BIN"), 0x000, 12),
|
|
new RomFile(Configuration.GetAltoIRomPath("c1_23.BIN"), 0x000, 8),
|
|
new RomFile(Configuration.GetAltoIRomPath("c2_23.BIN"), 0x000, 4),
|
|
new RomFile(Configuration.GetAltoIRomPath("c3_23.BIN"), 0x000, 0),
|
|
};
|
|
|
|
private static RomFile[] _constantRomsAltoII =
|
|
{
|
|
new RomFile(Configuration.GetAltoIIRomPath("c0"), 0x000, 12),
|
|
new RomFile(Configuration.GetAltoIIRomPath("c1"), 0x000, 8),
|
|
new RomFile(Configuration.GetAltoIIRomPath("c2"), 0x000, 4),
|
|
new RomFile(Configuration.GetAltoIIRomPath("c3"), 0x000, 0),
|
|
};
|
|
|
|
private static RomFile _acSourceRoms = new RomFile(Configuration.GetRomPath("ACSOURCE.NEW"), 0x000, 0);
|
|
|
|
private static ushort[] _constantRom;
|
|
private static byte[] _acSourceRom;
|
|
}
|
|
}
|