Improve SPU code and support state of voice
This commit is contained in:
parent
f2800aaf1e
commit
b79dd47982
|
@ -11,7 +11,7 @@ namespace JabyEngine {
|
|||
|
||||
// TODO: Rename to sample...?
|
||||
struct Voice {
|
||||
size_t get_id() {
|
||||
size_t get_id() const {
|
||||
return reinterpret_cast<size_t>(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);
|
||||
}
|
||||
}
|
|
@ -4,23 +4,6 @@
|
|||
|
||||
namespace JabyEngine {
|
||||
namespace SPU_IO_Values {
|
||||
namespace internal {
|
||||
template<typename T>
|
||||
struct AliasUbus32IOPort : public IOPort<ubus32_t> {
|
||||
T read() const {
|
||||
return T{IOPort<ubus32_t>::read()};
|
||||
}
|
||||
|
||||
void write(T value) {
|
||||
IOPort<ubus32_t>::write(value.raw);
|
||||
}
|
||||
};
|
||||
|
||||
#define alias_ioport_ubus32(type) \
|
||||
template<> \
|
||||
struct IOPort<type> : public SPU_IO_Values::internal::AliasUbus32IOPort<type> {}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -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<uint16_t>(value & 0xFFFF), .high = static_cast<uint16_t>(value >> 16)};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IOPort {
|
||||
using Value = T;
|
||||
|
@ -89,25 +80,34 @@ namespace JabyEngine {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct IOPort<ubus32_t> {
|
||||
using Value = ubus32_t;
|
||||
ubus32_t value;
|
||||
struct IOPort<uint32_t>;
|
||||
|
||||
ubus32_t read() const {
|
||||
auto*const cv_this = const_cast<const volatile IOPort<ubus32_t>*>(this);
|
||||
|
||||
return {.low = cv_this->value.low, .high = cv_this->value.high};
|
||||
template<typename T>
|
||||
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<const IOPort32<ValueHelper>*>(this);
|
||||
const volatile auto* cv_this = const_cast<volatile decltype(cast_this)>(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<volatile IOPort<ubus32_t>*>(this);
|
||||
void write(T value) {
|
||||
const auto new_value = ValueHelper{.value = value};
|
||||
auto* cast_this = reinterpret_cast<IOPort32<ValueHelper>*>(this);
|
||||
volatile auto* v_this = const_cast<volatile decltype(cast_this)>(cast_this);
|
||||
|
||||
cv_this->value.low = value.low;
|
||||
cv_this->value.high = value.high;
|
||||
}
|
||||
|
||||
void write(uint32_t value) {
|
||||
IOPort<ubus32_t>::write(ubus32_t::from(value));
|
||||
v_this->value.low = new_value.low;
|
||||
v_this->value.high = new_value.high;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,12 +20,12 @@ namespace JabyEngine {
|
|||
|
||||
using ADIO = IOPort<SPU_IO_Values::AD>;
|
||||
using DataTransferControlIO = IOPort<SPU_IO_Values::DataTransferControl>;
|
||||
using EchoIO = IOPort<SPU_IO_Values::Echo>;
|
||||
using KeyOffIO = IOPort<SPU_IO_Values::KeyOff>;
|
||||
using KeyOnIO = IOPort<SPU_IO_Values::KeyOn>;
|
||||
using KeyStatusIO = IOPort<SPU_IO_Values::KeyStatus>;
|
||||
using EchoIO = IOPort32<SPU_IO_Values::Echo>;
|
||||
using KeyOffIO = IOPort32<SPU_IO_Values::KeyOff>;
|
||||
using KeyOnIO = IOPort32<SPU_IO_Values::KeyOn>;
|
||||
using KeyStatusIO = IOPort32<SPU_IO_Values::KeyStatus>;
|
||||
using NoiseIO = IOPort<SPU_IO_Values::Noise>;
|
||||
using PitchModulationIO = IOPort<SPU_IO_Values::PitchModulation>;
|
||||
using PitchModulationIO = IOPort32<SPU_IO_Values::PitchModulation>;
|
||||
using SampleRateIO = IOPort<SPU_IO_Values::SampleRate>;
|
||||
using SimpleVolumeIO = IOPort<SPU_IO_Values::SimpleVolume>;
|
||||
using StatusRegisterIO = IOPort<SPU_IO_Values::StatusRegister>;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<const VAGHeader*>(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));
|
||||
|
|
Loading…
Reference in New Issue