#include #include #include #include #include typedef struct { // TTL state that the CPU controls uint16_t PC; uint8_t IR, D, AC, X, Y, OUT, undef; } CpuState; uint8_t ROM[1<<16][2], RAM[1<<15], IN=0xff; CpuState cpuCycle(const CpuState S) { CpuState T = S; // New state is old state unless something changes T.IR = ROM[S.PC][0]; // Instruction Fetch T.D = ROM[S.PC][1]; int ins = S.IR >> 5; // Instruction int mod = (S.IR >> 2) & 7; // Addressing mode (or condition) int bus = S.IR&3; // Busmode int W = (ins == 6); // Write instruction? int J = (ins == 7); // Jump instruction? uint8_t lo=S.D, hi=0, *to=NULL; // Mode Decoder int incX=0; if (!J) switch (mod) { #define E(p) (W?0:p) // Disable AC and OUT loading during RAM write case 0: to=E(&T.AC); break; case 1: to=E(&T.AC); lo=S.X; break; case 2: to=E(&T.AC); hi=S.Y; break; case 3: to=E(&T.AC); lo=S.X; hi=S.Y; break; case 4: to= &T.X; break; case 5: to= &T.Y; break; case 6: to=E(&T.OUT); break; case 7: to=E(&T.OUT); lo=S.X; hi=S.Y; incX=1; break; } uint16_t addr = (hi << 8) | lo; int B = S.undef; // Data Bus switch (bus) { case 0: B=S.D; break; case 1: if (!W) B = RAM[addr&0x7fff]; break; case 2: B=S.AC; break; case 3: B=IN; break; } if (W) RAM[addr&0x7fff] = B; // Random Access Memory uint8_t ALU; // Arithmetic and Logic Unit switch (ins) { case 0: ALU = B; break; // LD case 1: ALU = S.AC & B; break; // ANDA case 2: ALU = S.AC | B; break; // ORA case 3: ALU = S.AC ^ B; break; // XORA case 4: ALU = S.AC + B; break; // ADDA case 5: ALU = S.AC - B; break; // SUBA case 6: ALU = S.AC; break; // ST case 7: ALU = -S.AC; break; // Bcc/JMP } if (to) *to = ALU; // Load value into register if (incX) T.X = S.X + 1; // Increment X T.PC = S.PC + 1; // Next instruction if (J) { if (mod != 0) { // Conditional branch within page int cond = (S.AC>>7) + 2*(S.AC==0); if (mod & (1 << cond)) // 74153 T.PC = (S.PC & 0xff00) | B; } else T.PC = (S.Y << 8) | B; // Unconditional far jump } return T; } void garble(uint8_t mem[], int len) { for (int i=0; i 0) { // Rising hSync edge SDL_Event event; SDL_Rect dstrect; SDL_Rect srcrect; srcrect.x = 0; srcrect.w = 640; srcrect.y = vgaY; srcrect.h = 1; dstrect.x = 0; dstrect.w = 640; dstrect.y = vgaY; dstrect.h = 1; SDL_UpdateTexture(texture, &dstrect, pixels, 640 * sizeof(Uint32)); //SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, &srcrect, &dstrect); SDL_RenderPresent(renderer); vgaX = 0; vgaY++; T.undef = rand() & 0xff; // Change this once in a while if (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) break; } } S=T; } return 0; }