Integrate CircularBuffer as essential part of loading files from CD and dedicate file processing to the FileProcessor

This commit is contained in:
Jaby 2023-04-01 11:20:56 +02:00 committed by Jaby
parent d66c437d4c
commit 1b169cb35f
7 changed files with 85 additions and 53 deletions

View File

@ -11,6 +11,10 @@ namespace JabyEngine {
Progress progress; Progress progress;
size_t bytes_ready; size_t bytes_ready;
constexpr operator bool() const {
return this->progress != Progress::Error;
}
static constexpr Result new_error() { static constexpr Result new_error() {
return {Progress::Error, 0}; return {Progress::Error, 0};
} }
@ -27,6 +31,7 @@ namespace JabyEngine {
private: private:
struct State { struct State {
enum struct Step { enum struct Step {
Disabled,
ReadToken, ReadToken,
ObtainLiteralLength, ObtainLiteralLength,
CopyLiterals, CopyLiterals,
@ -35,12 +40,23 @@ namespace JabyEngine {
CopyMatch, CopyMatch,
}; };
Step step = Step::ReadToken; Step step = Step::Disabled;
size_t literal_length = 0; size_t literal_length = 0;
size_t match_length = 0; size_t match_length = 0;
uint16_t match_offset = 0xFFFF; uint16_t match_offset = 0;
State() = default; State() = default;
void enable() {
this->step = Step::ReadToken;
this->literal_length = 0;
this->match_length = 0;
this->match_offset = 0xFFFF;
}
void disable() {
this->step = Step::Disabled;
}
}; };
private: private:
@ -56,7 +72,7 @@ namespace JabyEngine {
} }
void setup(uint8_t* dst_adr); void setup(uint8_t* dst_adr);
void reset(); void disable();
Result process(ArrayRange<const uint8_t> data, bool is_last); Result process(ArrayRange<const uint8_t> data, bool is_last);
}; };

View File

@ -25,17 +25,15 @@ namespace JabyEngine {
}; };
private: private:
FileProcessor::State file_pro_state; FileProcessor::State file_state;
CircularBuffer<CD_IO::DataSector> circular_buffer; CircularBuffer<CD_IO::DataSector> circular_buffer;
LZ4Decompressor lz4_decomp; LZ4Decompressor lz4_decomp;
JobArray jobs; JobArray jobs;
const AutoLBAEntry* lba = nullptr; const AutoLBAEntry* lba = nullptr;
uint32_t*const tmp_area = nullptr; //< The start of the area to copy data to uint32_t*const tmp_area = nullptr; //< The start of the area to copy data to for the file processor
uint32_t* dst_area = nullptr; //< Current target for copying the data
void start_cur_job(); void start_cur_job();
void reading_state(const CDFile& file); bool process_data();
void done_state(const CDFile& file);
public: public:
CDFileProcessor() = default; CDFileProcessor() = default;

View File

@ -51,6 +51,8 @@ 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 SimpleTIM& file);
} }
} }

View File

