Advertisement
Redxone

(C) 6502 Emulator [Assembler WIP] [Not Cycle Accurate]

Nov 29th, 2018
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 22.90 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <time.h>
  6. #include "terminal.h"
  7. #define ProgramStart 0x0600
  8. #define RAMSize      64;
  9. #define Stackpos     0x0100
  10. #define Stacksize    0xFF
  11. #define IPS          0xD59F8
  12. #define CPU_Pause() (flagset(fBreak, 1));
  13. #define CPU_Resume() (flagset(fBreak, 0));
  14. #define mWORD(M,L) (mem_t)(M*256)+L
  15. #define wMSB(W) (byte_t)((mem_t)W>>8)
  16. #define wLSB(W) (byte_t)((mem_t)W&0xFF)
  17.  
  18. typedef enum {false, true} bool;
  19. typedef unsigned char  byte_t;
  20. typedef signed char sbyte_t;
  21. typedef unsigned short mem_t;
  22. typedef signed short smem_t;
  23. typedef enum
  24. {
  25.     fCarry    =  1,   // Result is less than 0x00 or greater than 0xFF
  26.     fZero     =  2,   // Result is 0
  27.     fInterupt =  4,   // IO interrupt
  28.     fDecimal  =  8,   // Count in base 10
  29.     fBreak    = 16,   // Interrupt in-process
  30.     fUnknown  = 32,   // ???
  31.     fOverflow = 64,   // Result is invalid 2s complement 8bit arithmetic. ( + add + equals - )
  32.     fNegative = 128,  // Result is a negative number.
  33.     bSign     = 0x80, // Value is a negative number.
  34.     rA = 0,
  35.     rX,
  36.     rY,
  37.     mINX = 0,
  38.     mINY,
  39.  
  40. } CPUEnums;
  41.  
  42. struct CPU
  43. {
  44.     byte_t A, X, Y, Flags, SP;
  45.     mem_t PC;
  46.     bool STEP;
  47. };
  48.  
  49. // Globals
  50.  
  51. static byte_t* pRAM;
  52. static struct CPU* pCPU;
  53.  
  54. // Routine prototypes
  55. static double uTimer;
  56. static bool inTerminal;
  57.  
  58. inline bool check_reserved(mem_t);
  59. inline void wait_timer();
  60. inline void SetPC(mem_t);
  61. inline void SetReg(byte_t, byte_t);
  62. inline byte_t GetReg(byte_t);
  63.  
  64. byte_t peek(mem_t);
  65. byte_t stack_pop();
  66. byte_t getflags();
  67. mem_t RelAdd(smem_t, sbyte_t);
  68.  
  69. void poke(mem_t, byte_t);
  70. void stack_push(byte_t);
  71. void flagset(byte_t, bool);
  72. void setflags(byte_t);
  73. void update_flag(bool, byte_t, byte_t, byte_t, byte_t);
  74. void load_program(const char* , long);
  75. int run_instr(byte_t,bool);
  76.  
  77. typedef struct AssemblerLabel
  78. {
  79.     const char* name;
  80.     sbyte_t relative;
  81.     mem_t absolute;
  82. } ALabel;
  83.  
  84. void RunTerminal();
  85. bool initalize();
  86.  
  87. // Main
  88.  
  89. int main()
  90. {
  91.     uTimer = clock();
  92.     if(initalize())
  93.     {
  94.         wait_timer();
  95.         //char program[] = {0x20,0x06,0x09,0x20,0x06,0x0C,0x20,0x06,0x12,0xA2,0x00,0x60,0xE8,0xE0,0x05,0xD0,0xFB,0x60,0x00};//{0xa2,0x00,0xe8,0xe0,0x50,0xd0,0xfb,0xea}; //{0xA2,0x00,0xE8,0x20,0x06,0x02}; //{0x08,0xA9,0x60,0x48,0x69,0x45,0x68,0x28,0x00};
  96.         //load_program(program, 19);
  97.         //pCPU->STEP = true;
  98.         //CPU_Start();
  99.         RunTerminal();
  100.     }
  101.     else
  102.     {
  103.         printf("Failed to initialize.");
  104.     }
  105.     free(pRAM);
  106.     free(pCPU);
  107.     return 0;
  108. }
  109.  
  110. // Timing
  111. void wait_timer()
  112. {
  113.     while( (clock()-uTimer) < 1000./IPS ) { };
  114.     uTimer = clock();
  115. }
  116.  
  117. // Debug
  118. void printf_cpuinfo()
  119. {
  120.     printf("\nA=$%x, X=$%x, Y=$%x\nSP=$%x, PC=$%x\n\nNV-BDIZC\n", pCPU->A, pCPU->X, pCPU->Y, pCPU->SP, pCPU->PC);
  121.     char flags[9] = "00000000\0";
  122.     register int i;
  123.     for(i = 0; i <= 7; i++)
  124.     {
  125.         int bit = pow(2,i);
  126.         flags[7-i] = (pCPU->Flags & bit) ? '1' : '0';
  127.     }
  128.     printf("%s\n",flags);
  129. }
  130.  
  131. // Memory
  132. bool check_reserved(mem_t location)
  133. {
  134.     return (location >= Stackpos && location <= Stackpos+Stacksize);
  135. }
  136. byte_t peek(mem_t location)
  137. {
  138.     if( location > 0xFFFF ) return '\0';
  139.     return (byte_t) *(pRAM + location);
  140. }
  141. void poke(mem_t location, byte_t data)
  142. {
  143.     if( location > 0xFFFF ) return;
  144.     *(pRAM + location) = data;
  145. }
  146. byte_t stack_pop()
  147. {
  148.     byte_t data = peek(Stackpos + pCPU->SP +1);
  149.     pCPU->SP++;
  150.     return data;
  151. }
  152. void stack_push(byte_t data)
  153. {
  154.     poke(Stackpos + pCPU->SP, data);
  155.     pCPU->SP--;
  156. }
  157. void load_program(const char* program, long bytes)
  158. {
  159.     printf("\nLoading %i bytes...\n", bytes);
  160.     for (int i = 0; i < bytes; i++)
  161.     {
  162.         poke(ProgramStart+i,program[i]);
  163.         printf("$%X: %X\n",(byte_t)ProgramStart+i, (byte_t)program[i]);
  164.     }
  165.     pCPU->PC = ProgramStart;
  166.     printf(" Loaded.\n");
  167. }
  168.  
  169. // CPU routines
  170. void SetPC(mem_t addr){ pCPU->PC = addr; }
  171. void SetReg(byte_t r, byte_t data)
  172. {
  173.     byte_t* robj = (!r) ? &pCPU->A : ( (r&1) ? &pCPU->X  : &pCPU->Y );
  174.     *robj = data;
  175.     flagset(fZero, data==0);
  176.     flagset(fNegative, (data&bSign)!=0);
  177. }
  178. byte_t GetReg(byte_t r)
  179. {
  180.     return (!r) ? pCPU->A : ( (r&1) ? pCPU->X  : pCPU->Y );
  181. }
  182.  
  183. // Flags
  184. void flagset(byte_t flag, bool val)
  185. {
  186.     if(!val) pCPU->Flags &= ~flag;
  187.     if( val) pCPU->Flags |=  flag;
  188. }
  189. void setflags(byte_t flags) { pCPU->Flags = flags; };
  190. byte_t getflags() { return pCPU->Flags; }
  191.  
  192. int run_instr(byte_t c, bool demo)
  193. {
  194.     smem_t pc = pCPU->PC;
  195.     byte_t flags = pCPU->Flags;
  196.     bool switchf = false; // Flag load switch.
  197.     bool C = flags&fCarry;
  198.     bool Z = flags&fZero;
  199.     bool I = flags&fInterupt;
  200.     bool D = flags&fDecimal;
  201.     bool B = flags&fBreak;
  202.     bool V = flags&fOverflow;
  203.     bool N = flags&fNegative;
  204.     byte_t H = peek(pCPU->PC+1);
  205.     byte_t L = peek(pCPU->PC+2);
  206.     mem_t HL = (mem_t)(L*0x100)+H; // Reverse endian.
  207.     byte_t A = pCPU->A;
  208.     byte_t X = pCPU->X;
  209.     byte_t Y = pCPU->Y;
  210.     byte_t ticks = 1;
  211.  
  212.     switch(c)
  213.     {
  214.         // Indirect helpers
  215.         #define dINX(M) peek((mem_t)(peek(M+X+1)*256)+peek(M+X))
  216.         #define dINY(M) peek((mem_t)((peek(M+1)*256)+peek(M+Y))+Y)
  217.         #define dIND(M) peek((mem_t)(peek(M+1)*256)+peek(M))
  218.         // Flag helpers
  219.         #define CMP(R,M) C=(R>=M);Z=(R==M);N=(R-M)&bSign
  220.         // If H has the same sign as L and the result has a different sign, overflow.
  221.         #define OVR(Q,W,E) !((Q&bSign)-(W&bSign))&&((Q&bSign)-(E&bSign))
  222.         #define ADC(M) C=(A+M<A);V=OVR(A,M,A+M)
  223.         #define SBC(M) C=(A-M>A);V=OVR(A,M,A-M)
  224.         // Math helpers
  225.         #define ROL(M) (M << 1) | (M >> 7)
  226.         #define ROR(M) (M >> 1) | (M << 7)
  227.  
  228.         // -- 00
  229.         /* BRK IMP */ case 0x00: B=1; break;
  230.         /* BPL REL */ case 0x10: N?0:(pc+=(sbyte_t)H); ticks++; break;
  231.         /* JSR ABS */ case 0x20: stack_push(wLSB(pc)+1);stack_push(wMSB(pc));pc=HL; ticks=0; break;
  232.         /* BMI REL */ case 0x30: N?(pc+=(sbyte_t)H):0; ticks++; break;
  233.         /* RTI IMP */ case 0x40: switchf=1;flags=stack_pop();pc=stack_pop(); ticks++; break;
  234.         /* BVC REL */ case 0x50: V?0:(pc+=(sbyte_t)H); ticks++; break;
  235.         /* RTS IMP */ case 0x60: pc=mWORD(stack_pop(),stack_pop()+1); break;
  236.         /* BVS REL */ case 0x70: V?(pc+=(sbyte_t)H):0; ticks++; break;
  237.         /* BCC REL */ case 0x90: C?0:(pc+=(sbyte_t)H); ticks++; break;
  238.         /* LDY IMM */ case 0xA0: Y=H; ticks++; break;
  239.         /* BCS REL */ case 0xB0: C?(pc+=(sbyte_t)H):0; ticks++; break;
  240.         /* CPY IMM */ case 0xC0: CMP(Y,H); ticks++; break;
  241.         /* BNE REL */ case 0xD0: C?0:(pc+=(sbyte_t)H); ticks++; break;
  242.         /* CPX IMM */ case 0xE0: CMP(X,H); ticks++; break;
  243.         /* BEQ REL */ case 0xF0: C?(pc+=(sbyte_t)H):0; ticks++; break;
  244.         // -- 01
  245.         /* ORA INX */ case 0x01: A|=dINX(H); ticks++; break;
  246.         /* ORA INY */ case 0x11: A|=dINY(H); ticks++; break;
  247.         /* AND INX */ case 0x21: A&=dINX(H); ticks++; break;
  248.         /* AND INY */ case 0x31: A&=dINY(H); ticks++; break;
  249.         /* EOR INX */ case 0x41: A^=dINX(H); ticks++; break;
  250.         /* EOR INY */ case 0x51: A^=dINY(H); ticks++; break;
  251.         /* ADC INX */ case 0x61: H=dINX(H)+C;ADC(H);A+=H; ticks++; break;
  252.         /* ADC INY */ case 0x71: H=dINY(H)+C;ADC(H);A+=H; ticks++; break;
  253.         /* STA INX */ case 0x81: poke(dINX(H),A); ticks++; break;
  254.         /* STA INY */ case 0x91: poke(dINY(H),A); ticks++; break;
  255.         /* LDA INX */ case 0xA1: A=dINX(H); ticks++; break;
  256.         /* LDA INY */ case 0xB1: A=dINY(H); ticks++; break;
  257.         /* CMP INX */ case 0xC1: H=dINX(H);CMP(A,H); ticks++; break;
  258.         /* CMP INY */ case 0xD1: H=dINY(H);CMP(A,H); ticks++; break;
  259.         /* SBC INX */ case 0xE1: H=dINX(H)-~C;SBC(H);A-=H; ticks++; break;
  260.         /* SBC INY */ case 0xF1: H=dINY(H)-~C;SBC(H);A-=H; ticks++; break;
  261.         // -- 02
  262.         /* LDX IMM */ case 0xA2: X=H; ticks++; break;
  263.         // -- 04
  264.         /* BIT ZP  */ case 0x24: H=peek(H);Z=!(A&H);V=(H&0x20);N=(H&0x40); ticks++; break;
  265.         /* STY ZP  */ case 0x84: poke(H,Y); ticks++; break;
  266.         /* STY ZPX */ case 0x94: poke(H+X,Y); ticks++; break;
  267.         /* LDY ZP  */ case 0xA4: Y=peek(H); ticks++; break;
  268.         /* LDY ZPX */ case 0xB4: Y=peek(H+X); ticks++; break;
  269.         /* CPY ZP  */ case 0xC4: H=peek(H); CMP(Y,H); ticks++; break;
  270.         /* CPX ZP  */ case 0xE4: H=peek(H); CMP(X,H); ticks++; break;
  271.         // -- 05
  272.         /* ORA ZP  */ case 0x05: A|=peek(H); ticks++; break;
  273.         /* ORA ZPX */ case 0x15: A|=peek(H+X); ticks++; break;
  274.         /* AND ZP  */ case 0x25: A&=peek(H); ticks++; break;
  275.         /* AND ZPX */ case 0x35: A&=peek(H+X); ticks++; break;
  276.         /* EOR ZP  */ case 0x45: A^=peek(H); ticks++; break;
  277.         /* EOR ZPX */ case 0x55: A^=peek(H+X); ticks++; break;
  278.         /* ADC ZP  */ case 0x65: H=peek(H);ADC(H);A+=H+C; ticks++; break;
  279.         /* ADC ZPX */ case 0x75: H=peek(H+X);ADC(H);A+=H+C; ticks++; break;
  280.         /* STA ZP  */ case 0x85: poke(H,A); ticks++; break;
  281.         /* STA ZPX */ case 0x95: poke(H+X,A); ticks++; break;
  282.         /* LDA ZP  */ case 0xA5: A=peek(H); ticks++; break;
  283.         /* LDA ZPX */ case 0xB5: A=peek(H+X); ticks++; break;
  284.         /* CMP ZP  */ case 0xC5: H=peek(H);CMP(A,H); ticks++; break;
  285.         /* CMP ZPX */ case 0xD5: H=peek(H+X);CMP(A,H); ticks++; break;
  286.         /* SBC ZP  */ case 0xE5: H=peek(H);SBC(H);A-=H-~C; ticks++; break;
  287.         /* SBC ZPX */ case 0xF5: H=peek(H+X);SBC(H);A-=H-~C; ticks++; break;
  288.         // -- 06
  289.         /* ASL ZP  */ case 0x06: L=peek(H);poke(H,L<<1);H=L<<1;C=(L&bSign);N=(H&bSign); ticks++; break;
  290.         /* ASL ZPX */ case 0x16: L=peek(H+X);poke(H+X,L<<1);H=L<<1;C=(L&bSign);N=(H&bSign); ticks++; break;
  291.         /* ROL ZP  */ case 0x26: L=peek(H);poke(H,ROL(L));H=ROL(L);C=(L&bSign);N=(H&bSign); ticks++; break;
  292.         /* ROL ZPX */ case 0x36: L=peek(H+X);poke(H+X,ROL(L));H=ROL(L);C=(L&bSign);N=(H&bSign); ticks++; break;
  293.         /* LSR ZP  */ case 0x46: L=peek(H);poke(H,(sbyte_t)L>>1);H=(sbyte_t)L>>1;C=(L&1);N=(H&bSign);Z=!H; ticks++; break;
  294.         /* LSR ZPX */ case 0x56: L=peek(H+X);poke(H+X,(sbyte_t)L>>1);H=(sbyte_t)L>>1;C=(L&1);N=(H&bSign);Z=!H; ticks++; break;
  295.         /* ROR ZP  */ case 0x66: L=peek(H);poke(H,ROR(L));H=ROR(L);C=(L&1);N=(H&bSign); ticks++; break;
  296.         /* ROR ZPX */ case 0x76: L=peek(H+X);poke(H+X,ROR(L));H=ROR(L);C=(L&1);N=(H&bSign); ticks++; break;
  297.         /* STX ZP  */ case 0x86: poke(H,X); ticks++; break;
  298.         /* STX ZPY */ case 0x96: poke(H+Y,X); ticks++; break;
  299.         /* LDX ZP  */ case 0xA6: X=peek(H); ticks++; break;
  300.         /* LDX ZPY */ case 0xB6: X=peek(H+Y); ticks++; break;
  301.         /* DEC ZP  */ case 0xC6: L=peek(H)-1;poke(H,L);Z=!L;N=L&bSign; ticks++; break;
  302.         /* DEC ZPX */ case 0xD6: L=peek(H+X)-1;poke(H,L);Z=!L;N=L&bSign; ticks++; break;
  303.         /* INC ZP  */ case 0xE6: L=peek(H)+1;poke(H,L);Z=!L;N=L&bSign; ticks++; break;
  304.         /* INC ZPX */ case 0xF6: L=peek(H+X)+1;poke(H,L);Z=!L;N=L&bSign; ticks++; break;
  305.         // -- 08
  306.         /* PHP IMP */ case 0x08: stack_push(flags); break;
  307.         /* CLC IMP */ case 0x18: C=0; break;
  308.         /* PLP IMP */ case 0x28: switchf=1;flags=stack_pop(); break;
  309.         /* SEC IMP */ case 0x38: C=1; break;
  310.         /* PHA IMP */ case 0x48: stack_push(A); break;
  311.         /* CLI IMP */ case 0x58: I=0; break;
  312.         /* PLA IMP */ case 0x68: A=stack_pop(A); break;
  313.         /* SEI IMP */ case 0x78: I=1; break;
  314.         /* DEY IMP */ case 0x88: Y--; break;
  315.         /* TYA IMP */ case 0x98: A=Y; break;
  316.         /* TAY IMP */ case 0xA8: Y=A; break;
  317.         /* CLV IMP */ case 0xB8: V=0; break;
  318.         /* INY IMP */ case 0xC8: Y++; break;
  319.         /* CLD IMP */ case 0xD8: D=0; break;
  320.         /* INX IMP */ case 0xE8: X++; break;
  321.         /* SED IMP */ case 0xF8: D=1; break;
  322.         // -- 09
  323.         /* ORA IMM */ case 0x09: A|=H; ticks++; break;
  324.         /* ORA ABY */ case 0x19: A|=peek(H+Y); ticks+=2; break;
  325.         /* AND IMM */ case 0x29: A&=H; ticks++; break;
  326.         /* AND ABY */ case 0x39: A&=peek(HL+Y); ticks+=2; break;
  327.         /* EOR IMM */ case 0x49: A^=peek(H); ticks++; break;
  328.         /* EOR ABY */ case 0x59: A^=peek(HL+Y); ticks+=2; break;
  329.         /* ADC IMM */ case 0x69: ADC(H);A+=H+C; ticks++; break;
  330.         /* ADC ABY */ case 0x79: H=peek(HL+Y);ADC(H);A+=H+C; ticks+=2; break;
  331.         /* STA ABY */ case 0x99: poke(HL+Y,A); ticks+=2; break;
  332.         /* LDA IMM */ case 0xA9: A=H; ticks++; break;
  333.         /* LDA ABY */ case 0xB9: A=peek(HL+Y); ticks+=2; break;
  334.         /* CMP IMM */ case 0xC9: CMP(A,H); ticks++; break;
  335.         /* CMP ABY */ case 0xD9: H=peek(HL+Y);CMP(A,H); ticks+=2; break;
  336.         /* SBC IMM */ case 0xE9: SBC(H);A-=H-~C; ticks++; break;
  337.         /* SBC ABY */ case 0xF9: H=peek(HL+Y);SBC(H);A-=H-~C; ticks+=2; break;
  338.         // -- 0A
  339.         /* ASL ACC */ case 0x0A: H=A<<1;C=(A&bSign);N=(H&bSign);A=H; break;
  340.         /* ROL ACC */ case 0x2A: H=ROL(A);C=(A&bSign);N=(H&bSign);A=H; ticks++; break;
  341.         /* LSR ACC */ case 0x4A: H=(sbyte_t)A>>1;C=(A&1);N=(H&bSign);A=H; ticks++; break;
  342.         /* ROR ACC */ case 0x6A: H=ROR(A);C=(A&1);N=(H&bSign);A=H; ticks++; break;
  343.         /* TXA IMP */ case 0x8A: A=X; break;
  344.         /* TXS IMP */ case 0x9A: stack_push(X); break;
  345.         /* TAX IMP */ case 0xAA: X=A; break;
  346.         /* TSX IMP */ case 0xBA: X=stack_pop(); break;
  347.         /* DEX IMP */ case 0xCA: X--; break;
  348.         /* NOP IMP */ case 0xEA: break;
  349.         // -- 0C
  350.         /* BIT ABS */ case 0x2C: H=peek(HL);Z=!(A&H);V=(H&0x20);N=(H&0x40); ticks+=2; break;
  351.         /* JMP ABS */ case 0x4C: pc=HL; ticks=0; break;
  352.         /* JMP IND */ case 0x6C: pc=dIND(HL); ticks=0; break;
  353.         /* STY ABS */ case 0x8C: poke(HL,Y); ticks+=2; break;
  354.         /* LDY ABS */ case 0xAC: Y=peek(HL); ticks+=2; break;
  355.         /* LDY ABX */ case 0xBC: Y=peek(HL+X); ticks+=2; break;
  356.         /* CPY ABS */ case 0xCC: H=peek(HL);CMP(Y,H); ticks+=2; break;
  357.         /* CPX ABS */ case 0xEC: H=peek(HL);CMP(X,H); ticks+=2; break;
  358.         // -- 0D
  359.         /* ORA ABS */ case 0x0D: A|=peek(HL); ticks+=2; break;
  360.         /* ORA ABX */ case 0x1D: A|=peek(HL+X); ticks+=2; break;
  361.         /* AND ABS */ case 0x2D: A&=peek(HL); ticks+=2; break;
  362.         /* AND ABX */ case 0x3D: A&=peek(HL+X); ticks+=2; break;
  363.         /* EOR ABS */ case 0x4D: A^=peek(HL); ticks+=2; break;
  364.         /* EOR ABX */ case 0x5D: A^=peek(HL+X); ticks+=2; break;
  365.         /* ADC ABS */ case 0x6D: H=peek(HL);ADC(H);A+=H+C; ticks+=2; break;
  366.         /* ADC ABX */ case 0x7D: H=peek(HL+X);ADC(H);A+=H+C; ticks+=2; break;
  367.         /* STA ABS */ case 0x8D: poke(HL,A); ticks+=2; break;
  368.         /* STA ABX */ case 0x9D: poke(HL+X,A); ticks+=2; break;
  369.         /* LDA ABS */ case 0xAD: A=peek(HL); ticks+=2; break;
  370.         /* LDA ABX */ case 0xBD: A=peek(HL+X); ticks+=2; break;
  371.         /* CMP ABS */ case 0xCD: H=peek(HL);CMP(A,H); ticks+=2; break;
  372.         /* CMP ABX */ case 0xDD: H=peek(HL+X);CMP(A,H); ticks+=2; break;
  373.         /* SBC ABS */ case 0xED: H=peek(HL);SBC(H);A-=H-~C; ticks+=2; break;
  374.         /* SBC ABX */ case 0xFD: H=peek(HL+X);SBC(H);A-=H-~C; ticks+=2; break;
  375.         // -- 0E
  376.         /* ASL ABS */ case 0x0E: H=peek(HL);C=(H&bSign);N=(H<<1)&bSign;poke(HL,H<<1); ticks+=2; break;
  377.         /* ASL ABX */ case 0x1E: H=peek(HL+X);C=(H&bSign);N=(H<<1)&bSign;poke(HL+X,H<<1); ticks+=2; break;
  378.         /* ROL ABS */ case 0x2E: H=peek(HL);C=(H&bSign);N=(ROL(H)&bSign);poke(HL,ROL(H)); ticks+=2; break;
  379.         /* ROL ABX */ case 0x3E: H=peek(HL+X);C=(H&bSign);N=(ROL(H)&bSign);poke(HL+X,ROL(H)); ticks+=2; break;
  380.         /* LSR ABS */ case 0x4E: L=peek(HL);H=(sbyte_t)L>>1;poke(HL,H);C=(L&1);N=(H&bSign);Z=!H; ticks+=2; break;
  381.         /* LSR ABX */ case 0x5E: L=peek(HL);H=(sbyte_t)L>>1;poke(HL,H);C=(L&1);N=(H&bSign);Z=!H; ticks+=2; break;
  382.         /* ROR ABS */ case 0x6E: H=peek(HL);C=(H&bSign);N=(ROR(H)&bSign);poke(HL,ROR(H)); ticks+=2; break;
  383.         /* ROR ABX */ case 0x7E: H=peek(HL+X);C=(H&bSign);N=(ROR(H)&bSign);poke(HL+X,ROR(H)); ticks+=2; break;
  384.         /* STX ABS */ case 0x8E: poke(HL,X); ticks+=2; break;
  385.         /* LDX ABS */ case 0x9E: X=peek(HL); ticks+=2; break;
  386.         /* LDX ABY */ case 0xBE: X=peek(HL+Y); ticks+=2; break;
  387.         /* DEC ABS */ case 0xCE: H=peek(HL)-1;poke(HL,H);Z=!H;N=H&bSign; ticks+=2; break;
  388.         /* DEC ABX */ case 0xDE: H=peek(HL+X)-1;poke(HL,H);Z=!H;N=H&bSign; ticks+=2; break;
  389.         /* INC ABS */ case 0xEE: H=peek(HL)+1;poke(HL,H);Z=!H;N=H&bSign; ticks+=2; break;
  390.         /* INC ABX */ case 0xFE: H=peek(HL+X)+1;poke(HL,H);Z=!H;N=H&bSign; ticks+=2; break;
  391.  
  392.         // ERR
  393.         default:
  394.             printf("\nEncountered Invalid instruction, halting...");
  395.             CPU_Pause();
  396.             return NULL;
  397.         break;
  398.     }
  399.  
  400.     // Very useful for running just to get how many bytes an instruction takes.
  401.     if(demo) return ticks;
  402.  
  403.     if(pCPU->STEP)
  404.     {
  405.         printf("\n-------------------------");
  406.         printf("\nRunning: %X", c);
  407.     }
  408.  
  409.     // SetReg is used here to trigger flags.
  410.     if(!switchf)
  411.     {
  412.         flagset(fCarry,C);
  413.         flagset(fZero,Z);
  414.         flagset(fInterupt,I);
  415.         flagset(fDecimal,D);
  416.         flagset(fBreak,B);
  417.         flagset(fOverflow,V);
  418.         flagset(fNegative,N);
  419.     }
  420.     else
  421.     {
  422.         pCPU->Flags = flags;
  423.     }
  424.  
  425.     if(pCPU->A!=A)SetReg(rA,A);
  426.     if(pCPU->X!=X)SetReg(rX,X);
  427.     if(pCPU->Y!=Y)SetReg(rY,Y);
  428.  
  429.     pCPU->PC = pc;
  430.  
  431.     if(pCPU->STEP)
  432.     {
  433.         printf_cpuinfo();
  434.         printf("-------------------------\n");
  435.     }
  436.     pCPU->PC += ticks;
  437.     wait_timer(); // Wait next icycle.
  438.     return ticks;
  439. }
  440.  
  441. // Routine definitions
  442.  
  443. bool initalize()
  444. {
  445.     pRAM = calloc(64, 1024); // 64k of RAM.
  446.     pCPU = malloc( sizeof(struct CPU) );
  447.  
  448.     if(!pRAM || !pCPU) return false;
  449.  
  450.     // Reset CPU
  451.     pCPU->Flags = fUnknown;
  452.     pCPU->A     = 0x00;
  453.     pCPU->X     = 0x00;
  454.     pCPU->Y     = 0x00;
  455.     pCPU->PC    = ProgramStart;
  456.     pCPU->SP    = 0xFF;
  457.     pCPU->STEP  = false;
  458.  
  459.     // Switch to terminal
  460.     inTerminal = true;
  461.  
  462.     return true;
  463. }
  464.  
  465. void CPU_Start()
  466. {
  467.     while( !(pCPU->Flags & fBreak) )
  468.     {
  469.         run_instr(peek(pCPU->PC),false);
  470.         if(pCPU->STEP)getch();
  471.     }
  472.     printf("\nStopped at: PC=$%x\n",pCPU->PC);
  473.     printf("System time: %.0f usec.\n",uTimer);
  474.     printf("-------------------------\n");
  475.     printf_cpuinfo();
  476. }
  477.  
  478. // Assembler
  479. void RunTerminal()
  480. {
  481.    // Label support.
  482.    char* buffer = calloc(1,100);
  483.    TermData* tdata;
  484.    int label_c=0;
  485.    ALabel** labels = calloc(20,sizeof(ALabel));
  486.    while(inTerminal)
  487.    {
  488.        if(!(pCPU->Flags&fBreak))
  489.        {
  490.            label_c = 0;
  491.            CPU_Start();
  492.            pCPU->PC--;
  493.        }
  494.        char pbytes[7];
  495.        char* found; // Used for labels.
  496.        sbyte_t addr_rel = ((sbyte_t)(ProgramStart-pCPU->PC));
  497.        printf("%X[%02X]: ",pCPU->PC,(byte_t)addr_rel);
  498.        fgets(buffer,100,stdin);
  499.        for(int i = 0; i < label_c; i++)
  500.        {
  501.            found = strstr(buffer,labels[i]->name);
  502.            if( found != NULL )
  503.            {
  504.                for(int x = 0; x < strlen(labels[i]->name); x++) *(found+i)=' ';
  505.                sprintf(found,"$%04X",labels[i]->absolute);
  506.            }
  507.        }
  508.        tdata = AssembleCMD(buffer,100,pCPU->PC);
  509.        char* fbuffer = tdata->finp.inp;
  510.        if(tdata->bytecode==0xFF)
  511.        {
  512.            // Labels!
  513.            if(!strncasecmp(fbuffer,"::",2))
  514.            {
  515.                ALabel* label = malloc(sizeof(ALabel));
  516.                char* name = malloc(strlen(fbuffer)-2);
  517.                strncpy(name,fbuffer+2,strlen(fbuffer)-1);
  518.                label->name = name;
  519.                label->relative = addr_rel;
  520.                label->absolute = pCPU->PC;
  521.                *(labels+label_c) = label;
  522.                label_c++;
  523.            }
  524.            else if(!strncmp(fbuffer,"RUNP",4))
  525.            {
  526.                pCPU->PC = ProgramStart;
  527.                flagset(fBreak,false);
  528.            }
  529.            else if(!strncmp(fbuffer,"RUN",3))
  530.                flagset(fBreak,false);
  531.            else if(!strncmp(fbuffer,"EXIT",4))
  532.            {
  533.                free(tdata->finp.inp);
  534.                free(tdata);
  535.                inTerminal = false;
  536.            }
  537.            else if(!strncmp(fbuffer,"=P",2))
  538.                pCPU->PC = ProgramStart;
  539.            else if(!strncmp(fbuffer,"=",1))
  540.            {
  541.                char pc[4];
  542.                int offs = (*(fbuffer+1)=='$')?2:1;
  543.                strncpy(pc,fbuffer+offs,4);
  544.                mem_t addr = strtol(pc,NULL,16);
  545.                pCPU->PC = addr;
  546.            }
  547.            else if(!strncmp(fbuffer,"PC=",1))
  548.            {
  549.                char pc[4];
  550.                int offs = (*(fbuffer+3)=='$')?4:3;
  551.                strncpy(pc,fbuffer+offs,4);
  552.                mem_t addr = strtol(pc,NULL,16);
  553.                pCPU->PC = addr;
  554.            }
  555.            else if(!strncmp(fbuffer,"++",2))
  556.                pCPU->PC++;
  557.            else if(!strncmp(fbuffer,"--",2))
  558.                pCPU->PC--;
  559.            else if(!strncmp(fbuffer,"STEP",4))
  560.            {
  561.                pCPU->STEP = !pCPU->STEP;
  562.                if(pCPU->STEP)
  563.                    printf("Stepping mode ON.\n");
  564.                else
  565.                    printf("Stepping mode OFF.\n");
  566.            }
  567.            else if(!strncmp(fbuffer,"RESET",5))
  568.            {
  569.                label_c = 0;
  570.                uTimer = clock();
  571.                initalize();
  572.                wait_timer();
  573.            }
  574.            else if(!strncmp(fbuffer,"READ",4)|!strncmp(fbuffer,"R",1))
  575.                printf("%X -> %X\n",pCPU->PC,peek(pCPU->PC));
  576.            else if(!strncmp(fbuffer,"HELP",4))
  577.            {
  578.                 printf("\n        .: LIST OF COMMANDS :.\n\n");
  579.                 printf("RUNP   : Runs program starting at 0x0600\n");
  580.                 printf("RUN    : Runs program at current addr\n");
  581.                 printf("=      : Sets PC to numeric argument\n");
  582.                 printf("PC=    : Check above\n");
  583.                 printf("=P     : Set PC to 0x0600\n");
  584.                 printf("++     : PC++\n");
  585.                 printf("--     : PC--\n");
  586.                 printf("STEP   : Toggles program stepping\n");
  587.                 printf("RESET  : Resets CPU and Assembler\n");
  588.                 printf("EXIT   : Exits program\n");
  589.                 printf("\n        .: Assembler Quirks :.\n\n");
  590.                 printf("::NAME : Declares NAME as Label at current addr\n\n");
  591.            }
  592.            else
  593.            {
  594.                printf("Syntax error\n");
  595.            }
  596.        }
  597.        else
  598.        {
  599.            mem_t pc = pCPU->PC;
  600.            // Insert instruction/bytes into RAM.
  601.            poke(pc,tdata->bytecode);
  602.            if(tdata->bytes > 1) poke(pc+1,tdata->H);
  603.            if(tdata->bytes > 2) poke(pc+2,tdata->L);
  604.            pCPU->PC += tdata->bytes;
  605.        }
  606.        free(tdata->finp.inp);
  607.        free(tdata);
  608.    }
  609.    for(int i = 0; i < label_c; i++)
  610.    {
  611.        free(labels[i]->name);
  612.        free(labels[i]);
  613.    }
  614.    free(buffer);
  615. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement