[net.sources] 6502 disassembler

elg@usl.UUCP (Eric Lee Green) (09/02/86)

Posted to net.sources is a commenting 6502 disassembler, currently for
the Commodore 128 but easily modifiable for any 6502-based computer
(it uses a .labels file and a hash table, and a very slight amount of
Commodore-specific knowledge). Would especially appreciate it if
someone would modify it for the C-64, don't really feel like typing in
a new .labels file. Enjoy, and leave any suggestions for improvements
in my mailbox (I'm sure there will be a LOT of improvements suggested,
because it was just a two-day hack to solve a particular problem).

Eric Green {akgua,ut-sally}!usl!elg

---------CUT HERE------------------CUT HERE------------------CUT HERE--------
: This is a shar archive.
: Remove everything above this line.
: Run the file through sh, not csh.
: (type `sh this_file')
: If you do not see the message
:	`this_file completed!'
: then the file was incomplete.
echo extracting - README
sed 's/^X//' > README << 'FRIDAY_NIGHT'
X This is a commenting disassembler for 6502 machine language,
Xfor the Commodore 128 (but easily modified for any other 6502 based
Xmachine, see notes below).  It disassembles code for human
Xperusal, not for feeding into an assembler (I use Merlin and the
XSourceror for that). 
X
XModification notes:
X     Currently, it comments the code with Commodore-128 specific
Xstuff.  However, it uses a hash table and a .labels file for most
Xstuff, so altering it to work with another 6502 based computer would
Xbe childs play (although it'll take awhile to type in another .labels
Xfile). One thing to look at: currently, for efficiency reasons, all of
Xzero page's comments are contained in tables.h in a static array of
X*char (the distribution is too close on the 128, which uses every byte
Xof zero page -- it would wreck havoc with the hash/rehash scheme).
XYou'll have to change these labels for your computer. Also, note that
Xin dsm.c there is code that detects references to screen and color
Xmemory. That will need to be yanked out for non-CBM computers.
X
X     I would especially be grateful if someone would type in the
Xlabels for the Commodore 64... I simply have no time to spend on
Xtyping in a thousand lines or so of labels. Also, if someone knows of
Xa listing of C-128 ROM entries, would be grateful if they'd tell me
Xwhere I can get ahold of it. I'm interested in learning more about my
Xnew machine. Finally, does anybody know of a semi-decent linking
Xassembler for 6502 assembly language? I'm so tired of dealing with
Xhundreds of global labels... fixing instances where I have 5 labels
Xnamed "loop" gets old after awhile.
X
X     This was just a two-day hack, so please leave any suggestions in
Xmy mailbox (I expect there will be quite a few). Maybe we can turn it
Xinto a four-day hack...
X
X  Eric Green (akgua,ut-sally)!usl!elg
FRIDAY_NIGHT
echo extracting - tables.h
sed 's/^X//' > tables.h << 'FRIDAY_NIGHT'
X
Xstatic char *opcode[] = {
X "brk","ora","002","003","004","ora","asl","007","php","ora","asl","011",
X "012","ora","asl","015","bpl","ora","018","019","020","ora","asl",
X "023","clc","ora","026","027","028","ora","asl","031","jsr","and","034",
X "035","bit","and","rol","039","plp","and","rol","043","bit","and",
X "rol","047","bmi","and","050","051","052","and","rol","055","sec","and",
X "058","059","060","and","rol","063","rti","eor","066","067","068","eor",
X "lsr","071","pha","eor","lsr","075","jmp","eor","lsr","079","bvc","eor",
X "082","083","084","eor","lsr","087","cli","eor","090","091","092","eor",
X "lsr","095","rts","adc","098","099","100","adc","ror","103","pla","adc",
X "ror","107","jmp","adc","ror","111","bvs","adc","114","115","116","adc",
X "ror","119","sei","adc","122","123","124","adc","ror","127","128","sta",
X "130","131","sty","sta","stx","135","dey","137","txa","139","sty","sta",
X "stx","143","bcc","sta","146","147","sty","sta","stx","151","tya","sta",
X "txs","155","156","sta","158","159","ldy","lda","ldx","163","ldy","lda",
X "ldx","167","tay","lda","tax","171","ldy","lda","ldx","175","bcs","lda",
X "178","179","ldy","lda","ldx","183","clv","lda","tsx","187","ldy","lda",
X "ldx","191","cpy","cmp","194","195","cpy","cmp","dec","199","iny","cmp",
X "dex","203","cpy","cmp","dec","207","bne","cmp","210","211","212","cmp",
X "dec","215","cld","cmp","218","219","220","cmp","dec","223","cpx","sbc",
X "226","227","cpx","sbc","inc","231","inx","sbc","nop","235","cpx","sbc",
X "inc","239","beq","sbc","242","243","244","sbc","inc","247","sed","sbc",
X "250","251","252","sbc","inc","255"
X};
X
Xstatic short mode[] = {
X  0,10,13,13,13,                          3,3,13,0,2,
X  1,13,13,6,6,                            13,9,11,13,13,
X  13,4,4,13,0,                            8,13,13,13,7,
X  7,13,6,10,13,                           13,3,3,3,13,
X  0,2,1,13,6,                             6,6,13,9,11,
X  13,13,13,4,4,                           13,0,8,13,13,
X  13,7,7,13,0,                            10,13,13,13,3,
X  3,13,0,2,1,                             13,6,6,6,13,
X  9,11,13,13,13,                          4,4,13,0,8,
X  13,13,13,7,7,                           13,0,10,13,13,
X  13,3,3,13,0,                            2,1,13,12,6,
X  6,13,9,11,13,                           13,13,4,4,13,
X  0,8,13,13,13,                           7,7,13,13,10,
X  13,13,3,3,3,                            13,0,13,0,13,
X  6,6,6,13,9,                             11,13,13,4,4,
X  5,13,0,8,0,                             13,13,7,13,13,
X  2,10,2,13,3,                            3,3,13,0,2,
X  0,13,6,6,6,                             13,9,11,13,13,
X  4,4,5,13,0,                             8,0,13,7,7,
X  8,13,2,10,13,                           13,3,3,3,13,
X  0,2,0,13,6,                             6,6,13,9,11,
X  13,13,13,4,4,                           13,0,8,13,13,
X  13,7,7,13,2,                            10,13,13,3,3,
X  3,13,0,3,0,                             13,6,6,6,13,
X  9,11,13,13,13,                          4,4,13,0,8,
X  13,13,13,7,7,13
X};
X
Xstatic short length[] = {  1,1,2,2,2,2,3,3,3,2,2,2,3,1 };
X
Xstatic char *before[] = {
X  ""," a "," #$"," $"," $"," $"," $"," $"," $"," $",
X  " ($", " ($", " ($",""
X};
X
Xstatic char *after[] = {
X  "        ","     ","   ","    ",
X ",x  ",",y  ","  ",",x",",y","  ",",x)","),y",")","        "
X};
X
Xstatic char *zero_page[] = {
X  "D6510 -- 6510 Data Direction Register",  /*  0 */
X  "R6510 -- 6510 Data Register",            /*  1 */
X  "BANK -- token 'search' looks for, or bank #", /* 2 */
X  "PC_HI -- Address for BASIC sys command or monitor and long call/jump routines", /* 3 */
X  "PC_LO -- Address for BASIC sys or monitor long call/jumps", /* 4 */
X  "S_REG -- status register temp",		/* 5 */
X  "A_REG -- .A reg temp",			/* 6 */
X  "X_REG -- .X reg temp",			/* 7 */
X  "Y_REG -- .Y reg temp",			/* 8 */
X  "STKPTR,INTEGR,CHARAC -- Stack pointer temp, BASIC search character",	/* 9 */
X  "ENDCHR -- flag: scan for quote at end of string", /* a */
X  "TRMPOS -- Screen column from last tab",	/* b */
X  "VERCK -- flag: 0=load, 1=verify",		/* c */
X  "COUNT -- Input buf. ptr/# of subscripts",	/* d */
X  "DIMFLG -- Flag: default array dimension",	/* e */
X  "VALTYP -- Data type: $ff=string,$00=numeric", /* f */
X  "INTFLG -- Data type: $00 = float,$80= integer",	      /* 10 */   
X  "GARBFL -- flag: data scan/list quote/garbage collection",  /* 11 */
X  "DORES,SUBFLG -- flag: subscript ref./user func. call",     /* 12 */
X  "INPFLG -- Flag: $00=input,$40=get,$98=read",		      /* 13 */
X  "DOMASK,TANSGN -- ??, Flag: tan sign/comparision result",   /* 14 */
X  "CHANNL",						      /* 15 */
X  "POKER,LINNUM -- temp integer value",			      /* 16 */
X  "POKER+1,LINNUM+1 -- temp integer value",		      /* 17 */
X  "TEMPPT -- pointer: temp string stack",		      /* 18 */
X  "LASTPT -- last temp string address",			      /* 19 */
X  "LASTPT+1 -- last temp string address",		      /* 1a */
X  "TEMPST -- stack for temp strings",			      /* 1b */
X  "TEMPST+1 -- stack for temp strings",			      /* $1C */
X  "TEMPST+2 -- stack for temp strings",			      /* $1D */
X  "TEMPST+3 -- stack for temp strings",			      /* $1E */
X  "TEMPST+4 -- stack for temp strings",			      /* $1F */
X  "TEMPST+5 -- stack for temp strings",			      /* $20 */
X  "TEMPST+6 -- stack for temp strings",			      /* $21 */
X  "TEMPST+7 -- stack for temp strings",			      /* $22 */
X  "TEMPST+8 -- stack for temp strings",			      /* $23 */
X  "INDEX -- utility pointer area",			      /* $24 */
X  "INDEX+1 -- utility pointer area",			      /* $25 */
X  "INDEX2 -- utility pointer area",			      /* 26 */
X  "INDEX2+1 -- utility pointer area",			      /* 27 */
X  "RESHO -- float. pt. product of multiply",		      /* 28 */
X  "RESMOH -- float. pt. product of multiply",		      /* 29 */
X  "ADDEND -- float pt. product of multiply",		      /* 2a */
X  "RESMO,RESLO -- float point product of multiply",	      /* 2b */
X  "??? -- floating point something",			      /* 2c */
X  "TXTTAB -- pointer: start of BASIC text",		      /* 2d */
X  "TXTTAB+1 -- pointer: start of BASIC text",		      /* 2e */
X  "VARTAB -- pointer: start of BASIC variables",	      /* 2f */
X  "VARTAB+1 -- pointer: start of BASIC variables",	      /* 30 */
X  "ARYTAB -- pointer: start of BASIC arrays",		      /* 31 */
X  "ARYTAB+1 -- pointer: start of BASIC arrays",		      /* 32 */
X  "STREND -- pointer: end of bASIC arrays + 1",		      /* 33 */
X  "STREND+1 -- pointer: end of BASIC arrays +1",	      /* 34 */
X  "FRETOP -- pointer: bottom of string storage",	      /* 35 */
X  "FRETOP+1 -- pointer: bottom of string storage",	      /* 36 */
X  "FRESPC -- utility string pointer",			      /* 37 */
X  "FRESPC+1 -- utility string pointer +1",		      /* 38 */
X  "MAX_MEM_1 -- top of string/variable bank (bank 1)",	      /* 39 */
X  "MAX_MEM_1+1 -- top of string/variable bank (bank 1)",      /* 3a */
X  "CURLIN -- current BASIC line number",		      /* 3b */
X  "CURLINE+1 --current BASIC line number",		      /* 3c */
X  "TXTPTR  -- pointer to BASIC text used by CHRGET etc.",     /* 3d */
X  "TXTPTR+1 -- pointer to BASIC text used by CHRGET etc.",    /* 3e */
X  "FORM,FNDPNT -- used by print using, pointer to item found by search.", /* 3f  */
X  "FORM+1,FNDNT+1 -- used by print using, pointer to item found by search.", /* 40 */
X  "DATLIN -- current data line number",			      /* 41 */
X  "DATLIN+1 -- current data line number",		      /* 42 */
X  "DATPTR -- current data line address",		      /* 43 */
X  "DATPTR+1 -- current data line address",		      /* 44 */
X  "INPPTR -- Vector: input routine",			      /* 45 */
X  "INPPTR+1 -- Vector: input routine",			      /* 46 */
X  "VARNAM -- current BASIC variable name",		      /* 47 */
X  "VARNAM+1 -- current BASIC variable name",		      /* 48 */
X  "FDECPT,VARPNT -- ???, Pointer: current BASIC variable data",	/* 49 */
X  "FDECPT+1,VARPNT+1 -- ???, Pointer: current BASIC variable data", /* 4a */
X  "LSTPNT,FORPNT -- ???, pointer: index variable for for/next",	/* 4b */
X  "ANDMSK,EORMSK",					      /* 4c */
X  "VARTXT,OPPTR",					      /* 4d */
X  "VARTXT+1,OPPTR+1",					      /* 4e */
X  "OPMASK",						      /* 4f */
X  "GRBPNT,TEMPF3,DEFPNT",				      /* 50 */
X  "GRBPNT+1,TEMPF3+1,DEFPNT+1",				      /* 51 */
X  "DSCPNT",						      /* 52 */
X  "DSCPNT+1",						      /* 53 */
X  "???",						      /* 54 */
X  "HELPER -- flags 'help' or 'list'",			      /* 55 */
X  "JMPER",						      /* 56 */
X  "JMPER+1???",						      /* 57 */
X  "OLDOV",						      /* 58 */
X  "TEMPF1,PTARG1 -- multiply defined for instr.",	      /* 59 */
X  "ARYPNT,HIGHDS",					      /* 5a */
X  "PTARG2",						      /* 5b */
X  "PTARG2+1,HIGHTR",					      /* 5c */
X  "STR1",						      /* 5d */
X  "STR1+1,TEMPF2",					      /* 5e */
X  "STR1+2,DECCNT -- Number of digits after the decimal point", /* 5f */
X  "STR2,TENEXP,T0 -- ??,??, ML Monitor Z.P. storeage in FAC", /* 60 */
X  "STR2+1,GRBTOP,DPTFLG,LOWTR -- ??,??, Decimal point flag, ??", /* 61 */
X  "STR2+2,EXPSGN -- ??, part of FAC???",		      /* 62 */
X  "POSITN,DSCTMP,LEFT_FLAG,FACEXP,T1 -- ??,??,paint-lft flg,FAC#1 exp.,mon. thingy", /* 63 */
X  "MATCH,RIGHT_FLAG,FACHO -- ??,paint-right flag,FAC#1 Mantissa", /* 64 */
X  "FACMOH -- FAC#1 mantissa high order",		      /* 65 */
X  "INDICE,FACMO,T2: ??,FAC#1 mantissa,mon. thingy",	      /* 66 */
X  "FACLO -- FAC#1 mantissa",				      /* 67 */
X  "FACSGN -- FAC#1 sign",				      /* 68 */
X  "DEGREE,SGNFLG: ??,pointer:series-eval constant",	      /* 69 */
X  "ARGEXP -- FAC#2 exponent",				      /* 6a */
X  "ARGHO -- FAC#2 MAntissa",				      /* 6b */
X  "ARGMOH,INIT_AS_0 -- FAC#2 mantissa, just a count for init", /* 6c */
X  "ARGMO -- FAC#2 mantissa middle order",		      /* 6d */
X  "ARGLO -- FAC#2 mantissa lo order",			      /* 6e */
X  "ARGSGN -- FAC#2 sign",				      /* 6f */
X  "STRNG1,ARISGN -- ??,sign comparison result: FAC#1 vs #2",  /* 70 */
X  "FACOV  -- FAC#1 low-order (rounding)",		      /* 71 */
X  "STRNG2,POLYPT,CURTOL -- ?? FBUFPT -- ptr: cassette buffer", /* 72 */
X  "STRNG2+1,POLYPT+1,CURTOL+1-- ?? FBUFPT+1 -- ptr: cassette buffer", /* 73 */
X  "AUTINC -- incrememt val. for auto (0=off)",		      /* 74 */
X  "AUTINC+1 -- incrememt val. for auto (0=off)",	      /* 75 */
X  "MVDFLG -- flag if 10k hires area allocated",		      /* 76 */
X  "Z_P_TEMP_1 -- print using's leading zero cnter, sprite temp, mid$ temp", /* 77 */
X  "HULP,KEYSIZ -- counter,??",				      /* 78 */
X  "SYNTMP -- used as temp for indirect loads",		      /* 79 */
X  "DSDESC,TXTPTR -- descriptor for ds$, monitor ZP storage",  /* 7a */
X  "DSDESC+1,TXTPTR+1 -- descriptor for ds$, monitor ZP storage", /* 7b */
X  "DSDESC+2,TXTPTR+2 -- descriptor for ds$, monitor ZP storage", /* 7c */
X  "TOS -- top of run time stack",			      /* 7d */
X  "TOS+1 -- top of run time stack",			      /* 7e */
X  "RUNMOD -- flags run/direct mode",			      /* 7f */
X  "PARSTS -- DOS parser status word  POINT -- using's pointer to dec.pt", /* 80 */
X  "PARSTX",						      /* 81 */
X  "OLDSTK",						      /* 82 */
X  "COLSEL  -- current color selected",			      /* 83 */
X  "MULTICOLOR_1",					      /* 84 */
X  "MULTICOLOR_2",					      /* 85 */
X  "FOREGROUND",						      /* 86 */
X  "SCALE_X -- Scale factor in X",			      /* 87 */
X  "SCALE_X+1 -- Scale factor in X",			      /* 88 */
X  "SCALE_Y -- Scale factor in Y",			      /* 89 */
X  "SCALE_Y+1 -- Scale factor in Y",			      /* 8a */
X  "STOPNB -- stop paint if not background/not same color",    /* 8b */
X  "GRAPNT",						      /* 8c */
X  "GRAPNT+1",						      /* 8d */
X  "VTEMP1",						      /* 8e */
X  "VTEMP2",						      /* 8f */
X  "STATUS -- I/O operation status byte",		      /* 90 */
X  "STKEY -- stop key flag",				      /* 91 */
X  "SVXT -- tape temporary",				      /* 92 */
X  "VERCK -- load or verify flag",			      /* 93 */
X  "C3PO -- serial buffered char flag",			      /* 94 */
X  "BSOUR -- char buffer for serial",			      /* 95 */
X  "SYNO -- Cassette sync #",				      /* 96 */
X  "XSAV -- temp for BASIN",				      /* 97 */
X  "LDTND -- index to logical file",			      /* 98 */
X  "DFLTN -- default input device #",			      /* 99 */
X  "DFLTO -- default output device #",			      /* 9a */
X  "PRTY -- cassette parity",				      /* 9b */
X  "DPSW -- cassette dipole switch",			      /* 9c */
X  "MSGFLG -- OS message flag",				      /* 9d */
X  "PTR1,T1 -- cassette error pass1, temporary 1",	      /* 9e */
X  "PTR2,T2 -- cassette error pass 2, temporary 2",	      /* 9f */
X  "TIME -- 24 hour clock in 1/60th seconds",		      /* a0 */
X  "TIME+1 -- 24 hour clock in 1/60th seconds",		      /* a1 */
X  "TIME+2 -- 24 hour clock in 1/60th seconds",		      /* a2 */
X  "R2D2 -- serial bus usage   PCNTR -- cassette",	      /* a3 */
X  "BSOUR1,FIRT -- temp used by serial routine",		      /* a4 */
X  "COUNT,CNTDN -- temp used by serial routine, cassette sync countdown", /* a5 */
X  "BUFPT -- cassette buffer pointer",			      /* a6 */
X  "INBIT,SHCNL -- RS232 rcvr input bit storage,cassette short count", /* a7 */
X  "BITCI,RER -- RS232 rcvr bit count,cassette read error",    /* a8 */
X  "RINONE -- RS232 rcvr flag for start bit check\n                                REZ -- Cassette reading zeros", /* a9 */
X  "RIDATA,RDFLG -- RS232 rcvr byte buffer, cassette read mode",	  /* aa */
X  "RIPRTY -- RS232 rcvr parity storage,  SHCNH -- Cassette short cnt.",	/* ab */
X  "SAL -- pointer: tape buffer/screen scrolling",	      /* ac */
X  "SAH -- pointer: tape buffer/screen scrolling",	      /* ad */
X  "EAL -- tape end addresses / end of program",		      /* ae */
X  "EAH -- tape end addresses / end of program",		      /* af */
X  "CMP0 -- tape timing constants",			      /* b0 */
X  "TEMP",						      /* b1 */
X  "TAPE1 -- address of tape buffer",			      /* b2 */
X  "TAPE1+1 -- address of tape buffer",			      /* b3 */
X  "BITTS,SNSW1 -- RS232 trns bit count",		      /* b4 */
X  "NXTBIT,DIFF -- RS232 TRNS next bit to be sent",	      /* b5 */
X  "RODATA,PRP -- rs232 trns byte buffer",		      /* b6 */
X  "FNLEN -- length current file name str",		      /* b7 */
X  "LA -- current file logical addr",			      /* b8 */
X  "SA -- current file 2ndary addr",			      /* b9 */
X  "FA -- current file device addr",			      /* ba */
X  "FNADR -- addr current file name str",		      /* bb */
X  "FNADR+1 -- addr current file name str",		      /* bc */
X  "ROPRTY,OCHAR -- rs232 trns parity buffer",		      /* bd */
X  "FSBLK -- cassette read block count",			      /* be */
X  "DRIVE,MYCH -- serial word buffer",			      /* bf */
X  "CAS1 -- Cassette manual/cntrled switch (updated during irq)", /* c0 */
X  "TRACK,STAL -- ??, I/O start address (lo)",		      /* c1 */
X  "SECTOR,STAH -- ??, I/O start address (hi)",		      /* c2 */
X  "MEMUSS,TMP2 -- Cassette load temps (2 bytes)",	      /* c3 */
X  "MEMUSS,TMP2 -- Cassette load temps (2 bytes)",	      /* c4 */
X  "DATA -- tape read/write data",			      /* c5 */
X  "BA -- bank for current load/save/verify operation",	      /* c6 */
X  "FNBANK -- bank where current FN is found (at 'fnadr')",    /* c7 */
X  "RIBUF -- RS232 input buffer pointer",		      /* c8 */
X  "RIBUF+1 -- RS232 input buffer pointer",		      /* c9 */
X  "ROBUF -- rs232 output buffer pointer",		      /* ca */
X  "ROBUF+1 -- rs232 output buffer pointer",		      /* cb */
X  "KEYTAB -- keyscan table pointer",			      /* cc */
X  "KEYTAB+1 -- keyscan table pointer",			      /* cd */
X  "IMPARM -- PRIMM utility string pointer",		      /* ce */
X  "IMPARM+1 -- PRIMM utility string pointer",		      /* cf */
X  "NDX -- index to keyboard queue",			      /* d0 */
X  "KYNDX -- pending function key flag",			      /* d1 */
X  "KEYIDX -- index into pending function key string",	      /* d2 */
X  "SHFLAG -- keyscan shift key status",			      /* d3 */
X  "SFDX -- keyscan current key index",			      /* d4 */
X  "LSTX -- keyscan last key index",			      /* d5 */
X  "CRSW -- <CR> input flag",				      /* d6 */
X  "MODE -- 40/80 column mode flag",			      /* d7 */
X  "GRAPHM -- text/graphic mode flag",			      /* d8 */
X  "CHAREN -- RAM/ROM vic character fetch flag (bit-2)",	      /* d9 */
X  "KEYSIZ,SEDSAL -- pointers for movlin",		      /* da */
X  "KEYLEN,BITMSK -- temporary for tab & line wrap routines",  /* db */
X  "KEYNUM,SAVER -- another temporary place to save a reg.",   /* dc */
X  "KEYNXT,SEDEAL",					      /* dd */
X  "KEYBNK,SEDT1 -- savpos",				      /* de */
X  "KEYTMP,SEDT2 -- ?savpos?",				      /* df */
X  "PNT -- pointer to current line (text)",		      /* e0 */
X  "PNT+1 -- pointer to current line (text)",		      /* e1 */
X  "USER -- pointer to current line (attribute)",	      /* e2 */
X  "USER+1 -- pointer to current line (attribute)",	      /* e3 */
X  "SCBOT -- window lower limit",			      /* e4 */
X  "SCTOP -- window upper limit",			      /* e5 */
X  "SCLF -- window left margin",				      /* e6 */
X  "SCRT -- window right margin",			      /* e7 */
X  "LSXP -- current input column start",			      /* e8 */
X  "LSTP -- current input line start",			      /* e9 */
X  "INDX -- current input line end",			      /* ea */
X  "TBLX -- current cursor line",			      /* eb */
X  "PNTR -- current cursor column",			      /* ec */
X  "LINES -- maximum number of screen lines",		      /* ed */
X  "COLUMNS -- maximum number of screen columns",	      /* ee */
X  "DATAX -- current data to print",			      /* ef */
X  "LSTCHR -- previous char printed (for <esc> test)",	      /* f0 */
X  "COLOR -- curr attribute to print (default fgnd color)",    /* f1 */
X  "TCOLOR -- saved attrib to print ('insert' and 'delete')",  /* f2 */
X  "RVS -- reverse mode flag",				      /* f3 */
X  "QTSW -- quote mode flag",				      /* f4 */
X  "INSRT -- insert mode flag",				      /* f5 */
X  "INSFLG -- auto-insert mode flag",			      /* f6 */
X  "LOCKS -- disables <shift><C=>,<ctrl>s",		      /* f7 */
X  "SCROLL -- disables screen scroll, line linker",	      /* f8 */
X  "BEEPER -- disables <ctrl>G",				      /* f9 */
X  "user zpg",					/* $fa */
X  "user zpg",					/* $fb */
X  "user zpg",					/* $fc */
X  "user zpg",					/* $fd */
X  "user zpg",					/* $fe */
X  "LOFBUF"
X};
FRIDAY_NIGHT
echo extracting - dsm.c
sed 's/^X//' > dsm.c << 'FRIDAY_NIGHT'
X /* Copyright, 1986 by Eric Green
X    All Rights Reserved, with following exceptions:
X
X   1) Right of duplication: Right of duplication granted to all, under
Xthe condition that 
X      a) source code to this file must be provided, and cannot be
Xpackaged seperately from the binary code
X      b) this copyright notice is left intact
X      c) right of duplication cannot be denied to any who recieve this file.
X
X   2) Right of derivative works: I hereby grant permission for all to
Xfreely modify this work. However, note that all derivative works
Xbecome property of Eric Green under copyright law, and thereby must
Xabide by the conditions of this copyright.
X
X*/
X
X#include <stdio.h>
X#include "tables.h"
X
X#ifndef lint
Xstatic char *copyright_notice = "Copyright 1986 by Eric Green";
X#endif
X
X/* 
X  program: dsm.c
X  purpose: disassemble a 6502 machine code file, generating C-128-specific
X    comments (although that is alterable by changing the .labels file or
X    for zero page, changing tables.h).
X  Author: Eric Green ( {akgua,ut-sally}!usl!{elg,usl-pc!jpdres10} )
X  program history: 
X   Version 1.0:
X   This is the second "C" program I've ever written (the first was a "grep").
X   It was programmed in its entirety on July 25, 1986, in one massive
X   hack attack. The .labels file, however, wasn't complete -- I can't type
X   that fast! Thus, if you think it looks sloppy, it probably is.
X
X   July 26 - added in to print hash table statistics (I'm paranoid),
X             print labels in front of their addresses, etc.,
X	     print out when we're in various buffers
X
X   July 28 - add in to print zero-page stuff for 3-byte instructions, too.
X
X*/
X
X
Xstatic  int pc;
Xstatic  int temp_mode;
Xstatic  int temp_length;
Xstatic  int op_lobyte;
Xstatic  int op_hibyte;
Xstatic  int op;
Xstatic  int op_address;
X
X
X/* note: if you ever expand this, it must be a large prime number */
X#define MAX_HASH_SIZE 2003
X
Xstatic int hashtab[MAX_HASH_SIZE];	    /* addresses to hash into */
Xstatic char *hashstring[MAX_HASH_SIZE];	    /* strings describing those
X					       addresses */
X
X/* hash table statistics -- I'm curious to know how efficient my algorithm
X   is. */
Xstatic int hash_calls = 0;                /* total calls to hash function */
Xstatic int total_hashes = 0;              /* calls + collisions */
X
Xmain()
X{
X  /* We shouldn't have any arguments -- the beginning address is the first
X     two bytes of the file, we just read from std. input, write to std.
X     output. */
X  
X  int index;
X
X  init_hash();				    /* init the hash table */
X  read_hash();				    /* fill it from ".hash" */
X
X  pc =  getchar();
X  pc = pc+getchar()*256;
X    
X  while ( (op=getchar()) != EOF)
X    {
X      index = hash (pc);
X      if (hashtab[index] != -1)
X	printf("         %s",hashstring[index]);
X      else
X	check_page(pc>>8);
X      temp_mode = mode[op];
X      temp_length = length[temp_mode];
X      if (temp_length == 3)
X	{
X	  op_lobyte = getchar();
X	  op_hibyte = getchar();
X	  op_address = op_hibyte*256+op_lobyte;
X	  printf ("%04x:%02x %02x %02x  %s %s%04x%s ;",pc,op,op_lobyte,op_hibyte,opcode[op],before[temp_mode],op_address,after[temp_mode]);
X	}
X      else if (temp_length == 2)
X	{
X	  op_lobyte = getchar();
X	  op_address = op_lobyte;
X	  if (temp_mode == 9)
X	    { do_rel(); }
X	  else
X	    printf ("%04x:%02x %02x     %s %s%02x%s ;",pc,op,op_lobyte,opcode[op],before[temp_mode],op_lobyte,after[temp_mode]);
X	}
X      else
X	printf ("%04x:%02x        %s %s%s ;",pc,op,opcode[op],before[temp_mode],after[temp_mode]);
X      print_chars();
X      if (temp_length == 2)
X	{
X	  if ( (temp_mode != 2) && (temp_mode != 13) && (temp_mode != 9) )
X	    printf (" %s\n",zero_page[op_lobyte]);
X	  else
X	    putchar ('\n');
X	}
X      else if (temp_length == 3)
X	hash_thingy(op_address);
X      else
X	putchar ('\n');
X      if ( (strcmp(opcode[op],"jmp")==0) || (strcmp(opcode[op],"rts")==0))
X	puts("-----------------------------------------\n");
X      pc = pc + temp_length;
X    }
X  printf("\n Hash calls=%d, total hashes=%d.\n",hash_calls,total_hashes);
X}
X
Xprint_chars()
X{
X  int ch;
X  int count;
X
X  ch = convert(op);
X  putchar(ch);
X  if (temp_length > 1)
X    {
X      ch = convert(op_lobyte);
X      putchar(ch);
X    }
X  else
X    putchar(' ');
X  if (temp_length > 2)
X    {
X      ch = convert(op_hibyte);
X      putchar(ch);
X    }
X  else
X    putchar(' ');
X  putchar(' ');
X}
X
Xint convert (ch)
X     int ch;
X{
X  int new;
X  new = '.';
X  if ( (ch > 31) && (ch < 65))
X    { new=ch;}
X  else if ( (ch > 64) && (ch < 91))
X    { new=ch+32;}
X  else if ( (ch > 90) && (ch < 96))
X    { new = ch;}
X  else if ( (ch>96) && (ch<123))
X    { new = ch-32;}
X  else if ( (ch>192) && (ch<219))
X    new = ch-96;
X  return(new);
X}
X
Xdo_rel()
X{
X  if (op_lobyte < 128)
X    {
X      op_address = op_lobyte+pc+2;
X    }
X  else
X    {
X      op_address = pc-(256-op_lobyte)+2;
X    }
X
X  printf ("%04x:%02x %02x     %s %s%04x%s ;",pc,op,op_lobyte,opcode[op],before[temp_mode],op_address,after[temp_mode]);
X}
X
Xinit_hash()				    /* init hashtab to -1 */
X{
X  int counter;
X  
X  for (counter=0;counter<MAX_HASH_SIZE;counter++)
X    hashtab[counter]= (-1);
X}
X
Xint hash(address)
X     int address;
X{
X  int guard;
X  int index;
X
X  hash_calls++;
X  guard = 0;
X  index = (address*3) % MAX_HASH_SIZE;
X  while ( (hashtab[index] != address) && (hashtab[index] != -1) &&
X	  (++guard < MAX_HASH_SIZE*2 ))
X    {
X      index = (index*3) % MAX_HASH_SIZE;
X    }
X  if (guard == MAX_HASH_SIZE*2)
X    {
X      printf("Error! HAsh_thingy overflow!\n");
X      exit(2);
X    }
X  total_hashes = total_hashes + 1 + guard;
X  return(index);
X}
X
Xhash_thingy(address)
X     int address;
X{
X  int index;
X
X  index = hash(address);
X  if (hashtab[index]==-1)
X    {
X      if (check_page(op_hibyte) == 0)
X	putchar('\n');
X    }
X  else
X    printf(" %s",hashstring[index]);
X}
X
X
Xint check_page(page)
X{
X  int returnflag = 1;
X
X  switch (page)
X    {
X    case 0:
X      printf(" %s\n",zero_page[op_lobyte]); break;
X    case 1:
X      puts(" 8510 CPU stack"); break;
X    case 4:
X    case 5:
X    case 6:
X    case 7:
X      puts(" VICSCN -- VIC 40 column text screen"); break;
X    case 8:
X    case 9:
X      puts(" BASIC run-time stack"); break;
X    case 0x0c:
X      puts(" rs-232 input buffer"); break;
X    case 0x0d:
X      puts(" rs-232 output buffer"); break;
X    case 0x10:
X      puts(" Programmable function key data"); break;
X    case 0xd8:
X    case 0xd9:
X    case 0xda:
X    case 0xdb:
X      puts(" VIC color matrix (nybbles)"); break;
X    default:
X      returnflag = 0;
X    }
X  return(returnflag);
X}
X
X
Xstatic char input_line[256];		    /* line we're reading in to
X					       put into the hash table */
X
Xread_hash()
X{
X  int index;
X  FILE *input_file;
X  int address;
X  char number[5];
X  char *rest;
X
X  input_file = fopen (".labels","r");
X  if (input_file == NULL)
X    return(0);
X  while ( fgets(input_line,255,input_file) != NULL)
X    {
X      if (input_line[0] != '#')
X	{
X	  input_line[4]=0;
X	  sscanf (input_line,"%x",&address);
X	  index = hash(address);
X	  hashtab[index]=address;
X	  rest = &input_line[5];
X  /*      printf ("%04x %d %s\n",address,index,rest); */
X	  hashstring[index]=malloc(strlen(rest)+1);
X	  strcpy (hashstring[index],rest);
X	}
X    }
X  printf("\nHash calls=%d, total hashes = %d\n\n",hash_calls,total_hashes);
X}    
X
FRIDAY_NIGHT
-- 

      Eric Green {akgua,ut-sally}!usl!elg
        (Snail Mail P.O. Box 92191, Lafayette, LA 70509)
          Bayou Telecommunication's ML guru, USL student

" In the beginning the Universe was created. This has made a lot of
 people very angry and been widely regarded as a bad move."