From 5fbaa3f62c6fae213845f63bb04cdf959252d963 Mon Sep 17 00:00:00 2001 From: ayabusa Date: Fri, 9 Jan 2026 19:00:39 +0100 Subject: [PATCH] Added most of the instructions, but it'll need further testing. --- src/font.h | 2 + src/main.c | 6 +- src/processor.c | 240 ++++++++++++++++++++++++++++++++++++++++-------- src/processor.h | 2 + 4 files changed, 212 insertions(+), 38 deletions(-) diff --git a/src/font.h b/src/font.h index 015a2d2..7c47f2d 100644 --- a/src/font.h +++ b/src/font.h @@ -1,6 +1,8 @@ #ifndef FONT_H #define FONT_H +#include + const uint8_t font[80] = { 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 0x20, 0x60, 0x20, 0x20, 0x70, // 1 diff --git a/src/main.c b/src/main.c index d265ec5..36eff79 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "font.h" #include "processor.h" @@ -36,12 +37,13 @@ int main(int argc, char * argv[]){ } printf("Welcome to the Chipy 8 emulator!\n"); - ch8_ctx context = {NULL, {0}, 0, 0, 0, 0x200, 0, {0}}; + 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; + srand( time( NULL ) ); while (running){ ; } diff --git a/src/processor.c b/src/processor.c index b625a76..3a76ab5 100644 --- a/src/processor.c +++ b/src/processor.c @@ -1,75 +1,243 @@ #include #include +#include #include "processor.h" +void ins_CLS(ch8_ctx * ctx){ + //TODO +} + +void ins_DRW(ch8_ctx * ctx, uint8_t x, uint8_t y, uint8_t n){ + //TODO +} + +void ins_JP(ch8_ctx * ctx, uint16_t nnn){ + ctx->PC = nnn; +} + +void ins_CALL(ch8_ctx * ctx, uint16_t nnn){ + ctx->SP++; + ctx->STACK[ctx->SP] = ctx->PC; + ctx->PC = nnn; +} + +void ins_RET(ch8_ctx * ctx){ + ctx->PC = ctx->STACK[ctx->SP]; + ctx->SP--; +} + +void ins_SE_IM(ch8_ctx * ctx, uint8_t x, uint8_t kk){ + if(ctx->REGS[x] == kk) + ctx->PC+=2; +} + +void ins_SNE_IM(ch8_ctx * ctx, uint8_t x, uint8_t kk){ + if(ctx->REGS[x] != kk) + ctx->PC+=2; +} + +void ins_SE(ch8_ctx * ctx, uint8_t x, uint8_t y){ + if(ctx->REGS[x] == ctx->REGS[y]) + ctx->PC+=2; +} + +void ins_LD_IM(ch8_ctx * ctx, uint8_t x, uint8_t kk){ + ctx->REGS[x] = kk; +} + +void ins_ADD_IM(ch8_ctx * ctx, uint8_t x, uint8_t kk){ + ctx->REGS[x]+=kk; +} + +void ins_LD(ch8_ctx * ctx, uint8_t x, uint8_t y){ + ctx->REGS[x] = ctx->REGS[y]; +} + +void ins_OR(ch8_ctx * ctx, uint8_t x, uint8_t y){ + ctx->REGS[x] |= ctx->REGS[y]; +} + +void ins_AND(ch8_ctx * ctx, uint8_t x, uint8_t y){ + ctx->REGS[x] &= ctx->REGS[y]; +} + +void ins_XOR(ch8_ctx * ctx, uint8_t x, uint8_t y){ + ctx->REGS[x] ^= ctx->REGS[y]; +} + +void ins_ADD(ch8_ctx * ctx, uint8_t x, uint8_t y){ + ctx->REGS[x] += ctx->REGS[y]; + uint16_t overflow = ctx->REGS[x] + ctx->REGS[y]; + ctx->REGS[0xF] = overflow>255; +} + +void ins_SUB(ch8_ctx * ctx, uint8_t x, uint8_t y){ + ctx->REGS[0xF] = ctx->REGS[x] > ctx->REGS[y]; + ctx->REGS[x] -= ctx->REGS[y]; +} + +void ins_SUBN(ch8_ctx * ctx, uint8_t x, uint8_t y){ + ctx->REGS[0xF] = ctx->REGS[y] > ctx->REGS[x]; + ctx->REGS[x] = ctx->REGS[y] - ctx->REGS[x]; +} + +void ins_SHR(ch8_ctx * ctx, uint8_t x){ + ctx->REGS[0xF] = x & 1; + ctx->REGS[x] = ctx->REGS[x]>>1; +} + +void ins_SHL(ch8_ctx * ctx, uint8_t x){ + ctx->REGS[0xF] = x & 0x80; + ctx->REGS[x] = ctx->REGS[x]<<1; +} + +void ins_SNE(ch8_ctx * ctx, uint8_t x, uint8_t y){ + if(ctx->REGS[x] != ctx->REGS[y]) + ctx->PC += 2; +} + +void ins_LD_I_nnn(ch8_ctx * ctx, uint16_t nnn){ + ctx->I=nnn; +} + +void ins_JP_V0(ch8_ctx * ctx, uint16_t nnn){ + ctx->PC = ctx->REGS[0] + nnn; +} + +void ins_RND(ch8_ctx * ctx, uint8_t x, uint8_t kk){ + ctx->REGS[x] = rand() & kk; +} + +void ins_SKP(ch8_ctx * ctx, uint8_t x){ + //TODO +} + +void ins_SKNP(ch8_ctx * ctx, uint8_t x){ + //TODO +} + +void ins_LDK(ch8_ctx * ctx, uint8_t x){ + //TODO +} + +void ins_LD_V_DT(ch8_ctx * ctx, uint8_t x){ + ctx->REGS[x] = ctx->DT; +} + +void ins_LD_DT_V(ch8_ctx * ctx, uint8_t x){ + ctx->DT = ctx->REGS[x]; +} + +void ins_LD_ST(ch8_ctx * ctx, uint8_t x){ + ctx->ST = ctx->REGS[x]; +} + +void ins_ADD_I(ch8_ctx * ctx, uint8_t x){ + ctx->I += ctx->REGS[x]; +} + +void ins_LD_F(ch8_ctx * ctx, uint8_t x){ + ctx->I = ctx->REGS[x] * 5; +} + +void ins_LD_B(ch8_ctx * ctx, uint8_t x){ + uint8_t nb = ctx->REGS[x]; + ctx->RAM[ctx->I + 2] = nb%10; + nb/=10; + ctx->RAM[ctx->I + 1] = nb%10; + nb/=10; + ctx->RAM[ctx->I] = nb; +} + +void ins_LD_I_V(ch8_ctx * ctx, uint8_t x){ + for(uint8_t i; i<=x; i++) + ctx->RAM[ctx->I + i] = ctx->REGS[i]; +} + +void ins_LD_V_I(ch8_ctx * ctx, uint8_t x){ + for(uint8_t i; i<=x; i++) + ctx->REGS[i] = ctx->RAM[ctx->I + i]; +} + 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++; + ctx->PC+=2; return; }if(b1==0 && b2 == 0xEE){ ins_RET(ctx); return; } + // Instruction: (3 is the instruction prefix, so n1 here) + // 3nnn: address + // 3xkk: x is the Vx reg, and kk an immediate value + // 3xy0: y is another Vy reg. + // First nimble (4 bits) uint8_t n1 = (b1&0xF0)>>4; + // Last nimble + uint8_t n4 = b2&0xF; + uint8_t x = (b1&0xF); + uint8_t y = (b2&0xF0)>>4; + uint16_t kk = b2; + uint16_t nnn = b2 + (x<<8); + + // << Switch de la mort qui tue >> switch (n1){ //case 0: //Sys instr, deprecated //break; case 1: - ins_JP(ctx); + ins_JP(ctx, nnn); return; case 2: - ins_CALL(ctx); + ins_CALL(ctx, nnn); return; case 3: - ins_SE(ctx); + ins_SE_IM(ctx, x, kk); break; case 4: - ins_SNE(ctx); + ins_SNE_IM(ctx, x, kk); break; case 5: - ins_SEV(ctx); + ins_SE(ctx, x, y); break; case 6: - ins_LD(ctx); + ins_LD_IM(ctx, x, kk); break; case 7: - ins_ADD(ctx); + ins_ADD_IM(ctx, x, kk); break; case 8: - // Last nimble - uint8_t n4=b2&0xF; switch (n4){ case 0: - ins_LDV(ctx); + ins_LD(ctx, x, y); break; case 1: - ins_OR(ctx); + ins_OR(ctx, x, y); break; case 2: - ins_ANDV(ctx); + ins_AND(ctx, x, y); break; case 3: - ins_XOR(ctx); + ins_XOR(ctx, x, y); break; case 4: - ins_ADDV(ctx); + ins_ADD(ctx, x, y); break; case 5: - ins_SUB(ctx); + ins_SUB(ctx, x, y); break; case 6: - ins_SHR(ctx); + ins_SHR(ctx, x); break; case 7: - ins_SUBN(ctx); + ins_SUBN(ctx, x, y); break; case 0xE: - ins_SHL(ctx); + ins_SHL(ctx, x); break; default: printf("Unknown 8xxx instruction b1: %X b2: %X\n", b1, b2); @@ -77,56 +245,56 @@ void execute_instruction(ch8_ctx * ctx){ } break; case 9: - ins_SNEV(ctx); + ins_SNE(ctx, x, y); break; case 0xA: - ins_LDI(ctx); + ins_LD_I_nnn(ctx, nnn); break; case 0xB: - ins_JPV(ctx); + ins_JP_V0(ctx, nnn); break; case 0xC: - ins_RND(ctx); + ins_RND(ctx, x, kk); break; case 0xD: - ins_DRW(ctx); + ins_DRW(ctx, x, y, n4); break; case 0xE: if(b2==0x9E) - ins_SKP(ctx); + ins_SKP(ctx, x); else if(b2==0xA1) - ins_SKNP(ctx); + ins_SKNP(ctx, x); else printf("Unknown Exxx instruction b1: %X b2: %X\n", b1, b2); break; default: // 0xF switch (b2){ case 7: - ins_LDVDT(ctx); + ins_LD_V_DT(ctx, x); break; case 0xA: - ins_LDK(ctx); + ins_LDK(ctx, x); break; case 0x15: - ins_LDDTV(ctx); + ins_LD_DT_V(ctx, x); break; case 0x18: - ins_LDST(ctx); + ins_LD_ST(ctx, x); break; case 0x1E: - ins_ADDI(ctx); + ins_ADD_I(ctx, x); break; case 0x29: - ins_LDF(ctx); + ins_LD_F(ctx, x); break; case 0x33: - ins_LDB(ctx); + ins_LD_B(ctx, x); break; case 0x55: - ins_LD_Rng_IV(ctx); + ins_LD_I_V(ctx, x); break; case 0x65: - ins_LD_Rng_VI(ctx); + ins_LD_V_I(ctx, x); break; default: printf("Unknown Fxxx instruction b1: %X b2: %X\n", b1, b2); @@ -135,5 +303,5 @@ void execute_instruction(ch8_ctx * ctx){ } // Goes to next instruction. // Note: we do not implement the Super Chip 48 instruction set - ctx->PC++; + ctx->PC+=2; } diff --git a/src/processor.h b/src/processor.h index d366a58..9243eca 100644 --- a/src/processor.h +++ b/src/processor.h @@ -1,6 +1,8 @@ #ifndef PROCESSOR_H #define PROCESSOR_H +#include "stdint.h" + typedef struct{ // The ram which store the ROM, DATA and some interpreter stuff uint8_t * RAM; -- 2.43.0