earthbound-battle-backgrounds 0.1.0

Emulate and render the battle backgrounds from EarthBound / Mother 2.
Documentation
use crate::rom;

pub const HORIZONTAL: u8 = 1;
pub const HORIZONTAL_INTERLACED: u8 = 2;
pub const VERTICAL: u8 = 3;

fn as_int16(value: impl Into<i16>) -> i16 {
    value.into()
}

#[derive(Debug)]
pub struct DistortionEffect {
    data: Vec<u8>,
}

impl DistortionEffect {
    pub fn new(index: usize) -> Self {
        let mut effect = DistortionEffect { data: vec![0; 17] };

        effect.read(index);

        effect
    }

    fn sanitize(type_: u8) -> u8 {
        if type_ != HORIZONTAL && type_ != VERTICAL {
            HORIZONTAL_INTERLACED
        } else {
            type_
        }
    }

    pub fn type_(&self) -> u8 {
        Self::sanitize(self.data[2])
    }

    pub fn frequency(&self) -> i16 {
        as_int16(i16::from(self.data[3]) + (i16::from(self.data[4]) << 8))
    }

    pub fn amplitude(&self) -> i16 {
        as_int16(i16::from(self.data[5]) + (i16::from(self.data[6]) << 8))
    }

    pub fn compression(&self) -> i16 {
        as_int16(i16::from(self.data[8]) + (i16::from(self.data[9]) << 8))
    }

    pub fn frequency_acceleration(&self) -> i16 {
        as_int16(i16::from(self.data[10]) + (i16::from(self.data[11]) << 8))
    }

    pub fn amplitude_acceleration(&self) -> i16 {
        as_int16(i16::from(self.data[12]) + (i16::from(self.data[13]) << 8))
    }

    pub fn speed(&self) -> i16 {
        as_int16(self.data[14])
    }

    pub fn compression_acceleration(&self) -> i16 {
        as_int16(i16::from(self.data[15]) + (i16::from(self.data[16]) << 8))
    }

    fn read(&mut self, index: usize) {
        let mut main = rom::read_block(0xF708 + index * 17);
        for i in 0..17 {
            self.data[i] = main.read_int16() as u8;
        }
    }
}