pub const OAM_Y_OFFSET: u32 = 16;
pub const OAM_X_OFFSET: u32 = 8;
#[inline]
pub fn tile_to_pixel(tile_x: u32, tile_y: u32, tile_size: u32) -> (u32, u32) {
(tile_x * tile_size, tile_y * tile_size)
}
#[inline]
pub fn pixel_to_tile(pixel_x: u32, pixel_y: u32, tile_size: u32) -> (u32, u32) {
(pixel_x / tile_size, pixel_y / tile_size)
}
#[inline]
pub fn oam_to_screen(oam_y: u32, oam_x: u32, oam_y_offset: u32, oam_x_offset: u32) -> (u32, u32) {
let screen_y = oam_y.saturating_sub(oam_y_offset);
let screen_x = oam_x.saturating_sub(oam_x_offset);
(screen_x, screen_y)
}
#[inline]
pub fn screen_to_oam(screen_y: u32, screen_x: u32, oam_y_offset: u32, oam_x_offset: u32) -> (u32, u32) {
(screen_y + oam_y_offset, screen_x + oam_x_offset)
}
#[inline]
pub fn oam_to_screen_signed(oam_y: i16, oam_x: i16, screen_width: u32, screen_height: u32) -> Option<(i32, i32)> {
let screen_y = oam_y as i32 - OAM_Y_OFFSET as i32;
let screen_x = oam_x as i32 - OAM_X_OFFSET as i32;
if screen_y < -16 || screen_y >= screen_height as i32 {
return None;
}
if screen_x < -8 || screen_x >= screen_width as i32 {
return None;
}
Some((screen_x, screen_y))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tile_to_pixel() {
assert_eq!(tile_to_pixel(0, 0, 8), (0, 0));
assert_eq!(tile_to_pixel(2, 1, 8), (16, 8));
assert_eq!(tile_to_pixel(7, 8, 8), (56, 64));
assert_eq!(tile_to_pixel(5, 10, 8), (40, 80));
}
#[test]
fn test_oam_to_screen() {
assert_eq!(oam_to_screen(0x60, 0x5a, OAM_Y_OFFSET, OAM_X_OFFSET), (82, 80));
assert_eq!(oam_to_screen(16, 8, OAM_Y_OFFSET, OAM_X_OFFSET), (0, 0));
assert_eq!(oam_to_screen(0, 0, OAM_Y_OFFSET, OAM_X_OFFSET), (0, 0)); }
#[test]
fn test_screen_to_oam() {
assert_eq!(screen_to_oam(80, 82, OAM_Y_OFFSET, OAM_X_OFFSET), (96, 90)); }
}