From 7ad002d5ce8cfa4e6ebce56d5f67511df21842f1 Mon Sep 17 00:00:00 2001 From: brandman211 Date: Mon, 17 Dec 2012 04:23:59 +0000 Subject: [PATCH] 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. --- BizHawk.Emulation/CPUs/CP1610/CP1610.cs | 21 ++++- BizHawk.Emulation/CPUs/CP1610/Disassembler.cs | 30 +++++++ BizHawk.Emulation/CPUs/CP1610/Execute.cs | 90 ++++++++++++++----- .../Consoles/Intellivision/Cartridge.cs | 42 ++++++++- .../Consoles/Intellivision/Intellicart.cs | 24 +++++ .../Consoles/Intellivision/Intellivision.cs | 14 ++- .../Consoles/Intellivision/MemoryMap.cs | 78 ++++++++++++++++ .../Consoles/Intellivision/PSG.cs | 2 + .../Consoles/Intellivision/STIC.cs | 54 ++++++++++- 9 files changed, 321 insertions(+), 34 deletions(-) diff --git a/BizHawk.Emulation/CPUs/CP1610/CP1610.cs b/BizHawk.Emulation/CPUs/CP1610/CP1610.cs index 162af684f0..f5328ae539 100644 --- a/BizHawk.Emulation/CPUs/CP1610/CP1610.cs +++ b/BizHawk.Emulation/CPUs/CP1610/CP1610.cs @@ -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(); } } diff --git a/BizHawk.Emulation/CPUs/CP1610/Disassembler.cs b/BizHawk.Emulation/CPUs/CP1610/Disassembler.cs index b9a7dc8eff..89ce2d6dfe 100644 --- a/BizHawk.Emulation/CPUs/CP1610/Disassembler.cs +++ b/BizHawk.Emulation/CPUs/CP1610/Disassembler.cs @@ -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; diff --git a/BizHawk.Emulation/CPUs/CP1610/Execute.cs b/BizHawk.Emulation/CPUs/CP1610/Execute.cs index 4a80736bb2..2cdb2da491 100644 --- a/BizHawk.Emulation/CPUs/CP1610/Execute.cs +++ b/BizHawk.Emulation/CPUs/CP1610/Execute.cs @@ -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; diff --git a/BizHawk.Emulation/Consoles/Intellivision/Cartridge.cs b/BizHawk.Emulation/Consoles/Intellivision/Cartridge.cs index c1635ef85e..61831fc4ff 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/Cartridge.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/Cartridge.cs @@ -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; diff --git a/BizHawk.Emulation/Consoles/Intellivision/Intellicart.cs b/BizHawk.Emulation/Consoles/Intellivision/Intellicart.cs index 778d6e6df4..326e0d38da 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/Intellicart.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/Intellicart.cs @@ -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; } diff --git a/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs b/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs index e375302f6c..86ed2868c0 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs @@ -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(); diff --git a/BizHawk.Emulation/Consoles/Intellivision/MemoryMap.cs b/BizHawk.Emulation/Consoles/Intellivision/MemoryMap.cs index 5ed88c41b0..43f75d7db9 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/MemoryMap.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/MemoryMap.cs @@ -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. diff --git a/BizHawk.Emulation/Consoles/Intellivision/PSG.cs b/BizHawk.Emulation/Consoles/Intellivision/PSG.cs index 44116494b7..22c4029a27 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/PSG.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/PSG.cs @@ -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; } diff --git a/BizHawk.Emulation/Consoles/Intellivision/STIC.cs b/BizHawk.Emulation/Consoles/Intellivision/STIC.cs index 747fae5272..4be5a5b899 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/STIC.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/STIC.cs @@ -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; } }