1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use super::*;

/// "Window Horizontal Edges"
///
/// Sets the horizontal edges of windows 0 and 1.
#[cfg(feature = "unsafe_addresses")]
pub const WIN_HORIZONTAL: WriteOnlyVolAddr<WinHorizontal> =
  unsafe { WriteOnlyVolAddr::new(0x0400_0040) };

/// Defines the horizontal bounds of Window 0 and 1.
///
/// The right side is **exclusive**, the left side is **inclusive**.
///
/// If the right side is greater than 240, or if the left side is greater than
/// the right side, then the right side counts as being 240.
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct WinHorizontal(u32);

#[rustfmt::skip]
#[allow(missing_docs)]
impl WinHorizontal {
  pub_const_fn_new_zero!();
  unsigned_bits_u32!(0..=7, win0_right, with_win0_right, set_win0_right);
  unsigned_bits_u32!(8..=15, win0_left, with_win0_left, set_win0_left);
  unsigned_bits_u32!(16..=23, win1_right, with_win1_right, set_win1_right);
  unsigned_bits_u32!(24..=31, win1_left, with_win1_left, set_win1_left);
}

/// "Window Vertical Edges"
///
/// Sets the vertical edges of windows 0 and 1.
#[cfg(feature = "unsafe_addresses")]
pub const WIN_VERTICAL: WriteOnlyVolAddr<WinVertical> =
  unsafe { WriteOnlyVolAddr::new(0x0400_0044) };

/// Defines the vertical bounds of Window 0 and 1.
///
/// The bottom side is **exclusive**, the top side is **inclusive**.
///
/// If the bottom side is greater than 160, or if the top side is greater than
/// the bottom side, then the bottom side counts as being 160.
///
/// (Remember that the GBA counts Y coordinates with 0 as the top.)
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct WinVertical(u32);

#[rustfmt::skip]
#[allow(missing_docs)]
impl WinVertical {
  pub_const_fn_new_zero!();
  unsigned_bits_u32!(0..=7, win0_bottom, with_win0_bottom, set_win0_bottom);
  unsigned_bits_u32!(8..=15, win0_top, with_win0_top, set_win0_top);
  unsigned_bits_u32!(16..=23, win1_bottom, with_win1_bottom, set_win1_bottom);
  unsigned_bits_u32!(24..=31, win1_top, with_win1_top, set_win1_top);
}

/// "Window Controls"
///
/// Determines what layers are drawn on the "inside" and "outside" of each
/// window.
#[cfg(feature = "unsafe_addresses")]
pub const WIN_CONTROL: SimpleVolAddr<WindowControlValue> =
  unsafe { SimpleVolAddr::new(0x0400_0048) };

/// Lets you set what layers appear inside and outside of the window areas.
///
/// * bg / obj / effect in win 0/1: These bits let you enable bg0/1/2/3 as well
///   as obj display and/or color special effect **inside** windows 0 and/or 1.
/// * bg / obj / effect outside win: These bits let you enable bg0/1/2/3 as well
///   as obj display and/or color special effect **outside** of all windows.
/// * bg / obj / effect in obj win: These bits let you enable bg0/1/2/3 as well
///   as obj display and/or color special effect **inside** of the OBJ window.
///
/// The obj window doesn't actually have a simple area control like win0 and
/// win1 do. Instead, the OBJ window includes the transparent pixels of any OBJ
/// with an ObjMode set to "ObjWindow" (and the non-transparent pixels of such
/// OBJ entries aren't drawn).
///
/// If more than one window is enabled and would draw a pixel, the priority is
/// for win0, then win1, then the obj window, then anything outside the windows.
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct WindowControlValue(u32);

#[rustfmt::skip]
#[allow(missing_docs)]
impl WindowControlValue {
  pub_const_fn_new_zero!();
  bool_bit_u32!(0, bg0_in_win0, with_bg0_in_win0, set_bg0_in_win0);
  bool_bit_u32!(1, bg1_in_win0, with_bg1_in_win0, set_bg1_in_win0);
  bool_bit_u32!(2, bg2_in_win0, with_bg2_in_win0, set_bg2_in_win0);
  bool_bit_u32!(3, bg3_in_win0, with_bg3_in_win0, set_bg3_in_win0);
  bool_bit_u32!(4, obj_in_win0, with_obj_in_win0, set_obj_in_win0);
  bool_bit_u32!(5, color_effect_in_win0, with_color_effect_in_win0, set_color_effect_in_win0);
  //
  bool_bit_u32!(8, bg0_in_win1, with_bg0_in_win1, set_bg0_in_win1);
  bool_bit_u32!(9, bg1_in_win1, with_bg1_in_win1, set_bg1_in_win1);
  bool_bit_u32!(10, bg2_in_win1, with_bg2_in_win1, set_bg2_in_win1);
  bool_bit_u32!(11, bg3_in_win1, with_bg3_in_win1, set_bg3_in_win1);
  bool_bit_u32!(12, obj_in_win1, with_obj_in_win1, set_obj_in_win1);
  bool_bit_u32!(13, color_effect_in_win1, with_color_effect_in_win1, set_color_effect_in_win1);
  //
  bool_bit_u32!(16, bg0_outside_win, with_bg0_outside_win, set_bg0_outside_win);
  bool_bit_u32!(17, bg1_outside_win, with_bg1_outside_win, set_bg1_outside_win);
  bool_bit_u32!(18, bg2_outside_win, with_bg2_outside_win, set_bg2_outside_win);
  bool_bit_u32!(19, bg3_outside_win, with_bg3_outside_win, set_bg3_outside_win);
  bool_bit_u32!(20, obj_outside_win, with_obj_outside_win, set_obj_outside_win);
  bool_bit_u32!(21, color_effect_outside_win, with_color_effect_outside_win, set_color_effect_outside_win);
  //
  bool_bit_u32!(16, bg0_in_obj_win, with_bg0_in_obj_win, set_bg0_in_obj_win);
  bool_bit_u32!(17, bg1_in_obj_win, with_bg1_in_obj_win, set_bg1_in_obj_win);
  bool_bit_u32!(18, bg2_in_obj_win, with_bg2_in_obj_win, set_bg2_in_obj_win);
  bool_bit_u32!(19, bg3_in_obj_win, with_bg3_in_obj_win, set_bg3_in_obj_win);
  bool_bit_u32!(20, obj_in_obj_win, with_obj_in_obj_win, set_obj_in_obj_win);
  bool_bit_u32!(21, color_effect_in_obj_win, with_color_effect_in_obj_win, set_color_effect_in_obj_win);
}