LD, LDH, WRAM, and HRAM
This commit is contained in:
parent
1bf98447a3
commit
022c24dd35
@ -3,4 +3,7 @@
|
||||
#include <common.h>
|
||||
|
||||
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);
|
@ -30,6 +30,7 @@ typedef struct {
|
||||
bool stepping;
|
||||
|
||||
bool int_master_enabled;
|
||||
u8 ie_register;
|
||||
} cpu_context;
|
||||
|
||||
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_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
9
include/ram.h
Normal 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);
|
86
lib/bus.c
86
lib/bus.c
@ -1,4 +1,8 @@
|
||||
#include <bus.h>
|
||||
#include <common.h>
|
||||
#include <cart.h>
|
||||
#include <cpu.h>
|
||||
#include <ram.h>
|
||||
|
||||
// 0x0000 - 0x3FFF : ROM Bank 0
|
||||
// 0x4000 - 0x7FFF : ROM Bank 1 - Switchable
|
||||
@ -17,16 +21,92 @@
|
||||
u8 bus_read(u16 address) {
|
||||
if(address < 0x8000) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#include <cart.h>
|
||||
#include <common.h>
|
||||
|
||||
typedef struct {
|
||||
char filename[1024];
|
||||
@ -182,6 +183,6 @@ u8 cart_read(u16 address){
|
||||
}
|
||||
|
||||
void cart_write(u16 address, u8 value){
|
||||
|
||||
NO_IMPL
|
||||
printf("UNSUPPORTED cart_write(%04X)\n");
|
||||
//NO_IMPL
|
||||
}
|
47
lib/cpu.c
47
lib/cpu.c
@ -1,11 +1,11 @@
|
||||
#include <cpu.h>
|
||||
#include <bus.h>
|
||||
#include <common.h>
|
||||
|
||||
cpu_context ctx = {0};
|
||||
|
||||
void cpu_init() {
|
||||
ctx.regs.pc = 0x100;
|
||||
ctx.regs.a = 0x01;
|
||||
}
|
||||
|
||||
static void fetch_instruction() {
|
||||
@ -13,42 +13,11 @@ static void fetch_instruction() {
|
||||
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() {
|
||||
IN_PROC proc = inst_get_processor(ctx.cur_inst->type);
|
||||
|
||||
if (!proc) {
|
||||
printf("no implementation(%02X)\n", ctx.cur_opcode);
|
||||
NO_IMPL
|
||||
}
|
||||
|
||||
@ -60,14 +29,22 @@ bool cpu_step() {
|
||||
if(!ctx.halted) {
|
||||
u16 pc = ctx.regs.pc;
|
||||
fetch_instruction();
|
||||
fetch_data();
|
||||
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);
|
||||
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);
|
||||
if(ctx.cur_inst == NULL){
|
||||
printf("Unknown Instruction! %02X\n", ctx.cur_opcode);
|
||||
exit(-7);
|
||||
}
|
||||
fetch_data();
|
||||
execute();
|
||||
}
|
||||
|
||||
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
137
lib/cpu_fetch.c
Normal 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;
|
||||
}
|
||||
}
|
@ -1,17 +1,9 @@
|
||||
#include <cpu.h>
|
||||
#include <emu.h>
|
||||
#include <bus.h>
|
||||
|
||||
//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){
|
||||
if (z != -1){
|
||||
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) {
|
||||
ctx->regs.a ^= ctx->fetched_data & 0XFF;
|
||||
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) {
|
||||
//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) {
|
||||
@ -68,7 +96,8 @@ IN_PROC processors[] = {
|
||||
[IN_LD] = proc_ld,
|
||||
[IN_JP] = proc_jp,
|
||||
[IN_DI] = proc_di,
|
||||
[IN_XOR] = proc_xor
|
||||
[IN_XOR] = proc_xor,
|
||||
[IN_LDH] = proc_ldh
|
||||
};
|
||||
|
||||
IN_PROC inst_get_processor(in_type type) {
|
||||
|
@ -26,4 +26,26 @@ u16 cpu_read_reg(reg_type rt) {
|
||||
case RT_SP: return ctx.regs.sp;
|
||||
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;
|
||||
}
|
||||
}
|
@ -2,17 +2,121 @@
|
||||
#include <cpu.h>
|
||||
|
||||
instruction instructions[0x100] = {
|
||||
//0x0X
|
||||
[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},
|
||||
|
||||
[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},
|
||||
|
||||
//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},
|
||||
|
||||
//0xBX
|
||||
//0xCX
|
||||
[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},
|
||||
[0xFA] = {IN_LD, AM_R_A16, RT_A},
|
||||
};
|
||||
|
||||
instruction *instruction_by_opcode(u8 opcode) {
|
||||
|
30
lib/ram.c
Normal file
30
lib/ram.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user