private string TraceLog(int address) { StringBuilder line = new StringBuilder(); int op = Peek(address); int opInfo = OpInfo.GetOps()[op]; int size = (opInfo >> 16) & 0xF; int addressing = (opInfo >> 8) & 0xFF; line.AppendFormat("{0} ", address.ToString("X4")); if (size == 0) { line.Append(" "); } else if (size == 1) { line.AppendFormat("{0} ", Peek(address).ToString("X2")); } else if (size == 2) { line.AppendFormat("{0} {1} ", Peek(address).ToString("X2"), Peek(address + 1).ToString("X2")); } else if (size == 3) { line.AppendFormat("{0} {1} {2} ", Peek(address).ToString("X2"), Peek(address + 1).ToString("X2"), Peek(address + 2).ToString("X2")); } line.Append(OpInfo.GetOpNames()[opInfo & 0xFF].PadLeft(4).PadRight(5)); //Should be 20 long at this point, addressing should be 28 long int val1; int val2; int val3; int val4; switch (addressing) { case OpInfo.AddrNone: line.Append(" "); break; case OpInfo.AddrAccumulator: line.Append("A "); break; case OpInfo.AddrImmediate: line.AppendFormat("#${0} ", Peek(address + 1).ToString("X2")); break; case OpInfo.AddrZeroPage: line.AppendFormat("${0} = {1} ", Peek(address + 1).ToString("X2"), Peek(Peek(address + 1)).ToString("X2")); break; case OpInfo.AddrZeroPageX: line.AppendFormat("${0},X @ {1} = {2} ", Peek(address + 1).ToString("X2"), ((Peek(address + 1) + nes.RegX) & 0xFF).ToString("X2"), Peek((Peek(address + 1) + nes.RegX) & 0xFF).ToString("X2")); break; case OpInfo.AddrZeroPageY: line.AppendFormat("${0},Y @ {1} = {2} ", Peek(address + 1).ToString("X2"), ((Peek(address + 1) + nes.RegY) & 0xFF).ToString("X2"), Peek((Peek(address + 1) + nes.RegY) & 0xFF).ToString("X2")); break; case OpInfo.AddrAbsolute: if (op == 0x4C || op == 0x20) { line.AppendFormat("${0} ", PeekWord(address + 1).ToString("X4")); } else { line.AppendFormat("${0} = {1} ", PeekWord(address + 1).ToString("X4"), Peek(PeekWord(address + 1)).ToString("X2")); } break; case OpInfo.AddrAbsoluteX: line.AppendFormat("${0},X @ {1} = {2} ", PeekWord(address + 1).ToString("X4"), ((PeekWord(address + 1) + nes.RegX) & 0xFFFF).ToString("X4"), Peek((PeekWord(address + 1) + nes.RegX) & 0xFFFF).ToString("X2")); break; case OpInfo.AddrAbsoluteY: line.AppendFormat("${0},Y @ {1} = {2} ", PeekWord(address + 1).ToString("X4"), ((PeekWord(address + 1) + nes.RegY) & 0xFFFF).ToString("X4"), Peek((PeekWord(address + 1) + nes.RegY) & 0xFFFF).ToString("X2")); break; case OpInfo.AddrIndirectAbs: line.AppendFormat("(${0}) = {1} ", PeekWord(address + 1).ToString("X4"), PeekWordWrap(PeekWord(address + 1)).ToString("X4")); break; case OpInfo.AddrRelative: int addr = Peek(address + 1); if (addr < 0x80) { addr += (address + size); } else { addr += (address + size) - 256; } line.AppendFormat("${0} ", addr.ToString("X4")); break; case OpInfo.AddrIndirectX: addr = val1 = Peek(address + 1); addr += nes.RegX; addr &= 0xFF; val2 = addr; addr = val3 = Peek(addr) + (Peek((addr + 1) & 0xFF) << 8); addr = val4 = Peek(addr); line.AppendFormat("(${0},X) @ {1} = {2} = {3} ", val1.ToString("X2"), val2.ToString("X2"), val3.ToString("X4"), val4.ToString("X2")); break; case OpInfo.AddrIndirectY: addr = val1 = Peek(address + 1); addr = val2 = Peek(addr) + (Peek((addr + 1) & 0xFF) << 8); addr += nes.RegY; addr &= 0xFFFF; val3 = addr; addr = val4 = Peek(addr & 0xFFFF); line.AppendFormat("(${0}),Y = {1} @ {2} = {3} ", val1.ToString("X2"), val2.ToString("X4"), val3.ToString("X4"), val4.ToString("X2")); break; } line.AppendFormat("A:{0} X:{1} Y:{2} P:", nes.RegA.ToString("X2"), nes.RegX.ToString("X2"), nes.RegY.ToString("X2")); if (nes.FlagCarry != 0) { line.Append("C"); } else { line.Append("c"); } if (nes.FlagZero == 0) { line.Append("Z"); } else { line.Append("z"); } if (nes.FlagIRQ != 0) { line.Append("I"); } else { line.Append("i"); } if (nes.FlagDecimal != 0) { line.Append("D"); } else { line.Append("d"); } if (0 != 0) { line.Append("B"); } else { line.Append("b"); } if (0 != 0) { line.Append("-"); } else { line.Append("_"); } if (nes.FlagOverflow != 0) { line.Append("V"); } else { line.Append("v"); } if ((nes.FlagSign >> 7) != 0) { line.Append("N"); } else { line.Append("n"); } line.AppendFormat(" S:{0} CYC:{1} SL:{2}", nes.RegS.ToString("X2"), (nes.PPU.scanlineCycle).ToString().PadLeft(3), nes.PPU.scanline.ToString().PadLeft(3)); return(line.ToString()); }
public string LogOp(int address) { StringBuilder line = new StringBuilder(); int op = Peek(address); int opInfo = OpInfo.GetOps()[op]; int size = (opInfo >> 16) & 0xF; int addressing = (opInfo >> 8) & 0xFF; line.AppendFormat("{0} ", address.ToString("X4")); if (size == 0) { line.Append(" "); } else if (size == 1) { line.AppendFormat("{0} ", Peek(address).ToString("X2")); } else if (size == 2) { line.AppendFormat("{0} {1} ", Peek(address).ToString("X2"), Peek(address + 1).ToString("X2")); } else if (size == 3) { line.AppendFormat("{0} {1} {2} ", Peek(address).ToString("X2"), Peek(address + 1).ToString("X2"), Peek(address + 2).ToString("X2")); } line.Append(OpInfo.GetOpNames()[opInfo & 0xFF].PadLeft(4).PadRight(5)); //Should be 20 long at this point, addressing should be 28 long int val1; int val2; int val3; int val4; switch (addressing) { case OpInfo.AddrNone: line.Append(" "); break; case OpInfo.AddrAccumulator: line.Append("A "); break; case OpInfo.AddrImmediate: line.AppendFormat("#${0} ", Peek(address + 1).ToString("X2")); break; case OpInfo.AddrZeroPage: line.AppendFormat("${0} = {1} ", Peek(address + 1).ToString("X2"), Peek(Peek(address + 1)).ToString("X2")); break; case OpInfo.AddrZeroPageX: line.AppendFormat("${0},X @ {1} = {2} ", Peek(address + 1).ToString("X2"), ((Peek(address + 1) + nes.RegX) & 0xFF).ToString("X2"), Peek((Peek(address + 1) + nes.RegX) & 0xFF).ToString("X2")); break; case OpInfo.AddrZeroPageY: line.AppendFormat("${0},Y @ {1} = {2} ", Peek(address + 1).ToString("X2"), ((Peek(address + 1) + nes.RegY) & 0xFF).ToString("X2"), Peek((Peek(address + 1) + nes.RegY) & 0xFF).ToString("X2")); break; case OpInfo.AddrAbsolute: if (op == 0x4C || op == 0x20) { line.AppendFormat("${0} ", PeekWord(address + 1).ToString("X4")); } else { line.AppendFormat("${0} = {1} ", PeekWord(address + 1).ToString("X4"), Peek(PeekWord(address + 1)).ToString("X2")); } break; case OpInfo.AddrAbsoluteX: line.AppendFormat("${0},X @ {1} = {2} ", PeekWord(address + 1).ToString("X4"), ((PeekWord(address + 1) + nes.RegX) & 0xFFFF).ToString("X4"), Peek((PeekWord(address + 1) + nes.RegX) & 0xFFFF).ToString("X2")); break; case OpInfo.AddrAbsoluteY: line.AppendFormat("${0},Y @ {1} = {2} ", PeekWord(address + 1).ToString("X4"), ((PeekWord(address + 1) + nes.RegY) & 0xFFFF).ToString("X4"), Peek((PeekWord(address + 1) + nes.RegY) & 0xFFFF).ToString("X2")); break; case OpInfo.AddrIndirectAbs: line.AppendFormat("(${0}) = {1} ", PeekWord(address + 1).ToString("X4"), PeekWordWrap(PeekWord(address + 1)).ToString("X4")); break; case OpInfo.AddrRelative: int addr = Peek(address + 1); if (addr < 0x80) { addr += (address + size); } else { addr += (address + size) - 256; } line.AppendFormat("${0} ", addr.ToString("X4")); break; case OpInfo.AddrIndirectX: addr = val1 = Peek(address + 1); addr += nes.RegX; addr &= 0xFF; val2 = addr; addr = val3 = Peek(addr) + (Peek((addr + 1) & 0xFF) << 8); addr = val4 = Peek(addr); line.AppendFormat("(${0},X) @ {1} = {2} = {3} ", val1.ToString("X2"), val2.ToString("X2"), val3.ToString("X4"), val4.ToString("X2")); break; case OpInfo.AddrIndirectY: addr = val1 = Peek(address + 1); addr = val2 = Peek(addr) + (Peek((addr + 1) & 0xFF) << 8); addr += nes.RegY; addr &= 0xFFFF; val3 = addr; addr = val4 = Peek(addr & 0xFFFF); line.AppendFormat("(${0}),Y = {1} @ {2} = {3} ", val1.ToString("X2"), val2.ToString("X4"), val3.ToString("X4"), val4.ToString("X2")); break; } return(line.ToString().Trim()); }