/****************************************************************************
 *        6502tbl.c    *    6502 Family Opcodes Table  version 0.04         *
 *       Copyright (c) 2000 Arnaud VERHILLE    all rights reserved.         *
 *                                                                          *
 * This source code is released as freeware for non-commercial purposes.    *
 *  - You are free to use and redistribute this code in modified or         *
 *    unmodified form, provided you list me in the credits.                 *
 *  - If you wish to use this for commercial purposes, please contact me    *
 *    at gist@wanadoo.fr                                                    *
 *  - The author of this copywritten work reserves the right to change the  *
 *    terms of its usage and license at any time, including retroactively   *
 *  - This entire notice must remain in the source code.                    *
 *                                                                          *
 ****************************************************************************/

 #include <stdio.h>
 #include <stdlib.h>
 #define VERSION 0.04


 /* W65C02 Opcode Mnemonic Table  */

 char mnemonic[256][5] = {
 "BRK","ORA","---","---","TSB","ORA","ASL","RMB0",
 "PHP","ORA","ASL","---","TSB","ORA","ASL","BBR0",
 "BPL","ORA","ORA","---","TRB","ORA","ASL","RMB1",
 "CLC","ORA","INC","---","TRB","ORA","ASL","BBR1",
 "JSR","AND","---","---","BIT","AND","ROL","RMB2",
 "PLP","AND","ROL","---","BIT","AND","ROL","BBR2",
 "BMI","AND","AND","---","BIT","AND","ROL","RMB3",
 "SEC","AND","DEC","---","BIT","AND","ROL","BBR3",
 "RTI","EOR","---","---","---","EOR","LSR","RMB4",
 "PHA","EOR","LSR","---","JMP","EOR","LSR","BBR4",
 "BVC","EOR","EOR","---","---","EOR","LSR","RMB5",
 "CLI","EOR","PHY","---","---","EOR","LSR","BBR5",
 "RTS","ADC","---","---","STZ","ADC","ROR","RMB6",
 "PLA","ADC","ROR","---","JMP","ADC","ROR","BBR6",
 "BVS","ADC","ADC","---","STZ","ADC","ROR","RMB7",
 "SEI","ADC","PLY","---","JMP","ADC","ROR","BBR7",
 "BRA","STA","---","---","STY","STA","STX","SMB0",
 "DEY","BIT","TXA","---","STY","STA","STX","BBS0",
 "BCC","STA","STA","---","STY","STA","STX","SMB1",
 "TYA","STA","TXS","---","STZ","STA","STZ","BBS1",
 "LDY","LDA","LDX","---","LDY","LDA","LDX","SMB2",
 "TAY","LDA","TAX","---","LDY","LDA","LDX","BBS2",
 "BCS","LDA","LDA","---","LDY","LDA","LDX","SMB3",
 "CLV","LDA","TSX","---","LDY","LDA","LDX","BBS3",
 "CPY","CMP","---","---","CPY","CMP","DEC","SMB4",
 "INY","CMP","DEX","WAI","CPY","CMP","DEC","BBS4",
 "BNE","CMP","CMP","---","---","CMP","DEC","SMB5",
 "CLD","CMP","PHX","STP","---","CMP","DEC","BBS5",
 "CPX","SBC","---","---","CPX","SBC","INC","SMB6",
 "INX","SBC","NOP","---","CPX","SBC","INC","BBS6",
 "BEQ","SBC","SBC","---","---","SBC","INC","SMB7",
 "SED","SBC","PLX","---","---","SBC","INC","BBS7"};

 /* W65C02S Adressing modes
  00             Undefined Opcode
  01  #          Immediate
  02  a          Absolute
  03  zp         Zero Page
  04  A          Accumulator
  05  i          Implied
  06  (zp),Y     (Zero Page Indirect),Y
  07  (zp,X)     (Zero Page Indirect,X)
  08  zp,X       Zero Page,X
  09  zp,Y       Zero Page,Y
  10  a,X        Absolute,X
  11  a,Y        Absolute,Y
  12  r          Program Counter Relative
  13  (a)        Absolute Indirect
  14  s          Stack
  15  (a,X)      Absolute Indexed Indirect
  16  (zp)       Zero Page Indirect   */

 char adrname[17][7] = {
 "", "#", "a", "zp", "A", "i", "(zp),Y", "(zp,X)", "zp,X",
 "zp,Y", "a,X", "a,Y", "r", "(a)", "s", "(a,X)", "(zp)" };

 int adrmode[256] = {
 14,  7,  0,  0,  3,  3,  3,  3, 14,  1,  4,  0,  2,  2,  2, 12,
 12,  6, 16,  0,  3,  8,  8,  3,  5, 11,  4,  0,  2, 10, 10, 12,
  2,  7,  0,  0,  3,  3,  3,  3, 14,  1,  4,  0,  2,  2,  2, 12,
 12,  6, 16,  0,  8,  8,  8,  3,  5, 11,  4,  0, 10, 10, 10, 12,
 14,  7,  0,  0,  0,  3,  3,  3, 14,  1,  4,  0,  2,  2,  2, 12,
 12,  6, 16,  0,  0,  8,  8,  3,  5, 11, 14,  0,  0, 10, 10, 12,
 14,  7,  0,  0,  3,  3,  3,  3, 14,  1,  4,  0, 13,  2,  2, 12,
 12,  6, 16,  0,  8,  8,  8,  3,  5, 11, 14,  0, 15, 10, 10, 12,
 12,  7,  0,  0,  3,  3,  3,  3,  5,  1,  5,  0,  2,  2,  2, 12,
 12,  6, 16,  0,  8,  8,  9,  3,  5, 11,  5,  0,  2, 10, 10, 12,
  1,  7,  1,  0,  3,  3,  3,  3,  5,  1,  5,  0,  2,  2,  2, 12,
 12,  6, 16,  0,  8,  8,  9,  3,  5, 11,  5,  0, 10, 10, 11, 12,
  1,  7,  0,  0,  3,  3,  3,  3,  5,  1,  5,  5,  2,  2,  2, 12,
 12,  6, 16,  0,  0,  8,  8,  3,  5, 11, 14,  5,  0, 10, 10, 12,
  1,  7,  0,  0,  3,  3,  3,  3,  5,  1,  5,  0,  2,  2,  2, 12,
 12,  6, 16,  0,  0,  8,  8,  3,  5, 11, 14,  0,  0, 10, 10, 12};

 /* 6502 microprocessor version Table
    0     = Undefined Opcode
    1     = 6502
    1 & 2 = W65C02S   */

int micro[256] = {
1,1,0,0,2,1,1,2,1,1,1,0,2,1,1,2,
1,1,2,0,2,1,1,2,1,1,2,0,2,1,1,2,
1,1,0,0,1,1,1,2,1,1,1,0,1,1,1,2,
1,1,2,0,2,1,1,2,1,1,2,0,2,1,1,2,
1,1,0,0,0,1,1,2,1,1,1,0,1,1,1,2,
1,1,2,0,0,1,1,2,1,1,2,0,0,1,1,2,
1,1,0,0,2,1,1,2,1,1,1,0,1,1,1,2,
1,1,2,0,2,1,1,2,1,1,2,0,2,1,1,2,
2,1,0,0,1,1,1,2,1,2,1,0,1,1,1,2,
1,1,2,0,1,1,1,2,1,1,1,0,2,1,2,2,
1,1,1,0,1,1,1,2,1,1,1,0,1,1,1,2,
1,1,2,0,1,1,1,2,1,1,1,0,1,1,1,2,
1,1,0,0,1,1,1,2,1,1,1,2,1,1,1,2,
1,1,2,0,0,1,1,2,1,1,2,2,0,1,1,2,
1,1,0,0,1,1,1,2,1,1,1,0,1,1,1,2,
1,1,2,0,0,1,1,2,1,1,2,0,0,1,1,2};





 /* Function Prototypes */

 void dumpopcodetable (void);
 void desas2file (char *filename,int long start );
 int main ();




 void dumpopcodetable (void)
 {
  FILE *fptr;            // Dump the Opcodes Array to Table.txt
  if ((fptr = fopen("Table.txt", "w")) == NULL )
     { printf ("Table.txt Write Error !!"); }
  else
     {
      int i,j;
      fprintf (fptr,"         W65C02S Opcodes List \n\n");
      for ( i = 0x00, j = 0x7F ; i <= 0x7F ; i++ )
          {
                 j++;
                 fprintf (fptr,"%02X  %-4s  %-7s        %02X  %-4s  %-7s\n",i,mnemonic[i],adrname[adrmode[i]],j,mnemonic[j],adrname[adrmode[j]]);
          }
      fprintf (fptr,"\n\nCreated by 6502tbl.exe v%3g (c) A.Verhille\n",VERSION);
      fprintf (fptr,"Contact : gist@wanadoo.fr");
      fclose(fptr);
     }
 }





 void desas2file (char *filename, int long start )
 {
  FILE *fptr1;
  FILE *fptr2;
  int buf, buf2, buf3, c=0;

  if ((fptr1 = fopen(filename,"r")) == NULL )     // Files flux init
    { printf ("%s read error\n",filename); }
  else
    {
     if ((fptr2 = fopen ("Desas.txt", "w")) == NULL )
       { printf ("Desas.txt write error\n"); }
     else
       {
        fprintf (fptr2,"%s 65C02 Desas List\n\n",filename);

        while ( c != start )      // init to start hex value
          {
           if (( buf = fgetc (fptr1)) == EOF )
             {
              printf ("Invalid origin hex value");
              exit (1);
             }
           c++;
          }

        printf ("Desassemble %s to Desas.txt\n",filename);
        printf ("Start adresse : 0x%06X\n\n",c);
        while (( buf = fgetc (fptr1)) != EOF)   // Desassemble
        {
         switch (adrmode[buf])
           {
           case 0 :
                fprintf (fptr2,"%06X: %02X \t\t\t\t;Undefined Opcode\n",c,buf);
                break;
           case 1 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X \t\t%-7s #$%02X\n",c,buf,buf2,mnemonic[buf],buf2);
                c++;
                break;
           case 2 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                if (( buf3 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X %02X\t%-7s $%02X%02X\n",c,buf,buf2,buf3,mnemonic[buf],buf3,buf2);
                c = c+2;
                break;
           case 3 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X\t\t%-7s $%02X\n",c,buf,buf2,mnemonic[buf],buf2);
                c ++;
                break;
           case 4 :
                fprintf (fptr2,"%06X: %02X \t\t%-7s A\n",c,buf,mnemonic[buf]);
                break;
           case 5 :
                fprintf (fptr2,"%06X: %02X \t\t%-7s\n",c,buf,mnemonic[buf]);
                break;
           case 6 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X\t\t%-7s ($%02X),Y\n",c,buf,buf2,mnemonic[buf],buf2);
                c ++;
                break;
           case 7 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X\t\t%-7s ($%02X,X)\n",c,buf,buf2,mnemonic[buf],buf2);
                c ++;
                break;
           case 8 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X\t\t%-7s $%02X,X\n",c,buf,buf2,mnemonic[buf],buf2);
                c ++;
                break;
           case 9 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X\t\t%-7s $%02X,Y\n",c,buf,buf2,mnemonic[buf],buf2);
                c ++;
                break;
           case 10 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                if (( buf3 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X %02X\t%-7s $%02X%02X,X\n",c,buf,buf2,buf3,mnemonic[buf],buf3,buf2);
                c = c+2;
                break;
           case 11 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                if (( buf3 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X %02X\t%-7s $%02X%02X,Y\n",c,buf,buf2,buf3,mnemonic[buf],buf3,buf2);
                c = c+2;
                break;
           case 12 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X\t\t%-7s ",c,buf,buf2,mnemonic[buf]);
                if ( buf2 >= 0x80 )              // 2's compilment
                  { buf2 = -(256 - buf2); }
                fprintf (fptr2,"%06X\t\n",c+2+buf2);
                c ++;
                break;
           case 13 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                if (( buf3 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X %02X\t%-7s ($%02X%02X)\n",c,buf,buf2,buf3,mnemonic[buf],buf3,buf2);
                c = c+2;
                break;
           case 14 :
                fprintf (fptr2,"%06X: %02X \t\t%-7s\n",c,buf,mnemonic[buf]);
                break;
           case 15 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                if (( buf3 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X %02X\t%-7s ($%02X%02X,X)\n",c,buf,buf2,buf3,mnemonic[buf],buf3,buf2);
                c = c+2;
                break;
           case 16 :
                if (( buf2 = fgetc (fptr1)) == EOF ) continue;
                fprintf (fptr2,"%06X: %02X %02X\t\t%-7s ($%02X)\n",c,buf,buf2,mnemonic[buf],buf2);
                c ++;
                break;
           }
         c++;
        }
       fprintf (fptr2,"\n\nCreated by 6502tbl.exe v%3g (c) A.Verhille\n",VERSION);
       fprintf (fptr2,"  gist@wanadoo.fr\t File size : 0x%lX",c-start-1);
       }
     }
   fclose (fptr1);
   fclose (fptr2);
 }





int main(int argc,char *argv[])
 {
  int i;
  int long start = 0;
  printf ("6502tbl.exe v%3g (c) A.Verhille\n",VERSION);
  printf ("Usage : 6502tbl [-o] [-s] -d file\n  -o\tDump 65C02 Opcode Table");
  printf ("\n  -s\tCount addresses from a given origin (hex)");
  printf ("\n  -d\tDesassemble 65C02 bin file\n\n");


  for ( i=1 ; ( i < argc ) && (*argv[i] == '-') ; i++ )
     switch ( argv [i][1] )
       {
        case 'o' :
             printf ("Opcode Table dumped to Table.txt\n");
             dumpopcodetable();
             break;
        case 's' :
             sscanf(argv[i],"-s%lx",&start);
             break;
        case 'd' :
             desas2file ( argv[i+1], start );
             break;
        default :
             printf ("Unknown parameter : -%c", argv[i][1]);
             break;
       }
  return 0;
 }