@ -1,8 +1,12 @@
#ifndef __JABYENGINE_FILE_TYPES_HPP__ #ifndef __JABYENGINE_FILE_TYPES_HPP__
#define __JABYENGINE_FILE_TYPES_HPP__ #define __JABYENGINE_FILE_TYPES_HPP__
#include "../Auxiliary/bits.hpp"
#include "../jabyengine_defines.h" #include "../jabyengine_defines.h"
namespace JabyEngine { namespace JabyEngine {
struct __no_align Nothing {
};
struct __no_align SimpleTIM { struct __no_align SimpleTIM {
static constexpr auto TextureX = BitRange::from_to(0, 8); static constexpr auto TextureX = BitRange::from_to(0, 8);
static constexpr auto TextureY = BitRange::from_to(9, 16); static constexpr auto TextureY = BitRange::from_to(9, 16);

View File

@ -24,11 +24,11 @@ namespace JabyEngine {
void LZ4Decompressor :: setup(uint8_t* dst_adr) { void LZ4Decompressor :: setup(uint8_t* dst_adr) {
this->dst_adr = dst_adr; this->dst_adr = dst_adr;
LZ4Decompressor::reset(); this->state.enable();
} }
void LZ4Decompressor :: reset() { void LZ4Decompressor :: disable() {
this->state = State(); this->state.disable();
} }
LZ4Decompressor::Result LZ4Decompressor :: process(ArrayRange<const uint8_t> data, bool is_last) { LZ4Decompressor::Result LZ4Decompressor :: process(ArrayRange<const uint8_t> data, bool is_last) {
@ -36,6 +36,9 @@ namespace JabyEngine {
while(data) { while(data) {
switch(this->state.step) { switch(this->state.step) {
case State::Step::Disabled:
return Result::new_done(data.size);
case State::Step::ReadToken: { case State::Step::ReadToken: {
const auto token = data.pop(); const auto token = data.pop();

View File

@ -3,6 +3,8 @@
#include <stdio.h> #include <stdio.h>
namespace JabyEngine { namespace JabyEngine {
static constexpr auto NormalCircularBufferSize = 5;
void CDFileProcessor :: start_cur_job() { void CDFileProcessor :: start_cur_job() {
using CD::internal::FileInfo; using CD::internal::FileInfo;
using CD::internal::SectorBufferAllocator; using CD::internal::SectorBufferAllocator;
@ -11,13 +13,6 @@ namespace JabyEngine {
CDFileProcessor &self = *reinterpret_cast<CDFileProcessor*>(ctx); CDFileProcessor &self = *reinterpret_cast<CDFileProcessor*>(ctx);
return self.circular_buffer.allocate(); return self.circular_buffer.allocate();
}; };
static const auto direct_copy_callback = [](void* ctx) -> CD_IO::DataSector* {
auto** data_sector = reinterpret_cast<CD_IO::DataSector**>(ctx);
auto* cur_sector = *data_sector;
data_sector += sizeof(CD_IO::DataSector);
return cur_sector;
};
switch(file.type) { switch(file.type) {
case CDFileType::SimpleTIM: case CDFileType::SimpleTIM:
@ -25,8 +20,11 @@ namespace JabyEngine {
return SectorBufferAllocator::invalid(); return SectorBufferAllocator::invalid();
case CDFileType::CopyTo: case CDFileType::CopyTo:
this->dst_area = file.payload.copy_to.dst; this->circular_buffer.setup(reinterpret_cast<CD_IO::DataSector*>(file.payload.copy_to.dst), 512);
return SectorBufferAllocator::create(&this->dst_area, direct_copy_callback); this->lz4_decomp.disable();
this->file_state = FileProcessor::create(this->tmp_area, Nothing());
return SectorBufferAllocator::create(this, circular_buffer_callback);
default: default:
return SectorBufferAllocator::invalid(); return SectorBufferAllocator::invalid();
@ -42,62 +40,57 @@ namespace JabyEngine {
printf(">>> CD needs to load LBA: %i -> %i\n", cur_lba.lba, cur_lba.size_words); printf(">>> CD needs to load LBA: %i -> %i\n", cur_lba.lba, cur_lba.size_words);
} }
void CDFileProcessor :: reading_state(const CDFile& file) { bool CDFileProcessor :: process_data() {
switch(file.type) { while(this->circular_buffer.has_data()) {
case CDFileType::SimpleTIM: ArrayRange<const uint8_t> cur_sector(reinterpret_cast<uint8_t*>(this->circular_buffer.get_next()->data), CD_IO::DataSector::SizeBytes);
printf("CDFileProcessor: SimpleTIM not supported yet\n");
break;
case CDFileType::CopyTo: // v We can not know if there will be more data or not - but it also doesn't matter much for us
default: const auto result = this->lz4_decomp.process(cur_sector, false);
break; this->circular_buffer.pop();
if(result) {
// Process the data in the tmp_area
if(this->file_state.process(result.bytes_ready/sizeof(uint32_t)) == Progress::Error) {
return false;
} }
} }
void CDFileProcessor :: done_state(const CDFile& file) { else {
switch(file.type) { return false;
case CDFileType::SimpleTIM:
printf("CDFileProcessor: SimpleTIM not supported yet\n");
break;
case CDFileType::CopyTo:
default:
break;
} }
} }
return true;
}
void CDFileProcessor :: setup(const volatile AutoLBAEntry* lba, JobArray jobs, uint32_t* tmp_area) { void CDFileProcessor :: setup(const volatile AutoLBAEntry* lba, JobArray jobs, uint32_t* tmp_area) {
this->lba = const_cast<const AutoLBAEntry*>(lba); this->lba = const_cast<const AutoLBAEntry*>(lba);
this->jobs = jobs; this->jobs = jobs;
// Setsup the circular buffer and determines where to place the temp area in // Setsup the circular buffer and determines where to place the temp area in
const_cast<uint32_t*&>(this->tmp_area) = reinterpret_cast<uint32_t*>(this->circular_buffer.setup(reinterpret_cast<CD_IO::DataSector*>(tmp_area), 5)); const_cast<uint32_t*&>(this->tmp_area) = reinterpret_cast<uint32_t*>(this->circular_buffer.setup(reinterpret_cast<CD_IO::DataSector*>(tmp_area), NormalCircularBufferSize));
CDFileProcessor::start_cur_job(); CDFileProcessor::start_cur_job();
} }
Progress CDFileProcessor :: process() { Progress CDFileProcessor :: process() {
const auto& cur_job = *this->jobs.files; CDFileProcessor::process_data();
switch(CD::internal::read_current_state()) { switch(CD::internal::read_current_state()) {
case CD::internal::State::Done: case CD::internal::State::Done:
// We are done now! /*
// The user decides if he wants the next value We are done now!
CDFileProcessor::done_state(cur_job); The user decides if he wants the next value
*/
return Progress::Done; return Progress::Done;
case CD::internal::State::BufferFull: case CD::internal::State::BufferFull:
// We have to process data and unpause the CD drive /* We processd data and unpause the CD drive */
CDFileProcessor::reading_state(cur_job); return CD::internal::continue_reading() ? Progress::InProgress : Progress::Error;
return CD::internal::continue_reading() ? CDFileProcessor::process() : Progress::Error;
case CD::internal::State::Reading: case CD::internal::State::Reading:
// Do we have data? Use it!
CDFileProcessor::reading_state(cur_job);
return Progress::InProgress; return Progress::InProgress;
case CD::internal::State::Error: case CD::internal::State::Error:
default: default:
// Error for real! /* Error for real */
return Progress::Error; return Progress::Error;
} }
} }

View File

@ -0,0 +1,16 @@
#include "simplehelper.hpp"
namespace JabyEngine {
namespace FileProcessor {
struct NothingState {
};
static Progress parse_nothing(State::Configuration& config, NothingState& state) {
return Progress::Done;
}
State create(const uint32_t* data_adr, const Nothing& nothing) {
return State::from(NothingState(), data_adr, parse_nothing);
}
}
}