ftp.nice.ch/pub/next/tools/emulators/a2_1.1.NIHS.bs.tar.gz#/a2/commands.c

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.