diff --git a/src/cartridge.ml b/src/cartridge.ml index ec83073..1ddc521 100644 --- a/src/cartridge.ml +++ b/src/cartridge.ml @@ -10,6 +10,7 @@ type memory_bank_controller = | MBC1 type t = { + full_rom : bytes; nintendo_logo : bytes; title : string; (* mem_type : memory_bank_controller; *) @@ -28,8 +29,7 @@ let check_nintendo_logo cartridge = (Bytes.compare cartridge.nintendo_logo reference) == 0 (** ROM size is expressed in KB *) -let get_ROM_size b = - match Bytes.get b 0 |> int_of_char with +let get_ROM_size = function | 0x00 -> 32 (* no ROM banking *) | 0x01 -> 64 (* 4 banks *) | 0x02 -> 128 (* 8 banks *) @@ -44,8 +44,7 @@ let get_ROM_size b = | _ -> raise Read_error (** RAM size is expressed in KB *) -let get_RAM_size b = - match Bytes.get b 0 |> int_of_char with +let get_RAM_size = function | 0x00 -> 0 | 0x01 -> 2 | 0x02 -> 8 @@ -55,41 +54,39 @@ let get_RAM_size b = let read_cartridge file = try - let fd = openfile file [Unix.O_RDONLY] 0o644 in + let ic = open_in_bin file in + + let file_size = in_channel_length ic in + + let full_rom = Bytes.create file_size in + really_input ic full_rom 0 file_size; + close_in ic; try - let nin_logo_offset = 0x0104 in - if (lseek fd nin_logo_offset SEEK_SET) != nin_logo_offset - then raise Read_error; (* Nintendo logo *) + let nin_logo_offset = 0x0104 in 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 nintendo_logo = Bytes.sub full_rom nin_logo_offset nin_logo_size in (* Title *) + let title_offset = 0x0134 in 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_b = Bytes.sub full_rom title_offset title_size in let title = Bytes.to_string title_b in (* ROM size *) - let byte = Bytes.create 1 in - let _ = lseek fd 4 SEEK_CUR in - if (read fd byte 0 1) != 1 - then raise Read_error; - let rom_size = get_ROM_size byte in + let rom_size_code = Bytes.get full_rom 0x0148 |> int_of_char in + let rom_size = get_ROM_size rom_size_code in (* RAM size *) - if (read fd byte 0 1) != 1 - then raise Read_error; - let ram_size = get_RAM_size byte in + let ram_size_code = Bytes.get full_rom 0x0149 |> int_of_char in + let ram_size = get_RAM_size ram_size_code in - Unix.close fd; - Some { nintendo_logo; title; rom_size; ram_size } + Some { full_rom; nintendo_logo; title; rom_size; ram_size } - with Read_error -> Unix.close fd; None + with + | Invalid_argument(msg) -> None (* This is triggered by Bytes.sub *) + | Read_error -> None - with Unix_error(err, cmd, msg) -> None + with Sys_error(msg) -> None