Advertisement
Redxone

(C) 6502 Assembler (WIP)

Nov 30th, 2018
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.00 KB | None | 0 0
  1. #pragma once
  2. #ifndef TERMINAL_H
  3. #define TERMINAL_H
  4.  
  5. typedef struct FilteredInput
  6. {
  7.     char* inp;
  8.     int nbytes;
  9. } FilteredInput;
  10.  
  11. typedef struct TerminalData
  12. {
  13.     FilteredInput finp;
  14.     char CMD[4];
  15.     const char* modestr;
  16.     int mode;
  17.     unsigned char bytecode;
  18.     int bytes;
  19.     long H,L;
  20. } TermData;
  21.  
  22. TermData* TerminalCMD( char* , long );
  23. unsigned char AssembleI( const char* , int );
  24. FilteredInput FilterInput( char* , long );
  25.  
  26. typedef enum
  27. {
  28.     md_IMP = 0,
  29.     md_IMM,
  30.     md_ZP,
  31.     md_ZPX,
  32.     md_ZPY,
  33.     md_ABS,
  34.     md_ABX,
  35.     md_ABY,
  36.     md_INX,
  37.     md_INY,
  38.     md_REL,
  39.     md_ACC,
  40.     md_IND,
  41.     ad_IMMH,
  42.     ad_IMMD
  43.  
  44. } TerminalEnums;
  45.  
  46. unsigned char AssembleI(const char* i, int m)
  47. {
  48.     #define DECODE(IMP,IMM,ZP,ZPX,ZPY,ABS,ABX,ABY,INX,INY,REL,ACC,IND) (m==md_IMP)?IMP:(m==md_IMM)?IMM:(m==md_ZP)?ZP:(m==md_ZPX)?ZPX:(m==md_ZPY)?ZPY:(m==md_ABS)?ABS:(m==md_ABX)?ABX:(m==md_ABY)?ABY:(m==md_INX)?INX:(m==md_INY)?INY:(m==md_REL)?REL:(m==md_ACC)?ACC:(m==md_IND)?IND:0xFF;
  49.  
  50.     if(!strncmp(i,"ADC",3)) return DECODE(0xFF,0x69,0x65,0x75,0xFF,0x6D,0x7D,0x79,0x61,0x71,0xFF,0xFF,0xFF);
  51.     if(!strncmp(i,"AND",3)) return DECODE(0xFF,0x29,0x25,0x35,0xFF,0x2D,0x3D,0x39,0x21,0x31,0xFF,0xFF,0xFF);
  52.     if(!strncmp(i,"ASL",3)) return DECODE(0xFF,0xFF,0x06,0x16,0xFF,0x0E,0x1E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  53.     if(!strncmp(i,"BCC",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x90,0xFF,0xFF);
  54.     if(!strncmp(i,"BEQ",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF);
  55.     if(!strncmp(i,"BIT",3)) return DECODE(0xFF,0x24,0xFF,0xFF,0xFF,0x2C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  56.     if(!strncmp(i,"BMI",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30,0xFF,0xFF);
  57.     if(!strncmp(i,"BNE",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0xFF,0xFF);
  58.     if(!strncmp(i,"BPL",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x10,0xFF,0xFF);
  59.     if(!strncmp(i,"BRK",3)) return DECODE(0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  60.     if(!strncmp(i,"BVC",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0,0xFF,0xFF);
  61.     if(!strncmp(i,"BVS",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF);
  62.     if(!strncmp(i,"CLC",3)) return DECODE(0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  63.     if(!strncmp(i,"CLD",3)) return DECODE(0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  64.     if(!strncmp(i,"CLI",3)) return DECODE(0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  65.     if(!strncmp(i,"CLV",3)) return DECODE(0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  66.     if(!strncmp(i,"CMP",3)) return DECODE(0xFF,0xC9,0xC5,0xD5,0xFF,0xCD,0xDD,0xD9,0xC1,0xD1,0xFF,0xFF,0xFF);
  67.     if(!strncmp(i,"CPX",3)) return DECODE(0xFF,0xE0,0xE4,0xFF,0xFF,0xEC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  68.     if(!strncmp(i,"CPY",3)) return DECODE(0xFF,0xC0,0xC4,0xFF,0xFF,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  69.     if(!strncmp(i,"DEC",3)) return DECODE(0xFF,0xFF,0xC6,0xD6,0xFF,0xCE,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  70.     if(!strncmp(i,"DEX",3)) return DECODE(0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  71.     if(!strncmp(i,"DEY",3)) return DECODE(0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  72.     if(!strncmp(i,"EOR",3)) return DECODE(0xFF,0x49,0x45,0x55,0xFF,0x4D,0x5D,0x59,0x41,0x51,0xFF,0xFF,0xFF);
  73.     if(!strncmp(i,"INC",3)) return DECODE(0xFF,0xFF,0xE6,0xF6,0xFF,0xEE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  74.     if(!strncmp(i,"INX",3)) return DECODE(0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  75.     if(!strncmp(i,"INY",3)) return DECODE(0xC8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  76.     if(!strncmp(i,"JMP",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x6C);
  77.     if(!strncmp(i,"JSR",3)) return DECODE(0xFF,0xFF,0xFF,0xFF,0xFF,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  78.     if(!strncmp(i,"LDA",3)) return DECODE(0xFF,0xA9,0xA5,0xB5,0xFF,0xAD,0xBD,0xB9,0xA1,0xB1,0xFF,0xFF,0xFF);
  79.     if(!strncmp(i,"LDX",3)) return DECODE(0xFF,0xA2,0xA6,0xFF,0xB6,0xAE,0xBE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  80.     if(!strncmp(i,"LDY",3)) return DECODE(0xFF,0xA0,0xA4,0xB4,0xFF,0xAC,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  81.     if(!strncmp(i,"LSR",3)) return DECODE(0xFF,0xFF,0x46,0x56,0xFF,0x4E,0x5E,0xFF,0xFF,0xFF,0xFF,0x4A,0xFF);
  82.     if(!strncmp(i,"NOP",3)) return DECODE(0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  83.     if(!strncmp(i,"ORA",3)) return DECODE(0xFF,0x09,0x05,0x15,0xFF,0x0D,0x1D,0x19,0x01,0x11,0xFF,0xFF,0xFF);
  84.     if(!strncmp(i,"PHA",3)) return DECODE(0x48,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  85.     if(!strncmp(i,"PHP",3)) return DECODE(0x08,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  86.     if(!strncmp(i,"PLA",3)) return DECODE(0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  87.     if(!strncmp(i,"PLP",3)) return DECODE(0x28,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  88.     if(!strncmp(i,"ROL",3)) return DECODE(0xFF,0xFF,0x26,0x36,0xFF,0x2E,0x3E,0xFF,0xFF,0xFF,0xFF,0x2A,0xFF);
  89.     if(!strncmp(i,"ROR",3)) return DECODE(0xFF,0xFF,0x66,0x76,0xFF,0x6E,0x7E,0xFF,0xFF,0xFF,0xFF,0x6A,0xFF);
  90.     if(!strncmp(i,"RTI",3)) return DECODE(0x40,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  91.     if(!strncmp(i,"RTS",3)) return DECODE(0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  92.     if(!strncmp(i,"SBC",3)) return DECODE(0xFF,0xE9,0xE5,0xF5,0xFF,0xED,0xFD,0xF9,0xE1,0xF1,0xFF,0xFF,0xFF);
  93.     if(!strncmp(i,"SEC",3)) return DECODE(0x38,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  94.     if(!strncmp(i,"SED",3)) return DECODE(0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  95.     if(!strncmp(i,"SEI",3)) return DECODE(0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  96.     if(!strncmp(i,"STA",3)) return DECODE(0xFF,0x85,0x95,0x8D,0xFF,0x8D,0x9D,0x99,0x81,0x91,0xFF,0xFF,0xFF);
  97.     if(!strncmp(i,"STX",3)) return DECODE(0xFF,0xFF,0x86,0xFF,0x96,0x8E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  98.     if(!strncmp(i,"STY",3)) return DECODE(0xFF,0xFF,0x84,0x94,0xFF,0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  99.     if(!strncmp(i,"TAX",3)) return DECODE(0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  100.     if(!strncmp(i,"TAY",3)) return DECODE(0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  101.     if(!strncmp(i,"TSX",3)) return DECODE(0xBA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  102.     if(!strncmp(i,"TXA",3)) return DECODE(0x8A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  103.     if(!strncmp(i,"TXS",3)) return DECODE(0x9A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  104.     if(!strncmp(i,"TYA",3)) return DECODE(0x98,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
  105.  
  106.  
  107.     return 0xFF; // Return invalid instruction
  108. }
  109.  
  110. FilteredInput FilterInput(char* CMD, long bytes)
  111. {
  112.     // Used for running terminal commands.
  113.     #define filter(C) C!='\t'&&C!=' '&&C!='\n'
  114.     register int i;
  115.     unsigned int nbytes=0;
  116.     for(i = 0; i < bytes; i++)
  117.     {
  118.         if(CMD[i]=='\0') break;
  119.         if(filter(CMD[i])) nbytes++;
  120.     }
  121.     char* buffer = malloc(nbytes+1);
  122.     buffer[nbytes] = '\0';
  123.     nbytes = 0;
  124.     for(i = 0; i < bytes; i++)
  125.     {
  126.         if(CMD[i]=='\0') break;
  127.         if(filter(CMD[i]))
  128.         {
  129.             buffer[nbytes] = CMD[i];
  130.             nbytes++;
  131.         }
  132.     }
  133.     FilteredInput finput = (FilteredInput){buffer,nbytes};
  134.     return finput;
  135. }
  136.  
  137. // Terminal
  138. TermData* AssembleCMD(char* CMD, long bytes, unsigned short PC)
  139. {
  140.     FilteredInput fCMD = FilterInput(CMD,bytes);
  141.     char* buffer = fCMD.inp;
  142.     int nbytes = fCMD.nbytes;
  143.     if(nbytes < 3)
  144.     {
  145.         TermData* data = malloc(sizeof(TermData));
  146.         data->bytecode = 0xFF;
  147.         data->finp = fCMD;
  148.         return data;
  149.     }
  150.     long opH=0;
  151.     long opL=0;
  152.     int modeactual;
  153.     char instruction[4];
  154.     instruction[3]='\0';
  155.     char modechk[6];
  156.     modechk[5]='\0';
  157.     strncpy(instruction,buffer,3);
  158.     strncpy(modechk,buffer+3,2);
  159.     strncpy(modechk+2,buffer+(nbytes-3),3);
  160.     int isize=1;
  161.     // Check next set to determine mode
  162.     // #Special Branch mode#
  163.     if(!strncmp(instruction,"B",1) && strncmp(instruction,"BIT",3) && !strncmp(modechk,"$",1))
  164.        modeactual = md_REL;
  165.     // #IMM modes#
  166.     else if(!strncmp(modechk,"#$",2))
  167.         modeactual = ad_IMMH;
  168.     else if(!strncmp(modechk,"#",1))
  169.         modeactual = ad_IMMD;
  170.     // #IND modes#
  171.     else if(!strncmp(modechk,"($",2) && !strncmp(modechk+2,",X)",3))
  172.         modeactual = md_INX;
  173.     else if(!strncmp(modechk,"($",2) && !strncmp(modechk+2,"),Y",3))
  174.         modeactual = md_INY;
  175.     // #ZP modes#
  176.     else if(!strncmp(modechk,"$",1) && !strncmp(modechk+3,",X",2) && nbytes<9)
  177.         modeactual = md_ZPX;
  178.     else if(!strncmp(modechk,"$",1) && !strncmp(modechk+3,",Y",2) && nbytes<9)
  179.         modeactual = md_ZPY;
  180.     else if(!strncmp(modechk,"$",1) && nbytes<7)
  181.         modeactual = md_ZP;
  182.     // #ABS modes#
  183.     else if(!strncmp(modechk,"$",1) && !strncmp(modechk+3,",X",2))
  184.         modeactual = md_ABX;
  185.     else if(!strncmp(modechk,"$",1) && !strncmp(modechk+3,",Y",2))
  186.         modeactual = md_ABY;
  187.     else if(!strncmp(modechk,"$",1))
  188.         modeactual = md_ABS;
  189.     else if(nbytes==3)
  190.         modeactual = md_IMP;
  191.     else // Oof, you done messed up, kid.
  192.     {
  193.         TermData* data = malloc(sizeof(TermData));
  194.         data->bytecode = 0xFF;
  195.         data->finp = fCMD;
  196.         return data;
  197.     }
  198.  
  199.     // Operand loading.
  200.     char op[2];
  201.     switch(modeactual)
  202.     {
  203.         case md_IMP: break;
  204.         case ad_IMMH:
  205.             strncpy(op,buffer+5,2);
  206.             opH = strtol(op,NULL,16);
  207.             isize++;
  208.             modeactual = md_IMM;
  209.         break;
  210.         case ad_IMMD:
  211.             strncpy(op,buffer+4,2);
  212.             opH = strtol(op,NULL,10);
  213.             isize++;
  214.             modeactual = md_IMM;
  215.         break;
  216.         case md_ZPY:
  217.         case md_ZPX:
  218.         case md_ZP :
  219.             strncpy(op,buffer+4,2);
  220.             opH = strtol(op,NULL,16);
  221.             isize++;
  222.         break;
  223.         case md_ABY:
  224.         case md_ABX:
  225.         case md_ABS:
  226.             strncpy(op,buffer+4,2);
  227.             opL = strtol(op,NULL,16);
  228.             strncpy(op,buffer+6,2);
  229.             opH = strtol(op,NULL,16);
  230.             isize+=2;
  231.         break;
  232.         case md_INY:
  233.         case md_INX:
  234.             strncpy(op,buffer+5,2);
  235.             opH = strtol(op,NULL,16);
  236.             isize++;
  237.         break;
  238.         case md_REL:
  239.             if(nbytes>6)
  240.             {
  241.                 // Convert from ABS to REL
  242.                 char op[2];
  243.                 strncpy(op,buffer+4,2);
  244.                 opH = strtol(op,NULL,16);
  245.                 strncpy(op,buffer+6,2);
  246.                 opL = strtol(op,NULL,16);
  247.                 unsigned short abs  = (unsigned short)(opH*256)+opL;
  248.                 signed char rel = (signed char)(abs-PC)-2; // -2 for BNE bytes.
  249.                 opH = (unsigned char)rel;
  250.                 printf("$%04X -> %02X\n",abs,(unsigned char)rel);
  251.             }
  252.             else
  253.             {
  254.                 strncpy(op,buffer+4,2);
  255.                 opH = strtol(op,NULL,16);
  256.             }
  257.             isize++;
  258.         break;
  259.     }
  260.     const char* strmodes[12] =
  261.     {
  262.         "IMP",
  263.         "IMM",
  264.         "ZP",
  265.         "ZPX",
  266.         "ZPY",
  267.         "ABS",
  268.         "ABX",
  269.         "ABY",
  270.         "INX",
  271.         "INY",
  272.         "REL",
  273.         "ACC"
  274.     };
  275.     //free(buffer);
  276.     TermData* data = malloc(sizeof(TermData));
  277.     strncpy(data->CMD,instruction,4);
  278.     data->finp = fCMD;
  279.     data->bytes = isize;
  280.     data->mode = modeactual;
  281.     data->modestr = strmodes[modeactual];
  282.     data->H = opH;
  283.     data->L = opL;
  284.     data->bytecode = AssembleI(instruction,modeactual);
  285.     return data;
  286. }
  287.  
  288. #endif // TERMINAL_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement