memory: separate the memory-related code into it's own file
After doing a little reading about the way the memory banks are mapped, it looks like this code is going to grow. Separate it into it's own file. While we're at it, make gb_mem_read() a proper function instead of a callback. Because these functions are used so frequently, this corresponds to a ~10-20% performance benefit (due to LTO).
This commit is contained in:
131
src/apps/gbdb.c
131
src/apps/gbdb.c
@@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
#define INPUT_MAX_LEN 512
|
#define INPUT_MAX_LEN 512
|
||||||
#define MAX_BREAKPTS 16 /* Should be plenty for anyone */
|
#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);
|
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 breakpoint_cb(struct lr35902_state *lr);
|
||||||
static void reset_breakpoints(void);
|
static void reset_breakpoints(void);
|
||||||
|
|
||||||
static uint8_t ram[MAX_RAM_LEN];
|
|
||||||
static const char prompt[] = "gbdb >";
|
static const char prompt[] = "gbdb >";
|
||||||
static const char usage[] =
|
static const char usage[] =
|
||||||
"Available commands:\n"
|
"Available commands:\n"
|
||||||
@@ -44,11 +41,7 @@ static const char usage[] =
|
|||||||
static struct lr35902_ops cpu_ops;
|
static struct lr35902_ops cpu_ops;
|
||||||
static struct lr35902_state cpu;
|
static struct lr35902_state cpu;
|
||||||
static struct gb_video video;
|
static struct gb_video video;
|
||||||
|
static void *memory = NULL;
|
||||||
static unsigned char bootrom[0x100] = {0};
|
|
||||||
static unsigned char cart_low[0x100] = {0};
|
|
||||||
|
|
||||||
static int bootrom_mapped = 1;
|
|
||||||
|
|
||||||
static int paused_breakpoint = 0;
|
static int paused_breakpoint = 0;
|
||||||
static volatile sig_atomic_t paused_signal = 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 <file>\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)
|
static void init(void)
|
||||||
{
|
{
|
||||||
cpu_ops.mem_read = mem_read;
|
|
||||||
cpu_ops.mem_write = mem_write;
|
|
||||||
cpu_ops.undef_d3 = breakpoint_cb;
|
cpu_ops.undef_d3 = breakpoint_cb;
|
||||||
|
|
||||||
lr35902_init(&cpu, &cpu_ops);
|
lr35902_init(&cpu, memory, &cpu_ops);
|
||||||
gb_video_init(&video);
|
gb_video_init(&video);
|
||||||
memset(&ram, 0, MAX_RAM_LEN);
|
gb_mem_init(memory, &video);
|
||||||
bootrom_mapped = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cycle()
|
static void cycle()
|
||||||
@@ -255,7 +185,7 @@ static void regs(char *arg_list)
|
|||||||
static void peek(char *arg_list)
|
static void peek(char *arg_list)
|
||||||
{
|
{
|
||||||
uint16_t pc = lr35902_get_reg_16(&cpu, LR35902_REG_PC);
|
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));
|
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++) {
|
for (i = 0; i < bytes; i++) {
|
||||||
//TODO: Make sure this has no side effects
|
//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') {
|
if (token != NULL && token[0] == 'i') {
|
||||||
printf("0x%04x:%s\n", addr + i, gb_byte_to_opcode(val));
|
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)
|
static void load(char *arg_list)
|
||||||
{
|
{
|
||||||
char *token = strtok(arg_list, " ");
|
char *token = strtok(arg_list, " ");
|
||||||
@@ -445,9 +352,8 @@ static void load(char *arg_list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strip_newline(token);
|
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)
|
static void load_bootrom(char *arg_list)
|
||||||
@@ -459,8 +365,8 @@ static void load_bootrom(char *arg_list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strip_newline(token);
|
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);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_run(void) {
|
static __attribute__((hot)) void do_run(void) {
|
||||||
paused = 0;
|
paused = 0;
|
||||||
signal(SIGINT, break_execution_handler);
|
signal(SIGINT, break_execution_handler);
|
||||||
|
|
||||||
@@ -501,7 +407,6 @@ static struct breakpoint {
|
|||||||
int id;
|
int id;
|
||||||
bool temp;
|
bool temp;
|
||||||
uint8_t op;
|
uint8_t op;
|
||||||
uint8_t *ptr;
|
|
||||||
} breakpoints[MAX_BREAKPTS];
|
} breakpoints[MAX_BREAKPTS];
|
||||||
|
|
||||||
static int num_breakpoints = 0;
|
static int num_breakpoints = 0;
|
||||||
@@ -525,7 +430,7 @@ static void reset_breakpoints(void)
|
|||||||
|
|
||||||
for (i = 0; i < num_breakpoints; i++) {
|
for (i = 0; i < num_breakpoints; i++) {
|
||||||
struct breakpoint *bkpt = &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)) {
|
if (num_breakpoints < ARRAY_SIZE(breakpoints)) {
|
||||||
breakpoints[num_breakpoints].addr = addr;
|
breakpoints[num_breakpoints].addr = addr;
|
||||||
breakpoints[num_breakpoints].op = mem_read(NULL, addr);
|
breakpoints[num_breakpoints].op = gb_mem_read(memory, 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].id = id++;
|
breakpoints[num_breakpoints].id = id++;
|
||||||
breakpoints[num_breakpoints].temp = temp;
|
breakpoints[num_breakpoints].temp = temp;
|
||||||
|
gb_mem_force_write(memory, addr, 0xd3);
|
||||||
num_breakpoints++;
|
num_breakpoints++;
|
||||||
} else {
|
} else {
|
||||||
printf("maximum number of breakpoints reached\n");
|
printf("maximum number of breakpoints reached\n");
|
||||||
@@ -593,8 +493,8 @@ static int do_delete_breakpoint(int id)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*bkpt->ptr = bkpt->op;
|
gb_mem_force_write(memory, bkpt->addr, bkpt->op);
|
||||||
|
|
||||||
index = bkpt - breakpoints;
|
index = bkpt - breakpoints;
|
||||||
memmove(&breakpoints[index], &breakpoints[index + 1],
|
memmove(&breakpoints[index], &breakpoints[index + 1],
|
||||||
num_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, "load", load);
|
||||||
tri_add_string(&commands, "bootrom", load_bootrom);
|
tri_add_string(&commands, "bootrom", load_bootrom);
|
||||||
tri_add_string(&commands, "mem", mem);
|
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, "peek", peek);
|
||||||
tri_add_string(&commands, "help", help);
|
tri_add_string(&commands, "help", help);
|
||||||
tri_add_string(&commands, "?", help);
|
tri_add_string(&commands, "?", help);
|
||||||
|
|||||||
167
src/gbemu/cpu.c
167
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,
|
void lr35902_init(struct lr35902_state *cpu,
|
||||||
|
struct gb_memory *memory,
|
||||||
const struct lr35902_ops *ops)
|
const struct lr35902_ops *ops)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cpu->mem_read = ops->mem_read;
|
cpu->memory = memory;
|
||||||
cpu->mem_write = ops->mem_write;
|
|
||||||
cpu->undef_d3 = ops->undef_d3;
|
cpu->undef_d3 = ops->undef_d3;
|
||||||
|
|
||||||
cpu->int_state = LR35902_INT_OFF;
|
cpu->int_state = LR35902_INT_OFF;
|
||||||
@@ -141,15 +142,15 @@ static const unsigned int cb_extra_cycles[256] = { 0 };
|
|||||||
(cpu)->zf = (reg) == 0; \
|
(cpu)->zf = (reg) == 0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LD_D8(cpu, reg) \
|
#define LD_D8(cpu, reg) \
|
||||||
do { \
|
do { \
|
||||||
(reg) = (cpu)->mem_read((cpu), (cpu)->pc++); \
|
(reg) = gb_mem_read((cpu)->memory, (cpu)->pc++); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LD_D16(cpu, reg) \
|
#define LD_D16(cpu, reg) \
|
||||||
do { \
|
do { \
|
||||||
(reg) = (cpu)->mem_read((cpu), (cpu)->pc++); \
|
(reg) = gb_mem_read((cpu)->memory, (cpu)->pc++); \
|
||||||
(reg) |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->pc++) << 8; \
|
(reg) |= (uint16_t) gb_mem_read((cpu)->memory, (cpu)->pc++) << 8; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ADD_8(cpu, dst, src) \
|
#define ADD_8(cpu, dst, src) \
|
||||||
@@ -248,49 +249,49 @@ static const unsigned int cb_extra_cycles[256] = { 0 };
|
|||||||
(cpu)->zf = ((_tmp) == 0); \
|
(cpu)->zf = ((_tmp) == 0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define JR_8(cpu) \
|
#define JR_8(cpu) \
|
||||||
do { \
|
do { \
|
||||||
val_16 = cpu->mem_read(cpu, cpu->pc++); \
|
val_16 = gb_mem_read((cpu)->memory, cpu->pc++); \
|
||||||
/* sign-extend */ \
|
/* sign-extend */ \
|
||||||
val_16 |= GET_BIT(val_16, 7) ? 0xff00 : 0; \
|
val_16 |= GET_BIT(val_16, 7) ? 0xff00 : 0; \
|
||||||
cpu->pc += val_16; \
|
cpu->pc += val_16; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* TODO: In general, check that we pop/push things correctly */
|
/* TODO: In general, check that we pop/push things correctly */
|
||||||
#define POP_16(cpu, dst) \
|
#define POP_16(cpu, dst) \
|
||||||
do { \
|
do { \
|
||||||
(dst) = (cpu)->mem_read((cpu), (cpu)->sp++); \
|
(dst) = gb_mem_read((cpu)->memory, (cpu)->sp++); \
|
||||||
(dst) |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->sp++) << 8; \
|
(dst) |= (uint16_t) gb_mem_read((cpu)->memory, (cpu)->sp++) << 8; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define PUSH_16(cpu, src) \
|
#define PUSH_16(cpu, src) \
|
||||||
do { \
|
do { \
|
||||||
(cpu)->mem_write(cpu, --cpu->sp, src); \
|
gb_mem_write(cpu->memory, --cpu->sp, src); \
|
||||||
(cpu)->mem_write(cpu, --cpu->sp, src >> 8); \
|
gb_mem_write(cpu->memory, --cpu->sp, src >> 8); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define CALL(cpu) \
|
#define CALL(cpu) \
|
||||||
do { \
|
do { \
|
||||||
uint16_t pc_base; \
|
uint16_t pc_base; \
|
||||||
cpu->mem_write(cpu, --cpu->sp, cpu->pc); \
|
gb_mem_write(cpu->memory, --cpu->sp, cpu->pc); \
|
||||||
cpu->mem_write(cpu, --cpu->sp, cpu->pc >> 8); \
|
gb_mem_write(cpu->memory, --cpu->sp, cpu->pc >> 8); \
|
||||||
pc_base = cpu->mem_read(cpu, cpu->pc++); \
|
pc_base = gb_mem_read(cpu->memory, cpu->pc++); \
|
||||||
pc_base |= (uint16_t) cpu->mem_read(cpu, cpu->pc) << 8; \
|
pc_base |= (uint16_t) gb_mem_read(cpu->memory, cpu->pc) << 8; \
|
||||||
cpu->pc = pc_base; \
|
cpu->pc = pc_base; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RET(cpu) \
|
#define RET(cpu) \
|
||||||
do { \
|
do { \
|
||||||
(cpu)->pc = 0; \
|
(cpu)->pc = 0; \
|
||||||
(cpu)->pc |= (uint16_t) (cpu)->mem_read((cpu), (cpu)->sp++) << 8; \
|
(cpu)->pc |= (uint16_t) gb_mem_read((cpu)->memory, (cpu)->sp++) << 8; \
|
||||||
(cpu)->pc |= (cpu)->mem_read((cpu), (cpu)->sp++); \
|
(cpu)->pc |= gb_mem_read((cpu)->memory, (cpu)->sp++); \
|
||||||
(cpu)->pc += 2; \
|
(cpu)->pc += 2; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define RST(cpu, n) \
|
#define RST(cpu, n) \
|
||||||
do { \
|
do { \
|
||||||
(cpu)->mem_write((cpu), (cpu)->sp++, (cpu)->pc >> 8); \
|
gb_mem_write((cpu)->memory, (cpu)->sp++, (cpu)->pc >> 8); \
|
||||||
(cpu)->mem_write((cpu), (cpu)->sp++, (cpu)->pc); \
|
gb_mem_write((cpu)->memory, (cpu)->sp++, (cpu)->pc); \
|
||||||
(cpu)->pc = (n); \
|
(cpu)->pc = (n); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -332,7 +333,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
int cycles;
|
int cycles;
|
||||||
|
|
||||||
cpu->metrics.retired_instrs++;
|
cpu->metrics.retired_instrs++;
|
||||||
inst = cpu->mem_read(cpu, cpu->pc++);
|
inst = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
cycles = op_extra_cycles[inst];
|
cycles = op_extra_cycles[inst];
|
||||||
|
|
||||||
switch (inst) {
|
switch (inst) {
|
||||||
@@ -342,7 +343,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
LD_D16(cpu, cpu->bc);
|
LD_D16(cpu, cpu->bc);
|
||||||
break;
|
break;
|
||||||
case 0x02: /* LD (BC), A */
|
case 0x02: /* LD (BC), A */
|
||||||
cpu->mem_write(cpu, cpu->bc, cpu->a);
|
gb_mem_write(cpu->memory, cpu->bc, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0x03: /* INC BC */
|
case 0x03: /* INC BC */
|
||||||
cpu->bc++;
|
cpu->bc++;
|
||||||
@@ -365,14 +366,14 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
WRITE_BIT(cpu->a, 0, cpu->cf);
|
WRITE_BIT(cpu->a, 0, cpu->cf);
|
||||||
break;
|
break;
|
||||||
case 0x08: /* LD (a16), SP */
|
case 0x08: /* LD (a16), SP */
|
||||||
cpu->sp = cpu->mem_read(cpu, cpu->pc++);
|
cpu->sp = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
cpu->sp |= cpu->mem_read(cpu, cpu->pc++) << 8;
|
cpu->sp |= gb_mem_read(cpu->memory, cpu->pc++) << 8;
|
||||||
break;
|
break;
|
||||||
case 0x09: /* ADD HL, BC */
|
case 0x09: /* ADD HL, BC */
|
||||||
ADD_16(cpu, cpu->hl, cpu->bc);
|
ADD_16(cpu, cpu->hl, cpu->bc);
|
||||||
break;
|
break;
|
||||||
case 0x0a: /* LD A, (BC) */
|
case 0x0a: /* LD A, (BC) */
|
||||||
cpu->a = cpu->mem_read(cpu, cpu->bc);
|
cpu->a = gb_mem_read(cpu->memory, cpu->bc);
|
||||||
break;
|
break;
|
||||||
case 0x0b: /* DEC, BC */
|
case 0x0b: /* DEC, BC */
|
||||||
cpu->bc--;
|
cpu->bc--;
|
||||||
@@ -401,7 +402,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
LD_D16(cpu, cpu->de);
|
LD_D16(cpu, cpu->de);
|
||||||
break;
|
break;
|
||||||
case 0x12: /* LD (DE), A */
|
case 0x12: /* LD (DE), A */
|
||||||
cpu->mem_write(cpu, cpu->de, cpu->a);
|
gb_mem_write(cpu->memory, cpu->de, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0x13: /* INC DE */
|
case 0x13: /* INC DE */
|
||||||
cpu->de++;
|
cpu->de++;
|
||||||
@@ -430,7 +431,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
ADD_16(cpu, cpu->hl, cpu->de);
|
ADD_16(cpu, cpu->hl, cpu->de);
|
||||||
break;
|
break;
|
||||||
case 0x1a: /* LD A, (DE) */
|
case 0x1a: /* LD A, (DE) */
|
||||||
cpu->a = cpu->mem_read(cpu, cpu->de);
|
cpu->a = gb_mem_read(cpu->memory, cpu->de);
|
||||||
break;
|
break;
|
||||||
case 0x1b: /* DEC BC */
|
case 0x1b: /* DEC BC */
|
||||||
cpu->bc--;
|
cpu->bc--;
|
||||||
@@ -463,7 +464,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
LD_D16(cpu, cpu->hl);
|
LD_D16(cpu, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x22: /* LD (HL+), A */
|
case 0x22: /* LD (HL+), A */
|
||||||
cpu->a = cpu->mem_read(cpu, cpu->hl++);
|
cpu->a = gb_mem_read(cpu->memory, cpu->hl++);
|
||||||
break;
|
break;
|
||||||
case 0x23: /* INC HL */
|
case 0x23: /* INC HL */
|
||||||
cpu->hl++;
|
cpu->hl++;
|
||||||
@@ -491,7 +492,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
ADD_16(cpu, cpu->hl, cpu->hl);
|
ADD_16(cpu, cpu->hl, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x2a: /* LD A, (HL+) */
|
case 0x2a: /* LD A, (HL+) */
|
||||||
cpu->a = cpu->mem_read(cpu, cpu->hl);
|
cpu->a = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
cpu->hl--;
|
cpu->hl--;
|
||||||
break;
|
break;
|
||||||
case 0x2b: /* DEC HL */
|
case 0x2b: /* DEC HL */
|
||||||
@@ -522,30 +523,30 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
LD_D16(cpu, cpu->sp);
|
LD_D16(cpu, cpu->sp);
|
||||||
break;
|
break;
|
||||||
case 0x32: /* LD (HL-), A */
|
case 0x32: /* LD (HL-), A */
|
||||||
cpu->mem_write(cpu, cpu->hl--, cpu->a);
|
gb_mem_write(cpu->memory, cpu->hl--, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0x33: /* INC SP */
|
case 0x33: /* INC SP */
|
||||||
cpu->sp++;
|
cpu->sp++;
|
||||||
break;
|
break;
|
||||||
case 0x34: /* INC (HL) */
|
case 0x34: /* INC (HL) */
|
||||||
val = cpu->mem_read(cpu, cpu->hl);
|
val = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
cpu->nf = 0;
|
cpu->nf = 0;
|
||||||
cpu->hf = CALC_H_ADD(val, 1);
|
cpu->hf = CALC_H_ADD(val, 1);
|
||||||
val++;
|
val++;
|
||||||
cpu->mem_write(cpu, cpu->hl, val);
|
gb_mem_write(cpu->memory, cpu->hl, val);
|
||||||
cpu->zf = (val == 0);
|
cpu->zf = (val == 0);
|
||||||
break;
|
break;
|
||||||
case 0x35: /* DEC (HL) */
|
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->hf = CALC_H_ADD(val, 1);
|
||||||
cpu->zf = (val == 0);
|
cpu->zf = (val == 0);
|
||||||
cpu->nf = 1;
|
cpu->nf = 1;
|
||||||
val--;
|
val--;
|
||||||
cpu->mem_write(cpu, cpu->hl, val);
|
gb_mem_write(cpu->memory, cpu->hl, val);
|
||||||
break;
|
break;
|
||||||
case 0x36: /* LD (HL), d8 */
|
case 0x36: /* LD (HL), d8 */
|
||||||
val = cpu->mem_read(cpu, cpu->pc++);
|
val = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
cpu->mem_write(cpu, cpu->hl++, val);
|
gb_mem_write(cpu->memory, cpu->hl++, val);
|
||||||
break;
|
break;
|
||||||
case 0x37: /* SCF */
|
case 0x37: /* SCF */
|
||||||
cpu->nf = 0;
|
cpu->nf = 0;
|
||||||
@@ -563,7 +564,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
ADD_16(cpu, cpu->hl, cpu->sp);
|
ADD_16(cpu, cpu->hl, cpu->sp);
|
||||||
break;
|
break;
|
||||||
case 0x3a: /* LD A, (HL-) */
|
case 0x3a: /* LD A, (HL-) */
|
||||||
cpu->a = cpu->mem_read(cpu, cpu->hl);
|
cpu->a = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
cpu->hl--;
|
cpu->hl--;
|
||||||
break;
|
break;
|
||||||
case 0x3b: /* DEC SP */
|
case 0x3b: /* DEC SP */
|
||||||
@@ -599,7 +600,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
cpu->b = cpu->l;
|
cpu->b = cpu->l;
|
||||||
break;
|
break;
|
||||||
case 0x46: /* LD B,(HL) */
|
case 0x46: /* LD B,(HL) */
|
||||||
cpu->b = cpu->mem_read(cpu, cpu->hl);
|
cpu->b = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x47: /* LD B,A */
|
case 0x47: /* LD B,A */
|
||||||
cpu->b = cpu->a;
|
cpu->b = cpu->a;
|
||||||
@@ -622,7 +623,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
cpu->c = cpu->l;
|
cpu->c = cpu->l;
|
||||||
break;
|
break;
|
||||||
case 0x4e: /* LD C,(HL) */
|
case 0x4e: /* LD C,(HL) */
|
||||||
cpu->c = cpu->mem_read(cpu, cpu->hl);
|
cpu->c = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x4f: /* LD C,A */
|
case 0x4f: /* LD C,A */
|
||||||
cpu->c = cpu->a;
|
cpu->c = cpu->a;
|
||||||
@@ -645,7 +646,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
cpu->d = cpu->l;
|
cpu->d = cpu->l;
|
||||||
break;
|
break;
|
||||||
case 0x56: /* LD D,(HL) */
|
case 0x56: /* LD D,(HL) */
|
||||||
cpu->d = cpu->mem_read(cpu, cpu->hl);
|
cpu->d = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x57: /* LD D,A */
|
case 0x57: /* LD D,A */
|
||||||
cpu->d = cpu->a;
|
cpu->d = cpu->a;
|
||||||
@@ -668,7 +669,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
cpu->e = cpu->h;
|
cpu->e = cpu->h;
|
||||||
break;
|
break;
|
||||||
case 0x5e: /* LD E,(HL) */
|
case 0x5e: /* LD E,(HL) */
|
||||||
cpu->e = cpu->mem_read(cpu, cpu->hl);
|
cpu->e = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x5f: /* LD E,A */
|
case 0x5f: /* LD E,A */
|
||||||
cpu->e = cpu->a;
|
cpu->e = cpu->a;
|
||||||
@@ -691,7 +692,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
cpu->h = cpu->l;
|
cpu->h = cpu->l;
|
||||||
break;
|
break;
|
||||||
case 0x66: /* LD H,(HL) */
|
case 0x66: /* LD H,(HL) */
|
||||||
cpu->h = cpu->mem_read(cpu, cpu->hl);
|
cpu->h = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x67: /* LD H,A */
|
case 0x67: /* LD H,A */
|
||||||
cpu->h = cpu->a;
|
cpu->h = cpu->a;
|
||||||
@@ -714,34 +715,34 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
case 0x6d: /* LD L,L */
|
case 0x6d: /* LD L,L */
|
||||||
break;
|
break;
|
||||||
case 0x6e: /* LD L,(HL) */
|
case 0x6e: /* LD L,(HL) */
|
||||||
cpu->l = cpu->mem_read(cpu, cpu->hl);
|
cpu->l = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0x6f: /* LD L,A */
|
case 0x6f: /* LD L,A */
|
||||||
cpu->l = cpu->a;
|
cpu->l = cpu->a;
|
||||||
break;
|
break;
|
||||||
case 0x70: /* LD (HL),B */
|
case 0x70: /* LD (HL),B */
|
||||||
cpu->mem_write(cpu, cpu->hl, cpu->b);
|
gb_mem_write(cpu->memory, cpu->hl, cpu->b);
|
||||||
break;
|
break;
|
||||||
case 0x71: /* LD (HL),C */
|
case 0x71: /* LD (HL),C */
|
||||||
cpu->mem_write(cpu, cpu->hl, cpu->c);
|
gb_mem_write(cpu->memory, cpu->hl, cpu->c);
|
||||||
break;
|
break;
|
||||||
case 0x72: /* LD (HL),D */
|
case 0x72: /* LD (HL),D */
|
||||||
cpu->mem_write(cpu, cpu->hl, cpu->d);
|
gb_mem_write(cpu->memory, cpu->hl, cpu->d);
|
||||||
break;
|
break;
|
||||||
case 0x73: /* LD (HL),E */
|
case 0x73: /* LD (HL),E */
|
||||||
cpu->mem_write(cpu, cpu->hl, cpu->e);
|
gb_mem_write(cpu->memory, cpu->hl, cpu->e);
|
||||||
break;
|
break;
|
||||||
case 0x74: /* LD (HL),H */
|
case 0x74: /* LD (HL),H */
|
||||||
cpu->mem_write(cpu, cpu->hl, cpu->h);
|
gb_mem_write(cpu->memory, cpu->hl, cpu->h);
|
||||||
break;
|
break;
|
||||||
case 0x75: /* LD (HL),L */
|
case 0x75: /* LD (HL),L */
|
||||||
cpu->mem_write(cpu, cpu->hl, cpu->l);
|
gb_mem_write(cpu->memory, cpu->hl, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0x76: /* HALT */
|
case 0x76: /* HALT */
|
||||||
cpu->halted = 1;
|
cpu->halted = 1;
|
||||||
break;
|
break;
|
||||||
case 0x77: /* LD (HL),A */
|
case 0x77: /* LD (HL),A */
|
||||||
cpu->mem_write(cpu, cpu->hl, cpu->a);
|
gb_mem_write(cpu->memory, cpu->hl, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0x78: /* LD A,B */
|
case 0x78: /* LD A,B */
|
||||||
cpu->a = cpu->b;
|
cpu->a = cpu->b;
|
||||||
@@ -762,7 +763,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
cpu->a = cpu->l;
|
cpu->a = cpu->l;
|
||||||
break;
|
break;
|
||||||
case 0x7e: /* LD A,(HL) */
|
case 0x7e: /* LD A,(HL) */
|
||||||
cpu->a = cpu->mem_read(cpu, cpu->hl);;
|
cpu->a = gb_mem_read(cpu->memory, cpu->hl);;
|
||||||
break;
|
break;
|
||||||
case 0x7f: /* LD A,A */
|
case 0x7f: /* LD A,A */
|
||||||
break;
|
break;
|
||||||
@@ -785,7 +786,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
ADD_8(cpu, cpu->a, cpu->l);
|
ADD_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0x86: /* ADD A,(HL) */
|
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;
|
break;
|
||||||
case 0x87: /* ADD A,A */
|
case 0x87: /* ADD A,A */
|
||||||
ADD_8(cpu, cpu->a, cpu->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);
|
ADC_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0x8e: /* ADC A,(HL) */
|
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;
|
break;
|
||||||
case 0x8f: /* ADC A,A */
|
case 0x8f: /* ADC A,A */
|
||||||
ADC_8(cpu, cpu->a, cpu->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);
|
SUB_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0x96: /* SUB A,(HL) */
|
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;
|
break;
|
||||||
case 0x97: /* SUB A,A */
|
case 0x97: /* SUB A,A */
|
||||||
SUB_8(cpu, cpu->a, cpu->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);
|
SBC_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0x9e: /* SBC A, (HL) */
|
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;
|
break;
|
||||||
case 0x9f: /* SBC A, A */
|
case 0x9f: /* SBC A, A */
|
||||||
SBC_8(cpu, cpu->a, cpu->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);
|
AND_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0xa6: /* AND A, (HL) */
|
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;
|
break;
|
||||||
case 0xa7: /* AND A, A */
|
case 0xa7: /* AND A, A */
|
||||||
AND_8(cpu, cpu->a, cpu->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);
|
XOR_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0xae: /* XOR A, (HL) */
|
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;
|
break;
|
||||||
case 0xaf: /* XOR A, A */
|
case 0xaf: /* XOR A, A */
|
||||||
XOR_8(cpu, cpu->a, cpu->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);
|
OR_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0xb6: /* OR A, (HL) */
|
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;
|
break;
|
||||||
case 0xb7: /* OR A, A */
|
case 0xb7: /* OR A, A */
|
||||||
OR_8(cpu, cpu->a, cpu->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);
|
CP_8(cpu, cpu->a, cpu->l);
|
||||||
break;
|
break;
|
||||||
case 0xbe: /* CP A, (HL) */
|
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;
|
break;
|
||||||
case 0xbf: /* CP A, A */
|
case 0xbf: /* CP A, A */
|
||||||
CP_8(cpu, cpu->a, cpu->a);
|
CP_8(cpu, cpu->a, cpu->a);
|
||||||
@@ -968,8 +969,8 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
break;
|
break;
|
||||||
case 0xc2:
|
case 0xc2:
|
||||||
case 0xc3: /* JP a16 */
|
case 0xc3: /* JP a16 */
|
||||||
val_16 = cpu->mem_read(cpu, cpu->pc++);
|
val_16 = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
val_16 |= ((uint16_t) cpu->mem_read(cpu, cpu->pc++) << 8);
|
val_16 |= ((uint16_t) gb_mem_read(cpu->memory, cpu->pc++) << 8);
|
||||||
cpu->pc = val_16;
|
cpu->pc = val_16;
|
||||||
break;
|
break;
|
||||||
case 0xc4: /* CALL NZ */
|
case 0xc4: /* CALL NZ */
|
||||||
@@ -996,7 +997,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
break;
|
break;
|
||||||
case 0xca:
|
case 0xca:
|
||||||
case 0xcb:
|
case 0xcb:
|
||||||
inst = cpu->mem_read(cpu, cpu->pc++);
|
inst = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
cycles = cb_extra_cycles[inst];
|
cycles = cb_extra_cycles[inst];
|
||||||
switch (inst) {
|
switch (inst) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
@@ -1151,7 +1152,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
case 4: val = cpu->h; break;
|
case 4: val = cpu->h; break;
|
||||||
case 5: val = cpu->l; break;
|
case 5: val = cpu->l; break;
|
||||||
case 7: val = cpu->a; 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);
|
BIT(cpu, val, (inst >> 3) & 7);
|
||||||
break;
|
break;
|
||||||
@@ -1228,9 +1229,9 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
case 5: reg = &cpu->l; break;
|
case 5: reg = &cpu->l; break;
|
||||||
case 7: reg = &cpu->a; break;
|
case 7: reg = &cpu->a; break;
|
||||||
case 6:
|
case 6:
|
||||||
val = cpu->mem_read(cpu, cpu->hl);
|
val = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
CLR_BIT(val, (inst >> 3) & 7);
|
CLR_BIT(val, (inst >> 3) & 7);
|
||||||
cpu->mem_write(cpu, cpu->hl, val);
|
gb_mem_write(cpu->memory, cpu->hl, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reg)
|
if (!reg)
|
||||||
@@ -1313,9 +1314,9 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
case 5: reg = &cpu->l; break;
|
case 5: reg = &cpu->l; break;
|
||||||
case 7: reg = &cpu->a; break;
|
case 7: reg = &cpu->a; break;
|
||||||
case 6:
|
case 6:
|
||||||
val = cpu->mem_read(cpu, cpu->hl);
|
val = gb_mem_read(cpu->memory, cpu->hl);
|
||||||
CLR_BIT(val, (inst >> 3) & 7);
|
CLR_BIT(val, (inst >> 3) & 7);
|
||||||
cpu->mem_write(cpu, cpu->hl, val);
|
gb_mem_write(cpu->memory, cpu->hl, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reg)
|
if (!reg)
|
||||||
@@ -1403,14 +1404,14 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
RST(cpu, 0x18);
|
RST(cpu, 0x18);
|
||||||
break;
|
break;
|
||||||
case 0xe0: /* LDH (a8), A / LD ($FF00+a8),A */
|
case 0xe0: /* LDH (a8), A / LD ($FF00+a8),A */
|
||||||
val = cpu->mem_read(cpu, cpu->pc++);
|
val = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
cpu->mem_write(cpu, 0xff00 + val, cpu->a);
|
gb_mem_write(cpu->memory, 0xff00 + val, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0xe1: /* POP HL */
|
case 0xe1: /* POP HL */
|
||||||
POP_16(cpu, cpu->hl);
|
POP_16(cpu, cpu->hl);
|
||||||
break;
|
break;
|
||||||
case 0xe2:
|
case 0xe2:
|
||||||
cpu->mem_write(cpu, 0xff00 + cpu->c, cpu->a);
|
gb_mem_write(cpu->memory, 0xff00 + cpu->c, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0xe3: /* UNDEF */
|
case 0xe3: /* UNDEF */
|
||||||
case 0xe4: /* UNDEF */
|
case 0xe4: /* UNDEF */
|
||||||
@@ -1425,9 +1426,9 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
case 0xe8:
|
case 0xe8:
|
||||||
case 0xe9:
|
case 0xe9:
|
||||||
case 0xea: /* LD (a16), A */
|
case 0xea: /* LD (a16), A */
|
||||||
val_16 = cpu->mem_read(cpu, cpu->pc++);
|
val_16 = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
val_16 |= cpu->mem_read(cpu, cpu->pc++) << 8;
|
val_16 |= gb_mem_read(cpu->memory, cpu->pc++) << 8;
|
||||||
cpu->mem_write(cpu, val_16, cpu->a);
|
gb_mem_write(cpu->memory, val_16, cpu->a);
|
||||||
break;
|
break;
|
||||||
case 0xeb: /* UNDEF */
|
case 0xeb: /* UNDEF */
|
||||||
break;
|
break;
|
||||||
@@ -1440,12 +1441,12 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
RST(cpu, 0x28);
|
RST(cpu, 0x28);
|
||||||
break;
|
break;
|
||||||
case 0xf0: /* LDH A,(a8) / LD A,($FF00+a8) */
|
case 0xf0: /* LDH A,(a8) / LD A,($FF00+a8) */
|
||||||
val = cpu->mem_read(cpu, cpu->pc++);
|
val = gb_mem_read(cpu->memory, cpu->pc++);
|
||||||
cpu->a = cpu->mem_read(cpu, 0xff00 + val);
|
cpu->a = gb_mem_read(cpu->memory, 0xff00 + val);
|
||||||
break;
|
break;
|
||||||
case 0xf1: /* POP AF */
|
case 0xf1: /* POP AF */
|
||||||
cpu->a = cpu->mem_read(cpu, cpu->sp++);
|
cpu->a = gb_mem_read(cpu->memory, cpu->sp++);
|
||||||
val = cpu->mem_read(cpu, cpu->sp++);
|
val = gb_mem_read(cpu->memory, cpu->sp++);
|
||||||
cpu->zf = GET_BIT(val, CPU_F_BIT_POS_Z);
|
cpu->zf = GET_BIT(val, CPU_F_BIT_POS_Z);
|
||||||
cpu->nf = GET_BIT(val, CPU_F_BIT_POS_N);
|
cpu->nf = GET_BIT(val, CPU_F_BIT_POS_N);
|
||||||
cpu->hf = GET_BIT(val, CPU_F_BIT_POS_H);
|
cpu->hf = GET_BIT(val, CPU_F_BIT_POS_H);
|
||||||
@@ -1471,7 +1472,7 @@ int lr35902_cycle(struct lr35902_state *cpu)
|
|||||||
case 0xfd: /* UNDEF */
|
case 0xfd: /* UNDEF */
|
||||||
break;
|
break;
|
||||||
case 0xfe: /* CP d8 */
|
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;
|
break;
|
||||||
case 0xff: /* RST 0x38 */
|
case 0xff: /* RST 0x38 */
|
||||||
RST(cpu, 0x38);
|
RST(cpu, 0x38);
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#ifndef GB_CPU_H
|
#ifndef GB_CPU_H
|
||||||
#define GB_CPU_H
|
#define GB_CPU_H
|
||||||
|
|
||||||
|
#include "gbemu/memory.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define CPU_F_BIT_POS_C 4
|
#define CPU_F_BIT_POS_C 4
|
||||||
@@ -66,6 +68,9 @@ struct lr35902_event {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct lr35902_state {
|
struct lr35902_state {
|
||||||
|
|
||||||
|
struct gb_memory *memory;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
/*
|
/*
|
||||||
* As a convenience, give ourselves a bunch of different ways to
|
* As a convenience, give ourselves a bunch of different ways to
|
||||||
@@ -95,8 +100,6 @@ struct lr35902_state {
|
|||||||
int stall_cycles;
|
int stall_cycles;
|
||||||
int halted;
|
int halted;
|
||||||
|
|
||||||
lr35902_mem_read_fn mem_read;
|
|
||||||
lr35902_mem_write_fn mem_write;
|
|
||||||
void (*undef_d3)(struct lr35902_state *reg);
|
void (*undef_d3)(struct lr35902_state *reg);
|
||||||
|
|
||||||
lr35902_interrupt_state int_state;
|
lr35902_interrupt_state int_state;
|
||||||
@@ -119,7 +122,8 @@ struct lr35902_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void lr35902_init(struct lr35902_state *cpu,
|
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,
|
uint16_t lr35902_get_reg_16(const struct lr35902_state *cpu,
|
||||||
lr35902_regs_16 reg);
|
lr35902_regs_16 reg);
|
||||||
|
|||||||
145
src/gbemu/memory.c
Normal file
145
src/gbemu/memory.c
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Log logic for memory-mapping for
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gbemu/memory.h"
|
||||||
|
#include "gbemu/video.h"
|
||||||
|
|
||||||
|
#include "common/common.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#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 <file>\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); */
|
||||||
|
/* } */
|
||||||
26
src/gbemu/memory.h
Normal file
26
src/gbemu/memory.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _GB_MEMORY_H_
|
||||||
|
#define _GB_MEMORY_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user