LD, LDH, WRAM, and HRAM

This commit is contained in:
Samuel Walker 2025-01-30 21:59:05 -07:00
parent 1bf98447a3
commit 022c24dd35
Signed by: piwalker
GPG Key ID: 616B1928705EA4C9
11 changed files with 458 additions and 58 deletions

View File

@ -3,4 +3,7 @@
#include <common.h> #include <common.h>
u8 bus_read(u16 address); u8 bus_read(u16 address);
void bus_write(u16 address, u8 value); void bus_write(u16 address, u8 value);
u16 bus_read16(u16 address);
void bus_write16(u16 address, u16 value);

View File

@ -30,6 +30,7 @@ typedef struct {
bool stepping; bool stepping;
bool int_master_enabled; bool int_master_enabled;
u8 ie_register;
} cpu_context; } cpu_context;
void cpu_init(); void cpu_init();
@ -42,4 +43,11 @@ IN_PROC inst_get_processor(in_type type);
#define CPU_FLAG_Z BIT(ctx->regs.f, 7) #define CPU_FLAG_Z BIT(ctx->regs.f, 7)
#define CPU_FLAG_C BIT(ctx->regs.f, 4) #define CPU_FLAG_C BIT(ctx->regs.f, 4)
u16 cpu_read_reg(reg_type rt); u16 cpu_read_reg(reg_type rt);
void cpu_set_reg(reg_type rt, u16 val);
void fetch_data();
u8 cpu_get_ie_register();
void cpu_set_ie_register(u8 ie);

9
include/ram.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <common.h>
u8 wram_read(u16 address);
void wram_write(u16 address, u8 value);
u8 hram_read(u16 address);
void hram_write(u16 address, u8 value);

View File

@ -1,4 +1,8 @@
#include <bus.h> #include <bus.h>
#include <common.h>
#include <cart.h>
#include <cpu.h>
#include <ram.h>
// 0x0000 - 0x3FFF : ROM Bank 0 // 0x0000 - 0x3FFF : ROM Bank 0
// 0x4000 - 0x7FFF : ROM Bank 1 - Switchable // 0x4000 - 0x7FFF : ROM Bank 1 - Switchable
@ -17,16 +21,92 @@
u8 bus_read(u16 address) { u8 bus_read(u16 address) {
if(address < 0x8000) { if(address < 0x8000) {
return cart_read(address); return cart_read(address);
} else if (address < 0xA000) {
//Char/Map Data
//TODO
printf("UNSUPPORTED bus_read(%04X)\n", address);
NO_IMPL
} else if (address < 0xC000) {
//Cartridge RAM
return cart_read(address);
} else if (address < 0xE000) {
//WRAM (Working RAM)
return wram_read(address);
} else if (address < 0xFE00) {
//reserved echo ram...
return 0;
} else if (address < 0xFEA0) {
//OAM
//TODO
printf("UNSUPPORTED bus_read(%04X)\n", address);
NO_IMPL
} else if (address < 0xFF00) {
//reserved unusable
return 0;
} else if (address < 0xFF80) {
//IO registers
//TODO
printf("UNSUPPORTED bus_read(%04X)\n", address);
//NO_IMPL
} else if (address == 0xFFFF) {
//CPU ENABLE REGISTER
//TODO
return cpu_get_ie_register();
} }
NO_IMPL return hram_read(address);
} }
void bus_write(u16 address, u8 value) { void bus_write(u16 address, u8 value) {
if(address < 0x8000) { if(address < 0x8000) {
cart_write(address); cart_write(address, value);
return;
} else if (address < 0xA000) {
//Char/Map Data
//TODO
printf("UNSUPPORTED bus_write(%04X)\n", address);
NO_IMPL
} else if (address < 0xC000) {
//Cartridge RAM
cart_write(address, value);
return;
} else if (address < 0xE000) {
//WRAM (Working RAM)
wram_write(address, value);
return;
} else if (address < 0xFE00) {
//reserved echo ram...
return;
} else if (address < 0xFEA0) {
//OAM
//TODO
printf("UNSUPPORTED bus_write(%04X)\n", address);
NO_IMPL
} else if (address < 0xFF00) {
//reserved unusable
return;
} else if (address < 0xFF80) {
//IO registers
//TODO
printf("UNSUPPORTED bus_write(%04X)\n", address);
//NO_IMPL
return;
} else if (address == 0xFFFF) {
//CPU ENABLE REGISTER
cpu_set_ie_register(value);
return; return;
} }
NO_IMPL hram_write(address, value);
}
u16 bus_read16(u16 address) {
u16 lo = bus_read(address);
u16 hi = bus_read(address+1);
return lo | (hi << 8);
}
void bus_write16(u16 address, u16 value) {
bus_write(address+1, (value >> 8) & 0xFF);
bus_write(address, value * 0xFF);
} }

View File

@ -1,4 +1,5 @@
#include <cart.h> #include <cart.h>
#include <common.h>
typedef struct { typedef struct {
char filename[1024]; char filename[1024];
@ -182,6 +183,6 @@ u8 cart_read(u16 address){
} }
void cart_write(u16 address, u8 value){ void cart_write(u16 address, u8 value){
printf("UNSUPPORTED cart_write(%04X)\n");
NO_IMPL //NO_IMPL
} }

View File

@ -1,11 +1,11 @@
#include <cpu.h> #include <cpu.h>
#include <bus.h> #include <bus.h>
#include <common.h>
cpu_context ctx = {0}; cpu_context ctx = {0};
void cpu_init() { void cpu_init() {
ctx.regs.pc = 0x100; ctx.regs.pc = 0x100;
ctx.regs.a = 0x01;
} }
static void fetch_instruction() { static void fetch_instruction() {
@ -13,42 +13,11 @@ static void fetch_instruction() {
ctx.cur_inst = instruction_by_opcode(ctx.cur_opcode); ctx.cur_inst = instruction_by_opcode(ctx.cur_opcode);
} }
static void fetch_data() {
ctx.mem_dest = 0;
ctx.dest_is_mem = false;
if(ctx.cur_inst == NULL) return;
switch(ctx.cur_inst->mode) {
case AM_IMP: return;
case AM_R:
ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_1);
return;
case AM_R_D8:
ctx.fetched_data = bus_read(ctx.regs.pc);
emu_cycles(1);
ctx.regs.pc++;
return;
case AM_D16: {
u16 lo = bus_read(ctx.regs.pc);
emu_cycles(1);
u16 hi = bus_read(ctx.regs.pc+1);
emu_cycles(1);
ctx.fetched_data = lo | (hi << 8);
ctx.regs.pc += 2;
return;
}
default:
printf("Unknown Addressing Mode! %d (%02X)\n", ctx.cur_inst->mode, ctx.cur_opcode);
exit(-7);
return;
}
}
static void execute() { static void execute() {
IN_PROC proc = inst_get_processor(ctx.cur_inst->type); IN_PROC proc = inst_get_processor(ctx.cur_inst->type);
if (!proc) { if (!proc) {
printf("no implementation(%02X)\n", ctx.cur_opcode);
NO_IMPL NO_IMPL
} }
@ -60,14 +29,22 @@ bool cpu_step() {
if(!ctx.halted) { if(!ctx.halted) {
u16 pc = ctx.regs.pc; u16 pc = ctx.regs.pc;
fetch_instruction(); fetch_instruction();
fetch_data(); printf("%04X: %-7s (%02X %02X %02X) AF: %02X%02X BC: %02X%02X DE: %02X%02X HL: %02X%02X SP: %04X PC: %04X\n", pc, inst_name(ctx.cur_inst->type), ctx.cur_opcode, bus_read(pc+1), bus_read(pc+2), ctx.regs.a, ctx.regs.f, ctx.regs.b, ctx.regs.c, ctx.regs.d, ctx.regs.e, ctx.regs.h, ctx.regs.l, ctx.regs.sp, ctx.regs.pc);
printf("%04X: %-7s (%02X %02X %02X) A: %02X B: %02X C: %02X\n", pc, inst_name(ctx.cur_inst->type), ctx.cur_opcode, bus_read(pc+1), bus_read(pc+2), ctx.regs.a, ctx.regs.b, ctx.regs.c);
if(ctx.cur_inst == NULL){ if(ctx.cur_inst == NULL){
printf("Unknown Instruction! %02X\n", ctx.cur_opcode); printf("Unknown Instruction! %02X\n", ctx.cur_opcode);
exit(-7); exit(-7);
} }
fetch_data();
execute(); execute();
} }
return true; return true;
}
u8 cpu_get_ie_register(){
return ctx.ie_register;
}
void cpu_set_ie_register(u8 ie){
ctx.ie_register = ie;
} }

137
lib/cpu_fetch.c Normal file
View File

@ -0,0 +1,137 @@
#include <cpu.h>
#include <bus.h>
#include <emu.h>
extern cpu_context ctx;
void fetch_data() {
ctx.mem_dest = 0;
ctx.dest_is_mem = false;
if(ctx.cur_inst == NULL) return;
switch(ctx.cur_inst->mode) {
case AM_IMP: return;
case AM_R:
ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_1);
return;
case AM_R_R:
ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_2);
case AM_R_D8:
ctx.fetched_data = bus_read(ctx.regs.pc);
emu_cycles(1);
ctx.regs.pc++;
return;
case AM_R_D16:
case AM_D16: {
u16 lo = bus_read(ctx.regs.pc);
emu_cycles(1);
u16 hi = bus_read(ctx.regs.pc+1);
emu_cycles(1);
ctx.fetched_data = lo | (hi << 8);
ctx.regs.pc += 2;
return;
}
case AM_MR_R:
ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_2);
ctx.mem_dest = cpu_read_reg(ctx.cur_inst->reg_1);
ctx.dest_is_mem = true;
if (ctx.cur_inst->reg_1 == RT_C) {
ctx.mem_dest |= 0xFF00;
}
return;
case AM_R_MR: {
u16 addr = cpu_read_reg(ctx.cur_inst->reg_2);
if(ctx.cur_inst->reg_1 == RT_C) {
addr |= 0xFF00;
}
ctx.fetched_data = bus_read(addr);
emu_cycles(1);
return;
}
case AM_R_HLI:
ctx.fetched_data = bus_read(cpu_read_reg(ctx.cur_inst->reg_2));
emu_cycles(1);
cpu_set_reg(RT_HL, cpu_read_reg(RT_HL)+1);
return;
case AM_R_HLD:
ctx.fetched_data = bus_read(cpu_read_reg(ctx.cur_inst->reg_2));
emu_cycles(1);
cpu_set_reg(RT_HL, cpu_read_reg(RT_HL)-1);
return;
case AM_HLI_R:
ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_2);
ctx.mem_dest = bus_read(cpu_read_reg(ctx.cur_inst->reg_1));
ctx.dest_is_mem = true;
cpu_set_reg(RT_HL, cpu_read_reg(RT_HL)+1);
return;
case AM_HLD_R:
ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_2);
ctx.mem_dest = cpu_read_reg(ctx.cur_inst->reg_1);
ctx.dest_is_mem = true;
cpu_set_reg(RT_HL, cpu_read_reg(RT_HL)-1);
return;
case AM_R_A8:
ctx.fetched_data = bus_read(bus_read(ctx.regs.pc));
emu_cycles(2);
ctx.regs.pc++;
return;
case AM_A8_R:
ctx.mem_dest = bus_read(ctx.regs.pc) | 0xFF00;
emu_cycles(1);
ctx.dest_is_mem = true;
ctx.regs.pc++;
return;
case AM_HL_SPR:
ctx.fetched_data = bus_read(ctx.regs.pc);
emu_cycles(1);
ctx.regs.pc++;
return;
case AM_D8:
ctx.fetched_data = bus_read(ctx.regs.pc);
emu_cycles(1);
ctx.regs.pc++;
return;
case AM_A16_R:
case AM_D16_R: {
u16 lo = bus_read(ctx.regs.pc);
emu_cycles(1);
u16 hi = bus_read(ctx.regs.pc+1);
emu_cycles(1);
ctx.mem_dest = lo | (hi << 8);
ctx.dest_is_mem = true;
ctx.regs.pc += 2;
ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_2);
} return;
case AM_MR_D8:
ctx.fetched_data = bus_read(ctx.regs.pc);
emu_cycles(1);
ctx.regs.pc++;
ctx.mem_dest = cpu_read_reg(ctx.cur_inst->reg_1);
ctx.dest_is_mem = true;
return;
case AM_MR:
ctx.mem_dest = cpu_read_reg(ctx.cur_inst->reg_1);
ctx.dest_is_mem = true;
ctx.fetched_data = bus_read(cpu_read_reg(ctx.cur_inst->reg_1));
emu_cycles(1);
return;
case AM_R_A16: {
u16 lo = bus_read(ctx.regs.pc);
emu_cycles(1);
u16 hi = bus_read(ctx.regs.pc+1);
emu_cycles(1);
ctx.fetched_data = bus_read(lo | (hi << 8));
emu_cycles(1);
ctx.regs.pc += 2;
} return;
default:
printf("Unknown Addressing Mode! %d (%02X)\n", ctx.cur_inst->mode, ctx.cur_opcode);
exit(-7);
return;
}
}

