67 lines
1.4 KiB
OCaml
67 lines
1.4 KiB
OCaml
(**
|
|
* Copyright (c) 2016, Fabien Freling
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD 2-clause license found in the
|
|
* LICENSE file at the top level directory of this source tree.
|
|
*)
|
|
|
|
(** Interrupt Master Enable flag *)
|
|
let gIME = ref false
|
|
|
|
let ie_addr = 0xFFFF
|
|
let if_addr = 0xFFF0
|
|
|
|
type t =
|
|
| V_Blank
|
|
| LCD_Stat
|
|
| Timer
|
|
| Serial
|
|
| Joypad
|
|
|
|
|
|
let get_flag_mask = function
|
|
| V_Blank -> 0b00000001
|
|
| LCD_Stat -> 0b00000010
|
|
| Timer -> 0b00000100
|
|
| Serial -> 0b00001000
|
|
| Joypad -> 0b00010000
|
|
|
|
(** Return the list of interrupt flags sorted by priority. *)
|
|
let get_flags byte =
|
|
|
|
let nth_interrupt i =
|
|
match i with
|
|
| 0 -> V_Blank
|
|
| 1 -> LCD_Stat
|
|
| 2 -> Timer
|
|
| 3 -> Serial
|
|
| 4 -> Joypad
|
|
| _ -> failwith "Invalid interrupt index." in
|
|
|
|
let rec get_flag byte i accu =
|
|
match i with
|
|
| 0 | 1 | 2 | 3 | 4 ->
|
|
if Bit.is_set byte i then
|
|
let interrupt = nth_interrupt i in
|
|
get_flag byte (i + 1) (interrupt :: accu)
|
|
else
|
|
get_flag byte (i + 1) accu
|
|
| _ -> List.rev accu in
|
|
|
|
get_flag byte 0 []
|
|
|
|
|
|
(** Interrupt Enable *)
|
|
let get_IE mem = Memory.get mem ie_addr |> int_of_char
|
|
|
|
(** Interrupt Flag *)
|
|
let get_IF mem = Memory.get mem if_addr |> int_of_char
|
|
|
|
let reset_IF_flag flag mem =
|
|
let if_reg = get_IF mem in
|
|
let flag_mask = get_flag_mask flag in
|
|
let new_if_reg = if_reg land (lnot flag_mask) |> char_of_int in
|
|
Memory.set mem if_addr new_if_reg
|
|
|