8

a CHIP-8 emulator
Log | Files | Refs | README

commit d804131ea9e814054e08ce16e90009b87b199522
Author: Naveen Narayanan <nan@sysgo.com>
Date:   Sun,  6 Mar 2022 16:00:17 +0100

Initial commit

Diffstat:
A8.c | 299+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AMakefile | 8++++++++
AREADME | 6++++++
3 files changed, 313 insertions(+), 0 deletions(-)

diff --git a/8.c b/8.c @@ -0,0 +1,299 @@ +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +#define BUFSZ 256 + +unsigned short opcode; +unsigned char mem[4096]; +unsigned char V[16]; +unsigned short I; +unsigned short pc; +unsigned char gfx[64 * 32]; +unsigned char delaytmr; +unsigned char soundtmr; +unsigned short stack[16]; +unsigned short* sp; +unsigned char keys[16]; +unsigned char buf[BUFSZ]; + +unsigned char fnt[80] = +{ + 0xF0, 0x90, 0x90, 0x90, 0xF0, //0 + 0x20, 0x60, 0x20, 0x20, 0x70, //1 + 0xF0, 0x10, 0xF0, 0x80, 0xF0, //2 + 0xF0, 0x10, 0xF0, 0x10, 0xF0, //3 + 0x90, 0x90, 0xF0, 0x10, 0x10, //4 + 0xF0, 0x80, 0xF0, 0x10, 0xF0, //5 + 0xF0, 0x80, 0xF0, 0x90, 0xF0, //6 + 0xF0, 0x10, 0x20, 0x40, 0x40, //7 + 0xF0, 0x90, 0xF0, 0x90, 0xF0, //8 + 0xF0, 0x90, 0xF0, 0x10, 0xF0, //9 + 0xF0, 0x90, 0xF0, 0x90, 0x90, //A + 0xE0, 0x90, 0xE0, 0x90, 0xE0, //B + 0xF0, 0x80, 0x80, 0x80, 0xF0, //C + 0xE0, 0x90, 0x90, 0x90, 0xE0, //D + 0xF0, 0x80, 0xF0, 0x80, 0xF0, //E + 0xF0, 0x80, 0xF0, 0x80, 0x80 //F +}; + +static void +init() +{ + pc = 0x200; + opcode = 0; + I = 0; + sp = stack; + + for (int i = 0; i < 80; ++i) + mem[i] = fnt[i]; + + for (int i = 0; i < BUFSZ; ++i) + mem[i + 512] = buf[i]; +} + +static void +clrscr() +{ +} + +static short +sprite() +{ + /* return address of sprite */ + return 0; +} + +static void +draw() +{ +} + +static int +key() +{ + /* return pressed key */ + return 0; +} + +static int +waitkey() +{ + /* block until keypress and return it */ + return 0; +} + +static void +bcd() +{ +} + +static void +execute() +{ + int x, y, c; + + switch (opcode & 0xF000) { + case 0x0000: + switch (opcode) { + case 0x00E0: + clrscr(); + pc += 2; + case 0x00EE: + if (sp > stack) { + pc = *sp; + --sp; + } + return; + default: + fprintf(stderr, "machine code routine\n"); + pc += 2; + return; + } + case 0x1000: + pc = opcode & 0x0FFF; + return; + case 0x2000: + *sp = pc; + ++sp; + pc = opcode & 0x0FFF; + return; + case 0x3000: + x = (opcode & 0x0F00) >> 8; + c = opcode & 0x00FF; + if (V[x] == c) + pc += 4; + return; + case 0x4000: + x = (opcode & 0x0F00) >> 8; + c = opcode & 0x00FF; + if (V[x] != c) + pc += 4; + return; + case 0x5000: + x = (opcode & 0x0F00) >> 8; + y = (opcode & 0x00F0) >> 4; + if (V[x] == V[y]) + pc += 4; + return; + case 0x6000: + x = (opcode & 0x0F00) >> 8; + c = opcode & 0x00FF; + V[x] = c; + pc += 2; + return; + case 0x7000: + x = (opcode & 0x0F00) >> 8; + c = opcode & 0x00FF; + V[x] += c; + pc += 2; + return; + case 0x8000: + x = (opcode & 0x0F00) >> 8; + y = (opcode & 0x00F0) >> 4; + pc += 2; + switch(opcode & 0x000F) { + case 0x0000: + V[x] = V[y]; + return; + case 0x0001: + V[x] |= V[y]; + return; + case 0x0002: + V[x] &= V[y]; + return; + case 0x0003: + V[x] ^= V[y]; + return; + case 0x0004: + V[0xF] = 0; + if (V[y] > CHAR_MAX - V[x]) + V[0xF] = 1; + V[x] += V[y]; + return; + case 0x0005: + V[0xF] = 0; + if (V[y] > V[x]) + V[0xF] = 1; + V[x] -= V[y]; + return; + case 0x0006: + V[0xF] = V[x] & 0x01; + V[x] >>= 1; + return; + case 0x0007: + V[0xF] = 1; + if (V[x] > V[y]) + V[0xF] = 0; + V[x] = V[y] - V[x]; + return; + case 0x000E: + V[0xF] = V[x] & 0x80; + V[x] <<= 1; + return; + default: + goto err; + } + case 0x9000: + x = (opcode & 0x0F00) >> 8; + y = (opcode & 0x00F0) >> 4; + if (V[x] != V[y]) + pc += 4; + pc += 2; + return; + case 0xA000: + I = opcode & 0x0FFF; + pc += 2; + return; + case 0xB000: + pc = V[0] + (opcode & 0x0FFF); + return; + case 0xC000: + x = (opcode & 0x0F00) >> 8; + c = (opcode & 0x00FF); + V[x] = (rand() % 256) & c; + pc += 2; + return; + case 0xD000: + x = (opcode & 0x0F00) >> 8; + y = (opcode & 0x00F0) >> 4; + c = opcode & 0x000F; + draw(V[x], V[y], c); + pc += 2; + return; + case 0xE000: + x = (opcode & 0x0F00) >> 8; + pc += 2; + switch (opcode & 0x00FF) { + case 0x009E: + if (key() == V[x]) + pc += 4; + return; + case 0x00A1: + if (key() != V[x]) + pc += 4; + return; + default: + goto err; + } + case 0xF000: + x = (opcode & 0x0F00) >> 8; + pc += 2; + switch (opcode & 0x00FF) { + case 0x0007: + V[x] = delaytmr; + return; + case 0x000A: + V[x] = waitkey(); + return; + case 0x0015: + delaytmr = V[x]; + return; + case 0x0018: + soundtmr = V[x]; + return; + case 0x001E: + I += V[x]; + return; + case 0x0029: + I = sprite(V[x]); + return; + case 0x0033: + bcd(x); + return; + case 0x0055: + for (int i = 0; i < 16; ++i) + mem[I + 1 + i] = V[i]; /* mem[I] shouldn't be modified */ + return; + case 0x0065: + for (int i = 0; i < 16; ++i) + V[i] = mem[I + 1 + i]; /* mem[I] shouldn't be modified */ + return; + default: + goto err; + } + default: + goto err; + } +err: + fprintf(stderr, "Unknown opcode: 0x%X\n", opcode); +} + +static void +cycle() +{ + opcode = mem[pc] << 8 | mem[pc+1]; + execute(); + if (delaytmr > 0) + --delaytmr; + if (soundtmr > 0) { + printf("BEEP\n"); + --soundtmr; + } +} + +int +main(int argc, char **argv) +{ + printf("Welcome to 8\n"); +} diff --git a/Makefile b/Makefile @@ -0,0 +1,8 @@ +BIN = 8 + +all: ${BIN} + +.PHONY: clean + +clean: + -rm -f ${BIN} diff --git a/README b/README @@ -0,0 +1,6 @@ +8 +--- +a CHIP-8 emulator + +love, +zer