This is commands.c in view mode; [Download] [Up]
/*
* 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
*/
#import <stdio.h>
#import <libc.h>
#import <ctype.h>
#import <signal.h>
#import "a2.h"
#import "cli.h"
#ifdef JOYSTICK_SUPPORT
#import <joystick.h>
#import <errno.h>
#endif JOYSTICK_SUPPORT
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;
void init_point(void)
{
pstack.sp = -1;
}
int pop_point(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);
}
int dup_point(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);
}
int push_point(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);
}
int clb(char *junk)
{
B = 0;
return(DISPLAY);
}
int seb(char *junk)
{
B = 1;
return(DISPLAY);
}
int clc(char *junk)
{
C = 0;
return(DISPLAY);
}
int sec(char *junk)
{
C = 1;
return(DISPLAY);
}
int sev(char *junk)
{
V = 1;
return(DISPLAY);
}
int clv(char *junk)
{
V = 0;
return(DISPLAY);
}
int sed(char *junk)
{
D = 1;
return(DISPLAY);
}
int cld(char *junk)
{
D = 0;
return(DISPLAY);
}
int sei(char *junk)
{
I = 1;
return(DISPLAY);
}
int clri(char *junk)
{
I = 0;
return(DISPLAY);
}
int sen(char *junk)
{
N = 1;
return(DISPLAY);
}
int cln(char *junk)
{
N = 0;
return(DISPLAY);
}
int sez(char *junk)
{
NZ = 0;
return(DISPLAY);
}
int clz(char *junk)
{
NZ = 1;
return(DISPLAY);
}
void quit_emulator(char *junk)
{
restore_term();
exit(0);
}
int ver(char *junk)
{
printf("a2 - Apple II emulator (c) Copyright 1990 by Rich Skrenta & Tom Markson\n");
return(OK);
}
int refresh(char *junk)
{
in_cli = FALSE;
return(OK);
}
int shell_escape(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);
}
int do_soft_reset(char *rest)
{
Pc = mem[0xFFFC] | (mem[0xFFFD] << 8);
return(DISPLAY);
}
int do_bload(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);
}
int do_bsave(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);
}
int show_point(char *rest)
{
lpoint = Pc;
return(DISPLAY);
}
int hack(char *rest)
{
extern int cur_track;
cur_track = get_hex_number(rest);
return(OK);
}
int do_jump(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);
}
}
int trace(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",
(unsigned int)trace_lo,
(unsigned int)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);
}
int ldx(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);
}
int ldy(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);
}
int lda(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);
}
int lds(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);
}
int set_break_point(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);
}
int clear_break_point(char *rest)
{
breakpoint = -1;
return(OK);
}
int notrace(char *junk)
{
trace_lo = -1;
if (logging_fp == NULL)
return(OK);
else
fclose(logging_fp);
logging_fp = NULL;
return(OK);
}
int insert_disk(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);
}
int dissassemble(char *rest)
{
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;
}
void ascii_dump(unsigned short l, unsigned short h)
{
while (l < h) {
if (isprint(mem[l]))
printf("%c",mem[l]);
else
printf(".");
l++;
}
}
int hex_dump(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);
}
int deposit(char *rest)
{
char *addr;
char *value;
unsigned short location;
long iloc;
long pre_val;
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);
pre_val = get_hex_number(value);
if (pre_val == -1) {
if (!fired_once)
printf("Invalid or Missing Hex address\n");
return OK;
}
else val = pre_val;
mem[location++] = val;
fired_once = 1;
} while (*rest != '\0');
return(OK);
}
int phantom_trace(char *rest)
{
char *phantoms;
char *addr1s;
char *addr2s;
char *file;
long phantom;
long low_val,high_val;
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",
(unsigned int)phantom_location,
(unsigned int)trace_lo,
(unsigned int)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;
}
int no_phantom_trace(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;
}
int cd(char *rest)
{
char *first;
char path[200];
first = rest;
rest = split(rest);
if (*first != '\0') {
if (chdir(first)) {
perror("cd");
printf("CWD remains ");
}
}
#ifdef NeXT
printf("%s\n",getwd(path));
#else
printf("%s\n",getcwd(path,198));
#endif
return OK;
}
int map(char *rest)
{
map_to_upper = !map_to_upper;
printf("Uppercase Mapping is %s\n",(map_to_upper)?"On":"Off");
return OK;
}
int sex(char *rest)
{
printf("You'll need a real Apple for that sort of thing\n");
return OK;
}
int help(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");
#ifdef JOYSTICK_SUPPORT
printf("recalibrate Recalibrate joystick\n");
#endif JOYSTICK_SUPPORT
printf("se[cdinvz] Set appropriate Status Flag\n");
printf("trace [addr] [addr] Trace Between addresses/display trace point\n");
return OK;
}
int set_escape_char(char *rest)
{
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);
}
int disk_names(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);
}
#ifdef JOYSTICK_SUPPORT
int do_joystick_recalibrate(char *rest)
{
int status;
struct JS_DATA_TYPE js;
int xmax, ymax;
printf ("Joystick calibration:\n");
printf ("Move joystick to upper left corner and press button one.\n");
while ((read (joystick_fd, &js, JS_RETURN) > 0) && (!(js.buttons & 1)))
;
status = read (joystick_fd, &js, JS_RETURN);
if (status != JS_RETURN)
{
int temperrno = errno;
perror ("js");
printf ("js - status = %d, errno = %d\n",
status, temperrno);
exit (1);
}
xmin = js.x;
ymin = js.y;
printf ("Move joystick to lower right corner and press button two.\n");
while ((read (joystick_fd, &js, JS_RETURN) > 0) && (!(js.buttons & 2)))
;
status = read (joystick_fd, &js, JS_RETURN);
if (status != JS_RETURN)
{
int temperrno = errno;
perror ("js");
printf ("js - status = %d, errno = %d\n",
status, temperrno);
exit (1);
}
xmax = js.x;
ymax = js.y;
printf ("Center joystick and press button one\n");
while ((read (joystick_fd, &js, JS_RETURN) > 0) && (!(js.buttons & 1)))
;
status = read (joystick_fd, &js, JS_RETURN);
if (status != JS_RETURN)
{
int temperrno = errno;
perror ("js");
printf ("js - status = %d, errno = %d\n",
status, temperrno);
exit (1);
}
xcenter = js.x;
ycenter = js.y;
if (((xmax - xcenter) < 128)
|| ((xcenter - xmin) < 128))
{
printf ("X-axis calibration failed\n");
return OK;
}
if (((ymax - ycenter) < 128)
|| ((ycenter - ymin) < 128))
{
printf ("Y-axis calibration failed\n");
return OK;
}
xpartition_low = ((float)(xcenter - xmin)) / 128.0;
ypartition_low = ((float)(ycenter - ymin)) / 128.0;
xpartition_high = ((float)(xmax - xcenter)) / 128.0;
ypartition_high = ((float)(ymax - ycenter)) / 128.0;
js.buttons = 0;
printf ("Press both buttos to end recalibration testing.\n");
while ((!(js.buttons & 1)) || (!(js.buttons & 2)))
{
int my_x, my_y;
status = read (joystick_fd, &js, JS_RETURN);
if (status != JS_RETURN)
{
int temperrno = errno;
perror ("js");
printf ("js - status = %d, errno = %d\n",
status, temperrno);
exit (1);
}
if (js.x < xcenter) my_x = (js.x - xmin) / xpartition_low;
else my_x = 128 + (js.x - xcenter) / xpartition_high;
if (js.y < ycenter) my_y = (js.y - ymin) / ypartition_low;
else my_y = 128 + (js.y - ycenter) / ypartition_high;
if (my_x < 0) my_x = 0;
if (my_x > 255) my_x = 255;
if (my_y < 0) my_y = 0;
if (my_y > 255) my_y = 255;
fprintf (stdout, "button 0: %s button 1: %s X position: %4d Y position: %4d\r",
(js.buttons & 1) ? "on " : "off",
(js.buttons & 2) ? "on " : "off",
my_x, my_y);
fflush (stdout);
/* give other processes a chance */
usleep (100);
}
return OK;
}
#endif JOYSTICK_SUPPORT
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.