diff --git a/src/apps/gbdb.c b/src/apps/gbdb.c index 6693b69..e4400b5 100644 --- a/src/apps/gbdb.c +++ b/src/apps/gbdb.c @@ -20,8 +20,6 @@ #define INPUT_MAX_LEN 512 #define MAX_BREAKPTS 16 /* Should be plenty for anyone */ -#define MAX_RAM_LEN (1 << 20) /* Up to 8Mb Cartridge */ -#define UNMAP_BOOTROM_ADDR 0xff50 typedef void (gbdb_cmd)(char *arg_string); @@ -29,7 +27,6 @@ static void breakpoint_addr_hit(uint16_t id); static void breakpoint_cb(struct lr35902_state *lr); static void reset_breakpoints(void); -static uint8_t ram[MAX_RAM_LEN]; static const char prompt[] = "gbdb >"; static const char usage[] = "Available commands:\n" @@ -44,11 +41,7 @@ static const char usage[] = static struct lr35902_ops cpu_ops; static struct lr35902_state cpu; static struct gb_video video; - -static unsigned char bootrom[0x100] = {0}; -static unsigned char cart_low[0x100] = {0}; - -static int bootrom_mapped = 1; +static void *memory = NULL; static int paused_breakpoint = 0; static volatile sig_atomic_t paused_signal = 0; @@ -90,76 +83,13 @@ static void strip_newline(char *string) } } -/* - * ram_{read,write} work easily because the cartridge is mapped to 0x0000 - * - */ -static uint8_t mem_read(struct lr35902_state *cpu, uint16_t addr) -{ - - switch (addr) { - case 0xFF40 ... 0xFF4B: - return gb_video_mem_read(&video, addr); - default: - return ram[addr]; - } -} - -static void mem_write(struct lr35902_state *cpu, uint16_t addr, uint8_t val) -{ - - switch (addr) { - case UNMAP_BOOTROM_ADDR: - if (val == 1) { - bootrom_mapped = 0; - memcpy(ram, cart_low, sizeof(cart_low)); - gb_log("bootrom unmapped\n"); - } - break; - case 0xFF40 ... 0xFF4B: - gb_video_mem_write(&video, addr, val); - break; - case 0 ... 0x100: - if (bootrom_mapped) { - break; - } - /* Intentional fall-through */ - default: - ram[addr] = val; - } - -} - -static void mem_dump(char *filename) -{ - //TODO: Check error codes like a real programmer :P - FILE* dump_file; - char *token = strtok(filename, " "); - - if (token == NULL) { - gb_log("usage: load \n"); - return; - } - strip_newline(token); - dump_file = fopen(token, "w"); - if(dump_file == NULL) { - gb_log("Failed to open mem dump file: %d\n", errno); - return; - } - fwrite(ram, MAX_RAM_LEN, 1, dump_file); - fclose(dump_file); -} - static void init(void) { - cpu_ops.mem_read = mem_read; - cpu_ops.mem_write = mem_write; cpu_ops.undef_d3 = breakpoint_cb; - lr35902_init(&cpu, &cpu_ops); + lr35902_init(&cpu, memory, &cpu_ops); gb_video_init(&video); - memset(&ram, 0, MAX_RAM_LEN); - bootrom_mapped = 1; + gb_mem_init(memory, &video); } static void cycle() @@ -255,7 +185,7 @@ static void regs(char *arg_list) static void peek(char *arg_list) { uint16_t pc = lr35902_get_reg_16(&cpu, LR35902_REG_PC); - uint8_t byte = mem_read(&cpu, pc); + uint8_t byte = gb_mem_read(memory, pc); printf("0x%04x:%s\n", pc, gb_byte_to_opcode(byte)); } @@ -400,7 +330,7 @@ static void mem(char *arg_list) for (i = 0; i < bytes; i++) { //TODO: Make sure this has no side effects - int val = mem_read(&cpu, addr + i); + uint8_t val = gb_mem_read(memory, addr + i); if (token != NULL && token[0] == 'i') { printf("0x%04x:%s\n", addr + i, gb_byte_to_opcode(val)); @@ -413,29 +343,6 @@ static void mem(char *arg_list) } -static void load_file_to_buffer(char *filename, uint8_t *buffer, size_t size) -{ - //TODO: Check error codes like a real programmer :P - FILE* prog_file; - long filesize; - - prog_file = fopen(filename, "r"); - if(prog_file < 0) { - printf("Failed to load game file: %d\n", errno); - return; - } - - fseek(prog_file, 0, SEEK_END); - filesize = ftell(prog_file); - fseek(prog_file, 0, SEEK_SET); - - if (fread(buffer, MIN(filesize, size), 1, prog_file) < 0) { - printf("Failed to read filed: %d\n", errno); - } - fclose(prog_file); - -} - static void load(char *arg_list) { char *token = strtok(arg_list, " "); @@ -445,9 +352,8 @@ static void load(char *arg_list) } strip_newline(token); - load_file_to_buffer(token, ram, sizeof(ram)); - load_file_to_buffer(token, cart_low, sizeof(cart_low)); + gb_memory_load_file(memory, GB_MEMORY_CART, token); } static void load_bootrom(char *arg_list) @@ -459,8 +365,8 @@ static void load_bootrom(char *arg_list) } strip_newline(token); - load_file_to_buffer(token, bootrom, sizeof(bootrom)); - load_file_to_buffer(token, ram, sizeof(bootrom)); + + gb_memory_load_file(memory, GB_MEMORY_BOOTROM, token); } @@ -469,7 +375,7 @@ static void quit(char *arg_list) exit(0); } -static void do_run(void) { +static __attribute__((hot)) void do_run(void) { paused = 0; signal(SIGINT, break_execution_handler); @@ -501,7 +407,6 @@ static struct breakpoint { int id; bool temp; uint8_t op; - uint8_t *ptr; } breakpoints[MAX_BREAKPTS]; static int num_breakpoints = 0; @@ -525,7 +430,7 @@ static void reset_breakpoints(void) for (i = 0; i < num_breakpoints; i++) { struct breakpoint *bkpt = &breakpoints[i]; - *bkpt->ptr = 0xd3; + gb_mem_force_write(memory, bkpt->addr, 0xd3); } } @@ -535,15 +440,10 @@ static int do_set_breakpoint(uint16_t addr, bool temp) if (num_breakpoints < ARRAY_SIZE(breakpoints)) { breakpoints[num_breakpoints].addr = addr; - breakpoints[num_breakpoints].op = mem_read(NULL, addr); - if (bootrom_mapped && addr < 0x100) { - breakpoints[num_breakpoints].ptr = &bootrom[addr]; - } else { - breakpoints[num_breakpoints].ptr = &ram[addr]; - } - *breakpoints[num_breakpoints].ptr = 0xd3; + breakpoints[num_breakpoints].op = gb_mem_read(memory, addr); breakpoints[num_breakpoints].id = id++; breakpoints[num_breakpoints].temp = temp; + gb_mem_force_write(memory, addr, 0xd3); num_breakpoints++; } else { printf("maximum number of breakpoints reached\n"); @@ -593,8 +493,8 @@ static int do_delete_breakpoint(int id) return -1; } - *bkpt->ptr = bkpt->op; - + gb_mem_force_write(memory, bkpt->addr, bkpt->op); + index = bkpt - breakpoints; memmove(&breakpoints[index], &breakpoints[index + 1], num_breakpoints - index - 1); @@ -816,7 +716,8 @@ int main(int argc, char **argv) tri_add_string(&commands, "load", load); tri_add_string(&commands, "bootrom", load_bootrom); tri_add_string(&commands, "mem", mem); - tri_add_string(&commands, "dump", mem_dump); + /* FIXME */ + /* tri_add_string(&commands, "dump", mem_dump); */ tri_add_string(&commands, "peek", peek); tri_add_string(&commands, "help", help); tri_add_string(&commands, "?", help); diff --git a/src/gbemu/cpu.c b/src/gbemu/cpu.c index b4d2146..0ecf396 100644 --- a/src/gbemu/cpu.c +++ b/src/gbemu/cpu.c @@ -72,12 +72,13 @@ void lr35902_set_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg, } void lr35902_init(struct lr35902_state *cpu, + struct gb_memory *memory, const struct lr35902_ops *ops) { int i; - cpu->mem_read = ops->mem_read; - cpu->mem_write = ops->mem_write; + cpu->memory = memory; + cpu->undef_d3 = ops->undef_d3; cpu->int_state = LR35902_INT_OFF; @@ -141,15 +142,15 @@ static const unsigned int cb_extra_cycles[256] = { 0 }; (cpu)->zf = (reg) == 0; \ } while (0) -#define LD_D8(cpu, reg) \ - do { \ - (reg) = (cpu)->mem_read((cpu), (cpu)->pc++); \ +#define LD_D8(cpu, reg) \ + do { \ + (reg) = gb_mem_read((cpu)->memory, (cpu)->pc++); \ } while (0) #define LD_D16(cpu, reg) \ do { \ - (reg) = (cpu)->mem_read((cpu), (cpu)->pc++); \ - (reg) |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->pc++) << 8; \ + (reg) = gb_mem_read((cpu)->memory, (cpu)->pc++); \ + (reg) |= (uint16_t) gb_mem_read((cpu)->memory, (cpu)->pc++) << 8; \ } while (0) #define ADD_8(cpu, dst, src) \ @@ -248,49 +249,49 @@ static const unsigned int cb_extra_cycles[256] = { 0 }; (cpu)->zf = ((_tmp) == 0); \ } while (0) -#define JR_8(cpu) \ - do { \ - val_16 = cpu->mem_read(cpu, cpu->pc++); \ - /* sign-extend */ \ - val_16 |= GET_BIT(val_16, 7) ? 0xff00 : 0; \ - cpu->pc += val_16; \ +#define JR_8(cpu) \ + do { \ + val_16 = gb_mem_read((cpu)->memory, cpu->pc++); \ + /* sign-extend */ \ + val_16 |= GET_BIT(val_16, 7) ? 0xff00 : 0; \ + cpu->pc += val_16; \ } while (0) /* TODO: In general, check that we pop/push things correctly */ #define POP_16(cpu, dst) \ do { \ - (dst) = (cpu)->mem_read((cpu), (cpu)->sp++); \ - (dst) |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->sp++) << 8; \ + (dst) = gb_mem_read((cpu)->memory, (cpu)->sp++); \ + (dst) |= (uint16_t) gb_mem_read((cpu)->memory, (cpu)->sp++) << 8; \ } while (0) #define PUSH_16(cpu, src) \ do { \ - (cpu)->mem_write(cpu, --cpu->sp, src); \ - (cpu)->mem_write(cpu, --cpu->sp, src >> 8); \ + gb_mem_write(cpu->memory, --cpu->sp, src); \ + gb_mem_write(cpu->memory, --cpu->sp, src >> 8); \ } while (0) #define CALL(cpu) \ do { \ uint16_t pc_base; \ - cpu->mem_write(cpu, --cpu->sp, cpu->pc); \ - cpu->mem_write(cpu, --cpu->sp, cpu->pc >> 8); \ - pc_base = cpu->mem_read(cpu, cpu->pc++); \ - pc_base |= (uint16_t) cpu->mem_read(cpu, cpu->pc) << 8; \ + gb_mem_write(cpu->memory, --cpu->sp, cpu->pc); \ + gb_mem_write(cpu->memory, --cpu->sp, cpu->pc >> 8); \ + pc_base = gb_mem_read(cpu->memory, cpu->pc++); \ + pc_base |= (uint16_t) gb_mem_read(cpu->memory, cpu->pc) << 8; \ cpu->pc = pc_base; \ } while (0) #define RET(cpu) \ do { \ (cpu)->pc = 0; \ - (cpu)->pc |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->sp++) << 8; \ - (cpu)->pc |= (cpu)->mem_read((cpu), (cpu)->sp++); \ + (cpu)->pc |= (uint16_t) gb_mem_read((cpu)->memory, (cpu)->sp++) << 8; \ + (cpu)->pc |= gb_mem_read((cpu)->memory, (cpu)->sp++); \ (cpu)->pc += 2; \ } while (0) #define RST(cpu, n) \ do { \ - (cpu)->mem_write((cpu), (cpu)->sp++, (cpu)->pc >> 8); \ - (cpu)->mem_write((cpu), (cpu)->sp++, (cpu)->pc); \ + gb_mem_write((cpu)->memory, (cpu)->sp++, (cpu)->pc >> 8); \ + gb_mem_write((cpu)->memory, (cpu)->sp++, (cpu)->pc); \ (cpu)->pc = (n); \ } while (0) @@ -332,7 +333,7 @@ int lr35902_cycle(struct lr35902_state *cpu) int cycles; cpu->metrics.retired_instrs++; - inst = cpu->mem_read(cpu, cpu->pc++); + inst = gb_mem_read(cpu->memory, cpu->pc++); cycles = op_extra_cycles[inst]; switch (inst) { @@ -342,7 +343,7 @@ int lr35902_cycle(struct lr35902_state *cpu) LD_D16(cpu, cpu->bc); break; case 0x02: /* LD (BC), A */ - cpu->mem_write(cpu, cpu->bc, cpu->a); + gb_mem_write(cpu->memory, cpu->bc, cpu->a); break; case 0x03: /* INC BC */ cpu->bc++; @@ -365,14 +366,14 @@ int lr35902_cycle(struct lr35902_state *cpu) WRITE_BIT(cpu->a, 0, cpu->cf); break; case 0x08: /* LD (a16), SP */ - cpu->sp = cpu->mem_read(cpu, cpu->pc++); - cpu->sp |= cpu->mem_read(cpu, cpu->pc++) << 8; + cpu->sp = gb_mem_read(cpu->memory, cpu->pc++); + cpu->sp |= gb_mem_read(cpu->memory, cpu->pc++) << 8; break; case 0x09: /* ADD HL, BC */ ADD_16(cpu, cpu->hl, cpu->bc); break; case 0x0a: /* LD A, (BC) */ - cpu->a = cpu->mem_read(cpu, cpu->bc); + cpu->a = gb_mem_read(cpu->memory, cpu->bc); break; case 0x0b: /* DEC, BC */ cpu->bc--; @@ -401,7 +402,7 @@ int lr35902_cycle(struct lr35902_state *cpu) LD_D16(cpu, cpu->de); break; case 0x12: /* LD (DE), A */ - cpu->mem_write(cpu, cpu->de, cpu->a); + gb_mem_write(cpu->memory, cpu->de, cpu->a); break; case 0x13: /* INC DE */ cpu->de++; @@ -430,7 +431,7 @@ int lr35902_cycle(struct lr35902_state *cpu) ADD_16(cpu, cpu->hl, cpu->de); break; case 0x1a: /* LD A, (DE) */ - cpu->a = cpu->mem_read(cpu, cpu->de); + cpu->a = gb_mem_read(cpu->memory, cpu->de); break; case 0x1b: /* DEC BC */ cpu->bc--; @@ -463,7 +464,7 @@ int lr35902_cycle(struct lr35902_state *cpu) LD_D16(cpu, cpu->hl); break; case 0x22: /* LD (HL+), A */ - cpu->a = cpu->mem_read(cpu, cpu->hl++); + cpu->a = gb_mem_read(cpu->memory, cpu->hl++); break; case 0x23: /* INC HL */ cpu->hl++; @@ -491,7 +492,7 @@ int lr35902_cycle(struct lr35902_state *cpu) ADD_16(cpu, cpu->hl, cpu->hl); break; case 0x2a: /* LD A, (HL+) */ - cpu->a = cpu->mem_read(cpu, cpu->hl); + cpu->a = gb_mem_read(cpu->memory, cpu->hl); cpu->hl--; break; case 0x2b: /* DEC HL */ @@ -522,30 +523,30 @@ int lr35902_cycle(struct lr35902_state *cpu) LD_D16(cpu, cpu->sp); break; case 0x32: /* LD (HL-), A */ - cpu->mem_write(cpu, cpu->hl--, cpu->a); + gb_mem_write(cpu->memory, cpu->hl--, cpu->a); break; case 0x33: /* INC SP */ cpu->sp++; break; case 0x34: /* INC (HL) */ - val = cpu->mem_read(cpu, cpu->hl); + val = gb_mem_read(cpu->memory, cpu->hl); cpu->nf = 0; cpu->hf = CALC_H_ADD(val, 1); val++; - cpu->mem_write(cpu, cpu->hl, val); + gb_mem_write(cpu->memory, cpu->hl, val); cpu->zf = (val == 0); break; case 0x35: /* DEC (HL) */ - val = cpu->mem_read(cpu, cpu->hl); + val = gb_mem_read(cpu->memory, cpu->hl); cpu->hf = CALC_H_ADD(val, 1); cpu->zf = (val == 0); cpu->nf = 1; val--; - cpu->mem_write(cpu, cpu->hl, val); + gb_mem_write(cpu->memory, cpu->hl, val); break; case 0x36: /* LD (HL), d8 */ - val = cpu->mem_read(cpu, cpu->pc++); - cpu->mem_write(cpu, cpu->hl++, val); + val = gb_mem_read(cpu->memory, cpu->pc++); + gb_mem_write(cpu->memory, cpu->hl++, val); break; case 0x37: /* SCF */ cpu->nf = 0; @@ -563,7 +564,7 @@ int lr35902_cycle(struct lr35902_state *cpu) ADD_16(cpu, cpu->hl, cpu->sp); break; case 0x3a: /* LD A, (HL-) */ - cpu->a = cpu->mem_read(cpu, cpu->hl); + cpu->a = gb_mem_read(cpu->memory, cpu->hl); cpu->hl--; break; case 0x3b: /* DEC SP */ @@ -599,7 +600,7 @@ int lr35902_cycle(struct lr35902_state *cpu) cpu->b = cpu->l; break; case 0x46: /* LD B,(HL) */ - cpu->b = cpu->mem_read(cpu, cpu->hl); + cpu->b = gb_mem_read(cpu->memory, cpu->hl); break; case 0x47: /* LD B,A */ cpu->b = cpu->a; @@ -622,7 +623,7 @@ int lr35902_cycle(struct lr35902_state *cpu) cpu->c = cpu->l; break; case 0x4e: /* LD C,(HL) */ - cpu->c = cpu->mem_read(cpu, cpu->hl); + cpu->c = gb_mem_read(cpu->memory, cpu->hl); break; case 0x4f: /* LD C,A */ cpu->c = cpu->a; @@ -645,7 +646,7 @@ int lr35902_cycle(struct lr35902_state *cpu) cpu->d = cpu->l; break; case 0x56: /* LD D,(HL) */ - cpu->d = cpu->mem_read(cpu, cpu->hl); + cpu->d = gb_mem_read(cpu->memory, cpu->hl); break; case 0x57: /* LD D,A */ cpu->d = cpu->a; @@ -668,7 +669,7 @@ int lr35902_cycle(struct lr35902_state *cpu) cpu->e = cpu->h; break; case 0x5e: /* LD E,(HL) */ - cpu->e = cpu->mem_read(cpu, cpu->hl); + cpu->e = gb_mem_read(cpu->memory, cpu->hl); break; case 0x5f: /* LD E,A */ cpu->e = cpu->a; @@ -691,7 +692,7 @@ int lr35902_cycle(struct lr35902_state *cpu) cpu->h = cpu->l; break; case 0x66: /* LD H,(HL) */ - cpu->h = cpu->mem_read(cpu, cpu->hl); + cpu->h = gb_mem_read(cpu->memory, cpu->hl); break; case 0x67: /* LD H,A */ cpu->h = cpu->a; @@ -714,34 +715,34 @@ int lr35902_cycle(struct lr35902_state *cpu) case 0x6d: /* LD L,L */ break; case 0x6e: /* LD L,(HL) */ - cpu->l = cpu->mem_read(cpu, cpu->hl); + cpu->l = gb_mem_read(cpu->memory, cpu->hl); break; case 0x6f: /* LD L,A */ cpu->l = cpu->a; break; case 0x70: /* LD (HL),B */ - cpu->mem_write(cpu, cpu->hl, cpu->b); + gb_mem_write(cpu->memory, cpu->hl, cpu->b); break; case 0x71: /* LD (HL),C */ - cpu->mem_write(cpu, cpu->hl, cpu->c); + gb_mem_write(cpu->memory, cpu->hl, cpu->c); break; case 0x72: /* LD (HL),D */ - cpu->mem_write(cpu, cpu->hl, cpu->d); + gb_mem_write(cpu->memory, cpu->hl, cpu->d); break; case 0x73: /* LD (HL),E */ - cpu->mem_write(cpu, cpu->hl, cpu->e); + gb_mem_write(cpu->memory, cpu->hl, cpu->e); break; case 0x74: /* LD (HL),H */ - cpu->mem_write(cpu, cpu->hl, cpu->h); + gb_mem_write(cpu->memory, cpu->hl, cpu->h); break; case 0x75: /* LD (HL),L */ - cpu->mem_write(cpu, cpu->hl, cpu->l); + gb_mem_write(cpu->memory, cpu->hl, cpu->l); break; case 0x76: /* HALT */ cpu->halted = 1; break; case 0x77: /* LD (HL),A */ - cpu->mem_write(cpu, cpu->hl, cpu->a); + gb_mem_write(cpu->memory, cpu->hl, cpu->a); break; case 0x78: /* LD A,B */ cpu->a = cpu->b; @@ -762,7 +763,7 @@ int lr35902_cycle(struct lr35902_state *cpu) cpu->a = cpu->l; break; case 0x7e: /* LD A,(HL) */ - cpu->a = cpu->mem_read(cpu, cpu->hl);; + cpu->a = gb_mem_read(cpu->memory, cpu->hl);; break; case 0x7f: /* LD A,A */ break; @@ -785,7 +786,7 @@ int lr35902_cycle(struct lr35902_state *cpu) ADD_8(cpu, cpu->a, cpu->l); break; case 0x86: /* ADD A,(HL) */ - ADD_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + ADD_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0x87: /* ADD A,A */ ADD_8(cpu, cpu->a, cpu->a); @@ -809,7 +810,7 @@ int lr35902_cycle(struct lr35902_state *cpu) ADC_8(cpu, cpu->a, cpu->l); break; case 0x8e: /* ADC A,(HL) */ - ADC_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + ADC_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0x8f: /* ADC A,A */ ADC_8(cpu, cpu->a, cpu->a); @@ -833,7 +834,7 @@ int lr35902_cycle(struct lr35902_state *cpu) SUB_8(cpu, cpu->a, cpu->l); break; case 0x96: /* SUB A,(HL) */ - SUB_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + SUB_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0x97: /* SUB A,A */ SUB_8(cpu, cpu->a, cpu->a); @@ -857,7 +858,7 @@ int lr35902_cycle(struct lr35902_state *cpu) SBC_8(cpu, cpu->a, cpu->l); break; case 0x9e: /* SBC A, (HL) */ - SBC_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + SBC_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0x9f: /* SBC A, A */ SBC_8(cpu, cpu->a, cpu->a); @@ -881,7 +882,7 @@ int lr35902_cycle(struct lr35902_state *cpu) AND_8(cpu, cpu->a, cpu->l); break; case 0xa6: /* AND A, (HL) */ - AND_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + AND_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0xa7: /* AND A, A */ AND_8(cpu, cpu->a, cpu->a); @@ -905,7 +906,7 @@ int lr35902_cycle(struct lr35902_state *cpu) XOR_8(cpu, cpu->a, cpu->l); break; case 0xae: /* XOR A, (HL) */ - XOR_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + XOR_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0xaf: /* XOR A, A */ XOR_8(cpu, cpu->a, cpu->a); @@ -929,7 +930,7 @@ int lr35902_cycle(struct lr35902_state *cpu) OR_8(cpu, cpu->a, cpu->l); break; case 0xb6: /* OR A, (HL) */ - OR_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + OR_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0xb7: /* OR A, A */ OR_8(cpu, cpu->a, cpu->a); @@ -953,7 +954,7 @@ int lr35902_cycle(struct lr35902_state *cpu) CP_8(cpu, cpu->a, cpu->l); break; case 0xbe: /* CP A, (HL) */ - CP_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->hl)); + CP_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->hl)); break; case 0xbf: /* CP A, A */ CP_8(cpu, cpu->a, cpu->a); @@ -968,8 +969,8 @@ int lr35902_cycle(struct lr35902_state *cpu) break; case 0xc2: case 0xc3: /* JP a16 */ - val_16 = cpu->mem_read(cpu, cpu->pc++); - val_16 |= ((uint16_t) cpu->mem_read(cpu, cpu->pc++) << 8); + val_16 = gb_mem_read(cpu->memory, cpu->pc++); + val_16 |= ((uint16_t) gb_mem_read(cpu->memory, cpu->pc++) << 8); cpu->pc = val_16; break; case 0xc4: /* CALL NZ */ @@ -996,7 +997,7 @@ int lr35902_cycle(struct lr35902_state *cpu) break; case 0xca: case 0xcb: - inst = cpu->mem_read(cpu, cpu->pc++); + inst = gb_mem_read(cpu->memory, cpu->pc++); cycles = cb_extra_cycles[inst]; switch (inst) { case 0x00: @@ -1151,7 +1152,7 @@ int lr35902_cycle(struct lr35902_state *cpu) case 4: val = cpu->h; break; case 5: val = cpu->l; break; case 7: val = cpu->a; break; - case 6: val = cpu->mem_read(cpu, cpu->hl); + case 6: val = gb_mem_read(cpu->memory, cpu->hl); } BIT(cpu, val, (inst >> 3) & 7); break; @@ -1228,9 +1229,9 @@ int lr35902_cycle(struct lr35902_state *cpu) case 5: reg = &cpu->l; break; case 7: reg = &cpu->a; break; case 6: - val = cpu->mem_read(cpu, cpu->hl); + val = gb_mem_read(cpu->memory, cpu->hl); CLR_BIT(val, (inst >> 3) & 7); - cpu->mem_write(cpu, cpu->hl, val); + gb_mem_write(cpu->memory, cpu->hl, val); } if (!reg) @@ -1313,9 +1314,9 @@ int lr35902_cycle(struct lr35902_state *cpu) case 5: reg = &cpu->l; break; case 7: reg = &cpu->a; break; case 6: - val = cpu->mem_read(cpu, cpu->hl); + val = gb_mem_read(cpu->memory, cpu->hl); CLR_BIT(val, (inst >> 3) & 7); - cpu->mem_write(cpu, cpu->hl, val); + gb_mem_write(cpu->memory, cpu->hl, val); } if (!reg) @@ -1403,14 +1404,14 @@ int lr35902_cycle(struct lr35902_state *cpu) RST(cpu, 0x18); break; case 0xe0: /* LDH (a8), A / LD ($FF00+a8),A */ - val = cpu->mem_read(cpu, cpu->pc++); - cpu->mem_write(cpu, 0xff00 + val, cpu->a); + val = gb_mem_read(cpu->memory, cpu->pc++); + gb_mem_write(cpu->memory, 0xff00 + val, cpu->a); break; case 0xe1: /* POP HL */ POP_16(cpu, cpu->hl); break; case 0xe2: - cpu->mem_write(cpu, 0xff00 + cpu->c, cpu->a); + gb_mem_write(cpu->memory, 0xff00 + cpu->c, cpu->a); break; case 0xe3: /* UNDEF */ case 0xe4: /* UNDEF */ @@ -1425,9 +1426,9 @@ int lr35902_cycle(struct lr35902_state *cpu) case 0xe8: case 0xe9: case 0xea: /* LD (a16), A */ - val_16 = cpu->mem_read(cpu, cpu->pc++); - val_16 |= cpu->mem_read(cpu, cpu->pc++) << 8; - cpu->mem_write(cpu, val_16, cpu->a); + val_16 = gb_mem_read(cpu->memory, cpu->pc++); + val_16 |= gb_mem_read(cpu->memory, cpu->pc++) << 8; + gb_mem_write(cpu->memory, val_16, cpu->a); break; case 0xeb: /* UNDEF */ break; @@ -1440,12 +1441,12 @@ int lr35902_cycle(struct lr35902_state *cpu) RST(cpu, 0x28); break; case 0xf0: /* LDH A,(a8) / LD A,($FF00+a8) */ - val = cpu->mem_read(cpu, cpu->pc++); - cpu->a = cpu->mem_read(cpu, 0xff00 + val); + val = gb_mem_read(cpu->memory, cpu->pc++); + cpu->a = gb_mem_read(cpu->memory, 0xff00 + val); break; case 0xf1: /* POP AF */ - cpu->a = cpu->mem_read(cpu, cpu->sp++); - val = cpu->mem_read(cpu, cpu->sp++); + cpu->a = gb_mem_read(cpu->memory, cpu->sp++); + val = gb_mem_read(cpu->memory, cpu->sp++); cpu->zf = GET_BIT(val, CPU_F_BIT_POS_Z); cpu->nf = GET_BIT(val, CPU_F_BIT_POS_N); cpu->hf = GET_BIT(val, CPU_F_BIT_POS_H); @@ -1471,7 +1472,7 @@ int lr35902_cycle(struct lr35902_state *cpu) case 0xfd: /* UNDEF */ break; case 0xfe: /* CP d8 */ - CP_8(cpu, cpu->a, cpu->mem_read(cpu, cpu->pc++)); + CP_8(cpu, cpu->a, gb_mem_read(cpu->memory, cpu->pc++)); break; case 0xff: /* RST 0x38 */ RST(cpu, 0x38); diff --git a/src/gbemu/cpu.h b/src/gbemu/cpu.h index 55f73b0..0b382f3 100644 --- a/src/gbemu/cpu.h +++ b/src/gbemu/cpu.h @@ -8,6 +8,8 @@ #ifndef GB_CPU_H #define GB_CPU_H +#include "gbemu/memory.h" + #include #define CPU_F_BIT_POS_C 4 @@ -66,6 +68,9 @@ struct lr35902_event { }; struct lr35902_state { + + struct gb_memory *memory; + union { /* * As a convenience, give ourselves a bunch of different ways to @@ -95,8 +100,6 @@ struct lr35902_state { int stall_cycles; int halted; - lr35902_mem_read_fn mem_read; - lr35902_mem_write_fn mem_write; void (*undef_d3)(struct lr35902_state *reg); lr35902_interrupt_state int_state; @@ -119,7 +122,8 @@ struct lr35902_ops { }; void lr35902_init(struct lr35902_state *cpu, - const struct lr35902_ops *ops); + struct gb_memory *memory, + const struct lr35902_ops *ops); uint16_t lr35902_get_reg_16(const struct lr35902_state *cpu, lr35902_regs_16 reg); diff --git a/src/gbemu/memory.c b/src/gbemu/memory.c new file mode 100644 index 0000000..99ecf59 --- /dev/null +++ b/src/gbemu/memory.c @@ -0,0 +1,145 @@ +/* + * Log logic for memory-mapping for + */ + +#include "gbemu/memory.h" +#include "gbemu/video.h" + +#include "common/common.h" + +#include +#include +#include + +#define MAX_RAM_LEN (1 << 20) /* Up to 8Mb Cartridge */ +#define UNMAP_BOOTROM_ADDR 0xff50 + +static struct gb_video *video; + +static uint8_t ram[MAX_RAM_LEN]; +static unsigned char bootrom[0x100] = {0}; +static unsigned char cart_low[0x100] = {0}; +static int bootrom_mapped = 1; + +void gb_mem_init(struct gb_memory *memory, struct gb_video *v) +{ + video = v; + memset(&ram, 0, MAX_RAM_LEN); + bootrom_mapped = 1; +} + +uint8_t gb_mem_read(struct gb_memory *cpu, uint16_t addr) +{ + + switch (addr) { + case 0xFF40 ... 0xFF4B: + return gb_video_mem_read(video, addr); + default: + return ram[addr]; + } +} + +void gb_mem_write(struct gb_memory *cpu, uint16_t addr, uint8_t val) +{ + + switch (addr) { + case UNMAP_BOOTROM_ADDR: + if (val == 1) { + bootrom_mapped = 0; + memcpy(ram, cart_low, sizeof(cart_low)); + } + break; + case 0xFF40 ... 0xFF4B: + gb_video_mem_write(video, addr, val); + break; + case 0 ... 0x100: + if (bootrom_mapped) { + break; + } + /* Intentional fall-through */ + default: + ram[addr] = val; + } + +} + +void gb_mem_force_write(struct gb_memory *cpu, uint16_t addr, uint8_t val) +{ + + switch (addr) { + case UNMAP_BOOTROM_ADDR: + break; + case 0xFF40 ... 0xFF4B: + gb_video_mem_write(video, addr, val); + break; + case 0 ... 0x100: + /* Intentional fall-through */ + default: + ram[addr] = val; + } + +} + +static void load_file_to_buffer(char *filename, uint8_t *buffer, size_t size) +{ + //TODO: Check error codes like a real programmer :P + FILE* prog_file; + long filesize; + + prog_file = fopen(filename, "r"); + if(prog_file < 0) { + printf("Failed to load game file: %d\n", errno); + return; + } + + fseek(prog_file, 0, SEEK_END); + filesize = ftell(prog_file); + fseek(prog_file, 0, SEEK_SET); + + if (fread(buffer, MIN(filesize, size), 1, prog_file) < 0) { + printf("Failed to read filed: %d\n", errno); + } + fclose(prog_file); + +} + +int gb_memory_load_file(struct gb_memory *memory, enum gb_memory_range destination, char *filename) +{ + //TODO: Check error codes like a real programmer :P + FILE* prog_file; + long filesize; + + switch (destination) { + case GB_MEMORY_BOOTROM: + load_file_to_buffer(filename, bootrom, sizeof(bootrom)); + load_file_to_buffer(filename, ram, sizeof(bootrom)); + + break; + case GB_MEMORY_CART: + load_file_to_buffer(filename, ram, sizeof(ram)); + load_file_to_buffer(filename, cart_low, sizeof(cart_low)); + break; + default: + return -1; + } +} + +/* static void mem_dump(char *filename) */ +/* { */ +/* //TODO: Check error codes like a real programmer :P */ +/* FILE* dump_file; */ +/* char *token = strtok(filename, " "); */ + +/* if (token == NULL) { */ +/* gb_log("usage: load \n"); */ +/* return; */ +/* } */ +/* strip_newline(token); */ +/* dump_file = fopen(token, "w"); */ +/* if(dump_file == NULL) { */ +/* gb_log("Failed to open mem dump file: %d\n", errno); */ +/* return; */ +/* } */ +/* fwrite(ram, MAX_RAM_LEN, 1, dump_file); */ +/* fclose(dump_file); */ +/* } */ diff --git a/src/gbemu/memory.h b/src/gbemu/memory.h new file mode 100644 index 0000000..53bbc6f --- /dev/null +++ b/src/gbemu/memory.h @@ -0,0 +1,26 @@ +#ifndef _GB_MEMORY_H_ +#define _GB_MEMORY_H_ + +#include + +struct gb_memory; +struct gb_video; + +enum gb_memory_range { + GB_MEMORY_BOOTROM, + GB_MEMORY_CART, +}; + +void gb_mem_init(struct gb_memory *memory, struct gb_video *v); + +int gb_memory_load_file(struct gb_memory *memory, + enum gb_memory_range destination, + char *filename); + +uint8_t gb_mem_read(struct gb_memory *mem, uint16_t addr); + +void gb_mem_write(struct gb_memory *state, uint16_t addr, uint8_t val); + +void gb_mem_force_write(struct gb_memory *cpu, uint16_t addr, uint8_t val); + +#endif