oboy/src/cartridge.ml

56 lines
1.5 KiB
OCaml

open Unix
open Printf
(** http://bgb.bircd.org/pandocs.htm#thecartridgeheader *)
type memory_bank_controller =
| ROM_ONLY
| MBC1
type t = {
nintendo_logo : bytes;
title : string;
(* mem_type : memory_bank_controller;
rom_size : int;
ram_size : int;
header_checksum : bytes;
global_checksum : bytes; *)
}
(** The Nintendo logo is a checksum in the header *)
let check_nintendo_logo cartridge =
let reference = Bytes.of_string
"\xCE\xED\x66\x66\xCC\x0D\x00\x0B\x03\x73\x00\x83\x00\x0C\x00\x0D\
\x00\x08\x11\x1F\x88\x89\x00\x0E\xDC\xCC\x6E\xE6\xDD\xDD\xD9\x99\
\xBB\xBB\x67\x63\x6E\x0E\xEC\xCC\xDD\xDC\x99\x9F\xBB\xB9\x33\x3E" in
(Bytes.compare cartridge.nintendo_logo reference) == 0
exception Read_error
let read_cartridge file =
try
let fd = openfile file [Unix.O_RDONLY] 0o644 in
try
let nin_logo_offset = 0x0104 in
if (lseek fd nin_logo_offset SEEK_SET) != nin_logo_offset
then raise Read_error;
let nin_logo_size = 48 in
let nintendo_logo = Bytes.create nin_logo_size in
if (read fd nintendo_logo 0 nin_logo_size) != nin_logo_size
then raise Read_error;
let title_size = 16 in
let title_b = Bytes.create title_size in
if (read fd title_b 0 title_size) != title_size
then raise Read_error;
let title = Bytes.to_string title_b in
Unix.close fd;
Some { nintendo_logo; title }
with Read_error -> Unix.close fd; None
with Unix_error(err, cmd, msg) -> None