mirror of
https://github.com/raxracks/chip8.git
synced 2024-07-05 04:11:18 +12:00
207 lines
4.1 KiB
C
207 lines
4.1 KiB
C
#include <stdio.h>
|
|
#include <slibs/slibs.h>
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
#include <cpu.h>
|
|
#include <raylib.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#define __DEBUG
|
|
|
|
#ifndef __DEBUG
|
|
#define printf
|
|
#endif
|
|
|
|
CPU cpu = { 0 };
|
|
uint8_t display[64 * 32];
|
|
|
|
int main(int argc, char** argv) {
|
|
assert(argc > 1);
|
|
|
|
srand(time(0));
|
|
|
|
sl_string code = { 0 };
|
|
sl_read_file(argv[1], &code);
|
|
memcpy(cpu.mem + 512, code.data, code.size);
|
|
|
|
InitWindow(1280, 640, "Chip8");
|
|
SetTargetFPS(60);
|
|
|
|
for(cpu.pc = 512; cpu.pc < 512 + code.size; cpu.pc += 2) {
|
|
uint8_t current = cpu.mem[cpu.pc] & 0xFF;
|
|
uint8_t a = (current >> 4) & 0xF;
|
|
uint8_t b = current & 0xF;
|
|
|
|
uint8_t next = cpu.mem[cpu.pc + 1] & 0xFF;
|
|
uint8_t c = (next >> 4) & 0xF;
|
|
uint8_t d = next & 0xF;
|
|
|
|
uint16_t address = b << 8 | c << 4 | d;
|
|
|
|
switch(a) {
|
|
case 0x0:
|
|
switch(d) {
|
|
case 0x0:
|
|
printf("CLS\n");
|
|
BeginDrawing();
|
|
ClearBackground(BLACK);
|
|
EndDrawing();
|
|
break;
|
|
case 0xE:
|
|
printf("RET\n");
|
|
break;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
cpu.pc = address - 2;
|
|
printf("JP 0x%X\n", address);
|
|
break;
|
|
case 0x3:
|
|
if(cpu.regs[b] == next)
|
|
cpu.pc += 2;
|
|
printf("SE V%X, 0x%X\n", b, next);
|
|
break;
|
|
case 0x4:
|
|
if(cpu.regs[b] != next)
|
|
cpu.pc += 2;
|
|
printf("SNE V%X, 0x%X\n", b, next);
|
|
break;
|
|
case 0x5:
|
|
if(cpu.regs[b] == cpu.regs[c])
|
|
cpu.pc += 2;
|
|
break;
|
|
case 0x6:
|
|
cpu.regs[b] = next;
|
|
printf("LD V%X, 0x%X\n", b, next);
|
|
break;
|
|
case 0x7:
|
|
cpu.regs[b] += next;
|
|
printf("ADD V%X, 0x%X\n", b, next);
|
|
break;
|
|
case 0x8:
|
|
switch(d) {
|
|
case 0x0:
|
|
cpu.regs[b] = cpu.regs[c];
|
|
printf("LD V%X, V%X\n", b, c);
|
|
break;
|
|
case 0x1:
|
|
cpu.regs[b] |= cpu.regs[c];
|
|
printf("OR V%X, V%X\n", b, c);
|
|
break;
|
|
case 0x2:
|
|
cpu.regs[b] &= cpu.regs[c];
|
|
printf("AND V%X, V%X");
|
|
break;
|
|
case 0x3:
|
|
cpu.regs[b] ^= cpu.regs[c];
|
|
break;
|
|
case 0x4:
|
|
cpu.regs[b] += cpu.regs[c];
|
|
printf("ADD V%X, V%X\n", b, c);
|
|
break;
|
|
case 0x5:
|
|
cpu.regs[b] -= cpu.regs[c];
|
|
printf("SUB V%X, V%X\n", b, c);
|
|
break;
|
|
case 0x6:
|
|
cpu.regs[0xF] = cpu.regs[b] & 1;
|
|
cpu.regs[b] >>= 1;
|
|
break;
|
|
case 0x7:
|
|
cpu.regs[b] = cpu.regs[c] - cpu.regs[b];
|
|
break;
|
|
case 0xE:
|
|
cpu.regs[0xF] = (cpu.regs[b] & 0xFF != 0) ? 1 : 0;
|
|
cpu.regs[b] <<= 1;
|
|
break;
|
|
}
|
|
break;
|
|
case 0x9:
|
|
if(cpu.regs[b] != cpu.regs[c])
|
|
cpu.pc += 2;
|
|
break;
|
|
case 0xA:
|
|
cpu.I = address;
|
|
printf("LD I, 0x%016X\n", address);
|
|
break;
|
|
case 0xB:
|
|
cpu.pc = cpu.regs[0] + address;
|
|
case 0xC:
|
|
cpu.regs[b] = rand() & next;
|
|
printf("RND V%X, 0x%X (out: 0x%08X)\n", b, next, cpu.regs[b]);
|
|
break;
|
|
case 0xD:
|
|
int xPos = cpu.regs[b];
|
|
int yPos = cpu.regs[c];
|
|
int height = d;
|
|
|
|
BeginDrawing();
|
|
for(int y = 0; y < height; y++) {
|
|
uint8_t line = cpu.mem[cpu.I + y];
|
|
for(int x = 0; x < 8; x++) {
|
|
uint8_t pixel = line & (0x80 >> x);
|
|
if(pixel != 0) {
|
|
int totalX = xPos + x;
|
|
int totalY = yPos + y;
|
|
|
|
totalX = totalX % 64;
|
|
totalY = totalY % 32;
|
|
|
|
int index = (totalY * 64) + totalX;
|
|
|
|
if(display[index] == 1)
|
|
cpu.regs[0xF] = 1;
|
|
|
|
display[index] ^= 1;
|
|
|
|
DrawRectangle((xPos + x) * 20, (yPos + y) * 20, 20, 20, display[index] == 0 ? BLACK : WHITE);
|
|
}
|
|
}
|
|
}
|
|
EndDrawing();
|
|
|
|
printf("DRW V%X, V%X, %d\n", b, c, height);
|
|
|
|
break;
|
|
case 0xF:
|
|
switch(next) {
|
|
case 0x1E:
|
|
cpu.I += cpu.regs[b];
|
|
printf("ADD I, V%X\n", b);
|
|
break;
|
|
case 0x29:
|
|
// TODO: unimplemented
|
|
break;
|
|
case 0x33:
|
|
// TODO: unimplemented
|
|
break;
|
|
case 0x55:
|
|
int offset = 0;
|
|
for(int i = 0; i <= b; i++) {
|
|
cpu.mem[cpu.I + offset++] = cpu.regs[i];
|
|
}
|
|
break;
|
|
case 0x65:
|
|
offset = 0;
|
|
for(int i = 0; i <= b; i++) {
|
|
cpu.regs[i] = cpu.mem[cpu.I + offset++];
|
|
}
|
|
printf("RSTR V%X\n", b);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("\nRegisters:\n");
|
|
for(int i = 0; i < sl_array_len(cpu.regs); i++) {
|
|
printf("V%X:\t0b%08b\t\t0x%08X\n", i, cpu.regs[i], cpu.regs[i]);
|
|
}
|
|
printf("I:\t0b%016b\t0x%016X\n", cpu.I, cpu.I);
|
|
|
|
CloseWindow();
|
|
|
|
return 0;
|
|
}
|