#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;
}
}
|