[comp.sys.cbm] 6502 disassembler for UNIX

carus@cbnewsc.ATT.COM (bryce.w.carus) (06/20/89)

Thanks to all who steered me to the two sources for a 6502 disassembler. The
one I chose to work with was Eric Green's DSM - 128 specific code. I've
modified it for the 64 and did some minor touch-ups. It works well for my
purposes. The output is similar to standard CBM monitors with
extensions...specifically, it displays ASCII equivalents of the hex code and
adds comments that may be contained in the tables & labels files.
: ---------CUT HERE---------
: This is a shar archieve.  Extract with sh, not csh.
: The rest of this file will extract:
:  drp.c drp.doc drp.labels drp.tables.h
echo x - drp.c
sed 's/^X//' > drp.c << '!EOR!'
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#define EOF (-1) /* same as stdio.h */
X#define NULL 0   /* same as stdio.h */
X#include "drp.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
X/* 
Xprogram: drp.c - modified by Bryce W. Carus from dsm.c (c128 version).
X            (carus@cbnewsc.att.com)
X
Xfiles:  drp.c           from dsm.c
X        drp.labels      from .labels
X        drp.tables.h    from tables.h
X
Xpurpose: disassemble a 6502 machine code file, generating C-64-specific
X         comments.
X
Xusage:  compile drp.c and rename (eg:mon64).
X        then...mon64 < binary_file [ > dis_file]
X
X        note 1: if "drp.labels" file is not in the same dir as drp.c, then the
X                comments in this external file will not be read.
X        note 2: the low byte/hi byte starting address must be added to the
X                start of the binary file to be disasembled.
X
Xdrp.c program history: 
X
X    Version 1.0:
X    June 7, 1989 - modified for c64 by B.W.Carus.
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 addr's */
X
X/* hash table statistics -- to see how efficient algorithm 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(); /* fill hash table w/ (-1)... */
X    read_hash(); /* ...now fill it from "drp.labels" */
X
X    pc =  getchar();    /* from in_file...a.out < in_file > out_file */
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],
X                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            { 
X                do_rel(); 
X            }
X            else
X                printf ("%04x:%02x %02x     %s %s%02x%s ;",pc,op,op_lobyte,opcode[op],before[temp_mode],op_lobyte,
X                    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        (strcmp(opcode[op],"rti")==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; ---never used so commented out...bwc */
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)
Xint ch;
X{
X    int new;
X    new = '.';
X    if ( (ch > 31) && (ch < 65))
X    { 
X        new=ch;
X    }
X    else if ( (ch > 64) && (ch < 91))
X    { 
X        new=ch+32;
X    }
X    else if ( (ch > 90) && (ch < 96))
X    { 
X        new = ch;
X    }
X    else if ( (ch>96) && (ch<123))
X    { 
X        new = ch-32;
X    }
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)
Xint 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)
Xint 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        puts(" Zero Page"); 
X        break;
X    case 1:
X        puts(" 6510 CPU stack"); 
X        break;
X    case 4:
X    case 5:
X    case 6:
X    case 7:
X        puts(" VICSCN -- VIC 40 column text screen"); 
X        break;
X    case 0xd4:
X        puts(" SID sound registers"); 
X        break;
X    case 0xd8:
X        puts(" VIC color ram -lo nibble"); 
X        break;
X    case 0xd9:
X        puts(" VIC color ram -lo nibble"); 
X        break;
X    case 0xda:
X        puts(" VIC color ram -lo nibble"); 
X        break;
X    case 0xdb:
X        puts(" VIC color ram -lo nibble"); 
X        break;
X    case 0xdc:
X        puts(" CIA#1 registers"); 
X        break;
X    case 0xdd:
X        puts(" CIA#2 registers"); 
X        break;
X    case 0xde:
X        puts(" I/O expansion - lo"); 
X        break;
X    case 0xdf:
X        puts(" I/O expansion - hi"); 
X        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]; ---not used so commented out...bwc */
X    char *rest;
X
X    input_file = fopen ("drp.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] != '#') /* ignore file's comment lines */
X        {
X            input_line[4]=0; /* filter fifth position */
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}
!EOR!
echo x - drp.doc
sed 's/^X//' > drp.doc << '!EOR!'
XDRPMON is an adaptation of Eric Green's "DSM" 128 specific disassembler...see
Xcomments within the body of drp.c.
X
XIt was compiled from two files:
X
X    1.  drp.c = the source file.
X    
X    2.  drp.tables.h = opcode tables and ZERO PAGE comments.
X
XA third file (drp.labels), a file containing comment labels not in ZERO PAGE,
Xmust reside in the same directory as the input and a.out files if it's comments
Xare to be included in the disassembly. This is because this file is read by
Xa.out at "run-time". The comment text can, of course, be modified by the user
Xas desired...the format of both files is straight forward.
X    
XCompile "drp.c" and rename resulting "a.out" file to anything desired.
X
XThe "a.out" file will compile without drp.labels.
X
X--------------------------------------------
XUsage: a.out < bin_input_file > output_file
X--------------------------------------------
X
XThe "bin_input_file" to be dis-assembled must contain the hex starting address
X(st'd CBM lo byte, hi byte format) as the first two characters.
X
XBryce W. Carus
X7jun89
Xcarus@cbnewsc.att.com
!EOR!
echo x - drp.labels
sed 's/^X//' > drp.labels << '!EOR!'
X# This file is an optional part of "drp.c".
X# It is a list of labels for the c64 specific 6510(6502) disassembler.
X#
X# This file, along with the a.out and binary input files, must be in the
X# same directory in order to have the comments included.
X#
X# There CANNOT be blank lines.
X#
X# Bryce W. Carus - 7jun89 - v1.0
X#
X0100,STACK -- 6510 stack...ends at 01ff
X01ff,BUF-1 -- input buffer...ends at 0258
X0200,BUF -- input buffer...ends at 0258
X0259,LAT -- Kernal's active logical file num's
X0263,FAT -- Kernal's device num's for each logical
X026d,SAT -- Kernal's secondary addr for each logical
X0276,KEYD-1 -- Keyboard buffer...ends at 0280
X0277,KEYD -- Keyboard buffer...ends at 0280
X0281,MEMSTR -- start of memory pointer
X0282,MEMSTR+1 -- start of memory pointer
X0283,MEMSIZ -- end of memory pointer
X0284,MEMSIZ+1 -- end of memory pointer
X0285,TIMOUT -- IEEE
X0286,COLOR -- cursor color
X0287,GDCOL -- color under cursor
X0288,HIBASE -- top page of screen
X0289,XMAX -- max keyb'd buff
X028a,RPTFLG -- repeater keys flag
X028b,KOUNT -- delay between repeats
X028c,DELAY -- delay before repeats
X028d,SHFLG -- SHIFT/CTRL/LOGO flag
X028e,LSTSHF -- last SHIFT/CTRL/LOGO flag
X028f,KEYLOG -- vector to keybd setup
X0290,KEYLOG+1 -- vector to keybd setup
X0291,MODE -- U/L case toggle enable/disable
X0292,AUTODN -- enable screen scroll
X0293,PSEUDO -- rs-232 fake reg's for 6551
X029f,IRQTMP -- hold irq vector during cassette I/O
X02a1,ENABL -- rs-232 int enabled
X02a2,CIACASS -- cassette activity
X02a5,SCTMP -- temp index to 40 col screen scroll
X02a6,PALNTSC -- PAL/NTSC flag
X02a7,FREBUF -- unused buffer...ends at 02ff
X0300 IERROR -- Vector for print BASIC error (err in .x)
X0301 IERROR+1 -- Vector for print BASIC error (err in .x)
X0302 IMAIN -- vector to main (system direct loop)
X0303 IMAIN+1 -- vector to main (system direct loop)
X0304 ICRNCH -- vector to crunch (tokenization routine)
X0305 ICRNCH+1 -- vector to crunch (tokenization routine)
X0306 IQPLOP -- vector to list BASIC text (char list)
X0307 IQPLOP+1 -- vector to list BASIC text (char list)
X0308 IGONE -- vector to GONE (BASIC char dispatch)
X0309 IGONE+1 -- vector to GONE (BASIC char dispatch)
X030a IEVAL -- vector to BASIC token evaluation
X030b IEVAL+1 -- vector to BASIC token evaluation
X030c SAREG -- hold .a reg for basic sys
X030d SXREG -- hold .x reg for basic sys 
X030e SYREG -- hold .y reg for basic sys
X030f SPREG -- hold .p reg for basic sys
X0310 USRPOK -- jmp for USR fuction
X0311 USRADD -- lo byte, hi byte of USR jmp
X0314 IIRQ -- IRQ RAM vector
X0315 IIRQ+1 -- IRQ RAM vector
X0316 IBRK -- BRK instr. ram vector
X0317 IBRK+1 -- BRK instr. ram vector
X0318 INMI -- NMI vector
X0319 INMI+1 -- NMI vector
X031a IOPEN -- kernal OPEN vector
X031b IOPEN+1 -- kernal OPEN vector
X031c ICLOSE -- kernal CLOSE vector
X031d ICLOSE+1 -- kernal CLOSE vector
X031e ICHKIN -- kernal CHKIN vector
X031f ICHKIN+1 -- kernal CHKIN vector
X0320 ICKOUT -- kernal CHKOUT vector
X0321 ICKOUT+1 -- kernal CHKOUT vector
X0322 ICLRCH -- kernal CLRCHN routine vector
X0323 ICLRCH+1 -- kernal CLRCHN routine vector
X0324 IBASIN -- kernal CHRIN routine vector
X0325 IBASIN+1 -- kernal CHRIN routine vector
X0326 IBSOUT -- kernal CHROUT routine vector
X0327 IBSOUT+1 -- kernal CHROUT routine vector
X0328 ISTOP -- kernal STOP routine vector
X0329 ISTOP+1 -- kernal STOP routine vector
X032a IGETIN -- kernal GETIN routine vector
X032b IGETIN+1 -- kernal GETIN routine vector
X032c ICLALL -- kernal CLALL routine vector
X032d ICLALL+1 -- kernal CLALL routine vector
X032e USRCMD -- not used
X032f USRCMD+1 -- not used
X0330 ILOAD -- kernal LOAD routine vector
X0331 ILOAD+1 -- kernal LOAD routine vector
X0332 ISAVE -- kernal SAVE routine vector
X0333 ISAVE+1 -- kernal SAVE routine vector
X0334 UNUSED
X0335 UNUSED
X0336 UNUSED
X0337 UNUSED
X0338 UNUSED
X0339 UNUSED
X033a UNUSED
X033b UNUSED
X033c TBUFFER -- cassette buffer
X03fc UNUSED
X03fd UNUSED
X03fe UNUSED
X03ff UNUSED
X0400 VICSCN -- default screen ends at $07e7
X0500 VICSCN+100 -- default screen ends at $07e7
X0600 VICSCN+200 -- default screen ends at $07e7
X0700 VICSCN+300 -- default screen ends at $07e7
X07f8 SPSHP -- sprite shape default buff, ends at $07ff
X0800 SBT -- start of BASIC text
X0810 SBT+1 -- start of BASIC text
Xa000 CSV -- BASIC cold start vector
Xa002 WSV -- BASIC warm start vector
Xbdcd LINPRT -- output num in ASCII decimal
Xd000 SP0x -- sprite 0 x-location
Xd001 SP0y -- sprite 0 y-location
Xd002 SP1x -- sprite 1 x-location
Xd003 SP1y -- sprite 1 y-location
Xd004 SP2x -- sprite 2 x-location
Xd005 SP2y -- sprite 2 y-location
Xd006 SP3x -- sprite 3 x-location
Xd007 SP3y -- sprite 3 y-location
Xd008 SP4x -- sprite 4 x-location
Xd009 SP4y -- sprite 4 y-location
Xd00a SP5x -- sprite 5 x-location
Xd00b SP5y -- sprite 5 y-location
Xd00c SP6x -- sprite 6 x-location
Xd00d SP6y -- sprite 6 y-location
Xd00e SP7x -- sprite 7 x-location
Xd00f SP7y -- sprite 7 y-location
Xd010 MSIGX -- SP0-7 MSB x-location 
Xd011 SCROLY -- v scrl, rows, blnk scrn, bitmp, ext color, $d012 hi bit
Xd012 RASTER -- Read/write raster value for IRQ compare 
Xd013 LPENX -- light pen latch x-position
Xd014 LPENY -- light pen latch y-position
Xd015 SPENA -- SP0-7 enable (1=enable)
Xd016 SCROLX -- h scrl, columns, multi, vid reset
Xd017 VXPAND -- SP0-7 vert expand
Xd018 VMCSB -- text base, video base
Xd019 VICIRQ -- VIC interrupt flag register (1=irq occured)
Xd01a IRQMSK -- VIC IRQ enable bits (1=enable)
Xd01b SPBGPR -- SP0-7/background priority (1=sprite)
Xd01c SPMC -- SP0-7 multi/hirez mode (1=multicolor)
Xd01d HXPAND -- SP0-7 horiz expand
Xd01e SPSPCL -- sprite to sprite collision latch
Xd01f SPBGCL -- sprite to background collision latch
Xd020 EXTCOL -- border color
Xd021 BGCOL0 -- background color 0
Xd022 BGCOL1 -- background color 1
Xd023 BGCOL2 -- background color 2
Xd024 BGCOL3 -- background color 3
Xd025 SPMC0 -- sprite multi-color register 0
Xd026 SPMC1 -- sprite multi-color register 1
Xd027 SP0COL -- sprite 0 color
Xd028 SP1COL -- sprite 1 color
Xd029 SP2COL -- sprite 2 color
Xd02a SP3COL -- sprite 3 color
Xd02b SP4COL -- sprite 4 color
Xd02c SP5COL -- sprite 5 color
Xd02d SP6COL -- sprite 6 color
Xd02e SP7COL -- sprite 7 color
Xd400 SIDREG0 -- voice 1 frequency lo
Xd401 SIDREG1 -- voice 1 frequency hi
Xd402 SIDREG2 -- voice 1 pulse width lo
Xd403 SIDREG3 -- voice 1 pulse width hi
Xd404 SIDREG4 -- voice 1 control register
Xd405 SIDREG5 -- voice 1 attack/decay
Xd406 SIDREG6 -- voice 1 sustain/release
Xd407 SIDREG7 -- voice 2 frequency low
Xd408 SIDREG8 -- voice 2 frequency hi
Xd409 SIDREG9 -- voice 2 pulse width lo
Xd40a SIDREG10 -- voice 2 pulse width hi
Xd40b SIDREG11 -- voice 2 control register
Xd40c SIDREG12 -- voice 2 attack/decay
Xd40d SIDREG13 -- voice 2 sustain-release
Xd40e SIDREG14 -- voice 3 frequency lo
Xd40f SIDREG15 -- voice 3 frequency hi
Xd410 SIDREG16 -- voice 3 pulse width lo
Xd411 SIDREG17 -- voice 3 pulse width hi
Xd412 SIDREG18 -- voice 3 control register
Xd413 SIDREG19 -- voice 3 attack/decay
Xd414 SIDREG20 -- voice 3 sustain/release
Xd415 SIDREG21 -- filter cutoff frequency lo
Xd416 SIDREG22 -- filter cutoff freq. hi
Xd417 SIDREG23 -- resonance/filter
Xd418 SIDREG24 -- mode/volume
Xd419 SIDREG25 -- pot x, a/d converter, paddle 1
Xd41a SIDREG26 -- pot y, a/d converter, paddle 2
Xd41b SIDREG27 -- oscillator 3, random number generator
Xd41c SIDREG28 -- envelope generator 3 output
Xdc00 D1PRA -- CIA#1 port A (output keyboard columns)
Xdc01 D1PRB -- CIA#1 port B (input keyboard rows)
Xdc02 D1DDRA - CIA#1 data direction port A
Xdc03 D1DDRB - CIA#1 data direction port B
Xdc04 D1T1L -- CIA#1 timer A lo
Xdc05 D1T1H -- CIA#1 timer A hi
Xdc06 D1T2L -- CIA#1 timer B lo
Xdc07 D1T2H -- CIA#1 timer B hi
Xdc08 D1TOD1 -- CIA#1 TOD tenths
Xdc09 D1TODS -- CIA#1 TOD seconds
Xdc0a D1TODM -- CIA#1 TOD minutes
Xdc0b D1TODH -- CIA#1 TOD hours
Xdc0c D1SDR -- CIA#1 serial data register
Xdc0d D1ICR -- CIA#1 interrupt control register
Xdc0e D1CRA -- CIA#1 control register A
Xdc0f D1CRB -- CIA#1 control register B
Xdd00 D2PRA -- CIA#2 port A bank select, serial bus, rs232
Xdd01 D2PRB -- CIA#2 port B user port, rs232 bits
Xdd02 D2DDRA - CIA#2 data direction port A
Xdd03 D2DDRB - CIA#2 data direction port B
Xdd04 D2T1L -- CIA#2 timer A lo
Xdd05 D2T1H -- CIA#2 timer A hi
Xdd06 D2T2L -- CIA#2 timer B lo
Xdd07 D2T2H -- CIA#2 timer B hi
Xdd08 D2TOD2 -- CIA#2 TOD tenths
Xdd09 D2TODS -- CIA#2 TOD seconds
Xdd0a D2TODM -- CIA#2 TOD minutes
Xdd0b D2TODH -- CIA#2 TOD hours
Xdd0c D2SDR -- CIA#2 serial data register
Xdd0d D2ICR -- CIA#2 interrupt control register
Xdd0e D2CRA -- CIA#2 control register A
Xdd0f D2CRB -- CIA#2 control register B
Xde00 I/O lo expansion 
Xdf00 I/O hi expansion
Xff80 release number of kernal
Xff81 jmp CINT -- init editor & display chips (editor)
Xff84 jmp IOINIT -- init i/o devices (ports,timers,etc.)
Xff87 jmp RAMTAS - init ram & buffers for system
Xff8a jmp RESTOR - restore vectors to initial system
Xff8d jmp VECTOR - change vectors for user
Xff90 jmp SETMSG - control O.S. messages
Xff93 jmp SECND - send SA after listen
Xff96 jmp TKSA - send SA after talk
Xff99 jmp MEMTOP - set/read top of system RAM
Xff9c jmp MEMBOT - set/read bottom of system RAM
Xff9f jmp KEY - scan keyboard (editor)
Xffa2 jmp SETTMO - set timeout in IEEE (reserved)
Xffa5 jmp ACPTR - handshake serial byte in
Xffa8 jmp CIOUT - handshake serial byte out
Xffab jmp UNTLK - send untalk out serial
Xffae jmp UNLSN - send unlisten out serial
Xffb1 jmp LISTN - send listen out serial
Xffb4 jmp TALK - send talk out serial
Xffb7 jmp READSS - return i/o status byte
Xffba jmp SETLFS - set LA, FA, SA
Xffbd jmp SETNAM - set length and file name address
Xffc0 jmp (OPEN) logical file
Xffc3 jmp (CLOSE) logical file
Xffc6 jmp (CHKIN) - set channel in
Xffc9 jmp (CKOUT) - set channel out
Xffcc jmp (CLRCH) - restore default i/o channel
Xffcf jmp (CHRIN) from channel
Xffd2 jmp (CHROUT) to channel
Xffd5 jmp (LOAD) - load from file
Xffd8 jmp (SAVE) - save to file
Xffdb jmp SETTIM - set internal clock
Xffde jmp RDTIM - read internal clock
Xffe1 jmp (STOP) - scan stop key
Xffe4 jmp (GETIN) - read buffered data
Xffe7 jmp (CLALL) - close all files & channels
Xffea jmp UDTIM - update software clock
Xffed jmp SCREEN - read number of rows & columns
Xfff0 jmp PLOT -- read/set x,y cursor 
Xfff3 jmp IOBASE -- return i/o base
Xfffa HARDNMI -- 6510 hardware NMI vector
Xfffb HARDNMI+1 -- 6510 hardware NMI vector
Xfffc HARDRES -- 6510 hardware reset vector
Xfffd HARDRES+1 -- 6510 hardware reset vector
Xfffe HARDIRQ -- 6510 hardware IRQ vector
Xffff HARDIRQ+1 -- 6510 hardware IRQ vector
!EOR!
echo x - drp.tables.h
sed 's/^X//' > drp.tables.h << '!EOR!'
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  "UNUSED", /* 2 */
X  "ADRAY1 -- vector to FP to signed int conversion", /* 3 */
X  "ADRAY1+1 -- vector to FP to signed int conversion", /* 4 */
X  "ADRAY2 -- vector to int to FP conversion", /* 5 */
X  "ADRAY2+1 -- vector to int to FP conversion", /* 6 */
X  "CHARAC -- search char for BASIC text input", /* 7 */
X  "ENDCHAR -- search char for BASIC text termination", /* 8 */
X  "TRMPOS -- cursor's column before last TAB or SPC", /* 9 */
X  "VERCK -- load or verify flag", /* a */
X  "COUNT -- Input buf. ptr/# of subscripts",   /* b */
X  "DIMFLG -- Flag: default array dimension",   /* c */
X  "VALTYP -- Data type: $ff=string,$00=numeric", /* d */
X  "INTFLG -- Data type: $00 = float,$80= integer",       /* e */   
X  "GARBFL -- Flag: LIST/prog token/garbage collection",  /* f */
X  "SUBFLG -- Flag: subscript ref./user func. call",     /* 10 */
X  "INPFLG -- Flag: $00=input,$40=get,$98=read",              /* 11 */
X  "TANSGN -- Flag: sign of TAN or SIN",   /* 12 */
X  "CHANNL -- current CMD channel", /* 13 */
X  "LINNUM -- temp integer value",  /* 14 */
X  "LINNUM+1 -- temp integer value", /* 15 */
X  "TEMPPT -- pointer: temp string stack", /* 16 */
X  "LASTPT -- last temp string address", /* 17 */
X  "LASTPT+1 -- last temp string address", /* 18 */
X  "TEMPST -- stack for temp strings",                    /* $19 */
X  "TEMPST+1 -- stack for temp strings",                  /* $1a */
X  "TEMPST+2 -- stack for temp strings",                  /* $1b */
X  "TEMPST+3 -- stack for temp strings",                  /* $1c */
X  "TEMPST+4 -- stack for temp strings",                  /* $1d */
X  "TEMPST+5 -- stack for temp strings",                  /* $1e */
X  "TEMPST+6 -- stack for temp strings",                  /* $1f */
X  "TEMPST+7 -- stack for temp strings",                  /* $2o */
X  "TEMPST+8 -- stack for temp strings",                  /* $21 */
X  "INDEX -- utility pointer area",                   /* 22 */
X  "INDEX+1 -- utility pointer area",                 /* 23 */
X  "INDEX2 -- utility pointer area",                  /* 24 */
X  "INDEX2+1 -- utility pointer area",                /* 25 */
X  "RESHO -- float. pt. multiplication work area",               /* 26 */
X  "RESHO+1 -- float. pt. multiplication work area",             /* 27 */
X  "RESHO+2 -- float. pt. multiplication work area",             /* 28 */
X  "RESHO+3 -- float. pt. multiplication work area",             /* 29 */
X  "RESHO+4 -- float. pt. multiplication work area",             /* 2a */
X  "TXTTAB -- pointer: start of BASIC text",              /* 2b */
X  "TXTTAB+1 -- pointer: start of BASIC text",            /* 2c */
X  "VARTAB -- pointer: start of BASIC variables",         /* 2d */
X  "VARTAB+1 -- pointer: start of BASIC variables",       /* 2e */
X  "ARYTAB -- pointer: start of BASIC arrays",            /* 2f */
X  "ARYTAB+1 -- pointer: start of BASIC arrays",          /* 30 */
X  "STREND -- pointer: end of bASIC arrays + 1",          /* 31 */
X  "STREND+1 -- pointer: end of BASIC arrays +1",         /* 32 */
X  "FRETOP -- pointer: bottom of string storage",         /* 33 */
X  "FRETOP+1 -- pointer: bottom of string storage",       /* 34 */
X  "FRESPC -- utility string pointer",                /* 35 */
X  "FRESPC+1 -- utility string pointer",           /* 36 */
X  "MAX_MEM_1 -- top of string/variable bank (bank 1)",       /* 37 */
X  "MAX_MEM_1+1 -- top of string/variable bank (bank 1)",      /* 38 */
X  "CURLIN -- current BASIC line number",             /* 39 */
X  "CURLINE+1 --current BASIC line number",           /* 3a */
X  "OLDLIN -- previous BASIC line num", /* 3b */
X  "OLDLIN+1 -- previous BASIC line num", /* 3c */
X  "OLDTXT -- pointer to addr of current BASIC statement", /* 3d */
X  "OLDTXT+1 -- pointer to addr of current BASIC statement", /* 3e */
X  "DATLIN -- current data line number",              /* 3f */
X  "DATLIN+1 -- current data line number",            /* 40 */
X  "DATPTR -- current data line address",             /* 41 */
X  "DATPTR+1 -- current data line address",           /* 42 */
X  "INPPTR -- Vector: input routine",                 /* 43 */
X  "INPPTR+1 -- Vector: input routine",               /* 44 */
X  "VARNAM -- current BASIC variable name",           /* 45 */
X  "VARNAM+1 -- current BASIC variable name",         /* 46 */
X  "VARPNT -- Pointer: current BASIC variable data",    /* 47 */
X  "VARPNT+1 -- Pointer: current BASIC variable data", /* 48 */
X  "FORPNT -- Pointer: index variable for for/next",    /* 49 */
X  "FORPNT+1 -- Pointer: index variable for for/next",    /* 4a */
X  "OPPTR -- math operator table displacement",       /* 4b */
X  "OPPTR+1 -- math operator table displacement",   /* 4c */
X  "OPMASK -- mask for comparisons", /* 4d */
X  "DEFPNT -- pointer to current FN descriptor",   /* 4e */
X  "DEFPNT+1 -- pointer to current FN descriptor", /* 4f */
X  "DSCPNT -- temp pntr to current string descriptor", /* 50 */
X  "DSCPNT+1 -- temp pntr to current string descriptor", /* 51 */
X  "DSCPNT+2 -- temp pntr to current string descriptor", /* 52 */
X  "FOUR6 -- constant for garbage collection", /* 53 */
X  "JMPER -- Jump to function", /* 54 */
X  "JMPER+1 -- Jump to function", /* 55 */
X  "JMPER+2 -- Jump to function", /* 56 */
X  "BNWA -- BASIC numeric work area", /* 57 */
X  "BNWA+1 -- BASIC numeric work area", /* 58 */
X  "BNWA+2 -- BASIC numeric work area", /* 59 */
X  "BNWA+3 -- BASIC numeric work area", /* 5a */
X  "BNWA+4 -- BASIC numeric work area", /* 5b */
X  "BNWA+5 -- BASIC numeric work area", /* 5c */
X  "BNWA+6 -- BASIC numeric work area", /* 5d */
X  "BNWA+7 -- BASIC numeric work area", /* 5e */
X  "BNWA+8 -- BASIC numeric work area", /* 5f */
X  "BNWA+9 -- BASIC numeric work area", /* 60 */
X  "FAC1 -- FP accumulator #1", /* 61 */
X  "FAC1+1 -- FP accumulator #1", /* 62 */
X  "FAC1+2 -- FP accumulator #1", /* 63 */
X  "FAC1+3 -- FP accumulator #1", /* 64 */
X  "FAC1+4 -- FP accumulator #1", /* 65 */
X  "FAC1+5 -- FP accumulator #1", /* 66 */
X  "FACSGN -- FP #1 sign", /* 67 */
X  "BITS -- FP #1 overflow", /* 68 */
X  "FAC2 -- FP accumulator #2", /* 69 */
X  "FAC2+1 -- FP accumulator #2", /* 6a */
X  "FAC2+2 -- FP accumulator #2", /* 6b */
X  "FAC2+3 -- FP accumulator #2", /* 6c */
X  "FAC2+4 -- FP accumulator #2", /* 6d */
X  "FAC2+5 -- FP accumulator #2", /* 6e */
X  "ARISGN -- sign comp of FP#1 to #2", /* 6f */
X  "FACOV -- FP #1 overflow rounder", /* 70 */
X  "FBUFPT -- series eval pntr", /* 71 */
X  "FBUFPT+1 -- series eval pntr", /* 72 */
X  "CHRGET -- sbr to get next char...", /* 73 */
X  "CHRGET -- sbr to get next char...", /* 74 */
X  "CHRGET -- sbr to get next char...", /* 75 */
X  "CHRGET -- sbr to get next char...", /* 76 */
X  "CHRGET -- sbr to get next char...", /* 77 */
X  "CHRGET -- sbr to get next char...", /* 78 */
X  "CHRGET -- sbr to get next char...", /* 79 */
X  "CHRGET-TXPTR -- sbr to get next char...", /* 7a */
X  "CHRGET-TXPTR -- sbr to get next char...", /* 7b */
X  "CHRGET-POINTB -- sbr to get next char...", /* 7c */
X  "CHRGET-POINTB -- sbr to get next char...", /* 7d */
X  "CHRGET-POINTB -- sbr to get next char...", /* 7e */
X  "CHRGET-POINTB -- sbr to get next char...", /* 7f */
X  "CHRGET-POINTB -- sbr to get next char...", /* 80 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 81 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 82 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 83 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 84 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 85 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 86 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 87 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 88 */
X  "CHRGET-POINTB -- sbr to get next char...", /* 89 */
X  "CHRGET-EXIT -- sbr to get next char...", /* 8a */
X  "RNDX -- RND seed value",    /* 8b */
X  "RNDX+1 -- RND seed value",    /* 8c */
X  "RNDX+2 -- RND seed value",    /* 8d */
X  "RNDX+3 -- RND seed value",    /* 8e */
X  "RNDX+4 -- RND seed value",    /* 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 -- cassette error pass1",        /* 9e */
X  "PTR2 -- cassette error pass2",       /* 9f */
X  "TIME -- 65536 jiffies",             /* a0 */
X  "TIME+1 -- 256 jiffies",           /* a1 */
X  "TIME+2 -- units jiffies",           /* a2 */
X  "TDSA -- temp serial bus usage",  /* a3 */
X  "TDSA+1 -- temp serial bus usage", /* a4 */
X  "TDSA+2 -- temp serial bus usage", /* a5 */
X  "BUFPT -- cassette buffer pointer",                /* a6 */
X  "INBIT -- RS232 input bit/cassette temp", /* a7 */
X  "BITCI -- RS232 input bit count,cassette temp",    /* a8 */
X  "RINONE -- RS232 flag-check for start bit", /* a9 */
X  "RIDATA -- RS232 input byte buffer, cassette temp",  /* aa */
X  "RIPRTY -- RS232 input parity/cassette leader 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  "CMP0+1 -- tape timing constants",     /* b1 */
X  "TAPE1 -- start of tape buffer",                 /* b2 */
X  "TAPE1+1 -- start of tape buffer",               /* b3 */
X  "BITTS -- RS232 trns bit count",             /* b4 */
X  "NXTBIT -- RS232 TRNS next bit to be sent",       /* b5 */
X  "RODATA -- 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 -- rs232 trns parity buffer",            /* bd */
X  "FSBLK -- cassette read block count",                  /* be */
X  "MYCH -- serial word buffer",                /* bf */
X  "CAS1 -- tape motor interlock", /* c0 */
X  "STAL -- I/O start address (lo)",            /* c1 */
X  "STAH -- I/O start address (hi)",           /* c2 */
X  "MEMUSS -- Cassette load temp",        /* c3 */
X  "MEMUSS+1 -- Cassette load temp",        /* c4 */
X  "LSTX -- matrix coord of last keypress",                /* c5 */
X  "NDX -- number of chars in keybd buff at $0277",       /* c6 */
X  "RVS -- reverse char flag - 0 = no",    /* c7 */
X  "INDX -- pointer end of input's logical line",             /* c8 */
X  "LXSP -- cursor pos at start of input",           /* c9 */
X  "LYSP -- cursor pos at start of input",            /* ca */
X  "SFDX -- matrix coord of current keypress",              /* cb */
X  "BLNSW -- cursor blink = 0, no =1",                 /* cc */
X  "BLNCT -- countdown to blink cursor",               /* cd */
X  "GDBLN -- char under cursor",              /* ce */
X  "BLNON -- flag for cursor blink on or off",            /* cf */
X  "CRSW -- flag input from screen or keys",                  /* d0 */
X  "PNT -- pointer to addr of current screen line", /* d1 */
X  "PNT+1 -- pointer to addr of current screen line",        /* d2 */
X  "PNTR -- cursor column on current line", /* d3 */
X  "QTSW -- flag if editor in quote mode", /* d4 */
X  "LNMX -- max length of physical screen line", /* d5 */
X  "TBLX -- current physical line number", /* d6 */
X  "TLCP -- ascii val of last char printed", /* d7 */
X  "INSRT -- insert mode flag", /* d8 */
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* d9 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* da */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* db */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* dc */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* dd */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* de */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* df */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e0 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e1 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e2 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e3 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e4 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e5 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e6 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e7 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e8 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* e9 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* ea */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* eb */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* ec */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* ed */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* ee */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* ef */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* f0 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* f1 */ 
X  "LDTB1 -- scrn line link tbl ends @ $f2", /* f2 */ 
X  "USER -- pointer to screen color ram", /* f3 */
X  "USER+1 -- pointer to screen color ram", /* f4 */
X  "KEYTAB -- vector to keyb'd decode table", /* f5 */
X  "KEYTAB+1 -- vector to keyb'd decode table", /* f6 */
X  "RIBUF -- rs232 input buff pointer", /* f7 */
X  "RIBUF+1 -- rs232 input buff pointer", /* f8 */
X  "ROBUF -- rs232 output buff pointer", /* f9 */
X  "ROBUF+1 -- rs232 output buff pointer", /* fa */
X  "zero page free byte",                  /* $fb */
X  "zero page free byte",                  /* $fc */
X  "zero page free byte",                  /* $fd */
X  "zero page free byte",                  /* $fe */
X  "BASZPT -- BASIC's FP to ASCII conv" /* ff */
X};
!EOR!

elg@killer.DALLAS.TX.US (Eric Green) (06/21/89)

in article <1317@cbnewsc.ATT.COM>, carus@cbnewsc.ATT.COM (bryce.w.carus) says:
> Thanks to all who steered me to the two sources for a 6502 disassembler. The
> one I chose to work with was Eric Green's DSM - 128 specific code. I've
> modified it for the 64 and did some minor touch-ups. It works well

Thanks! Hmm... guess that means I don't have to EMAIL it to you? :-)

I have used it on my Amiga, too -- be sure to use the +L option if
compiling it with Manx, and change all the getchar()'s to fgetc(stdin) to
get around Manx'es "agetc" routine (which eats nulls and newlines). 

Alas, I don't do 6502 anymore (nobody wants to pay you to program a 64
:-( ), so I had to do some real digging to find it again (had to
search through about 200 5 1/4" diskettes in three different disk
formats -- I gave up trying to catalog the 64 stuff long ago, if only
someone would come out with DirMaster for the 64!). Glad to see that
someone else had it on-line getting some use out of it.  I'd
appreciate it if someone would EMAIL me the original C-128 version, as
the only version I can seem to find is one later modified for the C-64
(sad, isn't it?).

As an aside, I expected the code to be much worse than it is -- I
didn't understand "C" well at all at the time, heck, I'd seen my first
Unix system about four months prior. I was surprised to find that all
it needed was a few declarations to meet minimal coding standards. 

--
    Eric Lee Green              P.O. Box 92191, Lafayette, LA 70509     
     ..!{ames,decwrl,mit-eddie,osu-cis}!killer!elg     (318)989-9849    
"I have seen or heard 'designer of the 68000' attached to so many names that
 I can only guess that the 68000 was produced by Cecil B. DeMille." -- Bcase