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
119
120
121
122
123
124
125
126
127
128
129
use super::*;

/// "Blend Control".
///
/// Allows the configuration of hardware color blending.
#[cfg(feature = "unsafe_addresses")]
pub const BLDCNT: SimpleVolAddr<BlendControlValue> =
  unsafe { SimpleVolAddr::new(0x0400_0050) };

/// This lets you configure hardware color blending.
///
/// There's three possible [`ColorSpecialEffect`] options you can enable: alpha
/// blending, increase brightness, and decrease brightness. You can also set no
/// effect to occur.
///
/// When selecting an effect, it uses the topmost pixel from all layers among
/// those enabled as a "1st target". If the effect is for alpha blending then it
/// will also then select a pixel to blend with from the topmost pixel among
/// those selected for "2nd target". However, the second pixel to alpha blend
/// _must_ be in the next lower priority layer from the first pixel.
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct BlendControlValue(u16);

#[rustfmt::skip]
#[allow(missing_docs)]
impl BlendControlValue {
  pub_const_fn_new_zero!();
  bool_bit_u16!(0, bg0_1st_target, with_bg0_1st_target, set_bg0_1st_target);
  bool_bit_u16!(1, bg1_1st_target, with_bg1_1st_target, set_bg1_1st_target);
  bool_bit_u16!(2, bg2_1st_target, with_bg2_1st_target, set_bg2_1st_target);
  bool_bit_u16!(3, bg3_1st_target, with_bg3_1st_target, set_bg3_1st_target);
  bool_bit_u16!(4, obj_1st_target, with_obj_1st_target, set_obj_1st_target);
  bool_bit_u16!(5, backdrop_1st_target, with_backdrop_1st_target, set_backdrop_1st_target);
  //
  const_enum_bits_u16!(ColorSpecialEffect, 0b1100_0000, effect, with_effect, set_effect);
  //
  bool_bit_u16!(8, bg0_2nd_target, with_bg0_2nd_target, set_bg0_2nd_target);
  bool_bit_u16!(9, bg1_2nd_target, with_bg1_2nd_target, set_bg1_2nd_target);
  bool_bit_u16!(10, bg2_2nd_target, with_bg2_2nd_target, set_bg2_2nd_target);
  bool_bit_u16!(11, bg3_2nd_target, with_bg3_2nd_target, set_bg3_2nd_target);
  bool_bit_u16!(12, obj_2nd_target, with_obj_2nd_target, set_obj_2nd_target);
  bool_bit_u16!(13, backdrop_2nd_target, with_backdrop_2nd_target, set_backdrop_2nd_target);
}

/// The color special effects available via hardware on the GBA.
///
/// * `NoEffect`: Does nothing, obviously.
/// * `AlphaBlend`: Alpha blend between the two pixels targeted, see
///   [`AlphaBlendValue`].
/// * `IncreaseBrightness` / `DecreaseBrightness`: Make the color brighter or
///   darker, see [`BLDBRIGHT`].
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct ColorSpecialEffect(u16);

#[rustfmt::skip]
#[allow(missing_docs)]
impl ColorSpecialEffect {
  pub const NoEffect: Self = Self(0);
  pub const AlphaBlend: Self = Self(1);
  pub const IncreaseBrightness: Self = Self(2);
  pub const DecreaseBrightness: Self = Self(3);
}

//

/// "Alpha Blend Control".
///
/// Only useful if [`BLDCNT`] is set for alpha blending.
///
/// Adjusts alpha blending coefficients.
#[cfg(feature = "unsafe_addresses")]
pub const BLDALPHA: SimpleVolAddr<AlphaBlendValue> =
  unsafe { SimpleVolAddr::new(0x0400_0050) };

/// Coefficients for the alpha blending special effect.
///
/// For two pixels, "1st target" and "2nd target" the blending (per channel) is
/// as follows:
///
/// ```txt
/// Intensity = min(31, Intensity_1st * eva + Intensity_2nd * evb)
/// ```
///
/// The `eva` and `evb` values are specified in increments of 1/16ths, in the
/// range `0..=16`.
///
/// How the target pixels are selected is described in [`BlendControlValue`].
///
/// If alpha blending is selected but there aren't two pixels to target then
/// only the topmost pixel is displayed, and at normal intensity.
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct AlphaBlendValue(u16);

#[rustfmt::skip]
#[allow(missing_docs)]
impl AlphaBlendValue {
  pub_const_fn_new_zero!();
  unsigned_bits_u16!(0..=4, eva, with_eva, set_eva);
  unsigned_bits_u16!(8..=12, evb, with_evb, set_evb);
}

//

/// "Brightness Blend Control".
///
/// Only useful if [`BLDCNT`] is set for increase or decrease brightness.
///
/// Performs a per-channel adjustment to the intensity of a color.
///
/// Increasing:
/// ```txt
/// Output = Initial + (31 - Initial) * BLDBRIGHT
/// ```
///
/// Decreasing:
/// ```txt
/// Output = Initial - Initial * BLDBRIGHT
/// ```
///
/// The `BLDBRIGHT` value is in terms of 1/16th increments, in the range
/// `0..=16`
///
/// How the target pixels is selected is described in [`BlendControlValue`].
#[cfg(feature = "unsafe_addresses")]
pub const BLDBRIGHT: WriteOnlyVolAddr<u32> =
  unsafe { WriteOnlyVolAddr::new(0x0400_0054) };