2015-02-27 22:24:26 +01:00
|
|
|
open Printf
|
|
|
|
|
|
|
|
(** http://bgb.bircd.org/pandocs.htm#cpuregistersandflags
|
|
|
|
http://gameboy.mongenel.com/dmg/lesson1.html *)
|
2015-02-24 17:30:14 +01:00
|
|
|
|
|
|
|
type registers = {
|
2015-02-27 22:24:26 +01:00
|
|
|
mutable a : char; (* accumulator *)
|
|
|
|
mutable f : char; (* flags *)
|
|
|
|
mutable b : char;
|
|
|
|
mutable c : char;
|
|
|
|
mutable d : char;
|
|
|
|
mutable e : char;
|
|
|
|
mutable h : char;
|
|
|
|
mutable l : char;
|
|
|
|
|
|
|
|
mutable sp : int; (* stack pointer *)
|
|
|
|
mutable pc : int; (* program counter *)
|
2015-02-24 17:30:14 +01:00
|
|
|
}
|
|
|
|
|
2015-02-27 22:24:26 +01:00
|
|
|
(* type flags = {
|
2015-02-27 14:00:38 +01:00
|
|
|
z : bool; (* zero *)
|
|
|
|
n : bool; (* substraction *)
|
|
|
|
h : bool; (* half-carry *)
|
|
|
|
cy : bool; (* carry *)
|
2015-02-27 22:24:26 +01:00
|
|
|
} *)
|
2015-02-24 17:30:14 +01:00
|
|
|
|
|
|
|
type t = {
|
|
|
|
reg : registers;
|
2015-02-27 22:24:26 +01:00
|
|
|
mutable cycles : int;
|
2015-02-24 17:30:14 +01:00
|
|
|
}
|
2015-02-27 22:24:26 +01:00
|
|
|
|
|
|
|
(** http://bgb.bircd.org/pandocs.htm#powerupsequence *)
|
|
|
|
let init_registers =
|
|
|
|
{
|
|
|
|
a = '\x00';
|
|
|
|
f = '\x00';
|
|
|
|
b = '\x00';
|
|
|
|
c = '\x00';
|
|
|
|
d = '\x00';
|
|
|
|
e = '\x00';
|
|
|
|
h = '\x00';
|
|
|
|
l = '\x00';
|
|
|
|
sp = 0xFFFE;
|
|
|
|
pc = 0x0100;
|
|
|
|
}
|
|
|
|
|
|
|
|
let init_cpu =
|
|
|
|
{ reg = init_registers; cycles = 0 }
|
|
|
|
|
|
|
|
let inc_pc cpu count =
|
|
|
|
cpu.reg.pc <- cpu.reg.pc + count
|
|
|
|
|
|
|
|
let inc_cycles cpu count =
|
|
|
|
cpu.cycles <- cpu.cycles + count
|
|
|
|
|
2015-02-28 00:25:10 +01:00
|
|
|
let merge_bytes low high =
|
|
|
|
(int_of_char high) * 256 + (int_of_char low)
|
|
|
|
|
|
|
|
let split_2B x =
|
|
|
|
let low = x mod 256 |> char_of_int in
|
|
|
|
let high = x / 256 |> char_of_int in
|
|
|
|
(high, low)
|
|
|
|
|
2015-03-22 16:57:03 +01:00
|
|
|
let read_2B m addr =
|
|
|
|
let low = Memory.get m addr in
|
|
|
|
let high = Memory.get m (addr + 1) in
|
2015-02-28 00:25:10 +01:00
|
|
|
merge_bytes low high
|
|
|
|
|
|
|
|
let inc_BC cpu =
|
|
|
|
let v = merge_bytes cpu.reg.c cpu.reg.b in
|
|
|
|
let low, high = split_2B (v + 1) in
|
|
|
|
cpu.reg.c <- low;
|
|
|
|
cpu.reg.b <- high
|
2015-02-27 22:24:26 +01:00
|
|
|
|
|
|
|
(** http://imrannazar.com/GameBoy-Z80-Opcode-Map *)
|
2015-03-22 16:57:03 +01:00
|
|
|
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
|
2015-02-28 00:25:10 +01:00
|
|
|
(* Hexa.print_slice cartridge.full_rom cpu.reg.pc (cpu.reg.pc + 7); *)
|
2015-03-22 16:57:03 +01:00
|
|
|
match Memory.get mem cpu.reg.pc with
|
2015-02-28 00:25:10 +01:00
|
|
|
| '\x00' -> printf " NOP\n";
|
|
|
|
inc_pc cpu 1; inc_cycles cpu 4
|
|
|
|
|
|
|
|
| '\x03' -> printf " INC \tBC\n";
|
|
|
|
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;
|
|
|
|
inc_pc cpu 2; inc_cycles cpu 8
|
|
|
|
|
|
|
|
| '\xAF' -> printf " XOR \tA, A\n";
|
|
|
|
let int_A = int_of_char cpu.reg.a in
|
|
|
|
cpu.reg.a <- char_of_int @@ int_A lxor int_A;
|
|
|
|
inc_pc cpu 1; inc_cycles cpu 4
|
|
|
|
|
2015-03-22 16:57:03 +01:00
|
|
|
| '\xC3' -> let addr = read_2B mem (cpu.reg.pc + 1) in
|
2015-02-28 00:25:10 +01:00
|
|
|
printf " JP \t0x%04X\n" addr;
|
|
|
|
cpu.reg.pc <- addr; inc_cycles cpu 16
|
|
|
|
|
2015-03-05 23:00:28 +01:00
|
|
|
| '\xE0' -> printf " LDH \t(0xFF%02X), A\n" (int_of_char n);
|
2015-03-22 16:57:03 +01:00
|
|
|
Memory.set mem (0xFF00 + (int_of_char n)) cpu.reg.a;
|
2015-03-05 23:00:28 +01:00
|
|
|
inc_pc cpu 2; inc_cycles cpu 12
|
|
|
|
|
|
|
|
| '\xF0' -> printf " LDH \tA, (0xFF%02X)\n" (int_of_char n);
|
2015-03-22 16:57:03 +01:00
|
|
|
cpu.reg.a = Memory.get mem (0xFF00 + (int_of_char n));
|
2015-02-28 00:25:10 +01:00
|
|
|
inc_pc cpu 2; inc_cycles cpu 12
|
|
|
|
|
|
|
|
| '\xF3' -> printf " DI\n";
|
|
|
|
(* fixme *)
|
|
|
|
inc_pc cpu 1; inc_cycles cpu 4
|
|
|
|
|
|
|
|
| _ as x -> eprintf "opcode %02X\n" (int_of_char x); failwith "Unimplemented opcode."
|