/* ---------------------------------------------------------------------- */
/*                   Copyright (C) 1992 by Natrlich!                     */
/*                      This file is copyrighted!                         */
/*                Refer to the documentation for details.                 */
/* ---------------------------------------------------------------------- */
/* rev. history   1.0 -- original buggy version               */
/*                1.1 -- fixed bcc/bpl bug                    */
/*                1.2 -- fixed dget_j, added ASCII support    */
/*                1.3 -- fixed tables (at LEAST 6 Errors)     */
/*                1.4 -- X drivers, .O65, FF FF done rite,    */
/*                       Boot files                           */
/*                1.5 -- print inverted chars optionally      */
/*                1.6 -- even more boot file support          */
/*                1.7 -- AppleII and C64 support              */
/*                1.8 -- no real changes, actually            */
/* ---------------------------------------------------------- */
#include "defines.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define __BIG_GENERATOR__
#include OSBIND
#include "code.h"
#include "seg.h"
#include "object.h"

#define ATARI  0
#define PLAIN  1
#define C64    2
#define APPLE  3
#define SPARTA 4
#define MODULE 5
#define BOOT   6


#define CHMIN  ' '
#define CHMAX  '~'

#ifdef isprint
# undef isprint
#endif

#define toprint( c)  ((c) & (0x7F | inverted))
#define isprint( c)  ( toprint( c) >= CHMIN && toprint( c) <= CHMAX)
#define chprint( c)  ( isprint( c) ? (char) toprint( c) : '.')

word           disasm(), seg_disasm();
extern char    trc_loss[];
int            maxerrors = 100;

struct
{
   byte  flag,
         secs;
   word  start,
         init;
} boot_header;

struct
{
   word  ffff,
         start,
         end;
} ffff_header;

struct
{
   byte  byte1,
         byte2;
   word  start,
         len;
} feff_header;

struct
{
   byte  byte1,
         len_lsb,
         len_msb;
} fdff_header;

struct
{
   byte  mode, lsb, msb;
   char  id[ 8];
} fcff_header;

struct
{
   char  id[8];
   word  w1;
} fbff_header;

struct
{
   word  start,
         end;
} faff_header;

struct
{
   word  start,
         end;
} apple_header;

struct
{
   word  start,
         end;
} c64_header;


word   __x;
lword  __lx;

void fixheader()
{
   ffff_header.start = dpeek( &ffff_header.start);
   ffff_header.end   = dpeek( &ffff_header.end);
}

#if OS == TOS
   int     tossable;
#endif


char  cminusminus[] = "; ---------------------------------------\n";
FILE  *fq;
int   pcoff,
      showascii = 1,
      showheader,
      pstart,
      inverted,
      filetype;
lword space,
      mspace;
byte  *room;
long  bread;
int   fp;
int   tok_remain;

