home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Otherware
/
Otherware_1_SB_Development.iso
/
amiga
/
utility
/
emulator
/
apple2em.lzh
/
commands.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-18
|
14KB
|
881 lines
/*
* 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);
}