From fdd66948242d31983a1c07f1f05407f6204a2b31 Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 4 Aug 2024 14:56:44 -0500 Subject: [PATCH 01/21] Simple extraction of wav data --- src/Tools/jaby_engine_fconv/Cargo.toml | 1 + .../jaby_engine_fconv/src/audio/adpcm/mod.rs | 41 +++++++++++++++++++ src/Tools/jaby_engine_fconv/src/audio/mod.rs | 1 + src/Tools/jaby_engine_fconv/src/main.rs | 5 +++ 4 files changed, 48 insertions(+) create mode 100644 src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs diff --git a/src/Tools/jaby_engine_fconv/Cargo.toml b/src/Tools/jaby_engine_fconv/Cargo.toml index add43e6a..543df9e2 100644 --- a/src/Tools/jaby_engine_fconv/Cargo.toml +++ b/src/Tools/jaby_engine_fconv/Cargo.toml @@ -8,6 +8,7 @@ panic = "abort" [dependencies] clap = {version = "4.4.11", features = ["derive"]} +hound = "3.5.1" image = "0.24.7" paste = "1.0.14" png = "0.17.10" diff --git a/src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs b/src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs new file mode 100644 index 00000000..374bd1af --- /dev/null +++ b/src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs @@ -0,0 +1,41 @@ +use clap::{Args, ValueEnum}; +use hound::Sample; +use image::{DynamicImage, io::Reader as ImageReader}; +use std::io::{Cursor, Write}; +use tool_helper::{print_warning, Error, Input}; + +#[derive(Args)] +pub struct Arguments { +} + +pub fn convert(input: Input, output: &mut dyn Write) -> Result<(), Error> { + let mut audio_io = hound::WavReader::new(input)?; + let header = audio_io.spec(); + + if header.sample_format != hound::SampleFormat::Int ||header.bits_per_sample != 16 { + return Err(Error::from_str("Only 16bit integer samples are supported")); + } + + if header.channels > 1 { + print_warning("Found more than one audio channel. First channel will be encoded.".to_owned()); + } + + let active_channel = 1; + let mut sample_count = 0; + for sample in audio_io.samples::() { + match sample { + Ok(sample) => { + sample_count += 1; + + if sample_count%active_channel == 0 { + output.write(&sample.to_le_bytes())?; + } + } + + Err(error) => { + return Err(Error::from_text(format!("Failed iterating over samples: {}", error))); + } + } + } + Ok(()) +} \ No newline at end of file diff --git a/src/Tools/jaby_engine_fconv/src/audio/mod.rs b/src/Tools/jaby_engine_fconv/src/audio/mod.rs index ec567062..296a1f2c 100644 --- a/src/Tools/jaby_engine_fconv/src/audio/mod.rs +++ b/src/Tools/jaby_engine_fconv/src/audio/mod.rs @@ -1 +1,2 @@ +pub mod adpcm; pub mod xa; \ No newline at end of file diff --git a/src/Tools/jaby_engine_fconv/src/main.rs b/src/Tools/jaby_engine_fconv/src/main.rs index 219dae79..80a8da00 100644 --- a/src/Tools/jaby_engine_fconv/src/main.rs +++ b/src/Tools/jaby_engine_fconv/src/main.rs @@ -21,8 +21,12 @@ struct CommandLine { #[derive(Subcommand)] enum SubCommands { + // === Internal Commands === Nothing, SimpleTIM(reduced_tim::Arguments), + ADPCM, + + // === External Commands === XA(xa::Arguments) } @@ -44,6 +48,7 @@ fn run_internal_conversion(cmd: CommandLine) -> Result<(), Error> { match cmd.sub_command { SubCommands::Nothing => nothing::copy(&mut input, dst_buffer), SubCommands::SimpleTIM(args) => reduced_tim::convert(args, input, dst_buffer), + SubCommands::ADPCM => adpcm::convert(input, dst_buffer), _ => Err(Error::not_implemented("External functions can not be called for internal conversion")) } }; From 746590eef328a5d2a6f54018ebeeb32b7d8c5d41 Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 4 Aug 2024 14:56:58 -0500 Subject: [PATCH 02/21] Embedd adpcm file --- examples/PoolBox/assets/Makefile | 5 +++++ examples/PoolBox/iso/Config.xml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/examples/PoolBox/assets/Makefile b/examples/PoolBox/assets/Makefile index 2b7aa634..57f66ca2 100644 --- a/examples/PoolBox/assets/Makefile +++ b/examples/PoolBox/assets/Makefile @@ -12,6 +12,7 @@ CLUT_4_COLOR_TRANS_FLAGS = simple-tim clut4 --color-trans ## Music tracks INPUT += $(OUTPUT_DIR)/Evacuation_cdda.xa INPUT += $(OUTPUT_DIR)/fox.xa +INPUT += $(OUTPUT_DIR)/apple.adpcm ## Images INPUT += $(OUTPUT_DIR)/TexturePage.img @@ -36,6 +37,10 @@ $(OUTPUT_DIR)/fox.xa: audio/temp/fox.wav @mkdir -p $(OUTPUT_DIR) jaby_engine_fconv $< -o $@ xa +$(OUTPUT_DIR)/%.adpcm: audio/temp/%.wav + @mkdir -p $(OUTPUT_DIR) + jaby_engine_fconv $< -o $@ adpcm + $(OUTPUT_DIR)/%.xa: audio/%.wav @mkdir -p $(OUTPUT_DIR) jaby_engine_fconv $< -o $@ xa diff --git a/examples/PoolBox/iso/Config.xml b/examples/PoolBox/iso/Config.xml index 04d443fd..aa8a298a 100644 --- a/examples/PoolBox/iso/Config.xml +++ b/examples/PoolBox/iso/Config.xml @@ -44,6 +44,9 @@ ../assets/bin/fox.xa + ../assets/audio/temp/breaking.wav \ No newline at end of file From 0dc1f522c54ece5b0e5fdd30d1144f303cf09c43 Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 4 Aug 2024 17:41:20 -0500 Subject: [PATCH 03/21] Convert wav files to .vag --- examples/PoolBox/assets/Makefile | 6 +-- examples/PoolBox/iso/Config.xml | 2 +- src/Tools/jaby_engine_fconv/Cargo.toml | 3 +- .../jaby_engine_fconv/src/audio/adpcm/mod.rs | 41 ----------------- src/Tools/jaby_engine_fconv/src/audio/mod.rs | 45 ++++++++++++++++++- .../jaby_engine_fconv/src/audio/vag/mod.rs | 22 +++++++++ .../jaby_engine_fconv/src/audio/xa/mod.rs | 34 ++------------ src/Tools/jaby_engine_fconv/src/main.rs | 26 ++++++++--- 8 files changed, 93 insertions(+), 86 deletions(-) delete mode 100644 src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs create mode 100644 src/Tools/jaby_engine_fconv/src/audio/vag/mod.rs diff --git a/examples/PoolBox/assets/Makefile b/examples/PoolBox/assets/Makefile index 57f66ca2..9ba30da4 100644 --- a/examples/PoolBox/assets/Makefile +++ b/examples/PoolBox/assets/Makefile @@ -12,7 +12,7 @@ CLUT_4_COLOR_TRANS_FLAGS = simple-tim clut4 --color-trans ## Music tracks INPUT += $(OUTPUT_DIR)/Evacuation_cdda.xa INPUT += $(OUTPUT_DIR)/fox.xa -INPUT += $(OUTPUT_DIR)/apple.adpcm +INPUT += $(OUTPUT_DIR)/apple.vag ## Images INPUT += $(OUTPUT_DIR)/TexturePage.img @@ -37,9 +37,9 @@ $(OUTPUT_DIR)/fox.xa: audio/temp/fox.wav @mkdir -p $(OUTPUT_DIR) jaby_engine_fconv $< -o $@ xa -$(OUTPUT_DIR)/%.adpcm: audio/temp/%.wav +$(OUTPUT_DIR)/%.vag: audio/temp/%.wav @mkdir -p $(OUTPUT_DIR) - jaby_engine_fconv $< -o $@ adpcm + jaby_engine_fconv $< -o $@ vag $(OUTPUT_DIR)/%.xa: audio/%.wav @mkdir -p $(OUTPUT_DIR) diff --git a/examples/PoolBox/iso/Config.xml b/examples/PoolBox/iso/Config.xml index aa8a298a..56bc04a2 100644 --- a/examples/PoolBox/iso/Config.xml +++ b/examples/PoolBox/iso/Config.xml @@ -45,7 +45,7 @@ ../assets/audio/temp/breaking.wav diff --git a/src/Tools/jaby_engine_fconv/Cargo.toml b/src/Tools/jaby_engine_fconv/Cargo.toml index 543df9e2..fb624db9 100644 --- a/src/Tools/jaby_engine_fconv/Cargo.toml +++ b/src/Tools/jaby_engine_fconv/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jaby_engine_fconv" -version = "0.1.6" +version = "0.2.0" edition = "2021" [profile.release] @@ -8,7 +8,6 @@ panic = "abort" [dependencies] clap = {version = "4.4.11", features = ["derive"]} -hound = "3.5.1" image = "0.24.7" paste = "1.0.14" png = "0.17.10" diff --git a/src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs b/src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs deleted file mode 100644 index 374bd1af..00000000 --- a/src/Tools/jaby_engine_fconv/src/audio/adpcm/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -use clap::{Args, ValueEnum}; -use hound::Sample; -use image::{DynamicImage, io::Reader as ImageReader}; -use std::io::{Cursor, Write}; -use tool_helper::{print_warning, Error, Input}; - -#[derive(Args)] -pub struct Arguments { -} - -pub fn convert(input: Input, output: &mut dyn Write) -> Result<(), Error> { - let mut audio_io = hound::WavReader::new(input)?; - let header = audio_io.spec(); - - if header.sample_format != hound::SampleFormat::Int ||header.bits_per_sample != 16 { - return Err(Error::from_str("Only 16bit integer samples are supported")); - } - - if header.channels > 1 { - print_warning("Found more than one audio channel. First channel will be encoded.".to_owned()); - } - - let active_channel = 1; - let mut sample_count = 0; - for sample in audio_io.samples::() { - match sample { - Ok(sample) => { - sample_count += 1; - - if sample_count%active_channel == 0 { - output.write(&sample.to_le_bytes())?; - } - } - - Err(error) => { - return Err(Error::from_text(format!("Failed iterating over samples: {}", error))); - } - } - } - Ok(()) -} \ No newline at end of file diff --git a/src/Tools/jaby_engine_fconv/src/audio/mod.rs b/src/Tools/jaby_engine_fconv/src/audio/mod.rs index 296a1f2c..bdfdb429 100644 --- a/src/Tools/jaby_engine_fconv/src/audio/mod.rs +++ b/src/Tools/jaby_engine_fconv/src/audio/mod.rs @@ -1,2 +1,43 @@ -pub mod adpcm; -pub mod xa; \ No newline at end of file +pub mod xa; +pub mod vag; + +use std::{env, path::PathBuf, process::Command}; +use tool_helper::Error; + +fn run_psxavenc(input: PathBuf, output: PathBuf, args: I) -> Result<(), Error> +where + I: IntoIterator, + S: AsRef, { + let psxavenc = get_psxavenc_path()?; + let result = Command::new(psxavenc).args(args).arg(input.to_string_lossy().as_ref()).arg(output.to_string_lossy().as_ref()).output()?; + + let stderr = tool_helper::vec_helper::to_string(result.stderr)?; + let stdout = tool_helper::vec_helper::to_string(result.stdout)?; + + if !result.status.success() { + return Err(Error::from_text(format!("psxavenc returned: {}. {}", result.status, stderr))); + } + + if !stdout.is_empty() { + println!("{}", stdout); + } + Ok(()) +} + +fn get_psxavenc_path() -> Result { + let tool_path = { + let mut my_path = env::current_exe()?; + + my_path.pop(); + my_path.push("extern"); + my_path.push("psxavenc"); + + my_path + }; + + if !tool_path.exists() { + return Err(Error::from_str("Could not locate psxavenc. Make sure it is installed under \"/bin/extern\"")); + } + + Ok(tool_path) +} \ No newline at end of file diff --git a/src/Tools/jaby_engine_fconv/src/audio/vag/mod.rs b/src/Tools/jaby_engine_fconv/src/audio/vag/mod.rs new file mode 100644 index 00000000..f9e9a411 --- /dev/null +++ b/src/Tools/jaby_engine_fconv/src/audio/vag/mod.rs @@ -0,0 +1,22 @@ +use clap::Args; +use std::path::PathBuf; +use tool_helper::Error; + +#[derive(Args)] +pub struct Arguments { + frequency: Option +} + +pub fn convert(args: Arguments, input: PathBuf, output: PathBuf) -> Result<(), Error> { + let mut cmd_args = vec!["-t", "vag"]; + let frequency_str; + + if let Some(frequency) = args.frequency { + frequency_str = frequency.to_string().to_owned(); + + cmd_args.push("-f"); + cmd_args.push(frequency_str.as_ref()); + } + + super::run_psxavenc(input, output, cmd_args) +} \ No newline at end of file diff --git a/src/Tools/jaby_engine_fconv/src/audio/xa/mod.rs b/src/Tools/jaby_engine_fconv/src/audio/xa/mod.rs index c53257d4..82a66ed4 100644 --- a/src/Tools/jaby_engine_fconv/src/audio/xa/mod.rs +++ b/src/Tools/jaby_engine_fconv/src/audio/xa/mod.rs @@ -1,5 +1,5 @@ use clap::{Args, ValueEnum}; -use std::{env, path::PathBuf, process::Command, str}; +use std::{path::PathBuf, str}; use tool_helper::Error; #[derive(Args)] @@ -43,39 +43,13 @@ impl Sample { pub fn convert(args: Arguments, input: PathBuf, output: PathBuf) -> Result<(), Error> { let quality = args.quality; let sample = args.sample; - let tool_path = { - let mut my_path = env::current_exe()?; - - my_path.pop(); - my_path.push("extern"); - my_path.push("psxavenc"); - - my_path - }; - - if !tool_path.exists() { - return Err(Error::from_str("Could not locate psxavenc. Make sure it is installed under \"/bin/extern\"")); - } - - let result = Command::new(tool_path).args([ + + super::run_psxavenc(input, output, [ "-t", "xacd", "-f", quality.get_frequency().to_string().as_ref(), "-b", "4", "-c", sample.get_channel().to_string().as_ref(), "-F", "0", "-C", "0", - input.to_string_lossy().as_ref(), output.to_string_lossy().as_ref() - ]) .output()?; - - let stderr = tool_helper::vec_helper::to_string(result.stderr)?; - let stdout = tool_helper::vec_helper::to_string(result.stdout)?; - - if !result.status.success() { - return Err(Error::from_text(format!("psxavenc returned: {}. {}", result.status, stderr))); - } - - if !stdout.is_empty() { - println!("{}", stdout); - } - Ok(()) + ]) } \ No newline at end of file diff --git a/src/Tools/jaby_engine_fconv/src/main.rs b/src/Tools/jaby_engine_fconv/src/main.rs index 80a8da00..e96f4413 100644 --- a/src/Tools/jaby_engine_fconv/src/main.rs +++ b/src/Tools/jaby_engine_fconv/src/main.rs @@ -24,10 +24,22 @@ enum SubCommands { // === Internal Commands === Nothing, SimpleTIM(reduced_tim::Arguments), - ADPCM, // === External Commands === - XA(xa::Arguments) + VAG(vag::Arguments), + XA(xa::Arguments), +} + +impl SubCommands { + pub fn is_external_command(&self) -> bool { + match self { + SubCommands::Nothing => false, + SubCommands::SimpleTIM(_) => false, + + SubCommands::VAG(_) => true, + SubCommands::XA(_) => true + } + } } fn run_internal_conversion(cmd: CommandLine) -> Result<(), Error> { @@ -48,8 +60,7 @@ fn run_internal_conversion(cmd: CommandLine) -> Result<(), Error> { match cmd.sub_command { SubCommands::Nothing => nothing::copy(&mut input, dst_buffer), SubCommands::SimpleTIM(args) => reduced_tim::convert(args, input, dst_buffer), - SubCommands::ADPCM => adpcm::convert(input, dst_buffer), - _ => Err(Error::not_implemented("External functions can not be called for internal conversion")) + _ => Err(Error::from_str("External functions can not be called for internal conversion")) } }; @@ -79,13 +90,14 @@ fn run_external_conversion(cmd: CommandLine) -> Result<(), Error> { let output_file = cmd.output_file.ok_or(Error::from_str("Output has to be a file"))?; match cmd.sub_command { - SubCommands::XA(args) => xa::convert(args, input_file, output_file), - _ => Err(Error::not_implemented("Internal functions can not be called for external conversion")) + SubCommands::VAG(args) => vag::convert(args, input_file, output_file), + SubCommands::XA(args) => xa::convert(args, input_file, output_file), + _ => Err(Error::from_str("Internal functions can not be called for external conversion")) } } fn run_main(cmd: CommandLine) -> Result<(), Error> { - if matches!(cmd.sub_command, SubCommands::XA(_)) { + if cmd.sub_command.is_external_command() { run_external_conversion(cmd) } From 07327fd64627a15a8ab05ec1a3e64ae01f80053a Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 4 Aug 2024 17:47:54 -0500 Subject: [PATCH 04/21] Add VAG configuration option --- config/Readme.md | 2 ++ include/PSX/jabyengine_config.hpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/config/Readme.md b/config/Readme.md index fd91bf39..cf73d137 100644 --- a/config/Readme.md +++ b/config/Readme.md @@ -39,6 +39,8 @@ struct DefaultConfiguration { ``` ### `CustomConfiguration` macros ```c++ +// Turns on support of Sonys VAG files for the CDFileProcessor (off by default) +#define __SUPPORT_VAG__ // Turns on colored rectangles during boot (off by default) #define __USE_DEBUG_COLOR__ // Turns on PS3 support (on by default) diff --git a/include/PSX/jabyengine_config.hpp b/include/PSX/jabyengine_config.hpp index 3a92f80d..868a6052 100644 --- a/include/PSX/jabyengine_config.hpp +++ b/include/PSX/jabyengine_config.hpp @@ -31,6 +31,8 @@ namespace JabyEngine { using Configuration = CustomConfiguration; #else using Configuration = DefaultConfiguration; + // TODO: v Turn off when this is supported + #define __SUPPORT_VAG__ #define __SUPPORT_PS3__ #endif // has jabyengine_custom_config } \ No newline at end of file From 10c394aebab3482722eed8e28b846e0cfba6ac3b Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 4 Aug 2024 18:13:44 -0500 Subject: [PATCH 05/21] Prepare VAG loading --- .../application/src/Custom/file_parser.cpp | 2 +- .../PoolBox/application/src/asset_mgr.cpp | 2 ++ include/PSX/File/Processor/file_processor.hpp | 5 ++-- include/PSX/File/cd_file_types.hpp | 21 +++++++++++++---- include/PSX/File/file_types.hpp | 15 ++++++++++-- .../src/File/Processor/cd_file_processor.cpp | 12 +++++++--- .../src/File/Processor/nothing_processor.cpp | 2 +- .../src/File/Processor/tim_processor.cpp | 2 +- .../src/File/Processor/vag_processor.cpp | 23 +++++++++++++++++++ 9 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 src/Library/src/File/Processor/vag_processor.cpp diff --git a/examples/PoolBox/application/src/Custom/file_parser.cpp b/examples/PoolBox/application/src/Custom/file_parser.cpp index 9f96fb97..f9a8da64 100644 --- a/examples/PoolBox/application/src/Custom/file_parser.cpp +++ b/examples/PoolBox/application/src/Custom/file_parser.cpp @@ -16,7 +16,7 @@ namespace JabyEngine { State create_custom(const uint32_t* data_adr, const CDFileType_t& file_type, const CDFile::Payload& payload) { switch(static_cast(file_type)) { case FileType::Jingle: - return State::from(JingleState{.sfx_id = payload.raw}, reinterpret_cast(data_adr), parse_jingle); + return State::from(JingleState{.sfx_id = payload.raw}, data_adr, parse_jingle); default: return FileProcessor::create(data_adr, Nothing()); diff --git a/examples/PoolBox/application/src/asset_mgr.cpp b/examples/PoolBox/application/src/asset_mgr.cpp index 0fcc3493..326e648d 100644 --- a/examples/PoolBox/application/src/asset_mgr.cpp +++ b/examples/PoolBox/application/src/asset_mgr.cpp @@ -17,6 +17,7 @@ namespace Assets { __jabyengine_start_lba_request __jabyengine_request_lba_for(PACO, "ASSETS/MAIN/PACO.IMG"), __jabyengine_request_lba_for(DFISH, "ASSETS/MAIN/DFISH.IMG"), + __jabyengine_request_lba_for(APPLE_SFX, "SFX/APPLE.VAG"), __jabyengine_request_lba_for(MIX_XA, "XAAUDIO/MIX.XA"), __jabyengine_request_lba_for(BIOS_INFO_OVL, "BIO.BIN"), __jabyengine_request_lba_for(GPU_TEST_OVL, "GTO.BIN"), @@ -61,6 +62,7 @@ namespace Assets { static const CDFile Files[] = { CDFileBuilder::simple_tim(LBA::PACO, PacoTIM), CDFileBuilder::simple_tim(LBA::DFISH, DoenerFishInfo.tim), + CDFileBuilder::sony_vag(LBA::APPLE_SFX, VAG::create(0)), CustomCDFileBuilder::jingle(32), }; diff --git a/include/PSX/File/Processor/file_processor.hpp b/include/PSX/File/Processor/file_processor.hpp index ecccbe3e..19e7e08b 100644 --- a/include/PSX/File/Processor/file_processor.hpp +++ b/include/PSX/File/Processor/file_processor.hpp @@ -37,8 +37,8 @@ namespace JabyEngine { Reserved reserved; template - static __always_inline State from(const T& state, const uint8_t* data_adr, GenericProcessRoutine process_routine) { - return {Configuration::from(process_routine, data_adr), *reinterpret_cast(&state)}; + static __always_inline State from(const T& state, const uint32_t* data_adr, GenericProcessRoutine process_routine) { + return {Configuration::from(process_routine, reinterpret_cast(data_adr)), *reinterpret_cast(&state)}; static_assert(sizeof(T) <= sizeof(Reserved)); } @@ -52,6 +52,7 @@ namespace JabyEngine { // The nothing state State create(const uint32_t* data_adr, const Nothing& nothing); State create(const uint32_t* data_adr, const SimpleTIM& file); + State create(const uint32_t* data_adr, const VAG& file); State create_custom(const uint32_t* data_adr, const CDFileType_t& file_type, const CDFile::Payload& payload); } diff --git a/include/PSX/File/cd_file_types.hpp b/include/PSX/File/cd_file_types.hpp index 908d3e92..df3feeae 100644 --- a/include/PSX/File/cd_file_types.hpp +++ b/include/PSX/File/cd_file_types.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include "../Overlay/overlay.hpp" #include "file_types.hpp" @@ -7,8 +8,11 @@ namespace JabyEngine { using RawPayload_t = uint32_t; enum struct CDFileType : CDFileType_t { - SimpleTIM = 0, - CopyTo, + CopyTo = 0, + SimpleTIM, + #ifdef __SUPPORT_VAG__ + SonyVAG, + #endif // __SUPPORT_VAG__ Custom, }; @@ -16,8 +20,9 @@ namespace JabyEngine { struct CDFile { union Payload { RawPayload_t raw; - SimpleTIM simple_tim; CopyTo copy_to; + SimpleTIM simple_tim; + VAG vag; Overlay overlay; }; @@ -38,13 +43,19 @@ namespace JabyEngine { #pragma pack(pop) struct CDFileBuilder { + static constexpr CDFile copy_to(uint8_t rel_lba_idx, uint32_t* dst) { + return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::CopyTo, .payload = {.copy_to = CopyTo{dst}}}; + } + static constexpr CDFile simple_tim(uint8_t rel_lba_idx, SimpleTIM simple_tim) { return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::SimpleTIM, .payload = {.simple_tim = simple_tim}}; } - static constexpr CDFile copy_to(uint8_t rel_lba_idx, uint32_t* dst) { - return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::CopyTo, .payload = {.copy_to = CopyTo{dst}}}; +#ifdef __SUPPORT_VAG__ + static constexpr CDFile sony_vag(uint8_t lba_idx, VAG vag) { + return CDFile{.rel_lba_idx = lba_idx, .type = CDFileType::SonyVAG, .payload = {.vag = vag}}; } +#endif //__SUPPORT_VAG__ static constexpr CDFile overlay(uint8_t rel_lba_idx, uint32_t* overlay_dst) { return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::CopyTo, .payload = {.overlay = Overlay{overlay_dst}}}; diff --git a/include/PSX/File/file_types.hpp b/include/PSX/File/file_types.hpp index bfdec4ba..00a247cf 100644 --- a/include/PSX/File/file_types.hpp +++ b/include/PSX/File/file_types.hpp @@ -8,6 +8,12 @@ namespace JabyEngine { struct Nothing { }; + struct CopyTo { + uint32_t* dst; + }; + + // TODO: Call TIM? + // TODO: Add create function? struct SimpleTIM { static constexpr auto TextureX = BitRange::from_to(0, 8); static constexpr auto TextureY = BitRange::from_to(9, 16); @@ -61,9 +67,14 @@ namespace JabyEngine { } }; - struct CopyTo { - uint32_t* dst; + struct VAG { + uint8_t voice_number; + + static constexpr VAG create(uint8_t voice_num) { + return VAG{.voice_number = voice_num}; + } }; + #pragma pack(pop) typedef CopyTo Overlay; diff --git a/src/Library/src/File/Processor/cd_file_processor.cpp b/src/Library/src/File/Processor/cd_file_processor.cpp index dcc21e67..63ab8a88 100644 --- a/src/Library/src/File/Processor/cd_file_processor.cpp +++ b/src/Library/src/File/Processor/cd_file_processor.cpp @@ -37,11 +37,17 @@ namespace JabyEngine { }(file, buf_cfg, is_lz4); switch(file.type) { - case CDFileType::SimpleTIM: - return FileProcessor::create(data_adr, file.payload.simple_tim); case CDFileType::CopyTo: return FileProcessor::create(data_adr, Nothing()); - + + case CDFileType::SimpleTIM: + return FileProcessor::create(data_adr, file.payload.simple_tim); + +#ifdef __SUPPORT_VAG__ + case CDFileType::SonyVAG: + return FileProcessor::create(data_adr, file.payload.vag); +#endif //__SUPPORT_VAG__ + default: return FileProcessor::create_custom(data_adr, static_cast(file.type) - static_cast(CDFileType::Custom), file.payload); } diff --git a/src/Library/src/File/Processor/nothing_processor.cpp b/src/Library/src/File/Processor/nothing_processor.cpp index 613078e8..8d628e8f 100644 --- a/src/Library/src/File/Processor/nothing_processor.cpp +++ b/src/Library/src/File/Processor/nothing_processor.cpp @@ -10,7 +10,7 @@ namespace JabyEngine { } State create(const uint32_t* data_adr, const Nothing& nothing) { - return State::from(NothingState(), reinterpret_cast(data_adr), parse_nothing); + return State::from(NothingState(), data_adr, parse_nothing); } } } \ No newline at end of file diff --git a/src/Library/src/File/Processor/tim_processor.cpp b/src/Library/src/File/Processor/tim_processor.cpp index 7de8d882..4376faac 100644 --- a/src/Library/src/File/Processor/tim_processor.cpp +++ b/src/Library/src/File/Processor/tim_processor.cpp @@ -139,7 +139,7 @@ namespace JabyEngine { } State create(const uint32_t* data_adr, const SimpleTIM& file) { - return State::from(SimpleTIMState(file), reinterpret_cast(data_adr), parse_header); + return State::from(SimpleTIMState(file), data_adr, parse_header); } } } diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp new file mode 100644 index 00000000..55330468 --- /dev/null +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -0,0 +1,23 @@ +#include +#include + +#ifdef __SUPPORT_VAG__ +namespace JabyEngine { + namespace FileProcessor { + struct VAGState { + static constexpr VAGState create() { + return VAGState{}; + } + }; + + static Progress parse_header(State::Configuration& config, VAGState& state) { + printf("What am I supposed to do?!\n"); + return Progress::Error; + } + + State create(const uint32_t* data_adr, const VAG& file) { + return State::from(VAGState::create(), data_adr, parse_header); + } + } +} +#endif // __SUPPORT_VAG__ \ No newline at end of file From 0b340abb20a6cbc2016c9760d24bbb63d28f45f2 Mon Sep 17 00:00:00 2001 From: jaby Date: Tue, 6 Aug 2024 12:58:31 -0500 Subject: [PATCH 06/21] Parse VAG header --- include/PSX/Auxiliary/big_endian.hpp | 19 ++++++++++ .../src/File/Processor/vag_processor.cpp | 35 +++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 include/PSX/Auxiliary/big_endian.hpp diff --git a/include/PSX/Auxiliary/big_endian.hpp b/include/PSX/Auxiliary/big_endian.hpp new file mode 100644 index 00000000..4e24c32b --- /dev/null +++ b/include/PSX/Auxiliary/big_endian.hpp @@ -0,0 +1,19 @@ +#pragma once +#include "../jabyengine_defines.hpp" + +namespace JabyEngine { + // Taken from boost endian + + static constexpr uint8_t read_be(uint8_t x) { + return x; + } + + static constexpr uint16_t read_be(uint16_t x) { + return (x << 8) | (x >> 8); + } + + static constexpr uint32_t read_be(uint32_t x) { + const uint32_t step16 = x << 16 | x >> 16; + return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff); + } +} \ No newline at end of file diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 55330468..2966a4f2 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -1,9 +1,34 @@ +#include #include #include #ifdef __SUPPORT_VAG__ namespace JabyEngine { namespace FileProcessor { + #pragma pack(push, 1) + struct VAGHeader { + char id[4]; + uint32_t version; + uint32_t reserved; + uint32_t sample_size; + uint32_t sample_frequency; + uint8_t reserved_2[12]; + char name[16]; + + constexpr uint32_t get_version() const { + return read_be(this->version); + } + + constexpr uint32_t get_sample_size() const { + return read_be(this->sample_size); + } + + constexpr uint32_t get_sample_frequency() const { + return read_be(this->sample_frequency); + } + }; + #pragma pack(pop) + struct VAGState { static constexpr VAGState create() { return VAGState{}; @@ -11,8 +36,14 @@ namespace JabyEngine { }; static Progress parse_header(State::Configuration& config, VAGState& state) { - printf("What am I supposed to do?!\n"); - return Progress::Error; + if(config.data_bytes >= sizeof(VAGHeader)) { + const auto& header = *reinterpret_cast(config.data_adr); + + printf("VAG-ID: %s\nName: %s\nSample size: %i\nSample rate: %i\n", header.id, header.name, header.get_sample_size(), header.get_sample_frequency()); + return Progress::Error; + } + + return Progress::InProgress; } State create(const uint32_t* data_adr, const VAG& file) { From f18c1eb1377b730570426bcbf6c2dfe6e3cfe98c Mon Sep 17 00:00:00 2001 From: jaby Date: Wed, 7 Aug 2024 23:01:43 -0500 Subject: [PATCH 07/21] Add SPU memory allocation --- include/PSX/Auxiliary/math_helper.hpp | 10 ++ include/PSX/SPU/spu.hpp | 11 ++ include/PSX/System/IOPorts/spu_io.hpp | 7 +- .../internal-include/SPU/spu_internal.hpp | 2 + src/Library/src/BootLoader/start_boot.cpp | 23 ++++ .../src/File/Processor/vag_processor.cpp | 5 +- src/Library/src/SPU/spu.cpp | 127 ++++++++++++++++++ 7 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 include/PSX/SPU/spu.hpp create mode 100644 src/Library/internal-include/SPU/spu_internal.hpp create mode 100644 src/Library/src/SPU/spu.cpp diff --git a/include/PSX/Auxiliary/math_helper.hpp b/include/PSX/Auxiliary/math_helper.hpp index 1ef021b0..1f022241 100644 --- a/include/PSX/Auxiliary/math_helper.hpp +++ b/include/PSX/Auxiliary/math_helper.hpp @@ -34,4 +34,14 @@ namespace JabyEngine { } return result; } + + template + static constexpr T min_of(T a, T b) { + return (a < b) ? a : b; + } + + template + static constexpr T max_of(T a, T b) { + return (a > b) ? a : b; + } } \ No newline at end of file diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp new file mode 100644 index 00000000..a6f280d7 --- /dev/null +++ b/include/PSX/SPU/spu.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "../jabyengine.hpp" + +namespace JabyEngine { + namespace SPU { + const uint8_t* allocate_voice(uint8_t voice, size_t size); + void deallocate_voice(uint8_t voice); + + void dump(); + } +} \ No newline at end of file diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index afa9c3d7..801d4314 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -4,6 +4,10 @@ namespace JabyEngine { namespace SPU_IO { + namespace MemoryMap { + static constexpr uintptr_t ADPCM = 0x01000; + } + enum struct Mode { Linear = 0, Exponential = 1, @@ -126,7 +130,8 @@ namespace JabyEngine { static constexpr auto EchoBits = BitRange::from_to(0, 23); }; - static constexpr size_t VoiceCount = 24; + static constexpr size_t VoiceCount = 24; + static constexpr size_t ReverbCount = 1; struct Key { __declare_io_port_w_type(inline, ubus32_t, On, 0x1F801D88); diff --git a/src/Library/internal-include/SPU/spu_internal.hpp b/src/Library/internal-include/SPU/spu_internal.hpp new file mode 100644 index 00000000..77e81455 --- /dev/null +++ b/src/Library/internal-include/SPU/spu_internal.hpp @@ -0,0 +1,2 @@ +#pragma once + diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index 422484a2..9d47eec3 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include extern "C" uint32_t __heap_start; @@ -39,6 +41,26 @@ namespace JabyEngine { } } + static void test_spu_alloc() { + static const auto calculate_spu_adr = [](size_t size) -> const uint8_t* { + return reinterpret_cast(SPU_IO::MemoryMap::ADPCM + size); + }; + static const auto simple_assert = [](uint32_t test_id, const uint8_t* adr, const uint8_t* expected) { + static const char* ok_text = "Test %i: 0x%p == 0x%p; OK\n"; + static const char* failed_text = "Test %i: 0x%p != 0x%p; Failed\n"; + + printf(adr == expected ? ok_text : failed_text, test_id, adr, expected); + }; + + printf("=== SPU test ===\n"); + simple_assert(0, SPU::allocate_voice(0, 0x600), calculate_spu_adr(0x0)); + simple_assert(1, SPU::allocate_voice(1, 0x800), calculate_spu_adr(0x600)); + simple_assert(2, SPU::allocate_voice(0, 0x300), calculate_spu_adr(0x0)); + simple_assert(3, SPU::allocate_voice(2, 0x300), calculate_spu_adr(0x300)); + + // TODO: More tests + } + namespace boot { namespace Start { // Thanks to Nicolas Noble! @@ -77,6 +99,7 @@ namespace JabyEngine { GTE::setup(); test_bios_font(); test_gte_scale(); + test_spu_alloc(); SPU::setup(); } diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 2966a4f2..4dbe7291 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -5,7 +5,6 @@ #ifdef __SUPPORT_VAG__ namespace JabyEngine { namespace FileProcessor { - #pragma pack(push, 1) struct VAGHeader { char id[4]; uint32_t version; @@ -27,7 +26,6 @@ namespace JabyEngine { return read_be(this->sample_frequency); } }; - #pragma pack(pop) struct VAGState { static constexpr VAGState create() { @@ -39,7 +37,8 @@ namespace JabyEngine { if(config.data_bytes >= sizeof(VAGHeader)) { const auto& header = *reinterpret_cast(config.data_adr); - printf("VAG-ID: %s\nName: %s\nSample size: %i\nSample rate: %i\n", header.id, header.name, header.get_sample_size(), header.get_sample_frequency()); + //printf("VAG-ID: %s\nName: %s\nSample size: %i\nSample rate: %i\n", header.id, header.name, header.get_sample_size(), header.get_sample_frequency()); + // TODO: Allocate SPU memory return Progress::Error; } diff --git a/src/Library/src/SPU/spu.cpp b/src/Library/src/SPU/spu.cpp new file mode 100644 index 00000000..06544f74 --- /dev/null +++ b/src/Library/src/SPU/spu.cpp @@ -0,0 +1,127 @@ +#include "../../internal-include/SPU/spu_internal.hpp" +#include +#include +#include +#include + +#include + +namespace JabyEngine { + namespace SPU { + namespace SPU_MemoryMap = SPU_IO::MemoryMap; + + struct SPUMemory { + const uint8_t* adr; + size_t size; + + static SPUMemory create(size_t size) { + return SPUMemory{.adr = reinterpret_cast(SPU_MemoryMap::ADPCM), .size = size}; + } + + constexpr void clear() { + this->adr = nullptr; + this->size = 0; + } + + constexpr const uint8_t* get_end_adr() const { + return (this->adr + this->size); + } + + constexpr bool is_free() const { + return this->adr == nullptr; + } + + constexpr bool intersects(const SPUMemory& other) const { + const auto* min = max_of(this->adr, other.adr); + const auto* max = min_of(this->get_end_adr(), other.get_end_adr()); + return min < max; + } + }; + + struct AllocatedVoice { + SPUMemory memory; + AllocatedVoice* next_entry; + }; + + struct VoiceManager { + struct Iterator { + AllocatedVoice* *prev_voice; + AllocatedVoice* current_voice; + + void next() { + this->prev_voice = &this->current_voice->next_entry; + this->current_voice = this->current_voice->next_entry; + } + + bool has_next() const { + return this->current_voice; + } + + operator bool() const { + return Iterator::has_next(); + } + }; + + AllocatedVoice allocated_voice_buffer[SPU_IO::VoiceCount + SPU_IO::ReverbCount] = {0}; + AllocatedVoice* first_allocated_voice = nullptr; + + Iterator iterator() { + return Iterator{.prev_voice = &this->first_allocated_voice, .current_voice = this->first_allocated_voice}; + } + + AllocatedVoice& get_voice(uint8_t id) { + return this->allocated_voice_buffer[id]; + } + }; + + static VoiceManager voice_mgr; + + using MemoryFoundCallback = const uint8_t* (AllocatedVoice& new_entry, AllocatedVoice* &prev_entry, AllocatedVoice* next_entry); + + static const uint8_t* verify_and_add(AllocatedVoice& new_entry, AllocatedVoice* &prev_entry, AllocatedVoice* next_entry) { + // TODO: Verify that we are not crashing into reverb or that we are higher then SPU + prev_entry = &new_entry; + new_entry.next_entry = next_entry; + + return new_entry.memory.adr; + } + + static const uint8_t* find_first_fit(AllocatedVoice &new_entry, MemoryFoundCallback memory_found) { + auto iterator = voice_mgr.iterator(); + while(iterator) { + if(!iterator.current_voice->memory.intersects(new_entry.memory)) { + break; + } + new_entry.memory.adr = iterator.current_voice->memory.get_end_adr(); + iterator.next(); + } + + return memory_found(new_entry, *iterator.prev_voice, iterator.current_voice); + } + + const uint8_t* allocate_voice(uint8_t voice, size_t size) { + auto& voice_entry = voice_mgr.get_voice(voice); + if(!voice_entry.memory.is_free()) { + deallocate_voice(voice); + } + + voice_entry.memory = SPUMemory::create(size); + return find_first_fit(voice_entry, verify_and_add); + // TODO: Set memory adr for voice in SPU + } + + void deallocate_voice(uint8_t voice) { + auto* voice_adr = &voice_mgr.get_voice(voice); + auto iterator = voice_mgr.iterator(); + + voice_adr->memory.clear(); + while(iterator) { + if(iterator.current_voice == voice_adr) { + *iterator.prev_voice = voice_adr->next_entry; + break; + } + iterator.next(); + } + } + } +} \ No newline at end of file From 12de2340cc3c660289851e49686c53c037388cc4 Mon Sep 17 00:00:00 2001 From: jaby Date: Thu, 22 Aug 2024 20:13:07 +0200 Subject: [PATCH 08/21] Move voice memory manager code into brand new SPU MMU --- include/PSX/SPU/spu.hpp | 4 - src/Library/internal-include/SPU/spu_mmu.hpp | 9 ++ src/Library/src/BootLoader/start_boot.cpp | 9 +- src/Library/src/SPU/spu.cpp | 119 +----------------- src/Library/src/SPU/spu_mmu.cpp | 125 +++++++++++++++++++ 5 files changed, 140 insertions(+), 126 deletions(-) create mode 100644 src/Library/internal-include/SPU/spu_mmu.hpp create mode 100644 src/Library/src/SPU/spu_mmu.cpp diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp index a6f280d7..64e60eca 100644 --- a/include/PSX/SPU/spu.hpp +++ b/include/PSX/SPU/spu.hpp @@ -3,9 +3,5 @@ namespace JabyEngine { namespace SPU { - const uint8_t* allocate_voice(uint8_t voice, size_t size); - void deallocate_voice(uint8_t voice); - - void dump(); } } \ No newline at end of file diff --git a/src/Library/internal-include/SPU/spu_mmu.hpp b/src/Library/internal-include/SPU/spu_mmu.hpp new file mode 100644 index 00000000..58103f4e --- /dev/null +++ b/src/Library/internal-include/SPU/spu_mmu.hpp @@ -0,0 +1,9 @@ +#pragma once +#include + +namespace JabyEngine { + namespace SPU_MMU { + const uint8_t* allocate(uint8_t voice, size_t size); + void deallocate(uint8_t voice); + } +} \ No newline at end of file diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index 9d47eec3..ba68fea0 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -2,6 +2,7 @@ #include "../../internal-include/GPU/gpu_internal.hpp" #include +#include "../../internal-include/SPU/spu_mmu.hpp" #include #include #include @@ -53,10 +54,10 @@ namespace JabyEngine { }; printf("=== SPU test ===\n"); - simple_assert(0, SPU::allocate_voice(0, 0x600), calculate_spu_adr(0x0)); - simple_assert(1, SPU::allocate_voice(1, 0x800), calculate_spu_adr(0x600)); - simple_assert(2, SPU::allocate_voice(0, 0x300), calculate_spu_adr(0x0)); - simple_assert(3, SPU::allocate_voice(2, 0x300), calculate_spu_adr(0x300)); + simple_assert(0, SPU_MMU::allocate(0, 0x600), calculate_spu_adr(0x0)); + simple_assert(1, SPU_MMU::allocate(1, 0x800), calculate_spu_adr(0x600)); + simple_assert(2, SPU_MMU::allocate(0, 0x300), calculate_spu_adr(0x0)); + simple_assert(3, SPU_MMU::allocate(2, 0x300), calculate_spu_adr(0x300)); // TODO: More tests } diff --git a/src/Library/src/SPU/spu.cpp b/src/Library/src/SPU/spu.cpp index 06544f74..40e88543 100644 --- a/src/Library/src/SPU/spu.cpp +++ b/src/Library/src/SPU/spu.cpp @@ -1,127 +1,10 @@ #include "../../internal-include/SPU/spu_internal.hpp" +#include "../../internal-include/SPU/spu_mmu.hpp" #include -#include #include #include -#include - namespace JabyEngine { namespace SPU { - namespace SPU_MemoryMap = SPU_IO::MemoryMap; - - struct SPUMemory { - const uint8_t* adr; - size_t size; - - static SPUMemory create(size_t size) { - return SPUMemory{.adr = reinterpret_cast(SPU_MemoryMap::ADPCM), .size = size}; - } - - constexpr void clear() { - this->adr = nullptr; - this->size = 0; - } - - constexpr const uint8_t* get_end_adr() const { - return (this->adr + this->size); - } - - constexpr bool is_free() const { - return this->adr == nullptr; - } - - constexpr bool intersects(const SPUMemory& other) const { - const auto* min = max_of(this->adr, other.adr); - const auto* max = min_of(this->get_end_adr(), other.get_end_adr()); - return min < max; - } - }; - - struct AllocatedVoice { - SPUMemory memory; - AllocatedVoice* next_entry; - }; - - struct VoiceManager { - struct Iterator { - AllocatedVoice* *prev_voice; - AllocatedVoice* current_voice; - - void next() { - this->prev_voice = &this->current_voice->next_entry; - this->current_voice = this->current_voice->next_entry; - } - - bool has_next() const { - return this->current_voice; - } - - operator bool() const { - return Iterator::has_next(); - } - }; - - AllocatedVoice allocated_voice_buffer[SPU_IO::VoiceCount + SPU_IO::ReverbCount] = {0}; - AllocatedVoice* first_allocated_voice = nullptr; - - Iterator iterator() { - return Iterator{.prev_voice = &this->first_allocated_voice, .current_voice = this->first_allocated_voice}; - } - - AllocatedVoice& get_voice(uint8_t id) { - return this->allocated_voice_buffer[id]; - } - }; - - static VoiceManager voice_mgr; - - using MemoryFoundCallback = const uint8_t* (AllocatedVoice& new_entry, AllocatedVoice* &prev_entry, AllocatedVoice* next_entry); - - static const uint8_t* verify_and_add(AllocatedVoice& new_entry, AllocatedVoice* &prev_entry, AllocatedVoice* next_entry) { - // TODO: Verify that we are not crashing into reverb or that we are higher then SPU - prev_entry = &new_entry; - new_entry.next_entry = next_entry; - - return new_entry.memory.adr; - } - - static const uint8_t* find_first_fit(AllocatedVoice &new_entry, MemoryFoundCallback memory_found) { - auto iterator = voice_mgr.iterator(); - while(iterator) { - if(!iterator.current_voice->memory.intersects(new_entry.memory)) { - break; - } - new_entry.memory.adr = iterator.current_voice->memory.get_end_adr(); - iterator.next(); - } - - return memory_found(new_entry, *iterator.prev_voice, iterator.current_voice); - } - - const uint8_t* allocate_voice(uint8_t voice, size_t size) { - auto& voice_entry = voice_mgr.get_voice(voice); - if(!voice_entry.memory.is_free()) { - deallocate_voice(voice); - } - - voice_entry.memory = SPUMemory::create(size); - return find_first_fit(voice_entry, verify_and_add); - // TODO: Set memory adr for voice in SPU - } - - void deallocate_voice(uint8_t voice) { - auto* voice_adr = &voice_mgr.get_voice(voice); - auto iterator = voice_mgr.iterator(); - - voice_adr->memory.clear(); - while(iterator) { - if(iterator.current_voice == voice_adr) { - *iterator.prev_voice = voice_adr->next_entry; - break; - } - iterator.next(); - } - } } } \ No newline at end of file diff --git a/src/Library/src/SPU/spu_mmu.cpp b/src/Library/src/SPU/spu_mmu.cpp new file mode 100644 index 00000000..967d8b83 --- /dev/null +++ b/src/Library/src/SPU/spu_mmu.cpp @@ -0,0 +1,125 @@ +#include "../../internal-include/SPU/spu_mmu.hpp" +#include +#include +#include +#include + +namespace JabyEngine { + namespace SPU_MMU { + namespace SPU_MemoryMap = SPU_IO::MemoryMap; + + struct SPUMemory { + // TODO: v change to uint16_t?? + const uint8_t* adr; + size_t size; + + static SPUMemory create(size_t size) { + return SPUMemory{.adr = reinterpret_cast(SPU_MemoryMap::ADPCM), .size = size}; + } + + constexpr void clear() { + this->adr = nullptr; + this->size = 0; + } + + constexpr const uint8_t* get_end_adr() const { + return (this->adr + this->size); + } + + constexpr bool is_free() const { + return this->adr == nullptr; + } + + constexpr bool intersects(const SPUMemory& other) const { + const auto* min = max_of(this->adr, other.adr); + const auto* max = min_of(this->get_end_adr(), other.get_end_adr()); + return min < max; + } + }; + + struct AllocatedVoice { + SPUMemory memory; + AllocatedVoice* next_entry; + }; + + struct VoiceManager { + struct Iterator { + AllocatedVoice* *prev_voice; + AllocatedVoice* current_voice; + + void next() { + this->prev_voice = &this->current_voice->next_entry; + this->current_voice = this->current_voice->next_entry; + } + + bool has_next() const { + return this->current_voice; + } + + operator bool() const { + return Iterator::has_next(); + } + }; + + AllocatedVoice allocated_voice_buffer[SPU_IO::VoiceCount + SPU_IO::ReverbCount] = {0}; + AllocatedVoice* first_allocated_voice = nullptr; + + Iterator iterator() { + return Iterator{.prev_voice = &this->first_allocated_voice, .current_voice = this->first_allocated_voice}; + } + + AllocatedVoice& get_voice(uint8_t id) { + return this->allocated_voice_buffer[id]; + } + }; + + static VoiceManager voice_mgr; + + using MemoryFoundCallback = const uint8_t* (AllocatedVoice& new_entry, AllocatedVoice* &prev_entry, AllocatedVoice* next_entry); + + static const uint8_t* verify_and_add(AllocatedVoice& new_entry, AllocatedVoice* &prev_entry, AllocatedVoice* next_entry) { + // TODO: Verify that we are not crashing into reverb or that we are higher then SPU + prev_entry = &new_entry; + new_entry.next_entry = next_entry; + + return new_entry.memory.adr; + } + + static const uint8_t* find_first_fit(AllocatedVoice &new_entry, MemoryFoundCallback memory_found) { + auto iterator = voice_mgr.iterator(); + while(iterator) { + if(!iterator.current_voice->memory.intersects(new_entry.memory)) { + break; + } + new_entry.memory.adr = iterator.current_voice->memory.get_end_adr(); + iterator.next(); + } + + return memory_found(new_entry, *iterator.prev_voice, iterator.current_voice); + } + + const uint8_t* allocate(uint8_t voice, size_t size) { + auto& voice_entry = voice_mgr.get_voice(voice); + if(!voice_entry.memory.is_free()) { + deallocate(voice); + } + + voice_entry.memory = SPUMemory::create(size); + return find_first_fit(voice_entry, verify_and_add); + } + + void deallocate(uint8_t voice) { + auto* voice_adr = &voice_mgr.get_voice(voice); + auto iterator = voice_mgr.iterator(); + + voice_adr->memory.clear(); + while(iterator) { + if(iterator.current_voice == voice_adr) { + *iterator.prev_voice = voice_adr->next_entry; + break; + } + iterator.next(); + } + } + } +} \ No newline at end of file From 92b19ecabc90dafb524b1cc9cf6823ddcfad93fe Mon Sep 17 00:00:00 2001 From: jaby Date: Sat, 24 Aug 2024 14:25:05 +0200 Subject: [PATCH 09/21] Support new SPU voice approach --- include/PSX/SPU/spu.hpp | 27 ++++++++++++++++++++++++++- mkfile/psexe.ld | 2 +- src/Library/src/SPU/spu.cpp | 21 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp index 64e60eca..f18f2f63 100644 --- a/include/PSX/SPU/spu.hpp +++ b/include/PSX/SPU/spu.hpp @@ -1,7 +1,32 @@ #pragma once -#include "../jabyengine.hpp" +#include "../System/IOPorts/spu_io.hpp" namespace JabyEngine { namespace SPU { + using SRAM_Adr = uint16_t; + + struct Voice { + size_t get_id() const { + return reinterpret_cast(this); + } + + SRAM_Adr allocate(size_t size) const; + SRAM_Adr allocate(SPU_IO::SampleRate frequency, size_t size) const; + void deallocate() const; + + void set_sample_rate(SPU_IO::SampleRate frequency) const { + SPU_IO::Voice[Voice::get_id()].sampleRate.write(frequency); + } + + void play() const { + SPU_IO::Key::On.write(1 << Voice::get_id()); + } + + void stop() const { + SPU_IO::Key::Off.write(1 << Voice::get_id()); + } + }; + + extern const Voice voice[SPU_IO::VoiceCount]; } } \ No newline at end of file diff --git a/mkfile/psexe.ld b/mkfile/psexe.ld index d02aff2f..8b672b79 100644 --- a/mkfile/psexe.ld +++ b/mkfile/psexe.ld @@ -55,7 +55,7 @@ __stack_start = ORIGIN(ram) + LENGTH(ram); SECTIONS { .zero (NOLOAD) : { - _ZN10JabyEngine2CD4zeroE = .; + _ZN10JabyEngine3SPU5voiceE = .; } > zero .bios (NOLOAD) : { diff --git a/src/Library/src/SPU/spu.cpp b/src/Library/src/SPU/spu.cpp index 40e88543..d01cbf44 100644 --- a/src/Library/src/SPU/spu.cpp +++ b/src/Library/src/SPU/spu.cpp @@ -4,7 +4,28 @@ #include #include +#include + namespace JabyEngine { namespace SPU { + SRAM_Adr Voice :: allocate(size_t size) const { + Voice::stop(); + const auto voice_id = Voice::get_id(); + const auto adr = static_cast(reinterpret_cast(SPU_MMU::allocate(voice_id, size))); + + SPU_IO::Voice[voice_id].adr.write({adr}); + return adr; + } + + SRAM_Adr Voice :: allocate(SPU_IO::SampleRate frequency, size_t size) const { + const auto result = Voice::allocate(size); + Voice::set_sample_rate(frequency); + return result; + } + + void Voice :: deallocate() const { + Voice::stop(); + SPU_MMU::deallocate(Voice::get_id()); + } } } \ No newline at end of file From 0dcd2b71a6d88af09396d922e3b5dcbae1c938ba Mon Sep 17 00:00:00 2001 From: jaby Date: Fri, 6 Sep 2024 11:51:13 +0200 Subject: [PATCH 10/21] Allocate voice --- include/PSX/System/IOPorts/spu_io.hpp | 6 +++++- .../src/File/Processor/vag_processor.cpp | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index 801d4314..bc7cac38 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -41,10 +41,14 @@ namespace JabyEngine { }; __declare_io_value(SampleRate, uint16_t) { + static constexpr SampleRate from_HZ(uint32_t freq) { + constexpr uint32_t Base1024Hz = static_cast((4096.0/44100.0)*1024.0); + return {static_cast((freq >> 10)*Base1024Hz)}; + } + static constexpr SampleRate from_HZ(double freq) { //4096 == 44100Hz constexpr double Base = (4096.0 / 44100.0); - return {static_cast((freq*Base))}; } }; diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 4dbe7291..2a5a023c 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #ifdef __SUPPORT_VAG__ @@ -28,8 +29,12 @@ namespace JabyEngine { }; struct VAGState { - static constexpr VAGState create() { - return VAGState{}; + uint32_t voice_id; + size_t bytes_left; + SPU::SRAM_Adr adr; + + static constexpr VAGState create(uint32_t voice_id) { + return VAGState{.voice_id = voice_id, .bytes_left = 0, .adr = 0}; } }; @@ -37,8 +42,10 @@ namespace JabyEngine { if(config.data_bytes >= sizeof(VAGHeader)) { const auto& header = *reinterpret_cast(config.data_adr); - //printf("VAG-ID: %s\nName: %s\nSample size: %i\nSample rate: %i\n", header.id, header.name, header.get_sample_size(), header.get_sample_frequency()); - // TODO: Allocate SPU memory + state.bytes_left = header.get_sample_size(); + state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), state.bytes_left); + + // TODO: Parse samples return Progress::Error; } @@ -46,7 +53,7 @@ namespace JabyEngine { } State create(const uint32_t* data_adr, const VAG& file) { - return State::from(VAGState::create(), data_adr, parse_header); + return State::from(VAGState::create(file.voice_number), data_adr, parse_header); } } } From a4426ad5d2f4e070b7e83a80d4ed337ef58a911d Mon Sep 17 00:00:00 2001 From: jaby Date: Fri, 6 Sep 2024 18:32:09 +0100 Subject: [PATCH 11/21] Save state --- include/PSX/SPU/spu.hpp | 4 +- .../System/IOPorts/IOValues/spu_io_values.hpp | 29 ++++++++++++ include/PSX/System/IOPorts/ioport.hpp | 26 +++++++++++ include/PSX/System/IOPorts/spu_io.hpp | 45 +++++++++---------- readme.md | 11 ++++- .../internal-include/GPU/gpu_internal.hpp | 4 +- .../internal-include/SPU/spu_internal.hpp | 41 +++++++++++++++++ .../src/File/Processor/vag_processor.cpp | 15 +++++-- 8 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 include/PSX/System/IOPorts/IOValues/spu_io_values.hpp diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp index f18f2f63..ab92464e 100644 --- a/include/PSX/SPU/spu.hpp +++ b/include/PSX/SPU/spu.hpp @@ -3,8 +3,8 @@ namespace JabyEngine { namespace SPU { - using SRAM_Adr = uint16_t; - + using SRAM_Adr = SPU_IO::SRAM_Adr; + struct Voice { size_t get_id() const { return reinterpret_cast(this); diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp new file mode 100644 index 00000000..91491b61 --- /dev/null +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "../ioport.hpp" + +namespace JabyEngine { + namespace SPU_IO_Values { + __declare_io_value(ControlRegister, uint16_t) { + enum RAMTransferMode { + Stop = 0, + ManualWrite = 1, + DMAWrite = 2, + DMARead = 3 + }; + + static constexpr auto Enable = Bit(15); + static constexpr auto Unmute = Bit(14); + static constexpr auto NoiseFrequcenyShift = BitRange::from_to(10, 13); + static constexpr auto NoiseFrequcenyStep = BitRange::from_to(8, 9); + static constexpr auto ReverbMasterEnable = Bit(7); + static constexpr auto IRQ9Enable = Bit(6); + static constexpr auto TransferMode = BitRange::from_to(4, 5); + static constexpr auto ExternalAudioReverb = Bit(3); + static constexpr auto CDAudioReverb = Bit(2); + static constexpr auto ExternalAudioEnable = Bit(1); + static constexpr auto CDAudioEnable = Bit(0); + }; + + using SRAM_Adr = uint16_t; + } +} \ No newline at end of file diff --git a/include/PSX/System/IOPorts/ioport.hpp b/include/PSX/System/IOPorts/ioport.hpp index 5ae35ff9..c8bc09bd 100644 --- a/include/PSX/System/IOPorts/ioport.hpp +++ b/include/PSX/System/IOPorts/ioport.hpp @@ -74,8 +74,33 @@ namespace JabyEngine { } }; + template + struct IOPortX { + using Value = S; + + S read() const { + return S{*const_cast(reinterpret_cast(this))}; + } + + void write(S value) { + *const_cast(reinterpret_cast(this)) = value.raw; + } + }; + + template + struct IOPortX { + T read() const { + return *const_cast(reinterpret_cast(this)); + } + + void write(T value) { + *const_cast(reinterpret_cast(this)) = value; + } + }; + template struct IOPort { + using Value = T; T value; T read() const { @@ -89,6 +114,7 @@ namespace JabyEngine { template<> struct IOPort { + using Value = ubus32_t; ubus32_t value; ubus32_t read() const { diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index bc7cac38..737c378c 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -1,9 +1,11 @@ #pragma once -#include "ioport.hpp" +#include "IOValues/spu_io_values.hpp" #include namespace JabyEngine { namespace SPU_IO { + using namespace SPU_IO_Values; + namespace MemoryMap { static constexpr uintptr_t ADPCM = 0x01000; } @@ -30,6 +32,9 @@ namespace JabyEngine { typedef uint8_t Step; __declare_io_value(DataTransferControl, uint16_t) { + static constexpr DataTransferControl NormalTransferMode() { + return DataTransferControl{0x0004}; + } }; __declare_io_value(SimpleVolume, int16_t) { @@ -101,27 +106,6 @@ namespace JabyEngine { }; #pragma pack(pop) - __declare_io_value(ControlRegister, uint16_t) { - enum RAMTransferMode { - Stop = 0, - ManualWrite = 1, - DMAWrite = 2, - DMARead = 3 - }; - - static constexpr auto Enable = Bit(15); - static constexpr auto Unmute = Bit(14); - static constexpr auto NoiseFrequcenyShift = BitRange::from_to(10, 13); - static constexpr auto NoiseFrequcenyStep = BitRange::from_to(8, 9); - static constexpr auto ReverbMasterEnable = Bit(7); - static constexpr auto IRQ9Enable = Bit(6); - static constexpr auto TransferMode = BitRange::from_to(4, 5); - static constexpr auto ExternalAudioReverb = Bit(3); - static constexpr auto CDAudioReverb = Bit(2); - static constexpr auto ExternalAudioEnable = Bit(1); - static constexpr auto CDAudioEnable = Bit(0); - }; - __declare_io_value(PMON, uint16_t) { static constexpr auto EnableBits = BitRange::from_to(1, 23); }; @@ -170,7 +154,22 @@ namespace JabyEngine { return {static_cast(static_cast(I16_MAX)*fraction)}; } - __declare_io_port(, ControlRegister, 0x1F801DAA); + struct SRAMTransferAddressIO : public IOPortX {}; + + struct ControlRegisterIO : public IOPortX { + using TransferMode = Value::RAMTransferMode; + + void set_transfer_mode(TransferMode mode) { + this->write(this->read().set(ControlRegister::TransferMode.with(mode))); + while(this->read().get(ControlRegister::TransferMode) != mode); + } + }; + + // TODO: The new way? v Parse with a Macro? + static auto& ControlRegister = *reinterpret_cast(0x1F801DAA); + static auto& SRAMTransferAdr = *reinterpret_cast(0x1F801DA6); + + //__declare_io_port(, ControlRegister, 0x1F801DAA); __declare_io_port(, DataTransferControl, 0x1F801DAC); __declare_io_port(, PMON, 0x1F801D90); __declare_io_port(, NON, 0x1F801D94); diff --git a/readme.md b/readme.md index e8ce7758..e2659b0c 100644 --- a/readme.md +++ b/readme.md @@ -9,11 +9,18 @@ - [ ] Emulator - [ ] Real Hardware -# Todo +# TODO - [ ] Ko-fi supporter list - [ ] Support more GTE - [X] Easy serial code swap - [X] Support .subst files to be substituted with environment variables - [X] Support pop-fe - [ ] PS3 PKG generation tool? -- [ ] PS3 runtime detection? \ No newline at end of file +- [ ] PS3 runtime detection? +- [ ] Move DMA code to public include for custom loading of files? + - [ ] Maybe make it an interface with SPU/GPU as a specification...? + - [ ] Could be empty classes that the linker maps to 0 or somewhere + - [ ] Could be a all static struct (I like that better; We are not Nicolas Noble) + - [ ] Redo the IO ports again...? +- [ ] Support better file loading with threads + - [ ] Loading Screen with GPU IO? (Does DMA and IO work together?) \ No newline at end of file diff --git a/src/Library/internal-include/GPU/gpu_internal.hpp b/src/Library/internal-include/GPU/gpu_internal.hpp index dfdbcfcd..43f1ac3e 100644 --- a/src/Library/internal-include/GPU/gpu_internal.hpp +++ b/src/Library/internal-include/GPU/gpu_internal.hpp @@ -72,7 +72,7 @@ namespace JabyEngine { #endif // __SUPPORT_PS3__ static void wait() { - ::JabyEngine::DMA_IO::GPU.wait(); + DMA_IO::GPU.wait(); } static void end() { @@ -101,7 +101,7 @@ namespace JabyEngine { } static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { - typedef DMA_IO::BCR::SyncMode1 SyncMode1; + using SyncMode1 = DMA_IO::BCR::SyncMode1; #ifdef __SUPPORT_PS3__ DMA_IO::GPU.set_adr(MADR); diff --git a/src/Library/internal-include/SPU/spu_internal.hpp b/src/Library/internal-include/SPU/spu_internal.hpp index 77e81455..d47508fb 100644 --- a/src/Library/internal-include/SPU/spu_internal.hpp +++ b/src/Library/internal-include/SPU/spu_internal.hpp @@ -1,2 +1,43 @@ #pragma once +#include +#include +namespace JabyEngine { + namespace SPU { + namespace internal { + namespace DMA { + static void wait() { + DMA_IO::SPU.wait(); + } + + static void end() { + SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::Stop); + } + + namespace Receive { + static void prepare() { + SPU_IO::DataTransferControl.write(SPU_IO::DataTransferControl::NormalTransferMode()); + SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::Stop); + SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::DMAWrite); + } + + static void set_src(SPU::SRAM_Adr adr) { + DMA_IO::SPU.set_adr(adr); + } + + static void set_dst(SPU::SRAM_Adr adr) { + SPU_IO::SRAMTransferAdr.write(adr); + } + + // Not adjusted yet + static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { + using SyncMode1 = DMA_IO::BCR::SyncMode1; + + DMA_IO::SPU.block_ctrl.write(DMA_IO::BCR::from(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))); + DMA_IO::SPU.channel_ctrl.write(DMA_IO::CHCHR::StartSPUReceive()); + } + } + } + } + } +} diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 2a5a023c..66eaa616 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -1,3 +1,4 @@ +#include "../../../internal-include/SPU/spu_internal.hpp" #include #include #include @@ -38,15 +39,23 @@ namespace JabyEngine { } }; + static Progress parse_sample(State::Configuration& config, VAGState& state) { + // Load balancer? + + } + static Progress parse_header(State::Configuration& config, VAGState& state) { if(config.data_bytes >= sizeof(VAGHeader)) { const auto& header = *reinterpret_cast(config.data_adr); state.bytes_left = header.get_sample_size(); - state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), state.bytes_left); + state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), state.bytes_left); + + SPU::internal::DMA::Receive::prepare(); + SPU::internal::DMA::Receive::set_dst(state.adr); - // TODO: Parse samples - return Progress::Error; + config.processed(sizeof(VAGHeader)); + return Helper::exchange_and_execute_process_function(parse_sample, config, state); } return Progress::InProgress; From 97de0344583503089615b95eb3a52a7931e182c5 Mon Sep 17 00:00:00 2001 From: jaby Date: Fri, 6 Sep 2024 18:58:36 +0100 Subject: [PATCH 12/21] Update IOPort code and prepare DMA usage - needs all testing --- .../System/IOPorts/IOValues/spu_io_values.hpp | 4 +-- include/PSX/System/IOPorts/ioport.hpp | 29 ++----------------- include/PSX/System/IOPorts/spu_io.hpp | 14 ++++----- .../internal-include/SPU/spu_internal.hpp | 2 +- .../src/File/Processor/vag_processor.cpp | 2 +- src/Library/src/SPU/spu.cpp | 4 +-- 6 files changed, 14 insertions(+), 41 deletions(-) diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp index 91491b61..1416fe0f 100644 --- a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -23,7 +23,7 @@ namespace JabyEngine { static constexpr auto ExternalAudioEnable = Bit(1); static constexpr auto CDAudioEnable = Bit(0); }; - - using SRAM_Adr = uint16_t; + + __declare_io_value(SRAM_Adr, uint16_t) {}; } } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/ioport.hpp b/include/PSX/System/IOPorts/ioport.hpp index c8bc09bd..7bec4c6d 100644 --- a/include/PSX/System/IOPorts/ioport.hpp +++ b/include/PSX/System/IOPorts/ioport.hpp @@ -74,41 +74,16 @@ namespace JabyEngine { } }; - template - struct IOPortX { - using Value = S; - - S read() const { - return S{*const_cast(reinterpret_cast(this))}; - } - - void write(S value) { - *const_cast(reinterpret_cast(this)) = value.raw; - } - }; - - template - struct IOPortX { - T read() const { - return *const_cast(reinterpret_cast(this)); - } - - void write(T value) { - *const_cast(reinterpret_cast(this)) = value; - } - }; - template struct IOPort { using Value = T; - T value; T read() const { - return {const_cast*>(this)->value.raw}; + return {const_cast(reinterpret_cast(this))->raw}; } void write(T value) { - const_cast*>(this)->value.raw = value.raw; + const_cast(reinterpret_cast(this))->raw = value.raw; } }; diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index 737c378c..f6eb9b07 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -42,8 +42,6 @@ namespace JabyEngine { return this->raw; } }; - __declare_io_value(Adr, uint16_t) { - }; __declare_io_value(SampleRate, uint16_t) { static constexpr SampleRate from_HZ(uint32_t freq) { @@ -94,13 +92,13 @@ namespace JabyEngine { IOPort volumeLeft; //Offset: 0x0 IOPort volumeRight; //Offset: 0x2 IOPort sampleRate; //Offset: 0x4; - IOPort adr; //Offset: 0x6 + IOPort adr; //Offset: 0x6 IOPort ad; //Offset: 0x8 IOPort sr; //Offset: 0xA IOPort currentVolume; //Offset: 0xC - IOPort repeatAdr; //Offset: 0xE + IOPort repeatAdr; //Offset: 0xE - static constexpr Adr start_adr() { + static constexpr SRAM_Adr start_adr() { return {0x200}; } }; @@ -147,16 +145,16 @@ namespace JabyEngine { __declare_io_port_w_type(inline, SimpleVolume, Left, 0x1F801D84); __declare_io_port_w_type(inline, SimpleVolume, Right, 0x1F801D86); }; - __declare_io_port_w_type(inline, Adr, WorkAreaAdr, 0x1F801DA2); + __declare_io_port_w_type(inline, SRAM_Adr, WorkAreaAdr, 0x1F801DA2); }; static constexpr SimpleVolume operator""_vol(long double fraction) { return {static_cast(static_cast(I16_MAX)*fraction)}; } - struct SRAMTransferAddressIO : public IOPortX {}; + struct SRAMTransferAddressIO : public IOPort {}; - struct ControlRegisterIO : public IOPortX { + struct ControlRegisterIO : public IOPort { using TransferMode = Value::RAMTransferMode; void set_transfer_mode(TransferMode mode) { diff --git a/src/Library/internal-include/SPU/spu_internal.hpp b/src/Library/internal-include/SPU/spu_internal.hpp index d47508fb..b1bbdec0 100644 --- a/src/Library/internal-include/SPU/spu_internal.hpp +++ b/src/Library/internal-include/SPU/spu_internal.hpp @@ -21,7 +21,7 @@ namespace JabyEngine { SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::DMAWrite); } - static void set_src(SPU::SRAM_Adr adr) { + static void set_src(uintptr_t adr) { DMA_IO::SPU.set_adr(adr); } diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 66eaa616..9c0e77a2 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -41,7 +41,7 @@ namespace JabyEngine { static Progress parse_sample(State::Configuration& config, VAGState& state) { // Load balancer? - + return Progress::Error; } static Progress parse_header(State::Configuration& config, VAGState& state) { diff --git a/src/Library/src/SPU/spu.cpp b/src/Library/src/SPU/spu.cpp index d01cbf44..3b7a8c9b 100644 --- a/src/Library/src/SPU/spu.cpp +++ b/src/Library/src/SPU/spu.cpp @@ -11,9 +11,9 @@ namespace JabyEngine { SRAM_Adr Voice :: allocate(size_t size) const { Voice::stop(); const auto voice_id = Voice::get_id(); - const auto adr = static_cast(reinterpret_cast(SPU_MMU::allocate(voice_id, size))); + const auto adr = SRAM_Adr{static_cast(reinterpret_cast(SPU_MMU::allocate(voice_id, size)))}; - SPU_IO::Voice[voice_id].adr.write({adr}); + SPU_IO::Voice[voice_id].adr.write(adr); return adr; } From 0fb71beff2d3d3f763bd8b004febf76e77f3f6d7 Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 8 Sep 2024 22:57:29 +0200 Subject: [PATCH 13/21] Use original IOPort code again --- include/PSX/System/IOPorts/ioport.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/PSX/System/IOPorts/ioport.hpp b/include/PSX/System/IOPorts/ioport.hpp index 7bec4c6d..63c72ce0 100644 --- a/include/PSX/System/IOPorts/ioport.hpp +++ b/include/PSX/System/IOPorts/ioport.hpp @@ -77,13 +77,14 @@ namespace JabyEngine { template struct IOPort { using Value = T; + T value; T read() const { - return {const_cast(reinterpret_cast(this))->raw}; + return {const_cast*>(this)->value.raw}; } void write(T value) { - const_cast(reinterpret_cast(this))->raw = value.raw; + const_cast*>(this)->value.raw = value.raw; } }; From 2f0d972a2a427b01eff7700114b75442df8c78a9 Mon Sep 17 00:00:00 2001 From: jaby Date: Tue, 10 Sep 2024 22:50:05 +0200 Subject: [PATCH 14/21] Share commo DMA related code for use with SPU --- include/PSX/File/file_processor_helper.hpp | 49 +++++++++++++++++++ .../internal-include/GPU/gpu_internal.hpp | 14 +++--- .../internal-include/SPU/spu_internal.hpp | 8 +-- .../src/File/Processor/tim_processor.cpp | 43 ++-------------- .../src/File/Processor/vag_processor.cpp | 2 + src/Library/src/GPU/gpu.cpp | 8 ++- 6 files changed, 70 insertions(+), 54 deletions(-) diff --git a/include/PSX/File/file_processor_helper.hpp b/include/PSX/File/file_processor_helper.hpp index 26e8fb57..facc5af2 100644 --- a/include/PSX/File/file_processor_helper.hpp +++ b/include/PSX/File/file_processor_helper.hpp @@ -1,6 +1,7 @@ #pragma once #include "Processor/file_processor.hpp" #include "cd_file_types.hpp" +#include namespace JabyEngine { namespace FileProcessor { @@ -18,6 +19,54 @@ namespace JabyEngine { config.process_routine = reinterpret_cast(process_routine); return process_routine(config, state); } + + namespace DMA { + using words_t = size_t; + + struct WordsReady { + uint32_t words_to_use; + bool is_last; + + static constexpr WordsReady calculate(const State::Configuration& config, words_t words_left) { + const auto config_data_words = (config.data_bytes/sizeof(uint32_t)); + const auto words_to_use = (config_data_words > words_left) ? words_left : config_data_words; + + return { + .words_to_use = words_to_use, + .is_last = words_to_use == words_left + }; + } + }; + + template + static words_t send_words(words_t words_to_send, bool send_all) { + auto blocks_to_send = words_to_send/16; + while(blocks_to_send > 0) { + const auto block_send = (blocks_to_send > UI16_MAX) ? UI16_MAX : blocks_to_send; + + // Send data! + T::wait(); + T::Receive::start(blocks_to_send); + blocks_to_send -= block_send; + } + + if(send_all) { + const auto last_words_to_send = (words_to_send & 0b1111); + if(last_words_to_send > 0) { + T::wait(); + T::Receive::start(1, last_words_to_send); + } + + T::wait(); + T::end(); + return words_to_send; + } + + else { + return (words_to_send & ~0b1111); + } + } + } } } } \ No newline at end of file diff --git a/src/Library/internal-include/GPU/gpu_internal.hpp b/src/Library/internal-include/GPU/gpu_internal.hpp index 43f1ac3e..f497734f 100644 --- a/src/Library/internal-include/GPU/gpu_internal.hpp +++ b/src/Library/internal-include/GPU/gpu_internal.hpp @@ -65,10 +65,10 @@ namespace JabyEngine { GPU_IO::GP1.write(GPU_IO::Command::ResetCMDBufer()); } - namespace DMA { + struct DMA { #ifdef __SUPPORT_PS3__ // The PS3 doesn't autoincrement the GPU MADR register so we have to do it - extern uintptr_t MADR; + static uintptr_t MADR; #endif // __SUPPORT_PS3__ static void wait() { @@ -79,7 +79,7 @@ namespace JabyEngine { reset_cmd_buffer(); } - namespace Receive { + struct Receive { static void prepare() { GPU_IO::GP1.write(GPU_IO::Command::DMADirection(GPU_IO::DMADirection::CPU2GPU)); reset_cmd_buffer(); @@ -87,7 +87,7 @@ namespace JabyEngine { static void set_src(uintptr_t adr) { #ifdef __SUPPORT_PS3__ - MADR = adr; + DMA::MADR = adr; #else DMA_IO::GPU.set_adr(adr); #endif // __SUPPORT_PS3__ @@ -105,13 +105,13 @@ namespace JabyEngine { #ifdef __SUPPORT_PS3__ DMA_IO::GPU.set_adr(MADR); - MADR += (blockCount * wordsPerBlock) << 2; + DMA::MADR += (blockCount * wordsPerBlock) << 2; #endif // __SUPPORT_PS3__ DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR::from(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))); DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPUReceive()); } - } - } + }; + }; } } } \ No newline at end of file diff --git a/src/Library/internal-include/SPU/spu_internal.hpp b/src/Library/internal-include/SPU/spu_internal.hpp index b1bbdec0..21726d8a 100644 --- a/src/Library/internal-include/SPU/spu_internal.hpp +++ b/src/Library/internal-include/SPU/spu_internal.hpp @@ -5,7 +5,7 @@ namespace JabyEngine { namespace SPU { namespace internal { - namespace DMA { + struct DMA { static void wait() { DMA_IO::SPU.wait(); } @@ -14,7 +14,7 @@ namespace JabyEngine { SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::Stop); } - namespace Receive { + struct Receive { static void prepare() { SPU_IO::DataTransferControl.write(SPU_IO::DataTransferControl::NormalTransferMode()); SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::Stop); @@ -36,8 +36,8 @@ namespace JabyEngine { DMA_IO::SPU.block_ctrl.write(DMA_IO::BCR::from(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))); DMA_IO::SPU.channel_ctrl.write(DMA_IO::CHCHR::StartSPUReceive()); } - } - } + }; + }; } } } diff --git a/src/Library/src/File/Processor/tim_processor.cpp b/src/Library/src/File/Processor/tim_processor.cpp index 4376faac..f19e3e18 100644 --- a/src/Library/src/File/Processor/tim_processor.cpp +++ b/src/Library/src/File/Processor/tim_processor.cpp @@ -1,7 +1,6 @@ #include "../../../internal-include/GPU/gpu_internal.hpp" #include #include -#include #include namespace JabyEngine { @@ -63,44 +62,12 @@ namespace JabyEngine { } static Progress parse_data(State::Configuration& config, SimpleTIMState& state) { - const auto config_data_words = (config.data_bytes/sizeof(uint32_t)); - const auto words_to_use = (config_data_words > state.words_left) ? state.words_left : config_data_words; - bool is_last = (words_to_use == state.words_left); - auto block_count = (words_to_use >> 4); + const auto [words_to_use, is_last] = Helper::DMA::WordsReady::calculate(config, state.words_left); + const auto words_used = Helper::DMA::send_words(words_to_use, is_last); - while(block_count > 0) { - const auto block_send = (block_count > UI16_MAX) ? UI16_MAX : block_count; - - // Send data! - GPU::internal::DMA::wait(); - GPU::internal::DMA::Receive::start(block_send); - block_count -= block_send; - } - - if(is_last) { - // Send words - const auto last_words = (words_to_use & 0b1111); - if(last_words > 0) { - GPU::internal::DMA::wait(); - GPU::internal::DMA::Receive::start(1, last_words); - } - - GPU::internal::DMA::wait(); - GPU::internal::DMA::end(); - - state.words_left = 0; - config.processed(words_to_use*sizeof(uint32_t)); - - return Progress::Done; - } - - else { - const auto words_used = (words_to_use & ~0b1111); - - state.words_left -= words_used; - config.processed(words_used*sizeof(uint32_t)); - return Progress::InProgress; - } + state.words_left -= words_used; + config.processed(words_used*sizeof(uint32_t)); + return is_last ? Progress::Done : Progress::InProgress; } static Progress switch_state_parse_data(State::Configuration& config, SimpleTIMState& state) { diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 9c0e77a2..5734538d 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -41,6 +41,8 @@ namespace JabyEngine { static Progress parse_sample(State::Configuration& config, VAGState& state) { // Load balancer? + + return Progress::Error; } diff --git a/src/Library/src/GPU/gpu.cpp b/src/Library/src/GPU/gpu.cpp index f4215500..30feeaf0 100644 --- a/src/Library/src/GPU/gpu.cpp +++ b/src/Library/src/GPU/gpu.cpp @@ -8,11 +8,9 @@ namespace JabyEngine { uint8_t Display :: current_id = 1; //< Setup will call exchange and set it to 0 namespace internal { - namespace DMA { - #ifdef __SUPPORT_PS3__ - uintptr_t MADR = 0; - #endif // __SUPPORT_PS3__ - } + #ifdef __SUPPORT_PS3__ + uintptr_t DMA :: MADR = 0; + #endif // __SUPPORT_PS3__ static SysCall::InterruptVerifierResult interrupt_verifier(); static void interrupt_handler(uint32_t); From efd887268b186e0b77ff883867497fe9c3bda687 Mon Sep 17 00:00:00 2001 From: jaby Date: Mon, 16 Sep 2024 21:52:27 +0200 Subject: [PATCH 15/21] DMA SPU memory --- examples/PoolBox/application/src/menu.cpp | 2 ++ include/PSX/Auxiliary/word_helper.hpp | 15 +++++++++++ .../System/IOPorts/IOValues/spu_io_values.hpp | 16 ++++++++++++ include/PSX/System/IOPorts/spu_io.hpp | 3 +++ .../internal-include/SPU/spu_internal.hpp | 5 ++-- .../src/File/Processor/vag_processor.cpp | 25 +++++++++++-------- 6 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 include/PSX/Auxiliary/word_helper.hpp diff --git a/examples/PoolBox/application/src/menu.cpp b/examples/PoolBox/application/src/menu.cpp index 2eace68f..1dcbfd09 100644 --- a/examples/PoolBox/application/src/menu.cpp +++ b/examples/PoolBox/application/src/menu.cpp @@ -1,6 +1,7 @@ #include "../include/shared.hpp" #include "include/menu.hpp" #include +#include namespace Menu { using DigitalButton = Periphery::GenericController::Button; @@ -24,6 +25,7 @@ namespace Menu { } if(controller.button.went_down(DigitalButton::Cross)) { + SPU::voice[0].play(); this->selection_callback(this->cur_selection); } diff --git a/include/PSX/Auxiliary/word_helper.hpp b/include/PSX/Auxiliary/word_helper.hpp new file mode 100644 index 00000000..6675c8af --- /dev/null +++ b/include/PSX/Auxiliary/word_helper.hpp @@ -0,0 +1,15 @@ +#pragma once +#include + +namespace JabyEngine { + using word_t = uint32_t; + + static constexpr size_t bytes_to_words(size_t bytes) { + return bytes/sizeof(word_t); + } + + static constexpr size_t words_to_bytes(size_t words) { + return words*sizeof(word_t); + } +} + diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp index 1416fe0f..36dd32e2 100644 --- a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -24,6 +24,22 @@ namespace JabyEngine { static constexpr auto CDAudioEnable = Bit(0); }; + __declare_io_value(StatusRegister, uint16_t) { + static constexpr auto Unused = BitRange::from_to(12, 15); + static constexpr auto CaputreBufferHalf = Bit(11); // TODO: Turn into enum?; Writing to First/Second half of Capture Buffers (0=First, 1=Second) + static constexpr auto TransferBusy = Bit(10); + static constexpr auto IsDMARead = Bit(9); + static constexpr auto isDMAWrite = Bit(8); + static constexpr auto isDMA = Bit(7); + static constexpr auto isIRQ = Bit(6); + // Copies of ControlRegister + static constexpr auto TransferMode = BitRange::from_to(4, 5); + static constexpr auto ExternalAudioReverb = Bit(3); + static constexpr auto CDAudioReverb = Bit(2); + static constexpr auto ExternalAudioEnable = Bit(1); + static constexpr auto CDAudioEnable = Bit(0); + }; + __declare_io_value(SRAM_Adr, uint16_t) {}; } } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index f6eb9b07..9d6197ee 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -163,8 +163,11 @@ namespace JabyEngine { } }; + struct StatusRegisterIO : public IOPort {}; + // TODO: The new way? v Parse with a Macro? static auto& ControlRegister = *reinterpret_cast(0x1F801DAA); + static auto& StatusRegister = *reinterpret_cast(0x1F801DAE); static auto& SRAMTransferAdr = *reinterpret_cast(0x1F801DA6); //__declare_io_port(, ControlRegister, 0x1F801DAA); diff --git a/src/Library/internal-include/SPU/spu_internal.hpp b/src/Library/internal-include/SPU/spu_internal.hpp index 21726d8a..9cdf0805 100644 --- a/src/Library/internal-include/SPU/spu_internal.hpp +++ b/src/Library/internal-include/SPU/spu_internal.hpp @@ -8,6 +8,7 @@ namespace JabyEngine { struct DMA { static void wait() { DMA_IO::SPU.wait(); + while(SPU_IO::StatusRegister.read().is_set(SPU_IO_Values::StatusRegister::TransferBusy)); } static void end() { @@ -16,9 +17,9 @@ namespace JabyEngine { struct Receive { static void prepare() { + end(); SPU_IO::DataTransferControl.write(SPU_IO::DataTransferControl::NormalTransferMode()); SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::Stop); - SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::DMAWrite); } static void set_src(uintptr_t adr) { @@ -27,9 +28,9 @@ namespace JabyEngine { static void set_dst(SPU::SRAM_Adr adr) { SPU_IO::SRAMTransferAdr.write(adr); + SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::DMAWrite); } - // Not adjusted yet static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { using SyncMode1 = DMA_IO::BCR::SyncMode1; diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 5734538d..4468aca1 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -1,5 +1,6 @@ #include "../../../internal-include/SPU/spu_internal.hpp" #include +#include #include #include #include @@ -31,32 +32,36 @@ namespace JabyEngine { struct VAGState { uint32_t voice_id; - size_t bytes_left; + size_t words_left; SPU::SRAM_Adr adr; static constexpr VAGState create(uint32_t voice_id) { - return VAGState{.voice_id = voice_id, .bytes_left = 0, .adr = 0}; + return VAGState{.voice_id = voice_id, .words_left = 0, .adr = 0}; } }; static Progress parse_sample(State::Configuration& config, VAGState& state) { - // Load balancer? + const auto [words_to_use, is_last] = Helper::DMA::WordsReady::calculate(config, state.words_left); + const auto words_used = Helper::DMA::send_words(words_to_use, is_last); - - return Progress::Error; + state.words_left -= words_used; + config.processed(words_used*sizeof(uint32_t)); + return is_last ? Progress::Done : Progress::InProgress; } static Progress parse_header(State::Configuration& config, VAGState& state) { if(config.data_bytes >= sizeof(VAGHeader)) { const auto& header = *reinterpret_cast(config.data_adr); + const auto bytes = header.get_sample_size(); - state.bytes_left = header.get_sample_size(); - state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), state.bytes_left); - - SPU::internal::DMA::Receive::prepare(); - SPU::internal::DMA::Receive::set_dst(state.adr); + state.words_left = bytes_to_words(bytes); + state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), words_to_bytes(state.words_left)); config.processed(sizeof(VAGHeader)); + SPU::internal::DMA::Receive::prepare(); + SPU::internal::DMA::Receive::set_dst(state.adr); + SPU::internal::DMA::Receive::set_src(reinterpret_cast(config.data_adr)); + return Helper::exchange_and_execute_process_function(parse_sample, config, state); } From f138ca9a9d4c370097be64a5ac06856ac1c6aa09 Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 22 Sep 2024 14:29:05 +0200 Subject: [PATCH 16/21] Fix EON --- .../System/IOPorts/IOValues/spu_io_values.hpp | 33 +++++++++++++++++-- include/PSX/System/IOPorts/spu_io.hpp | 26 ++++++++++----- src/Library/src/BootLoader/spu_boot.cpp | 2 +- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp index 36dd32e2..29abad4e 100644 --- a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -3,6 +3,23 @@ namespace JabyEngine { namespace SPU_IO_Values { + namespace internal { + template + struct AliasUbus32IOPort : public IOPort { + T read() const { + return T{IOPort::read()}; + } + + void write(T value) { + IOPort::write(value.raw); + } + }; + + #define alias_ioport_ubus32(type) \ + template<> \ + struct IOPort : public SPU_IO_Values::internal::AliasUbus32IOPort {} + } + __declare_io_value(ControlRegister, uint16_t) { enum RAMTransferMode { Stop = 0, @@ -24,6 +41,17 @@ namespace JabyEngine { static constexpr auto CDAudioEnable = Bit(0); }; + __declare_io_value(Echo, ubus32_t) { + static constexpr auto EchoBits = BitRange::from_to(0, 23); + + static constexpr Echo AllOff() { + return Echo{0}; + } + }; + + __declare_io_value(SRAM_Adr, uint16_t) { + }; + __declare_io_value(StatusRegister, uint16_t) { static constexpr auto Unused = BitRange::from_to(12, 15); static constexpr auto CaputreBufferHalf = Bit(11); // TODO: Turn into enum?; Writing to First/Second half of Capture Buffers (0=First, 1=Second) @@ -38,8 +66,7 @@ namespace JabyEngine { static constexpr auto CDAudioReverb = Bit(2); static constexpr auto ExternalAudioEnable = Bit(1); static constexpr auto CDAudioEnable = Bit(0); - }; - - __declare_io_value(SRAM_Adr, uint16_t) {}; + }; } + alias_ioport_ubus32(SPU_IO_Values::Echo); } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index 9d6197ee..3c08c64e 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -104,18 +104,16 @@ namespace JabyEngine { }; #pragma pack(pop) + // TODO: This is ubus32_t __declare_io_value(PMON, uint16_t) { static constexpr auto EnableBits = BitRange::from_to(1, 23); }; + // TODO: This is ubus32_t __declare_io_value(NON, uint16_t) { static constexpr auto NoiseBits = BitRange::from_to(0, 23); }; - __declare_io_value(EON, uint16_t) { - static constexpr auto EchoBits = BitRange::from_to(0, 23); - }; - static constexpr size_t VoiceCount = 24; static constexpr size_t ReverbCount = 1; @@ -152,8 +150,7 @@ namespace JabyEngine { return {static_cast(static_cast(I16_MAX)*fraction)}; } - struct SRAMTransferAddressIO : public IOPort {}; - +//--------------------------------------------------------------------------------------------------- struct ControlRegisterIO : public IOPort { using TransferMode = Value::RAMTransferMode; @@ -163,18 +160,29 @@ namespace JabyEngine { } }; - struct StatusRegisterIO : public IOPort {}; + struct EchoIO : public IOPort { + }; + + struct StatusRegisterIO : public IOPort { + }; + + struct SRAMTransferAddressIO : public IOPort { + }; + // TODO: The new way? v Parse with a Macro? + static auto& EON = *reinterpret_cast(0x1F801D98); + static auto& SRAMTransferAdr = *reinterpret_cast(0x1F801DA6); static auto& ControlRegister = *reinterpret_cast(0x1F801DAA); static auto& StatusRegister = *reinterpret_cast(0x1F801DAE); - static auto& SRAMTransferAdr = *reinterpret_cast(0x1F801DA6); + +//--------------------------------------------------------------------------------------------------- //__declare_io_port(, ControlRegister, 0x1F801DAA); __declare_io_port(, DataTransferControl, 0x1F801DAC); __declare_io_port(, PMON, 0x1F801D90); __declare_io_port(, NON, 0x1F801D94); - __declare_io_port(, EON, 0x1F801D98); + //__declare_io_port(, EON, 0x1F801D98); __declare_io_port_array(, Voice, VoiceCount, 0x1F801C00); } diff --git a/src/Library/src/BootLoader/spu_boot.cpp b/src/Library/src/BootLoader/spu_boot.cpp index 2371f0f9..32d73491 100644 --- a/src/Library/src/BootLoader/spu_boot.cpp +++ b/src/Library/src/BootLoader/spu_boot.cpp @@ -42,7 +42,7 @@ namespace JabyEngine { static void clear_noise_and_echo() { SPU_IO::NON.write({0}); - SPU_IO::EON.write({0}); + SPU_IO::EON.write(Echo::AllOff()); } static void clear_reverb() { From acef4b8d68063dfc6294bc95cec28560d20302fe Mon Sep 17 00:00:00 2001 From: jaby Date: Sun, 22 Sep 2024 16:10:18 +0200 Subject: [PATCH 17/21] Update SPU IO way --- include/PSX/SPU/spu.hpp | 13 +- .../System/IOPorts/IOValues/spu_io_values.hpp | 167 ++++++++++++- include/PSX/System/IOPorts/ioport.hpp | 5 +- include/PSX/System/IOPorts/spu_io.hpp | 219 +++++------------- .../internal-include/SPU/spu_internal.hpp | 2 +- src/Library/src/BootLoader/spu_boot.cpp | 41 ++-- .../src/File/Processor/vag_processor.cpp | 6 +- src/Library/src/SPU/spu.cpp | 6 +- 8 files changed, 258 insertions(+), 201 deletions(-) diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp index ab92464e..84937d52 100644 --- a/include/PSX/SPU/spu.hpp +++ b/include/PSX/SPU/spu.hpp @@ -3,27 +3,28 @@ namespace JabyEngine { namespace SPU { - using SRAM_Adr = SPU_IO::SRAM_Adr; + using SRAMAdr = SPU_IO::SRAMAdr; + // TODO: Rename to sample...? struct Voice { size_t get_id() const { return reinterpret_cast(this); } - SRAM_Adr allocate(size_t size) const; - SRAM_Adr allocate(SPU_IO::SampleRate frequency, size_t size) const; - void deallocate() const; + SRAMAdr allocate(size_t size) const; + SRAMAdr allocate(SPU_IO::SampleRate frequency, size_t size) const; + void deallocate() const; void set_sample_rate(SPU_IO::SampleRate frequency) const { SPU_IO::Voice[Voice::get_id()].sampleRate.write(frequency); } void play() const { - SPU_IO::Key::On.write(1 << Voice::get_id()); + SPU_IO::Key::On.write(SPU_IO::KeyOn::for_specific(Voice::get_id())); } void stop() const { - SPU_IO::Key::Off.write(1 << Voice::get_id()); + SPU_IO::Key::Off.write(SPU_IO::KeyOff::for_specific(Voice::get_id())); } }; diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp index 29abad4e..8a5ae53c 100644 --- a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -1,5 +1,6 @@ #pragma once #include "../ioport.hpp" +#include namespace JabyEngine { namespace SPU_IO_Values { @@ -20,6 +21,22 @@ namespace JabyEngine { struct IOPort : public SPU_IO_Values::internal::AliasUbus32IOPort {} } + namespace MemoryMap { + static constexpr uintptr_t ADPCM = 0x01000; + } + + __declare_io_value(AD, uint16_t) { + static constexpr auto AttackMode = Bit(15); + static constexpr auto AttackShift = BitRange::from_to(10, 14); + static constexpr auto AttackStep = BitRange::from_to(8, 9); + static constexpr auto DecayShift = BitRange::from_to(4, 7); + static constexpr auto SustainLevel = BitRange::from_to(0, 3); + + static constexpr AD none() { + return AD{0}; + } + }; + __declare_io_value(ControlRegister, uint16_t) { enum RAMTransferMode { Stop = 0, @@ -41,6 +58,12 @@ namespace JabyEngine { static constexpr auto CDAudioEnable = Bit(0); }; + __declare_io_value(DataTransferControl, uint16_t) { + static constexpr DataTransferControl NormalTransferMode() { + return DataTransferControl{0x0004}; + } + }; + __declare_io_value(Echo, ubus32_t) { static constexpr auto EchoBits = BitRange::from_to(0, 23); @@ -49,12 +72,109 @@ namespace JabyEngine { } }; - __declare_io_value(SRAM_Adr, uint16_t) { + __declare_io_value(KeyOff, ubus32_t) { + static constexpr KeyOff for_specific(uint32_t id) { + return KeyOff{ubus32_t::from(1 << id)}; + } + + static constexpr KeyOff all() { + return KeyOff{ubus32_t::from(UI32_MAX)}; + } + }; + + __declare_io_value(KeyOn, ubus32_t) { + static constexpr KeyOn for_specific(uint32_t id) { + return KeyOn{ubus32_t::from(1 << id)}; + } + + static constexpr KeyOn all() { + return KeyOn{ubus32_t::from(UI32_MAX)}; + } + }; + + __declare_io_value(KeyStatus, ubus32_t) { + }; + + __declare_io_value(Noise, uint16_t) { + static constexpr auto NoiseBits = BitRange::from_to(0, 23); + + static constexpr Noise AllOff() { + return Noise{0}; + } + }; + + __declare_io_value(PitchModulation, ubus32_t) { + static constexpr auto EnableBits = BitRange::from_to(1, 23); + + static constexpr PitchModulation AllOff() { + return PitchModulation{0}; + } + }; + + __declare_io_value(SampleRate, uint16_t) { + static constexpr SampleRate stop() { + return SampleRate{0}; + } + + static constexpr SampleRate from_HZ(uint32_t freq) { + constexpr uint32_t Base1024Hz = static_cast((4096.0/44100.0)*1024.0); + return SampleRate{static_cast((freq >> 10)*Base1024Hz)}; + } + + static constexpr SampleRate from_HZ(double freq) { + //4096 == 44100Hz + constexpr double Base = (4096.0 / 44100.0); + return SampleRate{static_cast((freq*Base))}; + } + }; + + __declare_io_value(SimpleVolume, int16_t) { + static constexpr auto MaxVolume = I16_MAX; + + static constexpr SimpleVolume mute() { + return SimpleVolume{0}; + } + + constexpr operator int16_t() const { + return this->raw; + } + }; + + static constexpr SimpleVolume operator""_vol(long double fraction) { + return {static_cast(static_cast(SimpleVolume::MaxVolume)*fraction)}; + } + + __declare_io_value(SR, uint16_t) { + static constexpr auto SustainMode = Bit(31 - 16); + static constexpr auto SustainDirection = Bit(30 - 16); + static constexpr auto SustainShift = BitRange::from_to((24 - 16), (28 - 16)); + static constexpr auto SustainStep = BitRange::from_to((22 - 16), (23 - 16)); + static constexpr auto ReleaseMode = Bit(21 - 16); + static constexpr auto ReleaseShift = BitRange::from_to((16 - 16), (20 - 16)); + + static constexpr SR none() { + return SR{0}; + } + }; + + __declare_io_value(SRAMAdr, uint16_t) { + static constexpr SRAMAdr null() { + return SRAMAdr{0x0}; + } + + static constexpr SRAMAdr adpcm_start() { + return SRAMAdr{MemoryMap::ADPCM}; + } }; __declare_io_value(StatusRegister, uint16_t) { + enum CapureBufferHalf { + First = 0, + Second = 1 + }; + static constexpr auto Unused = BitRange::from_to(12, 15); - static constexpr auto CaputreBufferHalf = Bit(11); // TODO: Turn into enum?; Writing to First/Second half of Capture Buffers (0=First, 1=Second) + static constexpr auto CaputreBufferHalf = Bit(11); static constexpr auto TransferBusy = Bit(10); static constexpr auto IsDMARead = Bit(9); static constexpr auto isDMAWrite = Bit(8); @@ -66,7 +186,48 @@ namespace JabyEngine { static constexpr auto CDAudioReverb = Bit(2); static constexpr auto ExternalAudioEnable = Bit(1); static constexpr auto CDAudioEnable = Bit(0); - }; + }; + + __declare_io_value(SweepVolume, int16_t) { + struct VolumeMode { + static constexpr auto MaxVolume = (I16_MAX >> 1); + static constexpr auto EnableSweep = Bit(15); + static constexpr auto Enable = !EnableSweep; + static constexpr auto Volume = BitRange::from_to(0, 14); + }; + + struct SweepMode { + enum Mode { + Linear = 0, + Exponential = 1, + }; + + enum Direction { + Increase = 0, + Decrease = 1, + }; + + enum Phase { + Posititve = 0, + Negative = 1, + }; + + static constexpr auto Mode = Bit(14); + static constexpr auto Direction = Bit(13); + static constexpr auto Phase = Bit(12); + static constexpr auto Shift = BitRange::from_to(2, 6); + static constexpr auto Step = BitRange::from_to(0, 1); + }; + + static constexpr SweepVolume mute() { + return SweepVolume{0}; + } + }; } alias_ioport_ubus32(SPU_IO_Values::Echo); + alias_ioport_ubus32(SPU_IO_Values::Noise); + alias_ioport_ubus32(SPU_IO_Values::KeyOff); + alias_ioport_ubus32(SPU_IO_Values::KeyOn); + alias_ioport_ubus32(SPU_IO_Values::KeyStatus); + alias_ioport_ubus32(SPU_IO_Values::PitchModulation); } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/ioport.hpp b/include/PSX/System/IOPorts/ioport.hpp index 63c72ce0..d3033589 100644 --- a/include/PSX/System/IOPorts/ioport.hpp +++ b/include/PSX/System/IOPorts/ioport.hpp @@ -69,7 +69,7 @@ namespace JabyEngine { uint16_t low; uint16_t high; - static ubus32_t from(uint32_t value) { + static constexpr ubus32_t from(uint32_t value) { return {.low = static_cast(value & 0xFFFF), .high = static_cast(value >> 16)}; } }; @@ -117,4 +117,7 @@ namespace JabyEngine { #define __declare_io_port_w_type(cv, type, name, adr) __declare_value_at(cv, ::JabyEngine::IOPort, name, adr) #define __declare_io_port(cv, name, adr) __declare_io_port_w_type(cv, struct name, name, adr) #define __declare_io_port_array(cv, name, size, adr) __declare_array_at(cv, struct name, name, size, adr) + + #define __new_declare_io_port(type, adr) *reinterpret_cast(adr) + #define __new_declare_io_port_array(type, size, adr) reinterpret_cast(*reinterpret_cast(adr)) } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index 3c08c64e..ebf834fd 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -6,151 +6,9 @@ namespace JabyEngine { namespace SPU_IO { using namespace SPU_IO_Values; - namespace MemoryMap { - static constexpr uintptr_t ADPCM = 0x01000; - } - - enum struct Mode { - Linear = 0, - Exponential = 1, - }; - - enum struct Direction { - Increase = 0, - Decrease = 1, - }; - - enum struct Phase { - Posititve = 0, - Negative = 1, - }; - - //0..0x1F = Fast..Slow - typedef uint8_t Shift; - - //0..3 = +7, +6, +5, +4 or -6, -7, -6, -5 - typedef uint8_t Step; - - __declare_io_value(DataTransferControl, uint16_t) { - static constexpr DataTransferControl NormalTransferMode() { - return DataTransferControl{0x0004}; - } - }; - - __declare_io_value(SimpleVolume, int16_t) { - constexpr operator int16_t() const { - return this->raw; - } - }; - - __declare_io_value(SampleRate, uint16_t) { - static constexpr SampleRate from_HZ(uint32_t freq) { - constexpr uint32_t Base1024Hz = static_cast((4096.0/44100.0)*1024.0); - return {static_cast((freq >> 10)*Base1024Hz)}; - } - - static constexpr SampleRate from_HZ(double freq) { - //4096 == 44100Hz - constexpr double Base = (4096.0 / 44100.0); - return {static_cast((freq*Base))}; - } - }; - - __declare_io_value(SweepVolume, int16_t) { - // For Volume Mode - static constexpr auto SweepEnable = Bit(15); - static constexpr auto VolumeEnable = !SweepEnable; - static constexpr auto Volume = BitRange::from_to(0, 14); - - // For Sweep Mode - static constexpr auto SweepMode = Bit(14); - static constexpr auto SweepDirection = Bit(13); - static constexpr auto SweepPhase = Bit(12); - static constexpr auto SweepShift = BitRange::from_to(2, 6); - static constexpr auto SweepStep = BitRange::from_to(0, 1); - }; - - __declare_io_value(SR, uint16_t) { - static constexpr auto SustainMode = Bit(31 - 16); - static constexpr auto SustainDirection = Bit(30 - 16); - static constexpr auto SustainShift = BitRange::from_to((24 - 16), (28 - 16)); - static constexpr auto SustainStep = BitRange::from_to((22 - 16), (23 - 16)); - static constexpr auto ReleaseMode = Bit(21 - 16); - static constexpr auto ReleaseShift = BitRange::from_to((16 - 16), (20 - 16)); - }; - - __declare_io_value(AD, uint16_t) { - static constexpr auto AttackMode = Bit(15); - static constexpr auto AttackShift = BitRange::from_to(10, 14); - static constexpr auto AttackStep = BitRange::from_to(8, 9); - static constexpr auto DecayShift = BitRange::from_to(4, 7); - static constexpr auto SustainLevel = BitRange::from_to(0, 3); - }; - - #pragma pack(push, 1) - struct Voice { - IOPort volumeLeft; //Offset: 0x0 - IOPort volumeRight; //Offset: 0x2 - IOPort sampleRate; //Offset: 0x4; - IOPort adr; //Offset: 0x6 - IOPort ad; //Offset: 0x8 - IOPort sr; //Offset: 0xA - IOPort currentVolume; //Offset: 0xC - IOPort repeatAdr; //Offset: 0xE - - static constexpr SRAM_Adr start_adr() { - return {0x200}; - } - }; - #pragma pack(pop) - - // TODO: This is ubus32_t - __declare_io_value(PMON, uint16_t) { - static constexpr auto EnableBits = BitRange::from_to(1, 23); - }; - - // TODO: This is ubus32_t - __declare_io_value(NON, uint16_t) { - static constexpr auto NoiseBits = BitRange::from_to(0, 23); - }; - static constexpr size_t VoiceCount = 24; static constexpr size_t ReverbCount = 1; - struct Key { - __declare_io_port_w_type(inline, ubus32_t, On, 0x1F801D88); - __declare_io_port_w_type(inline, ubus32_t, Off, 0x1F801D8C); - __declare_io_port_w_type(inline, ubus32_t, Status, 0x1F801D9C); - }; - - struct MainVolume { - __declare_io_port_w_type(inline, SweepVolume, Left, 0x1F801D80); - __declare_io_port_w_type(inline, SweepVolume, Right, 0x1F801D82); - }; - - struct CDVolume { - __declare_io_port_w_type(inline, SimpleVolume, Left, 0x1F801DB0); - __declare_io_port_w_type(inline, SimpleVolume, Right, 0x1F801DB2); - }; - - struct ExternalAudioInputVolume { - __declare_io_port_w_type(inline, SimpleVolume, Left, 0x1F801DB4); - __declare_io_port_w_type(inline, SimpleVolume, Right, 0x1F801DB6); - }; - - struct Reverb { - struct Volume { - __declare_io_port_w_type(inline, SimpleVolume, Left, 0x1F801D84); - __declare_io_port_w_type(inline, SimpleVolume, Right, 0x1F801D86); - }; - __declare_io_port_w_type(inline, SRAM_Adr, WorkAreaAdr, 0x1F801DA2); - }; - - static constexpr SimpleVolume operator""_vol(long double fraction) { - return {static_cast(static_cast(I16_MAX)*fraction)}; - } - -//--------------------------------------------------------------------------------------------------- struct ControlRegisterIO : public IOPort { using TransferMode = Value::RAMTransferMode; @@ -160,30 +18,71 @@ namespace JabyEngine { } }; - struct EchoIO : public IOPort { + using ADIO = IOPort; + using DataTransferControlIO = IOPort; + using EchoIO = IOPort; + using KeyOffIO = IOPort; + using KeyOnIO = IOPort; + using KeyStatusIO = IOPort; + using NoiseIO = IOPort; + using PitchModulationIO = IOPort; + using SampleRateIO = IOPort; + using SimpleVolumeIO = IOPort; + using StatusRegisterIO = IOPort; + using SRIO = IOPort; + using SRAMAdrIO = IOPort; + using SweepVolumeIO = IOPort; + + #pragma pack(push, 1) + struct Voice { + SweepVolumeIO volumeLeft; //Offset: 0x0 + SweepVolumeIO volumeRight; //Offset: 0x2 + SampleRateIO sampleRate; //Offset: 0x4; + SRAMAdrIO adr; //Offset: 0x6 + ADIO ad; //Offset: 0x8 + SRIO sr; //Offset: 0xA + SimpleVolumeIO currentVolume; //Offset: 0xC + SRAMAdrIO repeatAdr; //Offset: 0xE + }; + #pragma pack(pop) + + static auto& Voice = __new_declare_io_port_array(struct Voice, VoiceCount, 0x1F801C00); + static auto& PMON = __new_declare_io_port(PitchModulationIO, 0x1F801D90); + static auto& NON = __new_declare_io_port(NoiseIO, 0x1F801D94); + static auto& EON = __new_declare_io_port(EchoIO, 0x1F801D98); + static auto& SRAMTransferAdr = __new_declare_io_port(SRAMAdrIO, 0x1F801DA6); + static auto& ControlRegister = __new_declare_io_port(ControlRegisterIO, 0x1F801DAA); + static auto& DataTransferControl = __new_declare_io_port(DataTransferControlIO, 0x1F801DAC); + static auto& StatusRegister = __new_declare_io_port(StatusRegisterIO, 0x1F801DAE); + + struct CDVolume { + static inline auto& Left = __new_declare_io_port(SimpleVolumeIO, 0x1F801DB0); + static inline auto& Right = __new_declare_io_port(SimpleVolumeIO, 0x1F801DB2); }; - struct StatusRegisterIO : public IOPort { + struct ExternalAudioInputVolume { + static inline auto& Left = __new_declare_io_port(SimpleVolumeIO, 0x1F801DB4); + static inline auto& Right = __new_declare_io_port(SimpleVolumeIO, 0x1F801DB6); }; - struct SRAMTransferAddressIO : public IOPort { + struct Key { + static inline auto& On = __new_declare_io_port(KeyOnIO, 0x1F801D88); + static inline auto& Off = __new_declare_io_port(KeyOffIO, 0x1F801D8C); + static inline auto& Status = __new_declare_io_port(KeyStatusIO, 0x1F801D9C); }; - - // TODO: The new way? v Parse with a Macro? - static auto& EON = *reinterpret_cast(0x1F801D98); - static auto& SRAMTransferAdr = *reinterpret_cast(0x1F801DA6); - static auto& ControlRegister = *reinterpret_cast(0x1F801DAA); - static auto& StatusRegister = *reinterpret_cast(0x1F801DAE); - -//--------------------------------------------------------------------------------------------------- + struct MainVolume { + static inline auto& Left = __new_declare_io_port(SweepVolumeIO, 0x1F801D80); + static inline auto& Right = __new_declare_io_port(SweepVolumeIO, 0x1F801D82); + }; - //__declare_io_port(, ControlRegister, 0x1F801DAA); - __declare_io_port(, DataTransferControl, 0x1F801DAC); - __declare_io_port(, PMON, 0x1F801D90); - __declare_io_port(, NON, 0x1F801D94); - //__declare_io_port(, EON, 0x1F801D98); - - __declare_io_port_array(, Voice, VoiceCount, 0x1F801C00); + struct Reverb { + struct Volume { + static inline auto& Left = __new_declare_io_port(SimpleVolumeIO, 0x1F801D84); + static inline auto& Right = __new_declare_io_port(SimpleVolumeIO, 0x1F801D86); + }; + static inline auto& On = EON; + static inline auto& WorkAreaAdr = __new_declare_io_port(SRAMAdrIO, 0x1F801DA2); + }; } } \ No newline at end of file diff --git a/src/Library/internal-include/SPU/spu_internal.hpp b/src/Library/internal-include/SPU/spu_internal.hpp index 9cdf0805..cb5e7776 100644 --- a/src/Library/internal-include/SPU/spu_internal.hpp +++ b/src/Library/internal-include/SPU/spu_internal.hpp @@ -26,7 +26,7 @@ namespace JabyEngine { DMA_IO::SPU.set_adr(adr); } - static void set_dst(SPU::SRAM_Adr adr) { + static void set_dst(SPU::SRAMAdr adr) { SPU_IO::SRAMTransferAdr.write(adr); SPU_IO::ControlRegister.set_transfer_mode(SPU_IO::ControlRegister::DMAWrite); } diff --git a/src/Library/src/BootLoader/spu_boot.cpp b/src/Library/src/BootLoader/spu_boot.cpp index 32d73491..d92d4534 100644 --- a/src/Library/src/BootLoader/spu_boot.cpp +++ b/src/Library/src/BootLoader/spu_boot.cpp @@ -8,7 +8,7 @@ namespace JabyEngine { using namespace SPU_IO; static void clear_main_volume() { - static constexpr auto StartVol = SweepVolume::from(SweepVolume::VolumeEnable, SweepVolume::Volume.with(static_cast(I16_MAX >> 2))); + static constexpr auto StartVol = SweepVolume::from(SweepVolume::VolumeMode::Enable, SweepVolume::VolumeMode::Volume.with(SweepVolume::VolumeMode::MaxVolume >> 1)); MainVolume::Left.write(StartVol); MainVolume::Right.write(StartVol); @@ -18,37 +18,37 @@ namespace JabyEngine { CDVolume::Left.write(0.75_vol); CDVolume::Right.write(0.75_vol); - ExternalAudioInputVolume::Left.write({0}); - ExternalAudioInputVolume::Right.write({0}); + ExternalAudioInputVolume::Left.write(SimpleVolume::mute()); + ExternalAudioInputVolume::Right.write(SimpleVolume::mute()); } static void clear_voice() { for(auto& voice : SPU_IO::Voice) { - voice.volumeLeft.write({0}); - voice.volumeRight.write({0}); - voice.sampleRate.write({0}); - voice.ad.write({0}); - voice.sr.write({0}); - voice.currentVolume.write({0}); + voice.volumeLeft.write(SweepVolume::mute()); + voice.volumeRight.write(SweepVolume::mute()); + voice.sampleRate.write(SampleRate::stop()); + voice.ad.write(AD::none()); + voice.sr.write(SR::none()); + voice.currentVolume.write(SimpleVolume::mute()); - voice.adr.write(Voice::start_adr()); - voice.repeatAdr.write(Voice::start_adr()); + voice.adr.write(SRAMAdr::adpcm_start()); + voice.repeatAdr.write(SRAMAdr::adpcm_start()); } } static void clear_pmon() { - SPU_IO::PMON.write({0}); + SPU_IO::PMON.write(PitchModulation::AllOff()); } static void clear_noise_and_echo() { - SPU_IO::NON.write({0}); + SPU_IO::NON.write(Noise::AllOff()); SPU_IO::EON.write(Echo::AllOff()); } static void clear_reverb() { - Reverb::Volume::Left.write({0}); - Reverb::Volume::Right.write({0}); - Reverb::WorkAreaAdr.write({0}); + Reverb::Volume::Left.write(SimpleVolume::mute()); + Reverb::Volume::Right.write(SimpleVolume::mute()); + Reverb::WorkAreaAdr.write(SRAMAdr::null()); } static void setup_control_register() { @@ -57,12 +57,6 @@ namespace JabyEngine { SPU_IO::ControlRegister.write(SetupValue); } - static void setup_data_transfer_control() { - static constexpr struct DataTransferControl RequiredValue{(2 << 1)}; - - DataTransferControl.write(RequiredValue); - } - static void wait_voices() { static constexpr SimpleVolume Treshhold{static_cast(I16_MAX*0.03)}; @@ -75,7 +69,7 @@ namespace JabyEngine { } void stop_voices() { - SPU_IO::Key::Off.write({UI32_MAX}); + SPU_IO::Key::Off.write(KeyOff::all()); } void setup() { @@ -88,7 +82,6 @@ namespace JabyEngine { clear_noise_and_echo(); clear_reverb(); - setup_data_transfer_control(); setup_control_register(); } } diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index 4468aca1..dec432df 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -31,9 +31,9 @@ namespace JabyEngine { }; struct VAGState { - uint32_t voice_id; - size_t words_left; - SPU::SRAM_Adr adr; + uint32_t voice_id; + size_t words_left; + SPU::SRAMAdr adr; static constexpr VAGState create(uint32_t voice_id) { return VAGState{.voice_id = voice_id, .words_left = 0, .adr = 0}; diff --git a/src/Library/src/SPU/spu.cpp b/src/Library/src/SPU/spu.cpp index 3b7a8c9b..f541152f 100644 --- a/src/Library/src/SPU/spu.cpp +++ b/src/Library/src/SPU/spu.cpp @@ -8,16 +8,16 @@ namespace JabyEngine { namespace SPU { - SRAM_Adr Voice :: allocate(size_t size) const { + SRAMAdr Voice :: allocate(size_t size) const { Voice::stop(); const auto voice_id = Voice::get_id(); - const auto adr = SRAM_Adr{static_cast(reinterpret_cast(SPU_MMU::allocate(voice_id, size)))}; + const auto adr = SRAMAdr{static_cast(reinterpret_cast(SPU_MMU::allocate(voice_id, size)))}; SPU_IO::Voice[voice_id].adr.write(adr); return adr; } - SRAM_Adr Voice :: allocate(SPU_IO::SampleRate frequency, size_t size) const { + SRAMAdr Voice :: allocate(SPU_IO::SampleRate frequency, size_t size) const { const auto result = Voice::allocate(size); Voice::set_sample_rate(frequency); return result; From f2800aaf1e8fbbc015abbcb45ed4eae70db2cbed Mon Sep 17 00:00:00 2001 From: jaby Date: Mon, 23 Sep 2024 19:59:52 +0200 Subject: [PATCH 18/21] Support SFX --- .../PoolBox/application/src/asset_mgr.cpp | 4 ++- include/PSX/File/file_types.hpp | 8 ++++-- include/PSX/SPU/spu.hpp | 28 +++++++++++++------ .../System/IOPorts/IOValues/spu_io_values.hpp | 4 +++ .../src/File/Processor/vag_processor.cpp | 18 ++++++------ src/Library/src/SPU/spu.cpp | 6 ++-- 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/examples/PoolBox/application/src/asset_mgr.cpp b/examples/PoolBox/application/src/asset_mgr.cpp index 326e648d..b6153c4a 100644 --- a/examples/PoolBox/application/src/asset_mgr.cpp +++ b/examples/PoolBox/application/src/asset_mgr.cpp @@ -59,10 +59,12 @@ namespace Assets { } namespace Main { + using SPU::operator""_vol; + static const CDFile Files[] = { CDFileBuilder::simple_tim(LBA::PACO, PacoTIM), CDFileBuilder::simple_tim(LBA::DFISH, DoenerFishInfo.tim), - CDFileBuilder::sony_vag(LBA::APPLE_SFX, VAG::create(0)), + CDFileBuilder::sony_vag(LBA::APPLE_SFX, VAG::create(0, 1.0_vol)), CustomCDFileBuilder::jingle(32), }; diff --git a/include/PSX/File/file_types.hpp b/include/PSX/File/file_types.hpp index 00a247cf..542dbf99 100644 --- a/include/PSX/File/file_types.hpp +++ b/include/PSX/File/file_types.hpp @@ -2,6 +2,7 @@ #include "../Auxiliary/bits.hpp" #include "../GPU/gpu_types.hpp" #include "../jabyengine_defines.hpp" +#include "../SPU/spu.hpp" namespace JabyEngine { #pragma pack(push, 1) @@ -68,10 +69,11 @@ namespace JabyEngine { }; struct VAG { - uint8_t voice_number; + uint8_t voice_number; + SPU::SimpleVolume inital_stereo_vol; - static constexpr VAG create(uint8_t voice_num) { - return VAG{.voice_number = voice_num}; + static constexpr VAG create(uint8_t voice_num, SPU::SimpleVolume volume) { + return VAG{.voice_number = voice_num, .inital_stereo_vol = volume}; } }; diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp index 84937d52..235bfb5f 100644 --- a/include/PSX/SPU/spu.hpp +++ b/include/PSX/SPU/spu.hpp @@ -3,31 +3,41 @@ namespace JabyEngine { namespace SPU { - using SRAMAdr = SPU_IO::SRAMAdr; + using SPU_IO::operator""_vol; + + using SRAMAdr = SPU_IO::SRAMAdr; + using SimpleVolume = SPU_IO::SimpleVolume; + using SweepVolume = SPU_IO::SweepVolume; // TODO: Rename to sample...? struct Voice { - size_t get_id() const { + size_t get_id() { return reinterpret_cast(this); } - SRAMAdr allocate(size_t size) const; - SRAMAdr allocate(SPU_IO::SampleRate frequency, size_t size) const; - void deallocate() const; + SRAMAdr allocate(size_t size); + SRAMAdr allocate(SPU_IO::SampleRate frequency, size_t size); + void deallocate(); - void set_sample_rate(SPU_IO::SampleRate frequency) const { + void set_sample_rate(SPU_IO::SampleRate frequency) { SPU_IO::Voice[Voice::get_id()].sampleRate.write(frequency); } - void play() const { + void set_volume(SimpleVolume left, SimpleVolume right) { + // TODO: Verify that assembly code is super simple + SPU_IO::Voice[Voice::get_id()].volumeLeft.write(SweepVolume::create(left)); + SPU_IO::Voice[Voice::get_id()].volumeRight.write(SweepVolume::create(right)); + } + + void play() { SPU_IO::Key::On.write(SPU_IO::KeyOn::for_specific(Voice::get_id())); } - void stop() const { + void stop() { SPU_IO::Key::Off.write(SPU_IO::KeyOff::for_specific(Voice::get_id())); } }; - extern const Voice voice[SPU_IO::VoiceCount]; + extern Voice voice[SPU_IO::VoiceCount]; } } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp index 8a5ae53c..d2a9bcbe 100644 --- a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -219,6 +219,10 @@ namespace JabyEngine { static constexpr auto Step = BitRange::from_to(0, 1); }; + static constexpr SweepVolume create(SimpleVolume volume) { + return from(VolumeMode::Enable, VolumeMode::Volume.with(volume.raw >> 1)); + } + static constexpr SweepVolume mute() { return SweepVolume{0}; } diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index dec432df..ff429dd8 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -31,12 +31,12 @@ namespace JabyEngine { }; struct VAGState { - uint32_t voice_id; - size_t words_left; - SPU::SRAMAdr adr; + uint32_t voice_id; + size_t words_left; + SPU::SimpleVolume inital_vol; - static constexpr VAGState create(uint32_t voice_id) { - return VAGState{.voice_id = voice_id, .words_left = 0, .adr = 0}; + static constexpr VAGState create(uint32_t voice_id, SPU::SimpleVolume inital_vol) { + return VAGState{.voice_id = voice_id, .words_left = 0, .inital_vol = inital_vol}; } }; @@ -55,11 +55,13 @@ namespace JabyEngine { const auto bytes = header.get_sample_size(); state.words_left = bytes_to_words(bytes); - state.adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), words_to_bytes(state.words_left)); + + auto sram_adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), words_to_bytes(state.words_left)); + SPU::voice[state.voice_id].set_volume(state.inital_vol, state.inital_vol); config.processed(sizeof(VAGHeader)); SPU::internal::DMA::Receive::prepare(); - SPU::internal::DMA::Receive::set_dst(state.adr); + SPU::internal::DMA::Receive::set_dst(sram_adr); SPU::internal::DMA::Receive::set_src(reinterpret_cast(config.data_adr)); return Helper::exchange_and_execute_process_function(parse_sample, config, state); @@ -69,7 +71,7 @@ namespace JabyEngine { } State create(const uint32_t* data_adr, const VAG& file) { - return State::from(VAGState::create(file.voice_number), data_adr, parse_header); + return State::from(VAGState::create(file.voice_number, file.inital_stereo_vol), data_adr, parse_header); } } } diff --git a/src/Library/src/SPU/spu.cpp b/src/Library/src/SPU/spu.cpp index f541152f..46042ad6 100644 --- a/src/Library/src/SPU/spu.cpp +++ b/src/Library/src/SPU/spu.cpp @@ -8,7 +8,7 @@ namespace JabyEngine { namespace SPU { - SRAMAdr Voice :: allocate(size_t size) const { + SRAMAdr Voice :: allocate(size_t size) { Voice::stop(); const auto voice_id = Voice::get_id(); const auto adr = SRAMAdr{static_cast(reinterpret_cast(SPU_MMU::allocate(voice_id, size)))}; @@ -17,13 +17,13 @@ namespace JabyEngine { return adr; } - SRAMAdr Voice :: allocate(SPU_IO::SampleRate frequency, size_t size) const { + SRAMAdr Voice :: allocate(SPU_IO::SampleRate frequency, size_t size) { const auto result = Voice::allocate(size); Voice::set_sample_rate(frequency); return result; } - void Voice :: deallocate() const { + void Voice :: deallocate() { Voice::stop(); SPU_MMU::deallocate(Voice::get_id()); } From b79dd4798219e034fe1e8a42e5074199b0c58f25 Mon Sep 17 00:00:00 2001 From: jaby Date: Tue, 24 Sep 2024 22:21:58 +0200 Subject: [PATCH 19/21] Improve SPU code and support state of voice --- include/PSX/SPU/spu.hpp | 15 +++++- .../System/IOPorts/IOValues/spu_io_values.hpp | 41 ++++------------ include/PSX/System/IOPorts/ioport.hpp | 48 +++++++++---------- include/PSX/System/IOPorts/spu_io.hpp | 10 ++-- src/Library/internal-include/SPU/spu_mmu.hpp | 1 + src/Library/src/BootLoader/start_boot.cpp | 2 +- .../src/File/Processor/vag_processor.cpp | 9 ++-- 7 files changed, 59 insertions(+), 67 deletions(-) diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp index 235bfb5f..dd1a7fd4 100644 --- a/include/PSX/SPU/spu.hpp +++ b/include/PSX/SPU/spu.hpp @@ -11,7 +11,7 @@ namespace JabyEngine { // TODO: Rename to sample...? struct Voice { - size_t get_id() { + size_t get_id() const { return reinterpret_cast(this); } @@ -33,11 +33,22 @@ namespace JabyEngine { SPU_IO::Key::On.write(SPU_IO::KeyOn::for_specific(Voice::get_id())); } + void play_if_end() { + if(Voice::is_end()) { + Voice::play(); + } + } + void stop() { SPU_IO::Key::Off.write(SPU_IO::KeyOff::for_specific(Voice::get_id())); } + + bool is_end() const { + // TODO: Make work in XEBRA + return SPU_IO::Key::Status.read().is_set(Voice::get_id()); + } }; - extern Voice voice[SPU_IO::VoiceCount]; + static auto& voice = __new_declare_io_port_array(Voice, SPU_IO::VoiceCount, 0x0); } } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp index d2a9bcbe..72865aee 100644 --- a/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp +++ b/include/PSX/System/IOPorts/IOValues/spu_io_values.hpp @@ -4,23 +4,6 @@ namespace JabyEngine { namespace SPU_IO_Values { - namespace internal { - template - struct AliasUbus32IOPort : public IOPort { - T read() const { - return T{IOPort::read()}; - } - - void write(T value) { - IOPort::write(value.raw); - } - }; - - #define alias_ioport_ubus32(type) \ - template<> \ - struct IOPort : public SPU_IO_Values::internal::AliasUbus32IOPort {} - } - namespace MemoryMap { static constexpr uintptr_t ADPCM = 0x01000; } @@ -64,7 +47,7 @@ namespace JabyEngine { } }; - __declare_io_value(Echo, ubus32_t) { + __declare_io_value(Echo, uint32_t) { static constexpr auto EchoBits = BitRange::from_to(0, 23); static constexpr Echo AllOff() { @@ -72,27 +55,27 @@ namespace JabyEngine { } }; - __declare_io_value(KeyOff, ubus32_t) { + __declare_io_value(KeyOff, uint32_t) { static constexpr KeyOff for_specific(uint32_t id) { - return KeyOff{ubus32_t::from(1 << id)}; + return KeyOff{1u << id}; } static constexpr KeyOff all() { - return KeyOff{ubus32_t::from(UI32_MAX)}; + return KeyOff{UI32_MAX}; } }; - __declare_io_value(KeyOn, ubus32_t) { + __declare_io_value(KeyOn, uint32_t) { static constexpr KeyOn for_specific(uint32_t id) { - return KeyOn{ubus32_t::from(1 << id)}; + return KeyOn{1u << id}; } static constexpr KeyOn all() { - return KeyOn{ubus32_t::from(UI32_MAX)}; + return KeyOn{UI32_MAX}; } }; - __declare_io_value(KeyStatus, ubus32_t) { + __declare_io_value(KeyStatus, uint32_t) { }; __declare_io_value(Noise, uint16_t) { @@ -103,7 +86,7 @@ namespace JabyEngine { } }; - __declare_io_value(PitchModulation, ubus32_t) { + __declare_io_value(PitchModulation, uint32_t) { static constexpr auto EnableBits = BitRange::from_to(1, 23); static constexpr PitchModulation AllOff() { @@ -228,10 +211,4 @@ namespace JabyEngine { } }; } - alias_ioport_ubus32(SPU_IO_Values::Echo); - alias_ioport_ubus32(SPU_IO_Values::Noise); - alias_ioport_ubus32(SPU_IO_Values::KeyOff); - alias_ioport_ubus32(SPU_IO_Values::KeyOn); - alias_ioport_ubus32(SPU_IO_Values::KeyStatus); - alias_ioport_ubus32(SPU_IO_Values::PitchModulation); } \ No newline at end of file diff --git a/include/PSX/System/IOPorts/ioport.hpp b/include/PSX/System/IOPorts/ioport.hpp index d3033589..264af11b 100644 --- a/include/PSX/System/IOPorts/ioport.hpp +++ b/include/PSX/System/IOPorts/ioport.hpp @@ -65,15 +65,6 @@ namespace JabyEngine { }; } - struct ubus32_t { - uint16_t low; - uint16_t high; - - static constexpr ubus32_t from(uint32_t value) { - return {.low = static_cast(value & 0xFFFF), .high = static_cast(value >> 16)}; - } - }; - template struct IOPort { using Value = T; @@ -89,25 +80,34 @@ namespace JabyEngine { }; template<> - struct IOPort { - using Value = ubus32_t; - ubus32_t value; + struct IOPort; - ubus32_t read() const { - auto*const cv_this = const_cast*>(this); - - return {.low = cv_this->value.low, .high = cv_this->value.high}; + template + struct IOPort32 { + union ValueHelper { + struct { + uint16_t low; + uint16_t high; + }; + T value; + }; + using Value = T; + T value; + + T read() const { + const auto* cast_this = reinterpret_cast*>(this); + const volatile auto* cv_this = const_cast(cast_this); + + return ValueHelper{.low = cv_this->value.low, .high = cv_this->value.high}.value; } - void write(ubus32_t value) { - auto*const cv_this = const_cast*>(this); + void write(T value) { + const auto new_value = ValueHelper{.value = value}; + auto* cast_this = reinterpret_cast*>(this); + volatile auto* v_this = const_cast(cast_this); - cv_this->value.low = value.low; - cv_this->value.high = value.high; - } - - void write(uint32_t value) { - IOPort::write(ubus32_t::from(value)); + v_this->value.low = new_value.low; + v_this->value.high = new_value.high; } }; diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index ebf834fd..72279b27 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -20,12 +20,12 @@ namespace JabyEngine { using ADIO = IOPort; using DataTransferControlIO = IOPort; - using EchoIO = IOPort; - using KeyOffIO = IOPort; - using KeyOnIO = IOPort; - using KeyStatusIO = IOPort; + using EchoIO = IOPort32; + using KeyOffIO = IOPort32; + using KeyOnIO = IOPort32; + using KeyStatusIO = IOPort32; using NoiseIO = IOPort; - using PitchModulationIO = IOPort; + using PitchModulationIO = IOPort32; using SampleRateIO = IOPort; using SimpleVolumeIO = IOPort; using StatusRegisterIO = IOPort; diff --git a/src/Library/internal-include/SPU/spu_mmu.hpp b/src/Library/internal-include/SPU/spu_mmu.hpp index 58103f4e..7ed0560d 100644 --- a/src/Library/internal-include/SPU/spu_mmu.hpp +++ b/src/Library/internal-include/SPU/spu_mmu.hpp @@ -3,6 +3,7 @@ namespace JabyEngine { namespace SPU_MMU { + // TODO: Make this work with words? Word align? const uint8_t* allocate(uint8_t voice, size_t size); void deallocate(uint8_t voice); } diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index ba68fea0..177250bd 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -59,7 +59,7 @@ namespace JabyEngine { simple_assert(2, SPU_MMU::allocate(0, 0x300), calculate_spu_adr(0x0)); simple_assert(3, SPU_MMU::allocate(2, 0x300), calculate_spu_adr(0x300)); - // TODO: More tests + // TODO: More tests } namespace boot { diff --git a/src/Library/src/File/Processor/vag_processor.cpp b/src/Library/src/File/Processor/vag_processor.cpp index ff429dd8..3d256035 100644 --- a/src/Library/src/File/Processor/vag_processor.cpp +++ b/src/Library/src/File/Processor/vag_processor.cpp @@ -52,11 +52,14 @@ namespace JabyEngine { static Progress parse_header(State::Configuration& config, VAGState& state) { if(config.data_bytes >= sizeof(VAGHeader)) { const auto& header = *reinterpret_cast(config.data_adr); - const auto bytes = header.get_sample_size(); + const auto words = bytes_to_words(header.get_sample_size()); + const auto bytes = words_to_bytes(words); - state.words_left = bytes_to_words(bytes); + state.words_left = words; - auto sram_adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), words_to_bytes(state.words_left)); + auto sram_adr = SPU::voice[state.voice_id].allocate(SPU_IO::SampleRate::from_HZ(header.get_sample_frequency()), bytes); + // TODO: Keep this as optional? + printf("SPU: Allocated %i @0x%p to 0x%p (%i bytes)\n", state.voice_id, sram_adr.raw, (sram_adr.raw + bytes), bytes); SPU::voice[state.voice_id].set_volume(state.inital_vol, state.inital_vol); config.processed(sizeof(VAGHeader)); From 714ef195d3fc153c923fd0ab8237e0f23ed63f0c Mon Sep 17 00:00:00 2001 From: jaby Date: Tue, 24 Sep 2024 22:22:19 +0200 Subject: [PATCH 20/21] Play bubble sound when pressing buttons --- .../src/Overlay/ControllerTest/controller_state.cpp | 8 ++++++++ examples/PoolBox/application/src/asset_mgr.cpp | 2 ++ examples/PoolBox/assets/Makefile | 1 + examples/PoolBox/iso/Config.xml | 2 ++ 4 files changed, 13 insertions(+) diff --git a/examples/PoolBox/application/src/Overlay/ControllerTest/controller_state.cpp b/examples/PoolBox/application/src/Overlay/ControllerTest/controller_state.cpp index cda13cab..5d2919b8 100644 --- a/examples/PoolBox/application/src/Overlay/ControllerTest/controller_state.cpp +++ b/examples/PoolBox/application/src/Overlay/ControllerTest/controller_state.cpp @@ -1,5 +1,6 @@ #include "include/controller_state.hpp" #include +#include namespace ControllerTest { using DigitalButton = Periphery::AnalogeController::Button; @@ -7,6 +8,9 @@ namespace ControllerTest { static void set_active(GPU::SPRT_16::Linked& sprt, bool is_active) { sprt->tex_offset.y = is_active ? 16 : 0; + if(is_active) { + SPU::voice[1].play_if_end(); + } } static void set_active(GPU::POLY_FT4::Linked& poly, bool is_active) { @@ -14,6 +18,10 @@ namespace ControllerTest { poly->tex_offset1.y = is_active ? 16 : 0; poly->tex_offset2.y = is_active ? 32 : 16; poly->tex_offset3.y = is_active ? 32 : 16; + + if(is_active) { + SPU::voice[1].play_if_end(); + } } static const char* get_type_name(Periphery::ControllerType type) { diff --git a/examples/PoolBox/application/src/asset_mgr.cpp b/examples/PoolBox/application/src/asset_mgr.cpp index b6153c4a..54f9ab99 100644 --- a/examples/PoolBox/application/src/asset_mgr.cpp +++ b/examples/PoolBox/application/src/asset_mgr.cpp @@ -18,6 +18,7 @@ namespace Assets { __jabyengine_request_lba_for(PACO, "ASSETS/MAIN/PACO.IMG"), __jabyengine_request_lba_for(DFISH, "ASSETS/MAIN/DFISH.IMG"), __jabyengine_request_lba_for(APPLE_SFX, "SFX/APPLE.VAG"), + __jabyengine_request_lba_for(BLUBB_SFX, "SFX/BLUBB.VAG"), __jabyengine_request_lba_for(MIX_XA, "XAAUDIO/MIX.XA"), __jabyengine_request_lba_for(BIOS_INFO_OVL, "BIO.BIN"), __jabyengine_request_lba_for(GPU_TEST_OVL, "GTO.BIN"), @@ -65,6 +66,7 @@ namespace Assets { CDFileBuilder::simple_tim(LBA::PACO, PacoTIM), CDFileBuilder::simple_tim(LBA::DFISH, DoenerFishInfo.tim), CDFileBuilder::sony_vag(LBA::APPLE_SFX, VAG::create(0, 1.0_vol)), + CDFileBuilder::sony_vag(LBA::BLUBB_SFX, VAG::create(1, 1.0_vol)), CustomCDFileBuilder::jingle(32), }; diff --git a/examples/PoolBox/assets/Makefile b/examples/PoolBox/assets/Makefile index 9ba30da4..c93cc47b 100644 --- a/examples/PoolBox/assets/Makefile +++ b/examples/PoolBox/assets/Makefile @@ -13,6 +13,7 @@ CLUT_4_COLOR_TRANS_FLAGS = simple-tim clut4 --color-trans INPUT += $(OUTPUT_DIR)/Evacuation_cdda.xa INPUT += $(OUTPUT_DIR)/fox.xa INPUT += $(OUTPUT_DIR)/apple.vag +INPUT += $(OUTPUT_DIR)/blubb.vag ## Images INPUT += $(OUTPUT_DIR)/TexturePage.img diff --git a/examples/PoolBox/iso/Config.xml b/examples/PoolBox/iso/Config.xml index 56bc04a2..bcb3da94 100644 --- a/examples/PoolBox/iso/Config.xml +++ b/examples/PoolBox/iso/Config.xml @@ -45,7 +45,9 @@ ../assets/audio/temp/breaking.wav From a36b489dfd12c6b2b3fd3870f2f347f8114dac60 Mon Sep 17 00:00:00 2001 From: jaby Date: Thu, 26 Sep 2024 21:40:15 +0200 Subject: [PATCH 21/21] Fix XEBA and Voice::is_end code --- include/PSX/SPU/spu.hpp | 3 +-- include/PSX/System/IOPorts/spu_io.hpp | 16 ++++++++-------- src/Library/src/BootLoader/spu_boot.cpp | 6 +++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/PSX/SPU/spu.hpp b/include/PSX/SPU/spu.hpp index dd1a7fd4..769579e2 100644 --- a/include/PSX/SPU/spu.hpp +++ b/include/PSX/SPU/spu.hpp @@ -44,8 +44,7 @@ namespace JabyEngine { } bool is_end() const { - // TODO: Make work in XEBRA - return SPU_IO::Key::Status.read().is_set(Voice::get_id()); + return SPU_IO::Voice[Voice::get_id()].adsr_volume.read() == SimpleVolume::mute(); } }; diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index 72279b27..1b7638a7 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -35,14 +35,14 @@ namespace JabyEngine { #pragma pack(push, 1) struct Voice { - SweepVolumeIO volumeLeft; //Offset: 0x0 - SweepVolumeIO volumeRight; //Offset: 0x2 - SampleRateIO sampleRate; //Offset: 0x4; - SRAMAdrIO adr; //Offset: 0x6 - ADIO ad; //Offset: 0x8 - SRIO sr; //Offset: 0xA - SimpleVolumeIO currentVolume; //Offset: 0xC - SRAMAdrIO repeatAdr; //Offset: 0xE + SweepVolumeIO volumeLeft; //Offset: 0x0 + SweepVolumeIO volumeRight; //Offset: 0x2 + SampleRateIO sampleRate; //Offset: 0x4; + SRAMAdrIO adr; //Offset: 0x6 + ADIO ad; //Offset: 0x8 + SRIO sr; //Offset: 0xA + SimpleVolumeIO adsr_volume; //Offset: 0xC + SRAMAdrIO repeatAdr; //Offset: 0xE }; #pragma pack(pop) diff --git a/src/Library/src/BootLoader/spu_boot.cpp b/src/Library/src/BootLoader/spu_boot.cpp index d92d4534..ea1d6ea0 100644 --- a/src/Library/src/BootLoader/spu_boot.cpp +++ b/src/Library/src/BootLoader/spu_boot.cpp @@ -29,7 +29,7 @@ namespace JabyEngine { voice.sampleRate.write(SampleRate::stop()); voice.ad.write(AD::none()); voice.sr.write(SR::none()); - voice.currentVolume.write(SimpleVolume::mute()); + voice.adsr_volume.write(SimpleVolume::mute()); voice.adr.write(SRAMAdr::adpcm_start()); voice.repeatAdr.write(SRAMAdr::adpcm_start()); @@ -58,11 +58,11 @@ namespace JabyEngine { } static void wait_voices() { - static constexpr SimpleVolume Treshhold{static_cast(I16_MAX*0.03)}; + static constexpr auto Treshhold = SimpleVolume::mute(); try_again: for(const auto& voice : SPU_IO::Voice) { - if(voice.currentVolume.read() > Treshhold) { + if(voice.adsr_volume.read() > Treshhold) { goto try_again; } }