main( argc, argv)
int   argc;
char  **argv;
{
   static char    infile[ 256],
                  outfile[ 256];
   int            i = 0;

   fq = stdout;      /* done here for some lame Amiga cc */
#if ! VERSION
   chk_tables();
#endif
   while( ++i < argc)
   {
      if( *argv[i] == '-')
         switch( Xtolower( argv[i][1]))
         {
#if OS == TOS
            case 't' :
               tossable = ! tossable;
               break;
#endif
            case 'f' :
               switch( Xtolower( argv[ i][2]))
               {
                  case 'o' :
                     filetype = MODULE;
                     break;

                  case 's' :
                     filetype = SPARTA;
                     break;

                  case 'p' :
                     filetype = PLAIN;
                     if( ! sscanf( &argv[ i][ 3], "%X", &pstart) ||
                         ! pstart)
                        nferror("Missing start address");
                     break;

                  case 'b' :
                     filetype = BOOT;
                     break;

                  case 'a' :
                     filetype = APPLE;
                     break;

                  case 'c' :
                     filetype = C64;
                     break;

                  case 0   :
                  case 'x' :
                     filetype = ATARI;
                     
                  default  :
                     goto usage;                     
               }
               break;


            case 'a' :
               showascii = ! showascii;
               break;

#ifdef __DATE__
            case ':' :
               fputs( __DATE__, stderr);
# ifdef __TIME__
               fprintf( stderr, " %s", __TIME__);
# endif
               putc( '\n', stderr);
               break;
#endif
            case 'v' :
               fprintf( stderr, "disasm65 v1.8 (c) 1992 by Natuerlich!\
 -- disassembles 6502 binaries\n");
               break;

            case 'i' :
               inverted = ~inverted;
               break;

            case 'h' :
               showheader = ! showheader;
               break;

            case 'p' :
               pcoff = ! pcoff;
               break;

         }
      else
         if( ! infile[0])
            strcpy( infile, argv[i]);
         else
            if( ! outfile[0])
               strcpy( outfile, argv[i]);
            else
               goto usage;
   }
   if( ! infile[0])
      goto usage;

#if OS == MSDOS
   _fmode = O_BINARY;
#endif
   if( (fp = (int) Fopen( infile, OPEN_R)) < 0)
      nferror("File open failed");
   if( outfile[0] && ! (fq = fopen( outfile, "w")))
      nferror("File creation failed");

   switch( filetype)
   {
      case APPLE :
         if( (bread = Fread( fp, 4L, &apple_header)) < 4L)
            nferror( trc_loss);
         seg_disasm( dpeek( &apple_header.start),
                     dpeek( &apple_header.end), 0);
         break;


      case C64   :
      {
         word pos;

         if( (bread = Fread( fp, 2L, &c64_header)) < 2L)
            nferror( trc_loss);
         pos = Fseek( 0L, fp, SEEK_END) - 2;
         Fseek( 2L, fp, SEEK_SET);
         seg_disasm( dpeek( &c64_header), pos, 0);
      }
      break;


      case PLAIN :
      {
         word pos;

         pos = (word) Fseek( 0L, fp, SEEK_END);
         Fseek( 0L, fp, SEEK_SET);
         seg_disasm( pstart, pos, 0);
      }
      break;

      case BOOT :
      {
         word  start;

         if( (bread = Fread( fp, 6L, &boot_header)) < 6L)
            nferror( trc_loss);
         start = dpeek( &boot_header.start);
         if( showheader)
         {
            fputs( cminusminus, fq);
            fprintf( fq, "; Boot header - Flag $%02X  %d sectors\n\
; Address : $%04X  Init: $%04X\n",
                        boot_header.flag, (word) boot_header.secs,
                        start, dpeek( &boot_header.init));
            fputs( cminusminus, fq);
         }
         if( ! showascii && pcoff)
            fprintf( fq, "; link with  -x%04X\n\n", dpeek( &boot_header.init));
         seg_disasm( start + 6, boot_header.secs * 0x80 - 6, 0);
      }
      break;


      case SPARTA :
         if( do_sparta())
            do_atari();
         break;


      case MODULE :
         do_module();
         break;


      case ATARI  :
         if( (bread = Fread( fp, 6L, &ffff_header)) < 6L)
            nferror( trc_loss);
         if( ffff_header.ffff  != 0xFFFF)
            nferror("Not a $FF $FF header");
         do_atari();
   }

#if OS == TOS
   keypress();
#endif
   return(0);

usage:
#if OS == TOS
   fputs( "usage: disasm65 [-{tpiahvf}] infile [outfile]\n", stderr);
#else
   fputs( "usage: disasm65 [-{fahvip}] infile [outfile]\n", stderr);
#endif
   fputs( "\
\t-p\t: turn off the dump\n\
\t-i\t: don't print inverted stuff\n\
\t-a\t: turn off ASCII dump\n\
\t-h\t: show info about the binary headers\n\
\t-v\t: version\n\
\t-f[type]: input file type (default: -fx)\n\
\t   o\t: .O65 module\n\
\t   a\t: Apple II ProDOS binary\n\
\t   c\t: C64 binary\n\
\t   pxxxx: plain 6502 binary (xxxx gives start address)\n\
\t   s\t: SpartaDOS X-Cartridge drivers\n\
\t   x\t: Atari 8bit FF FF binaries\n", stderr);
#if OS == TOS
   fputs( "\t-t\t: wait for keypress before exitin'\n", stderr);
   keypress();
#endif
   return( 1);
}


