zws.com logo

products:

Re39 Sourcecode

/*
	RE39.CPP
 
	Re39 Disassembler
	Interactive disassembler for Rockwell C29 and C39 microcontrollers.
	(C) Copyright 1995 by Lewin A.R.W. Edwards.
	Binary may be redistributed freely.
	Source not for distribution under any circumstances.
 
	04/09/96    larwe   maintenance release, updated copyright and contact
	07/05/95	larwe	fixed bug disassembling files >64K, converted buf
						ptr to huge
						1.02 release
	06/23/95	larwe	fixed visual bug in T command "append/overwrite" msg
						changed signoff message slightly
						1.01 release
*/
 
 
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <dir.h>
#include <io.h>
#include <fcntl.h>
#include <alloc.h>
#include <ctype.h>
#pragma hdrstop
 
extern unsigned _stklen=8192;
 
 
/*
	*** Miscellaneous defines
*/
#define VERSION		"1.02s"
#define	PROMPT		"."
#define	CMDBUFSIZE	120			/* size of command buffer */
#define	SCRNLENGTH	20			/* number of lines to dump at a time */
 
/*
	*** Commands
*/
#define	CMD_NULL		0
#define	CMD_QUIT		'q'
#define	CMD_HELP		'?'
#define	CMD_DPLIST		'@'
#define	CMD_DPADDR		'p'
#define CMD_EXECUTE		'g'
#define	CMD_DPUMP		'm'
#define CMD_FREAD		'r'
#define CMD_HWCMT		'h'
#define CMD_DISM		'u'
#define CMD_DUMP		'd'
#define CMD_SELUPPER	'c'
#define CMD_STREAM		't'
#define CMD_DIR			'f'
 
/*
	*** Hardware comment modes
*/
#define HW_NONE			0	/* no comments */
#define	HW_GP			1   /* general purpose */
#define	HW_UART			2	/* 16450/16550 emulation */
 
/*
	*** Datapump types
*/
#define DP_DEFAULT		DP_NONE
#define	DP_DEFADDR		0xFF00
#define DP_NONE			0
#define	DP_288DPI		1
 
/*
	*** Strings
*/
const char *cx9_00_1f=	"Cx9 port A (bidirectional)\0"
						"Cx9 port B (output only)\0"
						"Cx9 port C (bidirectional)\0"
						"Cx9 port A direction (R/O)\0"
						"Cx9 port D & direction control\0"
						"Cx9 port B select (R/W)\0"
						"Cx9 port C direction (W)\0"
						"Cx9 port E (R/W)\0"
						"Cx9 mask option & port E dir'n\0"
						"Cx9 Low Power Register (LPR)\0"
						"Cx9 External Interrupt Register\0"
						"Cx9 Clear External Interrupt\0"
						"Cx9 PTG B Mode (R/W)\0"
						"Cx9 PBB (R/W)\0"
						"Cx9 PBUL, PBB to PBLL\0"
						"Cx9 PBUL PBB-PBLL Clear Download\0"
						"Cx9 Timer A Mode\0"
						"Cx9 TALC, TAUC-TAS, TALL\0"
						"Cx9 TAS (R), TAUL (W)\0"
						"Cx9 TAS, TAUL, Clear, Download\0"
						"Cx9 Timer B Mode\0"
						"Cx9 TBLC, TBUC-TBS, TBLL\0"
						"Cx9 TBS (R), TBUL (W)\0"
						"Cx9 TBS, TBUL, Clear, Download\0"
						"Cx9 bank switch register 0 (R/W)\0"
						"Cx9 bank switch register 1 (R/W)\0"
						"Cx9 bank switch register 2 (R/W)\0"
						"Cx9 bank switch register 3 (R/W)\0"
						"Cx9 bank switch register 4 (R/W)\0"
						"Cx9 bank switch register 5 (R/W)\0"
						"Cx9 bank switch register 6 (R/W)\0"
						"Cx9 bank switch register 7 (R/W)\0"
						"\0";
 
const char *cx9_20_32_g="C29 SP RAM 0, C39 Tx/Rx FIFO buf\0"
						"Cx9 SP RAM 1\0"
						"Cx9 SP RAM 2\0"
						"Cx9 SP RAM 3\0"
						"Cx9 SP RAM 4\0"
						"Cx9 SP RAM 5\0"
						"Cx9 SP RAM 6\0"
						"Cx9 SP RAM 7\0"
						"Cx9 SP RAM 8\0"
						"Cx9 SP RAM 9\0"
						"Cx9 SP RAM A\0"
						"Cx9 SP RAM B\0"
						"Cx9 SP RAM C\0"
						"Cx9 SP RAM D\0"
						"Cx9 SP RAM E\0"
						"Cx9 host handshake register\0"
						"C39 only : FIFO status register\0"
						"C39 only : FIFO int enable reg\0"
						"Cx9 host control register\0"
						"\0";
 
const char *cx9_20_32_u="C29 Tx/Rx, C39 Tx/Rx FIFO buf\0"
						"C29 Tx buffer, C39 LSR\0"
						"C29 SP RAM 2, C39 MSR\0"
						"Cx9 line control register\0"
						"Cx9 modem control register\0"
						"C29 SP RAM 5, C39 FIFO control\0"
						"Cx9 SP RAM 6\0"
						"Cx9 SP RAM 7, C39 scratch reg\0"
						"Cx9 divisor latch LSB\0"
						"Cx9 divisor latch MSB\0"
						"Cx9 SP RAM A\0"
						"Cx9 SP RAM B\0"
						"Cx9 SP RAM C\0"
						"Cx9 SP RAM D\0"
						"C29 SP RAM E, C39 GPFS\0"
						"Cx9 host handshake register\0"
						"C29 LSR, C39 FSR\0"
						"C29 MSR, C39 FIER\0"
						"Cx9 host control register\0"
						"\0";
 
const char *cx9_33_3f=	"Cx9 chip select fast/slow\0"
						"Cx9 PTG A mode\0"
						"Cx9 PAB\0"
						"Cx9 PAUL, PAB-PALL\0"
						"Cx9 PAUL PAB-PALL clear download\0"
						"Cx9 serial I/O buffers\0"
						"Cx9 serial interrupt enable\0"
						"Cx9 serial mode register\0"
						"Cx9 serial line control register\0"
						"Cx9 serial status register\0"
						"Cx9 serial form register\0"
						"Cx9 SOUT (RxD) divider latch (R)\0"
						"Cx9 SIN (TxD) divider latch (R)\0"
						"\0";
 
						/*  *********************************  */
						/* RC288DPi, RCV288DPi, RC288DPi-D registers */
const char *dp_288dpi=	"DPi Rx/voice Rx buf (RBUFFER/VBUFR)\0"
						"DPi VOLUME/VPAUSE/CELULR/xXHF/RXP\0"
						"DPi TDE/SQDIS/V54/S511/DCD/CODBITS\0"
						"DPi EPT/SEPT/SRCEN/RLSDE/ARC/SDIS\0"
						"DPi RB/EQT2/V32BS/FIFOEN/EQFZ/NRZIEN\0"
						"DPi ECFZ/ECSQ/FECSQ/TXSQ/CEQ/TTDIS\0"
						"DPi RTDIS/EXOS/CF17/HDLC/PEN/STB\0"
						"DPi RDLE/RDL/L2ACT/DDIS/L3ACT/RA\0"
						"DPi ASYN/TPDM/V21S/V54T/V54A/V54P\0"
						"DPi NV25/CC/DTMF/ORG/LL/DATA/RRTSE\0"
						"DPi PNSUC/FLAGDT/PE/FE/OE/CRCS/VSYNC\0"
						"DPi TONEx/ATV25/ATBEL/DISDET/EQMAT\0"
						"DPi AADET/ACDET/CADET/CCDET/SDET\0"
						"DPi P2DET/PNDET/S1DET/SCR1/U1DET\0"
						"DPi RTDET/BRKD/RREDT/V32BDT/SPEED\0"
						"DPi RLSD/FED/CTS/DSR/RI/TM/RTSDT\0"
						"DPi Tx/voice Tx buf (TBUFFER/VBUFT)\0"
						"DPi BRKS/PARSL/TXV/RXV/V23HDX/TEOF\0"
						"DPi configuration (CONF)\0"
						"DPi TLVL/RTH/TXCLK\0"
						"DPi handshake abort code (ABCODE)\0"
						"DPi SLEEP/RDWK/HWRWK/AUTO/RREN/EXL3\0"
						"DPi sec Rx/V.34 Rx status (SECRXB)\0"
						"DPi sec Tx/V.34 Tx status (SECTXB)\0"
						"DPi memory access data LSB (MEDAL)\0"
						"DPi memory access data MSB (MEDAM)\0"
						"DPi SFRES/RIEN/RION/DMAE/SCOBF\0"
						"DPi EDET/DTDET/OTS/DTMFD/DTMF code\0"
						"DPi memory access addr LSB (MEADDL)\0"
						"DPi MEACC/MEMW/MEMCR/addr bits 8-11\0"
						"DPi TDBIA/RDBIA/TDBIE/TDBE/RDBIE\0"
						"DPi NSIA/NCIA/NSIE/NEWS/NCIE/NEWC\0"
						"\0";
 
/*
	*** Variables
*/
char oldcmd[CMDBUFSIZE];		/* old command line */
char cmdline[CMDBUFSIZE];		/* command line */
char cmdword[CMDBUFSIZE];		/* command word buffer */
char command;					/* command last parsed */
char datapump;					/* datapump type */
unsigned int datapump_addr;		/* datapump starting address */
unsigned int datapump_len;		/* number of bytes occupied by datapump */
char showhardware;				/* flag : show hardware comments */
char instrupper;				/* flag : opcodes in uppercase */
unsigned char huge *buffer;		/* ptr to image read buffer */
unsigned long buffersize;		/* size of buffer */
unsigned long address;			/* current disassembly address */
const char *dp_comments;		/* selected datapump comment set */
FILE *dismfile;					/* file to stream output */
 
 
/*
	*** Prototypes
*/
void initscreen(void);
void getcmd(char *);
void statusbar(void);
void updatepc(void);
void nextword(char *);
void getword(char *,char *);
int wordtonum(char *,unsigned long *);
void dismline(unsigned long *,unsigned char huge *,char *);
unsigned char get_byte(unsigned long *,unsigned char huge *,char *,char *,char *,char);
void analyze_address(unsigned int, char*);
unsigned int get_word(unsigned long *,unsigned char huge *,char *,char *,char *,char);
void dumpline(unsigned long *,unsigned char huge *,char *);
void get_relative(unsigned long *,unsigned char huge *,char *,char *,char *);
char *seekstring(int,const char *);
int criticalhandler(int,int,int,int);
unsigned char buf_byte(unsigned long);
 
/*
	*** Main function
*/
 
void main()
{
	/* set up miscellaneous variables */
	oldcmd[0]=0;	/* clear command history */
	command=CMD_NULL;
	datapump=DP_DEFAULT;
	datapump_addr=DP_DEFADDR;
	datapump_len=0;
	buffer=NULL;
	buffersize=0;
	address=0;
	showhardware=1;
	instrupper=1;
	dismfile=NULL;
 
	/* initialize display */
	initscreen();
 
	/* initialize critical err handler */
	harderr(criticalhandler);
 
	/* sign-on message */
	highvideo();
	cprintf("Re39 V"VERSION" Rockwell Developer's Microtool         (AnMS : Better FREE Tools)\n\r\n\r");
 
	normvideo();
	cprintf("  (C) Copyright 1995 by Lewin Edwards; all rights reserved. This program is\n\r"
			"  NOT public domain.  It is distributable  and usable in all  circumstances\n\r"
			"  without royalty, provided copies  are shipped with original documentation\n\r"
			"  and are unmodified,  SUBJECT TO EXCLUSIONS.  You MUST read and understand\n\r"
			"  the copyright notice before using this product -  refer to documentation.\n\r\n\r"
			"Enter '?' for a brief on-line command reference.\n\r\n\r");
 
	/* main loop */
	while (command!=CMD_QUIT)
	{
		command=CMD_NULL;
		cmdline[0]=0;
		while (!cmdline[0])
			getcmd(cmdline);
		getword(cmdline,cmdword);	/* parse off command word */
 
		command=cmdword[0];
 
		switch(command)
		{
			/*** On-line help ***/
			case CMD_HELP :
					cprintf("\n\r"
							"Re39 Command Summary\n\r"
							"ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ\n\r"
							"?                   Help (this screen)\n\r"
							"@                   List datapump models supported by command M\n\r"
							"c [ON | OFF]        Enable/disable uppercase opcodes (default ON)\n\r"
							"d [xxxxxx] [*]      Dump ASCII/hex from xxxxxx or current addr, *=continuous\n\r"
							"f [directory]       Show directory listing\n\r"
							"h [GP | UART | OFF] Disable or select CPU hardware comments (default GP)\n\r"
							"m datapump          Set datapump model (affects comments in disassembly)\n\r"
							"p xxxx              Set datapump address (affects comments in disassembly)\n\r"
							"r file              Read binary dump to internal buffer\n\r"
							"t [file]            Enable streaming to textfile (T by itself closes file)\n\r"
							"u [xxxxxx] [*]      Unassemble from xxxxxx or current address, *=continuous\n\r"
							"\n\rAll numbers are in hexadecimal. '$' is not required when entering numbers.\n\r\n\r");
				break;
 
			/*** List supported datapumps ***/
			case CMD_DPLIST :
					cprintf("\n\r"
							"Rockwell Datapumps Supported by 'M' Command\n\r"
							"ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕ\n\r"
							"NONE            Disable datapump register comments\n\r"
							"288DPI          RC288DPi, RCV288DPi, RC288DPi-D V.34 datapumps\n\r\n\r"
							"To add more controllers to this list, send FULL technical reference manual to\n\r"
							"Lewin Edwards, PO Box 590, Toorak, Vic. 3142, Australia, tel +61-3-419-320415\n\r\n\r");
				break;
 
			/*** Set datapump address ***/
			case CMD_DPADDR : {
					unsigned long addr=0;
 
					nextword(cmdline);
					getword(cmdline,cmdword);
					if(wordtonum(cmdword,&addr))
						cprintf("'%s' is not a valid hexadecimal number.\n\r",cmdword);
					else
						if (addr>=0x10000lu)
							cprintf("$%lX is an invalid address. The datapump must lie between $0000-FFFF.\n\r",addr);
						else {
							cprintf("Base address for commenting datapump access is now located at $%lX.\n\r",addr);
							datapump_addr=(unsigned int) (addr & 0xffffu);
							statusbar();
						}
					}
				break;
 
			/*** Set datapump type ***/
			case CMD_DPUMP : {
					char ok=0;
					nextword(cmdline);
					getword(cmdline,cmdword);
					if (!strlen(cmdword) || !strcmp(cmdword,"none")) {
							datapump=DP_NONE;
							dp_comments=NULL;
							ok=1;
						}
					else if (!strcmp(cmdword,"288dpi")) {
							datapump=DP_288DPI;
							datapump_len=32;	/* 288DPi has 32 registers */
							dp_comments=dp_288dpi;
							ok=1;
						}
 
					if (!ok)
						cprintf("Unsupported datapump type. Type '@' for a list of supported datapumps.\n\r");
					else {
						if (datapump==DP_NONE)
							cprintf("Datapump comments are disabled.");
						else
							cprintf("Datapump comments are enabled.");
						nextword(cmdline);
						if (cmdline[0]!=0)
							cprintf(" Extra parameter(s) ignored.");
						cprintf("\n\r");
						statusbar();
					}
					}
				break;
 
			/*** Read image file ***/
			case CMD_FREAD : {
					char filename[CMDBUFSIZE];
					int handle;
 
					nextword(cmdline);
					getword(cmdline,filename);
					if (!strlen(filename)) {
						cprintf("You must specify a filename to load with this command.\n\r");
					}
					else {
						handle=open(filename,O_RDONLY | O_BINARY);
						if (handle==-1)
							cprintf("Cannot open '%s'.\n\r",filename);
						else {
							if (buffer!=NULL) {
								cprintf("Unloaded existing binary in memory : freed %lu bytes.\n\r",buffersize);
								farfree(buffer);
								buffer=NULL;
								buffersize=0;
								statusbar();
							}
							address=0;	/* reset disassembly address */
							buffer=(unsigned char far *) farmalloc(filelength(handle));
							if (buffer==NULL) {
								close(handle);
								cprintf("Insufficient free base memory to load '%s'.\n\r",filename);
							}
							else {
								unsigned long progress=0;
 
								buffersize=filelength(handle);
 
								/* read 32K blocks for as long as possible */
								while (buffersize-progress>32768u) {
									read(handle,buffer+progress,32768u);
									progress+=32768u;
								}
 
								/* read remainder of file bytewise */
								if (progress<buffersize)
									for (unsigned long l=progress;l<buffersize;l++)
										read(handle,buffer+l,1);
 
								cprintf("Read $%-06.06lX (%lu) bytes - suggested (EEP)ROM type : ",buffersize,buffersize);
 
								/* suggest EPROM size */
								if (buffersize<=2048)
									cprintf("2716/2732A/2732B");
								else if (buffersize<=4096)
									cprintf("2732");
								else if (buffersize<=8192)
									cprintf("2764");
								else if (buffersize<=16384)
									cprintf("27128");
								else if (buffersize<=32768ul)
									cprintf("27256");
								else if (buffersize<=65536ul)
									cprintf("27512");
								else if (buffersize<=131072ul)
									cprintf("27010");
								else if (buffersize<=262144ul)
									cprintf("27020");
								else if (buffersize<=524288ul)
									cprintf("27040");
								else
									cprintf("unknown");
								cprintf("\n\r");
							}
						}
					}
					statusbar();
				}
				break;
 
			/*** Select hardware comments ***/
			case CMD_HWCMT :
					nextword(cmdline);
					getword(cmdline,cmdword);
					if (!cmdword[0])
						strcpy(cmdword,"gp");
					if (cmdword[0]=='g')
						showhardware=HW_GP;
					else if (cmdword[0]=='u')
						showhardware=HW_UART;
					else if (cmdword[0]=='o')
						showhardware=HW_NONE;
					else
						cprintf("'%s' is not a valid parameter for this command.\n\r",cmdword);
					statusbar();
				break;
 
			/*** Disassemble ***/
			case CMD_DISM :
					if (buffer==NULL)
						cprintf("You must have an image file loaded before using this command.\n\r");
					else {
						unsigned long addr=0;
						char continuous=0;
 
						nextword(cmdline);
						getword(cmdline,cmdword);
						if (cmdword[0]=='*')
							continuous=1;
						else {
							if (cmdword[0]) {
								if(wordtonum(cmdword,&addr)) {
									cprintf("'%s' is not a valid hexadecimal number.\n\r",cmdword);
									break;
								}
								else
									if (addr>=buffersize) {
										cprintf("$%lX lies outside the address range of the image file now in memory.\n\r",addr);
										break;
									}
									else {
										address=addr;
										nextword(cmdline);
										getword(cmdline,cmdword);
										if (cmdword[0]=='*')
											continuous=1;
									}
							}
						}
 
 
						if (continuous) {
							char key;
 
							while (continuous) {
								/*** do one screenful ***/
								for (int i=0;i<SCRNLENGTH;i++) {
									char linebuf[100];
									dismline(&address,buffer,linebuf);
									cprintf("%s\n\r",linebuf);
									if (dismfile!=NULL)
										fprintf(dismfile,"%s\n",linebuf);
									updatepc();
								}
								highvideo();
								cprintf("-----  Press Esc to stop listing, any other key to show next screenful  -----");
								normvideo();
								key=getch();
								if (!key)
									key=getch();
 
								gotoxy(1,wherey());
								clreol();
								if (key==27)
									continuous=0;
							}
						}
						else {
							/*** do one screenful ***/
							for (int i=0;i<SCRNLENGTH;i++) {
								char linebuf[100];
								dismline(&address,buffer,linebuf);
								cprintf("%s\n\r",linebuf);
								if (dismfile!=NULL)
									fprintf(dismfile,"%s\n",linebuf);
								updatepc();
							}
						}
					}
				break;
 
			/*** Dump ***/
			case CMD_DUMP :
					if (buffer==NULL)
						cprintf("You must have an image file loaded before using this command.\n\r");
					else {
						unsigned long addr=0;
						char continuous=0;
 
						nextword(cmdline);
						getword(cmdline,cmdword);
						if (cmdword[0]=='*')
							continuous=1;
						else {
							if (cmdword[0]) {
								if(wordtonum(cmdword,&addr)) {
									cprintf("'%s' is not a valid hexadecimal number.\n\r",cmdword);
									break;
								}
								else
									if (addr>=buffersize) {
										cprintf("$%lX lies outside the address range of the image file now in memory.\n\r",addr);
										break;
									}
									else {
										address=addr;
										nextword(cmdline);
										getword(cmdline,cmdword);
										if (cmdword[0]=='*')
											continuous=1;
									}
							}
						}
 
 
						if (continuous) {
							char key;
 
							while (continuous) {
								/*** do one screenful ***/
								for (int i=0;i<SCRNLENGTH;i++) {
									char linebuf[100];
									dumpline(&address,buffer,linebuf);
									cprintf("%s\n\r",linebuf);
									if (dismfile!=NULL)
										fprintf(dismfile,"%s\n",linebuf);
									updatepc();
								}
								highvideo();
								cprintf("-----  Press Esc to stop listing, any other key to show next screenful  -----");
								normvideo();
								key=getch();
								if (!key)
									key=getch();
 
								gotoxy(1,wherey());
								clreol();
								if (key==27)
									continuous=0;
							}
						}
						else {
							/*** do one screenful ***/
							for (int i=0;i<SCRNLENGTH;i++) {
								char linebuf[100];
								dumpline(&address,buffer,linebuf);
								cprintf("%s\n\r",linebuf);
								if (dismfile!=NULL)
									fprintf(dismfile,"%s\n",linebuf);
								updatepc();
							}
						}
					}
				break;
 
			/*** Enable/disable uppercase opcodes ***/
			case CMD_SELUPPER :
					nextword(cmdline);
					getword(cmdline,cmdword);
					if (!cmdword[0])
						strcpy(cmdword,"on");
					if (!strcmp(cmdword,"on") || !strcmp(cmdword,"1"))
						instrupper=1;
					else if (!strcmp(cmdword,"off") || !strcmp(cmdword,"0"))
						instrupper=0;
					else
						cprintf("'%s' is not a valid parameter for this command.\n\r",cmdword);
					statusbar();
				break;
 
 
			/*** Set output stream file ***/
			case CMD_STREAM : {
					nextword(cmdline);
					getword(cmdline,cmdword);
 
					/* close file if no parameter specified */
					if (!cmdword[0])
					{
						if (dismfile==NULL)
							cprintf("You must specify an output filename for this command.\n\r");
						else {
							fclose(dismfile);
							dismfile=NULL;
							cprintf("Closed current stream file.\n\r");
						}
					}
					else {
						char kb=0;
 
						if (dismfile!=NULL)
						{
							fclose(dismfile);
							cprintf("Closed current stream file.\n\r");
						}
 
						/* check to see if file exists */
						dismfile=fopen(cmdword,"rt");
						if (dismfile!=NULL)
						{
							fclose(dismfile);
							cprintf("Specified file exists. Overwrite (O), Append (A) or Cancel (any other key) ? ");
							kb=getch();
							if (!kb)
								kb=(getch()==255);
							kb=toupper(kb);
							if (kb!='O' && kb!='A')
							{
								cprintf("-\n\rAborted.\n\r");
								break;
							}
							else
								cprintf("%c\n\r",kb);
						}
 
						/* append to file, or rewrite file, based on selection */
						if (kb=='A')
							dismfile=fopen(cmdword,"at");
						else
							dismfile=fopen(cmdword,"wt");
						if (dismfile==NULL)
							cprintf("Cannot open specified file for writing.\n\r");
						else
							cprintf("D and U output will be streamed to '%s'.\n\r",cmdword);
					}
				break;
			}
 
			/*** Show directory listing ***/
			case CMD_DIR : {
					struct find_t ffb;
					int err=0;
					int num=0;
 
					nextword(cmdline);
					getword(cmdline,cmdword);
					if (!cmdword[0])
					{
						strcpy(cmdword,"X:");
						cmdword[0]=getdisk()+'A';
					}
					if (cmdword[strlen(cmdword)-1]!='\\' && cmdword[strlen(cmdword)-1]!=':')
						strcat(cmdword,"\\");
					strcat(cmdword,"*.*");
 
					err=_dos_findfirst(cmdword,FA_ARCH | FA_DIREC,&ffb);
					while (!err)
					{
						if (ffb.attrib & FA_DIREC)
							cprintf("[%-12.12s] ",ffb.name);
						else
							cprintf(" %-12.12s  ",ffb.name);
						num++;
						if (num>=5)
						{
							num=0;
							cprintf("\n\r");
						}
						err=_dos_findnext(&ffb);
					}
					cprintf("\n\r");
				break;
			}
 
			/*** Execute code ***/
			case CMD_EXECUTE :
					cprintf("Code emulation is not supported in this version. 'Go' command is inoperative.\n\r");
				break;
 
			/*** Unknown command ***/
			default :
					cprintf("Unknown command '%s'. Type '?' for help.\n\r",cmdword);
				break;
		}
	}
 
	/* close stream file if applicable */
	if (dismfile!=NULL)
	{
		fclose(dismfile);
		cprintf("Closed stream file.\n\r");
	}
 
	/* restore main screen */
	window(1,1,80,25);
	textcolor(LIGHTGRAY);
	textbackground(BLACK);
	clrscr();
	cprintf("Thank you for using Re39. Address your comments to the author :\n\r"
			"Lewin A.R.W. Edwards, PO Box 590, Toorak Vic. 3142, Australia (larwe@ibm.net).\n\r"
			"Tel +61 419320415/+61 412809805/+61 414927056, BBS +61 3 98276881/98276277\n\r\n\r");
}
 
 
/*
	*** Initialize display
*/
void initscreen(void)
{
	window(1,1,80,24);
	textcolor(LIGHTGRAY);
	textbackground(BLACK);
	clrscr();
	statusbar();
}
 
/*
	*** Get command string
*/
void getcmd(char *cmdline)
{
	char keybuf=0;
	char extended;
	int position=0;
 
	cmdline[0]=0;
	cprintf(PROMPT);
 
	while (keybuf!=13)
	{
		/* get character */
		extended=0;
		keybuf=getch();
		if (!keybuf) {
			extended=1;
			keybuf=getch();
		}
 
		if (keybuf==13);
 
		/* Backspace */
		else if (!extended && keybuf==8) {
			if (position>0) {
				position--;
				cmdline[position]=0;
				cprintf("\b \b");
			}
		}
 
		/* Escape clears command line */
		else if (!extended && keybuf==27)
		{
			for (int i=0;i<position;i++)
				cprintf("\b \b");
			position=0;
 
		}
		/* F3 repeats last command */
		else if (extended && keybuf==61)
		{
			if (position>0)
				for (int i=0;i<position;i++)
					cprintf("\b \b");
			position=strlen(oldcmd);
			cprintf("%s",oldcmd);
			strcpy(cmdline,oldcmd);
		}
		else if (!extended) {
			if (position<CMDBUFSIZE-1) {
				cprintf("%c",keybuf);
				cmdline[position]=keybuf;
				cmdline[position+1]=0;
				position++;
			}
			else { /* beep if keyboard buffer full */
				sound(2000);
				delay(20);
				nosound();
				delay(10);
				while (kbhit()) getch();
			}
		}
	}
	strcpy(oldcmd,cmdline);
	cprintf("\n\r");
	strlwr(cmdline);
}
 
/*
	*** Put status bar at bottom of screen
*/
void statusbar(void)
{
	int x=wherex(),y=wherey();
 
	window(1,25,80,25);
	textbackground(RED);
	textcolor(WHITE);
	clreol();
	switch(datapump)
	{
		case DP_NONE :
				cprintf("Datapump cmts OFF > ");
			break;
 
		case DP_288DPI :
				cprintf("RC288DPi");
			break;
 
		default :
				cprintf("Error !!");
			break;
	}
	if (datapump!=DP_NONE)
		cprintf(" at $%04.4X > ",datapump_addr);
 
	switch(showhardware) {
		case HW_GP :
				cprintf("General-purpose  ");
			break;
 
		case HW_UART :
				cprintf("16x50 emulation  ");
			break;
 
		default :
				cprintf("Cx9 registers off");
	}
	cprintf(" > ");
 
	if (buffer==NULL)
		cprintf("No file loaded    ");
	else
		cprintf("%3lu Kbytes loaded ",buffersize/1024);
 
	cprintf(" > Next $%-06.6lX",address);
 
	gotoxy(76,1);
	textcolor(LIGHTGRAY);
	cprintf(VERSION);
	window(1,1,80,24);
	gotoxy(x,y);
	textcolor(LIGHTGRAY);
	textbackground(BLACK);
}
 
/*
	*** Update program counter at bottom of screen
*/
void updatepc(void)
{
	int x=wherex(),y=wherey();
 
	window(1,25,80,25);
	textbackground(RED);
	textcolor(WHITE);
	gotoxy(68,1);
	cprintf("%-06.6lX",address);
	window(1,1,80,24);
	gotoxy(x,y);
	textcolor(LIGHTGRAY);
	textbackground(BLACK);
}
 
/*
	*** Remove first keyword and trailing whitespace from string
*/
void nextword(char *text)
{
	/* parse off whitespace */
	while ((strlen(text)>0) && (text[0]==' ' || text[0]=='\t'))
		strcpy(text,(char *)&text[1]);
 
	/* parse off word */
	while ((strlen(text)>0) && (text[0]!=' ' && text[0]!='\t'))
		strcpy(text,(char *)&text[1]);
 
	/* parse off whitespace */
	while ((strlen(text)>0) && (text[0]==' ' || text[0]=='\t'))
		strcpy(text,(char *)&text[1]);
}
 
/*
	*** Separate the next word from the command line
*/
void getword(char *text,char *word)
{
	int pos=0;
 
	/* parse off whitespace */
	while ((strlen(text)>0) && (text[0]==' ' || text[0]=='\t'))
		strcpy(text,(char *)&text[1]);
 
	/* copy word */
	while (text[pos]!=0 && text[pos]!=' ' && text[pos]!='\t')
	{
		word[pos]=text[pos];
		pos++;
	}
	word[pos]=0;
}
 
/*
	*** Translate word into hex longint (strips leading $ if applicable)
	*** Returns 0 if OK, -1 if overflow or other error
*/
int wordtonum(char *word,unsigned long *num)
{
	/* parse off whitespace or leading $ */
	while ((strlen(word)>0) && (word[0]==' ' || word[0]=='\t' || word[0]=='$'))
		strcpy(word,(char *)&word[1]);
 
	/* zero-length strings and excessively long strings rejected instantly */
	if (!strlen(word) || strlen(word)>8)
		return -1;
 
	if(sscanf(word,"%lx", num)==1)
		return 0;
	else
		return 1;
}
 
/*
	*** Get one instruction and assemble a commented string, update address
	*** pointer with appropriate number of bytes so it points to the next
	*** instruction
*/
void dismline(unsigned long *addr,unsigned char huge *buf,char *string)
{
	unsigned char opcode=buf[*addr];
	unsigned char instr[21];
	unsigned char comment[41];
 
	sprintf(string,"%-06.6lX %-02.2X",*addr,opcode);
	(*addr)++;
	if (*addr>=buffersize)
		*addr=0;
	comment[0]=0;
	instr[0]=0;
 
	/* Okay, there are better ways of doing this, but hey ... who's ever
	   going to see this sourcecode other than myself ? ;-) */
	switch(opcode) {
		case 0x00 :
				strcpy(instr,"brk");
			break;
 
		case 0x01 :
				strcpy(instr,"ora ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0x02 :
				strcpy(instr,"mpy");
			break;
 
		case 0x03 :
				strcpy(instr,"tip");
			break;
 
		case 0x05:
				strcpy(instr,"ora $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x06:
				strcpy(instr,"asl $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x07:
				strcpy(instr,"rmb 0,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x08:
				strcpy(instr,"php");
			break;
 
		case 0x09:
				strcpy(instr,"ora #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0x0a:
				strcpy(instr,"asl a");
			break;
 
		case 0x0b:
				strcpy(instr,"jsb 0");
				strcpy(comment,"indirect $FFE0");
			break;
 
		case 0x0c:
				strcpy(instr,"jpi ($");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0x0d:
				strcpy(instr,"ora $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x0e:
				strcpy(instr,"asl $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x0f:
				strcpy(instr,"bbr 0,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x10:
				strcpy(instr,"bpl $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x11:
				strcpy(instr,"ora ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0x12:
				strcpy(instr,"mpa");
			break;
 
		case 0x13:
				strcpy(instr,"lab a");
			break;
 
		case 0x15:
				strcpy(instr,"ora $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x16:
				strcpy(instr,"asl $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x17:
				strcpy(instr,"rmb 1,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x18:
				strcpy(instr,"clc");
			break;
 
		case 0x19:
				strcpy(instr,"ora $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0x1a:
				strcpy(instr,"neg a");
			break;
 
		case 0x1b:
				strcpy(instr,"jsb 1");
				strcpy(comment,"indirect $FFE2");
			break;
 
		case 0x1d:
				strcpy(instr,"ora $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x1e:
				strcpy(instr,"asl $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x1f:
				strcpy(instr,"bbr 1,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x20:
				strcpy(instr,"jsr $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x21:
				strcpy(instr,"and ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0x22:
				strcpy(instr,"psh");
			break;
 
		case 0x23:
				strcpy(instr,"phw");
			break;
 
		case 0x24:
				strcpy(instr,"bit $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x25:
				strcpy(instr,"and $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x26:
				strcpy(instr,"rol $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x27:
				strcpy(instr,"rmb 2,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x28:
				strcpy(instr,"plp");
			break;
 
		case 0x29:
				strcpy(instr,"and #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0x2a:
				strcpy(instr,"rol a");
			break;
 
		case 0x2b:
				strcpy(instr,"jsb 2");
				strcpy(comment,"indirect $FFE4");
			break;
 
		case 0x2c:
				strcpy(instr,"bit $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x2d:
				strcpy(instr,"and $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x2e:
				strcpy(instr,"rol $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x2f:
				strcpy(instr,"bbr 2,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x30:
				strcpy(instr,"bmi $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x31:
				strcpy(instr,"and ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0x32:
				strcpy(instr,"pul");
			break;
 
		case 0x33:
				strcpy(instr,"plw");
			break;
 
		case 0x35:
				strcpy(instr,"and $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x36:
				strcpy(instr,"rol $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x37:
				strcpy(instr,"rmb 3,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x38:
				strcpy(instr,"sec");
			break;
 
		case 0x39:
				strcpy(instr,"and $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0x3a:
				strcpy(instr,"asr a");
			break;
 
		case 0x3b:
				strcpy(instr,"jsb 3");
				strcpy(comment,"indirect $FFE6");
			break;
 
		case 0x3d:
				strcpy(instr,"and $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x3e:
				strcpy(instr,"rol $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x3f:
				strcpy(instr,"bbr 3,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x40:
				strcpy(instr,"rti");
			break;
 
		case 0x41:
				strcpy(instr,"eor ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0x42:
				strcpy(instr,"rnd");
			break;
 
		case 0x45:
				strcpy(instr,"eor $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x46:
				strcpy(instr,"lsr $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x47:
				strcpy(instr,"rmb 4,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x48:
				strcpy(instr,"pha");
			break;
 
		case 0x49:
				strcpy(instr,"eor #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0x4a:
				strcpy(instr,"lsr a");
			break;
 
		case 0x4b:
				strcpy(instr,"jsb 4");
				strcpy(comment,"indirect $FFE8");
			break;
 
		case 0x4c:
				strcpy(instr,"jmp $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x4d:
				strcpy(instr,"eor $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x4e:
				strcpy(instr,"lsr $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x4f:
				strcpy(instr,"bbr 4,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x50:
				strcpy(instr,"bvc $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x51:
				strcpy(instr,"eor ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0x52:
				strcpy(instr,"clw");
			break;
 
		case 0x55:
				strcpy(instr,"eor $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x56:
				strcpy(instr,"lsr $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x57:
				strcpy(instr,"rmb 5,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x58:
				strcpy(instr,"cli");
			break;
 
		case 0x59:
				strcpy(instr,"eor $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0x5a:
				strcpy(instr,"phy");
			break;
 
		case 0x5b:
				strcpy(instr,"jsb 5");
				strcpy(comment,"indirect $FFEA");
			break;
 
		case 0x5d:
				strcpy(instr,"eor $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x5e:
				strcpy(instr,"lsr $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x5f:
				strcpy(instr,"bbr 5,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x60:
				strcpy(instr,"rts");
			break;
 
		case 0x61:
				strcpy(instr,"adc ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0x62:
				strcpy(instr,"taw");
			break;
 
		case 0x64:
				strcpy(instr,"add $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x65:
				strcpy(instr,"adc $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x66:
				strcpy(instr,"ror $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x67:
				strcpy(instr,"rmb 6,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x68:
				strcpy(instr,"pla");
			break;
 
		case 0x69:
				strcpy(instr,"adc #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0x6a:
				strcpy(instr,"ror a");
			break;
 
		case 0x6b:
				strcpy(instr,"jsb 6");
				strcpy(comment,"indirect $FFEC");
			break;
 
		case 0x6c:
				strcpy(instr,"jmp ($");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0x6d:
				strcpy(instr,"adc $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x6e:
				strcpy(instr,"ror $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x6f:
				strcpy(instr,"bbr 6,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x70:
				strcpy(instr,"bvs $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x71:
				strcpy(instr,"adc ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0x72:
				strcpy(instr,"twa");
			break;
 
		case 0x74:
				strcpy(instr,"add $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x75:
				strcpy(instr,"adc $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x76:
				strcpy(instr,"ror $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x77:
				strcpy(instr,"rmb 7,");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x78:
				strcpy(instr,"sei");
			break;
 
		case 0x79:
				strcpy(instr,"adc $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0x7a:
				strcpy(instr,"ply");
			break;
 
		case 0x7b:
				strcpy(instr,"jsb 7");
				strcpy(comment,"indirect $FFEE");
			break;
 
		case 0x7c:
				strcpy(instr,"jmp $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x7d:
				strcpy(instr,"adc $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x7e:
				strcpy(instr,"ror $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x7f:
				strcpy(instr,"bbr 7,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x80:
				strcpy(instr,"bra $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x81:
				strcpy(instr,"sta ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0x84:
				strcpy(instr,"sty $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x85:
				strcpy(instr,"sta $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x86:
				strcpy(instr,"stx $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x87:
				strcpy(instr,"smb 0,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x88:
				strcpy(instr,"dey");
			break;
 
		case 0x89:
				strcpy(instr,"add #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0x8a:
				strcpy(instr,"txa");
			break;
 
		case 0x8b:
				strcpy(instr,"nxt");
			break;
 
		case 0x8c:
				strcpy(instr,"sty $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x8d:
				strcpy(instr,"sta $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x8e:
				strcpy(instr,"stx $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0x8f:
				strcpy(instr,"bbs 0,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x90:
				strcpy(instr,"bcc $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0x91:
				strcpy(instr,"sta ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0x94:
				strcpy(instr,"sty $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x95:
				strcpy(instr,"sta $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x96:
				strcpy(instr,"stx $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0x97:
				strcpy(instr,"smb 1,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0x98:
				strcpy(instr,"tya");
			break;
 
		case 0x99:
				strcpy(instr,"sta $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0x9a:
				strcpy(instr,"txs");
			break;
 
		case 0x9b:
				strcpy(instr,"lii");
			break;
 
		case 0x9d:
				strcpy(instr,"sta $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0x9f:
				strcpy(instr,"bbs 1,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xa0:
				strcpy(instr,"ldy #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0xa1:
				strcpy(instr,"lda ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0xa2:
				strcpy(instr,"ldx #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0xa4:
				strcpy(instr,"ldy $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xa5:
				strcpy(instr,"lda $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xa6:
				strcpy(instr,"ldx $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xa7:
				strcpy(instr,"smb 2,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xa8:
				strcpy(instr,"tay");
			break;
 
		case 0xa9:
				strcpy(instr,"lda #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0xaa:
				strcpy(instr,"tax");
			break;
 
		case 0xab:
				strcpy(instr,"lan");
			break;
 
		case 0xac:
				strcpy(instr,"ldy $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xad:
				strcpy(instr,"lda $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xae:
				strcpy(instr,"ldx $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xaf:
				strcpy(instr,"bbs 2,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xb0:
				strcpy(instr,"bcs $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xb1:
				strcpy(instr,"lda ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0xb2:
				strcpy(instr,"sti #$");
				get_byte(addr,buf,string,instr,comment,0);
				strcat(instr,",$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xb4:
				strcpy(instr,"ldy $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xb5:
				strcpy(instr,"lda $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xb6:
				strcpy(instr,"ldx $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0xb7:
				strcpy(instr,"smb 3,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xb8:
				strcpy(instr,"clv");
			break;
 
		case 0xb9:
				strcpy(instr,"lda $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0xba:
				strcpy(instr,"tsx");
			break;
 
		case 0xbb:
				strcpy(instr,"ini");
			break;
 
		case 0xbc:
				strcpy(instr,"ldy $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xbd:
				strcpy(instr,"lda $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xbe:
				strcpy(instr,"lda $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0xbf:
				strcpy(instr,"bbs 3,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xc0:
				strcpy(instr,"cpy #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0xc1:
				strcpy(instr,"cmp ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0xc2:
				strcpy(instr,"rba $");
				get_byte(addr,buf,string,instr,comment,0);
				strcat(instr,",$");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xc4:
				strcpy(instr,"cpy $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xc5:
				strcpy(instr,"cmp $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xc6:
				strcpy(instr,"dec $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xc7:
				strcpy(instr,"smb 4,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xc8:
				strcpy(instr,"iny");
			break;
 
		case 0xc9:
				strcpy(instr,"cmp #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0xca:
				strcpy(instr,"dex");
			break;
 
		case 0xcb:
				strcpy(instr,"phi");
			break;
 
		case 0xcc:
				strcpy(instr,"cpy $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xcd:
				strcpy(instr,"cmp $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xce:
				strcpy(instr,"dec $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xcf:
				strcpy(instr,"bbs 4,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xd0:
				strcpy(instr,"bne $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xd1:
				strcpy(instr,"cmp ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0xd2:
				strcpy(instr,"sba $");
				get_byte(addr,buf,string,instr,comment,0);
				strcat(instr,",$");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xd4:
				strcpy(instr,"exc $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xd5:
				strcpy(instr,"cmp $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xd6:
				strcpy(instr,"dec $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xd7:
				strcpy(instr,"smb 5,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xd8:
				strcpy(instr,"cld");
			break;
 
		case 0xd9:
				strcpy(instr,"cmp $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0xda:
				strcpy(instr,"phx");
			break;
 
		case 0xdb:
				strcpy(instr,"pli");
			break;
 
		case 0xdd:
				strcpy(instr,"cmp $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xde:
				strcpy(instr,"dec $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xdf:
				strcpy(instr,"bbs 5,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xe0:
				strcpy(instr,"cpx #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0xe1:
				strcpy(instr,"sbc ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,")");
			break;
 
		case 0xe2:
				strcpy(instr,"bar $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_byte(addr,buf,string,instr,comment,0);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xe4:
				strcpy(instr,"cpx $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xe5:
				strcpy(instr,"sbc $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xe6:
				strcpy(instr,"inc $");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xe7:
				strcpy(instr,"smb 6,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xe8:
				strcpy(instr,"inx");
			break;
 
		case 0xe9:
				strcpy(instr,"sbc #$");
				get_byte(addr,buf,string,instr,comment,0);
			break;
 
		case 0xea:
				strcpy(instr,"nop");
			break;
 
		case 0xeb:
				strcpy(instr,"lai");
			break;
 
		case 0xec:
				strcpy(instr,"cpx $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xed:
				strcpy(instr,"sbc $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xee:
				strcpy(instr,"inc $");
				get_word(addr,buf,string,instr,comment,1);
			break;
 
		case 0xef:
				strcpy(instr,"bbs 6,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xf0:
				strcpy(instr,"beq $");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xf1:
				strcpy(instr,"sbc ($");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,"),x");
			break;
 
		case 0xf2:
				strcpy(instr,"bas $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_byte(addr,buf,string,instr,comment,0);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		case 0xf5:
				strcpy(instr,"sbc $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xf6:
				strcpy(instr,"inc $");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xf7:
				strcpy(instr,"smb 7,$");
				get_byte(addr,buf,string,instr,comment,1);
			break;
 
		case 0xf8:
				strcpy(instr,"sed");
			break;
 
		case 0xf9:
				strcpy(instr,"sbc $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",y");
			break;
 
		case 0xfa:
				strcpy(instr,"plx");
			break;
 
		case 0xfb:
				strcpy(instr,"pia");
			break;
 
		case 0xfd:
				strcpy(instr,"sbc $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xfe:
				strcpy(instr,"inc $");
				get_word(addr,buf,string,instr,comment,1);
				strcat(instr,",x");
			break;
 
		case 0xff:
				strcpy(instr,"bbs 7,$");
				get_byte(addr,buf,string,instr,comment,1);
				strcat(instr,",$");
				get_relative(addr,buf,string,instr,comment);
			break;
 
		default :
			strcpy(instr,"???");
			strcpy(comment,"undocumented opcode");
	}
 
	while(strlen(string)<22)
		strcat(string," ");
 
	while(strlen(instr)<22)
		strcat(instr," ");
 
	/* add delimiting semicolon if this line has a comment */
	if (strlen(comment))
		strcat(instr,";");
 
	/* uppercase instruction if desired */
	if (instrupper)
		strupr(instr);
 
	strcat(string,instr);
	strcat(string,comment);
}
 
/*
	*** Fetch one byte, increment address, and appends ASCII value of byte
	*** to string1 (with leading space) and string2 (no leading space)
	*** If isaddr is non-zero, the byte is taken to be a zero page address
	*** and is passed to the analyze_address function for commentary if
	*** applicable.
*/
unsigned char get_byte(unsigned long *addr,unsigned char huge *buf,char *string1,char *string2,char *comment,char isaddr)
{
	char tmps[5];
	unsigned char mybyte=buf[*addr];
	(*addr)++;
	if (*addr>=buffersize)
		*addr=0;
	sprintf(tmps," %-02.2X",mybyte);
	strcat(string1,tmps);
	sprintf(tmps,"%-02.2X",mybyte);
	strcat(string2,tmps);
	if(isaddr)
		analyze_address((unsigned int) mybyte,comment);
	return mybyte;
}
 
/*
	*** Fetch one word, increment address, and appends ASCII value of byte
	*** to string1 (with whitespace) and string2 (no spaces)
	*** If isaddr is non-zero, the word is taken to be a memory address
	*** and is passed to the analyze_address function for commentary if
	*** applicable.
*/
unsigned int get_word(unsigned long *addr,unsigned char huge *buf,char *string1,char *string2,char *comment,char isaddr)
{
	char tmps[7];
	unsigned int myword=buf[*addr];
	(*addr)++;
	if (*addr>=buffersize)
		*addr=0;
	myword+=(unsigned int) (buf[*addr]) << 8;
	(*addr)++;
	if (*addr>=buffersize)
		*addr=0;
	sprintf(tmps," %-02.2X %-02.2X",myword & 0xff,(myword & 0xff00) >> 8);
	strcat(string1,tmps);
	sprintf(tmps,"%-04.4X",myword);
	strcat(string2,tmps);
	if(isaddr)
		analyze_address(myword,comment);
	return myword;
}
 
/*
	*** Analyze 16-bit address and add commentary
	*** NB : Datapump comments override Cx9 internal hardware comments
*/
void analyze_address(unsigned int addr,char *comment)
{
	/* analyze hardware */
	if (showhardware!=HW_NONE && addr<0x800)
	{
		/* one-size-fits-all message */
		strcpy(comment,"internal to microcontroller");
 
		if (addr<0x800 && addr>=0x600)
			strcpy(comment,"Cx9 part of ES4 RAM");
		if (addr<0x600 && addr>=0x500)
			strcpy(comment,"Cx9 page 5 (UNAVAILABLE)");
		if (addr<0x500 && addr>=0x480) {
			strcpy(comment,"CRC control area");
		}
 
		/* analyze Cx9 addresses common to all hardware modes */
		if (addr<0x20)
			strcpy(comment,seekstring(addr,cx9_00_1f));
		else if (addr>=0x20 && addr <0x33 ) {
			if (showhardware==HW_GP)
				strcpy(comment,seekstring(addr-0x20,cx9_20_32_g));
			else if (showhardware==HW_UART)
				strcpy(comment,seekstring(addr-0x20,cx9_20_32_u));
		}
		else if (addr>=0x33 && addr<0x40)
			strcpy(comment,seekstring(addr-0x33,cx9_33_3f));
		else if (addr>=0x40 && addr<0x80)
			strcpy(comment,"Cx9 page 1 segment address");
		else if (addr>=0x80 && addr<0x100)
			strcpy(comment,"Cx9 page 0 internal RAM");
		else if (addr>=0x100 && addr<0x200)
			strcpy(comment,"Cx9 page 1 internal RAM");
		else if (addr>=0x200 && addr<0x300)
			strcpy(comment,"Cx9 page 2 internal RAM");
		else if (addr>=0x300 && addr<0x400)
			strcpy(comment,"Cx9 page 3 internal RAM");
		else if (addr>=0x400 && addr<0x480)
			strcpy(comment,"Cx9 page 4 internal RAM");
		else if (addr==0x480)
			strcpy(comment,"Cx9 CRC result low/input buffer");
		else if (addr==0x481)
			strcpy(comment,"Cx9 CRC result hi/initialize");
		else if (addr>=0x482 && addr<0x500)
			strcpy(comment,"Cx9 CRC control area");
	}
 
								/*  *********************************  */
	/* analyze datapump */
	if (datapump!=DP_NONE && addr>=datapump_addr && addr<=(datapump_addr+datapump_len) && dp_comments!=NULL)
	{
		strcpy(comment,seekstring(addr-datapump_addr,dp_comments));
	}
}
 
/*
	*** Dump one line full of bytes in hex and ASCII - 16 bytes
*/
void dumpline(unsigned long *addr,unsigned char huge *buf,char *string)
{
	unsigned char asciistr[17];
	unsigned char hexstr[80];
	unsigned char tmps[10];
 
	sprintf(string,"%-06.6lX  ",*addr);
	hexstr[0]=0;
 
	for (int i=0;i<16;i++)
	{
		/* add character to ASCII string */
		if(buf[*addr]>=32)
			asciistr[i]=buf[*addr];
		else
			asciistr[i]='.';
 
		/* add character to hex string */
		sprintf(tmps," %-02.2X",buf[*addr]);
		strcat(hexstr,tmps);
 
		(*addr)++;
		if (*addr>=buffersize)
			*addr=0;
	}
	asciistr[16]=0;
	strcat(string,asciistr);
	strcat(string," ");
	strcat(string,hexstr);
}
 
/*
	*** Fetch single-byte relative address, increment address, and build
	*** instruction and dump strings
*/
void get_relative(unsigned long *addr,unsigned char huge *buf,char *string1,char *string2,char *comment)
{
	char tmps[8];
	unsigned long tmpadd;
	signed long tmpofs;
 
	/* get byte, increment address with wraparound, and update dump string */
	tmpofs=(signed long) (signed char) get_byte(addr,buf,string1,string2,comment,0);
 
 
	/* remove byte from instruction string */
	string2[strlen(string2)-2]=0;
 
 
	/* generate address */
	tmpadd=(*addr)+tmpofs;
	sprintf(tmps,"%-06.06lx",tmpadd);
	strcat(string2,tmps);
 
 
	/* add offset comment IF there is no preexisting location comment */
	if (tmpofs>=0 && !strlen(comment))
		sprintf(comment,"offset +$%-02.02lX",tmpofs & 0xff);
	else if (!strlen(comment))
		sprintf(comment,"offset -$%-02.02lX",(0-tmpofs) & 0xff);
}
 
/*
	*** Seek (position) zero entries down (string)
*/
char *seekstring(int position,const char *string)
{
	int countsleft=position;
	const char *p=string;
 
	while (countsleft)
	{
		while (*p) p++;
		p++;
		countsleft--;
	}
	return (char *) p;
}
 
/*
	*** Critical error handler ***
*/
#pragma warn -par
int criticalhandler(int errval,int ax,int bp,int si)
{
	hardretn(-1);
	return -1;
}


zws.com and all original content herein is © Copyright 2002 by Lewin A.R.W. Edwards. "zws.com" is a trademark protected under U.S. and international law. Infringement or attempted dilution of the intellectual property rights held by Lewin A.R.W. Edwards will be prosecuted to the fullest possible extent.