#include <stdio.h> #include <ctype.h> #include "system.h" #include "atom.h" #include "cpu.h" #include "monitor.h" #include "file.h" int stricmp(const char *b, const char *a) { while (*a != '\0' && *b != '\0' && tolower(*a) == tolower(*b)) { a++; b++; } return *a == *b ? 0 : tolower(*a) < tolower(*b) ? -1 : 1; } char *get_token (char *string) { static char *s; char *t; if (string) s = string; /* New String */ while (*s == ' ') s++; /* Skip Leading Spaces */ if (*s) { t = s; /* Start of String */ while (*s != ' ' && *s) /* Locate End of String */ { s++; } if (*s == ' ') /* Space Terminated ? */ { *s = '\0'; /* C String Terminator */ s++; /* Point to Next Char */ } } else { t = NULL; } return t; /* Pointer to String */ } int get_hex (char *string, UWORD *hexval) { int ihexval; char *t; t = get_token(string); if (t) { sscanf (t,"%x",&ihexval); *hexval = ihexval; return 1; } return 0; } int monitor () { CPU_Status cpu_status; UWORD addr; UWORD break_addr; char s[128]; addr = 0; CPU_GetStatus (&cpu_status); while (TRUE) { char *t; printf ("> "); gets (s); t = get_token(s); if (stricmp(t,"BREAK") == 0) { get_hex (NULL, &break_addr); } else if (stricmp(t,"CONT") == 0) { return 1; } else if (stricmp(t,"SETPC") == 0) { get_hex (NULL, &addr); cpu_status.PC = addr; } else if (stricmp(t,"SETS") == 0) { get_hex (NULL, &addr); cpu_status.S = addr & 0xff; } else if (stricmp(t,"SETA") == 0) { get_hex (NULL, &addr); cpu_status.A = addr & 0xff; } else if (stricmp(t,"SETX") == 0) { get_hex (NULL, &addr); cpu_status.X = addr & 0xff; } else if (stricmp(t,"SETY") == 0) { get_hex (NULL, &addr); cpu_status.Y = addr & 0xff; } else if (stricmp(t,"SETN") == 0) { get_hex (NULL, &addr); cpu_status.flag.N = addr; } else if (stricmp(t,"SETV") == 0) { get_hex (NULL, &addr); cpu_status.flag.V = addr; } else if (stricmp(t,"SETB") == 0) { get_hex (NULL, &addr); cpu_status.flag.B = addr; } else if (stricmp(t,"SETD") == 0) { get_hex (NULL, &addr); cpu_status.flag.D = addr; } else if (stricmp(t,"SETI") == 0) { get_hex (NULL, &addr); cpu_status.flag.I = addr; } else if (stricmp(t,"SETZ") == 0) { get_hex (NULL, &addr); cpu_status.flag.Z = addr; } else if (stricmp(t,"SETC") == 0) { get_hex (NULL, &addr); cpu_status.flag.C = addr; } else if (stricmp(t,"SHOW") == 0) { printf ("PC=%4x, A=%2x, S=%2x, X=%2x, Y=%2x, C=%1x, Z=%1x, I=%1x, D=%1x, B=%1x, V=%1x, N=%1x\n", cpu_status.PC, cpu_status.A, cpu_status.S, cpu_status.X, cpu_status.Y, cpu_status.flag.C, cpu_status.flag.Z, cpu_status.flag.I, cpu_status.flag.D, cpu_status.flag.B, cpu_status.flag.V, cpu_status.flag.N); } else if (stricmp(t,"ROM") == 0) { UWORD addr1; UWORD addr2; int status; status = get_hex (NULL, &addr1); status |= get_hex (NULL, &addr2); if (status) { SetMemory (addr1, addr2, ROM); printf ("Changed Memory from %4x to %4x into ROM\n", addr1, addr2); } else { printf ("*** Memory Unchanged (Missing Parameter) ***\n"); } } else if (stricmp(t,"RAM") == 0) { UWORD addr1; UWORD addr2; int status; status = get_hex (NULL, &addr1); status |= get_hex (NULL, &addr2); if (status) { SetMemory (addr1, addr2, RAM); printf ("Changed Memory from %4x to %4x into RAM\n", addr1, addr2); } else { printf ("*** Memory Unchanged (Missing Parameter) ***\n"); } } else if (stricmp(t,"D") == 0) { int addr1; int addr2; UWORD xaddr1; UWORD xaddr2; UWORD temp; int i; addr1 = addr; addr2 = 0; get_hex (NULL, &xaddr1); get_hex (NULL, &xaddr2); addr1 = xaddr1; addr2 = xaddr2; if (addr2 == 0) addr2 = addr1 + 255; addr = addr2 + 1; while (addr1 <= addr2) { temp = addr1; printf ("%4x : ",temp); for (i=0;i<16;i++) { printf ("%2x ",GetByte(temp)); temp++; if (temp > addr2) break; } temp = addr1; printf ("\t"); for (i=0;i<16;i++) { if (GetByte(temp) >= ' ' && GetByte(temp) <= 'z') { printf ("%c",GetByte(temp)); } else { printf ("."); } temp++; if (temp > addr2) break; } printf ("\n"); addr1 += 16; } } else if (stricmp(t,"M") == 0) { UWORD addr; UWORD temp; get_hex (NULL, &addr); while (get_hex(NULL, &temp)) { PutByte (addr++,(UBYTE)temp); } } else if (stricmp(t,"Y") == 0) { UWORD addr1; UWORD addr2; addr1 = addr; addr2 = 0; get_hex (NULL, &addr1); get_hex (NULL, &addr2); addr = disassemble (addr1,addr2); } else if (stricmp(t,"HELP") == 0 || stricmp(t,"?") == 0) { printf ("SET{PC,A,S,X,Y} hexval - Set Register Value\n"); printf ("SET{N,V,B,D,I,Z,C} hexval - Set Flag Value\n"); printf ("D [startaddr] [endaddr] - Display Memory\n"); printf ("M [startaddr] [hexval...] - Modify Memory\n"); printf ("Y [startaddr] [endaddr] - Disassemble Memory\n"); printf ("ROM addr1 addr2 - Convert Memory Block into ROM\n"); printf ("RAM addr1 addr2 - Convert Memory Block into RAM\n"); printf ("CONT - Continue\n"); printf ("SHOW - Show Registers\n"); printf ("QUIT - Quit Emulation\n"); printf ("HELP or ? - This Text\n"); } else if (stricmp(t,"QUIT") == 0) { return 0; } else if (stricmp(t, "SAVE") == 0) { char *name = get_token(NULL); if (name != NULL) save_to_file(name); } else if (stricmp(t, "LOAD") == 0) { char *name = get_token(NULL); if (name != NULL) load_from_file(name); } else { CPU_PutStatus (&cpu_status); GO(1); CPU_GetStatus (&cpu_status); printf ("PC=%4x, A=%2x, S=%2x, X=%2x, Y=%2x, C=%1x, Z=%1x, I=%1x, D=%1x, B=%1x, V=%1x, N=%1x\n", cpu_status.PC, cpu_status.A, cpu_status.S, cpu_status.X, cpu_status.Y, cpu_status.flag.C, cpu_status.flag.Z, cpu_status.flag.I, cpu_status.flag.D, cpu_status.flag.B, cpu_status.flag.V, cpu_status.flag.N); /* printf ("Invalid command.\n"); */ disassemble( cpu_status.PC, cpu_status.PC + 1); } }; } static UWORD addr; unsigned int disassemble (UWORD addr1, UWORD addr2) { UBYTE instr; int count; addr = addr1; count = (addr2 == 0) ? 20 : 0; while (addr < addr2 || count > 0) { printf ("%x\t",addr); instr = GetByte(addr++); show_opcode (instr); show_operand (instr); printf ("\n"); if (count > 0) count--; } return addr; } void show_opcode (UBYTE instr) { switch (instr) { case 0x6d : case 0x65 : case 0x69 : case 0x7d : case 0x79 : case 0x61 : case 0x71 : case 0x75 : printf ("ADC"); break; case 0x2d : case 0x25 : case 0x29 : case 0x3d : case 0x39 : case 0x21 : case 0x31 : case 0x35 : printf ("AND"); break; case 0x0e : case 0x06 : case 0x1e : case 0x16 : printf ("ASL"); break; case 0x2c : case 0x24 : printf ("BIT"); break; case 0xcd : case 0xc5 : case 0xc9 : case 0xdd : case 0xd9 : case 0xc1 : case 0xd1 : case 0xd5 : printf ("CMP"); break; case 0xec : case 0xe4 : case 0xe0 : printf ("CPX"); break; case 0xcc : case 0xc4 : case 0xc0 : printf ("CPY"); break; case 0xce : case 0xc6 : case 0xde : case 0xd6 : printf ("DEC"); break; case 0x4d : case 0x45 : case 0x49 : case 0x5d : case 0x59 : case 0x41 : case 0x51 : case 0x55 : printf ("EOR"); break; case 0xee : case 0xe6 : case 0xfe : case 0xf6 : printf ("INC"); break; case 0x4c : case 0x6c : case 0x20 : printf ("JMP"); break; case 0xad : case 0xa5 : case 0xa9 : case 0xbd : case 0xb9 : case 0xa1 : case 0xb1 : case 0xb5 : printf ("LDA"); break; case 0xae : case 0xa6 : case 0xa2 : case 0xbe : case 0xb6 : printf ("LDX"); break; case 0xac : case 0xa4 : case 0xa0 : case 0xbc : case 0xb4 : printf ("LDY"); break; case 0x4e : case 0x46 : case 0x5e : case 0x56 : printf ("LSR"); break; case 0x4a : printf ("LSR\tA"); break; case 0x0d : case 0x05 : case 0x09 : case 0x1d : case 0x19 : case 0x01 : case 0x11 : case 0x15 : printf ("ORA"); break; case 0x2e : case 0x26 : case 0x3e : case 0x36 : printf ("ROL"); break; case 0x2a : printf ("ROL\tA"); break; case 0x6e : case 0x66 : case 0x7e : case 0x76 : printf ("ROR"); break; case 0x6a : printf ("ROR\tA"); break; case 0xed : case 0xe5 : case 0xe9 : case 0xfd : case 0xf9 : case 0xe1 : case 0xf1 : case 0xf5 : printf ("SBC"); break; case 0x8d : case 0x85 : case 0x9d : case 0x99 : case 0x81 : case 0x91 : case 0x95 : printf ("STA"); break; case 0x8e : case 0x86 : case 0x96 : printf ("STX"); break; case 0x8c : case 0x84 : case 0x94 : printf ("STY"); break; case 0x90 : printf ("BCC"); break; case 0xb0 : printf ("BCS"); break; case 0xf0 : printf ("BEQ"); break; case 0x30 : printf ("BMI"); break; case 0xd0 : printf ("BNE"); break; case 0x10 : printf ("BPL"); break; case 0x50 : printf ("BVC"); break; case 0x70 : printf ("BVS"); break; case 0xff : printf ("ESC"); break; case 0x0a : printf ("ASL\tA"); break; case 0x00 : printf ("BRK"); break; case 0x18 : printf ("CLC"); break; case 0xd8 : printf ("CLD"); break; case 0x58 : printf ("CLI"); break; case 0xb8 : printf ("CLV"); break; case 0xca : printf ("DEX"); break; case 0x88 : printf ("DEY"); break; case 0xe8 : printf ("INX"); break; case 0xc8 : printf ("INY"); break; case 0xea : printf ("NOP"); break; case 0x48 : printf ("PHA"); break; case 0x08 : printf ("PHP"); break; case 0x68 : printf ("PLA"); break; case 0x28 : printf ("PLP"); break; case 0x40 : printf ("RTI"); break; case 0x60 : printf ("RTS"); break; case 0x38 : printf ("SEC"); break; case 0xf8 : printf ("SED"); break; case 0x78 : printf ("SEI"); break; case 0xaa : printf ("TAX"); break; case 0xa8 : printf ("TAY"); break; case 0xba : printf ("TSX"); break; case 0x8a : printf ("TXA"); break; case 0x9a : printf ("TXS"); break; case 0x98 : printf ("TYA"); break; default : printf ("*** ILLEGAL INSTRUCTION (%x) ***",instr); break; } } void show_operand (UBYTE instr) { UBYTE byte; UWORD word; switch (instr) { /* ========================= Absolute Addressing Modes ========================= */ case 0x6d : /* ADC */ case 0x2d : /* AND */ case 0x0e : /* ASL */ case 0x2c : /* BIT */ case 0xcd : /* CMP */ case 0xec : /* CPX */ case 0xcc : /* CPY */ case 0xce : /* DEC */ case 0x4d : /* EOR */ case 0xee : /* INC */ case 0x4c : /* JMP */ case 0x20 : /* JSR */ case 0xad : /* LDA */ case 0xae : /* LDX */ case 0xac : /* LDY */ case 0x4e : /* LSR */ case 0x0d : /* ORA */ case 0x2e : /* ROL */ case 0x6e : /* ROR */ case 0xed : /* SBC */ case 0x8d : /* STA */ case 0x8e : /* STX */ case 0x8c : /* STY */ word = (GetByte(addr+1) << 8) | GetByte(addr); printf ("\t$%x",word); addr += 2; break; /* ====================== 0-Page Addressing Mode ====================== */ case 0x65 : /* ADC */ case 0x25 : /* AND */ case 0x06 : /* ASL */ case 0x24 : /* BIT */ case 0xc5 : /* CMP */ case 0xe4 : /* CPX */ case 0xc4 : /* CPY */ case 0xc6 : /* DEC */ case 0x45 : /* EOR */ case 0xe6 : /* INC */ case 0xa5 : /* LDA */ case 0xa6 : /* LDX */ case 0xa4 : /* LDY */ case 0x46 : /* LSR */ case 0x05 : /* ORA */ case 0x26 : /* ROL */ case 0x66 : /* ROR */ case 0xe5 : /* SBC */ case 0x85 : /* STA */ case 0x86 : /* STX */ case 0x84 : /* STY */ byte = GetByte(addr++); printf ("\t$%x",byte); break; /* ======================== Relative Addressing Mode ======================== */ case 0x90 : /* BCC */ case 0xb0 : /* BCS */ case 0xf0 : /* BEQ */ case 0x30 : /* BMI */ case 0xd0 : /* BNE */ case 0x10 : /* BPL */ case 0x50 : /* BVC */ case 0x70 : /* BVS */ byte = GetByte(addr++); printf ("\t$%x",addr+(SBYTE)byte); break; /* ========================= Immediate Addressing Mode ========================= */ case 0x69 : /* ADC */ case 0x29 : /* AND */ case 0xc9 : /* CMP */ case 0xe0 : /* CPX */ case 0xc0 : /* CPY */ case 0x49 : /* EOR */ case 0xa9 : /* LDA */ case 0xa2 : /* LDX */ case 0xa0 : /* LDY */ case 0x09 : /* ORA */ case 0xe9 : /* SBC */ case 0xff : /* ESC */ byte = GetByte(addr++); printf ("\t#$%x",byte); break; /* ===================== ABS,X Addressing Mode ===================== */ case 0x7d : /* ADC */ case 0x3d : /* AND */ case 0x1e : /* ASL */ case 0xdd : /* CMP */ case 0xde : /* DEC */ case 0x5d : /* EOR */ case 0xfe : /* INC */ case 0xbd : /* LDA */ case 0xbc : /* LDY */ case 0x5e : /* LSR */ case 0x1d : /* ORA */ case 0x3e : /* ROL */ case 0x7e : /* ROR */ case 0xfd : /* SBC */ case 0x9d : /* STA */ word = (GetByte(addr+1) << 8) | GetByte(addr); printf ("\t%x,X",word); addr += 2; break; /* ===================== ABS,Y Addressing Mode ===================== */ case 0x79 : /* ADC */ case 0x39 : /* AND */ case 0xd9 : /* CMP */ case 0x59 : /* EOR */ case 0xb9 : /* LDA */ case 0xbe : /* LDX */ case 0x19 : /* ORA */ case 0xf9 : /* SBC */ case 0x99 : /* STA */ word = (GetByte(addr+1) << 8) | GetByte(addr); printf ("\t%x,Y",word); addr += 2; break; /* ======================= (IND,X) Addressing Mode ======================= */ case 0x61 : /* ADC */ case 0x21 : /* AND */ case 0xc1 : /* CMP */ case 0x41 : /* EOR */ case 0xa1 : /* LDA */ case 0x01 : /* ORA */ case 0xe1 : /* SBC */ case 0x81 : /* STA */ byte = GetByte(addr++); printf ("\t($%x,X)",byte); break; /* ======================= (IND),Y Addressing Mode ======================= */ case 0x71 : /* ADC */ case 0x31 : /* AND */ case 0xd1 : /* CMP */ case 0x51 : /* EOR */ case 0xb1 : /* LDA */ case 0x11 : /* ORA */ case 0xf1 : /* SBC */ case 0x91 : /* STA */ byte = GetByte(addr++); printf ("\t($%x),Y",byte); break; /* ======================== 0-Page,X Addressing Mode ======================== */ case 0x75 : /* ADC */ case 0x35 : /* AND */ case 0x16 : /* ASL */ case 0xd5 : /* CMP */ case 0xd6 : /* DEC */ case 0x55 : /* EOR */ case 0xf6 : /* INC */ case 0xb5 : /* LDA */ case 0xb4 : /* LDY */ case 0x56 : /* LSR */ case 0x15 : /* ORA */ case 0x36 : /* ROL */ case 0x76 : /* ROR */ case 0xf5 : /* SBC */ case 0x95 : /* STA */ case 0x94 : /* STY */ byte = GetByte(addr++); printf ("\t$%x,X",byte); break; /* ======================== 0-Page,Y Addressing Mode ======================== */ case 0xb6 : /* LDX */ case 0x96 : /* STX */ byte = GetByte(addr++); printf ("\t$%x,Y",byte); break; /* ======================== Indirect Addressing Mode ======================== */ case 0x6c : /* printf ("JMP INDIRECT at %x\n",instr_addr); */ word = (GetByte(addr+1) << 8) | GetByte(addr); printf ("\t($%x)",word); addr += 2; break; } }