Support for loading TIM

This commit is contained in:
Jaby
2024-12-29 21:57:38 +01:00
parent c3cc4a729d
commit c66b68a0e8
19 changed files with 286 additions and 125 deletions

View File

@@ -0,0 +1,73 @@
#include "tim_helper.hpp"
#include <stdio.hpp>
namespace JabyEngine {
namespace FileProcessor {
using GPU::AreaU16;
using GPU::PositionU16;
using GPU::SizeU16;
namespace {
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 : public TIMFileProcessor::GenericTIM {
// TODO: Create function???
SimpleTIMState(const SimpleTIM& dst_info) {
this->tex_area = AreaU16::create(dst_info.get_texture_position(), SizeU16::create(0, 0));
this->clut_area = AreaU16::create(dst_info.get_clut_position(), SizeU16::create(0, 0));
this->words_left = 0;
}
virtual Progress parse_header(State::Configuration& config) override {
if(config.data_bytes >= sizeof(SimpleTIMSize)) {
// TODO: Return value???
SimpleTIMSize size_info;
Helper::simple_read(size_info, config);
this->clut_area.size = size_info.get_clut_size();
this->tex_area.size = size_info.get_texture_size();
return Progress::Done;
}
return Progress::InProgress;
}
virtual Progress pre_data_parsing(State::Configuration& config) {
return Progress::Done;
}
};
}
State create(const uint32_t* data_adr, const SimpleTIM& file) {
using Callback = Progress(*)(State::Configuration& config, SimpleTIMState& simple_tim);
return State::from(SimpleTIMState(file), data_adr, reinterpret_cast<Callback>(TIMFileProcessor::parse_header));
}
}
}

View File

@@ -0,0 +1,67 @@
#include "tim_helper.hpp"
namespace JabyEngine {
namespace TIMFileProcessor {
namespace {
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::create(x, y), SizeU16::create(w, h));
GPU::internal::DMA::Receive::set_src(reinterpret_cast<const uintptr_t>(src));
}
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;
}
Progress parse_data(State::Configuration& config, GenericTIM& generic_tim) {
const auto [words_to_use, is_last] = Helper::DMA::WordsReady::calculate(config, generic_tim.words_left);
const auto words_used = Helper::DMA::send_words<GPU::internal::DMA>(words_to_use, is_last);
generic_tim.words_left -= words_used;
config.processed(words_used*sizeof(uint32_t));
return is_last ? Progress::Done : Progress::InProgress;
}
Progress switch_state_parse_data(State::Configuration& config, GenericTIM& generic_tim) {
const auto result = generic_tim.pre_data_parsing(config);
if(result == Progress::Done) {
generic_tim.words_left = TIMFileProcessor::set_gpu_receive_data(reinterpret_cast<const uint32_t*>(config.data_adr), generic_tim.tex_area);
return Helper::exchange_and_execute_process_function<TIMFileProcessor::GenericTIM>(TIMFileProcessor::parse_data, config, generic_tim);
}
return result;
}
Progress parse_clut(State::Configuration& config, GenericTIM& generic_tim) {
if(const auto result = TIMFileProcessor::parse_data(config, generic_tim); result != Progress::Done) {
return result;
}
else {
return switch_state_parse_data(config, generic_tim);
}
}
}
Progress parse_header(State::Configuration& config, GenericTIM& generic_tim) {
const auto result = generic_tim.parse_header(config);
if(result == Progress::Done) {
//Check if we have a clut to care about
if(generic_tim.has_clut()) {
//CLUTs are 16bit full color anyway
generic_tim.words_left = TIMFileProcessor::set_gpu_receive_data(reinterpret_cast<const uint32_t*>(config.data_adr), generic_tim.clut_area);
return Helper::exchange_and_execute_process_function(parse_clut, config, generic_tim);
}
else {
return switch_state_parse_data(config, generic_tim);
}
}
return result;
}
}
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include "../../../../internal-include/GPU/gpu_internal.hpp"
#include <PSX/File/file_processor_helper.hpp>
#include <PSX/GPU/gpu_types.hpp>
namespace JabyEngine {
namespace TIMFileProcessor {
using namespace FileProcessor;
using namespace GPU;
struct GenericTIM {
AreaU16 clut_area;
AreaU16 tex_area;
size_t words_left; //32bit values
bool has_clut() const {
return this->clut_area.size.width > 0;
}
virtual Progress parse_header(State::Configuration& config) = 0;
virtual Progress pre_data_parsing(State::Configuration& config) = 0;
};
Progress parse_header(State::Configuration& config, GenericTIM& generic_tim);
}
}

View File

@@ -0,0 +1,54 @@
#include "tim_helper.hpp"
#include <stdio.hpp>
namespace JabyEngine {
namespace FileProcessor {
namespace {
using GPU::AreaU16;
struct BlockInfo {
uint32_t size;
uint16_t x;
uint16_t y;
uint16_t w;
uint16_t h;
};
struct TIMState : public TIMFileProcessor::GenericTIM {
// TODO: Create function???
TIMState() {
}
virtual Progress parse_header(State::Configuration& config) override {
static constexpr auto HEADER_SIZE = 2*sizeof(uint32_t);
if(config.data_bytes >= (HEADER_SIZE + sizeof(BlockInfo))) {
BlockInfo block_info;
config.processed(HEADER_SIZE);
Helper::simple_read(block_info, config);
this->clut_area = AreaU16::create(block_info.x, block_info.y, block_info.w, block_info.h);
return Progress::Done;
}
return Progress::Error;
}
virtual Progress pre_data_parsing(State::Configuration& config) {
if(config.data_bytes >= sizeof(BlockInfo)) {
BlockInfo block_info;
Helper::simple_read(block_info, config);
this->tex_area = AreaU16::create(block_info.x, block_info.y, block_info.w, block_info.h);
return Progress::Done;
}
return Progress::InProgress;
}
};
}
State create(const uint32_t* data_adr, const TIM& file) {
using Callback = Progress(*)(State::Configuration& config, TIMState& simple_tim);
return State::from(TIMState(), data_adr, reinterpret_cast<Callback>(TIMFileProcessor::parse_header));
}
}
}

View File

@@ -43,6 +43,9 @@ namespace JabyEngine {
case CDFileType::SimpleTIM:
return FileProcessor::create(data_adr, file.payload.simple_tim);
case CDFileType::SonyTIM:
return FileProcessor::create(data_adr, file.payload.tim);
case CDFileType::SonyVAG:
return FileProcessor::create(data_adr, file.payload.vag);

View File

@@ -1,113 +0,0 @@
#include "../../../internal-include/GPU/gpu_internal.hpp"
#include <PSX/File/file_processor_helper.hpp>
#include <PSX/GPU/gpu_types.hpp>
#include <stdio.hpp>
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), words_left(0) {
}
};
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::create(x, y), SizeU16::create(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 [words_to_use, is_last] = Helper::DMA::WordsReady::calculate(config, state.words_left);
const auto words_used = Helper::DMA::send_words<GPU::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 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), data_adr, parse_header);
}
}
}
#undef private