do_atari()
{
   lword bread;

   for(;;)
   {
      fixheader();
      if( showheader)
      {
         fputs( cminusminus, fq);
         fprintf( fq, "; FFFF header  start : $%04X  end : $%04X\n",
                     ffff_header.start, ffff_header.end);
         fputs( cminusminus, fq);
      }
      fprintf( fq, "\n\t\t   * =  $%04X\n\n",
                  ffff_header.start, ffff_header.ffff);
      seg_disasm( ffff_header.start,
                  (1 + ffff_header.end - ffff_header.start), 0);
      if( (bread = Fread( fp, 4L, ((char huge *) &ffff_header) + 2)) <= 0)
         break;
      if( bread < 4)
         nferror("Garbage at end of segment");
      if( ffff_header.start == 0xFFFF)
      {
         ffff_header.ffff  = ffff_header.start;
         ffff_header.start = ffff_header.end;
         if( (bread = Fread( fp, 2L, (char huge *) &ffff_header + 4)) <= 0 ||
             bread < 2)
            nferror("It's a trashed binary");
      }
   }
}


do_sparta()
{
   word  head, len, pc, byteit,
         oldpcoff = pcoff,
         oldshowascii = showascii;

   for(;;)
   {
      if( (bread = Fread( fp, 2L, &head)) <= 0 || (bread == 1 && head < 256))
         break;
      if( bread != 2)
         nferror("File trunctated or mangled");
      len = dpeek( &head);

      switch( len)
      {
         case 0xFFFF :
            ffff_header.ffff = 0xFFFF;
            if( (bread = Fread( fp, 4L, (char huge *) &ffff_header + 2)) != 4L)
               nferror( trc_loss);
            return( 1);

         case 0xFFFE :
            if( (bread = Fread( fp, 6L, &feff_header)) != 6L)
               nferror( trc_loss);
            len = dpeek( &feff_header.len);
            pc  = dpeek( &feff_header.start);
            if( showheader)
            {
               fputs( cminusminus, fq);
               fprintf( fq, "; FEFF header  %02X %02X  start : $%04X  len : $%04X\n",
                           feff_header.byte1, feff_header.byte2,
                           pc, len);
               fputs( cminusminus, fq);
            }
            fprintf( fq, "\n\t\t   * =  $%04X\n\n", pc);
            if( feff_header.byte2 > 0x80)
               continue;
            byteit = 0;
            break;

         case 0xFFFD :
            if( (bread = Fread( fp, 3L, &fdff_header)) != 3L)
               nferror( trc_loss);
            len = dpeek( &fdff_header.len_lsb);
            if( showheader)
            {
               fputs( cminusminus, fq);
               fprintf( fq, "; FDFF header  $%02X  len : $%04X\n",
                           fdff_header.byte1,
                           len);
               fputs( cminusminus, fq);
            }
            showascii = 0;
            pcoff = byteit = 1;
            break;

         case 0xFFFC :
            if( (bread = Fread( fp, 11L, &fcff_header)) != 11L)
               nferror( trc_loss);
            if( showheader)
            {
               fputs( cminusminus, fq);
               fputs( "; FCFF header (Export address @ loadtime)\n", fq);
               fputs( cminusminus, fq);
            }
            fprintf( fq, "\t\t   .byte $%02X\n\t\t   .word $%02X%02X\n\t\t \
  .byte \"%8.8s\"\n",
                        fcff_header.mode,
                        fcff_header.msb, fcff_header.lsb,
                        fcff_header.id);
            continue;

         case 0xFFFB :
            if( (bread = Fread( fp, 10L, &fbff_header)) != 10L)
               nferror( trc_loss);
            if( showheader)
            {
               fputs( cminusminus, fq);
               fputs( "; FBFF header (Import address @ loadtime)\n", fq);
               fputs( cminusminus, fq);
            }
            fprintf( fq, "\t\t   .byte \"%8.8s\"\n\t\t   .word $%04X\n",
                        fbff_header.id,
                        len = dpeek( &fbff_header.w1));
            showascii = 0;
            pcoff = byteit = 1;
            break;

         case 0xFFFA :
            if( (bread = Fread( fp, 4L, (char huge *) &faff_header)) != 4L)
               nferror( trc_loss);
            pc  = dpeek( &faff_header.start);
            len = dpeek( &faff_header.end);
            if( showheader)
            {
               fputs( cminusminus, fq);
               fprintf( fq, "; FAFF header  start : $%04X  end : $%04X\n",
                           pc, len);
               fputs( cminusminus, fq);
            }
            len = 1 + len - pc;
            fprintf( fq, "\n\t\t   * =  $%04X\n\n", pc);
            byteit = 0;
            break;

         default     :
         {
            static char mess[] = "Unknown SpartaDOS header $FFFF";

            sprintf( mess + 26, "%04X", len);
            nferror( mess);
         }
      }

      pc = seg_disasm( pc, len, byteit);
      showascii = oldshowascii;
      pcoff = oldpcoff;
   }
   return( 0);
}


static char *txlat[] =
{
   "Reloc. code   ",
   "Static data   ",
   "Reloc. .WORDs ",
   "Reloc. .DBYTEs",
   ".DS allocation"
};

do_module()
{
   extern byte huge        *pb;
   extern s_dropped huge   *ps;
   extern lword            bytes, sbytes;
   word                    i;
   word                    pc = DEFORG;

   do_load( fp);
   if( showheader)
   {
      s_dropped huge *p = ps;
      word           plus = 0;

      fputs( cminusminus, fq);
      fprintf( fq, "; SEGMENTS:\n");
      for( i = (word) sbytes; i; i--, p++)
      {
         fprintf( fq, ";\tType: %s  $%04X-$%04X\n",
                     txlat[ p->type], DEFORG + p->index + plus,
                     DEFORG + p->index + plus + p->size - 1);
         if( p->type == S_DS)
            plus += p->size;
      }
      fputs( cminusminus, fq);
   }
   for( i = (word) sbytes; i; i--, pc += ps->size, ps++)
      if( ps->type != S_DS)
      {
         disasm( pc, pb, (lword) ps->size, 0);
         pb += ps->size;
      }
}

word  seg_disasm( pc, len, byteit)
word  pc, len;
int   byteit;
{
   static lword   space,
                  mspace;
   static byte    *room;


      space = (lword) len;
      if( space > mspace)
      {
         if( mspace)
            free( room);
         if( ! (room = (byte *) malloc( (mspace = space))))
            nferror("out of memory");
      }
      if( Fread( fp, space, room) != space)
         nferror("read failed (file truncated ?)");

      return( disasm( pc, room, space, byteit));
}

char
   adc[]="adc", xnd[]="and", asl[]="asl", bcc[]="bcc",
   bcs[]="bcs", beq[]="beq", bit[]="bit", bmi[]="bmi",
   bne[]="bne", bpl[]="bpl", bra[]="bra",xbrk[]="brk",
   bvc[]="bvc", bvs[]="bvs", clc[]="clc", cld[]="cld",
   cli[]="cli", clv[]="clv", cmp[]="cmp", cpx[]="cpx",
   cpy[]="cpy", dea[]="dea", dec[]="dec", dex[]="dex",
   dey[]="dey", eor[]="eor", ina[]="ina", inc[]="inc",
   inx[]="inx", iny[]="iny", jmp[]="jmp", jsr[]="jsr",
   lda[]="lda", ldx[]="ldx", ldy[]="ldy", lsr[]="lsr",
   nop[]="nop", ora[]="ora", pha[]="pha", php[]="php",
   phx[]="phx", phy[]="phy", pla[]="pla", plp[]="plp",
   plx[]="plx", ply[]="ply", rol[]="rol", ror[]="ror",
   rti[]="rti", rts[]="rts", sbc[]="sbc", sec[]="sec",
   sed[]="sed", sei[]="sei", sta[]="sta", stx[]="stx",
   sty[]="sty", stz[]="stz", tax[]="tax", tay[]="tay",
   trb[]="trb", tsb[]="tsb", tsx[]="txa", txa[]="txa",
   txs[]="txs", tya[]="tya", o__[]=".byte";

char  *ops[] =
{
  xbrk, ora, o__, o__, tsb, ora, asl, o__,
   php, ora, asl, o__, tsb, ora, asl, o__,    /*0*/

   bpl, ora, ora, o__, trb, ora, asl, o__,
   clc, ora, ina, o__, trb, ora, asl, o__,    /*1*/

   jsr, xnd, o__, o__, bit, xnd, rol, o__,
   plp, xnd, rol, o__, bit, xnd, rol, o__,    /*2*/

   bmi, xnd, xnd, o__, bit, xnd, rol, o__,
   sec, xnd, dea, o__, bit, xnd, rol, o__,    /*3*/

   rti, eor, o__, o__, o__, eor, lsr, o__,
   pha, eor, lsr, o__, jmp, eor, lsr, o__,    /*4*/

   bvc, eor, eor, o__, o__, eor, lsr, o__,
   cli, eor, phy, o__, o__, eor, lsr, o__,    /*5*/

   rts, adc, o__, o__, stz, adc, ror, o__,
   pla, adc, ror, o__, jmp, adc, ror, o__,    /*6*/

   bvs, adc, adc, o__, stz, adc, ror, o__,
   sei, adc, ply, o__, jmp, adc, ror, o__,    /*7*/

   bra, sta, o__, o__, sty, sta, stx, o__,
   dey, o__, txa, o__, sty, sta, stx, o__,    /*8*/

   bcc, sta, sta, o__, sty, sta, stx, o__,
   tya, sta, txs, o__, stz, sta, stz, o__,    /*9*/

   ldy, lda, ldx, o__, ldy, lda, ldx, o__,
   tay, lda, tax, o__, ldy, lda, ldx, o__,    /*A*/

   bcs, lda, lda, o__, ldy, lda, ldx, o__,
   clv, lda, tsx, o__, ldy, lda, ldx, o__,    /*B*/

   cpy, cmp, o__, o__, cpy, cmp, dec, o__,
   iny, cmp, dex, o__, cpy, cmp, dec, o__,    /*C*/

   bne, cmp, cmp, o__, o__, cmp, dec, o__,
   cld, cmp, phx, o__, o__, cmp, dec, o__,    /*D*/

   cpx, sbc, o__, o__, cpx, sbc, inc, o__,
   inx, sbc, nop, o__, cpx, sbc, inc, o__,    /*E*/

   beq, sbc, sbc, o__, o__, sbc, inc, o__,
   sed, sbc, plx, o__, o__, sbc, inc, o__     /*F*/
};


