[comp.sources.amiga] v02i053: dis6502 - disassemble 6502 object code

page@swan.ulowell.edu (Bob Page) (11/05/88)

Submitted-by: finkel@taurus.BITNET (Udi Finkelstein)
Posting-number: Volume 2, Issue 53
Archive-name: applications/dis6502.1

Dis6502 disassembles 6502 binary files.  Binary formats understood
include C64, Atari and boot files.  Equate and control files can be
included to name well-known locations and to control the disassembly
process.  The output includes a cross reference.

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	Makefile
#	Makefile.unix
#	c64.predefs
#	dis.1
#	dis.h
#	dis.notes
#	initopts.c
#	lex.c
#	lex.l
#	main.c
#	print.c
#	ref.c
#	tbl.c
# This archive created: Fri Nov  4 17:33:09 1988
cat << \SHAR_EOF > Makefile
OBJS = main.o initopts.o lex.o ref.o print.o tbl.o
SRCS = dis.h main.c initopts.c lex.l ref.c print.c tbl.c 
CFLAGS = +p -n  -DAMIGA


dis:		$(OBJS)
		ln -g $(OBJS) -o dis -lcl32

tbl.o:		dis.h tbl.c

initopts.o:	dis.h initopts.c

main.o:		dis.h main.c

lex.c:		lex.l

lex.o:		lex.c dis.h

ref.o:		dis.h ref.c

print.o:	dis.h print.c

SHAR_EOF
cat << \SHAR_EOF > Makefile.unix
OBJS = main.o initopts.o lex.o ref.o print.o tbl.o
SRCS = dis.h main.c initopts.c lex.l ref.c print.c tbl.c 
CFLAGS = -O

dis:		$(OBJS)
		cc $(OBJS) -o dis

tbl.o:		dis.h tbl.c
		cc -c tbl.c

initopts.o:	dis.h initopts.c

main.o:		dis.h main.c

lex.o:		lex.c

lex.c:		dis.h lex.l

ref.o:		dis.h ref.c

print.o:	dis.h print.c

dis.man:	dis.1
		nroff -man dis.1 > dis.man

install:	dis
		cp dis /a/rgb/bin/dis6502

clean:
		rm -f $(OBJS) lex.c dis.man

clobber:	clean
		rm -f dis

ckpt:		$(SRCS)
		ci -l $(SRCS)

lint: dis.h main.c initopts.c lex.c ref.c print.c tbl.c 
		lint  dis.h main.c initopts.c lex.c ref.c print.c tbl.c 

shar:		Makefile dis.1 $(SRCS)
		shar -f shar Makefile dis.1 $(SRCS)
SHAR_EOF
cat << \SHAR_EOF > c64.predefs
1	CINT		.EQ	$FF81
2	IOINIT		.EQ	$FF84
3	RAMTAS		.EQ	$FF87
4	RESTOR		.EQ	$FF8A
5	VECTOR		.EQ	$FF8D
6	SETMSG		.EQ	$FF90
7	SECOND		.EQ	$FF93
8	TKSA		.EQ	$FF96
9	MEMTOP		.EQ	$FF99
10	MEMBOT		.EQ	$FF9C
11	SCNKEY		.EQ	$FF9F
12	SETTMO		.EQ	$FFA2
13	ACPTR		.EQ	$FFA5
14	CIOUT		.EQ	$FFA8
15	UNTLK		.EQ	$FFAB
16	UNLSN		.EQ	$FFAE
17	LISTEN		.EQ	$FFB1
18	TALK		.EQ	$FFB4
19	READST		.EQ	$FFB7
20	SETLFS		.EQ	$FFBA
21	SETNAM		.EQ	$FFBD
22	OPEN		.EQ	$FFC0
23	CLOSE		.EQ	$FFC3
24	CHKIN		.EQ	$FFC6
25	CHKOUT		.EQ	$FFC9
26	CLRCHN		.EQ	$FFCC
27	CHRIN		.EQ	$FFCF
28	CHROUT		.EQ	$FFD2
29	LOAD		.EQ	$FFD5
30	SAVE		.EQ	$FFD8
31	SETTIM		.EQ	$FFDB
32	RDTIME		.EQ	$FFDE
33	STOP		.EQ	$FFE1
34	GETIN		.EQ	$FFE4
35	CLALL		.EQ	$FFE7
36	UDTIME		.EQ	$FFEA
37	SCREEN		.EQ	$FFED
38	PLOT		.EQ	$FFF0
39	IOBASE		.EQ	$FFF3

40	IERRORLO	.EQ	$0300
41	IERRORHI	.EQ	$0301
42	IMAINLO		.EQ	$0302
43	IMAINHI		.EQ	$0303
44	ICRNCHLO	.EQ	$0304
45	ICRNCHHI	.EQ	$0305
46	IQPLOPLO	.EQ	$0306
47	IQPLOPHI	.EQ	$0307
48	IGONELO		.EQ	$0308
49	IGONEHI		.EQ	$0309
50	IEVALLO		.EQ	$030A
51	IEVALHI		.EQ	$030B
52	SAREG		.EQ	$030C
53	SXREG		.EQ	$030D
54	SYREG		.EQ	$030E
55	SPREG		.EQ	$030F
56	USRPOK		.EQ	$0310
57	USRADDLO	.EQ	$0311
58	USRADDHI	.EQ	$0312
59	CINVLO		.EQ	$0314
60	CINVHI		.EQ	$0315
61	CBINVLO		.EQ	$0316
62	CBINVHI		.EQ	$0317
63	NMINVLO		.EQ	$0318
64	NMINVHI		.EQ	$0319
65	IOPENLO		.EQ	$031A
66	IOPENHI		.EQ	$031B
67	ICLOSELO	.EQ	$031C
68	ICLOSEHI	.EQ	$031D
69	ICKINLO		.EQ	$031E
70	ICKINHI		.EQ	$031F
71	ICKOUTLO	.EQ	$0320
72	ICKOUTHI	.EQ	$0321
73	ICLRCHLO	.EQ	$0322
74	ICLRCHHI	.EQ	$0323
75	IBASINLO	.EQ	$0324
76	IBASINHI	.EQ	$0325
77	IBSOUTLO	.EQ	$0326
78	IBSOUTHI	.EQ	$0327
79	ISTOPLO		.EQ	$0328
80	ISTOPHI		.EQ	$0329
81	IGETINLO	.EQ	$032A
82	IGETINHI	.EQ	$032B
83	ICLALLLO	.EQ	$032C
84	ICLALLHI	.EQ	$032D
85	USRCMDLO	.EQ	$032E
86	USRCMDHI	.EQ	$032F
87	ILOADLO		.EQ	$0330
88	ILOADHI		.EQ	$0331
89	ISAVELO		.EQ	$0332
90	ISAVEHI		.EQ	$0333

