Basic support for CPU opcodes.
Support for 2 opcodes: nop and jump. These are the first opcodes encountered in Super Mario Land.
This commit is contained in:
parent
fa09906bcb
commit
b2c7e7b947
68
src/cpu.ml
68
src/cpu.ml
|
@ -1,26 +1,68 @@
|
||||||
(** http://bgb.bircd.org/pandocs.htm#cpuregistersandflags *)
|
open Printf
|
||||||
|
|
||||||
|
(** http://bgb.bircd.org/pandocs.htm#cpuregistersandflags
|
||||||
|
http://gameboy.mongenel.com/dmg/lesson1.html *)
|
||||||
|
|
||||||
type registers = {
|
type registers = {
|
||||||
a : char; (* accumulator *)
|
mutable a : char; (* accumulator *)
|
||||||
b : char;
|
mutable f : char; (* flags *)
|
||||||
c : char;
|
mutable b : char;
|
||||||
d : char;
|
mutable c : char;
|
||||||
e : char;
|
mutable d : char;
|
||||||
h : char;
|
mutable e : char;
|
||||||
l : char;
|
mutable h : char;
|
||||||
|
mutable l : char;
|
||||||
|
|
||||||
sp : int; (* stack pointer *)
|
mutable sp : int; (* stack pointer *)
|
||||||
pc : int; (* program counter *)
|
mutable pc : int; (* program counter *)
|
||||||
}
|
}
|
||||||
|
|
||||||
type flags = {
|
(* type flags = {
|
||||||
z : bool; (* zero *)
|
z : bool; (* zero *)
|
||||||
n : bool; (* substraction *)
|
n : bool; (* substraction *)
|
||||||
h : bool; (* half-carry *)
|
h : bool; (* half-carry *)
|
||||||
cy : bool; (* carry *)
|
cy : bool; (* carry *)
|
||||||
}
|
} *)
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
reg : registers;
|
reg : registers;
|
||||||
flags : flags;
|
mutable cycles : int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(** 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
|
||||||
|
|
||||||
|
let read_2B b addr =
|
||||||
|
let low = Bytes.get b addr in
|
||||||
|
let high = Bytes.get b (addr + 1) in
|
||||||
|
(int_of_char high) * 256 + (int_of_char low)
|
||||||
|
|
||||||
|
(** http://imrannazar.com/GameBoy-Z80-Opcode-Map *)
|
||||||
|
let run cpu (cartridge: Cartridge.t) =
|
||||||
|
(* Hexa.print_slice cartridge.full_rom cpu.reg.pc (cpu.reg.pc + 7) ~width:16; *)
|
||||||
|
match Bytes.get cartridge.full_rom cpu.reg.pc with
|
||||||
|
| '\x00' -> printf " nop\n"; inc_pc cpu 1; inc_cycles cpu 4
|
||||||
|
| '\xC3' -> let addr = read_2B cartridge.full_rom (cpu.reg.pc + 1) in
|
||||||
|
printf " jp 0x%02x\n" addr; cpu.reg.pc <- addr; inc_cycles cpu 16
|
||||||
|
| _ as x -> eprintf "OpCode %02X\n" (int_of_char x); failwith "Unimplemented opcode."
|
||||||
|
|
22
src/hexa.ml
22
src/hexa.ml
|
@ -1,14 +1,14 @@
|
||||||
open Printf
|
open Printf
|
||||||
|
|
||||||
let print_bytes b ?(width=8) =
|
let rec print_slice ?(width=8) b start last =
|
||||||
|
if start < last then
|
||||||
|
let max = min (start + width - 1) last in
|
||||||
|
for i = start to max do
|
||||||
|
printf "%02X " (Bytes.get b i |> int_of_char)
|
||||||
|
done;
|
||||||
|
print_newline ();
|
||||||
|
print_slice ~width b (start + width) last
|
||||||
|
|
||||||
|
let print_bytes ?(width=8) b width =
|
||||||
let l = Bytes.length b in
|
let l = Bytes.length b in
|
||||||
let rec print_line b start last =
|
print_slice ~width b 0 l
|
||||||
if start < last then
|
|
||||||
let max = min (start + width - 1) last in
|
|
||||||
for i = start to max do
|
|
||||||
printf "%02X " (Bytes.get b i |> int_of_char)
|
|
||||||
done;
|
|
||||||
print_newline ();
|
|
||||||
print_line b (start + width) last
|
|
||||||
in
|
|
||||||
print_line b 0 l
|
|
||||||
|
|
17
src/oboy.ml
17
src/oboy.ml
|
@ -1,5 +1,9 @@
|
||||||
open Printf
|
open Printf
|
||||||
|
|
||||||
|
let rec run (cpu: Cpu.t) (cartridge: Cartridge.t) =
|
||||||
|
Cpu.run cpu cartridge;
|
||||||
|
run cpu cartridge
|
||||||
|
|
||||||
(** Power up sequence
|
(** Power up sequence
|
||||||
http://bgb.bircd.org/pandocs.htm#powerupsequence *)
|
http://bgb.bircd.org/pandocs.htm#powerupsequence *)
|
||||||
let power_up cartridge =
|
let power_up cartridge =
|
||||||
|
@ -10,12 +14,19 @@ let power_up cartridge =
|
||||||
print_endline "Valid ROM.";
|
print_endline "Valid ROM.";
|
||||||
printf "Title: %s\n" cartridge.title;
|
printf "Title: %s\n" cartridge.title;
|
||||||
printf "ROM size: %iKB\n" cartridge.rom_size;
|
printf "ROM size: %iKB\n" cartridge.rom_size;
|
||||||
printf "RAM size: %iKB\n" cartridge.ram_size
|
printf "RAM size: %iKB\n" cartridge.ram_size;
|
||||||
|
|
||||||
|
let cpu = Cpu.init_cpu in
|
||||||
|
run cpu cartridge
|
||||||
|
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
if Array.length Sys.argv < 2
|
if Array.length Sys.argv < 2 then
|
||||||
then print_endline "Please specify a ROM.";
|
begin
|
||||||
|
prerr_endline "Please specify a ROM.";
|
||||||
|
eprintf "Usage: %s path/to/rom\n" Sys.argv.(0);
|
||||||
|
exit 1;
|
||||||
|
end;
|
||||||
|
|
||||||
let cartridge = Cartridge.read_cartridge Sys.argv.(1) in
|
let cartridge = Cartridge.read_cartridge Sys.argv.(1) in
|
||||||
match cartridge with
|
match cartridge with
|
||||||
|
|
Loading…
Reference in a new issue