byte  mode[]=
{
   8, 0xA, 0x0, 0, 2, 2, 2, 0,  8, 1,0xF,0, 0x5, 5, 5, 0,     /*0*/
   9, 0xB, 0xD, 0, 2, 3, 3, 0,  8, 7, 8, 0, 0x5, 6, 6, 0,     /*1*/
   5, 0xA, 0x0, 0, 2, 2, 2, 0,  8, 1,0xF,0, 0x5, 5, 5, 0,     /*2*/
   9, 0xB, 0xD, 0, 3, 3, 3, 0,  8, 7, 8, 0, 0x6, 6, 6, 0,     /*3*/
   8, 0xA, 0x0, 0, 0, 2, 2, 0,  8, 1,0xF,0, 0x5, 5, 5, 0,     /*4*/
   9, 0xB, 0xD, 0, 0, 3, 3, 0,  8, 7, 8, 0, 0x0, 6, 6, 0,     /*5*/
   8, 0xA, 0x0, 0, 2, 2, 2, 0,  8, 1,0xF,0, 0xC, 5, 5, 0,     /*6*/
   9, 0xB, 0xD, 0, 3, 3, 3, 0,  8, 7, 8, 0, 0xE, 6, 6, 0,     /*7*/

   9, 0xA, 0x0, 0, 2, 2, 2, 0,  8, 0, 8, 0, 0x5, 5, 5, 0,     /*8*/
   9, 0xB, 0xD, 0, 3, 3, 4, 0,  8, 7, 8, 0, 0x6, 6, 6, 0,     /*9*/
   1, 0xA, 0x1, 0, 2, 2, 2, 0,  8, 1, 8, 0, 0x5, 5, 5, 0,     /*A*/
   9, 0xB, 0xD, 0, 3, 3, 4, 0,  8, 7, 8, 0, 0x6, 6, 7, 0,     /*B*/
   1, 0xA, 0x0, 0, 2, 2, 2, 0,  8, 1, 8, 0, 0x5, 5, 5, 0,     /*C*/
   9, 0xB, 0xD, 0, 0, 3, 3, 0,  8, 7, 8, 0, 0x0, 6, 6, 0,     /*D*/
   1, 0xA, 0x0, 0, 2, 2, 2, 0,  8, 1, 8, 0, 0x5, 5, 5, 0,     /*E*/
   9, 0xB, 0xD, 0, 0, 3, 3, 0,  8, 7, 8, 0, 0x0, 6, 6, 0      /*F*/
};

#if ! VERSION
chk_tables()
{
   register byte huge   *p = mode;
   register char huge   **q = ops;
   register int         i = 256;

   while( i--)
      if( (*q++ != o__) ^ (*p++ >= 1))
         fprintf( stderr, "Table entry mismatch for op-code $%02X \
 mnemo=\"%s\" mode=%d\n", 255 - i, q[-1], p[-1]);
}
#endif

#define  get_j()           \
{                          \
   pc++;                   \
   if( len--)              \
      j = *p++;            \
   else                    \
      goto fini;           \
}

#define  dget_j()          \
   if( (len - 2) >= 0)     \
   {                       \
      j    = dpeek( p);    \
      and  = j;            \
      shift= peek( p + 1); \
      p   += 2;            \
      len -= 2;            \
      pc  += 2;            \
   }                       \
   else                    \
      goto fini2


#define printpc()    fprintf( fq, "%04X  ", pc)


word  disasm( pc, p, len, byteit)
register word  pc;
byte huge      *p;
word           byteit;
long           len;
{
   register word     i, j;
   register byte     shift, and;

   while( len--)
   {
      if( ! pcoff)
         printpc();
      else
         putc( '\t', fq);
      i = *p++;
      pc++;
      if( byteit)
      {
         if( ! pcoff)
            fprintf( fq, "%02X", i);
         fprintf( fq, "\t   .byte $%02X", i);
         if( showascii)
            fprintf( fq, "\t\t; \"%c\"", chprint( i));
      }
      else
         switch( mode[i])
         {
            case 0x0 :
               if( ! pcoff)
                  fprintf( fq, "%02X", i);
               fprintf( fq, "\t   %s", ops[ i]);
               if( ops[i] == o__)
                  fprintf( fq, " $%02X", i);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c\"", chprint( i));
               break;

            case 0x1 :
               get_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X", i, j);
               fprintf( fq, "\t   %s #", ops[i]);
               if( j < 0xA)
                  fprintf( fq, "%d", j);
               else
                  fprintf( fq, "$%X", j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c\"", chprint( i), chprint( j));
               break;

            case 0x2 :
               get_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X", i, j);
               fprintf( fq, "\t   %s $%02X", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c\"", chprint( i), chprint( j));
               break;

            case 0x3 :
               get_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X", i, j);
               fprintf( fq, "\t   %s $%02X,X", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c\"", chprint( i), chprint( j));
               break;

            case 0x4 :
               get_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X", i, j);
               fprintf( fq, "\t   %s $%02X,Y", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c\"", chprint( i), chprint( j));
               break;

            case 0x5 :
               dget_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X %02X", i,(word) and,(word) shift);
               fprintf( fq, "\t   %s $%04X", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c%c\"",
                           chprint( i), chprint( and), chprint( shift));
               break;

            case 0x6 :
               dget_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X %02X", i,(word) and,(word) shift);
               fprintf( fq, "\t   %s $%04X,X", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c%c\"",
                           chprint( i), chprint( and), chprint( shift));
               break;

            case 0x7 :
               dget_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X %02X", i,(word) and,(word) shift);
               fprintf( fq, "\t   %s $%04X,Y", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c%c\"",
                           chprint( i), chprint( and), chprint( shift));
               break;

            case 0x8 :
               if( ! pcoff)
                  fprintf( fq, "%02X", i);
               fprintf( fq, "\t   %s", ops[i]);
               if( showascii)
                  fprintf( fq, "\t\t\t; \"%c\"", chprint( i));
               break;

            case 0x9 :
               {
                  register byte  j;
                  register word  k;

                  get_j();
                  k = j;
                  if( ! pcoff)
                     fprintf( fq, "%02X %02X", i, k);
                  fprintf( fq, "\t   %s $%04X", ops[ i], pc +
                                                         (signed char) j);
                  if( showascii)
                     fprintf( fq, "\t\t; \"%c%c\"",
                              chprint( i), chprint( j));
               }
               break;

            case 0xA :
               get_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X", i, j);
               fprintf( fq, "\t   %s ($%02X,X)", ops[i], j);
               if( showascii)
                     fprintf( fq, "\t\t; \"%c%c\"",
                              chprint( i), chprint( j));
               break;

            case 0xB :
               get_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X", i, j);
               fprintf( fq, "\t   %s ($%02X),Y", ops[i], j);
               if( showascii)
                     fprintf( fq, "\t\t; \"%c%c\"",
                              chprint( i), chprint( j));
               break;

            case 0xC :
               dget_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X %02X", i,(word) and,(word) shift);
               fprintf( fq, "\t   %s ($%04X)", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c%c%c\"",
                           chprint( i), chprint( and), chprint( shift));
               break;

            case 0xD :
               get_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X", i, j);
               fprintf( fq, "\t   %s ($%02X)", ops[i], j);
               if( showascii)
                     fprintf( fq, "\t\t; \"%c%c\"",
                              chprint( i), chprint( j));
               break;

            case 0xE :
               dget_j();
               if( ! pcoff)
                  fprintf( fq, "%02X %02X %02X", i,(word) and,(word) shift);
               fprintf( fq, "\t   %s ($%04X,X)", ops[i], j);
               if( showascii)
                  fprintf( fq, "\t; \"%c%c%c\"",
                           chprint( i), chprint( and), chprint( shift));
                break;

            case 0xF :
               if( ! pcoff)
                  fprintf( fq, "%02X", i);
               fprintf( fq, "\t   %s a", ops[i]);
               if( showascii)
                  fprintf( fq, "\t\t; \"%c\"", chprint( i));
               break;

         }
      putc( '\n', fq);
   }
   return( pc);

fini:
   if( ! pcoff)
      fprintf( fq, "%02X", i);
   fprintf( fq, "\t   .byte $%02X", i);
   if( showascii)
      fprintf( fq, "\t\t; \"%c\"", chprint( i));
   putc( '\n', fq);
   return( pc);

fini2:
   if( ! len)
      goto fini;
   j = *p;
   if( ! pcoff)
      fprintf( fq, "%02X %02X", i, j);
   fprintf( fq, "\t   .byte $%02X, $%02X", i, j);
   if( showascii)
         fprintf( fq, "\t; \"%c%c\"", chprint( i), chprint( j));
   putc( '\n', fq);
   return( pc);
}

keypress()
{
#if OS == TOS
   if( tossable)
   {
      while( Bconstat( 2))
         Bconin( 2);
      Bconin( 2);
   }
#endif
}

h_print()
{
   fputs( "disasm65: ", stderr);
}

finalshit()
{
}

