146 lines
5.5 KiB
C++
146 lines
5.5 KiB
C++
#include "../../../internal-include/GPU/gpu_internal.hpp"
|
|
#include "simplehelper.hpp"
|
|
#include <PSX/GPU/gpu_types.hpp>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
|
|
namespace JabyEngine {
|
|
namespace FileProcessor {
|
|
using GPU::AreaU16;
|
|
using GPU::PositionU16;
|
|
using GPU::SizeU16;
|
|
|
|
struct SimpleTIMSize : private SimpleTIM {
|
|
constexpr SimpleTIMSize() {
|
|
}
|
|
|
|
constexpr uint16_t get_texture_width() const {
|
|
return SimpleTIM::get_texture_x();
|
|
}
|
|
|
|
constexpr uint16_t get_texture_height() const {
|
|
return SimpleTIM::get_texture_y();
|
|
}
|
|
|
|
constexpr SizeU16 get_texture_size() const {
|
|
return {SimpleTIMSize::get_texture_width(), SimpleTIMSize::get_texture_height()};
|
|
}
|
|
|
|
constexpr uint16_t get_clut_width() const {
|
|
return SimpleTIM::get_clut_x();
|
|
}
|
|
|
|
constexpr uint16_t get_clut_height() const {
|
|
return SimpleTIM::get_clut_y();
|
|
}
|
|
|
|
constexpr SizeU16 get_clut_size() const {
|
|
return {SimpleTIMSize::get_clut_width(), SimpleTIMSize::get_clut_height()};
|
|
}
|
|
};
|
|
|
|
struct SimpleTIMState {
|
|
SimpleTIM dst_info;
|
|
SimpleTIMSize size_info;
|
|
size_t words_left; //32bit values
|
|
|
|
constexpr SimpleTIMState(const SimpleTIM& dst_info) : dst_info(dst_info) {
|
|
}
|
|
};
|
|
|
|
static void set_gpu_receive(const uint32_t* src, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
|
GPU::internal::DMA::Receive::prepare();
|
|
GPU::internal::DMA::Receive::set_dst(PositionU16(x, y), SizeU16(w, h));
|
|
GPU::internal::DMA::Receive::set_src(reinterpret_cast<const uintptr_t>(src));
|
|
}
|
|
|
|
static size_t set_gpu_receive_data(const uint32_t* src, const AreaU16& dst) {
|
|
const auto width = dst.size.width;
|
|
const auto height = dst.size.height;
|
|
|
|
set_gpu_receive(src, dst.position.x, dst.position.y, width, height);
|
|
return (width*height)/2;
|
|
}
|
|
|
|
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);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
static Progress switch_state_parse_data(State::Configuration& config, SimpleTIMState& state) {
|
|
state.words_left = set_gpu_receive_data(reinterpret_cast<const uint32_t*>(config.data_adr), {state.dst_info.get_texture_position(), state.size_info.get_texture_size()});
|
|
return Helper::exchange_and_execute_process_function(parse_data, config, state);
|
|
}
|
|
|
|
static Progress parse_clut(State::Configuration& config, SimpleTIMState& state) {
|
|
if(const auto result = parse_data(config, state); result != Progress::Done) {
|
|
return result;
|
|
}
|
|
|
|
else {
|
|
return switch_state_parse_data(config, state);
|
|
}
|
|
}
|
|
|
|
static Progress parse_header(State::Configuration& config, SimpleTIMState& state) {
|
|
if(config.data_bytes >= sizeof(SimpleTIMSize)) {
|
|
Helper::simple_read(state.size_info, config);
|
|
|
|
//Check if we have a clut to care about
|
|
if(state.size_info.get_clut_width() > 0) {
|
|
//CLUTs are 16bit full color anyway
|
|
state.words_left = set_gpu_receive_data(reinterpret_cast<const uint32_t*>(config.data_adr), {state.dst_info.get_clut_position(), state.size_info.get_clut_size()});
|
|
return Helper::exchange_and_execute_process_function(parse_clut, config, state);
|
|
}
|
|
|
|
//We have direct data
|
|
else {
|
|
return switch_state_parse_data(config, state);
|
|
}
|
|
}
|
|
|
|
return Progress::InProgress;
|
|
}
|
|
|
|
State create(const uint32_t* data_adr, const SimpleTIM& file) {
|
|
return State::from(SimpleTIMState(file), reinterpret_cast<const uint8_t*>(data_adr), parse_header);
|
|
}
|
|
}
|
|
}
|
|
#undef private |