Implement timers
This commit is contained in:
parent
6c7544dffb
commit
67093196ea
3 changed files with 102 additions and 12 deletions
|
@ -1,22 +1,34 @@
|
|||
open Bytes
|
||||
open Printf
|
||||
|
||||
(** http://bgb.bircd.org/pandocs.htm#memorymap
|
||||
http://imrannazar.com/GameBoy-Emulation-in-JavaScript:-Memory *)
|
||||
(** @see http://bgb.bircd.org/pandocs.htm#memorymap
|
||||
@see http://imrannazar.com/GameBoy-Emulation-in-JavaScript:-Memory *)
|
||||
|
||||
(** Common addresses *)
|
||||
let gDIV = 0xFF04 (** divider register *)
|
||||
let gTIMA = 0xFF05 (** timer counter *)
|
||||
let gTMA = 0xFF06 (** timer modulo *)
|
||||
let gTAC = 0xFF07 (** timer control *)
|
||||
|
||||
type map = {
|
||||
rom_bank_00 : bytes; (* cartridge, 16KB *)
|
||||
rom_bank_01 : bytes; (* additional bank, 16KB *)
|
||||
vram : bytes; (* Video RAM, 8KB *)
|
||||
vram : bytes; (* Video RAM, 8KB *)
|
||||
wram_bank_0 : bytes; (* work RAM, 4KB *)
|
||||
wram_bank_1 : bytes; (* work RAM, 4KB *)
|
||||
io : bytes; (* I/O ports *)
|
||||
hram : bytes; (* High RAM, 8KB *)
|
||||
interrupt : bytes; (* Interrupt Enable Register *)
|
||||
io : bytes; (* I/O ports *)
|
||||
hram : bytes; (* High RAM, 8KB *)
|
||||
interrupt : bytes; (* Interrupt Enable Register *)
|
||||
}
|
||||
|
||||
type t = {
|
||||
map : map;
|
||||
timer_div : Timer.t;
|
||||
tima : Timer.t;
|
||||
}
|
||||
|
||||
let init (cartridge: Cartridge.t) =
|
||||
{
|
||||
let map = {
|
||||
rom_bank_00 = sub cartridge.full_rom 0 0x4000;
|
||||
rom_bank_01 = create 0x4000;
|
||||
vram = create 0x2000;
|
||||
|
@ -25,7 +37,19 @@ let init (cartridge: Cartridge.t) =
|
|||
io = create 0x0080;
|
||||
hram = create 0x2000;
|
||||
interrupt = create 1
|
||||
}
|
||||
} in
|
||||
|
||||
(** Init register values
|
||||
@see http://bgb.bircd.org/pandocs.htm#powerupsequence *)
|
||||
let zero = char_of_int 0 in
|
||||
set map.io 0x05 zero; (* TIMA, 0xFF05 *)
|
||||
set map.io 0x06 zero; (* TMA, 0xFF06 *)
|
||||
set map.io 0x07 zero; (* TAC, 0xFF07 *)
|
||||
|
||||
let timer_div = Timer.create 16384 true in
|
||||
let tima = Timer.create_tima 0 in
|
||||
|
||||
{ map; timer_div; tima; }
|
||||
|
||||
let get_mem_bank mem addr =
|
||||
match addr with
|
||||
|
@ -50,3 +74,28 @@ let get mem addr =
|
|||
let set mem addr c =
|
||||
let m, x = get_mem_bank mem addr in
|
||||
set m x c
|
||||
|
||||
(** Increment byte in memory, wrap value in case of overflow *)
|
||||
let inc mem addr =
|
||||
let m, x = get_mem_bank mem addr in
|
||||
let value = Bytes.get m x |> int_of_char in
|
||||
let inc_value = value + 1 in
|
||||
let overflow = inc_value > 0xFF in
|
||||
let c = inc_value mod 0x01FF |> char_of_int in
|
||||
Bytes.set m x c;
|
||||
overflow
|
||||
|
||||
|
||||
let update_timers mem cycles =
|
||||
let should_inc_div = Timer.update mem.timer_div cycles in
|
||||
if should_inc_div then ignore (inc mem.map gDIV);
|
||||
|
||||
let should_inc_tima = Timer.update mem.tima cycles in
|
||||
if should_inc_tima then begin
|
||||
let overflow = inc mem.map gTIMA in
|
||||
if overflow then begin
|
||||
let tma = get mem.map gTMA in
|
||||
set mem.map gTIMA tma
|
||||
(* TODO: INT 50 - Timer interupt *)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue