mirror of https://github.com/mlaux/gb6.git
Compare commits
8 Commits
b2a6890524
...
d69a3b35f1
Author | SHA1 | Date |
---|---|---|
Matthew Laux | d69a3b35f1 | |
Matthew Laux | f9f199dad2 | |
Matthew Laux | d22e2d9cba | |
Matthew Laux | aba7a9b847 | |
Matthew Laux | a3efa63361 | |
Matthew Laux | 5ed288eaa9 | |
Matthew Laux | bad415fa23 | |
Matthew Laux | ead7a3e17c |
|
@ -14,3 +14,4 @@ lib
|
|||
imgui.ini
|
||||
.DS_Store
|
||||
roms
|
||||
examples/*.bin
|
||||
|
|
|
@ -34,8 +34,8 @@ add_executable(gb6
|
|||
)
|
||||
|
||||
target_link_libraries(gb6
|
||||
"-framework OpenGL"
|
||||
"-framework CoreFoundation"
|
||||
"-lGL"
|
||||
"-ldl"
|
||||
"${SDL_LIBS}"
|
||||
)
|
||||
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
|
||||
for src_file in *.asm; do
|
||||
[ -e "$src_file" ] || continue
|
||||
|
||||
|
||||
obj_file="$(basename "$src_file" .asm).obj"
|
||||
bin_file="$(basename "$src_file" .asm).bin"
|
||||
echo "$src_file -> $bin_file"
|
||||
|
||||
rgbasm -o $obj_file $src_file
|
||||
rgblink --nopad -o $bin_file $obj_file
|
||||
done
|
||||
|
||||
rm -f *.obj
|
|
@ -0,0 +1,23 @@
|
|||
section "main", rom0
|
||||
|
||||
nop
|
||||
ld b, $0
|
||||
ld c, $11
|
||||
ld d, $22
|
||||
ld e, $33
|
||||
ld h, $44
|
||||
ld l, $55
|
||||
ld [hl], $66
|
||||
ld a, $77
|
||||
ld bc, $0123
|
||||
ld de, $4567
|
||||
ld hl, $89ab
|
||||
ld sp, $cdef
|
||||
simple_loop:
|
||||
dec a
|
||||
jr nz, simple_loop
|
||||
|
||||
end:
|
||||
jr end
|
||||
|
||||
db $fd
|
|
@ -0,0 +1,156 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h> // mprotect
|
||||
#include <unistd.h> // getpagesize
|
||||
|
||||
// A -> D0
|
||||
// BC -> D1
|
||||
// DE -> D2
|
||||
// HL -> A0
|
||||
// SP -> A7
|
||||
|
||||
uint8_t out_code[1024];
|
||||
uint8_t memory[1024]; // ???
|
||||
uint32_t out_ptr;
|
||||
|
||||
struct basic_block {
|
||||
// in 68k space?
|
||||
uint8_t code[256];
|
||||
size_t length;
|
||||
};
|
||||
|
||||
// need some kind of map from gb address to struct basic_block?
|
||||
|
||||
uint8_t test_code[] = {
|
||||
0x00, // nop
|
||||
0x06, 0x00, // ld b, $0
|
||||
0x0e, 0x11, // ld c, $11
|
||||
0x16, 0x22, // ld d, $22
|
||||
0x1e, 0x33, // ld e, $33
|
||||
0x26, 0x44, // ld h, $44
|
||||
0x2e, 0x55, // ld l, $55
|
||||
0x36, 0x66, // ld [hl], $66
|
||||
0x3e, 0x77, // ld a, $77
|
||||
0x01, 0x23, 0x01, // ld bc, $0123
|
||||
0x11, 0x67, 0x45, // ld de, $4567
|
||||
0x21, 0xab, 0x89, // ld hl, $89ab
|
||||
0x31, 0xef, 0xcd, // ld sp, $cdef
|
||||
0x3e, 0x0a, // .loop: ld a, 10
|
||||
0x3d, // dec a
|
||||
0x20, 0xfd, // jr nz, .loop
|
||||
0x18, 0xfe, // jr $-1
|
||||
0xc9 // ret
|
||||
};
|
||||
|
||||
struct basic_block *compile_block(uint16_t src_address, uint8_t *gb_code)
|
||||
{
|
||||
uint8_t instruction;
|
||||
struct basic_block *bblock;
|
||||
uint32_t dst_ptr = 0;
|
||||
uint16_t src_ptr = 0;
|
||||
|
||||
printf("compile block starting at 0x%04x\n", src_address);
|
||||
|
||||
bblock = malloc(sizeof *bblock);
|
||||
// bblock->code = out_code + start;
|
||||
|
||||
while (1) {
|
||||
instruction = gb_code[src_ptr++];
|
||||
if (instruction == 0xfd) {
|
||||
// invalid opcode for testing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bblock->length = 6;
|
||||
bblock->code[0] = 0xb8; // mov eax, 1234h
|
||||
bblock->code[1] = 0x34;
|
||||
bblock->code[2] = 0x12;
|
||||
bblock->code[3] = 0x00;
|
||||
bblock->code[4] = 0x00;
|
||||
bblock->code[5] = 0xc3; // ret
|
||||
|
||||
return bblock;
|
||||
}
|
||||
|
||||
void run_block(struct basic_block *bblock)
|
||||
{
|
||||
// calling convention? do i need to do this from asm?
|
||||
uint16_t jump_target = ((uint16_t (*)()) bblock->code)();
|
||||
}
|
||||
|
||||
// TODO
|
||||
void block_cache_add(uint16_t src_address, struct basic_block *bblock)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
struct basic_block *block_cache_get(uint16_t src_address)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 1. compile each block ending in a jump
|
||||
// 2. turn the jump into a return
|
||||
// 3. add the compiled code to some kind of cache
|
||||
// 3. return back to check the cache and maybe compile the next block
|
||||
|
||||
void run_all(uint8_t *gb_code)
|
||||
{
|
||||
struct basic_block *bblock;
|
||||
uint16_t jump_target = 0;
|
||||
int page_size, ret;
|
||||
|
||||
while (1) {
|
||||
bblock = block_cache_get(jump_target);
|
||||
if (!bblock) {
|
||||
bblock = compile_block(jump_target, gb_code + jump_target);
|
||||
if (bblock->length == 0) {
|
||||
break;
|
||||
}
|
||||
block_cache_add(jump_target, bblock);
|
||||
}
|
||||
|
||||
// for testing...
|
||||
page_size = getpagesize();
|
||||
ret = mprotect(
|
||||
(void *) ((uint64_t) bblock & ~(page_size - 1)),
|
||||
page_size,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC
|
||||
);
|
||||
if (ret == -1) {
|
||||
perror("mprotect");
|
||||
exit(0);
|
||||
}
|
||||
jump_target = ((uint16_t (*)()) bblock->code)();
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
long len;
|
||||
uint8_t *data;
|
||||
|
||||
if (argc < 2) {
|
||||
data = test_code;
|
||||
} else {
|
||||
fp = fopen(argv[1], "r");
|
||||
fseek(fp, 0, SEEK_END);
|
||||
len = ftell(fp);
|
||||
rewind(fp);
|
||||
data = malloc(len);
|
||||
fread(data, 1, len, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
run_all(data);
|
||||
|
||||
if (data != test_code) {
|
||||
free(data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
123
src/cpu.c
123
src/cpu.c
|
@ -73,13 +73,14 @@ static inline void write8(struct cpu *cpu, u16 address, u8 data)
|
|||
|
||||
static inline void write16(struct cpu *cpu, u16 address, u16 data)
|
||||
{
|
||||
dmg_write(cpu->dmg, address, data);
|
||||
dmg_write(cpu->dmg, address, data & 0xff);
|
||||
dmg_write(cpu->dmg, address + 1, data >> 8);
|
||||
}
|
||||
|
||||
static void inc_with_carry(struct cpu *regs, u8 *reg)
|
||||
{
|
||||
clear_flag(regs, FLAG_SIGN);
|
||||
if(*reg == 0xff || *reg == 0x0f)
|
||||
if((*reg & 0xf) == 0xf)
|
||||
set_flag(regs, FLAG_HALF_CARRY);
|
||||
else clear_flag(regs, FLAG_HALF_CARRY);
|
||||
(*reg)++;
|
||||
|
@ -91,7 +92,7 @@ static void inc_with_carry(struct cpu *regs, u8 *reg)
|
|||
static void dec_with_carry(struct cpu *regs, u8 *reg)
|
||||
{
|
||||
set_flag(regs, FLAG_SIGN);
|
||||
if(*reg == 0x00 || *reg == 0x10)
|
||||
if((*reg & 0xf) == 0)
|
||||
set_flag(regs, FLAG_HALF_CARRY);
|
||||
else clear_flag(regs, FLAG_HALF_CARRY);
|
||||
(*reg)--;
|
||||
|
@ -103,11 +104,20 @@ static void dec_with_carry(struct cpu *regs, u8 *reg)
|
|||
static u8 rotate_left(struct cpu *regs, u8 reg)
|
||||
{
|
||||
int old_carry = flag_isset(regs, FLAG_CARRY);
|
||||
// copy old leftmost bit to carry flag, clear Z, N, H
|
||||
regs->f = (reg & 0x80) >> 3;
|
||||
// rotate
|
||||
int result = reg << 1 | old_carry;
|
||||
if (!result) set_flag(regs, FLAG_ZERO);
|
||||
int result = (u8) ((reg & 0x7f) << 1) | old_carry;
|
||||
|
||||
if (!result) {
|
||||
set_flag(regs, FLAG_ZERO);
|
||||
} else {
|
||||
clear_flag(regs, FLAG_ZERO);
|
||||
}
|
||||
clear_flag(regs, FLAG_SIGN);
|
||||
clear_flag(regs, FLAG_HALF_CARRY);
|
||||
if (reg & 0x80) {
|
||||
set_flag(regs, FLAG_CARRY);
|
||||
} else {
|
||||
clear_flag(regs, FLAG_CARRY);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -154,7 +164,7 @@ static u8 rrc(struct cpu *cpu, u8 val)
|
|||
|
||||
static u8 shift_left(struct cpu *cpu, u8 value)
|
||||
{
|
||||
int result = value << 1;
|
||||
u8 result = value << 1;
|
||||
if (result == 0) {
|
||||
set_flag(cpu, FLAG_ZERO);
|
||||
} else {
|
||||
|
@ -172,7 +182,7 @@ static u8 shift_left(struct cpu *cpu, u8 value)
|
|||
|
||||
static u8 shift_right(struct cpu *cpu, u8 value)
|
||||
{
|
||||
int result = (signed) value >> 1;
|
||||
u8 result = (signed char) value >> 1;
|
||||
if (result == 0) {
|
||||
set_flag(cpu, FLAG_ZERO);
|
||||
} else {
|
||||
|
@ -257,13 +267,9 @@ static void and(struct cpu *cpu, u8 value)
|
|||
|
||||
static void add(struct cpu *cpu, u8 value, int with_carry)
|
||||
{
|
||||
u8 sum_trunc;
|
||||
int sum_full = cpu->a + value;
|
||||
int carry = (with_carry && flag_isset(cpu, FLAG_CARRY)) ? 1 : 0;
|
||||
if (carry) {
|
||||
sum_full++;
|
||||
}
|
||||
sum_trunc = (u8) sum_full;
|
||||
int sum_full = cpu->a + value + carry;
|
||||
u8 sum_trunc = (u8) sum_full;
|
||||
if (sum_trunc == 0) {
|
||||
set_flag(cpu, FLAG_ZERO);
|
||||
} else {
|
||||
|
@ -285,25 +291,21 @@ static void add(struct cpu *cpu, u8 value, int with_carry)
|
|||
|
||||
static void subtract(struct cpu *cpu, u8 value, int with_carry, int just_compare)
|
||||
{
|
||||
u8 sum_trunc;
|
||||
int sum_full = cpu->a - value;
|
||||
int carry = (with_carry && flag_isset(cpu, FLAG_CARRY)) ? 1 : 0;
|
||||
if (carry) {
|
||||
sum_full--;
|
||||
}
|
||||
sum_trunc = (u8) sum_full;
|
||||
int sum_full = cpu->a - value - carry;
|
||||
u8 sum_trunc = (u8) sum_full;
|
||||
if (!sum_trunc) {
|
||||
set_flag(cpu, FLAG_ZERO);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
}
|
||||
set_flag(cpu, FLAG_SIGN);
|
||||
if (value > cpu->a) {
|
||||
if (sum_full < 0) {
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_CARRY);
|
||||
}
|
||||
if (((cpu->a & 0xf) - (value & 0xf)) & 0x10) {
|
||||
if (((cpu->a & 0xf) - (value & 0xf) - carry) & 0x10) {
|
||||
set_flag(cpu, FLAG_HALF_CARRY);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||
|
@ -336,21 +338,48 @@ static u16 pop(struct cpu *cpu)
|
|||
|
||||
static void add16(struct cpu *cpu, u16 src)
|
||||
{
|
||||
clear_flag(cpu, FLAG_SIGN);
|
||||
int total = read_hl(cpu) + src; // promoted to int
|
||||
int trunc = total & 0xffff;
|
||||
clear_flag(cpu, FLAG_SIGN);
|
||||
if (total > 0xffff) {
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_CARRY);
|
||||
}
|
||||
if (((cpu->h & 0xf) + ((src >> 8) & 0xf)) & 0x10) {
|
||||
if (((read_hl(cpu) & 0xfff) + (src & 0xfff)) & 0x1000) {
|
||||
// true if carry from bit 11 to bit 12
|
||||
set_flag(cpu, FLAG_HALF_CARRY);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||
}
|
||||
|
||||
write_hl(cpu, total & 0xffff);
|
||||
write_hl(cpu, trunc);
|
||||
}
|
||||
|
||||
static void add_sp(struct cpu *cpu, u8 value)
|
||||
{
|
||||
int total = cpu->sp + (signed char) value;
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
clear_flag(cpu, FLAG_SIGN);
|
||||
if (total > 0xffff) {
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_CARRY);
|
||||
}
|
||||
cpu->sp = (u16) total;
|
||||
}
|
||||
|
||||
static void ld_hl_sp(struct cpu *cpu, u8 value)
|
||||
{
|
||||
int total = cpu->sp + (signed char) value;
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
clear_flag(cpu, FLAG_SIGN);
|
||||
if (total > 0xffff) {
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
} else {
|
||||
clear_flag(cpu, FLAG_CARRY);
|
||||
}
|
||||
write_hl(cpu, total);
|
||||
}
|
||||
|
||||
static u8 read_reg(struct cpu *cpu, int index)
|
||||
|
@ -407,6 +436,8 @@ static void extended_insn(struct cpu *cpu, u8 insn)
|
|||
srl,
|
||||
};
|
||||
|
||||
// rl, sla, sra
|
||||
|
||||
#ifdef GB6_DEBUG
|
||||
printf(" %s\n", instructions[insn + 0x100].format);
|
||||
#endif
|
||||
|
@ -473,6 +504,24 @@ static void daa(struct cpu *cpu)
|
|||
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||
}
|
||||
|
||||
static void scf(struct cpu *cpu)
|
||||
{
|
||||
clear_flag(cpu, FLAG_SIGN);
|
||||
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
}
|
||||
|
||||
static void ccf(struct cpu *cpu)
|
||||
{
|
||||
clear_flag(cpu, FLAG_SIGN);
|
||||
clear_flag(cpu, FLAG_HALF_CARRY);
|
||||
if (flag_isset(cpu, FLAG_CARRY)) {
|
||||
clear_flag(cpu, FLAG_CARRY);
|
||||
} else {
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
}
|
||||
}
|
||||
|
||||
static u16 handlers[] = { 0x40, 0x48, 0x50, 0x58, 0x60 };
|
||||
|
||||
static u16 check_interrupts(struct cpu *cpu)
|
||||
|
@ -508,10 +557,15 @@ void cpu_step(struct cpu *cpu)
|
|||
intr_dest = check_interrupts(cpu);
|
||||
if (intr_dest) {
|
||||
push(cpu, cpu->pc);
|
||||
cpu->halted = 0;
|
||||
cpu->pc = intr_dest;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpu->halted) {
|
||||
return;
|
||||
}
|
||||
|
||||
u8 opc = dmg_read(cpu->dmg, cpu->pc);
|
||||
#ifdef GB6_DEBUG
|
||||
printf("0x%04x %s\n", cpu->pc, instructions[opc].format);
|
||||
|
@ -531,6 +585,7 @@ void cpu_step(struct cpu *cpu)
|
|||
break;
|
||||
case 0x0f: // RRCA
|
||||
cpu->a = rrc(cpu, cpu->a);
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
break;
|
||||
case 0x10: // STOP
|
||||
cpu->pc++;
|
||||
|
@ -541,6 +596,7 @@ void cpu_step(struct cpu *cpu)
|
|||
break;
|
||||
case 0x07: // RLCA
|
||||
cpu->a = rlc(cpu, cpu->a);
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
break;
|
||||
case 0x08: // LD (a16),SP
|
||||
write16(cpu, read16(cpu, cpu->pc), cpu->sp);
|
||||
|
@ -554,16 +610,18 @@ void cpu_step(struct cpu *cpu)
|
|||
break;
|
||||
case 0x17: // RLA
|
||||
cpu->a = rotate_left(cpu, cpu->a);
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
break;
|
||||
case 0x1f: // RRA
|
||||
cpu->a = rotate_right(cpu, cpu->a);
|
||||
clear_flag(cpu, FLAG_ZERO);
|
||||
break;
|
||||
|
||||
case 0x37: // SCF
|
||||
set_flag(cpu, FLAG_CARRY);
|
||||
scf(cpu);
|
||||
break;
|
||||
case 0x3f: // CCF
|
||||
clear_flag(cpu, FLAG_CARRY);
|
||||
ccf(cpu);
|
||||
break;
|
||||
|
||||
// incs and decs
|
||||
|
@ -944,6 +1002,7 @@ void cpu_step(struct cpu *cpu)
|
|||
break;
|
||||
|
||||
case 0x76: // HALT
|
||||
//cpu->halted = 1;
|
||||
break;
|
||||
|
||||
case 0xc1: // POP BC
|
||||
|
@ -993,6 +1052,10 @@ void cpu_step(struct cpu *cpu)
|
|||
case 0xe5: // PUSH HL
|
||||
push(cpu, read_hl(cpu));
|
||||
break;
|
||||
case 0xe8:
|
||||
add_sp(cpu, read8(cpu, cpu->pc));
|
||||
cpu->pc++;
|
||||
break;
|
||||
case 0xe9: // JP HL
|
||||
cpu->pc = read_hl(cpu);
|
||||
break;
|
||||
|
@ -1018,7 +1081,7 @@ void cpu_step(struct cpu *cpu)
|
|||
push(cpu, read_af(cpu));
|
||||
break;
|
||||
case 0xf8: // LD HL, SP+i8
|
||||
write_hl(cpu, cpu->sp + (signed) read8(cpu, cpu->pc));
|
||||
ld_hl_sp(cpu, read8(cpu, cpu->pc));
|
||||
cpu->pc++;
|
||||
break;
|
||||
case 0xf9: // LD SP, HL
|
||||
|
|
|
@ -20,6 +20,8 @@ struct cpu
|
|||
u32 cycle_count;
|
||||
u8 interrupt_enable;
|
||||
|
||||
u8 halted;
|
||||
|
||||
struct dmg *dmg;
|
||||
// u8 (*mem_read)(void *, u16);
|
||||
// void (*mem_write)(void *, u16, u8);
|
||||
|
|
33
src/dmg.c
33
src/dmg.c
|
@ -40,7 +40,7 @@ void dmg_set_button(struct dmg *dmg, int field, int button, int pressed)
|
|||
|
||||
static u8 get_button_state(struct dmg *dmg)
|
||||
{
|
||||
u8 ret = 0;
|
||||
u8 ret = 0xf0;
|
||||
if (dmg->action_selected) {
|
||||
ret |= dmg->action_buttons;
|
||||
}
|
||||
|
@ -50,8 +50,6 @@ static u8 get_button_state(struct dmg *dmg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int counter;
|
||||
|
||||
u8 dmg_read(void *_dmg, u16 address)
|
||||
{
|
||||
struct dmg *dmg = (struct dmg *) _dmg;
|
||||
|
@ -82,8 +80,13 @@ u8 dmg_read(void *_dmg, u16 address)
|
|||
} else if (address == 0xff00) {
|
||||
return get_button_state(dmg);
|
||||
} else if (address == REG_TIMER_DIV) {
|
||||
counter++;
|
||||
return counter;
|
||||
return (dmg->timer_div & 0xff00) >> 8;
|
||||
} else if (address == REG_TIMER_COUNT) {
|
||||
return dmg->timer_count;
|
||||
} else if (address == REG_TIMER_MOD) {
|
||||
return dmg->timer_mod;
|
||||
} else if (address == REG_TIMER_CONTROL) {
|
||||
return dmg->timer_control;
|
||||
} else if (address == 0xff0f) {
|
||||
return dmg->interrupt_requested;
|
||||
} else if (address == 0xffff) {
|
||||
|
@ -116,6 +119,17 @@ void dmg_write(void *_dmg, u16 address, u8 data)
|
|||
} else if (address < 0xe000) {
|
||||
// printf("write ram %04x %02x\n", address, data);
|
||||
dmg->main_ram[address - 0xc000] = data;
|
||||
} else if (address == REG_TIMER_DIV) {
|
||||
dmg->timer_div = 0;
|
||||
} else if (address == REG_TIMER_COUNT) {
|
||||
printf("write timer count\n");
|
||||
dmg->timer_count = data;
|
||||
} else if (address == REG_TIMER_MOD) {
|
||||
printf("write timer mod\n");
|
||||
dmg->timer_mod = data;
|
||||
} else if (address == REG_TIMER_CONTROL) {
|
||||
printf("write timer control\n");
|
||||
dmg->timer_control = data;
|
||||
} else if (address == 0xFF46) {
|
||||
u16 src = data << 8;
|
||||
int k = 0;
|
||||
|
@ -248,15 +262,14 @@ static void render_objs(struct dmg *dmg)
|
|||
|
||||
static void timer_step(struct dmg *dmg)
|
||||
{
|
||||
dmg->timer_div++;
|
||||
return;
|
||||
|
||||
if (!(dmg_read(dmg, REG_TIMER_CONTROL) & TIMER_CONTROL_ENABLED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int passed = dmg->cpu->cycle_count - dmg->last_timer_update;
|
||||
// TODO
|
||||
if (passed < 10000) {
|
||||
return;
|
||||
}
|
||||
|
||||
u8 counter = dmg_read(dmg, REG_TIMER_COUNT);
|
||||
u8 modulo = dmg_read(dmg, REG_TIMER_MOD);
|
||||
|
@ -278,7 +291,7 @@ void dmg_step(void *_dmg)
|
|||
// order of dependencies? i think cpu needs to step first then update
|
||||
// all other hw
|
||||
cpu_step(dmg->cpu);
|
||||
// timer_step(dmg);
|
||||
timer_step(dmg);
|
||||
|
||||
// each line takes 456 cycles
|
||||
int cycle_diff = dmg->cpu->cycle_count - dmg->last_lcd_update;
|
||||
|
|
|
@ -36,12 +36,16 @@ struct dmg {
|
|||
u32 last_lcd_update;
|
||||
u32 last_timer_update;
|
||||
int joypad_selected;
|
||||
int action_selected; // non-0 if A/B/start/select selected, 0 for directions
|
||||
int action_selected;
|
||||
u8 interrupt_enabled;
|
||||
u8 interrupt_requested;
|
||||
|
||||
u8 joypad;
|
||||
u8 action_buttons;
|
||||
u16 timer_div;
|
||||
u8 timer_count;
|
||||
u8 timer_mod;
|
||||
u8 timer_control;
|
||||
};
|
||||
|
||||
void dmg_new(struct dmg *dmg, struct cpu *cpu, struct rom *rom, struct lcd *lcd);
|
||||
|
|
Loading…
Reference in New Issue