Add flag register.
This commit is contained in:
parent
e5bc9bc4db
commit
f3916dfd64
55
src/cpu.ml
55
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."
|
||||
|
|
|
@ -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."
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue