From: ayabusa Date: Wed, 24 Dec 2025 17:40:09 +0000 (+0100) Subject: added rom loading, reg and mem structure, and did the instruction decoder X-Git-Url: https://git.ayabusa.dev/?a=commitdiff_plain;h=622c5af4ab2ec99e9b81de275f7cdebb29e0d410;p=chipy-8.git added rom loading, reg and mem structure, and did the instruction decoder --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28c2520 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +*.swp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f3947a6 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +flags = -g -Wall -Wextra -fsanitize=address +src = src/*.c +inc = src/ +out = build/chipy8 +rom = game.ch8 + +all: clean comp run + +clean: + rm -f $(out) + +comp: + $(CC) $(src) -I $(inc) -o $(out) $(flags) + +run: + ./$(out) $(rom) diff --git a/game.ch8 b/game.ch8 new file mode 100644 index 0000000..d5a865f Binary files /dev/null and b/game.ch8 differ diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..015a2d2 --- /dev/null +++ b/src/font.h @@ -0,0 +1,23 @@ +#ifndef FONT_H +#define FONT_H + +const uint8_t font[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 +}; + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d265ec5 --- /dev/null +++ b/src/main.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include "font.h" +#include "processor.h" + +int init(ch8_ctx * context, char * rom_name){ + FILE * rom_file = fopen(rom_name, "r"); + if (rom_file == NULL){ + printf("Could not open the file <%s>\n", rom_name); + fclose(rom_file); + return 1; + } + context->RAM = calloc(0x1000, 1); + if (context->RAM == NULL){ + printf("Could not allocate enough space (4KB)\n"); + fclose(rom_file); + return 1; + } + // The font is located at address 0, so that program can access it + memcpy(context->RAM, font, 80); + + // Next we load the rom at address 0x200 + fread((context->RAM + 0x200), 1, 0xDFF, rom_file); + + fclose(rom_file); + return 0; +} + + +int main(int argc, char * argv[]){ + if (argc!=2){ + printf("Usage: ./chipy8 \n"); + return 1; + } + printf("Welcome to the Chipy 8 emulator!\n"); + + ch8_ctx context = {NULL, {0}, 0, 0, 0, 0x200, 0, {0}}; + if(init(&context, argv[1])){ // If error in init + free(context.RAM); + return 1; + } + int running = 1; + while (running){ + ; + } + free(context.RAM); + return 0; +} diff --git a/src/processor.c b/src/processor.c new file mode 100644 index 0000000..b625a76 --- /dev/null +++ b/src/processor.c @@ -0,0 +1,139 @@ +#include +#include +#include "processor.h" + +void execute_instruction(ch8_ctx * ctx){ + // The two instruction bytes + uint8_t b1=*(ctx->RAM + ctx->PC), b2=*(ctx->RAM + ctx->PC + 1); + if(b1==0 && b2 == 0xE0){ + ins_CLS(ctx); + ctx->PC++; + return; + }if(b1==0 && b2 == 0xEE){ + ins_RET(ctx); + return; + } + // First nimble (4 bits) + uint8_t n1 = (b1&0xF0)>>4; + switch (n1){ + //case 0: + //Sys instr, deprecated + //break; + case 1: + ins_JP(ctx); + return; + case 2: + ins_CALL(ctx); + return; + case 3: + ins_SE(ctx); + break; + case 4: + ins_SNE(ctx); + break; + case 5: + ins_SEV(ctx); + break; + case 6: + ins_LD(ctx); + break; + case 7: + ins_ADD(ctx); + break; + case 8: + // Last nimble + uint8_t n4=b2&0xF; + switch (n4){ + case 0: + ins_LDV(ctx); + break; + case 1: + ins_OR(ctx); + break; + case 2: + ins_ANDV(ctx); + break; + case 3: + ins_XOR(ctx); + break; + case 4: + ins_ADDV(ctx); + break; + case 5: + ins_SUB(ctx); + break; + case 6: + ins_SHR(ctx); + break; + case 7: + ins_SUBN(ctx); + break; + case 0xE: + ins_SHL(ctx); + break; + default: + printf("Unknown 8xxx instruction b1: %X b2: %X\n", b1, b2); + break; + } + break; + case 9: + ins_SNEV(ctx); + break; + case 0xA: + ins_LDI(ctx); + break; + case 0xB: + ins_JPV(ctx); + break; + case 0xC: + ins_RND(ctx); + break; + case 0xD: + ins_DRW(ctx); + break; + case 0xE: + if(b2==0x9E) + ins_SKP(ctx); + else if(b2==0xA1) + ins_SKNP(ctx); + else + printf("Unknown Exxx instruction b1: %X b2: %X\n", b1, b2); + break; + default: // 0xF + switch (b2){ + case 7: + ins_LDVDT(ctx); + break; + case 0xA: + ins_LDK(ctx); + break; + case 0x15: + ins_LDDTV(ctx); + break; + case 0x18: + ins_LDST(ctx); + break; + case 0x1E: + ins_ADDI(ctx); + break; + case 0x29: + ins_LDF(ctx); + break; + case 0x33: + ins_LDB(ctx); + break; + case 0x55: + ins_LD_Rng_IV(ctx); + break; + case 0x65: + ins_LD_Rng_VI(ctx); + break; + default: + printf("Unknown Fxxx instruction b1: %X b2: %X\n", b1, b2); + } + break; + } + // Goes to next instruction. + // Note: we do not implement the Super Chip 48 instruction set + ctx->PC++; +} diff --git a/src/processor.h b/src/processor.h new file mode 100644 index 0000000..d366a58 --- /dev/null +++ b/src/processor.h @@ -0,0 +1,26 @@ +#ifndef PROCESSOR_H +#define PROCESSOR_H + +typedef struct{ +// The ram which store the ROM, DATA and some interpreter stuff +uint8_t * RAM; + +// general purpose registers +uint8_t REGS[16]; + +// address special reg +uint16_t I; + +// Delay and sound timers +uint8_t DT; +uint8_t ST; + +// Program counter, not accessible directly by the game +uint16_t PC; + +// Stack and stack pointer +uint8_t SP; +uint16_t STACK[16]; +} ch8_ctx; + +#endif