View File

@ -1,17 +1,9 @@
#include <cpu.h> #include <cpu.h>
#include <emu.h> #include <emu.h>
#include <bus.h>
//process CPU instructions... //process CPU instructions...
static void proc_none(cpu_context *ctx) {
printf("INVALID INSTRUCTION!\n");
exit(-7);
}
static void proc_nop(cpu_context *ctx) {
}
void cpu_set_flags(cpu_context *ctx, u8 z, u8 n, u8 h, u8 c){ void cpu_set_flags(cpu_context *ctx, u8 z, u8 n, u8 h, u8 c){
if (z != -1){ if (z != -1){
BIT_SET(ctx->regs.f, 7, z) BIT_SET(ctx->regs.f, 7, z)
@ -27,6 +19,24 @@ void cpu_set_flags(cpu_context *ctx, u8 z, u8 n, u8 h, u8 c){
} }
} }
static void proc_none(cpu_context *ctx) {
printf("INVALID INSTRUCTION!\n");
exit(-7);
}
static void proc_nop(cpu_context *ctx) {
}
static void proc_ldh(cpu_context *ctx) {
if (!ctx->dest_is_mem) {
cpu_set_reg(ctx->cur_inst->reg_1, bus_read(0XFF00 | ctx->fetched_data));
} else {
bus_write(0xFF00 | ctx->mem_dest, ctx->cur_inst->reg_2);
}
emu_cycles(1);
}
static void proc_xor(cpu_context *ctx) { static void proc_xor(cpu_context *ctx) {
ctx->regs.a ^= ctx->fetched_data & 0XFF; ctx->regs.a ^= ctx->fetched_data & 0XFF;
cpu_set_flags(ctx, ctx->regs.a == 0, 0, 0, 0); cpu_set_flags(ctx, ctx->regs.a == 0, 0, 0, 0);
@ -37,7 +47,25 @@ static void proc_di(cpu_context *ctx) {
} }
static void proc_ld(cpu_context *ctx) { static void proc_ld(cpu_context *ctx) {
//TODO if(ctx->dest_is_mem) {
if(ctx->cur_inst->reg_2 >= RT_AF) {
bus_write16(ctx->mem_dest, ctx->fetched_data);
emu_cycles(1);
} else {
bus_write(ctx->mem_dest, ctx->fetched_data);
emu_cycles(1);
}
return;
}
if (ctx->cur_inst->mode == AM_HL_SPR) {
u8 hflag = (cpu_read_reg(ctx->cur_inst->reg_2) & 0xF) + (ctx->fetched_data & 0xF) >= 0x10;
u8 cflag = (cpu_read_reg(ctx->cur_inst->reg_2) & 0xFF) + (ctx->fetched_data & 0xFF) >= 0x100;
cpu_set_flags(ctx, 0, 0, hflag, cflag);
cpu_set_reg(ctx->cur_inst->reg_1, cpu_read_reg(ctx->cur_inst->reg_2) + (char)ctx->fetched_data);
}
cpu_set_reg(ctx->cur_inst->reg_1, ctx->fetched_data);
} }
static bool check_condition(cpu_context *ctx) { static bool check_condition(cpu_context *ctx) {
@ -68,7 +96,8 @@ IN_PROC processors[] = {
[IN_LD] = proc_ld, [IN_LD] = proc_ld,
[IN_JP] = proc_jp, [IN_JP] = proc_jp,
[IN_DI] = proc_di, [IN_DI] = proc_di,
[IN_XOR] = proc_xor [IN_XOR] = proc_xor,
[IN_LDH] = proc_ldh
}; };
IN_PROC inst_get_processor(in_type type) { IN_PROC inst_get_processor(in_type type) {

View File

@ -26,4 +26,26 @@ u16 cpu_read_reg(reg_type rt) {
case RT_SP: return ctx.regs.sp; case RT_SP: return ctx.regs.sp;
default: return 0; default: return 0;
} }
}
void cpu_set_reg(reg_type rt, u16 val) {
switch(rt) {
case RT_A: ctx.regs.a = val & 0XFF; break;
case RT_F: ctx.regs.f = val & 0XFF; break;
case RT_B: ctx.regs.b = val & 0XFF; break;
case RT_C: ctx.regs.c = val & 0XFF; break;
case RT_D: ctx.regs.d = val & 0XFF; break;
case RT_E: ctx.regs.e = val & 0XFF; break;
case RT_H: ctx.regs.h = val & 0XFF; break;
case RT_L: ctx.regs.l = val & 0XFF; break;
case RT_AF: *((u16 *)&ctx.regs.a) = reverse(val); break;
case RT_BC: *((u16 *)&ctx.regs.b) = reverse(val); break;
case RT_DE: *((u16 *)&ctx.regs.d) = reverse(val); break;
case RT_HL: *((u16 *)&ctx.regs.h) = reverse(val); break;
case RT_PC: ctx.regs.pc = val; break;
case RT_SP: ctx.regs.sp = val; break;
case RT_NONE: break;
}
} }

View File

@ -2,17 +2,121 @@
#include <cpu.h> #include <cpu.h>
instruction instructions[0x100] = { instruction instructions[0x100] = {
//0x0X
[0x00] = {IN_NOP, AM_IMP}, [0x00] = {IN_NOP, AM_IMP},
[0x01] = {IN_LD, AM_R_D16, RT_BC},
[0x02] = {IN_LD, AM_MR_R, RT_BC, RT_A},
[0x05] = {IN_DEC, AM_R, RT_B}, [0x05] = {IN_DEC, AM_R, RT_B},
[0x06] = {IN_LD, AM_R_D8, RT_B},
[0x08] = {IN_LD, AM_A16_R, RT_NONE, RT_SP},
[0x0A] = {IN_LD, AM_R_MR, RT_A, RT_BC},
[0x0E] = {IN_LD, AM_R_D8, RT_C}, [0x0E] = {IN_LD, AM_R_D8, RT_C},
//0x1X
[0x11] = {IN_LD, AM_R_D16, RT_DE},
[0x12] = {IN_LD, AM_MR_R, RT_DE, RT_A},
[0x15] = {IN_DEC, AM_R, RT_D},
[0x16] = {IN_LD, AM_R_D8, RT_D},
[0x1A] = {IN_LD, AM_R_MR, RT_A, RT_DE},
[0x1E] = {IN_LD, AM_R_D8, RT_E},
//0x2X
[0x21] = {IN_LD, AM_R_D16, RT_HL},
[0x22] = {IN_LD, AM_HLI_R, RT_HL, RT_A},
[0x25] = {IN_DEC, AM_R, RT_H},
[0x26] = {IN_LD, AM_R_D8, RT_H},
[0x2A] = {IN_LD, AM_R_HLI, RT_A, RT_HL},
[0x2E] = {IN_LD, AM_R_D8, RT_L},
//0x3X
[0x31] = {IN_LD, AM_R_D16, RT_SP},
[0x32] = {IN_LD, AM_HLD_R, RT_HL, RT_A},
[0x35] = {IN_DEC, AM_MR, RT_HL},
[0x36] = {IN_LD, AM_MR_D8, RT_HL},
[0x3A] = {IN_LD, AM_R_HLD, RT_A, RT_HL},
[0x3E] = {IN_LD, AM_R_D8, RT_A},
//0x4X
[0x40] = {IN_LD, AM_R_R, RT_B, RT_B},
[0x41] = {IN_LD, AM_R_R, RT_B, RT_C},
[0x42] = {IN_LD, AM_R_R, RT_B, RT_D},
[0x43] = {IN_LD, AM_R_R, RT_B, RT_E},
[0x44] = {IN_LD, AM_R_R, RT_B, RT_H},
[0x45] = {IN_LD, AM_R_R, RT_B, RT_L},
[0x46] = {IN_LD, AM_R_MR, RT_B, RT_HL},
[0x47] = {IN_LD, AM_R_R, RT_B, RT_A},
[0x48] = {IN_LD, AM_R_R, RT_C, RT_B},
[0x49] = {IN_LD, AM_R_R, RT_C, RT_C},
[0x4A] = {IN_LD, AM_R_R, RT_C, RT_D},
[0x4B] = {IN_LD, AM_R_R, RT_C, RT_E},
[0x4C] = {IN_LD, AM_R_R, RT_C, RT_H},
[0x4D] = {IN_LD, AM_R_R, RT_C, RT_L},
[0x4E] = {IN_LD, AM_R_MR, RT_C, RT_HL},
[0x4F] = {IN_LD, AM_R_R, RT_C, RT_A},
//0x5X
[0x50] = {IN_LD, AM_R_R, RT_D, RT_B},
[0x51] = {IN_LD, AM_R_R, RT_D, RT_C},
[0x52] = {IN_LD, AM_R_R, RT_D, RT_D},
[0x53] = {IN_LD, AM_R_R, RT_D, RT_E},
[0x54] = {IN_LD, AM_R_R, RT_D, RT_H},
[0x55] = {IN_LD, AM_R_R, RT_D, RT_L},
[0x56] = {IN_LD, AM_R_MR, RT_D, RT_HL},
[0x57] = {IN_LD, AM_R_R, RT_D, RT_A},
[0x58] = {IN_LD, AM_R_R, RT_E, RT_B},
[0x59] = {IN_LD, AM_R_R, RT_E, RT_C},
[0x5A] = {IN_LD, AM_R_R, RT_E, RT_D},
[0x5B] = {IN_LD, AM_R_R, RT_E, RT_E},
[0x5C] = {IN_LD, AM_R_R, RT_E, RT_H},
[0x5D] = {IN_LD, AM_R_R, RT_E, RT_L},
[0x5E] = {IN_LD, AM_R_MR, RT_E, RT_HL},
[0x5F] = {IN_LD, AM_R_R, RT_E, RT_A},
//0x6X
[0x60] = {IN_LD, AM_R_R, RT_H, RT_B},
[0x61] = {IN_LD, AM_R_R, RT_H, RT_C},
[0x62] = {IN_LD, AM_R_R, RT_H, RT_D},
[0x63] = {IN_LD, AM_R_R, RT_H, RT_E},
[0x64] = {IN_LD, AM_R_R, RT_H, RT_H},
[0x65] = {IN_LD, AM_R_R, RT_H, RT_L},
[0x66] = {IN_LD, AM_R_MR, RT_H, RT_HL},
[0x67] = {IN_LD, AM_R_R, RT_H, RT_A},
[0x68] = {IN_LD, AM_R_R, RT_L, RT_B},
[0x69] = {IN_LD, AM_R_R, RT_L, RT_C},
[0x6A] = {IN_LD, AM_R_R, RT_L, RT_D},
[0x6B] = {IN_LD, AM_R_R, RT_L, RT_E},
[0x6C] = {IN_LD, AM_R_R, RT_L, RT_H},
[0x6D] = {IN_LD, AM_R_R, RT_L, RT_L},
[0x6E] = {IN_LD, AM_R_MR, RT_L, RT_HL},
[0x6F] = {IN_LD, AM_R_R, RT_L, RT_A},
//0x7X
[0x70] = {IN_LD, AM_MR_R, RT_HL, RT_B},
[0x71] = {IN_LD, AM_MR_R, RT_HL, RT_C},
[0x72] = {IN_LD, AM_MR_R, RT_HL, RT_D},
[0x73] = {IN_LD, AM_MR_R, RT_HL, RT_E},
[0x74] = {IN_LD, AM_MR_R, RT_HL, RT_H},
[0x75] = {IN_LD, AM_MR_R, RT_HL, RT_L},
[0x76] = {IN_HALT},
[0x77] = {IN_LD, AM_MR_R, RT_HL, RT_A},
[0x78] = {IN_LD, AM_R_R, RT_A, RT_B},
[0x79] = {IN_LD, AM_R_R, RT_A, RT_C},
[0x7A] = {IN_LD, AM_R_R, RT_A, RT_D},
[0x7B] = {IN_LD, AM_R_R, RT_A, RT_E},
[0x7C] = {IN_LD, AM_R_R, RT_A, RT_H},
[0x7D] = {IN_LD, AM_R_R, RT_A, RT_L},
[0x7E] = {IN_LD, AM_R_MR, RT_A, RT_HL},
[0x7F] = {IN_LD, AM_R_R, RT_A, RT_A},
//0x8X
//0x9X
//0xAX
[0xAF] = {IN_XOR, AM_R, RT_A}, [0xAF] = {IN_XOR, AM_R, RT_A},
//0xBX
//0xCX
[0xC3] = {IN_JP, AM_D16}, [0xC3] = {IN_JP, AM_D16},
//0xDX
//0xEX
[0xE0] = {IN_LDH, AM_A8_R, RT_NONE, RT_A},
[0xE2] = {IN_LD, AM_MR_R, RT_C, RT_A},
[0xEA] = {IN_LD, AM_A16_R, RT_NONE, RT_A},
//0xFX
[0xF0] = {IN_LDH, AM_R_A8, RT_A},
[0xF2] = {IN_LD, AM_R_MR, RT_A, RT_C},
[0xF3] = {IN_DI}, [0xF3] = {IN_DI},
[0xFA] = {IN_LD, AM_R_A16, RT_A},
}; };
instruction *instruction_by_opcode(u8 opcode) { instruction *instruction_by_opcode(u8 opcode) {

30
lib/ram.c Normal file
View File

@ -0,0 +1,30 @@
#include <ram.h>
typedef struct {
u8 wram[0x2000];
u8 hram[0x80];
} ram_context;
static ram_context ctx;
u8 wram_read(u16 address) {
address -= 0xC000;
return ctx.wram[address];
}
void wram_write(u16 address, u8 value){
address -= 0xC000;
ctx.wram[address] = value;
}
u8 hram_read(u16 address){
address -= 0xFF80;
return ctx.hram[address];
}
void hram_write(u16 address, u8 value){
address -= 0xFF80;
ctx.hram[address] = value;
}