diff --git a/src/cpu.ml b/src/cpu.ml index 8f42fc1..861e2e2 100644 --- a/src/cpu.ml +++ b/src/cpu.ml @@ -17,15 +17,16 @@ type registers = { mutable pc : int; (* program counter *) } -(* type flags = { - z : bool; (* zero *) - n : bool; (* substraction *) - h : bool; (* half-carry *) - cy : bool; (* carry *) -} *) + type flags = { + mutable z : bool; (* zero *) + mutable n : bool; (* substraction *) + mutable h : bool; (* half-carry *) + mutable c : bool; (* carry *) +} type t = { reg : registers; + flag : flags; mutable cycles : int; } @@ -44,8 +45,20 @@ let init_registers = pc = 0x0100; } +let init_flags = + { + z = false; n = false; h = false; c = false + } + let init_cpu = - { reg = init_registers; cycles = 0 } + { reg = init_registers; flag = init_flags; cycles = 0 } + +let update_flag_reg cpu = + let z = if cpu.flag.z then 0b10000000 else 0 in + let n = if cpu.flag.n then 0b01000000 else 0 in + let h = if cpu.flag.h then 0b00100000 else 0 in + let c = if cpu.flag.c then 0b00010000 else 0 in + cpu.reg.f <- char_of_int @@ z + n + h + c let inc_pc cpu count = cpu.reg.pc <- cpu.reg.pc + count @@ -72,10 +85,18 @@ let inc_BC cpu = cpu.reg.c <- low; cpu.reg.b <- high +let cmp_A cpu n = + let diff = int_of_char (cpu.reg.a) - n in + cpu.flag.z <- diff = 0; + cpu.flag.n <- true; + cpu.flag.h <- diff > 0x0F || diff < 0; + cpu.flag.c <- diff > 0xFF || diff < 0; + update_flag_reg cpu + (** http://imrannazar.com/GameBoy-Z80-Opcode-Map *) let run cpu (mem: Memory.map) = - let n = Memory.get mem (cpu.reg.pc + 1) in - let nn = Memory.get mem (cpu.reg.pc + 2) in + let n = Memory.get mem (cpu.reg.pc + 1) |> int_of_char in +(* let nn = Memory.get mem (cpu.reg.pc + 2) in *) (* Hexa.print_slice cartridge.full_rom cpu.reg.pc (cpu.reg.pc + 7); *) match Memory.get mem cpu.reg.pc with | '\x00' -> printf " NOP\n"; @@ -85,8 +106,8 @@ let run cpu (mem: Memory.map) = inc_BC cpu; inc_pc cpu 1; inc_cycles cpu 8 - | '\x3E' -> printf " LD \tA, 0x%02X\n" (int_of_char n); - cpu.reg.a <- n; + | '\x3E' -> printf " LD \tA, 0x%02X\n" n; + cpu.reg.a <- char_of_int(n); inc_pc cpu 2; inc_cycles cpu 8 | '\xAF' -> printf " XOR \tA, A\n"; @@ -98,16 +119,20 @@ let run cpu (mem: Memory.map) = printf " JP \t0x%04X\n" addr; cpu.reg.pc <- addr; inc_cycles cpu 16 - | '\xE0' -> printf " LDH \t(0xFF%02X), A\n" (int_of_char n); - Memory.set mem (0xFF00 + (int_of_char n)) cpu.reg.a; + | '\xE0' -> printf " LDH \t(0xFF%02X), A\n" n; + Memory.set mem (0xFF00 + n) cpu.reg.a; inc_pc cpu 2; inc_cycles cpu 12 - | '\xF0' -> printf " LDH \tA, (0xFF%02X)\n" (int_of_char n); - cpu.reg.a = Memory.get mem (0xFF00 + (int_of_char n)); + | '\xF0' -> printf " LDH \tA, (0xFF%02X)\n" n; + cpu.reg.a <- Memory.get mem (0xFF00 + n); inc_pc cpu 2; inc_cycles cpu 12 | '\xF3' -> printf " DI\n"; (* fixme *) inc_pc cpu 1; inc_cycles cpu 4 + | '\xFE' -> printf " CP\t0x%02X\n" n; + cmp_A cpu n; + inc_pc cpu 2; inc_cycles cpu 8 + | _ as x -> eprintf "opcode %02X\n" (int_of_char x); failwith "Unimplemented opcode." diff --git a/src/memory.ml b/src/memory.ml index 785c170..5bba426 100644 --- a/src/memory.ml +++ b/src/memory.ml @@ -8,6 +8,8 @@ type map = { rom_bank_01 : bytes; (* additional bank, 16KB *) vram : bytes; (* Video RAM, 8KB *) io : bytes; (* I/O ports *) + hram : bytes; (* High RAM, 8KB *) + interrupt : bytes; (* Interrupt Enable Register *) } let init (cartridge: Cartridge.t) = @@ -16,6 +18,8 @@ let init (cartridge: Cartridge.t) = rom_bank_01 = create 0x4000; vram = create 0x2000; io = create 0x0080; + hram = create 0x2000; + interrupt = create 1 } let get_mem_bank mem addr = @@ -25,6 +29,8 @@ let get_mem_bank mem addr = | x when x < 0xA000 -> mem.vram, (x - 0x8000) | x when x < 0xFF00 -> failwith "Unimplemented memory range." | x when x < 0xFF80 -> mem.io, x - 0xFF00 + | x when x < 0xFFFF -> mem.hram, x - 0xFF80 + | 0xFFFF -> mem.interrupt, 0 | _ -> failwith "Invalid memory range."