jabyengine/src/Library/src/File/Processor/vag_processor.cpp

78 lines
3.1 KiB
C++

#include "../../../internal-include/SPU/spu_internal.hpp"
#include <PSX/Auxiliary/big_endian.hpp>
#include <PSX/Auxiliary/word_helper.hpp>
#include <PSX/File/file_processor_helper.hpp>
#include <PSX/SPU/spu.hpp>
#include <stdio.hpp>
namespace JabyEngine {
namespace FileProcessor {
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);
}
};
struct VAGState {
uint32_t voice_id;
size_t words_left;
SPU::SimpleVolume inital_vol;
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};
}
};
static Progress parse_sample(State::Configuration& config, VAGState& state) {
const auto [words_to_use, is_last] = Helper::DMA::WordsReady::calculate(config, state.words_left);
const auto words_used = Helper::DMA::send_words<SPU::internal::DMA>(words_to_use, is_last);
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<const VAGHeader*>(config.data_adr);
const auto words = bytes_to_words(header.get_sample_size());
const auto bytes = words_to_bytes(words);
state.words_left = words;
auto sram_adr = SPU::voice[state.voice_id].allocate(SPU_IO_Values::SampleRate::from_HZ(header.get_sample_frequency()), bytes);
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(sram_adr);
SPU::internal::DMA::Receive::set_src(reinterpret_cast<uintptr_t>(config.data_adr));
return Helper::exchange_and_execute_process_function(parse_sample, config, state);
}
return Progress::InProgress;
}
State create(const uint32_t* data_adr, const VAG& file) {
return State::from(VAGState::create(file.voice_number, file.inital_stereo_vol), data_adr, parse_header);
}
}
}