91	TBUFFER		.EQ	$033C
92	VICSCN		.EQ	$0400
SHAR_EOF
cat << \SHAR_EOF > dis.1
.TH DIS6502 1 "1 OCT 1986"
.UC 4
.SH NAME
dis6502 \- Disassemble 6502 object code
.SH SYNOPSIS
.I dis6502
[
.I \-b 
]
[
.I -p \fIpfile\fP 
]
.I file
.LP
.SH DESCRIPTION
.I  Dis6502
disassembles 6502 binary files.  Binary formats understood include
Atari binary files (L menu command) and boot files.
Equate and control files can be included via the
.I -p
option to name well known locations and to control the disassembly
process.  The output includes a cross reference.
.PP
The disassembly process is a two pass operation:  First the program
flow is traced starting with the init and run parameters in the file
headers.  The dump routine then prints out the information.
.PP
The command line options are:
.TP
.I \-b
Assume that the file is a boot file, not a load file.
.TP
.I \-p \fIpfile\fP 
Read in the predefine file \fIpfile\fP.
Up to 20 \fI-p\fP options may be included.
.PP
Lines in pfile consist of:
.PP
 lineno name .eq number
.PP
 .stop number
.PP
 .trace number
.PP 
.I Lineno
refers to a decimal number.  
.I Number 
may be a decimal number or
may be a hexadecimal number (the first character of the number
should be "$").  For example, "$21b5" is
the hexadecimal number 21b5.
.I Name
is a sequence of numbers and characters starting with a
letter.
.I .trace 
causes
the trace process to continue at the address given.  
.I .stop
causes the
trace process to stop at the address given.
.SH AUTHOR
Robert Bond
.SH BUGS
SHAR_EOF
cat << \SHAR_EOF > dis.h
#include <stdio.h>

#define NPREDEF 10

extern char *predef[];
extern int  npredef;
extern char *file;
extern char *progname;
extern int  bopt;
#ifndef AMIGA
extern unsigned char f[];
extern unsigned char d[];
#else
extern unsigned char *d,*f;
#endif

#define getword(x) (d[x] + (d[x+1] << 8))
#define getbyte(x) (d[x])

/* f bits */

#define LOADED 1			/* Location loaded */
#define JREF   2			/* Referenced as jump/branch dest */
#define DREF   4			/* Referenced as data */
#define SREF   8			/* Referenced as subroutine dest */
#define NAMED  0x10			/* Has a name */
#define TDONE  0x20			/* Has been traced */
#define ISOP   0x40			/* Is a valid instruction opcode */

struct info {
	char opn[4];
	int  nb;
	int  flag;
};

extern struct info optbl[];

/* Flags */

/* Where control goes */

#define NORM 1
#define JUMP 2
#define FORK 4
#define STOP 8

#define CTLMASK (NORM|JUMP|FORK|STOP)

/* Instruction format */

#define IMM  0x20
#define ABS  0x40
#define ACC  0x80
#define IMP  0x100
#define INX  0x200
#define INY  0x400
#define ZPX  0x800
#define ABX  0x1000
#define ABY  0x2000
#define REL  0x4000
#define IND  0x8000
#define ZPY  0x10000
#define ZPG  0x20000
#define ILL  0x40000

#define ADRMASK (IMM|ABS|ACC|IMP|INX|INY|ZPX|ABX|ABY|REL|IND|ZPY|ZPG|ILL)

struct ref_chain {
	struct ref_chain *next;
	int who;
};

struct ref_chain *get_ref();
char *get_name();

/* lex junk */

#define EQ 256
#define NUMBER 257
#define NAME 258
#define COMMENT 259
#define LI 260
#define TSTART 261
#define TSTOP 262

extern FILE *yyin, *yyout;
int lineno;

int yywrap(), yyerror();
char *emalloc();

typedef union  {
	int ival;
	char *sval;
} VALUE;

extern VALUE token;
SHAR_EOF
cat << \SHAR_EOF > dis.notes



       Some notes about Robert Bond's 'dis' program, Amiga version.



This  is a quick & dirty port of a 6502 reverse assembler I that I had under
my  hand  for a long time.  I didn't bother optimizing the stuff too much, I
just  wanted to see it working.  This is the sort of 'dirty' ports where you
first  compiler  the  original file, then watch the compiler errors, and fix
the errors in the file, without looking anywhere else in it.  Therefor:

1)  'dis'  requires  C:Sort  (  too much bother to replace ) & C:Type ( I AM
    lazy!!!)

2)  I  still  don't  understand  why  are  the  line  numbers  needed in the
    c64.predef file. I don't have much UNIX experience, and no experience at
    all with lex. lex code is like chinese to  me, but  reading  the  perdef
    I think that the line numbers are ignored and are used  only  to  easily
    identify '.eq' lines.

3)  The program  is recursive, too  much recursive!  the trace routine calls
    itself not only on branches, but every instruction! large stacks (  even
    50K isn't too much for large programs ), are welcomed... I  will  modify
    this as soon as I'll have time. it should be easy to remove recursion in
    the non branch/jmp instructions. branches must have recursion.

I also enhanced the original package, and added support for c64 binary file,
which  wasn't there before.  ( It had only ATARI load/boot files ).  The C64
file format was much simpler than those other 2 formats.  To select C64 file
format, use the '-c' flag.  I also included a c64.predefs file with some C64
constant  addresses.  Also, FYI, lex.c was generated on a SUN from lex.l and
then downloaded to the Amiga.  lex.c was also __edited__ before compilation.
I  know  that  it's  a  no-no  to  edit  machine-generated files, but it was
necessary.


Udi Finkelstein

10 Glitzenstein st.
Tel Aviv 64686 Israel
Phone: 972-3-263-927

BITNET:     finkel@taurus.BITNET                     ( Best )
UUCP:       ...!uunet!ulysses!attibr!althea!finkel   ( Try avoiding this )
ARPA:       finkel%taurus@cunyvm.cuny.edu            ( Same as BITNET )
FIDO:       Udi Finkelstein ( At 2:40/117 or 2:40/135
                              If you can get there at all!)
SHAR_EOF
cat << \SHAR_EOF > initopts.c

/* 
 * 
 *  dis [-p predefineds] file
 *
 *  The -p option may be repeated.
 */

#include "dis.h"

char *predef[NPREDEF];
int  npredef = 0;
char *file;
char *progname = "dis";
int  bopt = 0;

initopts(argc,argv)
int argc;
char *argv[];
{
    int ai;
    char *ca;
    int fileset = 0;

    progname = argv[0];

    while (--argc) {
        if ((*++argv)[0] == '-') {
	    ca = *argv;
	    for(ai = 1; ca[ai] != '\0'; ai++)
                switch (ca[ai]) {
                case 'p':
		    predef[npredef] = *++argv;
		    npredef++;
                    argc--;
                    break;
		case 'b':
		    bopt = 1;
		    break;

		case 'c':
			bopt = 2;
			break;
                default: crash("Invalid option letter");
                }
        } else if (!fileset) {
	    file = *argv;
	    fileset++;
	} else crash("Usage: [-{c|b}] [-p predef] file");
    }
    if (!fileset)
	 crash("Usage: [-{c|b}] [-p predef] file");
}
SHAR_EOF
cat << \SHAR_EOF > lex.c
# include "stdio.h"
# define U(x) x
# define NLSTATE yyprevious=YYNEWLINE
# define BEGIN yybgin = yysvec + 1 +
# define INITIAL 0
# define YYLERR yysvec
# define YYSTATE (yyestate-yysvec-1)
# define YYOPTIM 1
# define YYLMAX BUFSIZ
# define output(c) putc(c,yyout)
# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
# define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;}
# define yymore() (yymorfg=1)
# define ECHO fprintf(yyout, "%s",yytext)
# define REJECT { nstr = yyreject(); goto yyfussy;}
int yyleng; extern char yytext[];
int yymorfg;
extern char *yysptr, yysbuf[];
int yytchar;
FILE *yyin = {stdin}, *yyout = {stdout};
extern int yylineno;
struct yysvf { 
	struct yywork *yystoff;
	struct yysvf *yyother;
	int *yystops;};
struct yysvf *yyestate;
extern struct yysvf yysvec[], *yybgin;
#undef ECHO
#include "dis.h"
#ifndef AMIGA
int lineno = 0;
#endif
char *strcpy();
# define YYNEWLINE 10
yylex(){
int nstr; extern int yyprevious;
while((nstr = yylook()) >= 0)
yyfussy: switch(nstr){
case 0:
if(yywrap()) return(0); break;
case 1:
{ ; }
break;
case 2:
{	lineno++;
				return '\n';
}
break;
case 3:
{ 
				return EQ;
}
break;
case 4:
{ 
				return LI;
}
break;
case 5:
{ 
				return EQ;
}
break;
case 6:
{ 
				return LI;
}
break;
case 7:
{
				return TSTART;
}
break;
case 8:
{
				return TSTOP;
}
break;
case 9:
{
				(void)sscanf(yytext, "%d", &token.ival); 
				return NUMBER;
}
break;
case 10:
{
				(void)sscanf(yytext+1, "%x", &token.ival);
				return NUMBER;
}
break;
case 11:
{
				token.sval = emalloc((unsigned) strlen(yytext)+1);
				(void)strcpy((char *)token.sval, (char *)yytext);
				return NAME;
}
break;
case 12:
{
				return COMMENT;
}
break;
case 13:
		{ return yytext[0]; }
break;
case -1:
break;
default:
fprintf(yyout,"bad switch yylook %d",nstr);
} return(0); }
/* end of yylex */

char *
emalloc(n)
unsigned n;
{
	char *ptr, *malloc();

	if ((ptr = malloc(n)) == (char *) 0) {
		(void) fprintf(stderr,"out of core");
		exit(1);
	}
	return ptr;
}
int yyvstop[] = {
0,

13,
0,

1,
13,
0,

2,
0,

13,
0,

12,
13,
0,

13,
0,

9,
13,
0,

11,
13,
0,

10,
0,

12,
0,

9,
0,

11,
0,

3,
0,

4,
0,

5,
0,

6,
0,

8,
0,

7,
0,
0};
# define YYTYPE char
struct yywork { YYTYPE verify, advance; } yycrank[] = {
0,0,	0,0,	1,3,	0,0,	
0,0,	0,0,	0,0,	0,0,	
0,0,	0,0,	1,4,	1,5,	
0,0,	0,0,	0,0,	0,0,	
0,0,	0,0,	0,0,	0,0,	
7,12,	0,0,	0,0,	0,0,	
0,0,	0,0,	0,0,	0,0,	
7,12,	7,0,	12,0,	0,0,	
0,0,	0,0,	0,0,	0,0,	
0,0,	1,6,	2,6,	0,0,	
0,0,	0,0,	0,0,	1,7,	
2,7,	0,0,	0,0,	1,8,	
2,8,	1,9,	0,0,	0,0,	
0,0,	0,0,	0,0,	0,0,	
6,11,	6,11,	6,11,	6,11,	
6,11,	6,11,	6,11,	6,11,	
6,11,	6,11,	1,10,	7,12,	
0,0,	0,0,	0,0,	0,0,	
1,10,	6,11,	6,11,	6,11,	
6,11,	6,11,	6,11,	8,13,	
0,0,	0,0,	0,0,	0,0,	
7,12,	0,0,	8,14,	0,0,	
0,0,	0,0,	7,12,	0,0,	
0,0,	14,22,	0,0,	0,0,	
1,3,	0,0,	0,0,	0,0,	
0,0,	13,21,	0,0,	0,0,	
0,0,	6,11,	6,11,	6,11,	
6,11,	6,11,	6,11,	8,15,	
0,0,	0,0,	7,12,	0,0,	
0,0,	0,0,	8,16,	0,0,	
0,0,	0,0,	26,28,	0,0,	
0,0,	8,17,	8,18,	9,19,	
9,19,	9,19,	9,19,	9,19,	
9,19,	9,19,	9,19,	9,19,	
9,19,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	15,23,	
16,24,	17,25,	18,26,	25,27,	
27,29,	28,30,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
30,31,	0,0,	0,0,	0,0,	
10,20,	0,0,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
10,20,	10,20,	10,20,	10,20,	
0,0};
struct yysvf yysvec[] = {
0,	0,	0,
yycrank+-1,	0,		0,	
yycrank+-2,	yysvec+1,	0,	
yycrank+0,	0,		yyvstop+1,
yycrank+0,	0,		yyvstop+3,
yycrank+0,	0,		yyvstop+6,
yycrank+8,	0,		yyvstop+8,
yycrank+-19,	0,		yyvstop+10,
yycrank+10,	0,		yyvstop+13,
yycrank+79,	0,		yyvstop+15,
yycrank+89,	0,		yyvstop+18,
yycrank+0,	yysvec+6,	yyvstop+21,
yycrank+-20,	yysvec+7,	yyvstop+23,
yycrank+20,	0,		0,	
yycrank+20,	0,		0,	
yycrank+34,	0,		0,	
yycrank+43,	0,		0,	
yycrank+33,	0,		0,	
yycrank+36,	0,		0,	
yycrank+0,	yysvec+9,	yyvstop+25,
yycrank+0,	yysvec+10,	yyvstop+27,
yycrank+0,	0,		yyvstop+29,
yycrank+0,	0,		yyvstop+31,
yycrank+0,	0,		yyvstop+33,
yycrank+0,	0,		yyvstop+35,
yycrank+40,	0,		0,	
yycrank+25,	0,		0,	
yycrank+40,	0,		0,	
yycrank+54,	0,		0,	
yycrank+0,	0,		yyvstop+37,
yycrank+79,	0,		0,	
yycrank+0,	0,		yyvstop+39,
0,	0,	0};
struct yywork *yytop = yycrank+211;
struct yysvf *yybgin = yysvec+1;
char yymatch[] = {
00  ,01  ,01  ,01  ,01  ,01  ,01  ,01  ,
01  ,011 ,012 ,01  ,01  ,01  ,01  ,01  ,
01  ,01  ,01  ,01  ,01  ,01  ,01  ,01  ,
01  ,01  ,01  ,01  ,01  ,01  ,01  ,01  ,
011 ,01  ,01  ,01  ,01  ,01  ,01  ,01  ,
01  ,01  ,01  ,01  ,01  ,01  ,01  ,01  ,
'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,
'0' ,'0' ,01  ,01  ,01  ,01  ,01  ,01  ,
01  ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'G' ,
'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,
'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,
'G' ,'G' ,'G' ,01  ,01  ,01  ,01  ,'_' ,
01  ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'G' ,
'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,
'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,'G' ,
'G' ,'G' ,'G' ,01  ,01  ,01  ,01  ,01  ,
0};
char yyextra[] = {
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0};
#ifndef lint
static	char ncform_sccsid[] = "@(#)ncform 1.2 86/10/08 SMI"; /* from S5R2 1.2 */
#endif

int yylineno =1;
# define YYU(x) x
# define NLSTATE yyprevious=YYNEWLINE
char yytext[YYLMAX];
struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp;
char yysbuf[YYLMAX];
char *yysptr = yysbuf;
int *yyfnd;
extern struct yysvf *yyestate;
int yyprevious = YYNEWLINE;
yylook(){
	register struct yysvf *yystate, **lsp;
	register struct yywork *yyt;
	struct yysvf *yyz;
	int yych, yyfirst;
	struct yywork *yyr;
# ifdef LEXDEBUG
	int debug;
# endif
	char *yylastch;
	/* start off machines */
# ifdef LEXDEBUG
	debug = 0;
# endif
	yyfirst=1;
	if (!yymorfg)
		yylastch = yytext;
	else {
		yymorfg=0;
		yylastch = yytext+yyleng;
		}
	for(;;){
		lsp = yylstate;
		yyestate = yystate = yybgin;
		if (yyprevious==YYNEWLINE) yystate++;
		for (;;){
# ifdef LEXDEBUG
			if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1);
# endif
			yyt = yystate->yystoff;
			if(yyt == yycrank && !yyfirst){  /* may not be any transitions */
				yyz = yystate->yyother;
				if(yyz == 0)break;
				if(yyz->yystoff == yycrank)break;
				}
			*yylastch++ = yych = input();
			yyfirst=0;
		tryagain:
# ifdef LEXDEBUG
			if(debug){
				fprintf(yyout,"char ");
				allprint(yych);
				putchar('\n');
				}
# endif
			yyr = yyt;
			if ( (int)yyt > (int)yycrank){
				yyt = yyr + yych;
				if (yyt <= yytop && yyt->verify+yysvec == yystate){
					if(yyt->advance+yysvec == YYLERR)	/* error transitions */
						{unput(*--yylastch);break;}
					*lsp++ = yystate = yyt->advance+yysvec;
					goto contin;
					}
				}
# ifdef YYOPTIM
			else if((int)yyt < (int)yycrank) {		/* r < yycrank */
				yyt = yyr = yycrank+(yycrank-yyt);
# ifdef LEXDEBUG
				if(debug)fprintf(yyout,"compressed state\n");
# endif
				yyt = yyt + yych;
				if(yyt <= yytop && yyt->verify+yysvec == yystate){
					if(yyt->advance+yysvec == YYLERR)	/* error transitions */
						{unput(*--yylastch);break;}
					*lsp++ = yystate = yyt->advance+yysvec;
					goto contin;
					}
				yyt = yyr + YYU(yymatch[yych]);
# ifdef LEXDEBUG
				if(debug){
					fprintf(yyout,"try fall back character ");
					allprint(YYU(yymatch[yych]));
					putchar('\n');
					}
# endif
				if(yyt <= yytop && yyt->verify+yysvec == yystate){
					if(yyt->advance+yysvec == YYLERR)	/* error transition */
						{unput(*--yylastch);break;}
					*lsp++ = yystate = yyt->advance+yysvec;
					goto contin;
					}
				}
			if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){
# ifdef LEXDEBUG
				if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1);
# endif
				goto tryagain;
				}
# endif
			else
				{unput(*--yylastch);break;}
		contin:
# ifdef LEXDEBUG
			if(debug){
				fprintf(yyout,"state %d char ",yystate-yysvec-1);
				allprint(yych);
				putchar('\n');
				}
# endif
			;
			}
# ifdef LEXDEBUG
		if(debug){
			fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1);
			allprint(yych);
			putchar('\n');
			}
# endif
		while (lsp-- > yylstate){
			*yylastch-- = 0;
			if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){
				yyolsp = lsp;
				if(yyextra[*yyfnd]){		/* must backup */
					while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){
						lsp--;
						unput(*yylastch--);
						}
					}
				yyprevious = YYU(*yylastch);
				yylsp = lsp;
				yyleng = yylastch-yytext+1;
				yytext[yyleng] = 0;
# ifdef LEXDEBUG
				if(debug){
					fprintf(yyout,"\nmatch ");
					sprint(yytext);
					fprintf(yyout," action %d\n",*yyfnd);
					}
# endif
				return(*yyfnd++);
				}
			unput(*yylastch);
			}
		if (yytext[0] == 0  /* && feof(yyin) */)
			{
			yysptr=yysbuf;
			return(0);
			}
		yyprevious = yytext[0] = input();
		if (yyprevious>0)
			output(yyprevious);
		yylastch=yytext;
# ifdef LEXDEBUG
		if(debug)putchar('\n');
# endif
		}
	}
yyback(p, m)
	int *p;
{
if (p==0) return(0);
while (*p)
	{
	if (*p++ == m)
		return(1);
	}
return(0);
}
	/* the following are only used in the lex library */
yyinput(){
	return(input());
	}
yyoutput(c)
  int c; {
	output(c);
	}
yyunput(c)
   int c; {
	unput(c);
	}
SHAR_EOF
cat << \SHAR_EOF > lex.l
%{
#undef ECHO
#include "dis.h"
int lineno = 0;
char *strcpy();
%}
%%
[ \t] { ; }
[\n] {	lineno++;
				return '\n';
}
\.EQ { 
				return EQ;
}
\.LI { 
				return LI;
}
\.eq { 
				return EQ;
}
\.li { 
				return LI;
}
".trace" {
				return TSTART;
}
".stop" {
				return TSTOP;
}
[0-9]+	{
				(void)sscanf(yytext, "%d", &token.ival); 
				return NUMBER;
}
\$[A-Fa-f0-9]+ {
				(void)sscanf(yytext+1, "%x", &token.ival);
				return NUMBER;
}
[A-Za-z][A-Za-z0-9_]* {
				token.sval = emalloc((unsigned) strlen(yytext)+1);
				(void)strcpy((char *)token.sval, (char *)yytext);
				return NAME;
}
\*.* {
				return COMMENT;
}
.			{ return yytext[0]; }
%%

char *
emalloc(n)
unsigned n;
{
	char *ptr, *malloc();

	if ((ptr = malloc(n)) == (char *) 0) {
		(void) fprintf(stderr,"out of core");
		exit(1);
	}
	return ptr;
}
SHAR_EOF
cat << \SHAR_EOF > main.c
#include "dis.h"

#define NTSTART 20

char *cur_file = NULL;			/* the file thats open */
int  pre_index = 0;
int  tstart[NTSTART];			/* .trace directive keep locations */
int  tstarti = 0;

VALUE token;

#ifdef AMIGA
unsigned char *d,*f; /* Manx has a bug preventing us from declaring arrays >64K */
extern unsigned char *calloc();
#else
unsigned char d[0x10000];	 	/* The data */
unsigned char f[0x10000];		/* Flags for memory usage */ 
#endif

#define RUNLOC  0x2e0
#define INITLOC 0x2e2

main(argc, argv)
int argc;
char *argv[];
{
	int i;

#ifdef AMIGA
d = calloc(0x10000,1);
f = calloc(0x10000,1);
#endif

	initopts(argc, argv);
	if (npredef > 0) {
		cur_file = predef[0];
		pre_index++;
		yyin = fopen(cur_file, "r");
		if (!yyin)
			crash ("Cant open predefine file");
		get_predef();
	}
	switch (bopt) {
		case 0:
			loadboot();
			break;
		case 1:
			loadfile();
			break;
		case 2:
			c64loadfile();
			break;
		}
	for (i = 0; i<tstarti; i++)
		start_trace(tstart[i], "*PTRACE*");

	dumpitout();

#ifdef AMIGA
free(d);
free(f);
#endif

	exit(0);
}

crash(p)
char *p;
{
	fprintf(stderr, "%s: %s\n", progname, p);
	if (cur_file != NULL)
		fprintf(stderr, "Line %d of %s\n", lineno+1, cur_file);
#ifdef AMIGA
free(d);
free(f);
#endif
	exit(1);
}

get_predef()
{
	int loc;
	char *name;

	for(;;) 
		switch (yylex()) {
		case '\n':
			break;
		case 0:
			return;
		case TSTART:
			if (yylex() != NUMBER) 
				crash(".trace needs a number operand");
			loc = token.ival;
			if (loc > 0x10000 || loc < 0)
				crash("Number out of range");
			if (tstarti == NTSTART) 
				crash("Too many .trace directives");
			tstart[tstarti++] = loc;
			while (yylex() != '\n')
				;
			break;
		case TSTOP:
			if (yylex() != NUMBER) 
				crash(".stop needs a number operand");
			loc = token.ival;
			if (loc > 0x10000 || loc < 0)
				crash("Number out of range");
			f[loc] |= TDONE;
			while (yylex() != '\n')
				;
			break;
		case NUMBER:
			switch (yylex()) {
			case LI:
			case COMMENT:
				while (yylex() != '\n')
					;
				break;
			case '\n':
				break;
			case NAME:
				name = token.sval;
				if (yylex() != EQ) 
					crash("Only EQ and LI supported in defines file");
				if (yylex() != NUMBER)
					crash("EQ operand must be a number");
				loc = token.ival;
				if (loc > 0x10000 || loc < 0)
					crash("Number out of range");
				f[loc] |= NAMED;
				save_name(loc, name); 
				while (yylex() != '\n') 
					;
				break;
			default:
				crash("Invalid line in predef file");
			}
			break;
		default:
			crash("Invalid line in predef file");
		}
}

loadboot()
{
	struct boot_hdr {
		unsigned char flags;
		unsigned char nsec;
		unsigned char base_low;
		unsigned char base_hi;
		unsigned char init_low;
		unsigned char init_hi;
	} bh;

	FILE *fp;
	int base_addr;
	register int i;
	int len;

	fp = fopen(file, "r");
	cur_file = NULL;
	if (!fp) { 
		fprintf(stderr, "Cant open %s\n", file);

#ifdef AMIGA
free(d);
free(f);
#endif

		exit(1);
	}

	if(fread((char *)&bh, sizeof(bh), 1, fp) != 1) 
		crash("Input too short");
	
	base_addr = bh.base_low + (bh.base_hi << 8);
	len = bh.nsec * 128;
	rewind(fp);
	if (fread((char *)&d[base_addr], 1, len, fp) != len) 
		crash("input too short");

	for(i = base_addr; len > 0; len--) 
		f[i++] |= LOADED;

	start_trace(base_addr+6, "**BOOT**");
}


loadfile()
{
	FILE *fp;
	int base_addr;
	int last_addr;
	register int i;
	int had_header;
	int tmp;

	had_header = 0;
	fp = fopen(file, "r");
	cur_file = NULL;
	if (!fp) { 
		fprintf(stderr, "Cant open %s\n", file);

#ifdef AMIGA
free(d);
free(f);
#endif

		exit(1);
	}
	for(;;) {

		i = getc(fp);

		if (i == EOF) {
			if (f[RUNLOC] & LOADED & f[RUNLOC+1]) {
				i = getword(RUNLOC);
				start_trace(i, "**RUN**");
			}
			return;
		}

		i = i | (getc(fp) << 8);
		if (i == 0xffff)  {
			had_header = 1;
			base_addr = getc(fp);
			base_addr = base_addr | (getc(fp) << 8);
			if (base_addr < 0 || base_addr > 0xffff) 
				crash("Invalid base addr in input file");
		} else {
			if (!had_header)
				crash("Invalid header in input file");
			base_addr = i;
		}

		last_addr = getc(fp);
		last_addr = last_addr | (getc(fp) << 8);
		if (last_addr < base_addr || last_addr > 0xffff) 
			crash("Invalid length in input file");

		printf("Load:  %4x -> %4x\n", base_addr, last_addr);
		for(i = base_addr; i <= last_addr; i++) {
			tmp = getc(fp);
			if (tmp == EOF) 
				crash("File too small");
			d[i] = tmp;
			f[i] |= LOADED;
		}

		if (f[INITLOC] & LOADED & f[INITLOC+1])  {
			i = getword(INITLOC);
			start_trace(i, "**INIT**");
		}

		f[INITLOC] &= ~LOADED;
		f[INITLOC+1] &= ~LOADED;
	}

}


c64loadfile()
{
	FILE *fp;
	unsigned int base_addr,i;
	int c;

	fp = fopen(file, "r");
	cur_file = NULL;
	if (!fp) { 
		fprintf(stderr, "Cant open %s\n", file);

#ifdef AMIGA
		free(d);
		free(f);
#endif

		exit(1);
	}

	base_addr = getc(fp);
	i = ( base_addr += ( (unsigned int)getc(fp) << 8 ) );

	while( (c = getc(fp)) != EOF) {
		d[i] = c;
		f[i++] |= LOADED;
		}

	start_trace(base_addr, "**C64BIN**");
}


start_trace(loc, name)
unsigned int loc;
char *name;
{
	printf("Trace: %4x %s\n", loc, name);
	f[loc] |= (NAMED | SREF);
	if (!get_name(loc))
		save_name(loc, name);
	save_ref(0, loc);
	trace(loc);
}
	
trace(addr)
register unsigned int addr;
{
	int opcode;
	register struct info *ip; 
	int operand;
	int istart;

	if (f[addr] & TDONE)
		return;
	else 
		f[addr] |= TDONE;

	istart = addr;
	opcode = getbyte(addr);
	ip = &optbl[opcode];

	if (ip->flag & ILL)
		return;

	f[addr] |= ISOP;

	addr++;

	/* Get the operand */

	switch(ip->nb) {
		case 1:
			break;
		case 2:
			operand = getbyte(addr);
			f[addr++] |= TDONE;
			break;
		case 3:
			operand = getword(addr);
			f[addr++] |= TDONE;
			f[addr++] |= TDONE;
			break;
	}

	/* Mark data references */

	switch (ip->flag & ADRMASK) {
		case IMM:
		case ACC:
		case IMP:
		case REL:
		case IND:
			break;
		case ABS:
			if (ip->flag & (JUMP | FORK))
				break;
			/* Fall into */
		case ABX:
		case ABY:
		case INX:
		case INY:
		case ZPG:
		case ZPX:
		case ZPY:
			f[operand] |= DREF;
			save_ref(istart, operand);
			break;
		default:
			crash("Optable error");
			break;
	}

	/* Trace the next instruction */

	switch (ip->flag & CTLMASK) {
		case NORM:
			trace(addr);
			break;
		case JUMP:
			f[operand] |= JREF;
			save_ref(istart, operand);
			trace(operand);
			break;
		case FORK:
			if (ip->flag & REL) {
				if (operand > 127) 
					operand = (~0xff | operand);
				operand = operand + addr;
				f[operand] |= JREF;
			} else {
				f[operand] |= SREF;
			}
			save_ref(istart, operand);
			trace(operand);
			trace(addr);
			break;
		case STOP:
			break;
		default:
			crash("Optable error");
			break;
	}
}

int
yywrap()
{
	(void)fclose(yyin);
	if (npredef == pre_index) {
		return(1);
	} else  {
		lineno = 0;
		cur_file = predef[pre_index];
		pre_index++;
		yyin = fopen(cur_file, "r");
		if (!yyin) 
			crash("Can't open predefines file");
		return (0);
	}
}
SHAR_EOF
cat << \SHAR_EOF > print.c
#include <ctype.h>
#include "dis.h"

char *strcpy();
char *strcat();

dumpitout()
{
	int i;

	for(i = 0; i<0x10000;) {
		if (f[i] & LOADED) {

			if (f[i] & SREF && f[i] & ISOP)
				printf("\n\n\n");

			printf("%04x  ",i);
			print_bytes(i);
			print_label(i);
			if (f[i] & ISOP)
				i += print_inst(i);
			else
				i += print_data(i);
			printf("\n");

		} else {
			i++;
		}
	}

	print_refs();
}

pchar(c)
int c;
{
	if (isascii(c) && isprint(c))
		return(c);
	return('.');
}

char *
lname(i)
int i;
{
	static char buf[20];
	char t;

	if (f[i] & NAMED) 
		return(get_name(i));
	if ((i > 0) && ((f[i-1] & (NAMED | DREF)) == (NAMED | DREF))) {
		(void)strcpy(buf, get_name(i-1));
		(void)strcat(buf, "+1");
		return (buf);
	}
	if (f[i] & SREF)
		t = 'S';
	else if (f[i] & JREF)
		t = 'L';
	else if (f[i] & DREF)
		t = 'D';
	else 
		t = 'X';
	
	(void)sprintf(buf, "%c%x", t, i);
	return (buf);
}

print_label(i)
{
	if (f[i] & (NAMED | JREF | SREF | DREF)) 
		printf("%-10s", lname(i));
	else
		printf("%10s"," ");
}

print_bytes(addr)
int addr;
{
	register struct info *ip; 

	if ((f[addr] & ISOP) == 0) {
		printf("           ");
		return;
	}

	ip = &optbl[getbyte(addr)];

	switch (ip->nb) {
		case 1:
			printf("%02x         ", getbyte(addr));
			break;
		case 2:
			printf("%02x %02x      ", getbyte(addr), getbyte(addr+1));
			break;
		case 3:
			printf("%02x %02x %02x   ", getbyte(addr), getbyte(addr+1), getbyte(addr+2));
			break;
	}
}
		

print_inst(addr)
int addr;
{
	int opcode;
	register struct info *ip; 
	int operand;

	opcode = getbyte(addr);
	ip = &optbl[opcode];

	printf("%s  ", ip->opn);

	addr++;

	switch(ip->nb) {
		case 1:
			break;
		case 2:
			operand = getbyte(addr);
			break;
		case 3:
			operand = getword(addr);
			break;
	}

	if (ip->flag & REL) {
		if (operand > 127) 
			operand = (~0xff | operand);
		operand = operand + ip->nb + addr - 1;
	}

	switch (ip->flag & ADRMASK) {
		case IMM:
			printf("#$%02x                        * %d %c", operand, operand, pchar(operand));
			break;
		case ACC:
		case IMP:
			break;
		case REL:
		case ABS:
		case ZPG:
			printf("%s ", lname(operand));
			break;
		case IND:
			printf("(%s) ", lname(operand));
			break;
		case ABX:
		case ZPX:
			printf("%s,X ", lname(operand));
			break;
		case ABY:
		case ZPY:
			printf("%s,Y ", lname(operand));
			break;
		case INX:
			printf("(%s,X) ", lname(operand));
			break;
		case INY:
			printf("(%s),Y", lname(operand));
			break;
		default:
			break;
	}

	return(ip->nb);

}

print_data(i)
{
	int count;
	int j;
	int start;

	start = i;
	printf(".DB  %02x ", getbyte(i));
	count = 1;
	i++;

	for (j = 1; j < 8; j++) {
		if (f[i] & (JREF | SREF | DREF) || ((f[i] & LOADED) == 0)) 
			break;
		else
			printf("%02x ", getbyte(i));
		i++;
		count++;
	}
	for (j = count; j < 8; j++)
		printf("   ");

	printf("    * ");

	for (j = start; j < i ; j++) 
			printf("%c", pchar((int)getbyte(j)));

	return (count);
}

print_refs()
{
	char tname[50];
	char cmd[200];
	FILE *fp;
	register struct ref_chain *rp;
	register int i;
	int npline;

#ifndef AMIGA
	(void)sprintf(tname, "dis.%d", getpid());
	(void)sprintf(cmd, "sort %s; rm %s", tname, tname);
#else
	(void)sprintf(tname, "dis.%ld", FindTask(0L));
	(void)sprintf(cmd, "Sort from %s to %s", tname, &tname[3] );
#endif

	fp = fopen(tname, "w");
	if (!fp) 
		crash("Cant open temporary file/n");

	for (i = 0; i<0x10000; i++) {
		if(f[i] & (JREF|SREF|DREF)) {
			rp = get_ref(i);
			if (!rp) {
				fprintf(stderr, "No ref %d\n", i);
				break;
			}

			fprintf(fp, "%-8s  %04x   ", lname(i), i);
			npline = 0;
			while (rp) {
				fprintf(fp, "%04x ", rp->who);
				npline++;
				if (npline == 12) {
					fprintf(fp,"\n");
					fprintf(fp,"%-8s  %04x   ",lname(i),i);
					npline = 0;
				}
				rp = rp->next;
			}
			fprintf(fp, "\n");
		}

	}

	(void)fclose(fp);

	printf("\n\n\n\n\nCross References\n\n");
	printf("%-8s  Value  References\n", "Symbol");
	(void)fflush (stdout);

#ifndef AMIGA
	(void)system(cmd);
#else
	(void)Execute(cmd,0L,0L);
	(void)sprintf(cmd, "Type %s",&tname[3]);
	(void)Execute(cmd,0L,Output());
	DeleteFile(tname);
	DeleteFile(&tname[3]);
#endif
}
SHAR_EOF
cat << \SHAR_EOF > ref.c
#include "dis.h"

#define HTSIZE 0x1000			/* Power of 2 */
#define HTMASK (HTSIZE-1)

struct hashslot {
	int addr;			/* The key */
	struct ref_chain *ref;		/* Who references it */
	char *name;			/* The symbolic name (if it has one) */
};

struct   hashslot hashtbl[HTSIZE];	/* the hash table */

struct hashslot *
hash(loc, allocate)
int loc;
int allocate;
{
	int probes;
	register struct hashslot *hp;

	hp = &hashtbl[loc & HTMASK];
	probes = 0;

	while (probes< HTSIZE) {
		if (hp->addr == loc)
			return(hp);
		if (hp->name == NULL && hp->ref == NULL) {
			if (allocate) {
				hp->addr = loc;
				return(hp);
			} else {
				return(NULL);
			}
		}
		hp++;
		if (hp == &hashtbl[HTSIZE])
			hp = &hashtbl[0];
		probes++;
	}

	crash("Hash table full");
	/*NOTREACHED*/
}

save_ref(refer, refee) 
int refer;
int refee;
{
	struct ref_chain *rc;
	struct hashslot *hp;

	rc = (struct ref_chain *)emalloc(sizeof(*rc));
	rc->who = refer;
	hp = hash(refee, 1);
	rc->next = hp->ref;
	hp->ref = rc;
}

save_name(loc, name)
int loc;
char *name;
{
	struct hashslot *hp;

	hp = hash(loc, 1);
	hp->name = name;
}

struct ref_chain *
get_ref(loc)
{
	struct hashslot *hp;

	hp = hash(loc, 0);
	if (!hp) 
		return(NULL);
	return(hp->ref);
}

char *
get_name(loc)
{
	struct hashslot *hp;

	hp = hash(loc, 0);
	if (!hp) 
		return(NULL);
	return(hp->name);
}
SHAR_EOF
cat << \SHAR_EOF > tbl.c
#include "dis.h"

struct info optbl[256] = {
	/* 00 */	{ { 'B', 'R', 'K', 0, },  1, IMP|STOP, },
	/* 01 */	{ { 'O', 'R', 'A', 0, },  2, INX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 05 */	{ { 'O', 'R', 'A', 0, },  2, ZPG|NORM, },
	/* 06 */	{ { 'A', 'S', 'L', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 08 */	{ { 'P', 'H', 'P', 0, },  1, IMP|NORM, },
	/* 09 */	{ { 'O', 'R', 'A', 0, },  2, IMM|NORM, },
	/* 0a */	{ { 'A', 'S', 'L', 0, },  1, ACC|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 0d */	{ { 'O', 'R', 'A', 0, },  3, ABS|NORM, },
	/* 0e */	{ { 'A', 'S', 'L', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 10 */	{ { 'B', 'P', 'L', 0, },  2, REL|FORK, },
	/* 11 */	{ { 'O', 'R', 'A', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 15 */	{ { 'O', 'R', 'A', 0, },  2, ZPX|NORM, },
	/* 16 */	{ { 'A', 'S', 'L', 0, },  2, ZPX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 18 */	{ { 'C', 'L', 'C', 0, },  1, IMP|NORM, },
	/* 19 */	{ { 'O', 'R', 'A', 0, },  3, ABY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 1d */	{ { 'O', 'R', 'A', 0, },  3, ABX|NORM, },
	/* 1e */	{ { 'A', 'S', 'L', 0, },  3, ABX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 20 */	{ { 'J', 'S', 'R', 0, },  3, ABS|FORK, },
	/* 21 */	{ { 'A', 'N', 'D', 0, },  2, INX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 24 */	{ { 'B', 'I', 'T', 0, },  2, ZPG|NORM, },
	/* 25 */	{ { 'A', 'N', 'D', 0, },  2, ZPG|NORM, },
	/* 26 */	{ { 'R', 'O', 'L', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 28 */	{ { 'P', 'L', 'P', 0, },  1, IMP|NORM, },
	/* 29 */	{ { 'A', 'N', 'D', 0, },  2, IMM|NORM, },
	/* 2a */	{ { 'R', 'O', 'L', 0, },  1, ACC|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 2c */	{ { 'B', 'I', 'T', 0, },  3, ABS|NORM, },
	/* 2d */	{ { 'A', 'N', 'D', 0, },  3, ABS|NORM, },
	/* 2e */	{ { 'R', 'O', 'L', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 30 */	{ { 'B', 'M', 'I', 0, },  2, REL|FORK, },
	/* 31 */	{ { 'A', 'N', 'D', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 35 */	{ { 'A', 'N', 'D', 0, },  2, ZPX|NORM, },
	/* 36 */	{ { 'R', 'O', 'L', 0, },  2, ZPX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 38 */	{ { 'S', 'E', 'C', 0, },  1, IMP|NORM, },
	/* 39 */	{ { 'A', 'N', 'D', 0, },  3, ABY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 3d */	{ { 'A', 'N', 'D', 0, },  3, ABX|NORM, },
	/* 3e */	{ { 'R', 'O', 'L', 0, },  3, ABX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 40 */	{ { 'R', 'T', 'I', 0, },  1, IMP|STOP, },
	/* 41 */	{ { 'E', 'O', 'R', 0, },  2, INX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 45 */	{ { 'E', 'O', 'R', 0, },  2, ZPG|NORM, },
	/* 46 */	{ { 'L', 'S', 'R', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 48 */	{ { 'P', 'H', 'A', 0, },  1, IMP|NORM, },
	/* 49 */	{ { 'E', 'O', 'R', 0, },  2, IMM|NORM, },
	/* 4a */	{ { 'L', 'S', 'R', 0, },  1, ACC|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 4c */	{ { 'J', 'M', 'P', 0, },  3, ABS|JUMP, },
	/* 4d */	{ { 'E', 'O', 'R', 0, },  3, ABS|NORM, },
	/* 4e */	{ { 'L', 'S', 'R', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 50 */	{ { 'B', 'V', 'C', 0, },  2, REL|FORK, },
	/* 51 */	{ { 'E', 'O', 'R', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 55 */	{ { 'E', 'O', 'R', 0, },  2, ZPX|NORM, },
	/* 56 */	{ { 'L', 'S', 'R', 0, },  2, ZPX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 58 */	{ { 'C', 'L', 'I', 0, },  1, IMP|NORM, },
	/* 59 */	{ { 'E', 'O', 'R', 0, },  3, ABY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 5d */	{ { 'E', 'O', 'R', 0, },  3, ABX|NORM, },
	/* 5e */	{ { 'L', 'S', 'R', 0, },  3, ABX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 60 */	{ { 'R', 'T', 'S', 0, },  1, IMP|STOP, },
	/* 61 */	{ { 'A', 'D', 'C', 0, },  2, INX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 65 */	{ { 'A', 'D', 'C', 0, },  2, ZPG|NORM, },
	/* 66 */	{ { 'R', 'O', 'R', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 68 */	{ { 'P', 'L', 'A', 0, },  1, IMP|NORM, },
	/* 69 */	{ { 'A', 'D', 'C', 0, },  2, IMM|NORM, },
	/* 6a */	{ { 'R', 'O', 'R', 0, },  1, ACC|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 6c */	{ { 'J', 'M', 'P', 0, },  3, IND|STOP, },
	/* 6d */	{ { 'A', 'D', 'C', 0, },  3, ABS|NORM, },
	/* 6e */	{ { 'R', 'O', 'R', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 70 */	{ { 'B', 'V', 'S', 0, },  2, REL|FORK, },
	/* 71 */	{ { 'A', 'D', 'C', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 75 */	{ { 'A', 'D', 'C', 0, },  2, ZPX|NORM, },
	/* 76 */	{ { 'R', 'O', 'R', 0, },  2, ZPX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 78 */	{ { 'S', 'E', 'I', 0, },  1, IMP|NORM, },
	/* 79 */	{ { 'A', 'D', 'C', 0, },  3, ABY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 7d */	{ { 'A', 'D', 'C', 0, },  3, ABX|NORM, },
	/* 7e */	{ { 'R', 'O', 'R', 0, },  3, ABX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 81 */	{ { 'S', 'T', 'A', 0, },  2, INX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 84 */	{ { 'S', 'T', 'Y', 0, },  2, ZPG|NORM, },
	/* 85 */	{ { 'S', 'T', 'A', 0, },  2, ZPG|NORM, },
	/* 86 */	{ { 'S', 'T', 'X', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 88 */	{ { 'D', 'E', 'Y', 0, },  1, IMP|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 8a */	{ { 'T', 'X', 'A', 0, },  1, IMP|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 8c */	{ { 'S', 'T', 'Y', 0, },  3, ABS|NORM, },
	/* 8d */	{ { 'S', 'T', 'A', 0, },  3, ABS|NORM, },
	/* 8e */	{ { 'S', 'T', 'X', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 90 */	{ { 'B', 'C', 'C', 0, },  2, REL|FORK, },
	/* 91 */	{ { 'S', 'T', 'A', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 94 */	{ { 'S', 'T', 'Y', 0, },  2, ZPX|NORM, },
	/* 95 */	{ { 'S', 'T', 'A', 0, },  2, ZPX|NORM, },
	/* 96 */	{ { 'S', 'T', 'X', 0, },  2, ZPY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 98 */	{ { 'T', 'Y', 'A', 0, },  1, IMP|NORM, },
	/* 99 */	{ { 'S', 'T', 'A', 0, },  3, ABY|NORM, },
	/* 9a */	{ { 'T', 'X', 'S', 0, },  1, IMP|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 9d */	{ { 'S', 'T', 'A', 0, },  3, ABX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* a0 */	{ { 'L', 'D', 'Y', 0, },  2, IMM|NORM, },
	/* a1 */	{ { 'L', 'D', 'A', 0, },  2, INX|NORM, },
	/* a2 */	{ { 'L', 'D', 'X', 0, },  2, IMM|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* a4 */	{ { 'L', 'D', 'Y', 0, },  2, ZPG|NORM, },
	/* a5 */	{ { 'L', 'D', 'A', 0, },  2, ZPG|NORM, },
	/* a6 */	{ { 'L', 'D', 'X', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* a8 */	{ { 'T', 'A', 'Y', 0, },  1, IMP|NORM, },
	/* a9 */	{ { 'L', 'D', 'A', 0, },  2, IMM|NORM, },
	/* aa */	{ { 'T', 'A', 'X', 0, },  1, IMP|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* ac */	{ { 'L', 'D', 'Y', 0, },  3, ABS|NORM, },
	/* ad */	{ { 'L', 'D', 'A', 0, },  3, ABS|NORM, },
	/* ae */	{ { 'L', 'D', 'X', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* b0 */	{ { 'B', 'C', 'S', 0, },  2, REL|FORK, },
	/* b1 */	{ { 'L', 'D', 'A', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* b4 */	{ { 'L', 'D', 'Y', 0, },  2, ZPX|NORM, },
	/* b5 */	{ { 'L', 'D', 'A', 0, },  2, ZPX|NORM, },
	/* b6 */	{ { 'L', 'D', 'X', 0, },  2, ZPY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* b8 */	{ { 'C', 'L', 'V', 0, },  1, IMP|NORM, },
	/* b9 */	{ { 'L', 'D', 'A', 0, },  3, ABY|NORM, },
	/* ba */	{ { 'T', 'S', 'X', 0, },  1, IMP|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* bc */	{ { 'L', 'D', 'Y', 0, },  3, ABX|NORM, },
	/* bd */	{ { 'L', 'D', 'A', 0, },  3, ABX|NORM, },
	/* be */	{ { 'L', 'D', 'X', 0, },  3, ABY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* c0 */	{ { 'C', 'P', 'Y', 0, },  2, IMM|NORM, },
	/* c1 */	{ { 'C', 'M', 'P', 0, },  2, INX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* c4 */	{ { 'C', 'P', 'Y', 0, },  2, ZPG|NORM, },
	/* c5 */	{ { 'C', 'M', 'P', 0, },  2, ZPG|NORM, },
	/* c6 */	{ { 'D', 'E', 'C', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* c8 */	{ { 'I', 'N', 'Y', 0, },  1, IMP|NORM, },
	/* c9 */	{ { 'C', 'M', 'P', 0, },  2, IMM|NORM, },
	/* ca */	{ { 'D', 'E', 'X', 0, },  1, IMP|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* cc */	{ { 'C', 'P', 'Y', 0, },  3, ABS|NORM, },
	/* cd */	{ { 'C', 'M', 'P', 0, },  3, ABS|NORM, },
	/* ce */	{ { 'D', 'E', 'C', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* d0 */	{ { 'B', 'N', 'E', 0, },  2, REL|FORK, },
	/* d1 */	{ { 'C', 'M', 'P', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* d5 */	{ { 'C', 'M', 'P', 0, },  2, ZPX|NORM, },
	/* d6 */	{ { 'D', 'E', 'C', 0, },  2, ZPX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* d8 */	{ { 'C', 'L', 'D', 0, },  1, IMP|NORM, },
	/* d9 */	{ { 'C', 'M', 'P', 0, },  3, ABY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* dd */	{ { 'C', 'M', 'P', 0, },  3, ABX|NORM, },
	/* de */	{ { 'D', 'E', 'C', 0, },  3, ABX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* e0 */	{ { 'C', 'P', 'X', 0, },  2, IMM|NORM, },
	/* e1 */	{ { 'S', 'B', 'C', 0, },  2, INX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* e4 */	{ { 'C', 'P', 'X', 0, },  2, ZPG|NORM, },
	/* e5 */	{ { 'S', 'B', 'C', 0, },  2, ZPG|NORM, },
	/* e6 */	{ { 'I', 'N', 'C', 0, },  2, ZPG|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* e8 */	{ { 'I', 'N', 'X', 0, },  1, IMP|NORM, },
	/* e9 */	{ { 'S', 'B', 'C', 0, },  2, IMM|NORM, },
	/* ea */	{ { 'N', 'O', 'P', 0, },  1, IMP|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* ec */	{ { 'C', 'P', 'X', 0, },  3, ABS|NORM, },
	/* ed */	{ { 'S', 'B', 'C', 0, },  3, ABS|NORM, },
	/* ee */	{ { 'I', 'N', 'C', 0, },  3, ABS|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* f0 */	{ { 'B', 'E', 'Q', 0, },  2, REL|FORK, },
	/* f1 */	{ { 'S', 'B', 'C', 0, },  2, INY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* f5 */	{ { 'S', 'B', 'C', 0, },  2, ZPX|NORM, },
	/* f6 */	{ { 'I', 'N', 'C', 0, },  2, ZPX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* f8 */	{ { 'S', 'E', 'D', 0, },  1, IMP|NORM, },
	/* f9 */	{ { 'S', 'B', 'C', 0, },  3, ABY|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
	/* fd */	{ { 'S', 'B', 'C', 0, },  3, ABX|NORM, },
	/* fe */	{ { 'I', 'N', 'C', 0, },  3, ABX|NORM, },
	/* 00 */	{ { '?', '?', '?', 0, },  1, ILL|NORM, },
};
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.