Move voice memory manager code into brand new SPU MMU
This commit is contained in:
parent
f18c1eb137
commit
12de2340cc
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
#include <PSX/jabyengine.hpp>
|
||||
|
||||
namespace JabyEngine {
|
||||
namespace SPU_MMU {
|
||||
const uint8_t* allocate(uint8_t voice, size_t size);
|
||||
void deallocate(uint8_t voice);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#include "../../internal-include/GPU/gpu_internal.hpp"
|
||||
#include <stdio.hpp>
|
||||
|
||||
#include "../../internal-include/SPU/spu_mmu.hpp"
|
||||
#include <PSX/GTE/gte.hpp>
|
||||
#include <PSX/SPU/spu.hpp>
|
||||
#include <PSX/System/IOPorts/spu_io.hpp>
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1,127 +1,10 @@
|
|||
#include "../../internal-include/SPU/spu_internal.hpp"
|
||||
#include "../../internal-include/SPU/spu_mmu.hpp"
|
||||
#include <PSX/System/IOPorts/spu_io.hpp>
|
||||
#include <PSX/Auxiliary/math_helper.hpp>
|
||||
#include <PSX/SPU/spu.hpp>
|
||||
#include <stddef.hpp>
|
||||
|
||||
#include <stdio.hpp>
|
||||
|
||||
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<const uint8_t*>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
#include "../../internal-include/SPU/spu_mmu.hpp"
|
||||
#include <PSX/System/IOPorts/spu_io.hpp>
|
||||
#include <PSX/Auxiliary/math_helper.hpp>
|
||||
#include <PSX/SPU/spu.hpp>
|
||||
#include <stddef.hpp>
|
||||
|
||||
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<const uint8_t*>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue