home *** CD-ROM | disk | FTP | other *** search
- /*
- * a2, an Apple II emulator in C
- * (c) Copyright 1990 by Rich Skrenta
- *
- * Command line interface written by Tom Markson
- *
- * Distribution agreement:
- *
- * You may freely copy or redistribute this software, so long
- * as there is no profit made from its use, sale, trade or
- * reproduction. You may not change this copyright notice,
- * and it must be included prominently in any copy made.
- *
- * Send emulator related mail to: skrenta@blekko.commodore.com
- * skrenta@blekko.uucp
- */
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
- #include "a2.h"
- #include "cli.h"
-
-
- extern unsigned short lpoint;
- extern long phantom_location;
- extern char *getcwd();
- extern int map_to_upper;
- extern char escape_char;
- long get_hex_number();
-
- char diskname[2][200]; /* disk names stored here */
-
- struct point_stack {
- unsigned short data[MAXSTACK];
- int sp;
- } pstack;
-
- init_point(){
- pstack.sp = -1;
- }
-
- pop_point(rest)
- char *rest;
- {
- if (pstack.sp < 0 ) {
- printf("stack empty\n");
- return OK;
- }
- switch (*rest){
- case 'l':
- case 'L':
- printf("%x\n", lpoint = pstack.data[pstack.sp--]);
- break;
- case 'p':
- case 'P':
- printf("%x\n", lpoint = pstack.data[pstack.sp--]);
- break;
- default :
- printf("pop [lp]\n");
- break;
- }
- return(OK);
- }
-
- dup_point(rest)
- char *rest;
- {
- if (pstack.sp < 0 ) {
- printf("stack empty\n");
- return OK;
- }
- switch (*rest){
- case 'l':
- case 'L':
- lpoint = pstack.data[pstack.sp];
- break;
- case 'p':
- case 'P':
- lpoint = pstack.data[pstack.sp];
- break;
- default :
- printf("dup [lp]\n");
- break;
- }
- return(OK);
- }
-
- push_point(rest)
- char *rest;
- {
- long value;
- char *addr;
-
- assert (pstack.sp < MAXSTACK);
- switch (*rest){
- case 'l':
- case 'L':
- pstack.data[++pstack.sp] = lpoint;
- break;
- case 'p':
- case 'P':
- pstack.data[++pstack.sp] = Pc;
- break;
- default:
- addr = rest;
- rest = split(rest);
- value = get_hex_number(addr);
- if (value == -1L)
- printf("push [l|p|<addr>]\n");
- else
- pstack.data[++pstack.sp]=(unsigned short)value;
- break;
- }
- return(OK);
- }
-
-
- clb(junk)
- char *junk;
- {
-
- B = 0;
- return(DISPLAY);
- }
-
-
- seb(junk)
- char *junk;
- {
-
- B = 1;
- return(DISPLAY);
- }
-
-
- clc(junk)
- char *junk;
- {
- C = 0;
- return(DISPLAY);
- }
-
-
- sec(junk)
- char *junk;
- {
- C = 1;
- return(DISPLAY);
- }
-
-
- sev(junk)
- char *junk;
- {
- V = 1;
- return(DISPLAY);
- }
-
-
- clv(junk)
- char *junk;
- {
- V = 0;
- return(DISPLAY);
- }
-
-
- sed(junk)
- char *junk;
- {
- D = 1;
- return(DISPLAY);
- }
-
-
- cld(junk)
- char *junk;
- {
- D = 0;
- return(DISPLAY);
- }
-
-
- sei(junk)
- char *junk;
- {
- I = 1;
- return(DISPLAY);
- }
-
-
- clri(junk)
- char *junk;
- {
- I = 0;
- return(DISPLAY);
- }
-
-
- sen(junk)
- char *junk;
- {
- N = 1;
- return(DISPLAY);
- }
-
-
- cln(junk)
- char *junk;
- {
- N = 0;
- return(DISPLAY);
- }
-
-
- sez(junk)
- char *junk;
- {
- NZ = 0;
- return(DISPLAY);
- }
-
-
- clz(junk)
- char *junk;
- {
- NZ = 1;
- return(DISPLAY);
- }
-
-
- quit_emulator(junk)
- char *junk;
- {
- exit(0);
- }
-
-
-
- ver(junk)
- char *junk;
- {
- printf("a2 - Apple II emulator (c) Copyright 1990 by Rich Skrenta & Tom Markson\n");
- return(OK);
- }
-
-
- refresh(junk)
- char *junk;
- {
-
- in_cli = FALSE;
- return(OK);
- }
-
-
- shell_escape(rest)
- char *rest;
- {
- char line[100];
- char *s;
-
- s = getenv("SHELL");
- if (s == NULL)
- s = "/bin/sh";
-
- strcpy(line, s);
-
- if (*rest != '\0') {
- strcat(line, " -c '");
- strcat(line, rest);
- strcat(line, "'");
- }
- system(line);
-
- printf("\n");
- return(OK);
- }
-
-
- do_soft_reset(rest)
- char *rest;
- {
-
- Pc = mem[0xFFFC] | (mem[0xFFFD] << 8);
- return(DISPLAY);
- }
-
-
- do_bload(rest)
- char *rest;
- {
- char *first;
- char *file;
- unsigned short start;
- long foo;
-
- file = rest;
- rest = split(rest);
- first = rest;
- rest = split(rest);
- foo = get_hex_number(first);
- if (foo == -1) {
- printf("usage: bload file hex-address\n");
- return(OK);
- }
- start = (unsigned int) foo;
- bload(file, start);
-
- return(OK);
- }
-
-
- do_bsave(rest)
- char *rest;
- {
- char *startc, *sizec, *file;
- unsigned short start, size;
- long istart, iend;
- file = rest;
- rest = split(rest);
- startc = rest;
- rest = split(rest);
- sizec = rest;
- rest = split(rest);
- istart = get_hex_number(startc);
- iend = get_hex_number(sizec);
- if ((istart == -1) || (iend == -1))
- printf("usage: bsave file hex-address hex-length\n");
- else {
- start = (unsigned short) istart;
- size = (unsigned short) iend;
- bsave(file, start, size);
- }
-
- return(OK);
- }
-
-
-
- show_point(rest)
- char *rest;
- {
-
- lpoint = Pc;
- return(DISPLAY);
- }
-
-
- hack(rest)
- char *rest;
- {
- extern int cur_track;
-
- cur_track = get_hex_number(rest);
- return(OK);
- }
-
-
- do_jump(rest)
- char *rest;
- {
- char *start;
- long istart;
- start = rest;
- rest = split(rest);
- istart = get_hex_number(start);
-
- if (istart == -1) {
- printf("usage: jmp <hex address>\n");
- return(OK);
- } else {
- Pc = istart & 0xFFFF;
- return(DISPLAY);
- }
- }
-
-
-
- trace(rest)
- char *rest;
- {
- char *addr1, *addr2, *file;
- long addr1i, addr2i;
-
- addr1 = rest;
- rest = split(rest);
- addr2 = rest;
- rest = split(rest);
- file = rest;
- rest = split(rest);
- addr1i = get_hex_number(addr1);
- addr2i = get_hex_number(addr2);
- if (addr1i == -1 && addr2i == -1) {
- if (trace_lo == -1)
- printf("No trace region set\n");
- else
- printf("Tracing between $%.4X and $%.4x\n",
- trace_lo, trace_hi);
- return(OK);
- }
-
- if (addr1i == -1 || addr2i == -1) {
- printf("usage: trace [low high]\n");
- return(OK);
- }
-
- if (logging_fp == NULL) {
- if (*file == '\0' || file == NULL) {
- printf("Trace log will go to file 'trace'.\n");
- file = "trace";
- }
- logging_fp = fopen(file, "w");
- if (logging_fp == NULL) {
- perror("can't open trace file");
- trace_lo = -1;
- return(OK);
- }
- }
-
- trace_lo = addr1i & 0xFFFF;
- trace_hi = addr2i & 0xFFFF;
-
- return(OK);
- }
-
-
- ldx(rest)
- char *rest;
- {
- long number;
- char *first;
-
- first = rest;
- rest = split(rest);
- number = get_hex_number(first);
-
- number &= 0xFF;
- if (number < 0) {
- printf("usage: ldx <hex number>\n");
- return(OK);
- }
-
- X = number & 0xFF;
- return(DISPLAY);
- }
-
-
- ldy(rest)
- char *rest;
- {
- long number;
- char *first;
- first = rest;
- rest = split(rest);
- number = get_hex_number(first);
-
- if (number < 0) {
- printf("usage: ldy <hex number>\n");
- return(OK);
- }
-
- Y = number & 0xFF;
- return(DISPLAY);
- }
-
-
- lda(rest)
- char *rest;
- {
- long number;
- char *first;
- first = rest;
- rest = split(rest);
- number = get_hex_number(first);
- if (number < 0) {
- printf("usage: lda <hex number>\n");
- return(OK);
- }
-
- A = number & 0xFF;
- return(DISPLAY);
- }
-
-
- lds(rest)
- char *rest;
- {
- long number;
- char *first;
- first = rest;
- rest = split(rest);
- number = get_hex_number(first);
- if (number < 0) {
- printf("usage: lds <hex number>\n");
- return(OK);
- }
-
- Sp = number & 0xFF;
- return(DISPLAY);
- }
-
-
- set_break_point(rest)
- char *rest;
- {
- long addr;
- char *first;
- first = rest;
- rest = split(rest);
- addr = get_hex_number(first);
- if (addr == -1)
- if (breakpoint == -1)
- printf("no breakpoint set\n");
- else
- printf("break point set at %x\n",
- (unsigned short)breakpoint);
- else
- breakpoint = addr;
- running = FALSE;
- return(OK);
- }
-
-
- clear_break_point(rest)
- char *rest;
- {
- breakpoint = -1;
- return(OK);
- }
-
-
- notrace(junk)
- char *junk;
- {
-
- trace_lo = -1;
- if (logging_fp == NULL)
- return(OK);
- else
- fclose(logging_fp);
- logging_fp = NULL;
- return(OK);
- }
-
-
- insert_disk(rest)
- char *rest;
- {
- char *name;
- char *which;
- int fd;
- int read_only = 0;
-
- name = rest;
- rest = split(rest);
- which = rest;
- rest = split(rest);
-
- if (name == NULL || *name == '\0') {
- printf("usage: insert <file name> [drive]\n");
- return(OK);
- }
-
- fd = open(name, 2); /* attempt open for read/write */
- if (fd >= 0)
- read_only = 0;
- else { /* attempt open read only */
- read_only = 1;
- fd = open(name, 0);
- }
- if (fd < 0) {
- fprintf(stderr, "can't open %s: ", name);
- perror("");
- return(OK);
- }
-
- if (*which == '2')
- drive = 1;
- else
- drive = 0;
-
- if (disk[drive] >= 0)
- close(disk[drive]);
-
- strcpy(diskname[drive], name);
-
- disk[drive] = fd;
- write_prot[drive] = read_only;
-
- printf("disk %d inserted, %swrite protected\n", drive + 1,
- read_only ? "" : "not ");
-
- return(OK);
- }
-
-
- dissassemble(rest)
- char *rest;
- {
- unsigned short start,end;
- long istart;
- long iend;
- int count = 0;
- char *first,*last;
-
- first = rest;
- rest = split(rest);
- last = rest;
- rest = split(rest);
-
- istart = get_hex_number(first);
- iend = get_hex_number(last);
- if (istart != -1)
- lpoint = istart;
- if (iend == -1)
- iend=65537;
- while ( (long) lpoint < iend) {
- lpoint += diss(lpoint, stdout);
- printf("\n");
- count++;
- if (iend == 65537)
- if (count > term_lines-3)
- break;
- }
- return OK;
- }
-
- ascii_dump(l,h)
- unsigned short l,h;
- {
- while (l < h) {
- if (isprint(mem[l]))
- printf("%c",mem[l]);
- else
- printf(".");
- l++;
- }
- }
-
- hex_dump(rest)
- char *rest;
- {
- char *start,*end;
- unsigned short last, addr,oaddr;
- long iaddr1,iaddr2;
- int count;
-
- start = rest;
- rest = split(rest);
- end = rest;
- rest = split(rest);
- iaddr1 = get_hex_number( start );
- iaddr2 = get_hex_number( end );
-
- if (iaddr2 != -1 && iaddr1 > iaddr2)
- return(OK);
-
- if (iaddr1 != -1)
- lpoint = (unsigned short) iaddr1;
- if (iaddr2 == -1)
- last = lpoint + 1;
- else
- last = (unsigned short) iaddr2 + 1;
-
- last &= 0xFFFF;
-
- addr = lpoint;
- count = 0;
- printf("%.4X: ", addr);
- oaddr = addr;
- do {
- if (count % 16 == 0 && count != 0) {
- ascii_dump(oaddr,addr);
- oaddr = addr;
- printf("\n%.4X: ", addr);
- }
- printf("%.2X ", mem[addr]);
- addr++;
- count++;
- } while (addr != last);
- while ((count % 16) != 0) {
- printf(" "); /* 3 spaces dd_ */
- count++;
- }
- ascii_dump(oaddr,addr);
- printf("\n");
- return(OK);
- }
-
- deposit(rest)
- char *rest;
- {
- char *addr;
- char *value;
- unsigned short location;
- long iloc;
- unsigned char val;
- int fired_once;
-
- addr = rest;
- rest = split(rest);
- fired_once = 0;
- iloc = get_hex_number(addr);
- if (iloc == -1) {
- printf("usage: deposit <addr> <value> [<value>...]\n");
- return(OK);
- }
-
- location = (unsigned short) iloc;
- do {
- value = rest;
- rest = split(rest);
- val = get_hex_number(value);
- if (val == -1) {
- if (!fired_once)
- printf("Invalid or Missing Hex address\n");
- return OK;
- }
- mem[location++] = val;
- fired_once = 1;
- } while (*rest != '\0');
-
- return(OK);
- }
-
- phantom_trace(rest)
- char *rest;
- {
- char *phantoms;
- char *addr1s;
- char *addr2s;
- char *file;
- long phantom;
- long low_val,high_val;
- int err = 0;
-
- phantoms = rest;
- rest = split(rest);
- addr1s = rest;
- rest = split(rest);
- addr2s = rest;
- rest = split(rest);
- file = rest;
- rest = split(rest);
-
- phantom = (unsigned short)get_hex_number(phantoms);
- low_val = get_hex_number(addr1s);
- high_val = get_hex_number(addr2s);
- if (*phantoms == '\0') {
- if (phantom_location == -1) {
- printf("The phantom sleeps.");
- if (trace_lo != -1 && trace_hi != -1)
- printf("however, a trace is active.");
- printf("\n");
- } else
- printf("the phantom waits until Pc = %.4X and then traces from %.4X to %.4X\n",phantom_location,trace_lo,trace_hi);
- return(OK);
- }
- if (low_val == -1 || high_val == -1 || phantom == -1) {
- printf("usage: phantom <addr> <addr> <addr> [file]\n");
- return OK;
- } phantom_location = phantom; trace_lo = low_val; trace_hi = high_val; if (logging_fp == NULL) {
- if (*file == '\0' || file == NULL) {
- printf("the phantom will trace to file 'trace'.\n");
- file = "trace";
- }
- logging_fp = fopen(file, "w");
- if (logging_fp == NULL) {
- perror("can't open trace file");
- trace_lo = -1;
- return(OK);
- }
- }
- return OK;
- }
-
- no_phantom_trace(rest)
- char *rest;
- {
- phantom_location = -1;
- trace_lo = -1;
- printf("the phantom goes to sleep.\n");
- if (logging_fp == NULL)
- return OK;
- fclose(logging_fp);
- logging_fp = NULL;
- return OK;
- }
-
- cd(rest)
- char *rest;
- {
-
- char *first;
- char path[200];
-
- first = rest;
- rest = split(rest);
- if (*first != '\0') {
- if (chdir(first)) {
- perror("cd");
- printf("CWD remains ");
- }
- }
- printf("%s\n",getcwd(path,198));
- return OK;
- }
-
- map(rest)
- char *rest;
- {
- map_to_upper = !map_to_upper;
- printf("Uppercase Mapping is %s\n",(map_to_upper)?"On":"Off");
- return OK;
- }
-
- sex(rest)
- char *rest;
- {
- printf("You'll need a real Apple for that sort of thing\n");
- return OK;
- }
-
-
- help(rest)
- char *rest;
- {
- printf("![command] Escape to Unix\n");
- printf(". Display Current Pc Point\n");
- printf("bload file addr load binary file into mem at addr\n");
- printf("breakpoint [addr] Set the Breakpoint to addr\n");
- printf("bsave file start end Save Memory from start to end in file\n");
- printf("cd [directory] Set/Show Current Working Directory\n");
- printf("cl[cdinvz] Clear appropriate Status Bit\n");
- printf("continue Resume Execution of Emulator\n");
- printf("deposit addr [val]+ Put val(s) into addr\n");
- printf("dup [l|p] duplicate top of stack into l or p\n");
- printf("escape char set escape char to be char \n");
- printf("examine addr Display Value in addr\n");
- printf("insert file drive# Make file disk in drive#\n");
- printf("jmp addr Make Pc=addr\n");
- printf("ld[asxy] val Load Register with val\n");
- printf("list [addr] [addr] Dissassemble at point or addr\n");
- printf("map Toggle lower -> upper case mapping\n");
- printf("nobreak Turn off breakpoint\n");
- printf("pop [l|p] get p or l from top of stack\n");
- printf("push [l|p|<addr> push l,p, or hex addr on stack\n");
- printf("reset Pc = Apple Reset Vector\n");
- printf("se[cdinvz] Set appropriate Status Flag\n");
- printf("trace [addr] [addr] Trace Between addresses/display trace point\n");
- return OK;
- }
-
- set_escape_char(rest)
- char *rest;
- {
- char c;
- if (*rest != '\0')
- escape_char = *rest;
- printf("escape character is ");
- if (isprint(escape_char))
- printf("%c",(int)escape_char);
- else
- printf("^%c",(char)escape_char+64);
- printf(" (0x%.2X)",(int)escape_char);
- printf("\n");
- return(OK);
- }
-
- disk_names(rest)
- char *rest;
- {
-
- printf("drive 1: %s\n", disk[0] >= 0 ? diskname[0] : "empty");
- printf("drive 2: %s\n", disk[1] >= 0 ? diskname[1] : "empty");
- return(OK);
- }
-