Compare commits
2 commits
5e36a84f51
...
36c1e52e29
Author | SHA1 | Date | |
---|---|---|---|
36c1e52e29 | |||
e84b6d2e3f |
8
build.rs
8
build.rs
|
@ -6,7 +6,7 @@ fn main() {
|
||||||
let mut consts = ConstWriter::for_build("lsdpack_bc")
|
let mut consts = ConstWriter::for_build("lsdpack_bc")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.finish_dependencies();
|
.finish_dependencies();
|
||||||
let bytes: Vec<u8> = SONG_SOURCE
|
let mut bytes: Vec<u8> = SONG_SOURCE
|
||||||
.lines()
|
.lines()
|
||||||
.map(|s| s.trim().strip_prefix("DB "))
|
.map(|s| s.trim().strip_prefix("DB "))
|
||||||
.flatten() // filter to lines starting with DB
|
.flatten() // filter to lines starting with DB
|
||||||
|
@ -29,6 +29,12 @@ fn main() {
|
||||||
.flatten() // filter to lines from SongLocations
|
.flatten() // filter to lines from SongLocations
|
||||||
.map(|s| usize::from_str_radix(s.split_once('$').unwrap().1, 16).unwrap() - 0x4000)
|
.map(|s| usize::from_str_radix(s.split_once('$').unwrap().1, 16).unwrap() - 0x4000)
|
||||||
.collect();
|
.collect();
|
||||||
|
// gba psg has inverted wave channel polarity
|
||||||
|
for sample_pair in &mut bytes[0..*song_positions.iter().min().unwrap()] {
|
||||||
|
let upper = *sample_pair & 0xF0;
|
||||||
|
let lower = *sample_pair & 0x0F;
|
||||||
|
*sample_pair = (0xF0 - upper) | (0x0F - lower);
|
||||||
|
}
|
||||||
consts.add_array("LSDPACK_DATA", "u8", &bytes);
|
consts.add_array("LSDPACK_DATA", "u8", &bytes);
|
||||||
consts.add_array("LSDPACK_SONG_POSITIONS", "usize", &song_positions);
|
consts.add_array("LSDPACK_SONG_POSITIONS", "usize", &song_positions);
|
||||||
}
|
}
|
||||||
|
|
146
src/lsdpack.rs
146
src/lsdpack.rs
|
@ -1,9 +1,10 @@
|
||||||
|
use core::{fmt::Write, ops::Add};
|
||||||
use gba::prelude::*;
|
use gba::prelude::*;
|
||||||
use voladdress::{Safe, VolAddress};
|
use voladdress::{Safe, VolAddress};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
enum LsdpackCmd {
|
enum LsdpackCmd {
|
||||||
// special commands (not just plain register writes)
|
// special commands (not just plain register writes)
|
||||||
EndTick = 0,
|
EndTick = 0,
|
||||||
|
@ -139,11 +140,24 @@ impl Lsdpack {
|
||||||
fn write_next_samples(&mut self) {
|
fn write_next_samples(&mut self) {
|
||||||
let ptr = self.sample_ptr;
|
let ptr = self.sample_ptr;
|
||||||
self.sample_ptr += 16;
|
self.sample_ptr += 16;
|
||||||
//let sound_enabled = SOUND_ENABLED.read();
|
|
||||||
//SOUND_ENABLED.write(sound_enabled.with_wave_playing(false));
|
// let sound_enabled = SOUND_ENABLED.read();
|
||||||
let lrvol = LEFT_RIGHT_VOLUME.read();
|
// SOUND_ENABLED.write(sound_enabled.with_wave_playing(false));
|
||||||
LEFT_RIGHT_VOLUME.write(lrvol.with_wave_left(false).with_wave_right(false));
|
|
||||||
WAVE_BANK.write(WaveBank::new().with_enabled(false));
|
//let lrvol = LEFT_RIGHT_VOLUME.read();
|
||||||
|
//LEFT_RIGHT_VOLUME.write(lrvol.with_wave_left(false).with_wave_right(false));
|
||||||
|
|
||||||
|
let wb = WAVE_BANK.read();
|
||||||
|
//WAVE_BANK.write(WaveBank::new().with_enabled(false));
|
||||||
|
|
||||||
|
let wave_ram_ptr = (WAVE_RAM.as_mut_ptr() as *mut u8);
|
||||||
|
for i in 0..16 {
|
||||||
|
unsafe {
|
||||||
|
wave_ram_ptr.add(i).write_volatile(self.data[ptr + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
WAVE_RAM.index(0).write(u32::from_le_bytes(
|
WAVE_RAM.index(0).write(u32::from_le_bytes(
|
||||||
TryFrom::try_from(&self.data[ptr..ptr + 4]).unwrap(),
|
TryFrom::try_from(&self.data[ptr..ptr + 4]).unwrap(),
|
||||||
));
|
));
|
||||||
|
@ -156,10 +170,20 @@ impl Lsdpack {
|
||||||
WAVE_RAM.index(3).write(u32::from_le_bytes(
|
WAVE_RAM.index(3).write(u32::from_le_bytes(
|
||||||
TryFrom::try_from(&self.data[ptr + 12..ptr + 16]).unwrap(),
|
TryFrom::try_from(&self.data[ptr + 12..ptr + 16]).unwrap(),
|
||||||
));
|
));
|
||||||
WAVE_BANK.write(WaveBank::new().with_enabled(true));
|
*/
|
||||||
//SOUND_ENABLED.write(sound_enabled);
|
|
||||||
LEFT_RIGHT_VOLUME.write(lrvol);
|
//WAVE_BANK.write(WaveBank::new().with_enabled(true));
|
||||||
WAVE_FREQ.write(WaveFrequency::new().with_length(self.sample_pitch));
|
WAVE_BANK.write(
|
||||||
|
WaveBank::new()
|
||||||
|
.with_enabled(true)
|
||||||
|
.with_two_banks(false)
|
||||||
|
.with_bank1(!wb.bank1()),
|
||||||
|
);
|
||||||
|
|
||||||
|
// SOUND_ENABLED.write(sound_enabled);
|
||||||
|
//LEFT_RIGHT_VOLUME.write(lrvol);
|
||||||
|
|
||||||
|
unsafe { WAVE_FREQ.cast() }.write(self.sample_pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link_section = ".iwram"]
|
#[link_section = ".iwram"]
|
||||||
|
@ -183,6 +207,33 @@ impl Lsdpack {
|
||||||
ongoing = flagged_ongoing;
|
ongoing = flagged_ongoing;
|
||||||
ongoing &= self.apply_cmd(cmd);
|
ongoing &= self.apply_cmd(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* // stupid hack while testing. only enable wav channel so i can hear it at all
|
||||||
|
SOUND_ENABLED.write(
|
||||||
|
SoundEnable::new()
|
||||||
|
.with_tone1_playing(false)
|
||||||
|
.with_tone2_playing(false)
|
||||||
|
.with_wave_playing(true)
|
||||||
|
.with_noise_playing(false)
|
||||||
|
.with_enabled(true),
|
||||||
|
);
|
||||||
|
LEFT_RIGHT_VOLUME.write(
|
||||||
|
LeftRightVolume::new()
|
||||||
|
.with_tone1_left(false)
|
||||||
|
.with_tone1_right(false)
|
||||||
|
.with_tone2_left(false)
|
||||||
|
.with_tone2_right(false)
|
||||||
|
.with_wave_left(true)
|
||||||
|
.with_wave_right(true)
|
||||||
|
.with_noise_right(false)
|
||||||
|
.with_noise_left(false)
|
||||||
|
.with_left_volume(3)
|
||||||
|
.with_right_volume(3),
|
||||||
|
);
|
||||||
|
// */
|
||||||
|
|
||||||
|
//WAVE_BANK.write(WaveBank::new().with_enabled(true));
|
||||||
|
//WAVE_LEN_VOLUME.write(WaveLenVolume::new().with_length(255).with_volume(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link_section = ".iwram"]
|
#[link_section = ".iwram"]
|
||||||
|
@ -206,13 +257,21 @@ impl Lsdpack {
|
||||||
#[link_section = ".iwram"]
|
#[link_section = ".iwram"]
|
||||||
fn write_lsb<T>(&mut self, voladdr: VolAddress<T, Safe, Safe>) {
|
fn write_lsb<T>(&mut self, voladdr: VolAddress<T, Safe, Safe>) {
|
||||||
let voladdr = unsafe { voladdr.cast::<u16>() };
|
let voladdr = unsafe { voladdr.cast::<u16>() };
|
||||||
voladdr.write((voladdr.read() & 0xFF00) | (self.next_byte() as u16));
|
//voladdr.write((voladdr.read() & 0xFF00) | (self.next_byte() as u16));
|
||||||
|
unsafe {
|
||||||
|
(voladdr.as_mut_ptr() as *mut u8).write_volatile(self.next_byte());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link_section = ".iwram"]
|
#[link_section = ".iwram"]
|
||||||
fn write_msb<T>(&mut self, voladdr: VolAddress<T, Safe, Safe>) {
|
fn write_msb<T>(&mut self, voladdr: VolAddress<T, Safe, Safe>) {
|
||||||
let voladdr = unsafe { voladdr.cast::<u16>() };
|
let voladdr = unsafe { voladdr.cast::<u16>() };
|
||||||
voladdr.write((voladdr.read() & 0xFF) | ((self.next_byte() as u16) << 8));
|
//voladdr.write((voladdr.read() & 0xFF) | ((self.next_byte() as u16) << 8));
|
||||||
|
unsafe {
|
||||||
|
(voladdr.as_mut_ptr() as *mut u8)
|
||||||
|
.add(1)
|
||||||
|
.write_volatile(self.next_byte());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link_section = ".iwram"]
|
#[link_section = ".iwram"]
|
||||||
|
@ -225,6 +284,22 @@ impl Lsdpack {
|
||||||
#[link_section = ".iwram"]
|
#[link_section = ".iwram"]
|
||||||
fn apply_cmd(&mut self, cmd: LsdpackCmd) -> bool {
|
fn apply_cmd(&mut self, cmd: LsdpackCmd) -> bool {
|
||||||
use LsdpackCmd::*;
|
use LsdpackCmd::*;
|
||||||
|
/*
|
||||||
|
if let Ok(mut logger) =
|
||||||
|
gba::mgba::MgbaBufferedLogger::try_new(gba::mgba::MgbaMessageLevel::Info)
|
||||||
|
{
|
||||||
|
match cmd {
|
||||||
|
SampleStart | SampleNext | WavOnOff | WavLength | WavEnv | WavPitchLsb
|
||||||
|
| WavPitchMsb | ChannelVolume | Pan | SoundOffOn | WavePattern0 | WavePattern1
|
||||||
|
| WavePattern2 | WavePattern3 | WavePattern4 | WavePattern5 | WavePattern6
|
||||||
|
| WavePattern7 | WavePattern8 | WavePattern9 | WavePatternA | WavePatternB
|
||||||
|
| WavePatternC | WavePatternD | WavePatternE | WavePatternF => {
|
||||||
|
writeln!(logger, "{:?}", cmd).ok();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// */
|
||||||
match cmd {
|
match cmd {
|
||||||
// special commands:
|
// special commands:
|
||||||
EndTick => return false,
|
EndTick => return false,
|
||||||
|
@ -303,44 +378,49 @@ impl Lsdpack {
|
||||||
// general register writes:
|
// general register writes:
|
||||||
Pu0Sweep => unsafe { TONE1_SWEEP.cast() }.write(self.next_byte()),
|
Pu0Sweep => unsafe { TONE1_SWEEP.cast() }.write(self.next_byte()),
|
||||||
Pu0LengthWave => self.write_lsb(TONE1_PATTERN),
|
Pu0LengthWave => self.write_lsb(TONE1_PATTERN),
|
||||||
Pu0Env => self.write_msb(TONE1_PATTERN),
|
Pu0Env => {
|
||||||
|
self.next_byte();
|
||||||
|
} //self.write_msb(TONE1_PATTERN),
|
||||||
Pu0PitchLsb => self.write_lsb(TONE1_FREQUENCY),
|
Pu0PitchLsb => self.write_lsb(TONE1_FREQUENCY),
|
||||||
Pu0PitchMsb => self.write_msb(TONE1_FREQUENCY),
|
Pu0PitchMsb => self.write_msb(TONE1_FREQUENCY),
|
||||||
Pu1LengthWave => self.write_lsb(TONE2_PATTERN),
|
Pu1LengthWave => self.write_lsb(TONE2_PATTERN),
|
||||||
Pu1Env => self.write_msb(TONE2_PATTERN),
|
Pu1Env => {
|
||||||
|
self.next_byte();
|
||||||
|
} //self.write_msb(TONE2_PATTERN),
|
||||||
Pu1PitchLsb => self.write_lsb(TONE2_FREQUENCY),
|
Pu1PitchLsb => self.write_lsb(TONE2_FREQUENCY),
|
||||||
Pu1PitchMsb => self.write_msb(TONE2_FREQUENCY),
|
Pu1PitchMsb => self.write_msb(TONE2_FREQUENCY),
|
||||||
WavOnOff => WAVE_BANK.write(WaveBank::new().with_enabled(self.next_byte() != 0)),
|
//WavOnOff => unsafe { WAVE_BANK.cast() }.write(self.next_byte()),
|
||||||
|
WavOnOff => WAVE_BANK.write(
|
||||||
|
WaveBank::new().with_enabled(self.next_byte() != 0), //.with_two_banks(true)
|
||||||
|
//.with_bank1(false),
|
||||||
|
),
|
||||||
WavLength => self.write_lsb(WAVE_LEN_VOLUME),
|
WavLength => self.write_lsb(WAVE_LEN_VOLUME),
|
||||||
WavEnv => self.write_msb(WAVE_LEN_VOLUME),
|
WavEnv => self.write_msb(WAVE_LEN_VOLUME),
|
||||||
WavPitchLsb => self.write_lsb(WAVE_FREQ),
|
WavPitchLsb => self.write_lsb(WAVE_FREQ),
|
||||||
WavPitchMsb => self.write_msb(WAVE_FREQ),
|
WavPitchMsb => self.write_msb(WAVE_FREQ),
|
||||||
NoiLength => self.write_lsb(NOISE_LEN_ENV),
|
NoiLength => self.write_lsb(NOISE_LEN_ENV),
|
||||||
NoiEnv => self.write_msb(NOISE_LEN_ENV),
|
NoiEnv => {
|
||||||
|
self.next_byte();
|
||||||
|
} //self.write_msb(NOISE_LEN_ENV),
|
||||||
NoiWave => self.write_lsb(NOISE_FREQ),
|
NoiWave => self.write_lsb(NOISE_FREQ),
|
||||||
NoiTrig => self.write_msb(NOISE_FREQ),
|
NoiTrig => self.write_msb(NOISE_FREQ),
|
||||||
ChannelVolume => self.write_lsb(LEFT_RIGHT_VOLUME),
|
ChannelVolume => self.write_lsb(LEFT_RIGHT_VOLUME),
|
||||||
Pan => self.write_msb(LEFT_RIGHT_VOLUME),
|
Pan => self.write_msb(LEFT_RIGHT_VOLUME),
|
||||||
SoundOffOn => unsafe { SOUND_ENABLED.cast() }.write(self.next_byte()),
|
SoundOffOn => unsafe { SOUND_ENABLED.cast() }.write(self.next_byte()),
|
||||||
WavePattern0 => todo!(),
|
WavePattern0 | WavePattern1 | WavePattern2 | WavePattern3 | WavePattern4
|
||||||
WavePattern1 => todo!(),
|
| WavePattern5 | WavePattern6 | WavePattern7 | WavePattern8 | WavePattern9
|
||||||
WavePattern2 => todo!(),
|
| WavePatternA | WavePatternB | WavePatternC | WavePatternD | WavePatternE
|
||||||
WavePattern3 => todo!(),
|
| WavePatternF => {
|
||||||
WavePattern4 => todo!(),
|
let which = cmd as u8 as usize & 0xF;
|
||||||
WavePattern5 => todo!(),
|
unsafe {
|
||||||
WavePattern6 => todo!(),
|
((0x04000090 + which) as *mut u8).write_volatile(self.next_byte());
|
||||||
WavePattern7 => todo!(),
|
}
|
||||||
WavePattern8 => todo!(),
|
}
|
||||||
WavePattern9 => todo!(),
|
|
||||||
WavePatternA => todo!(),
|
|
||||||
WavePatternB => todo!(),
|
|
||||||
WavePatternC => todo!(),
|
|
||||||
WavePatternD => todo!(),
|
|
||||||
WavePatternE => todo!(),
|
|
||||||
WavePatternF => todo!(),
|
|
||||||
_Invalid0B | _Invalid0C | _Invalid0D | _Invalid0E | _Invalid0F | _Invalid15
|
_Invalid0B | _Invalid0C | _Invalid0D | _Invalid0E | _Invalid0F | _Invalid15
|
||||||
| _Invalid1F | _Invalid27 | _Invalid28 | _Invalid29 | _Invalid2A | _Invalid2B
|
| _Invalid1F | _Invalid27 | _Invalid28 | _Invalid29 | _Invalid2A | _Invalid2B
|
||||||
| _Invalid2C | _Invalid2D | _Invalid2E | _Invalid2F => unimplemented!(),
|
| _Invalid2C | _Invalid2D | _Invalid2E | _Invalid2F => {
|
||||||
|
unimplemented!("Invalid command: {:x}", cmd as u8)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue