IntelliHawk:

-Cleanup.
-Added "Total Executed Cycles" to the log.
-By observing the aforementioned data, I realized that the docs probably meant to say 14934 instead of 14394.
--By adjusting this...TITLE SCREEN!
--Still, there are definitely discrepancies with the log that imply that I'm far from done.
-Enabled ANDR and XOR because they were executed during the title sequence, though it's hard to tell if it should at this point.
This commit is contained in:
brandman211 2012-12-17 04:23:59 +00:00
parent 461e6c6cea
commit 7ad002d5ce
9 changed files with 321 additions and 34 deletions

View File

@ -26,7 +26,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
static CP1610()
{
if (Logging)
{
Log = new StreamWriter("log_CP1610.txt");
}
}
public void Reset()
@ -35,7 +37,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
Interruptible = false;
FlagS = FlagC = FlagZ = FlagO = FlagI = FlagD = false;
for (int register = 0; register <= 6; register++)
{
Register[register] = 0;
}
RegisterPC = RESET;
}
@ -47,6 +51,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
public void SetIntRM(bool value)
{
IntRM = value;
if (IntRM)
{
Interrupted = false;
}
}
public void SetBusRq(bool value)
@ -67,9 +75,14 @@ namespace BizHawk.Emulation.CPUs.CP1610
public void LogData()
{
if (!Logging)
{
return;
}
Log.WriteLine("Total Executed Cycles = {0}", TotalExecutedCycles);
for (int register = 0; register <= 5; register++)
{
Log.WriteLine("R{0:d} = {1:X4}", register, Register[register]);
}
Log.WriteLine("SP = {0:X4}", RegisterSP);
Log.WriteLine("PC = {0:X4}", RegisterPC);
Log.WriteLine("S = {0}", FlagS);
@ -81,7 +94,13 @@ namespace BizHawk.Emulation.CPUs.CP1610
Log.WriteLine("INTRM = {0}", IntRM);
Log.WriteLine("BUSRQ = {0}", BusRq);
Log.WriteLine("BUSAK = {0}", BusAk);
//Log.WriteLine("MSYNC = {0}", MSync);
/*
Log.WriteLine("MSYNC = {0}", MSync);
Log.WriteLine("0x28 = {0}", ReadMemory(0x28));
Log.WriteLine("0x29 = {0}", ReadMemory(0x29));
Log.WriteLine("0x2A = {0}", ReadMemory(0x2A));
Log.WriteLine("0x2B = {0}", ReadMemory(0x2B));
*/
Log.Flush();
}
}

View File

@ -37,7 +37,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
addr = (ushort)(((decle2 << 8) & 0xFC00) | (decle3 & 0x3FF));
result = "J";
if (dest != 0x7)
{
result += "SR";
}
// ff indicates how to affect the Interrupt (I) flag in the CP1610
switch (decle2 & 0x3)
{
@ -52,7 +54,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
return UNKNOWN;
}
if (dest != 0x3)
{
result += " R" + dest + ",";
}
result += string.Format(" ${0:X4}", addr);
addrToAdvance = 3;
return result;
@ -122,13 +126,17 @@ namespace BizHawk.Emulation.CPUs.CP1610
case 0x035:
result = "NOP";
if ((opcode & 0x1) != 0)
{
result += " 1";
}
return result;
case 0x036:
case 0x037:
result = "SIN";
if ((opcode & 0x1) != 0)
{
result += " 1";
}
return result;
case 0x038:
case 0x039:
@ -151,7 +159,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "SWAP R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x048:
case 0x049:
@ -164,7 +174,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "SLL R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x050:
case 0x051:
@ -177,7 +189,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "RLC R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x058:
case 0x059:
@ -190,7 +204,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "SLLC R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x060:
case 0x061:
@ -203,7 +219,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "SLR R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x068:
case 0x069:
@ -216,7 +234,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "SAR R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x070:
case 0x071:
@ -229,7 +249,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "RRC R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x078:
case 0x079:
@ -242,7 +264,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = "SARC R" + dest;
if (((opcode >> 2) & 0x1) != 0)
{
result += ", 1";
}
return result;
case 0x080:
case 0x081:
@ -718,7 +742,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
cond = opcode & 0xF;
ext = opcode & 0x10;
if (ext != 0)
{
result = "BEXT";
}
else
{
switch (cond)
@ -777,10 +803,14 @@ namespace BizHawk.Emulation.CPUs.CP1610
{
// Branch in the reverse direction by negating the offset and subtracting 1.
if (((opcode >> 5) & 0x1) != 0)
{
offset = (ushort)(-offset - 1);
}
result += string.Format(" ${0:X4}", offset);
if (ext != 0)
{
result += string.Format(", ${0:X1}", opcode & 0x8);
}
}
addrToAdvance = 2;
return result;

View File

@ -47,9 +47,13 @@ namespace BizHawk.Emulation.CPUs.CP1610
ushort value;
// Auto-decrement the stack pointer if it's the memory register.
if (mem == 0x6)
{
RegisterSP--;
}
if (!FlagD)
{
value = ReadMemory(Register[mem]);
}
else
{
// Double Byte Data.
@ -58,7 +62,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
}
// Auto-increment the memory register if it does so on write.
if (mem >= 0x4 && mem != 0x6)
{
Register[mem]++;
}
return value;
}
@ -67,13 +73,19 @@ namespace BizHawk.Emulation.CPUs.CP1610
if (!FlagD)
{
if (mem != 0x6)
{
return 8;
}
else
{
return 11;
}
}
else
{
// Double Byte Data.
return 10;
}
}
public void Indirect_Set(byte mem, byte src)
@ -81,11 +93,14 @@ namespace BizHawk.Emulation.CPUs.CP1610
WriteMemory(Register[mem], Register[src]);
// Auto-increment the memory register if it does so on read.
if (mem >= 0x4)
{
Register[mem]++;
}
}
public int Execute()
{
int cycles = 0;
/*
Take an interrupt if the previous instruction was interruptible, interrupts are enabled, and IntRM has a
falling edge.
@ -103,7 +118,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
Interruptible = false;
Indirect_Set(6, 7);
RegisterPC = INTERRUPT;
return 28;
cycles = 28;
PendingCycles -= cycles;
TotalExecutedCycles += cycles;
return cycles;
}
if (Logging)
{
@ -115,7 +133,7 @@ namespace BizHawk.Emulation.CPUs.CP1610
}
byte dest, src, mem;
ushort dest_value, src_value, mem_read, addr, addr_read, offset;
int cycles = 0, decle2, decle3, result = 0, twos, status_word, lower, sign, cond, ext;
int decle2, decle3, result = 0, twos, status_word, lower, sign, cond, ext;
//int ones, carry;
bool branch = false;
bool FlagD_prev = FlagD;
@ -148,8 +166,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
// aaaaaaaaaaaaaaaa indicates the address to where the CP1610 should Jump
addr = (ushort)(((decle2 << 8) & 0xFC00) | (decle3 & 0x3FF));
if (dest != 0x7)
{
// Store the return address.
Register[dest] = (ushort)(RegisterPC & 0xFFFF);
}
// ff indicates how to affect the Interrupt (I) flag in the CP1610
switch (decle2 & 0x3)
{
@ -357,8 +377,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = Register[dest] << 1;
if (((opcode >> 2) & 0x1) == 0)
{
// Single shift.
cycles = 6;
}
else
{
// Double shift.
@ -385,8 +407,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
result = (dest_value << 1) | (FlagC ? 1 : 0);
FlagC = ((dest_value & 0x8000) != 0);
if (((opcode >> 2) & 0x1) == 0)
{
// Single rotate.
cycles = 6;
}
else
{
// Double rotate.
@ -415,8 +439,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
result = dest_value << 1;
FlagC = ((dest_value & 0x8000) != 0);
if (((opcode >> 2) & 0x1) == 0)
{
// Single shift.
cycles = 6;
}
else
{
// Double shift.
@ -442,8 +468,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
dest = (byte)(opcode & 0x3);
result = Register[dest] >> 1;
if (((opcode >> 2) & 0x1) == 0)
{
// Single shift.
cycles = 6;
}
else
{
// Double shift.
@ -469,8 +497,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
sign = dest_value & 0x8000;
result = (dest_value >> 1) | sign;
if (((opcode >> 2) & 0x1) == 0)
{
// Single shift.
cycles = 6;
}
else
{
// Double shift.
@ -497,8 +527,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
result = (dest_value >> 1) | ((FlagC ? 1 : 0) << 15);
FlagC = ((dest_value & 0x1) != 0);
if (((opcode >> 2) & 0x1) == 0)
{
// Single rotate.
cycles = 6;
}
else
{
// Double rotate.
@ -527,8 +559,10 @@ namespace BizHawk.Emulation.CPUs.CP1610
result = (dest_value >> 1) | sign;
FlagC = ((dest_value & 0x1) != 0);
if (((opcode >> 2) & 0x1) == 0)
{
// Single shift.
cycles = 6;
}
else
{
// Double shift.
@ -614,9 +648,13 @@ namespace BizHawk.Emulation.CPUs.CP1610
Calc_FlagZ(result);
Register[dest] = (ushort)result;
if (dest == 0x6 || dest == 0x7)
{
cycles = 7;
}
else
{
cycles = 6;
}
Interruptible = true;
break;
// ADDR
@ -922,16 +960,15 @@ namespace BizHawk.Emulation.CPUs.CP1610
case 0x1BD:
case 0x1BE:
case 0x1BF:
throw new NotImplementedException();
//src = (byte)((opcode >> 3) & 0x7);
//dest = (byte)(opcode & 0x7);
//result = Register[dest] & Register[src];
//Calc_FlagS(result);
//Calc_FlagZ(result);
//Register[dest] = (ushort)result;
//cycles = 6;
//Interruptible = true;
//break;
src = (byte)((opcode >> 3) & 0x7);
dest = (byte)(opcode & 0x7);
result = Register[dest] & Register[src];
Calc_FlagS(result);
Calc_FlagZ(result);
Register[dest] = (ushort)result;
cycles = 6;
Interruptible = true;
break;
// XORR
case 0x1C0:
case 0x1C1:
@ -1079,7 +1116,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
ext = opcode & 0x10;
// BEXT
if (ext != 0)
{
throw new ArgumentException(UNEXPECTED_BEXT);
}
else
{
switch (cond)
@ -1159,7 +1198,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
cycles = 9;
}
else
{
cycles = 7;
}
Interruptible = true;
break;
// MVO
@ -1700,18 +1741,17 @@ namespace BizHawk.Emulation.CPUs.CP1610
case 0x3C5:
case 0x3C6:
case 0x3C7:
throw new NotImplementedException();
//dest = (byte)(opcode & 0x7);
//addr = ReadMemory(RegisterPC++);
//dest_value = Register[dest];
//addr_read = ReadMemory(addr);
//result = dest_value ^ addr_read;
//Calc_FlagS(result);
//Calc_FlagZ(result);
//Register[dest] = (ushort)result;
//cycles = 10;
//Interruptible = true;
//break;
dest = (byte)(opcode & 0x7);
addr = ReadMemory(RegisterPC++);
dest_value = Register[dest];
addr_read = ReadMemory(addr);
result = dest_value ^ addr_read;
Calc_FlagS(result);
Calc_FlagZ(result);
Register[dest] = (ushort)result;
cycles = 10;
Interruptible = true;
break;
// XOR@
case 0x3C8:
case 0x3C9:
@ -1781,7 +1821,9 @@ namespace BizHawk.Emulation.CPUs.CP1610
break;
}
if (FlagD == FlagD_prev)
{
FlagD = false;
}
PendingCycles -= cycles;
TotalExecutedCycles += cycles;
return cycles;

View File

@ -15,7 +15,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
int index = 0;
// Combine every two bytes into a word.
while (index + 1 < Rom.Length)
{
Data[(index / 2) + 0x2C00] = (ushort)((Rom[index++] << 8) | Rom[index++]);
}
/*
for (int index = 0; index < Rom.Length; index++)
Data[index + 0x2C00] = Rom[index];
@ -32,17 +34,27 @@ namespace BizHawk.Emulation.Consoles.Intellivision
case 0x0000:
dest = addr - 0x0400;
if (addr <= 0x03FF)
{
break;
if (addr <= 0x04FF)
}
else if (addr <= 0x04FF)
{
// OK on all but Intellivision 2.
return Data[dest];
}
else if (addr <= 0x06FF)
{
return Data[dest];
}
else if (addr <= 0x0CFF)
{
// OK if no Intellivoice.
return Data[dest];
}
else
{
return Data[dest];
}
case 0x2000:
dest = (addr - 0x2000) + 0x0C00;
// OK if no ECS.
@ -50,34 +62,50 @@ namespace BizHawk.Emulation.Consoles.Intellivision
case 0x4000:
dest = (addr - 0x4000) + 0x1C00;
if (addr <= 0x47FF)
{
// OK if no ECS.
return Data[dest];
}
else if (addr == 0x4800)
{
// return Data[dest];
// For now, assume unmapped. TODO: Fix.
return null;
}
else
{
return Data[dest];
}
case 0x5000:
case 0x6000:
dest = (addr - 0x5000) + 0x2C00;
if (addr <= 0x5014)
{
return Data[dest];
}
else
{
return Data[dest];
}
case 0x7000:
dest = (addr - 0x7000) + 0x4C00;
if (addr == 0x7000)
{
// OK if no ECS.
// return Data[dest];
// For now, assume unmapped. TODO: Fix.
return null;
}
else if (addr <= 0x77FF)
{
// OK if no ECS.
return Data[dest];
}
else
{
// OK if no ECS.
return Data[dest];
}
case 0x8000:
dest = (addr - 0x8000) + 0x5C00;
// OK. Avoid STIC alias at $8000-$803F.
@ -87,9 +115,13 @@ namespace BizHawk.Emulation.Consoles.Intellivision
case 0xB000:
dest = (addr - 0x9000) + 0x6C00;
if (addr <= 0xB7FF)
{
return Data[dest];
}
else
{
return Data[dest];
}
case 0xC000:
dest = (addr - 0xC000) + 0x9C00;
// OK. Avoid STIC alias at $C000-$C03F.
@ -104,9 +136,13 @@ namespace BizHawk.Emulation.Consoles.Intellivision
case 0xF000:
dest = (addr - 0xF000) + 0xCC00;
if (addr <= 0xF7FF)
{
return Data[dest];
}
else
{
return Data[dest];
}
}
return null;
}
@ -120,8 +156,10 @@ namespace BizHawk.Emulation.Consoles.Intellivision
case 0x0000:
dest = addr - 0x0400;
if (addr <= 0x03FF)
{
break;
if (addr <= 0x04FF)
}
else if (addr <= 0x04FF)
{
// OK on all but Intellivision 2.
Data[dest] = value;

View File

@ -57,7 +57,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
int offset = 0;
// Check to see if the header is valid.
if (Rom[offset++] != 0xA8 || Rom[offset++] != (0xFF ^ Rom[offset++]))
{
return -1;
}
ushort crc, expected;
// Parse for data segments.
for (int segment = 0; segment < Rom[1]; segment++)
@ -70,7 +72,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
ushort start = (ushort)(upper_start << 8);
ushort end = (ushort)((upper_end << 8) | 0xFF);
if (end < start)
{
throw new ArgumentException("Ranges can't start higher than they end.");
}
for (int addr = start; addr <= end; addr++)
{
ushort data;
@ -83,7 +87,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
}
expected = (ushort)((Rom[offset++] << 8) | Rom[offset++]);
if (expected != crc)
{
throw new ArgumentException("Invalid CRC.");
}
}
// Parse for memory attributes.
for (int range = 0; range < 32; range++)
@ -91,7 +97,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
byte attributes = Rom[offset + (range >> 1)];
// Every second 2K block is stored in the upper 4 bits.
if ((range & 0x1) != 0)
{
attributes = (byte)(attributes >> 4);
}
attributes &= 0xF;
MemoryAttributes[range] = new bool[4];
// Readable.
@ -109,25 +117,35 @@ namespace BizHawk.Emulation.Consoles.Intellivision
int index;
// The lower and upper 2K in a 4K range are 16 addresses away from each other.
if ((range & 0x1) != 0)
{
index = offset + 16 + (range >> 1);
}
else
{
index = offset + 32 + (range >> 1);
}
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);
if (end < start)
{
throw new ArgumentException("Ranges can't start higher than they end.");
}
FineAddresses[range] = new ushort[2];
FineAddresses[range][0] = start;
FineAddresses[range][1] = end;
}
crc = 0xFFFF;
for (int index = 0; index < 48; index++)
{
crc = UpdateCRC16(crc, Rom[offset++]);
}
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("Invalid CRC.");
}
return offset;
}
@ -136,7 +154,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
int range = addr / 2048;
bool[] attributes = MemoryAttributes[range];
if (attributes[0] && addr >= FineAddresses[range][0] && addr <= FineAddresses[range][1])
{
return Data[addr];
}
return null;
}
@ -148,9 +168,13 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// Only write lower 8 bits if the Narrow attribute is set.
if (attributes[2])
{
value &= 0xFF;
}
if (attributes[3])
{
throw new NotImplementedException("Bank-switched memory attribute not implemented.");
}
Data[addr] = value;
return true;
}

View File

@ -25,17 +25,25 @@ namespace BizHawk.Emulation.Consoles.Intellivision
public void LoadExecutiveRom(string path)
{
var erom = File.ReadAllBytes(path);
if (erom.Length != 8192) throw new ApplicationException("EROM file is wrong size - expected 8192 bytes");
if (erom.Length != 8192)
{
throw new ApplicationException("EROM file is wrong size - expected 8192 bytes");
}
int index = 0;
// Combine every two bytes into a word.
while (index + 1 < erom.Length)
{
ExecutiveRom[index / 2] = (ushort)((erom[index++] << 8) | erom[index++]);
}
}
public void LoadGraphicsRom(string path)
{
GraphicsRom = File.ReadAllBytes(path);
if (GraphicsRom.Length != 2048) throw new ApplicationException("GROM file is wrong size - expected 2048 bytes");
if (GraphicsRom.Length != 2048)
{
throw new ApplicationException("GROM file is wrong size - expected 2048 bytes");
}
}
public Intellivision(CoreComm comm, GameInfo game, byte[] rom)
@ -73,7 +81,7 @@ namespace BizHawk.Emulation.Consoles.Intellivision
public void FrameAdvance(bool render, bool rendersound)
{
Frame++;
Cpu.AddPendingCycles(14394 + 3791);
Cpu.AddPendingCycles(14934);
while (Cpu.GetPendingCycles() > 0)
{
int cycles = Cpu.Execute();

View File

@ -26,93 +26,147 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
case 0x0000:
if (addr <= 0x007F)
{
// STIC.
break;
}
else if (addr <= 0x00FF)
{
// Unoccupied.
break;
}
else if (addr <= 0x01EF)
{
core = (ushort)(ScratchpadRam[addr - 0x0100] & 0x00FF);
}
else if (addr <= 0x01FF)
{
// PSG.
break;
}
else if (addr <= 0x035F)
{
core = SystemRam[addr - 0x0200];
}
else if (addr <= 0x03FF)
{
// TODO: Garbage values for Intellivision II.
break;
}
else if (addr <= 0x04FF)
{
// TODO: Additional EXEC ROM for Intellivision II.
break;
}
break;
case 0x1000:
core = (ushort)(ExecutiveRom[addr - 0x1000] & 0x3FF);
break;
case 0x3000:
if (addr <= 0x37FF)
{
// TODO: OK only during VBlank Period 2.
core = (byte)(GraphicsRom[addr - 0x3000] & 0x00FF);
}
else if (addr <= 0x39FF)
{
// TODO: OK only during VBlank Period 2.
core = (byte)(GraphicsRam[addr - 0x3800] & 0x00FF);
}
else if (addr <= 0x3BFF)
{
// TODO: OK only during VBlank Period 2.
core = (byte)(GraphicsRam[addr - 0x3A00] & 0x00FF);
}
else if (addr <= 0x3DFF)
{
// TODO: OK only during VBlank Period 2.
core = (byte)(GraphicsRam[addr - 0x3C00] & 0x00FF);
}
else
{
// TODO: OK only during VBlank Period 2.
core = (byte)(GraphicsRam[addr - 0x3E00] & 0x00FF);
}
break;
case 0x7000:
if (addr <= 0x77FF)
{
// Available to cartridges.
break;
}
else if (addr <= 0x79FF)
{
// Write-only Graphics RAM.
break;
}
else if (addr <= 0x7BFF)
{
// Write-only Graphics RAM.
break;
}
else if (addr <= 0x7DFF)
{
// Write-only Graphics RAM.
break;
}
else
{
// Write-only Graphics RAM.
break;
}
case 0xB000:
if (addr <= 0xB7FF)
{
// Available to cartridges.
break;
}
else if (addr <= 0xB9FF)
{
// Write-only Graphics RAM.
break;
}
else if (addr <= 0xBBFF)
{
// Write-only Graphics RAM.
break;
}
else if (addr <= 0xBDFF)
{
// Write-only Graphics RAM.
break;
}
else
{
// Write-only Graphics RAM.
break;
}
case 0xF000:
if (addr <= 0xF7FF)
{
// Available to cartridges.
break;
}
else if (addr <= 0xF9FF)
{
// Write-only Graphics RAM.
break;
}
else if (addr <= 0xFBFF)
{
// Write-only Graphics RAM.
break;
}
else if (addr <= 0xFDFF)
{
// Write-only Graphics RAM.
break;
}
else
{
// Write-only Graphics RAM.
break;
}
}
if (CoreComm.MemoryCallbackSystem.HasRead)
@ -121,13 +175,21 @@ namespace BizHawk.Emulation.Consoles.Intellivision
}
if (cart != null)
{
return (ushort)cart;
}
else if (stic != null)
{
return (ushort)stic;
}
else if (psg != null)
{
return (ushort)psg;
}
else if (core != null)
{
return (ushort)core;
}
return UNMAPPED;
}
@ -140,11 +202,15 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
case 0x0000:
if (addr <= 0x007F)
{
// STIC.
break;
}
else if (addr <= 0x00FF)
{
// Unoccupied.
break;
}
else if (addr <= 0x01EF)
{
ScratchpadRam[addr - 0x0100] = (byte)(value & 0x00FF);
@ -161,19 +227,25 @@ namespace BizHawk.Emulation.Consoles.Intellivision
return true;
}
else if (addr <= 0x03FF)
{
// Read-only garbage values for Intellivision II.
break;
}
else if (addr <= 0x04FF)
{
// Read-only additional EXEC ROM for Intellivision II.
break;
}
break;
case 0x1000:
// Read-only Executive ROM.
break;
case 0x3000:
if (addr <= 0x37FF)
{
// Read-only Graphics ROM.
break;
}
else if (addr <= 0x39FF)
{
// TODO: OK only during VBlank Period 2.
@ -200,8 +272,10 @@ namespace BizHawk.Emulation.Consoles.Intellivision
}
case 0x7000:
if (addr <= 0x77FF)
{
// Available to cartridges.
break;
}
else if (addr <= 0x79FF)
{
// TODO: OK only during VBlank Period 2.
@ -230,8 +304,10 @@ namespace BizHawk.Emulation.Consoles.Intellivision
case 0xA000:
case 0xB000:
if (addr <= 0xB7FF)
{
// Available to cartridges.
break;
}
else if (addr <= 0xB9FF)
{
// TODO: OK only during VBlank Period 2.
@ -258,8 +334,10 @@ namespace BizHawk.Emulation.Consoles.Intellivision
}
case 0xF000:
if (addr <= 0xF7FF)
{
// Available to cartridges.
break;
}
else if (addr <= 0xF9FF)
{
// TODO: OK only during VBlank Period 2.

View File

@ -18,7 +18,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
public ushort? ReadPSG(ushort addr)
{
if (addr >= 0x01F0 && addr <= 0x01FF)
{
return Register[addr - 0x01F0];
}
return null;
}

View File

@ -72,19 +72,25 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// TODO: OK only during VBlank Period 1.
if (addr == 0x0021)
{
Fgbg = false;
}
return Register[addr];
}
else if (addr <= 0x007F)
{
// TODO: OK only during VBlank Period 2.
return Register[addr - 0x0040];
}
break;
case 0x4000:
if (addr <= 0x403F)
{
// TODO: OK only during VBlank Period 1.
if (addr == 0x4021)
{
Fgbg = false;
}
}
break;
case 0x8000:
@ -92,7 +98,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// TODO: OK only during VBlank Period 1.
if (addr == 0x8021)
{
Fgbg = false;
}
}
break;
case 0xC000:
@ -100,7 +108,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// TODO: OK only during VBlank Period 1.
if (addr == 0xC021)
{
Fgbg = false;
}
}
break;
}
@ -116,20 +126,26 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// TODO: OK only during VBlank Period 1.
if (addr == 0x0021)
{
Fgbg = true;
}
Register[addr] = value;
return true;
}
else if (addr <= 0x007F)
{
// Read-only STIC.
break;
}
break;
case 0x4000:
if (addr <= 0x403F)
{
// TODO: OK only during VBlank Period 1.
if (addr == 0x4021)
{
Fgbg = true;
}
Register[addr - 0x4000] = value;
return true;
}
@ -139,7 +155,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// TODO: OK only during VBlank Period 1.
if (addr == 0x8021)
{
Fgbg = true;
}
Register[addr & 0x003F] = value;
return true;
}
@ -149,7 +167,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// TODO: OK only during VBlank Period 1.
if (addr == 0xC021)
{
Fgbg = true;
}
Register[addr - 0xC000] = value;
return true;
}
@ -160,16 +180,20 @@ namespace BizHawk.Emulation.Consoles.Intellivision
public void Execute(int cycles)
{
PendingCycles -= cycles;
TotalExecutedCycles += cycles;
if (PendingCycles <= 0)
{
Sr1 = !Sr1;
if (Sr1)
AddPendingCycles(14394 - 3791 + 530);
{
AddPendingCycles(14934 - 3791);
}
else
{
AddPendingCycles(3791);
}
}
PendingCycles -= cycles;
TotalExecutedCycles += cycles;
}
public int ColorToRGBA(int color)
@ -226,7 +250,7 @@ namespace BizHawk.Emulation.Consoles.Intellivision
bool gram = ((card & 0x0800) != 0);
int card_num = card >> 3;
int fg = card & 0x0007;
int bg = 0x000000;
int bg;
if (Fgbg)
{
bg = ((card >> 9) & 0x0008) | ((card >> 11) & 0x0004) | ((card >> 9) & 0x0003);
@ -264,23 +288,33 @@ namespace BizHawk.Emulation.Consoles.Intellivision
{
// The rightmost column does not get displayed.
if (card_col == 19 && squares_col == 7)
{
continue;
}
int color;
int pixel = buffer_offset + (squares_row * 159) + squares_col;
// Determine the color of the quadrant the pixel is in.
if (squares_col < 4)
{
if (squares_row < 4)
{
color = 0;
}
else
{
color = 2;
}
}
else
{
if (squares_row < 4)
{
color = 1;
}
else
{
color = 3;
}
}
FrameBuffer[pixel] = ColorToRGBA(colors[color]);
}
@ -294,7 +328,9 @@ namespace BizHawk.Emulation.Consoles.Intellivision
// Cycle through the Color Stack registers.
ColorSP++;
if (ColorSP > 0x002B)
{
ColorSP = 0x0028;
}
}
bg = ReadMemory(ColorSP) & 0x000F;
}
@ -305,21 +341,31 @@ namespace BizHawk.Emulation.Consoles.Intellivision
int row_mem = (card_num * 8) + pict_row;
byte row;
if (gram)
{
row = (byte)ReadMemory((ushort)(0x3800 + row_mem));
}
else
{
row = (byte)ReadMemory((ushort)(0x3000 + row_mem));
}
for (int pict_col = 0; pict_col < 8; pict_col++)
{
// The rightmost column does not get displayed.
if (card_col == 19 && pict_col == 0)
{
continue;
}
int pixel = buffer_offset + (pict_row * 159) + (7 - pict_col);
// If the pixel is on, give it the FG color.
if ((row & 0x1) != 0)
{
// The pixels go right as the bits get less significant.
FrameBuffer[pixel] = ColorToRGBA(fg);
}
else
{
FrameBuffer[pixel] = ColorToRGBA(bg);
}
row >>= 1;
}
}