oboy/src/core/interrupt.ml

67 lines
1.4 KiB
OCaml
Raw Normal View History

2016-02-28 23:41:06 +01:00
(**
* 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.
*)
2016-03-01 23:15:56 +01:00
(** Interrupt Master Enable flag *)
let gIME = ref false
let ie_addr = 0xFFFF
let if_addr = 0xFFF0
2016-02-28 23:41:06 +01:00
type t =
2016-02-29 23:07:42 +01:00
| V_Blank
| LCD_Stat
| Timer
| Serial
| Joypad
2016-02-28 23:41:06 +01:00
2016-03-01 23:15:56 +01:00
let get_flag_mask = function
| V_Blank -> 0b00000001
| LCD_Stat -> 0b00000010
| Timer -> 0b00000100
| Serial -> 0b00001000
| Joypad -> 0b00010000
2016-02-29 23:07:42 +01:00
(** Return the list of interrupt flags sorted by priority. *)
2016-02-28 23:41:06 +01:00
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
2016-02-29 23:07:42 +01:00
| _ -> List.rev accu in
2016-02-28 23:41:06 +01:00
get_flag byte 0 []
2016-03-01 23:15:56 +01:00
(** 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