diff --git a/include/PSX/AutoLBA/auto_lba.hpp b/include/PSX/AutoLBA/auto_lba.hpp index d211535d..51291181 100644 --- a/include/PSX/AutoLBA/auto_lba.hpp +++ b/include/PSX/AutoLBA/auto_lba.hpp @@ -1,6 +1,6 @@ #ifndef __JABYENGINE_AUTO_LBA_HPP__ #define __JABYENGINE_AUTO_LBA_HPP__ -#include "../../stdint.h" +#include "../Auxiliary/bits.hpp" namespace JabyEngine { #define __jabyengine_start_lba_request @@ -8,8 +8,36 @@ namespace JabyEngine { #define __jabyengine_end_lba_request EndOfRequest struct __attribute__((packed)) AutoLBAEntry { - uint16_t lba; - uint16_t size_words; + // This layout should make it a bit easier to read the "BitRange" values + static constexpr auto SizeInSectors = BitRange::from_to(22, 31); + static constexpr auto IsLZ4Compressed = Bit(19); + static constexpr auto LBAValue = BitRange::from_to(0, 18); + + uint32_t value; + + constexpr uint32_t get_lba() const { + return bit::value::get_normalized(this->value, AutoLBAEntry::LBAValue); + } + + constexpr uint32_t get_lba() const volatile { + return const_cast(this)->get_lba(); + } + + constexpr uint32_t get_size_in_sectors() const { + return this->value >> SizeInSectors.pos; + } + + constexpr uint32_t get_size_in_sectors() const volatile { + return const_cast(this)->get_size_in_sectors(); + } + + constexpr bool is_lz4() const { + return bit::is_set(this->value, AutoLBAEntry::IsLZ4Compressed); + } + + constexpr bool is_lz4() const volatile { + return const_cast(this)->is_lz4(); + } }; } diff --git a/include/PSX/Auxiliary/bits.hpp b/include/PSX/Auxiliary/bits.hpp index 935d2700..2e2cce79 100644 --- a/include/PSX/Auxiliary/bits.hpp +++ b/include/PSX/Auxiliary/bits.hpp @@ -1,17 +1,95 @@ #ifndef __JABYENGINE_BITS_HPP__ #define __JABYENGINE_BITS_HPP__ #include "../jabyengine_defines.h" +#include "types.hpp" namespace JabyEngine { namespace bit { + template + static constexpr T set(T raw_value, size_t bit); + namespace value { + template + static constexpr T set_normalized(T raw_value, T value, size_t start_bit, size_t length); + } + } + + struct ClearBit { + uint16_t pos; + + constexpr ClearBit(uint16_t bit_pos) : pos(bit_pos) { + } + }; + + struct Bit { + uint16_t pos; + + constexpr Bit(uint16_t bit_pos) : pos(bit_pos) { + } + + constexpr ClearBit operator!() const { + return ClearBit(this->pos); + } + + template + constexpr explicit operator T() const { + return bit::set(0, this->pos); + } + }; + + struct BitRange { + template + using RangeValuePair = pair; + + uint16_t pos; + uint16_t length; + + constexpr BitRange(uint16_t pos, uint16_t length) : pos(pos), length(length) { + } + + static constexpr BitRange from_to(uint16_t first_bit, uint16_t last_bit) { + return BitRange(first_bit, (last_bit - first_bit) + 1); + } + + template + constexpr RangeValuePair with(T value) const { + return {*this, value}; + } + + template + constexpr T as_value(T value) const { + return bit::value::set_normalized(static_cast(0), value, this->pos, this->length); + } + + template + constexpr RangeValuePair range_max() const { + return BitRange::with((1 << this->length) - 1); + } + }; + + namespace bit { + template + static constexpr T clear(T raw_value, size_t bit) { + return (raw_value & ~(1 << bit)); + } + + template + static constexpr T clear(T raw_value, Bit bit) { + return clear(raw_value, bit.pos); + } + template static constexpr T set(T raw_value, size_t bit) { return (raw_value | (1 << bit)); } template - static constexpr T clear(T raw_value, size_t bit) { - return (raw_value & ~(1 << bit)); + static constexpr T set(T raw_value, Bit bit) { + return set(raw_value, bit.pos); + } + + template + static constexpr T set(T raw_value, ClearBit bit) { + return clear(raw_value, bit.pos); } template @@ -19,30 +97,52 @@ namespace JabyEngine { return static_cast(raw_value & (1 << bit)); } - namespace value { - template - static constexpr T crop_value(T raw_value, size_t length) { - return (raw_value & ((1 << length) - 1)); - } + template + static constexpr bool is_set(T raw_value, Bit bit) { + return is_set(raw_value, bit.pos); + } - template - static constexpr T range_mask(size_t start_bit, size_t length) { - return (((1 << length) - 1) << start_bit); + namespace value { + namespace helper { + template + static constexpr T crop_value(T raw_value, size_t length) { + return (raw_value & ((1 << length) - 1)); + } + + template + static constexpr T range_mask(size_t start_bit, size_t length) { + return (((1 << length) - 1) << start_bit); + } } template static constexpr T clear_normalized(T raw_value, size_t start_bit, size_t length) { - return (raw_value & ~range_mask(start_bit, length)); + return (raw_value & ~helper::range_mask(start_bit, length)); } template static constexpr T set_normalized(T raw_value, T value, size_t start_bit, size_t length) { - return (clear_normalized(raw_value, start_bit, length) | (value << start_bit)); + return (clear_normalized(raw_value, start_bit, length) | (helper::crop_value(value, length) << start_bit)); + } + + template + static constexpr T set_normalized(T raw_value, BitRange bits, T value) { + return set_normalized(raw_value, value, bits.pos, bits.length); + } + + template + static constexpr T set_normalized(T raw_value, const BitRange::RangeValuePair &value_pair) { + return set_normalized(raw_value, value_pair.first, static_cast(value_pair.second)); } template static constexpr T get_normalized(T raw_value, size_t start_bit, size_t length) { - return (raw_value & range_mask(start_bit, length)) >> start_bit; + return helper::crop_value((raw_value & helper::range_mask(start_bit, length)) >> start_bit, length); + } + + template + static constexpr T get_normalized(T raw_value, BitRange range) { + return get_normalized(raw_value, range.pos, range.length); } } diff --git a/include/PSX/Auxiliary/circular_buffer.hpp b/include/PSX/Auxiliary/circular_buffer.hpp index eaba8814..c68f3631 100644 --- a/include/PSX/Auxiliary/circular_buffer.hpp +++ b/include/PSX/Auxiliary/circular_buffer.hpp @@ -3,66 +3,61 @@ #include "array_range.hpp" namespace JabyEngine { - template - class FastCircularBuffer { - private: - T* start_adr = nullptr; - size_t read_idx = 0; - size_t write_idx = 0; + template + class CircularBuffer { + private: + T* start_adr = nullptr; + T* end_adr = nullptr; + T* read_adr = nullptr; + T* write_adr = nullptr; - static size_t increment(size_t cur_idx, size_t step) { - return ((cur_idx + step) & (ElementCount - 1)); + T* increment(T* cur_element) const { + cur_element += 1; + if(cur_element == this->end_adr) { + return this->start_adr; } - public: - FastCircularBuffer() = default; - - void setup(T* buffer_start_adr) { - this->start_adr = buffer_start_adr; - this->read_idx = 0; - this->write_idx = 0; - } + return cur_element; + } - T* allocate() { - const auto new_idx = FastCircularBuffer::increment(this->write_idx, 1); - if(new_idx != this->read_idx) { - auto* dst = (this->start_adr + this->write_idx); - - this->write_idx = new_idx; - return dst; - } + public: + CircularBuffer() = default; + + T* setup(T* buffer_start_adr, size_t elements) { + this->start_adr = buffer_start_adr; + this->end_adr = &buffer_start_adr[elements]; + this->read_adr = this->start_adr; + this->write_adr = this->start_adr; + return this->end_adr; + } + + T* allocate() { + T* cur_adr = this->write_adr; + T* next_adr = CircularBuffer::increment(cur_adr); + if(next_adr == this->read_adr) { return nullptr; } - const T* pop() { - if(this->write_idx != this->read_idx) { - const auto* src = (this->start_adr + this->read_idx); - FastCircularBuffer::drop(1); - - return src; - } - - return nullptr; + else { + this->write_adr = next_adr; + return cur_adr; } + } - void drop(size_t elements) { - this->read_idx = FastCircularBuffer::increment(this->read_idx, elements); + T* get_next() const { + return this->read_adr; + } + + void pop() { + if(CircularBuffer::has_data()) { + this->read_adr = CircularBuffer::increment(this->read_adr); } + } - constexpr ArrayRange get_first_continious() const { - return {&this->start_adr[this->read_idx], (this->write_idx >= this->read_idx) ? (this->write_idx - this->read_idx) : (ElementCount - this->read_idx)}; - } - - constexpr ArrayRange get_second_continious() const { - return {this->start_adr, (this->write_idx < this->read_idx) ? this->write_idx : 0}; - } - - constexpr bool has_data() const { - return (this->read_idx != this->write_idx); - } - - static_assert(ElementCount == 2 || ElementCount == 4 || ElementCount == 8 || ElementCount == 16 || ElementCount == 32 || ElementCount == 64 || ElementCount == 128 || ElementCount == 256, "ElementCount for FastCircularBuffer must be power of 2"); + constexpr bool has_data() const { + return (this->read_adr != this->write_adr); + } }; } diff --git a/include/PSX/Auxiliary/complex_bitmap.hpp b/include/PSX/Auxiliary/complex_bitmap.hpp deleted file mode 100644 index b1a6bb64..00000000 --- a/include/PSX/Auxiliary/complex_bitmap.hpp +++ /dev/null @@ -1,210 +0,0 @@ -#ifndef __JABYENGINE_COMPLEX_BITMAP_HPP__ -#define __JABYENGINE_COMPLEX_BITMAP_HPP__ -#include "bits.hpp" - -namespace JabyEngine { - struct ClearBitValue { - size_t bit; - - constexpr ClearBitValue(size_t bit) : bit(bit) { - } - }; - - template - struct Bit { - typedef T ValueType; - - size_t value; - - constexpr Bit(size_t value) : value(value) { - } - - constexpr operator size_t() const { - return this->value; - } - - constexpr ClearBitValue operator!() const { - return ClearBitValue(this->value); - } - }; - - template - struct BitRangeValue { - T value; - size_t begin; - size_t length; - - constexpr BitRangeValue() = default; - constexpr BitRangeValue(T value, size_t begin, size_t length) : value(value), begin(begin), length(length) { - } - }; - - template - struct BitRange { - typedef T ValueType; - - size_t begin; - size_t length; - - static constexpr BitRange from_to(size_t start, size_t end) { - return {start, (end - start + 1)}; - } - - constexpr BitRangeValue with(T value) const { - return BitRangeValue(value, this->begin, this->length); - } - - constexpr BitRangeValue max() const { - return BitRange::with((1 << this->length) - 1); - } - }; - - template - static constexpr __always_inline BitRangeValue operator<<(const BitRange& range, T value) { - return BitRangeValue{value, range.begin, range.length}; - } - - template - class ComplexBitMap { - public: - typedef T UnderlyingType; - T raw; - - private: - template - constexpr __always_inline ComplexBitMap& set_va(const S& value) { - return this->set(value); - } - - template - constexpr __always_inline ComplexBitMap& set_va(const S& value, const ARGS&...args) { - return this->set_va(value).set_va(args...); - } - - public: - template - static constexpr __always_inline ComplexBitMap with(ARGS...args) { - return ComplexBitMap().set_va(args...); - } - - //Accesssing bits - template - constexpr ComplexBitMap& set_bit(S bit) { - this->raw = bit::set(this->raw, static_cast(bit)); - return *this; - } - - template - constexpr void set_bit(S bit) volatile { - this->raw = bit::set(this->raw, static_cast(bit)); - } - - template - constexpr ComplexBitMap& clear_bit(S bit) { - this->raw = bit::clear(this->raw, static_cast(bit)); - return *this; - } - - template - constexpr void clear_bit(S bit) volatile { - this->raw = bit::clear(this->raw, static_cast(bit)); - } - - template - constexpr bool is_bit_set(S bit) { - return bit::is_set(this->raw, static_cast(bit)); - } - - template - constexpr bool is_bit_set(S bit) const volatile { - return bit::is_set(this->raw, static_cast(bit)); - } - - //Accessing values - template - constexpr ComplexBitMap& set_value(S value, const BitRange& range) { - this->raw = bit::value::set_normalized(this->raw, static_cast(value), range.begin, range.length); - return *this; - } - - template - constexpr void set_value(S value, const BitRange& range) volatile { - this->raw = bit::value::set_normalized(this->raw, static_cast(value), range.begin, range.length); - } - - template - constexpr ComplexBitMap& clear_value(const BitRange& range) { - this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length); - return *this; - } - - template - constexpr void clear_value(const BitRange& range) volatile { - this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length); - } - - template - constexpr S get_value(const BitRange& range) const { - return static_cast(bit::value::get_normalized(this->raw, range.begin, range.length)); - } - - template - constexpr S get_value(const BitRange& range) const volatile { - return static_cast(bit::value::get_normalized(this->raw, range.begin, range.length)); - } - - //For easier checking - constexpr bool is(Bit bit) const { - return ComplexBitMap::is_bit_set(bit); - } - - constexpr bool is(Bit bit) const volatile { - return ComplexBitMap::is_bit_set(bit); - } - - // For easier constructing - template - constexpr __always_inline ComplexBitMap& set(const BitRange& range, T value) { - this->set_value(value, range); - return *this; - } - - template - constexpr __always_inline ComplexBitMap& set(const BitRangeValue& value) { - this->set_value(value.value, {value.begin, value.length}); - return *this; - } - - template - constexpr __always_inline ComplexBitMap& set(const Bit& bit) { - this->set_bit(bit.value); - return *this; - } - - constexpr __always_inline ComplexBitMap& set(const ClearBitValue& value) { - this->clear_bit(value.bit); - return *this; - } - - constexpr __always_inline ComplexBitMap& operator|(const BitRangeValue& value) { - this->set_value(value.value, value.range); - return *this; - } - - constexpr __always_inline ComplexBitMap& operator|(const Bit& bit) { - this->set_bit(bit.value); - return *this; - } - - constexpr __always_inline ComplexBitMap& operator|(const ClearBitValue& value) { - this->clear_bit(value.bit); - return *this; - } - - constexpr __always_inline operator T() const { - return this->raw; - } - }; -} - -#endif //!__JABYENGINE_COMPLEX_BITMAP_HPP__ \ No newline at end of file diff --git a/include/PSX/Auxiliary/lz4_decompressor.hpp b/include/PSX/Auxiliary/lz4_decompressor.hpp index e8343cc9..0ebd7b90 100644 --- a/include/PSX/Auxiliary/lz4_decompressor.hpp +++ b/include/PSX/Auxiliary/lz4_decompressor.hpp @@ -11,6 +11,10 @@ namespace JabyEngine { Progress progress; size_t bytes_ready; + constexpr operator bool() const { + return this->progress != Progress::Error; + } + static constexpr Result new_error() { return {Progress::Error, 0}; } @@ -27,6 +31,7 @@ namespace JabyEngine { private: struct State { enum struct Step { + Disabled, ReadToken, ObtainLiteralLength, CopyLiterals, @@ -35,12 +40,23 @@ namespace JabyEngine { CopyMatch, }; - Step step = Step::ReadToken; + Step step = Step::Disabled; size_t literal_length = 0; size_t match_length = 0; - uint16_t match_offset = 0xFFFF; + uint16_t match_offset = 0; 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: @@ -56,7 +72,7 @@ namespace JabyEngine { } void setup(uint8_t* dst_adr); - void reset(); + void disable(); Result process(ArrayRange data, bool is_last); }; diff --git a/include/PSX/File/Processor/cd_file_processor.hpp b/include/PSX/File/Processor/cd_file_processor.hpp index a1b4be58..42b408c5 100644 --- a/include/PSX/File/Processor/cd_file_processor.hpp +++ b/include/PSX/File/Processor/cd_file_processor.hpp @@ -1,7 +1,9 @@ #ifndef __JABYENGINE_CD_FILE_PROCESSOR_HPP__ #define __JABYENGINE_CD_FILE_PROCESSOR_HPP__ #include "../../AutoLBA/auto_lba.hpp" +#include "../../Auxiliary/circular_buffer.hpp" #include "../../Auxiliary/lz4_decompressor.hpp" +#include "../../System/IOPorts/cd_io.hpp" #include "../cd_file_types.hpp" #include "file_processor.hpp" @@ -10,30 +12,60 @@ extern "C" uint32_t __heap_base; namespace JabyEngine { class CDFileProcessor { public: + struct BufferConfiguration { + static constexpr size_t SmallSectorCount = 5; + static constexpr size_t MediumSectorCount = 16; + + uint32_t* adr = nullptr; + size_t sector_count = 0; + + static constexpr BufferConfiguration new_default() { + return {&__heap_base, BufferConfiguration::MediumSectorCount}; + } + }; + struct JobArray { const CDFile* files = nullptr; size_t size = 0; + + bool next() { + this->files += 1; + this->size -= 1; + + return this->size > 0; + } }; private: - FileProcessor::State file_pro_state; - LZ4Decompressor lz4_decomp; - JobArray jobs; - uint8_t* work_area = nullptr; - const AutoLBAEntry* lba = nullptr; + FileProcessor::State file_state; + CircularBuffer circular_buffer; + LZ4Decompressor lz4_decomp; + JobArray jobs; - void start_cur_job(); + void start_cur_job(const AutoLBAEntry* lba, const BufferConfiguration& buf_cfg); + bool process_data(); public: CDFileProcessor() = default; - void setup(const volatile AutoLBAEntry* lba, JobArray jobs, uint8_t* work_area = reinterpret_cast(&__heap_base)); + void setup(const volatile AutoLBAEntry* lba, JobArray jobs, const BufferConfiguration& buf_cfg); + + template + void setup(const volatile AutoLBAEntry* lba, const CDFile (&file_array)[N], const BufferConfiguration& buf_cfg) { + CDFileProcessor::setup(lba, JobArray{file_array, N}, buf_cfg); + } + Progress process(); + + bool next(const volatile AutoLBAEntry* lba, const BufferConfiguration& buf_cfg) { + if(this->jobs.next()) { + CDFileProcessor::start_cur_job(const_cast(lba), buf_cfg); + return true; + } + + return false; + } }; } -// This will be used as the file processor but will work on cd types -// Will probably use file_processor -// Will also setup the circular buffer for the CD code - #endif //!__JABYENGINE_CD_FILE_PROCESSOR_HPP__ \ No newline at end of file diff --git a/include/PSX/File/Processor/file_processor.hpp b/include/PSX/File/Processor/file_processor.hpp index bdfba65f..5930071a 100644 --- a/include/PSX/File/Processor/file_processor.hpp +++ b/include/PSX/File/Processor/file_processor.hpp @@ -20,17 +20,17 @@ namespace JabyEngine { struct Configuration { ProcessRoutine process_routine = nullptr; - const uint32_t* data_adr = nullptr; - size_t data_word_size = 0ull; + const uint8_t* data_adr = nullptr; + size_t data_bytes = 0ull; template - static __always_inline Configuration from(GenericProcessRoutine process_routine, const uint32_t* data_adr) { + static __always_inline Configuration from(GenericProcessRoutine process_routine, const uint8_t* data_adr) { return {reinterpret_cast(process_routine), data_adr}; } - constexpr void processed(size_t words) { - this->data_adr += words; - this->data_word_size -= words; + constexpr void processed(size_t bytes) { + this->data_adr += bytes; + this->data_bytes -= bytes; } }; @@ -39,18 +39,20 @@ namespace JabyEngine { Reserved reserved; template - static __always_inline State from(const T& reserved, const uint32_t* data_adr, GenericProcessRoutine process_routine) { + static __always_inline State from(const T& reserved, const uint8_t* data_adr, GenericProcessRoutine process_routine) { return {Configuration::from(process_routine, data_adr), *reinterpret_cast(&reserved)}; static_assert(sizeof(T) <= sizeof(Reserved)); } public: - Progress process(size_t word_size) { - this->config.data_word_size += word_size; + Progress process(size_t bytes_ready) { + this->config.data_bytes += bytes_ready; return (*this->config.process_routine)(this->config, this->reserved); } }; + // The nothing state + State create(const uint32_t* data_adr, const Nothing& nothing); State create(const uint32_t* data_adr, const SimpleTIM& file); } } diff --git a/include/PSX/File/cd_file_types.hpp b/include/PSX/File/cd_file_types.hpp index 4e8d0eb6..67634209 100644 --- a/include/PSX/File/cd_file_types.hpp +++ b/include/PSX/File/cd_file_types.hpp @@ -11,9 +11,10 @@ namespace JabyEngine { struct __no_align CDFile { union __no_align Payload { - uint32_t empty; + uint32_t raw; SimpleTIM simple_tim; CopyTo copy_to; + Overlay overlay; }; uint8_t rel_lba_idx; @@ -31,6 +32,10 @@ namespace JabyEngine { static constexpr CDFile copy_to(uint8_t rel_lba_idx, uint32_t* dst) { return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::CopyTo, .payload = {.copy_to = CopyTo{dst}}}; } + + static constexpr CDFile overlay(uint8_t rel_lba_idx, uint32_t* overlay_dst) { + return CDFile{.rel_lba_idx = rel_lba_idx, .type = CDFileType::CopyTo, .payload = {.overlay = Overlay{overlay_dst}}}; + } }; } #endif //!__JABYENGINE_CD_FILE_TYPES_HPP__ \ No newline at end of file diff --git a/include/PSX/File/file_types.hpp b/include/PSX/File/file_types.hpp index 6f353d7c..bba6c5f5 100644 --- a/include/PSX/File/file_types.hpp +++ b/include/PSX/File/file_types.hpp @@ -1,41 +1,48 @@ #ifndef __JABYENGINE_FILE_TYPES_HPP__ #define __JABYENGINE_FILE_TYPES_HPP__ -#include "../Auxiliary/complex_bitmap.hpp" +#include "../Auxiliary/bits.hpp" #include "../jabyengine_defines.h" namespace JabyEngine { - struct __no_align SimpleTIM : private ComplexBitMap { - static constexpr auto TextureX = BitRange(0, 8); - static constexpr auto TextureY = BitRange(9, 16); - static constexpr auto ClutX = BitRange(17, 22); - static constexpr auto ClutY = BitRange(23, 31); + struct __no_align Nothing { + }; + + struct __no_align SimpleTIM { + static constexpr auto TextureX = BitRange::from_to(0, 8); + static constexpr auto TextureY = BitRange::from_to(9, 16); + static constexpr auto ClutX = BitRange::from_to(17, 22); + static constexpr auto ClutY = BitRange::from_to(23, 31); + + uint32_t raw; constexpr SimpleTIM() { this->raw = 0; } - constexpr SimpleTIM(uint16_t texX, uint16_t texY, uint16_t clutX, uint16_t clutY) : ComplexBitMap(ComplexBitMap::with(TextureX.with(texX >> 1), TextureY.with(texY >> 1), ClutX.with(clutX >> 4), ClutY.with(clutY))) { + constexpr SimpleTIM(uint16_t texX, uint16_t texY, uint16_t clutX, uint16_t clutY) : raw(TextureX.as_value(texX >> 1) | TextureY.as_value(texY >> 1) | ClutX.as_value(clutX >> 4) | ClutY.as_value(clutY)) { } constexpr uint16_t getTextureX() const { - return (ComplexBitMap::get_value(SimpleTIM::TextureX) << 1); + return bit::value::get_normalized(this->raw, TextureX) << 1; } constexpr uint16_t getTextureY() const { - return (ComplexBitMap::get_value(SimpleTIM::TextureY) << 1); + return bit::value::get_normalized(this->raw, TextureY) << 1; } constexpr uint16_t getClutX() const { - return (ComplexBitMap::get_value(SimpleTIM::ClutX) << 4); + return bit::value::get_normalized(this->raw, SimpleTIM::ClutX) << 4; } constexpr uint16_t getClutY() const { - return ComplexBitMap::get_value(SimpleTIM::ClutY); + return bit::value::get_normalized(this->raw, ClutY); } }; struct __no_align CopyTo { uint32_t* dst; }; + + typedef CopyTo Overlay; } #endif // !__JABYENGINE_FILE_TYPES_HPP__ \ No newline at end of file diff --git a/include/PSX/GPU/gpu.hpp b/include/PSX/GPU/gpu.hpp index 2960d8e3..6f026a8f 100644 --- a/include/PSX/GPU/gpu.hpp +++ b/include/PSX/GPU/gpu.hpp @@ -22,11 +22,11 @@ namespace JabyEngine { #endif static void enable() { - GPU_IO::GP1.write(GPU_IO::Command::GP1::SetDisplayState(GPU_IO::DisplayState::On)); + GPU_IO::GP1 = GPU_IO::Command::SetDisplayState(GPU_IO::DisplayState::On); } static void disable() { - GPU_IO::GP1.write(GPU_IO::Command::GP1::SetDisplayState(GPU_IO::DisplayState::Off)); + GPU_IO::GP1 = GPU_IO::Command::SetDisplayState(GPU_IO::DisplayState::Off); } }; diff --git a/include/PSX/GPU/gpu_types.hpp b/include/PSX/GPU/gpu_types.hpp index 814f7370..48bfc0ca 100644 --- a/include/PSX/GPU/gpu_types.hpp +++ b/include/PSX/GPU/gpu_types.hpp @@ -1,7 +1,6 @@ #ifndef __JABYENGINE_GPU_TYPES_HPP__ #define __JABYENGINE_GPU_TYPES_HPP__ #include "../jabyengine_defines.h" -#include "../Auxiliary/complex_bitmap.hpp" namespace JabyEngine { namespace GPU { @@ -41,12 +40,12 @@ namespace JabyEngine { class Color { private: - static constexpr auto RedRange = BitRange::from_to(0, 4); - static constexpr auto GreenRange = BitRange::from_to(5, 9); - static constexpr auto BlueRange = BitRange::from_to(10, 14); - static constexpr auto SemiTransperancyBit = Bit(15); + static constexpr auto RedRange = BitRange::from_to(0, 4); + static constexpr auto GreenRange = BitRange::from_to(5, 9); + static constexpr auto BlueRange = BitRange::from_to(10, 14); + static constexpr auto SemiTransperancyBit = Bit(15); - ComplexBitMap value = {0}; + uint16_t value = 0; public: static constexpr Color from_rgb(uint8_t r, uint8_t g, uint8_t b) { @@ -58,17 +57,17 @@ namespace JabyEngine { } constexpr Color& set_red(uint8_t red) { - this->value.set_value(static_cast(red), RedRange); + this->value = bit::value::set_normalized(this->value, RedRange.with(red)); return *this; } constexpr Color& set_green(uint8_t green) { - this->value.set_value(static_cast(green), GreenRange); + this->value = bit::value::set_normalized(this->value, GreenRange.with(green)); return *this; } constexpr Color& set_blue(uint8_t blue) { - this->value.set_value(static_cast(blue), BlueRange); + this->value = bit::value::set_normalized(this->value, BlueRange.with(blue)); return *this; } }; diff --git a/include/PSX/Overlay/overlay.hpp b/include/PSX/Overlay/overlay.hpp index cd7b8ae8..1040eed4 100644 --- a/include/PSX/Overlay/overlay.hpp +++ b/include/PSX/Overlay/overlay.hpp @@ -3,11 +3,9 @@ #include "../AutoLBA/auto_lba.hpp" namespace JabyEngine { - struct __attribute__((packed)) OverlayHeader { - void (*execute)(); - uint16_t lba_size; //< The size of the OverlayLBA section - }; - typedef AutoLBAEntry OverlayLBA; + + // Can be used to create dummy values to trick LZ4 into compressing an uncompressed overlay + #define __create_dummy_fill(length) static const uint8_t __section(".keep.dummy") __used DummyFilling[length] = {0x0} } #endif //!__JABYENGINE_OVERLAY__HPP__ \ No newline at end of file diff --git a/include/PSX/Overlay/overlay_declaration.hpp b/include/PSX/Overlay/overlay_declaration.hpp index 279c1dfc..85cf0449 100644 --- a/include/PSX/Overlay/overlay_declaration.hpp +++ b/include/PSX/Overlay/overlay_declaration.hpp @@ -4,10 +4,7 @@ // No include here because this header should be included in a namespace and we don't want multiple namespace definitions of OverlayHeader and OverlayLBA #include "../AutoLBA/auto_lba_declaration.hpp" -extern const JabyEngine::OverlayHeader overlay_header; #define __declare_overlay_header(function, enum_struct) \ -__declare_lba_header(enum_struct); \ -[[gnu::used]] \ -const JabyEngine::OverlayHeader __section(".header") overlay_header = {.execute = &function, .lba_size = static_cast(enum_struct::EndOfRequest)}; +__declare_lba_header(enum_struct) #endif //!__JABYENGINE_OVERLAY_DECLARATION__HPP__ \ No newline at end of file diff --git a/include/PSX/System/IOPorts/cd_io.hpp b/include/PSX/System/IOPorts/cd_io.hpp index 2833467d..f981aaac 100644 --- a/include/PSX/System/IOPorts/cd_io.hpp +++ b/include/PSX/System/IOPorts/cd_io.hpp @@ -4,6 +4,18 @@ namespace JabyEngine { namespace CD_IO { + struct DataSector { + static constexpr size_t SizeBytes = 2048; + static constexpr size_t SizeWords = (SizeBytes/sizeof(uint32_t)); + + uint32_t data[SizeWords]; + + template + static constexpr T words_to_sectors(T size) { + return (size + static_cast(DataSector::SizeWords - 1))/static_cast(DataSector::SizeWords); + } + }; + enum Index { Index0 = 0, Index1 = 1, @@ -19,56 +31,74 @@ namespace JabyEngine { static constexpr uint8_t Max = 0xFF; }; - typedef struct IndexStatus : public ComplexBitMap { - static constexpr auto PortIndex = BitRange::from_to(0, 1); - static constexpr auto HasXAFifoData = Bit(2); - static constexpr auto IsParameterFifoEmpty = Bit(3); - static constexpr auto HasParameterFifoSpace = Bit(4); - static constexpr auto HasResponseFifoData = Bit(5); - static constexpr auto HasDataFifoData = Bit(6); - static constexpr auto IsTransmissionBusy = Bit(7); - } IndexStatus_t; + __declare_io_type(Mode, uint8_t, + static constexpr auto DoubleSpeed = Bit(7); + static constexpr auto SingleSpeed = !DoubleSpeed; + static constexpr auto XADPCM = Bit(6); + static constexpr auto WholeSector = Bit(5); + static constexpr auto DataSector = !WholeSector; + static constexpr auto UseXAFilter = Bit(3); + static constexpr auto AudioPlayIRQ = Bit(2); + static constexpr auto AutoPauseTrack = Bit(1); + static constexpr auto CDDA = Bit(0); + ); - struct InterruptEnable : public ComplexBitMap { - static constexpr auto InterruptTypValue = BitRange::from_to(0, 2); - static constexpr auto InterruptExtended = BitRange::from_to(0, 4); - static constexpr auto UnknownIRQ = Bit(3); - static constexpr auto CommandStartIRQ = Bit(4); - }; - typedef InterruptEnable InterruptFlag; + __declare_io_type(IndexStatus, uint8_t, + static constexpr auto PortIndex = BitRange::from_to(0, 1); + static constexpr auto HasXAFifoData = Bit(2); + static constexpr auto IsParameterFifoEmpty = Bit(3); + static constexpr auto HasParameterFifoSpace = Bit(4); + static constexpr auto HasResponseFifoData = Bit(5); + static constexpr auto HasDataFifoData = Bit(6); + static constexpr auto IsTransmissionBusy = Bit(7); + ); - struct Request : public ComplexBitMap { - static constexpr auto WantCommandStartIRQ = Bit(5); - static constexpr auto WantData = Bit(7); - }; + __declare_io_type(InterruptEnable, uint8_t, + static constexpr auto InterruptTypValue = BitRange::from_to(0, 2); + static constexpr auto InterruptExtended = BitRange::from_to(0, 4); + static constexpr auto UnknownIRQ = Bit(3); + static constexpr auto CommandStartIRQ = Bit(4); + ); + typedef InterruptEnable_v InterruptFlag_v; - struct SoundMapCoding : public ComplexBitMap { - static constexpr auto Stereo = Bit(0); + __declare_io_type(Request, uint8_t, + static constexpr auto WantCommandStartIRQ = Bit(5); + static constexpr auto WantData = Bit(7); + + void want_data() { + this->raw_value = static_cast(Self::WantData); + } + + void reset() { + this->raw_value = 0; + } + ); + + __declare_io_type(SoundMapCoding, uint8_t, + static constexpr auto Stereo = Bit(0); static constexpr auto Mono = !Stereo; - static constexpr auto SampleRate_18900hz = Bit(2); + static constexpr auto SampleRate_18900hz = Bit(2); static constexpr auto SampleRate_37800hz = !SampleRate_18900hz; - static constexpr auto BitsPerSample8 = Bit(4); + static constexpr auto BitsPerSample8 = Bit(4); static constexpr auto BitsPerSample4 = !BitsPerSample8; - static constexpr auto Emphasis = Bit(6); - }; + static constexpr auto Emphasis = Bit(6); + ); - struct AudioVolumeApply : public ComplexBitMap { - static constexpr auto Mute = Bit(0); - static constexpr auto ApplyChanges = Bit(5); - }; + __declare_io_type(AudioVolumeApply, uint8_t, + static constexpr auto Mute = Bit(0); + static constexpr auto ApplyChanges = Bit(5); + ); - typedef VolatilePOD ResponseFifo_t; - typedef VolatilePOD CommandFifo_t; - typedef VolatilePOD DataFifo_t; - typedef VolatilePOD DataFifo16_t; - typedef VolatilePOD ParameterFifo_t; - typedef VolatilePOD SoundMapDataOut_t; - typedef VolatilePOD VolumeRegister_t; - typedef VolatileBitMapPOD InterruptEnableRegister_t; - typedef VolatileBitMapPOD InterruptFlagRegister_t; - typedef VolatileBitMapPOD RequestRegister_t; - typedef VolatileBitMapPOD SoundMapCodingInfo_t; - typedef VolatileBitMapPOD AudioVolumeApplyChange_t; + __declare_io_type(ResponseFifo, uint8_t,); + __declare_io_type(CommandFifo, uint8_t,); + __declare_io_type(DataFifo, uint8_t,); + __declare_io_type(DataFifo16, uint16_t,); + __declare_io_type(ParameterFifo, uint8_t,); + __declare_io_type(SoundMapDataOut, uint8_t,); + __declare_io_type(LeftCD2LeftSPU, CDDAVolume::Type,); + __declare_io_type(LeftCD2RightSPU, CDDAVolume::Type,); + __declare_io_type(RightCD2RightSPU,CDDAVolume::Type,); + __declare_io_type(RightCD2LeftSPU, CDDAVolume::Type,); struct Interrupt { enum Type : uint8_t { @@ -80,110 +110,110 @@ namespace JabyEngine { DiskError = 5 }; - static void enable(InterruptEnableRegister_t& port) { - port.write(InterruptEnable::InterruptTypValue.max()); + static void enable(InterruptEnable_v& port) { + port.set(InterruptEnable_t::InterruptTypValue.range_max()); } - static void enable_extended(InterruptEnableRegister_t& port) { - port.write({InterruptEnable::with(InterruptEnable::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); + static void enable_extended(InterruptEnable_v& port) { + port = InterruptEnable_t::from(InterruptEnable_t::InterruptTypValue.range_max(), InterruptEnable_t::UnknownIRQ, InterruptEnable_t::CommandStartIRQ); } - static Type get_type(const InterruptFlagRegister_t& port) { - return static_cast(port.read().get_value(InterruptFlag::InterruptTypValue)); + static Type get_type(const InterruptFlag_v& port) { + return static_cast(port.get(InterruptFlag_v::InterruptTypValue)); } - static void ack(InterruptFlagRegister_t& port) { - port.write(InterruptFlag::InterruptTypValue.max()); + static void ack(InterruptFlag_v& port) { + port.set(InterruptFlag_v::InterruptTypValue.range_max()); } - static void ack_extended(InterruptFlagRegister_t& port) { - port.write({InterruptFlag::with(InterruptFlag::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); + static void ack_extended(InterruptFlag_v& port) { + port = InterruptFlag_v::from(InterruptFlag_v::InterruptTypValue.range_max(), InterruptEnable_v::UnknownIRQ, InterruptEnable_v::CommandStartIRQ); } }; struct Command { - struct Info { + struct Desc { uint8_t id; Interrupt::Type complete_irq; }; - static constexpr Info GetStat{0x01, Interrupt::Type::Acknowledge}; - static constexpr Info SetLoc{0x02, Interrupt::Type::Acknowledge}; - static constexpr Info ReadN{0x06, Interrupt::Type::DataReady}; - static constexpr Info Pause{0x09, Interrupt::Type::Complete}; - static constexpr Info Init{0x0A, Interrupt::Type::Complete}; - static constexpr Info SetMode{0x0E, Interrupt::Type::Acknowledge}; + static constexpr Desc GetStat{0x01, Interrupt::Type::Acknowledge}; + static constexpr Desc SetLoc{0x02, Interrupt::Type::Acknowledge}; + static constexpr Desc ReadN{0x06, Interrupt::Type::DataReady}; + static constexpr Desc Pause{0x09, Interrupt::Type::Complete}; + static constexpr Desc Init{0x0A, Interrupt::Type::Complete}; + static constexpr Desc SetMode{0x0E, Interrupt::Type::Acknowledge}; }; static constexpr auto IORegister1Adr = 0x1F801801; static constexpr auto IORegister2Adr = 0x1F801802; static constexpr auto IORegister3Adr = 0x1F801803; - __declare_io_port_global(IndexStatus_t, IndexStatus, 0x1F801800); + __declare_new_io_port(IndexStatus, 0x1F801800); #define __declare_index_io_port(type, name, adr) __cast_io_adr_with_type(inline, type, name, adr) #define __declare_index_io_port_const(type, name, adr) __cast_io_adr_with_type(const inline, type, name, adr) struct PortIndex0 { - __declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); - __declare_index_io_port( CommandFifo_t, CommandFifo, IORegister1Adr); + __declare_new_const_io_port(ResponseFifo, IORegister1Adr); + __declare_new_io_port(CommandFifo, IORegister1Adr); - __declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); - __declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); - __declare_index_io_port( ParameterFifo_t, ParameterFifo, IORegister2Adr); + __declare_new_const_io_port(DataFifo, IORegister2Adr); + __declare_new_const_io_port(DataFifo16, IORegister2Adr); + __declare_new_io_port(ParameterFifo, IORegister2Adr); - __declare_index_io_port_const(InterruptEnableRegister_t, InterruptEnableRegister, IORegister3Adr); - __declare_index_io_port( RequestRegister_t, RequestRegister, IORegister3Adr); + __declare_new_const_io_port(InterruptEnable, IORegister3Adr); + __declare_new_io_port(Request, IORegister3Adr); static void change_to() { - IndexStatus.write({static_cast(Index::Index0)}); + IndexStatus = Index::Index0; } }; struct PortIndex1 { - __declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); - __declare_index_io_port( SoundMapDataOut_t, SoundMapDataOut, IORegister1Adr); + __declare_new_const_io_port(ResponseFifo, IORegister1Adr); + __declare_new_io_port(SoundMapDataOut, IORegister1Adr); - __declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); - __declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); - __declare_index_io_port( InterruptEnableRegister_t, InterruptEnableRegister, IORegister2Adr); + __declare_new_const_io_port(DataFifo, IORegister2Adr); + __declare_new_const_io_port(DataFifo16, IORegister2Adr); + __declare_new_io_port(InterruptEnable, IORegister2Adr); - __declare_index_io_port(InterruptFlagRegister_t, InterruptFlagRegister, IORegister3Adr); + __declare_new_io_port(InterruptFlag, IORegister3Adr); static void change_to() { - IndexStatus.write({static_cast(Index::Index1)}); + IndexStatus = Index::Index1; } }; struct PortIndex2 { - __declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); - __declare_index_io_port( SoundMapCodingInfo_t, SoundMapCodingInfo, IORegister1Adr); + __declare_new_const_io_port(ResponseFifo, IORegister1Adr); + __declare_new_io_port(SoundMapCoding, IORegister1Adr); - __declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); - __declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); - __declare_index_io_port( VolumeRegister_t, LeftCD2LeftSPU, IORegister2Adr); + __declare_new_const_io_port(DataFifo, IORegister2Adr); + __declare_new_const_io_port(DataFifo16, IORegister2Adr); + __declare_new_io_port(LeftCD2LeftSPU, IORegister2Adr); - __declare_index_io_port_const(InterruptEnableRegister_t, InterruptEnableRegister, IORegister3Adr); - __declare_index_io_port( VolumeRegister_t, LeftCD2RightSPU, IORegister3Adr); + __declare_new_const_io_port(InterruptEnable, IORegister3Adr); + __declare_new_io_port(LeftCD2RightSPU, IORegister3Adr); static void change_to() { - IndexStatus.write({static_cast(Index::Index2)}); + IndexStatus = Index::Index2; } }; struct PortIndex3 { - __declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); - __declare_index_io_port( VolumeRegister_t, RightCD2RightSPU, IORegister1Adr); + __declare_new_const_io_port(ResponseFifo, IORegister1Adr); + __declare_new_io_port(RightCD2RightSPU, IORegister1Adr); - __declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); - __declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); - __declare_index_io_port( VolumeRegister_t, RightCD2LeftSPU, IORegister1Adr); + __declare_new_const_io_port(DataFifo, IORegister2Adr); + __declare_new_const_io_port(DataFifo16, IORegister2Adr); + __declare_new_io_port(RightCD2LeftSPU, IORegister1Adr); - __declare_index_io_port_const(InterruptFlagRegister_t, InterruptFlagRegister, IORegister3Adr); - __declare_index_io_port( AudioVolumeApplyChange_t, AudioVolumeApplyChange, IORegister3Adr); + __declare_new_const_io_port(InterruptFlag, IORegister3Adr); + __declare_new_io_port(AudioVolumeApply, IORegister3Adr); static void change_to() { - IndexStatus.write({static_cast(Index::Index3)}); + IndexStatus = Index::Index3; } }; diff --git a/include/PSX/System/IOPorts/dma_io.hpp b/include/PSX/System/IOPorts/dma_io.hpp index 7a48a58f..7f7a1e69 100644 --- a/include/PSX/System/IOPorts/dma_io.hpp +++ b/include/PSX/System/IOPorts/dma_io.hpp @@ -4,130 +4,152 @@ namespace JabyEngine { namespace DMA_IO { - struct MADR : public ComplexBitMap { - static constexpr auto MemoryAdr = BitRange::from_to(0, 23); - }; + __declare_io_type(MADR, uint32_t, + static constexpr auto MemoryAdr = BitRange::from_to(0, 23); + ); - struct BCR : public ComplexBitMap { - struct __no_align SyncMode0 { - static constexpr auto NumberOfWords = BitRange::from_to(0, 15); - static constexpr auto CD_OneBlock = Bit(16); + __declare_io_type(BCR, uint32_t, + struct SyncMode0 { + static constexpr auto NumberOfWords = BitRange::from_to(0, 15); + static constexpr auto CD_OneBlock = Bit(16); + + static constexpr Self for_cd() { + // v Should be replaced with a named constant + return Self::from(SyncMode0::CD_OneBlock, SyncMode0::NumberOfWords.with(512)); + } }; - struct SyncMode1 : public ComplexBitMap { - static constexpr auto BlockSize = BitRange::from_to(0, 15); - static constexpr auto BlockAmount = BitRange::from_to(16, 31); + struct SyncMode1 { + static constexpr auto BlockSize = BitRange::from_to(0, 15); + static constexpr auto BlockAmount = BitRange::from_to(16, 31); }; struct SyncMode2 { }; - }; + ); - struct CHCHR : public ComplexBitMap { - enum _SyncMode { + __declare_io_type(CHCHR, uint32_t, + enum SyncMode_t { Sync0 = 0, //Start immediately, Sync1 = 1, //Sync blocks to DMA requests Sync2 = 2, //Linked List }; - static constexpr auto ManualStart = Bit(28); + static constexpr auto ManualStart = Bit(28); - static constexpr auto Start = Bit(24); + static constexpr auto Start = Bit(24); static constexpr auto Busy = Start; - static constexpr auto ChoppingCPUWindowSize = BitRange::from_to(20, 22); - static constexpr auto ChoppingDMAWindowSize = BitRange::from_to(16, 18); + static constexpr auto ChoppingCPUWindowSize = BitRange::from_to(20, 22); + static constexpr auto ChoppingDMAWindowSize = BitRange::from_to(16, 18); - static constexpr auto SyncMode = BitRange<_SyncMode>::from_to(9, 10); + static constexpr auto SyncMode = BitRange::from_to(9, 10); static constexpr auto UseSyncMode0 = SyncMode.with(Sync0); static constexpr auto UseSyncMode1 = SyncMode.with(Sync1); static constexpr auto UseSyncMode2 = SyncMode.with(Sync2); - static constexpr auto UseChopping = Bit(8); + static constexpr auto UseChopping = Bit(8); - static constexpr auto MemoryAdrDecreaseBy4 = Bit(1); + static constexpr auto MemoryAdrDecreaseBy4 = Bit(1); static constexpr auto MemoryAdrIncreaseBy4 = !MemoryAdrDecreaseBy4; - static constexpr auto FromMainRAM = Bit(0); + static constexpr auto FromMainRAM = Bit(0); static constexpr auto ToMainRAM = !FromMainRAM; - static constexpr CHCHR StartMDECin() { - return CHCHR{0x01000201}; + static constexpr Self StartMDECin() { + return Self{0x01000201}; } - static constexpr CHCHR StartMDECout() { - return CHCHR{0x01000200}; + static constexpr Self StartMDECout() { + return Self{0x01000200}; } - static constexpr CHCHR StartGPUReceive() { - return CHCHR{0x01000201}; + static constexpr Self StartGPUReceive() { + return Self{0x01000201}; } - static constexpr CHCHR StartCDROM() { - return CHCHR{0x11000000}; + static constexpr Self StartCDROM() { + return Self{0x11000000}; } - static constexpr CHCHR StartSPUReceive() { - return CHCHR{0x01000201}; + static constexpr Self StartSPUReceive() { + return Self{0x01000201}; } - static constexpr CHCHR StartOTC() { - return CHCHR{0x11000002}; + static constexpr Self StartOTC() { + return Self{0x11000002}; } - }; + ); struct __no_align Registers { - VolatileBitMapPOD adr; - VolatileBitMapPOD block_ctrl; - VolatileBitMapPOD channel_ctrl; + MADR_v adr; + BCR_v block_ctrl; + CHCHR_v channel_ctrl; + + void set_adr(uintptr_t adr) { + this->adr.set(MADR_t::MemoryAdr.with(adr)); + } + + void wait() { + while(this->channel_ctrl.is_set(CHCHR_t::Busy)); + } }; + // Those types do not need to be volatile because there members are + typedef Registers MDECin_v; + typedef Registers MDECout_v; + typedef Registers GPU_v; + typedef Registers CDROM_v; + typedef Registers SPU_v; + typedef Registers PIO_v; + typedef Registers OTC_v; + //0: Highest, 7: Lowest typedef uint32_t Priority; static constexpr Priority HighestPriority = 0; static constexpr Priority LowestPriority = 7; - struct DMAControlRegister : public ComplexBitMap { - static constexpr auto OTCEnable = Bit(27); - static constexpr auto OTCPriority = BitRange::from_to(24, 26); + __declare_io_type(DPCR, uint32_t, + static constexpr auto OTCEnable = Bit(27); + static constexpr auto OTCPriority = BitRange::from_to(24, 26); - static constexpr auto PIOEnable = Bit(23); - static constexpr auto PIOPriority = BitRange::from_to(20, 22); + static constexpr auto PIOEnable = Bit(23); + static constexpr auto PIOPriority = BitRange::from_to(20, 22); - static constexpr auto SPUEnable = Bit(19); - static constexpr auto SPUPriority = BitRange::from_to(16, 18); + static constexpr auto SPUEnable = Bit(19); + static constexpr auto SPUPriority = BitRange::from_to(16, 18); - static constexpr auto CDROMEnable = Bit(15); - static constexpr auto CDROMPriority = BitRange::from_to(12, 14); + static constexpr auto CDROMEnable = Bit(15); + static constexpr auto CDROMPriority = BitRange::from_to(12, 14); - static constexpr auto GPUEnable = Bit(11); - static constexpr auto GPUPriority = BitRange::from_to(8, 10); + static constexpr auto GPUEnable = Bit(11); + static constexpr auto GPUPriority = BitRange::from_to(8, 10); - static constexpr auto MDECoutEnable = Bit(7); - static constexpr auto MDECoutPriority = BitRange::from_to(4, 6); + static constexpr auto MDECoutEnable = Bit(7); + static constexpr auto MDECoutPriority = BitRange::from_to(4, 6); - static constexpr auto MDECinEnable = Bit(3); - static constexpr auto MDECinPriority = BitRange::from_to(0, 2); - }; + static constexpr auto MDECinEnable = Bit(3); + static constexpr auto MDECinPriority = BitRange::from_to(0, 2); + ); - struct DMAInterruptRegister : public ComplexBitMap { - static constexpr auto MasterEnable = Bit(31); - static constexpr auto Flags = BitRange::from_to(24, 30); - static constexpr auto MasterEnableDPCR = Bit(23); - static constexpr auto EnableDPCR = BitRange::from_to(16, 22); - static constexpr auto ForceIRQ = Bit(15); - }; + __declare_io_type(DICR, uint32_t, + static constexpr auto MasterEnable = Bit(31); + static constexpr auto Flags = BitRange::from_to(24, 30); + static constexpr auto MasterEnableDPCR = Bit(23); + static constexpr auto EnableDPCR = BitRange::from_to(16, 22); + static constexpr auto ForceIRQ = Bit(15); + ); - __declare_io_port_global_struct(Registers, MDECin, 0x1F801080); - __declare_io_port_global_struct(Registers, MDECout, 0x1F801090); - __declare_io_port_global_struct(Registers, GPU, 0x1F8010A0); - __declare_io_port_global_struct(Registers, CDROM, 0x1F8010B0); - __declare_io_port_global_struct(Registers, SPU, 0x1F8010C0); - __declare_io_port_global_struct(Registers, PIO, 0x1F8010D0); - __declare_io_port_global_struct(Registers, OTC, 0x1F8010E0); + __declare_new_io_port(MDECin, 0x1F801080); + __declare_new_io_port(MDECout, 0x1F801090); + __declare_new_io_port(GPU, 0x1F8010A0); + __declare_new_io_port(CDROM, 0x1F8010B0); + __declare_new_io_port(SPU, 0x1F8010C0); + __declare_new_io_port(PIO, 0x1F8010D0); + __declare_new_io_port(OTC, 0x1F8010E0); - __declare_io_port_global(DMAControlRegister, DPCR, 0x1F8010F0); - __declare_io_port_global(DMAInterruptRegister, DICR, 0x1F8010F4); + __declare_new_io_port(DPCR, 0x1F8010F0); + __declare_new_io_port(DICR, 0x1F8010F4); } } #endif //!__JABYENGINE_DMA_IO_HPP__ \ No newline at end of file diff --git a/include/PSX/System/IOPorts/gpu_io.hpp b/include/PSX/System/IOPorts/gpu_io.hpp index b5f4bf0c..43d93dfb 100644 --- a/include/PSX/System/IOPorts/gpu_io.hpp +++ b/include/PSX/System/IOPorts/gpu_io.hpp @@ -47,124 +47,162 @@ namespace JabyEngine { Off = 1 }; - struct Command { - struct GP0 : public ComplexBitMap { - - static constexpr GP0 QuickFill(GPU::Color24 color) { - return {(0x02 << 24) | color.raw()}; - } - - static constexpr GP0 CPU2VRAM_Blitting() { - return {(0b101u << 29)}; - } - - static constexpr GP0 DrawAreaTemplate(uint8_t code, uint16_t x, uint16_t y) { - constexpr auto Command = BitRange::from_to(24, 31); - constexpr auto Y = BitRange::from_to(10, 18); - constexpr auto X = BitRange::from_to(0, 9); - - return {GP0::with(Command.with(code), Y.with(y), X.with(x))}; - } - - static constexpr GP0 DrawAreaTopLeft(uint16_t x, uint16_t y) { - return DrawAreaTemplate(0xE3, x, y); - } - - static constexpr GP0 DrawAreaBottomRight(uint16_t x, uint16_t y) { - return DrawAreaTemplate(0xE4, x, y); - } - - static constexpr GP0 TopLeftPosition(uint16_t x, uint16_t y) { - return {static_cast((y << 16u) | x)}; - } - - static constexpr GP0 WidthHeight(uint16_t w, uint16_t h) { - return {static_cast((h << 16u) | w)}; - } + __declare_io_type(DisplayMode, uint32_t, + enum struct TVEncoding { + NTSC = 0, + PAL = 1, }; - struct GP1 : public ComplexBitMap { + static constexpr auto HorizontalResolution368 = Bit(6); + static constexpr auto VerticalInterlace = Bit(5); + static constexpr auto DisplayAreaColorDepth = BitRange::from_to(4, 4); + static constexpr auto VideoMode = BitRange::from_to(3, 3); + static constexpr auto VerticalResolution = BitRange::from_to(2, 2); + static constexpr auto HorizontalResolution = BitRange::from_to(0, 1); + + static constexpr Self PAL() { + return Self::from( + HorizontalResolution.with(GPU_IO::HorizontalResolution::$320), + VerticalResolution.with(GPU_IO::VerticalResolution::$240), + VideoMode.with(TVEncoding::PAL), + DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit) + ); + } + + static constexpr Self NTSC() { + return Self::from( + HorizontalResolution.with(GPU_IO::HorizontalResolution::$320), + VerticalResolution.with(GPU_IO::VerticalResolution::$240), + VideoMode.with(TVEncoding::NTSC), + DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit) + ); + } + ); + + __declare_io_type(GP0, uint32_t, + ); + + __declare_io_type(GP1, uint32_t, + ); + + + struct Command { + struct Helper { + static constexpr GP0_t DrawAreaTemplate(uint8_t code, uint16_t x, uint16_t y) { + constexpr auto Command = BitRange::from_to(24, 31); + constexpr auto Y = BitRange::from_to(10, 18); + constexpr auto X = BitRange::from_to(0, 9); + + return GP0_t::from(Command.with(code), Y.with(y), X.with(x)); + } + static constexpr uint32_t construct_cmd(uint8_t cmd, uint32_t value) { return ((cmd << 24) | value); } - - static constexpr GP1 Reset() { - return {0}; - } - - static constexpr GP1 ResetCMDBufer() { - return {construct_cmd(0x01, 0)}; - } - - static constexpr GP1 SetDisplayState(DisplayState state) { - return {construct_cmd(0x03, static_cast(state))}; - } - - static constexpr GP1 DMADirection(DMADirection dir) { - return {construct_cmd(0x04, static_cast(dir))}; - } - - static constexpr GP1 DisplayArea(uint16_t x, uint16_t y) { - constexpr auto X = BitRange::from_to(0, 9); - constexpr auto Y = BitRange::from_to(10, 18); - - return {construct_cmd(0x05, ComplexBitMap::with(X.with(x), Y.with(y)).raw)}; - } - - static constexpr GP1 HorizontalDisplayRange(uint32_t x1, uint32_t x2) { - constexpr auto X1 = BitRange::from_to(0, 11); - constexpr auto X2 = BitRange::from_to(12, 23); - - return {construct_cmd(0x06, ComplexBitMap::with(X1.with(x1), X2.with(x2)).raw)}; - } - - static constexpr GP1 VerticalDisplayRange(uint32_t y1, uint32_t y2) { - constexpr auto Y1 = BitRange::from_to(0, 9); - constexpr auto Y2 = BitRange::from_to(10, 19); - - return {construct_cmd(0x07, ComplexBitMap::with(Y1.with(y1), Y2.with(y2)).raw)}; - } - - static constexpr GP1 DisplayMode(uint32_t mode) { - return {construct_cmd(0x08, mode)}; - } }; + + static constexpr GP0_t QuickFill(GPU::Color24 color) { + return {(0x02 << 24) | color.raw()}; + } + + static constexpr GP0_t CPU2VRAM_Blitting() { + return {(0b101u << 29)}; + } + + static constexpr GP0_t DrawAreaTopLeft(uint16_t x, uint16_t y) { + return Helper::DrawAreaTemplate(0xE3, x, y); + } + + static constexpr GP0_t DrawAreaBottomRight(uint16_t x, uint16_t y) { + return Helper::DrawAreaTemplate(0xE4, x, y); + } + + static constexpr GP0_t TopLeftPosition(uint16_t x, uint16_t y) { + return {static_cast((y << 16u) | x)}; + } + + static constexpr GP0_t WidthHeight(uint16_t w, uint16_t h) { + return {static_cast((h << 16u) | w)}; + } + + static constexpr GP1_t Reset() { + return {0}; + } + + static constexpr GP1_t ResetCMDBufer() { + return {Helper::construct_cmd(0x01, 0)}; + } + + static constexpr GP1_t SetDisplayState(DisplayState state) { + return {Helper::construct_cmd(0x03, static_cast(state))}; + } + + static constexpr GP1_t DMADirection(DMADirection dir) { + return {Helper::construct_cmd(0x04, static_cast(dir))}; + } + + static constexpr GP1_t DisplayArea(uint16_t x, uint16_t y) { + constexpr auto X = BitRange::from_to(0, 9); + constexpr auto Y = BitRange::from_to(10, 18); + + return {Helper::construct_cmd(0x05, X.as_value(x) | Y.as_value(y))}; + } + + static constexpr GP1_t HorizontalDisplayRange(uint32_t x1, uint32_t x2) { + constexpr auto X1 = BitRange::from_to(0, 11); + constexpr auto X2 = BitRange::from_to(12, 23); + + return {Helper::construct_cmd(0x06, X1.as_value(x1) | X2.as_value(x2))}; + } + + static constexpr GP1_t VerticalDisplayRange(uint32_t y1, uint32_t y2) { + constexpr auto Y1 = BitRange::from_to(0, 9); + constexpr auto Y2 = BitRange::from_to(10, 19); + + return {Helper::construct_cmd(0x07, Y1.as_value(y1) | Y2.as_value(y2))}; + } + + static constexpr GP1_t DisplayMode(DisplayMode_t mode) { + return {Helper::construct_cmd(0x08, mode)}; + } }; - struct GPUStatusRegister : public ComplexBitMap { - static constexpr auto DrawingOddLinesInterlaced = Bit(31); - static constexpr auto DMADirectionValue = BitRange::from_to(29, 30); - static constexpr auto DMAReady = Bit(28); - static constexpr auto VRAMtoCPUtransferReay = Bit(27); - static constexpr auto GP0ReadyForCMD = Bit(26); - static constexpr auto FifoNotFull = Bit(25); // Only for Fifo - static constexpr auto InterruptRequest = Bit(24); - static constexpr auto DisplayDisabled = Bit(23); - static constexpr auto VerticalInterlaceOn = Bit(22); - static constexpr auto DisplayAreaColorDepth = BitRange::from_to(21, 21); - static constexpr auto VideoModePal = Bit(20); - static constexpr auto VerticalResolutionValue = BitRange::from_to(19, 19); - static constexpr auto HorizontalResolutionValue = BitRange::from_to(17, 18); - static constexpr auto HorizontalResolution368 = Bit(16); - static constexpr auto TexturesDisabled = Bit(15); - static constexpr auto NotDrawingMaskedPixels = Bit(12); - static constexpr auto MaskBitSetDuringDrawEnabled = Bit(11); - static constexpr auto DrawingToDisplayAreadAllowed = Bit(10); - static constexpr auto DitherEnabled = Bit(9); - static constexpr auto TexturePageColorValue = BitRange::from_to(7, 8); - static constexpr auto SemiTransparencyValue = BitRange::from_to(5, 6); - static constexpr auto TexturePageY = BitRange::from_to(4, 4); // N*256 - static constexpr auto TexturePageX = BitRange::from_to(0, 3); // N*64 + __declare_io_type(GPUSTAT, uint32_t, + static constexpr auto DrawingOddLinesInterlaced = Bit(31); + static constexpr auto DMADirectionValue = BitRange::from_to(29, 30); + static constexpr auto DMAReady = Bit(28); + static constexpr auto VRAMtoCPUtransferReay = Bit(27); + static constexpr auto GP0ReadyForCMD = Bit(26); + static constexpr auto FifoNotFull = Bit(25); // Only for Fifo + static constexpr auto InterruptRequest = Bit(24); + static constexpr auto DisplayDisabled = Bit(23); + static constexpr auto VerticalInterlaceOn = Bit(22); + static constexpr auto DisplayAreaColorDepth = BitRange::from_to(21, 21); + static constexpr auto VideoModePal = Bit(20); + static constexpr auto VerticalResolutionValue = BitRange::from_to(19, 19); + static constexpr auto HorizontalResolutionValue = BitRange::from_to(17, 18); + static constexpr auto HorizontalResolution368 = Bit(16); + static constexpr auto TexturesDisabled = Bit(15); + static constexpr auto NotDrawingMaskedPixels = Bit(12); + static constexpr auto MaskBitSetDuringDrawEnabled = Bit(11); + static constexpr auto DrawingToDisplayAreadAllowed = Bit(10); + static constexpr auto DitherEnabled = Bit(9); + static constexpr auto TexturePageColorValue = BitRange::from_to(7, 8); + static constexpr auto SemiTransparencyValue = BitRange::from_to(5, 6); + static constexpr auto TexturePageY = BitRange::from_to(4, 4); // N*256 + static constexpr auto TexturePageX = BitRange::from_to(0, 3); // N*64 - static constexpr auto VerticalResolution480 = Bit(19); - static constexpr auto TexturePageY256 = Bit(4); - }; + static constexpr auto VerticalResolution480 = Bit(19); + static constexpr auto TexturePageY256 = Bit(4); + ); - __declare_io_port_global(Command::GP0, GP0, 0x1F801810); - __declare_io_port_global(Command::GP1, GP1, 0x1F801814); + typedef volatile uint32_t GPUREAD_v; - __declare_io_port_global_const_simple(uint32_t, GPUREAD, 0x1F801810); - __declare_io_port_global_const(GPUStatusRegister, GPUSTAT, 0x1F801814); + __declare_new_io_port(GP0, 0x1F801810); + __declare_new_io_port(GP1, 0x1F801814); + + __declare_new_const_io_port(GPUREAD, 0x1F801810); + __declare_new_const_io_port(GPUSTAT, 0x1F801814); } } #endif //!__JABYENGINE_GPU_IO_HPP__ \ No newline at end of file diff --git a/include/PSX/System/IOPorts/interrupt_io.hpp b/include/PSX/System/IOPorts/interrupt_io.hpp index 4e2556b8..cb2aeb3f 100644 --- a/include/PSX/System/IOPorts/interrupt_io.hpp +++ b/include/PSX/System/IOPorts/interrupt_io.hpp @@ -4,42 +4,42 @@ namespace JabyEngine { struct Interrupt { - static constexpr auto VBlank = Bit(0); - static constexpr auto GPU = Bit(1); - static constexpr auto CDROM = Bit(2); - static constexpr auto DMA = Bit(3); - static constexpr auto Timer0 = Bit(4); - static constexpr auto Timer1 = Bit(5); - static constexpr auto Timer2 = Bit(6); - static constexpr auto Periphery = Bit(7); - static constexpr auto SIO = Bit(8); - static constexpr auto SPU = Bit(9); - static constexpr auto Controller = Bit(10); + static constexpr auto VBlank = Bit(0); + static constexpr auto GPU = Bit(1); + static constexpr auto CDROM = Bit(2); + static constexpr auto DMA = Bit(3); + static constexpr auto Timer0 = Bit(4); + static constexpr auto Timer1 = Bit(5); + static constexpr auto Timer2 = Bit(6); + static constexpr auto Periphery = Bit(7); + static constexpr auto SIO = Bit(8); + static constexpr auto SPU = Bit(9); + static constexpr auto Controller = Bit(10); static constexpr auto LightPen = Controller; - typedef struct Status : public ComplexBitMap { - } Status_t; + __declare_io_type(Status, uint32_t, + ); - typedef struct Mask : public ComplexBitMap { - } Mask_t; + __declare_io_type(Mask, uint32_t, + ); - __declare_io_port_member(Status_t, Status, 0x1F801070); - __declare_io_port_member(Mask_t, Mask, 0x1F801074); + __declare_new_io_port(Status, 0x1F801070); + __declare_new_io_port(Mask, 0x1F801074); - static bool is_irq(Bit irq) { - return Status.read().is_bit_set(irq); + static bool is_irq(Bit irq) { + return Status.is_set(irq); } - static void ack_irq(Bit irq) { - Status.write({Status.read().clear_bit(irq)}); + static void ack_irq(Bit irq) { + Status.clear(irq); } - static void disable_irq(Bit irq) { - Mask.write({Mask.read().clear_bit(irq)}); + static void disable_irq(Bit irq) { + Mask.clear(irq); } - static void enable_irq(Bit irq) { - Mask.write({Mask.read().set_bit(irq)}); + static void enable_irq(Bit irq) { + Mask.set(irq); } }; } diff --git a/include/PSX/System/IOPorts/ioport.hpp b/include/PSX/System/IOPorts/ioport.hpp index bec6bf78..7120225f 100644 --- a/include/PSX/System/IOPorts/ioport.hpp +++ b/include/PSX/System/IOPorts/ioport.hpp @@ -1,60 +1,124 @@ #ifndef __JABYENGINE_IOPORT_HPP__ #define __JABYENGINE_IOPORT_HPP__ -#include "../../Auxiliary/complex_bitmap.hpp" +#include "../../Auxiliary/types.hpp" +#include "../../Auxiliary/bits.hpp" namespace JabyEngine { - template - struct VolatilePOD { - volatile T raw; + namespace IOPort { + struct IOValueType { + template + struct Normal { + typedef T Value; + typedef T UnderlyingValue; + }; - constexpr T read() const { - return this->raw; + template + struct Volatile { + typedef volatile T Value; + typedef T UnderlyingValue; + }; + }; + } + + namespace IOAdress { + constexpr uintptr_t patch_adr(uintptr_t adr) { + constexpr uintptr_t Mask = 0xF0000000; + constexpr uintptr_t Base = 0x10000000; // We might want to change this later to 0xB0000000 for caching and stuff (More research needed) + + return (Base + (adr & ~Mask)); } + } - constexpr void write(T value) { - this->raw = value; - } - }; + #define __declare_new_named_io_port(type, name, adr) \ + static inline auto& name = *reinterpret_cast(IOAdress::patch_adr(adr)) - // For use with ComplexBitMaps or what else satisfies this API - template - struct VolatileBitMapPOD { - typedef typename T::UnderlyingType Raw; + #define __declare_new_io_port(name, adr) \ + __declare_new_named_io_port(name, name, adr) - VolatilePOD pod; + #define __declare_new_const_io_port(name, adr) \ + __declare_new_named_io_port(const name, name, adr) + + #define __declare_new_io_port_array(name, adr, size) \ + static inline auto& name = reinterpret_cast(*reinterpret_cast(adr)) - constexpr Raw read_raw() const { - return this->pod.read(); - } - - constexpr T read() const { - return T{this->pod.read()}; - } - - constexpr Raw read(const BitRange& range) const { - return VolatileBitMapPOD::read().get_value(range); - } - - constexpr void write_raw(Raw value) { - this->pod.write(value); - } - - constexpr void write(const T& value) { - this->pod.write(static_cast(value)); - } - - constexpr void write(const BitRangeValue& value) { - VolatileBitMapPOD::write(T{T::with(value)}); - } - }; + // We need this construct to ensure the types end up being a POD - Inheritance doesn't qualify for a POD + #define __declare_io_type(name, type, ...) \ + template typename T> \ + struct name##_io_base { \ + typedef T::UnderlyingValue UnderlyingValue; \ + typedef name##_io_base Self; \ + \ + T::Value raw_value = 0; \ + \ + __VA_ARGS__ \ + \ + template \ + static constexpr Self from(const ARGS&...args) { \ + return Self().set_va(args...); \ + } \ + \ + constexpr Self& set(Bit bit) { \ + this->raw_value = bit::set(this->raw_value, bit); \ + return *this; \ + } \ + \ + constexpr Self& set(ClearBit bit) { \ + this->raw_value = bit::set(this->raw_value, bit); \ + return *this; \ + } \ + \ + constexpr Self& set(BitRange bits, UnderlyingValue value) { \ + this->raw_value = bit::value::set_normalized(this->raw_value, bits, value); \ + return *this; \ + } \ + \ + template \ + constexpr Self& set(const BitRange::RangeValuePair& value) { \ + this->raw_value = bit::value::set_normalized(this->raw_value, value); \ + return *this; \ + } \ + \ + template \ + constexpr Self& set_va(const S& head) { \ + return this->set(head); \ + } \ + \ + template \ + constexpr Self& set_va(const S& head, const ARGS&...tail) { \ + return this->set(head).set_va(tail...); \ + } \ + \ + constexpr UnderlyingValue get(BitRange bits) const { \ + return bit::value::get_normalized(this->raw_value, bits.pos, bits.length); \ + } \ + \ + constexpr Self& clear(Bit bit) { \ + this->raw_value = bit::clear(this->raw_value, bit); \ + return *this; \ + } \ + \ + constexpr bool is_set(Bit bit) const { \ + return bit::is_set(this->raw_value, bit); \ + } \ + \ + constexpr void operator=(UnderlyingValue value) { \ + this->raw_value = value; \ + } \ + \ + constexpr operator UnderlyingValue() const { \ + return this->raw_value; \ + } \ + }; \ + \ + typedef name##_io_base name##_v; \ + typedef name##_io_base name##_t struct __no_align ubus32_t { - typedef ComplexBitMap Base16; + __declare_io_type(uint16_t, uint16_t,); + uint16_t_v low; + uint16_t_v high; - VolatileBitMapPOD low; - VolatileBitMapPOD high; - - constexpr ubus32_t(uint32_t value) { + constexpr ubus32_t(uint32_t value) : low{0}, high{0} { *this = value; } @@ -63,34 +127,18 @@ namespace JabyEngine { } constexpr operator uint32_t() const { - return ((this->high.read_raw() << 16) | this->low.read_raw()); + const uint32_t high = this->high; + const uint32_t low = this->low; + + return ((high << 16) | low); } constexpr ubus32_t& operator=(uint32_t value) { - this->low.write_raw(value & 0xFFFF); - this->high.write_raw(value >> 16); + this->low = (value & 0xFFFF); + this->high = (value >> 16); return *this; } }; - static constexpr uintptr_t IO_Base_Mask = 0xF0000000; - static constexpr uintptr_t IO_Base_Adr = 0x10000000; - - #define __io_port_adr(adr) (IO_Base_Adr + (adr & ~IO_Base_Mask)) - #define __cast_io_adr_with_type(cv, type, name, adr) static __always_inline cv auto& name = *reinterpret_cast(__io_port_adr(adr)) - - - #define __declare_io_port_global(type, name, adr) __cast_io_adr_with_type(, VolatileBitMapPOD, name, adr) - #define __declare_io_port_global_const(type, name, adr) __cast_io_adr_with_type(const, VolatileBitMapPOD, name, adr) - #define __declare_io_port_global_simple(type, name, adr) __cast_io_adr_with_type(, VolatilePOD, name, adr) - #define __declare_io_port_global_const_simple(type, name, adr) __cast_io_adr_with_type(const, VolatilePOD, name, adr) - - #define __declare_io_port_member(type, name, adr) __cast_io_adr_with_type(inline, VolatileBitMapPOD, name, adr) - #define __declare_io_port_member_const(type, name, adr) __cast_io_adr_with_type(const inline, VolatileBitMapPOD, name, adr) - #define __declare_io_port_member_simple(type, name, adr) __cast_io_adr_with_type(inline, VolatilePOD, name, adr) - #define __declare_io_port_member_const_simple(type, name, adr) __cast_io_adr_with_type(const inline, VolatilePOD, name, adr) - - #define __declare_io_port_global_array(type, name, adr, size) static __always_inline auto& name = reinterpret_cast(*reinterpret_cast(__io_port_adr(adr))) - #define __declare_io_port_global_struct(type, name, adr) static __always_inline auto& name = *reinterpret_cast(__io_port_adr(adr)) } #endif //!__JABYENGINE_IOPORT_HPP__ \ No newline at end of file diff --git a/include/PSX/System/IOPorts/memory_io.hpp b/include/PSX/System/IOPorts/memory_io.hpp index 104b8d5f..dd884d23 100644 --- a/include/PSX/System/IOPorts/memory_io.hpp +++ b/include/PSX/System/IOPorts/memory_io.hpp @@ -4,20 +4,20 @@ namespace JabyEngine { namespace Memory_IO { - struct COM_DELAY { - typedef uint32_t Type; + __declare_io_type(COM_DELAY, uint32_t, + void setup() { + this->raw_value = 0x1325; + } + ); - static constexpr uint32_t SetupValue = 0x1325; - }; + __declare_io_type(CD_DELAY, uint32_t, + void setup() { + this->raw_value = 0x20943; + } + ); - struct CD_DELAY { - typedef uint32_t Type; - - static constexpr uint32_t SetupValue = 0x20943; - }; - - __declare_io_port_global_simple(COM_DELAY::Type, COM_DELAY, 0x1F801020); - __declare_io_port_global_simple(CD_DELAY::Type, CD_DELAY, 0x1F801018); + __declare_new_io_port(COM_DELAY, 0x1F801020); + __declare_new_io_port(CD_DELAY, 0x1F801018); } } diff --git a/include/PSX/System/IOPorts/spu_io.hpp b/include/PSX/System/IOPorts/spu_io.hpp index 0e582749..a5edfea0 100644 --- a/include/PSX/System/IOPorts/spu_io.hpp +++ b/include/PSX/System/IOPorts/spu_io.hpp @@ -25,60 +25,64 @@ namespace JabyEngine { //0..3 = +7, +6, +5, +4 or -6, -7, -6, -5 typedef uint8_t Step; - typedef int16_t SimpleVolume; + typedef int16_t SimpleVolume; + typedef volatile int16_t SimpleVolume_v; - struct SampleRate : public ComplexBitMap { - static constexpr SampleRate from_HZ(double freq) { + typedef volatile uint16_t Adr_v; + typedef volatile uint16_t DataTransferControl_v; + + __declare_io_type(SampleRate, uint16_t, + static constexpr Self from_HZ(double freq) { //4096 == 44100Hz constexpr double Base = (4096.0 / 44100.0); return {static_cast((freq*Base))}; } - }; + ); - struct SweepVolume : public ComplexBitMap { + __declare_io_type(SweepVolume, int16_t, // For Volume Mode - static constexpr auto SweepEnable = Bit(15); + static constexpr auto SweepEnable = Bit(15); static constexpr auto VolumeEnable = !SweepEnable; - static constexpr auto Volume = BitRange::from_to(0, 14); + static constexpr auto Volume = BitRange::from_to(0, 14); // For Sweep Mode - static constexpr auto SweepMode = Bit(14); - static constexpr auto SweepDirection = Bit(13); - static constexpr auto SweepPhase = Bit(12); - static constexpr auto SweepShift = BitRange::from_to(2, 6); - static constexpr auto SweepStep = BitRange::from_to(0, 1); + static constexpr auto SweepMode = Bit(14); + static constexpr auto SweepDirection = Bit(13); + static constexpr auto SweepPhase = Bit(12); + static constexpr auto SweepShift = BitRange::from_to(2, 6); + static constexpr auto SweepStep = BitRange::from_to(0, 1); + ); + + __declare_io_type(SR, uint16_t, + static constexpr auto SustainMode = Bit(31 - 16); + static constexpr auto SustainDirection = Bit(30 - 16); + static constexpr auto SustainShift = BitRange::from_to((24 - 16), (28 - 16)); + static constexpr auto SustainStep = BitRange::from_to((22 - 16), (23 - 16)); + static constexpr auto ReleaseMode = Bit(21 - 16); + static constexpr auto ReleaseShift = BitRange::from_to((16 - 16), (20 - 16)); + ); + + __declare_io_type(AD, uint16_t, + static constexpr auto AttackMode = Bit(15); + static constexpr auto AttackShift = BitRange::from_to(10, 14); + static constexpr auto AttackStep = BitRange::from_to(8, 9); + static constexpr auto DecayShift = BitRange::from_to(4, 7); + static constexpr auto SustainLevel = BitRange::from_to(0, 3); + ); + + struct __no_align Voice_v { + SweepVolume_v volumeLeft; //Offset: 0x0 + SweepVolume_v volumeRight; //Offset: 0x2 + SampleRate_v sampleRate; //Offset: 0x4; + Adr_v adr; //Offset: 0x6 + AD_v ad; //Offset: 0x8 + SR_v sr; //Offset: 0xA + SimpleVolume_v currentVolume; //Offset: 0xC + Adr_v repeatAdr; //Offset: 0xE }; - struct SR : public ComplexBitMap { - static constexpr auto SustainMode = Bit(31 - 16); - static constexpr auto SustainDirection = Bit(30 - 16); - static constexpr auto SustainShift = BitRange::from_to((24 - 16), (28 - 16)); - static constexpr auto SustainStep = BitRange::from_to((22 - 16), (23 - 16)); - static constexpr auto ReleaseMode = Bit(21 - 16); - static constexpr auto ReleaseShift = BitRange::from_to((16 - 16), (20 - 16)); - }; - - struct AD : public ComplexBitMap { - static constexpr auto AttackMode = Bit(15); - static constexpr auto AttackShift = BitRange::from_to(10, 14); - static constexpr auto AttackStep = BitRange::from_to(8, 9); - static constexpr auto DecayShift = BitRange::from_to(4, 7); - static constexpr auto SustainLevel = BitRange::from_to(0, 3); - }; - - struct __no_align Voice { - VolatileBitMapPOD volumeLeft; //Offset: 0x0 - VolatileBitMapPOD volumeRight; //Offset: 0x2 - VolatileBitMapPOD sampleRate; //Offset: 0x4; - VolatilePOD adr; //Offset: 0x6 - VolatileBitMapPOD ad; //Offset: 0x8 - VolatileBitMapPOD sr; //Offset: 0xA - VolatilePOD currentVolume; //Offset: 0xC - VolatilePOD repeatAdr; //Offset: 0xE - }; - - struct ControlRegister : public ComplexBitMap { + __declare_io_type(ControlRegister, uint16_t, enum RAMTransferMode { Stop = 0, ManualWrite = 1, @@ -86,69 +90,71 @@ namespace JabyEngine { DMARead = 3 }; - static constexpr auto Enable = Bit(15); - static constexpr auto Unmute = Bit(14); - static constexpr auto NoiseFrequcenyShift = BitRange::from_to(10, 13); - static constexpr auto NoiseFrequcenyStep = BitRange::from_to(8, 9); - static constexpr auto ReverbMasterEnable = Bit(7); - static constexpr auto IRQ9Enable = Bit(6); - static constexpr auto TransferMode = BitRange::from_to(4, 5); - static constexpr auto ExternalAudioReverb = Bit(3); - static constexpr auto CDAudioReverb = Bit(2); - static constexpr auto ExternalAudioEnable = Bit(1); - static constexpr auto CDAudioEnable = Bit(0); - }; + static constexpr auto Enable = Bit(15); + static constexpr auto Unmute = Bit(14); + static constexpr auto NoiseFrequcenyShift = BitRange::from_to(10, 13); + static constexpr auto NoiseFrequcenyStep = BitRange::from_to(8, 9); + static constexpr auto ReverbMasterEnable = Bit(7); + static constexpr auto IRQ9Enable = Bit(6); + static constexpr auto TransferMode = BitRange::from_to(4, 5); + static constexpr auto ExternalAudioReverb = Bit(3); + static constexpr auto CDAudioReverb = Bit(2); + static constexpr auto ExternalAudioEnable = Bit(1); + static constexpr auto CDAudioEnable = Bit(0); + ); - struct PitchModFlags : public ComplexBitMap { - static constexpr BitRange EnableBits = BitRange::from_to(1, 23); - }; + __declare_io_type(PMON, uint16_t, + static constexpr auto EnableBits = BitRange::from_to(1, 23); + ); - struct NoiseGenerator : public ComplexBitMap { - static constexpr BitRange NoiseBits = BitRange::from_to(0, 23); - }; + __declare_io_type(NON, uint16_t, + static constexpr auto NoiseBits = BitRange::from_to(0, 23); + ); - struct EchoOn : public ComplexBitMap { - static constexpr BitRange EchoBits = BitRange::from_to(0, 23); - }; + __declare_io_type(EON, uint16_t, + static constexpr auto EchoBits = BitRange::from_to(0, 23); + ); static constexpr size_t VoiceCount = 24; struct Key { - __cast_io_adr_with_type(inline, ubus32_t, On, 0x1F801D88); - __cast_io_adr_with_type(inline, ubus32_t, Off, 0x1F801D8C); - __cast_io_adr_with_type(inline, ubus32_t, Status, 0x1F801D9C); + typedef ubus32_t ubus32_v; + + __declare_new_named_io_port(ubus32, On, 0x1F801D88); + __declare_new_named_io_port(ubus32, Off, 0x1F801D8C); + __declare_new_named_io_port(ubus32, Status, 0x1F801D9C); }; struct MainVolume { - __declare_io_port_member(SweepVolume, Left, 0x1F801D80); - __declare_io_port_member(SweepVolume, Right, 0x1F801D82); + __declare_new_named_io_port(SweepVolume, Left, 0x1F801D80); + __declare_new_named_io_port(SweepVolume, Right, 0x1F801D82); }; struct CDVolume { - __declare_io_port_member_simple(SimpleVolume, Left, 0x1F801DB0); - __declare_io_port_member_simple(SimpleVolume, Right, 0x1F801DB2); + __declare_new_named_io_port(SimpleVolume, Left, 0x1F801DB0); + __declare_new_named_io_port(SimpleVolume, Right, 0x1F801DB2); }; struct ExternalAudioInputVolume { - __declare_io_port_member_simple(SimpleVolume, Left, 0x1F801DB4); - __declare_io_port_member_simple(SimpleVolume, Right, 0x1F801DB6); + __declare_new_named_io_port(SimpleVolume, Left, 0x1F801DB4); + __declare_new_named_io_port(SimpleVolume, Right, 0x1F801DB6); }; struct Reverb { struct Volume { - __declare_io_port_member_simple(SimpleVolume, Left, 0x1F801D84); - __declare_io_port_member_simple(SimpleVolume, Right, 0x1F801D86); + __declare_new_named_io_port(SimpleVolume, Left, 0x1F801D84); + __declare_new_named_io_port(SimpleVolume, Right, 0x1F801D86); }; - __declare_io_port_member_simple(uint16_t, WorkAreaAdr, 0x1F801DA2); + __declare_new_named_io_port(Adr, WorkAreaAdr, 0x1F801DA2); }; - __declare_io_port_global(ControlRegister, Control, 0x1F801DAA); - __declare_io_port_global_simple(uint16_t, DataTransferControl, 0x1F801DAC); - __declare_io_port_global(PitchModFlags, PMON, 0x1F801D90); - __declare_io_port_global(NoiseGenerator, NON, 0x1F801D94); - __declare_io_port_global(EchoOn, EON, 0x1F801D98); + __declare_new_io_port(ControlRegister, 0x1F801DAA); + __declare_new_io_port(DataTransferControl, 0x1F801DAC); + __declare_new_io_port(PMON, 0x1F801D90); + __declare_new_io_port(NON, 0x1F801D94); + __declare_new_io_port(EON, 0x1F801D98); - __declare_io_port_global_array(struct Voice, Voice, 0x1F801C00, VoiceCount); + __declare_new_io_port_array(Voice, 0x1F801C00, VoiceCount); } } #endif //!__JABYENGINE_SPU_IO_HPP__ \ No newline at end of file diff --git a/include/PSX/System/IOPorts/timer_io.hpp b/include/PSX/System/IOPorts/timer_io.hpp index c8ff6e96..eadd5d44 100644 --- a/include/PSX/System/IOPorts/timer_io.hpp +++ b/include/PSX/System/IOPorts/timer_io.hpp @@ -4,94 +4,108 @@ namespace JabyEngine { namespace Timer_IO { - struct CounterMode : public ComplexBitMap { - static constexpr auto SyncEnable = Bit(0); + __declare_io_type(CounterMode, uint32_t, + static constexpr auto SyncEnable = Bit(0); static constexpr auto FreeRun = !SyncEnable; - static constexpr auto SyncMode = BitRange::from_to(1, 2); - static constexpr auto ResetAfterTarget = Bit(3); - static constexpr auto IRQAtTarget = Bit(4); - static constexpr auto IRQAtMax = Bit(5); - static constexpr auto IRQEveryTime = Bit(6); + static constexpr auto SyncMode = BitRange::from_to(1, 2); + static constexpr auto ResetAfterTarget = Bit(3); + static constexpr auto IRQAtTarget = Bit(4); + static constexpr auto IRQAtMax = Bit(5); + static constexpr auto IRQEveryTime = Bit(6); static constexpr auto IRQOneShot = !IRQEveryTime; - static constexpr auto IRQToggle = Bit(7); + static constexpr auto IRQToggle = Bit(7); static constexpr auto IRQPulse = !IRQToggle; - static constexpr auto ClockSource = BitRange::from_to(8, 9); - static constexpr auto HasIRQRequest = Bit(10); - static constexpr auto IsTargetReached = Bit(11); - static constexpr auto IsMaxReached = Bit(12); - }; + static constexpr auto ClockSource = BitRange::from_to(8, 9); + static constexpr auto HasIRQRequest = Bit(10); + static constexpr auto IsTargetReached = Bit(11); + static constexpr auto IsMaxReached = Bit(12); + ); - struct CounterTarget : public ComplexBitMap { - static constexpr auto CounterTargetValue = BitRange::from_to(0, 15); - }; + __declare_io_type(CounterTarget, uint32_t, + static constexpr auto CounterTargetValue = BitRange::from_to(0, 15); + ); - struct CounterValue : public ComplexBitMap { - static constexpr auto Value = BitRange::from_to(0, 15); - }; + __declare_io_type(CounterValue, uint32_t, + static constexpr auto Value = BitRange::from_to(0, 15); + ); struct __no_align Counter { - VolatileBitMapPOD value; - VolatileBitMapPOD mode; - VolatileBitMapPOD target; + CounterValue_v value; + CounterMode_v mode; + CounterTarget_v target; + private: uint32_t _unused; + + public: + constexpr uint16_t get_current_value() const { + return this->value.get(CounterValue_v::Value); + } + + constexpr void set_target_value(uint16_t value) { + this->target.set(CounterTarget_v::CounterTargetValue, value); + } + + constexpr void set_mode(CounterMode_t mode) { + this->mode = mode; + } }; static constexpr uintptr_t counter_base_adr(size_t ID) { return (0x1F801100 + (ID*0x10)); } - struct __no_align Counter0 : public Counter { + struct __no_align Counter0_v : public Counter { struct SyncMode { - static constexpr auto Pause_During_Hblank = CounterMode::SyncMode.with(0); - static constexpr auto Zero_At_Hblank = CounterMode::SyncMode.with(1); - static constexpr auto Zero_At_Hblank_Pause_Outside_Hblank = CounterMode::SyncMode.with(2); - static constexpr auto Pause_Until_Hblank_Then_Freerun = CounterMode::SyncMode.with(3); + static constexpr auto Pause_During_Hblank = CounterMode_v::SyncMode.with(0u); + static constexpr auto Zero_At_Hblank = CounterMode_v::SyncMode.with(1u); + static constexpr auto Zero_At_Hblank_Pause_Outside_Hblank = CounterMode_v::SyncMode.with(2u); + static constexpr auto Pause_Until_Hblank_Then_Freerun = CounterMode_v::SyncMode.with(3u); }; struct Source { - static constexpr auto System_Clock = CounterMode::ClockSource.with(0); - static constexpr auto Dot_Clock = CounterMode::ClockSource.with(1); - static constexpr auto System_Clock_Too = CounterMode::ClockSource.with(2); - static constexpr auto Dot_Clock_Too = CounterMode::ClockSource.with(3); + static constexpr auto System_Clock = CounterMode_v::ClockSource.with(0u); + static constexpr auto Dot_Clock = CounterMode_v::ClockSource.with(1u); + static constexpr auto System_Clock_Too = CounterMode_v::ClockSource.with(2u); + static constexpr auto Dot_Clock_Too = CounterMode_v::ClockSource.with(3u); }; }; - struct __no_align Counter1 : public Counter { + struct __no_align Counter1_v : public Counter { struct SyncMode { - static constexpr auto Pause_During_Vblank = CounterMode::SyncMode.with(0); - static constexpr auto Zero_At_Vblank = CounterMode::SyncMode.with(1); - static constexpr auto Zero_At_Vblank_Pause_Outside_Vblank = CounterMode::SyncMode.with(2); - static constexpr auto Pause_Until_Vblank_Then_Freerun = CounterMode::SyncMode.with(3); + static constexpr auto Pause_During_Vblank = CounterMode_v::SyncMode.with(0u); + static constexpr auto Zero_At_Vblank = CounterMode_v::SyncMode.with(1u); + static constexpr auto Zero_At_Vblank_Pause_Outside_Vblank = CounterMode_v::SyncMode.with(2u); + static constexpr auto Pause_Until_Vblank_Then_FreeRun = CounterMode_v::SyncMode.with(3u); }; struct Source { - static constexpr auto System_Clock = CounterMode::ClockSource.with(0); - static constexpr auto Hblank = CounterMode::ClockSource.with(1); - static constexpr auto System_Clock_Too = CounterMode::ClockSource.with(2); - static constexpr auto Hblank_Too = CounterMode::ClockSource.with(3); + static constexpr auto System_Clock = CounterMode_v::ClockSource.with(0u); + static constexpr auto Hblank = CounterMode_v::ClockSource.with(1u); + static constexpr auto System_Clock_Too = CounterMode_v::ClockSource.with(2u); + static constexpr auto Hblank_Too = CounterMode_v::ClockSource.with(3u); }; }; - struct __no_align Counter2 : public Counter { + struct __no_align Counter2_v : public Counter { struct SyncMode { - static constexpr auto Stop_Counter = CounterMode::SyncMode.with(0); - static constexpr auto Freerun = CounterMode::SyncMode.with(1); - static constexpr auto Freerun_Too = CounterMode::SyncMode.with(2); - static constexpr auto Stop_Counter_Too = CounterMode::SyncMode.with(3); + static constexpr auto Stop_Counter = CounterMode_v::SyncMode.with(0u); + static constexpr auto FreeRun = CounterMode_v::SyncMode.with(1u); + static constexpr auto FreeRun_Too = CounterMode_v::SyncMode.with(2u); + static constexpr auto Stop_Counter_Too = CounterMode_v::SyncMode.with(3u); }; struct Source { - static constexpr auto System_Clock = CounterMode::ClockSource.with(0); - static constexpr auto System_Clock_Too = CounterMode::ClockSource.with(1); - static constexpr auto System_Clock_Div_8 = CounterMode::ClockSource.with(2); - static constexpr auto System_Clock_Div_8_Too = CounterMode::ClockSource.with(3); + static constexpr auto System_Clock = CounterMode_v::ClockSource.with(0u); + static constexpr auto System_Clock_Too = CounterMode_v::ClockSource.with(1u); + static constexpr auto System_Clock_Div_8 = CounterMode_v::ClockSource.with(2u); + static constexpr auto System_Clock_Div_8_Too = CounterMode_v::ClockSource.with(3u); }; }; - __declare_io_port_global_struct(struct Counter0, Counter0, counter_base_adr(0)); - __declare_io_port_global_struct(struct Counter1, Counter1, counter_base_adr(1)); - __declare_io_port_global_struct(struct Counter2, Counter2, counter_base_adr(2)); + __declare_new_io_port(Counter0, counter_base_adr(0)); + __declare_new_io_port(Counter1, counter_base_adr(1)); + __declare_new_io_port(Counter2, counter_base_adr(2)); } } diff --git a/include/PSX/Timer/high_res_timer.hpp b/include/PSX/Timer/high_res_timer.hpp index 7cb78e5c..9ae8141d 100644 --- a/include/PSX/Timer/high_res_timer.hpp +++ b/include/PSX/Timer/high_res_timer.hpp @@ -66,7 +66,7 @@ namespace JabyEngine { ~HighResTime() = delete; static TimeStamp get_time_stamp() { - return TimeStamp(HighResTime::global_counter_10ms, Timer_IO::Counter2.value.read(Timer_IO::CounterValue::Value)); + return TimeStamp(HighResTime::global_counter_10ms, Timer_IO::Counter2.get_current_value()); } }; #endif //JABYENGINE_USE_HIGH_PERCISION_TIMER diff --git a/include/PSX/jabyengine.hpp b/include/PSX/jabyengine.hpp index 867d8f16..65a33360 100644 --- a/include/PSX/jabyengine.hpp +++ b/include/PSX/jabyengine.hpp @@ -1,36 +1,9 @@ #ifndef __JABYENGINE__HPP__ #define __JABYENGINE__HPP__ -#include "../stdint.h" +#include "jabyengine_defines.h" namespace JabyEngine { - struct NextRoutine { - static constexpr uintptr_t OverlayBit = (1 << ((sizeof(uintptr_t)*8) - 2)); - typedef NextRoutine (*MainRoutine)(); - - uintptr_t value; - - constexpr static NextRoutine null() { - return {.value = 0}; - } - - static NextRoutine from(MainRoutine function) { - return {.value = reinterpret_cast(function)}; - } - - constexpr bool is_overlay() const { - return (this->value & OverlayBit); - } - - constexpr bool is_absolute() const { - return !NextRoutine::is_overlay(); - } - - constexpr bool is_null() const { - return this->value == 0; - } - }; - - typedef NextRoutine::MainRoutine MainRoutine; + typedef void (*MainRoutine)(); } #endif //!__JABYENGINE__HPP__ \ No newline at end of file diff --git a/include/PSX/jabyengine_defines.h b/include/PSX/jabyengine_defines.h index efdd97b3..8c838cb7 100644 --- a/include/PSX/jabyengine_defines.h +++ b/include/PSX/jabyengine_defines.h @@ -3,9 +3,10 @@ #include "jabyengine_config.hpp" #include "../stddef.h" -#define __keep __attribute__((used)) +#define __used __attribute__((used)) #define __no_align __attribute__((packed)) #define __no_inline __attribute__((noinline)) +#define __no_return __attribute__((noreturn)) #define __always_inline __attribute__((always_inline)) #define __section(name) __attribute__((section(name))) #define __collect(...) __VA_ARGS__ diff --git a/lib/ExportPath.mk b/lib/ExportPath.mk new file mode 100644 index 00000000..fcc3b8d3 --- /dev/null +++ b/lib/ExportPath.mk @@ -0,0 +1,2 @@ +#Add the JabyEngine tools to path +export PATH := $(JABY_ENGINE_DIR)/bin/:$(PATH) \ No newline at end of file diff --git a/lib/Makefile b/lib/Makefile index 188bde77..5b262c51 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,5 +1,5 @@ -#Add the JabyEngine tools to path -export PATH := $(JABY_ENGINE_DIR)/bin/:$(PATH) +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(SELF_DIR)ExportPath.mk #Build architecture/variant string, possible values: x86, armv7le, etc... PLATFORM ?= PSX diff --git a/lib/PSEXETarget.mk b/lib/PSEXETarget.mk index 295089a9..7445dd7d 100644 --- a/lib/PSEXETarget.mk +++ b/lib/PSEXETarget.mk @@ -7,10 +7,6 @@ include $(AUTO_OVERLAY_DIR)/Overlays.mk JABY_ENGINE_LIB_DIR = $(JABY_ENGINE_DIR)/lib/PSX-$(BUILD_PROFILE) JABY_ENGINE_LIB_NAME = JabyEngine_$(TV_FORMAT) -#Bind this to the overlay.json file maybe? -BOOT_TYPE = main -OBJS += $(JABY_ENGINE_LIB_DIR)/$(BOOT_TYPE)_boot.o - #Linking rule $(TARGET).elf: $(OBJS) $(JABY_ENGINE_LIB_DIR)/lib$(JABY_ENGINE_LIB_NAME).a $(AUTO_OVERLAY_DIR)/Overlays.ld $(LD) -o $(TARGET).elf $(LDFLAGS_all) $(LDFLAGS) $(OBJS) -L$(JABY_ENGINE_LIB_DIR) -l$(JABY_ENGINE_LIB_NAME) $(LIBS) diff --git a/src/Library/Makefile b/src/Library/Makefile index ba511a31..4183fabe 100644 --- a/src/Library/Makefile +++ b/src/Library/Makefile @@ -16,9 +16,7 @@ SRCS += src/syscall_printf.asm include ../../lib/Makefile LIB_DIR = ../../lib/$(CONFIG_NAME) -MAIN_BOOT_OBJ = $(filter %/main_boot.o,$(OBJS)) -OVERLAY_BOOT_OBJ = $(filter %/overlay_boot.o,$(OBJS)) -MAIN_LIB_OBJS = $(filter-out $(MAIN_BOOT_OBJ) $(OVERLAY_BOOT_OBJ),$(OBJS)) +MAIN_LIB_OBJS = $(filter-out $(MAIN_BOOT_OBJ) $(OVERLAY_BOOT_OBJ),$(OBJS)) #$(info $$var is [${MAIN_BOOT_OBJ}]) #$(info $$var2 is [${MAIN_LIB_OBJS}]) @@ -33,15 +31,8 @@ $(LIB_DIR)/$(ARTIFACT).a: $(TARGET).a @mkdir -p $(LIB_DIR) cp $(TARGET).a $(LIB_DIR)/$(ARTIFACT).a -$(LIB_DIR)/$(notdir $(MAIN_BOOT_OBJ)): $(MAIN_BOOT_OBJ) - @mkdir -p $(LIB_DIR) - cp $(MAIN_BOOT_OBJ) $(LIB_DIR)/$(notdir $(MAIN_BOOT_OBJ)) - -$(LIB_DIR)/$(notdir $(OVERLAY_BOOT_OBJ)): $(OVERLAY_BOOT_OBJ) - @mkdir -p $(LIB_DIR) - cp $(OVERLAY_BOOT_OBJ) $(LIB_DIR)/$(notdir $(OVERLAY_BOOT_OBJ)) - # Improve later +# rule to make the boot image $(SPLASH_IMAGE): ressources/Splash.png jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@ @@ -49,7 +40,7 @@ $(SPLASH_IMAGE_NTSC): ressources/Splash_ntsc.png jaby_engine_fconv --lz4 $< simple-tim full16 | cpp_out --name SplashScreen -o $@ #Rules section for default compilation and linking -all: $(SPLASH_IMAGE) $(SPLASH_IMAGE_NTSC) $(LIB_DIR)/$(ARTIFACT).a $(LIB_DIR)/$(notdir $(MAIN_BOOT_OBJ)) $(LIB_DIR)/$(notdir $(OVERLAY_BOOT_OBJ)) +all: $(SPLASH_IMAGE) $(SPLASH_IMAGE_NTSC) $(LIB_DIR)/$(ARTIFACT).a clean: rm -fr $(SPLASH_IMAGE) diff --git a/src/Library/include/CD/cd_internal.hpp b/src/Library/include/CD/cd_internal.hpp deleted file mode 100644 index 73469ce7..00000000 --- a/src/Library/include/CD/cd_internal.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __JABYENGINE_CD_INTERNAL_HPP__ -#define __JABYENGINE_CD_INTERNAL_HPP__ -#include "cd_types.hpp" -#include - -namespace JabyEngine { - namespace CD { - namespace internal { - extern VolatilePOD last_interrupt; - - struct Command { - static void wait_until(CD_IO::Interrupt::Type irq) { - while(last_interrupt.read() != irq); - } - - template - static void send(CD_IO::CommandFifo_t& cmd_fifo, CD_IO::ParameterFifo_t& parameter_fifo, CD_IO::Command::Info cmd, ARGS...args) { - while(CD_IO::IndexStatus.read().is_bit_set(CD_IO::IndexStatus::IsTransmissionBusy)); - - (parameter_fifo.write(static_cast(args)), ...); - cmd_fifo.write(cmd.id); - } - - template - static void send(CD_IO::Command::Info cmd, ARGS...args) { - send(T::CommandFifo, T::ParameterFifo, cmd, args...); - } - - template - static void send_wait(CD_IO::CommandFifo_t& cmd_fifo, CD_IO::ParameterFifo_t& parameter_fifo, CD_IO::Command::Info cmd, ARGS...args) { - send(cmd_fifo, parameter_fifo, cmd, args...); - wait_until(cmd.complete_irq); - } - - template - static void send_wait(CD_IO::Command::Info cmd, ARGS...args) { - send_wait(T::CommandFifo, T::ParameterFifo, cmd, args...); - } - }; - - State read_file(FileInfo file_info, const SectorBufferAllocator& buffer_allocator); - } - } -} -#endif //!__JABYENGINE_CD_INTERNAL_HPP__ \ No newline at end of file diff --git a/src/Library/include/GPU/gpu_internal.hpp b/src/Library/include/GPU/gpu_internal.hpp deleted file mode 100644 index 7d2b89e2..00000000 --- a/src/Library/include/GPU/gpu_internal.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef __JABYENGINE_GPU_INTERNAL_HPP__ -#define __JABYENGINE_GPU_INTERNAL_HPP__ -#include -#include -#include - -namespace JabyEngine { - namespace GPU { - namespace internal { - struct Screen { - struct Mode { - enum struct TVEncoding { - NTSC = 0, - PAL = 1, - }; - - static constexpr auto HorizontalResolution368 = Bit(6); - static constexpr auto VerticalInterlace = Bit(5); - static constexpr auto DisplayAreaColorDepth = BitRange::from_to(4, 4); - static constexpr auto VideoMode = BitRange::from_to(3, 3); - static constexpr auto VerticalResolution = BitRange::from_to(2, 2); - static constexpr auto HorizontalResolution = BitRange::from_to(0, 1); - - static constexpr uint32_t PAL() { - return ComplexBitMap::with( - Mode::HorizontalResolution.with(GPU_IO::HorizontalResolution::$320), - Mode::VerticalResolution.with(GPU_IO::VerticalResolution::$240), - Mode::VideoMode.with(TVEncoding::PAL), - Mode::DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit) - ).raw; - } - - static constexpr uint32_t NTSC() { - return ComplexBitMap::with( - Mode::HorizontalResolution.with(GPU_IO::HorizontalResolution::$320), - Mode::VerticalResolution.with(GPU_IO::VerticalResolution::$240), - Mode::VideoMode.with(TVEncoding::NTSC), - Mode::DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit) - ).raw; - } - }; - - static void configurate() { - static constexpr uint16_t FirstVisiblePixelH = 0x260; - - #ifdef JABYENGINE_PAL - static constexpr uint16_t FirstVisiblePixelV = 0xA3; - - GPU_IO::GP1.write(GPU_IO::Command::GP1::DisplayMode(Mode::PAL())); - GPU::Screen::set_offset(0, 0); - #else - static constexpr uint16_t FirstVisiblePixelV = 0x88; - - GPU_IO::GP1.write(GPU_IO::Command::GP1::DisplayMode(Mode::NTSC())); - GPU::Screen::set_offset(0, 5); //< Random values - #endif - } - - static void exchange_buffer_and_display(); - }; - - static void set_draw_area(uint16_t x, uint16_t y) { - GPU_IO::GP0.write(GPU_IO::Command::GP0::DrawAreaTopLeft(x, y)); - GPU_IO::GP0.write(GPU_IO::Command::GP0::DrawAreaBottomRight((x + Display::Width), (y + Display::Height))); - } - - static void quick_fill_fast(const Color24& color, const PositionU16& pos, const SizeU16& size) { - GPU_IO::GP0.write(GPU_IO::Command::GP0::QuickFill(color)); - GPU_IO::GP0.write(GPU_IO::Command::GP0::TopLeftPosition(pos.x, pos.y)); - GPU_IO::GP0.write(GPU_IO::Command::GP0::WidthHeight(size.width, size.height)); - } - - static void reset_cmd_buffer() { - GPU_IO::GP1.write(GPU_IO::Command::GP1::ResetCMDBufer()); - } - - static void wait_ready_for_CMD() { - while(!GPU_IO::GPUSTAT.read().is(GPU_IO::GPUStatusRegister::GP0ReadyForCMD)); - } - - namespace DMA { - static void wait() { - while(::JabyEngine::DMA_IO::GPU.channel_ctrl.read().is(::JabyEngine::DMA_IO::CHCHR::Busy)); - } - - static void end() { - reset_cmd_buffer(); - } - - namespace Receive { - static void prepare() - { - GPU_IO::GP1.write(GPU_IO::Command::GP1::DMADirection(GPU_IO::DMADirection::CPU2GPU)); - reset_cmd_buffer(); - } - - static void set_src(uintptr_t adr) { - DMA_IO::GPU.adr.write(DMA_IO::MADR::MemoryAdr.with(static_cast(adr))); - } - - static void set_dst(const PositionU16& position, const SizeU16& size) { - wait_ready_for_CMD(); - GPU_IO::GP0.write(GPU_IO::Command::GP0::CPU2VRAM_Blitting()); - GPU_IO::GP0.write(GPU_IO::Command::GP0::TopLeftPosition(position.x, position.y)); - GPU_IO::GP0.write(GPU_IO::Command::GP0::WidthHeight(size.width, size.height)); - } - - static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { - typedef DMA_IO::BCR::SyncMode1 SyncMode1; - - DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR{SyncMode1::with(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))}); - DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPUReceive()); - } - } - } - } - } -} - -#endif //!__JABYENGINE_GPU_INTERNAL_HPP__ \ No newline at end of file diff --git a/src/Library/include/BootLoader/boot_loader.hpp b/src/Library/internal-include/BootLoader/boot_loader.hpp similarity index 67% rename from src/Library/include/BootLoader/boot_loader.hpp rename to src/Library/internal-include/BootLoader/boot_loader.hpp index 8153adc8..888c1b54 100644 --- a/src/Library/include/BootLoader/boot_loader.hpp +++ b/src/Library/internal-include/BootLoader/boot_loader.hpp @@ -3,12 +3,7 @@ #include namespace JabyEngine { - //boot namespace? namespace boot { - namespace BootFile { - JabyEngine::NextRoutine setup(); - } - namespace CD { void setup(); } @@ -23,13 +18,11 @@ namespace JabyEngine { void setup(); } - namespace Start { - JabyEngine::NextRoutine setup(); - } - namespace Timer { void setup(); } } + + void __no_return run(); } #endif //!BOOT_LOADER_HPP \ No newline at end of file diff --git a/src/Library/internal-include/CD/cd_internal.hpp b/src/Library/internal-include/CD/cd_internal.hpp new file mode 100644 index 00000000..aad04e32 --- /dev/null +++ b/src/Library/internal-include/CD/cd_internal.hpp @@ -0,0 +1,52 @@ +#ifndef __JABYENGINE_CD_INTERNAL_HPP__ +#define __JABYENGINE_CD_INTERNAL_HPP__ +#include "cd_types.hpp" + +namespace JabyEngine { + namespace CD { + namespace internal { + extern State current_state; + extern CD_IO::Interrupt::Type last_interrupt; + extern uint8_t cmd_interrupt_bit; + + struct Command { + static void wait_completed() { + while(const_cast(cmd_interrupt_bit) > 0); + } + + template + static void send(CD_IO::CommandFifo_v& cmd_fifo, CD_IO::ParameterFifo_v& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) { + while(CD_IO::IndexStatus.is_set(CD_IO::IndexStatus_t::IsTransmissionBusy)); + + ((parameter_fifo = args),...); + cmd_fifo = cmd.id; + cmd_interrupt_bit = bit::set(0, cmd.complete_irq); + } + + template + static void send(CD_IO::Command::Desc cmd, ARGS...args) { + send(T::CommandFifo, T::ParameterFifo, cmd, args...); + } + + template + static void send_wait(CD_IO::CommandFifo_v& cmd_fifo, CD_IO::ParameterFifo_v& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) { + send(cmd_fifo, parameter_fifo, cmd, args...); + wait_completed(); + } + + template + static void send_wait(CD_IO::Command::Desc cmd, ARGS...args) { + send_wait(T::CommandFifo, T::ParameterFifo, cmd, args...); + } + }; + + static State read_current_state() { + return const_cast(current_state); + } + + void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator); + void continue_reading(); + } + } +} +#endif //!__JABYENGINE_CD_INTERNAL_HPP__ \ No newline at end of file diff --git a/src/Library/include/CD/cd_types.hpp b/src/Library/internal-include/CD/cd_types.hpp similarity index 63% rename from src/Library/include/CD/cd_types.hpp rename to src/Library/internal-include/CD/cd_types.hpp index 9beb22bf..5e1f07d6 100644 --- a/src/Library/include/CD/cd_types.hpp +++ b/src/Library/internal-include/CD/cd_types.hpp @@ -2,6 +2,7 @@ #define __JABYENGINE_INTERNAL_CD_TYPES_HPP__ #include #include +#include #include namespace JabyEngine { @@ -16,30 +17,9 @@ namespace JabyEngine { Error, }; - struct DataSector { - static constexpr size_t SizeBytes = 2048; - static constexpr size_t SizeWords = (SizeBytes/sizeof(uint32_t)); - - uint32_t data[SizeWords]; - - template - static constexpr T words_to_sectors(T size) { - return (size + static_cast(DataSector::SizeWords - 1))/static_cast(DataSector::SizeWords); - } - }; - - struct FileInfo { - uint16_t lba; - uint16_t sectors; - - static constexpr FileInfo from(const AutoLBAEntry& entry) { - return FileInfo{entry.lba, DataSector::words_to_sectors(entry.size_words)}; - } - }; - class SectorBufferAllocator { private: - typedef DataSector* (*AllocatorFunction)(void* ctx); + typedef CD_IO::DataSector* (*AllocatorFunction)(void* ctx); private: void* ctx = nullptr; @@ -54,6 +34,14 @@ namespace JabyEngine { static constexpr SectorBufferAllocator create(void* obj, AllocatorFunction function) { return SectorBufferAllocator(obj, function); } + + static constexpr SectorBufferAllocator invalid() { + return SectorBufferAllocator(nullptr, nullptr); + } + + inline CD_IO::DataSector* allocate_sector() const { + return this->allocate(this->ctx); + } }; struct CDTimeStamp { @@ -64,17 +52,13 @@ namespace JabyEngine { uint8_t sec; uint8_t sector; - static constexpr CDTimeStamp from(uint16_t lba) { - const auto [min, new_lba] = div_and_mod(lba, static_cast(MaxSector*MaxSeconds)); - const auto [sec, sectors] = div_and_mod(new_lba, static_cast(MaxSector)); + static constexpr CDTimeStamp from(uint32_t lba) { + const auto [min, new_lba] = div_and_mod(lba, MaxSector*MaxSeconds); + const auto [sec, sectors] = div_and_mod(new_lba, MaxSector); return CDTimeStamp{static_cast(min), static_cast(sec), static_cast(sectors)}; } - static constexpr CDTimeStamp from(const FileInfo& file_info) { - return CDTimeStamp::from(file_info.lba); - } - constexpr uint8_t get_min_cd() const { return to_bcd(this->min); } diff --git a/src/Library/internal-include/GPU/gpu_internal.hpp b/src/Library/internal-include/GPU/gpu_internal.hpp new file mode 100644 index 00000000..9903400b --- /dev/null +++ b/src/Library/internal-include/GPU/gpu_internal.hpp @@ -0,0 +1,87 @@ +#ifndef __JABYENGINE_GPU_INTERNAL_HPP__ +#define __JABYENGINE_GPU_INTERNAL_HPP__ +#include +#include +#include + +namespace JabyEngine { + namespace GPU { + namespace internal { + struct Screen { + static void configurate() { + static constexpr uint16_t FirstVisiblePixelH = 0x260; + + #ifdef JABYENGINE_PAL + static constexpr uint16_t FirstVisiblePixelV = 0xA3; + + GPU_IO::GP1 = GPU_IO::Command::DisplayMode(GPU_IO::DisplayMode_t::PAL()); + GPU::Screen::set_offset(0, 0); + #else + static constexpr uint16_t FirstVisiblePixelV = 0x88; + + GPU_IO::GP1 = GPU_IO::Command::DisplayMode(GPU_IO::DisplayMode_t::NTSC()); + GPU::Screen::set_offset(0, 5); //< Random values + #endif + } + + static void exchange_buffer_and_display(); + }; + + static void set_draw_area(uint16_t x, uint16_t y) { + GPU_IO::GP0 = GPU_IO::Command::DrawAreaTopLeft(x, y); + GPU_IO::GP0 = GPU_IO::Command::DrawAreaBottomRight((x + Display::Width), (y + Display::Height)); + } + + static void quick_fill_fast(const Color24& color, const PositionU16& pos, const SizeU16& size) { + GPU_IO::GP0 = GPU_IO::Command::QuickFill(color); + GPU_IO::GP0 = GPU_IO::Command::TopLeftPosition(pos.x, pos.y); + GPU_IO::GP0 = GPU_IO::Command::WidthHeight(size.width, size.height); + } + + static void reset_cmd_buffer() { + GPU_IO::GP1 = GPU_IO::Command::ResetCMDBufer(); + } + + static void wait_ready_for_CMD() { + while(!GPU_IO::GPUSTAT.is_set(GPU_IO::GPUSTAT_t::GP0ReadyForCMD)); + } + + namespace DMA { + static void wait() { + ::JabyEngine::DMA_IO::GPU.wait(); + } + + static void end() { + reset_cmd_buffer(); + } + + namespace Receive { + static void prepare() { + GPU_IO::GP1 = GPU_IO::Command::DMADirection(GPU_IO::DMADirection::CPU2GPU); + reset_cmd_buffer(); + } + + static void set_src(uintptr_t adr) { + DMA_IO::GPU.set_adr(adr); + } + + static void set_dst(const PositionU16& position, const SizeU16& size) { + wait_ready_for_CMD(); + GPU_IO::GP0 = GPU_IO::Command::CPU2VRAM_Blitting(); + GPU_IO::GP0 = GPU_IO::Command::TopLeftPosition(position.x, position.y); + GPU_IO::GP0 = GPU_IO::Command::WidthHeight(size.width, size.height); + } + + static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { + typedef DMA_IO::BCR_t::SyncMode1 SyncMode1; + + DMA_IO::GPU.block_ctrl = DMA_IO::BCR_t::from(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount)); + DMA_IO::GPU.channel_ctrl = DMA_IO::CHCHR_t::StartGPUReceive(); + } + } + } + } + } +} + +#endif //!__JABYENGINE_GPU_INTERNAL_HPP__ \ No newline at end of file diff --git a/src/Library/src/Auxiliary/lz4_decompressor.cpp b/src/Library/src/Auxiliary/lz4_decompressor.cpp index 3422a6ab..1c1ff4bf 100644 --- a/src/Library/src/Auxiliary/lz4_decompressor.cpp +++ b/src/Library/src/Auxiliary/lz4_decompressor.cpp @@ -24,11 +24,11 @@ namespace JabyEngine { void LZ4Decompressor :: setup(uint8_t* dst_adr) { this->dst_adr = dst_adr; - LZ4Decompressor::reset(); + this->state.enable(); } - void LZ4Decompressor :: reset() { - this->state = State(); + void LZ4Decompressor :: disable() { + this->state.disable(); } LZ4Decompressor::Result LZ4Decompressor :: process(ArrayRange data, bool is_last) { @@ -36,6 +36,9 @@ namespace JabyEngine { while(data) { switch(this->state.step) { + case State::Step::Disabled: + return Result::new_done(data.size); + case State::Step::ReadToken: { const auto token = data.pop(); @@ -67,9 +70,10 @@ namespace JabyEngine { memcpy(this->dst_adr, data, bytes_copy); this->state.literal_length -= bytes_copy; + bytes_ready += bytes_copy; + if(this->state.literal_length == 0) { - this->state.step = State::Step::ObtainMatchOffset; - bytes_ready += bytes_copy; + this->state.step = State::Step::ObtainMatchOffset; } } break; diff --git a/src/Library/src/BootLoader/boot_file/main_boot.cpp b/src/Library/src/BootLoader/boot_file/main_boot.cpp deleted file mode 100644 index afd053a1..00000000 --- a/src/Library/src/BootLoader/boot_file/main_boot.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "../../../include/BootLoader/boot_loader.hpp" -#include - -#include - -extern JabyEngine::NextRoutine main(); - -namespace JabyEngine { - namespace boot { - namespace BootFile { - JabyEngine::NextRoutine setup() { - printf("Running main!\n"); - return JabyEngine::NextRoutine::from(main); - } - } - } -} \ No newline at end of file diff --git a/src/Library/src/BootLoader/boot_file/overlay_boot.cpp b/src/Library/src/BootLoader/boot_file/overlay_boot.cpp deleted file mode 100644 index 0bd5e969..00000000 --- a/src/Library/src/BootLoader/boot_file/overlay_boot.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "../../../include/BootLoader/boot_loader.hpp" -#include - -namespace JabyEngine { - namespace boot { - namespace BootFile { - JabyEngine::NextRoutine setup() { - printf("Overlay boot not implemented!\n"); - return JabyEngine::NextRoutine::null(); - } - } - } -} \ No newline at end of file diff --git a/src/Library/src/BootLoader/cd_boot.cpp b/src/Library/src/BootLoader/cd_boot.cpp index 66a79fe2..24da5b48 100644 --- a/src/Library/src/BootLoader/cd_boot.cpp +++ b/src/Library/src/BootLoader/cd_boot.cpp @@ -1,5 +1,5 @@ -#include "../../include/BootLoader/boot_loader.hpp" -#include "../../include/CD/cd_internal.hpp" +#include "../../internal-include/BootLoader/boot_loader.hpp" +#include "../../internal-include/CD/cd_internal.hpp" #include #include #include @@ -16,20 +16,19 @@ namespace JabyEngine { void setup() { __syscall_EnterCriticalSection(); - Memory_IO::COM_DELAY.write(Memory_IO::COM_DELAY::SetupValue); - Memory_IO::CD_DELAY.write(Memory_IO::CD_DELAY::SetupValue); + Memory_IO::COM_DELAY.setup(); + Memory_IO::CD_DELAY.setup(); __syscall_SysEnqIntRP(CdromIoIrq, &::JabyEngine::CD::internal::callback); CD_IO::PortIndex1::change_to(); - CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlagRegister); - CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnableRegister); + CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag); + CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnable); - Interrupt::ack_irq(Interrupt::CDROM); Interrupt::enable_irq(Interrupt::CDROM); + Interrupt::ack_irq(Interrupt::CDROM); __syscall_ExitCriticalSection(); - CD_IO::PortIndex0::change_to(); Command::send_wait(CD_IO::PortIndex0::CommandFifo, CD_IO::PortIndex0::ParameterFifo, CD_IO::Command::GetStat); diff --git a/src/Library/src/BootLoader/gpu_boot.cpp b/src/Library/src/BootLoader/gpu_boot.cpp index 9f4eca69..5f38475e 100644 --- a/src/Library/src/BootLoader/gpu_boot.cpp +++ b/src/Library/src/BootLoader/gpu_boot.cpp @@ -1,4 +1,4 @@ -#include "../../include/GPU/gpu_internal.hpp" +#include "../../internal-include/GPU/gpu_internal.hpp" #include #include #include @@ -43,13 +43,13 @@ namespace JabyEngine { // Upload SplashScreen picture auto state = FileProcessor::create(&__boot_loader_end, SimpleTIM(32, 0, 0, 0)); - while(state.process((bytes_ready/sizeof(uint32_t))) == Progress::InProgress); + state.process(bytes_ready); Display::enable(); } void setup() { - GPU_IO::GP1.write(GPU_IO::Command::GP1::Reset()); + GPU_IO::GP1 = GPU_IO::Command::Reset(); internal::Screen::configurate(); internal::Screen::exchange_buffer_and_display(); diff --git a/src/Library/src/BootLoader/spu_boot.cpp b/src/Library/src/BootLoader/spu_boot.cpp index 9521352b..bff3a1d8 100644 --- a/src/Library/src/BootLoader/spu_boot.cpp +++ b/src/Library/src/BootLoader/spu_boot.cpp @@ -6,65 +6,66 @@ namespace JabyEngine { namespace boot { namespace SPU { using namespace JabyEngine; + using namespace SPU_IO; static void clear_main_volume() { - static constexpr auto StartVol = SPU_IO::SweepVolume::with(SPU_IO::SweepVolume::VolumeEnable, SPU_IO::SweepVolume::Volume.with(I16_MAX >> 2)); + static constexpr auto StartVol = SweepVolume_t::from(SweepVolume_t::VolumeEnable, SweepVolume_t::Volume.with(static_cast(I16_MAX >> 2))); - SPU_IO::MainVolume::Left.write({StartVol}); - SPU_IO::MainVolume::Right.write({StartVol}); + MainVolume::Left = StartVol; + MainVolume::Right = StartVol; } static void clear_cd_and_ext_audio_volume() { - SPU_IO::CDVolume::Left.write(0); - SPU_IO::CDVolume::Right.write(0); + CDVolume::Left = 0; + CDVolume::Right = 0; - SPU_IO::ExternalAudioInputVolume::Left.write(0); - SPU_IO::ExternalAudioInputVolume::Right.write(0); + ExternalAudioInputVolume::Left = 0; + ExternalAudioInputVolume::Right = 0; } static void clear_control_register() { - SPU_IO::Control.write(SPU_IO::ControlRegister()); + ControlRegister = 0; } static void clear_voice() { for(auto& voice : SPU_IO::Voice) { - voice.volumeLeft.write(SPU_IO::SweepVolume()); - voice.volumeRight.write(SPU_IO::SweepVolume()); - voice.sampleRate.write(SPU_IO::SampleRate()); - voice.ad.write(SPU_IO::AD()); - voice.sr.write(SPU_IO::SR()); - voice.currentVolume.write(SPU_IO::SimpleVolume(0)); + voice.volumeLeft = SweepVolume_t(); + voice.volumeRight = SweepVolume_t(); + voice.sampleRate = SampleRate_t(); + voice.ad = AD_t(); + voice.sr = SR_t(); + voice.currentVolume = 0; - voice.adr.write(0x200); - voice.repeatAdr.write(0x200); + voice.adr = 0x200; + voice.repeatAdr = 0x200; } } static void clear_pmon() { - SPU_IO::PMON.write(SPU_IO::PitchModFlags()); + SPU_IO::PMON = PMON_t(); } static void clear_noise_and_echo() { - SPU_IO::NON.write(SPU_IO::NoiseGenerator()); - SPU_IO::EON.write(SPU_IO::EchoOn()); + SPU_IO::NON = NON_t(); + SPU_IO::EON = EON_t(); } static void clear_reverb() { - SPU_IO::Reverb::Volume::Left.write(0); - SPU_IO::Reverb::Volume::Right.write(0); - SPU_IO::Reverb::WorkAreaAdr.write(0); + Reverb::Volume::Left = 0; + Reverb::Volume::Right = 0; + Reverb::WorkAreaAdr = 0; } static void setup_control_register() { - static constexpr auto SetupValue = SPU_IO::ControlRegister::with(SPU_IO::ControlRegister::Enable, SPU_IO::ControlRegister::Unmute, SPU_IO::ControlRegister::CDAudioEnable); + static constexpr auto SetupValue = ControlRegister_t::from(ControlRegister_t::Enable, ControlRegister_t::Unmute, ControlRegister_t::CDAudioEnable); - SPU_IO::Control.write({SetupValue}); + SPU_IO::ControlRegister = SetupValue; } static void setup_data_transfer_control() { static constexpr uint16_t RequiredValue = (2 << 1); - SPU_IO::DataTransferControl.write(RequiredValue); + DataTransferControl = RequiredValue; } static void wait_voices() { @@ -72,7 +73,7 @@ namespace JabyEngine { try_again: for(const auto& voice : SPU_IO::Voice) { - if(voice.currentVolume.read() > Treshhold) { + if(voice.currentVolume > Treshhold) { goto try_again; } } diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index 6d6e183e..111c5fbf 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -1,17 +1,19 @@ -#include "BootLoader/boot_loader.hpp" +#include "../../internal-include/BootLoader/boot_loader.hpp" #include +// 2x For setup timing #include #include namespace JabyEngine { namespace boot { - namespace Start { + namespace Start { + //This should become part of the bootloader later static void enable_DMA() { - DMA_IO::DPCR.write(DMA_IO::DMAControlRegister{DMA_IO::DPCR.read() | DMA_IO::DMAControlRegister::SPUEnable | DMA_IO::DMAControlRegister::GPUEnable}); + DMA_IO::DPCR = DMA_IO::DPCR_t(DMA_IO::DPCR).set(DMA_IO::DPCR_t::SPUEnable).set(DMA_IO::DPCR_t::GPUEnable).set(DMA_IO::DPCR_t::CDROMEnable); } - JabyEngine::NextRoutine setup() { + static void setup() { enable_DMA(); SPU::stop_voices(); @@ -29,8 +31,15 @@ namespace JabyEngine { //Pause?? SPU::setup(); - return BootFile::setup(); } } } + + void start() { + printf("Starting Planschbecken\n"); + boot::Start::setup(); + + printf("Running main...\n"); + run(); + } } \ No newline at end of file diff --git a/src/Library/src/BootLoader/timer_boot.cpp b/src/Library/src/BootLoader/timer_boot.cpp index 0d348a79..201e41ba 100644 --- a/src/Library/src/BootLoader/timer_boot.cpp +++ b/src/Library/src/BootLoader/timer_boot.cpp @@ -18,7 +18,7 @@ void setup() { using namespace Timer_IO; - static constexpr auto Mode = CounterMode::with(CounterMode::FreeRun, Counter2::SyncMode::Freerun, CounterMode::ResetAfterTarget, CounterMode::IRQAtTarget, CounterMode::IRQEveryTime, CounterMode::IRQPulse, Counter2::Source::System_Clock_Div_8); + static constexpr auto Mode = CounterMode_t::from(CounterMode_t::FreeRun, Counter2_v::SyncMode::FreeRun, CounterMode_t::ResetAfterTarget, CounterMode_t::IRQAtTarget, CounterMode_t::IRQEveryTime, CounterMode_t::IRQPulse, Counter2_v::Source::System_Clock_Div_8); Interrupt::disable_irq(Interrupt::Timer2); @@ -26,8 +26,8 @@ __syscall_SysEnqIntRP(Timer2Irq, &IRQCallback); __syscall_ExitCriticalSection(); - Counter2.target.write(CounterTarget::CounterTargetValue.with(HighResTime::TicksFor10ms)); - Counter2.mode.write({Mode}); + Counter2.set_target_value(HighResTime::TicksFor10ms); + Counter2.set_mode(Mode); Interrupt::enable_irq(Interrupt::Timer2); } diff --git a/src/Library/src/CD/cd.cpp b/src/Library/src/CD/cd.cpp index 859172e3..9ef12677 100644 --- a/src/Library/src/CD/cd.cpp +++ b/src/Library/src/CD/cd.cpp @@ -1,47 +1,109 @@ -#include "../../include/CD/cd_internal.hpp" +#include "../../internal-include/CD/cd_internal.hpp" +#include #include #include -#include - namespace JabyEngine { namespace CD { namespace internal { - struct Mode : public ComplexBitMap { - static constexpr auto DoubleSpeed = Bit(7); - static constexpr auto SingleSpeed = !DoubleSpeed; - static constexpr auto XADPCM = Bit(6); - static constexpr auto WholeSector = Bit(5); - static constexpr auto DataSector = !WholeSector; - static constexpr auto UseXAFilter = Bit(3); - static constexpr auto AudioPlayIRQ = Bit(2); - static constexpr auto AutoPauseTrack = Bit(1); - static constexpr auto CDDA = Bit(0); + static constexpr auto DataSectorMode = CD_IO::Mode_t::from(CD_IO::Mode_t::DoubleSpeed, CD_IO::Mode_t::DataSector); + + static InterruptVerifierResult interrupt_verifier(); + static void interrupt_handler(uint32_t); + + static SectorBufferAllocator sector_allocator; + static uint32_t cur_lba; + static uint32_t dst_lba; + + CD_IO::Interrupt::Type last_interrupt = CD_IO::Interrupt::Type::None; + uint8_t cmd_interrupt_bit = 0; + State current_state = State::Free; + InterrupCallback callback = { + .next = nullptr, + .handler_function = reinterpret_cast(interrupt_handler), + .verifier_function = interrupt_verifier }; - static constexpr auto DataSectorMode = Mode::with(Mode::DoubleSpeed, Mode::DataSector); - - static SectorBufferAllocator sector_allocator; - static uint16_t sectors_left; + static void pause_cd() { + CD_IO::PortIndex0::change_to(); + Command::send(CD_IO::Command::Pause); + } + + // Requires Index0 + static void read_cd(uint32_t lba) { + const auto loc = CDTimeStamp::from(lba); + + Command::send_wait(CD_IO::Command::SetLoc, loc.get_min_cd(), loc.get_sec_cd(), loc.get_sector_cd()); + Command::send(CD_IO::Command::ReadN); + current_state = State::Reading; + } + + static void read_sector_dma(CD_IO::DataSector& sector) { + static const auto WaitSectorReady = []() { + while(!CD_IO::IndexStatus.is_set(CD_IO::IndexStatus_t::HasDataFifoData)); + }; + + static const auto ReadSector = [](uint32_t* dst) { + DMA_IO::CDROM.set_adr(reinterpret_cast(dst)); + DMA_IO::CDROM.block_ctrl = DMA_IO::BCR_t::SyncMode0::for_cd(); + DMA_IO::CDROM.channel_ctrl = DMA_IO::CHCHR_t::StartCDROM(); + + DMA_IO::CDROM.wait(); + + CD_IO::PortIndex0::Request.reset(); + }; + + WaitSectorReady(); + ReadSector(sector.data); + } + + static void read_sector_to(CD_IO::DataSector& sector) { + CD_IO::PortIndex0::change_to(); + CD_IO::PortIndex0::Request.want_data(); + + // We only support DMA rn + read_sector_dma(sector); + + // Do we ever want to support reading via IO Port? + // Doesn't seem to important when we can use DMA + } static InterruptVerifierResult interrupt_verifier() { if(Interrupt::is_irq(Interrupt::CDROM)) { - const uint8_t old_idx = (CD_IO::IndexStatus.read() & 0x3); + const uint8_t old_status = CD_IO::IndexStatus; CD_IO::PortIndex1::change_to(); - const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlagRegister); - last_interrupt.write(cur_irq); - CD_IO::Interrupt::ack(CD_IO::PortIndex1::InterruptFlagRegister); + const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag); + last_interrupt = cur_irq; + CD_IO::Interrupt::ack(CD_IO::PortIndex1::InterruptFlag); + cmd_interrupt_bit = bit::clear(cmd_interrupt_bit, cur_irq); if(cur_irq == CD_IO::Interrupt::DataReady) { - sectors_left--; - if(sectors_left == 0) { - CD_IO::PortIndex0::change_to(); - Command::send(CD_IO::Command::Pause); + // Obtain sector content here + auto* sector = sector_allocator.allocate_sector(); + if(sector) { + //Now obtain sector + read_sector_to(*sector); + + cur_lba++; + if(cur_lba == dst_lba) { + current_state = State::Done; + pause_cd(); + } + } + + else { + current_state = State::BufferFull; + pause_cd(); } } - CD_IO::IndexStatus.write({old_idx}); + else if(cur_irq == CD_IO::Interrupt::DiskError) { + current_state = State::Error; + } + + // No masking required because we can only write bit 0 - 2 + CD_IO::IndexStatus = old_status; return InterruptVerifierResult::ExecuteHandler; } @@ -55,27 +117,23 @@ namespace JabyEngine { __syscall_ReturnFromException(); } - VolatilePOD last_interrupt{CD_IO::Interrupt::Type::None}; - InterrupCallback callback = { - .next = nullptr, - .handler_function = reinterpret_cast(interrupt_handler), - .verifier_function = interrupt_verifier - }; - - State read_file(FileInfo file_info, const SectorBufferAllocator& buffer_allocator) { + void read_file(AutoLBAEntry file_info, const SectorBufferAllocator& buffer_allocator) { + cur_lba = file_info.get_lba(); + dst_lba = cur_lba + file_info.get_size_in_sectors(); sector_allocator = buffer_allocator; - sectors_left = file_info.sectors; + Command::wait_completed(); CD_IO::PortIndex0::change_to(); Command::send_wait(CD_IO::Command::SetMode, DataSectorMode); - const auto loc = CDTimeStamp::from(file_info); - Command::send_wait(CD_IO::Command::SetLoc, loc.get_min_cd(), loc.get_sec_cd(), loc.get_sector_cd()); - Command::send(CD_IO::Command::ReadN); + read_cd(cur_lba); + } - printf("Now reading: %i\n", file_info.lba); - printf("I'm not fully implemented! %s\n", __FUNCTION__); - return State::Error; + void continue_reading() { + if(current_state == State::BufferFull) { + Command::wait_completed(); + read_cd(cur_lba); + } } } } diff --git a/src/Library/src/File/Processor/cd_file_processor.cpp b/src/Library/src/File/Processor/cd_file_processor.cpp index 62bc2c8f..04bf7f8a 100644 --- a/src/Library/src/File/Processor/cd_file_processor.cpp +++ b/src/Library/src/File/Processor/cd_file_processor.cpp @@ -1,31 +1,116 @@ +#include "../../../internal-include/CD/cd_internal.hpp" #include -#include #include namespace JabyEngine { - void CDFileProcessor :: start_cur_job() { - using CD::internal::FileInfo; + static constexpr auto DisabledCircularBufferSize = 512; + + void CDFileProcessor :: start_cur_job(const AutoLBAEntry* lba, const BufferConfiguration& buf_cfg) { using CD::internal::SectorBufferAllocator; + const auto configurate_for = [this](const CDFile& file, const BufferConfiguration& buf_cfg, bool is_lz4) -> FileProcessor::State { + const uint32_t* data_adr = [this](const CDFile& file, const BufferConfiguration& buf_cfg, bool is_lz4) -> const uint32_t* { + const auto disable_lz4 = [this](uint32_t* work_area, size_t size, uint32_t* overwrite_dst = nullptr) -> uint32_t* { + reinterpret_cast(this->circular_buffer.setup(reinterpret_cast(work_area), size)); - const auto& cur_lba = this->lba[this->jobs.files->rel_lba_idx]; + this->lz4_decomp.disable(); + return overwrite_dst ? overwrite_dst : reinterpret_cast(work_area); + }; - CD::internal::read_file(FileInfo::from(cur_lba), SectorBufferAllocator::create(this, [](void* ctx) -> CD::internal::DataSector* { - printf("Blubb?!\n"); - return nullptr; - })); + const auto enable_lz4 = [this](uint32_t* work_area, size_t size, uint32_t* override_dst = nullptr) -> uint32_t* { + uint8_t* dst_adr = reinterpret_cast(this->circular_buffer.setup(reinterpret_cast(work_area), size)); + + if(override_dst) { + dst_adr = reinterpret_cast(override_dst); + } - printf(">>> CD needs to load LBA: %i -> %i\n", cur_lba.lba, cur_lba.size_words); + this->lz4_decomp.setup(dst_adr); + return reinterpret_cast(dst_adr); + }; + + if(file.type == CDFileType::CopyTo) { + return is_lz4 ? enable_lz4(buf_cfg.adr, buf_cfg.sector_count, file.payload.overlay.dst) : disable_lz4(file.payload.copy_to.dst, DisabledCircularBufferSize); + } + + else { + return is_lz4 ? enable_lz4(buf_cfg.adr, buf_cfg.sector_count) : disable_lz4(buf_cfg.adr, DisabledCircularBufferSize); + } + }(file, buf_cfg, is_lz4); + + switch(file.type) { + case CDFileType::SimpleTIM: + return FileProcessor::create(data_adr, file.payload.simple_tim); + + case CDFileType::CopyTo: + default: + return FileProcessor::create(data_adr, Nothing()); + } + }; + + const auto& cur_job = *this->jobs.files; + const auto& cur_lba = lba[cur_job.rel_lba_idx]; + + this->file_state = configurate_for(cur_job, buf_cfg, cur_lba.is_lz4()); + CD::internal::read_file(cur_lba, SectorBufferAllocator::create(this, + [](void* ctx) -> CD_IO::DataSector* { + CDFileProcessor &self = *reinterpret_cast(ctx); + return self.circular_buffer.allocate(); + })); + + printf(">>> CD needs to load LBA: %i -> %i (is LZ4: [%s])\n", cur_lba.get_lba(), cur_lba.get_size_in_sectors(), cur_lba.is_lz4() ? "Yes" : "No"); } - void CDFileProcessor :: setup(const volatile AutoLBAEntry* lba, JobArray jobs, uint8_t* work_area) { - this->lba = const_cast(lba); - this->work_area = work_area; - this->jobs = jobs; + bool CDFileProcessor :: process_data() { + while(this->circular_buffer.has_data()) { + ArrayRange cur_sector(reinterpret_cast(this->circular_buffer.get_next()->data), CD_IO::DataSector::SizeBytes); + + // v We can not know if there will be more data or not - but it also doesn't matter much for us + const auto result = this->lz4_decomp.process(cur_sector, false); + this->circular_buffer.pop(); - CDFileProcessor::start_cur_job(); + if(result) { + // Process the data in the tmp_area + if(this->file_state.process(result.bytes_ready) == Progress::Error) { + return false; + } + } + + else { + return false; + } + } + return true; + } + + void CDFileProcessor :: setup(const volatile AutoLBAEntry* lba, JobArray jobs, const BufferConfiguration& buf_cfg) { + this->jobs = jobs; + CDFileProcessor::start_cur_job(const_cast(lba), buf_cfg); } Progress CDFileProcessor :: process() { - return Progress::Error; + const auto cur_state = CD::internal::read_current_state(); + + CDFileProcessor::process_data(); + switch(cur_state) { + case CD::internal::State::Done: + /* + We are done now! + The user decides if he wants the next value + */ + //while(this->file_state.process(0) != Progress::Done); + return Progress::Done; + + case CD::internal::State::BufferFull: + /* We processd data and unpause the CD drive */ + CD::internal::continue_reading(); + return Progress::InProgress; + + case CD::internal::State::Reading: + return Progress::InProgress; + + case CD::internal::State::Error: + default: + /* Error for real */ + return Progress::Error; + } } } \ No newline at end of file diff --git a/src/Library/src/File/Processor/nothing_processor.cpp b/src/Library/src/File/Processor/nothing_processor.cpp new file mode 100644 index 00000000..3bedba7b --- /dev/null +++ b/src/Library/src/File/Processor/nothing_processor.cpp @@ -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(), reinterpret_cast(data_adr), parse_nothing); + } + } +} \ No newline at end of file diff --git a/src/Library/src/File/Processor/simplehelper.hpp b/src/Library/src/File/Processor/simplehelper.hpp index 0c179381..bdcfcae5 100644 --- a/src/Library/src/File/Processor/simplehelper.hpp +++ b/src/Library/src/File/Processor/simplehelper.hpp @@ -10,12 +10,10 @@ namespace JabyEngine { namespace Helper { template static void simple_read(T& dst, State::Configuration& config) { - static constexpr size_t UINT32_SIZE = (sizeof(T)/sizeof(uint32_t)); + static constexpr size_t T_SIZE = sizeof(T); dst = *reinterpret_cast(config.data_adr); - config.processed(UINT32_SIZE); - - static_assert((UINT32_SIZE*sizeof(uint32_t)) == sizeof(T)); + config.processed(T_SIZE); } template diff --git a/src/Library/src/File/Processor/tim_processor.cpp b/src/Library/src/File/Processor/tim_processor.cpp index 636a00eb..f0528270 100644 --- a/src/Library/src/File/Processor/tim_processor.cpp +++ b/src/Library/src/File/Processor/tim_processor.cpp @@ -1,4 +1,4 @@ -#include "../../../include/GPU/gpu_internal.hpp" +#include "../../../internal-include/GPU/gpu_internal.hpp" #include "simplehelper.hpp" #include #include @@ -50,9 +50,10 @@ namespace JabyEngine { } static Progress parse_data(State::Configuration& config, SimpleTIMState& state) { - const auto words_to_use = (config.data_word_size > state.words_left) ? state.words_left : config.data_word_size; - bool is_last = (words_to_use == state.words_left); - auto block_count = (words_to_use >> 4); + 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; @@ -75,7 +76,7 @@ namespace JabyEngine { GPU::internal::DMA::end(); state.words_left = 0; - config.processed(words_to_use); + config.processed(words_to_use*sizeof(uint32_t)); return Progress::Done; } @@ -84,13 +85,13 @@ namespace JabyEngine { const auto words_used = (words_to_use & ~0b1111); state.words_left -= words_used; - config.processed(words_used); + config.processed(words_used*sizeof(uint32_t)); return Progress::InProgress; } } static Progress switch_state_parse_data(State::Configuration& config, SimpleTIMState& state) { - set_gpu_receive_data(config.data_adr, state, state.size_info.getTextureWidth(), state.size_info.getTextureHeight()); + set_gpu_receive_data(reinterpret_cast(config.data_adr), state, state.size_info.getTextureWidth(), state.size_info.getTextureHeight()); return Helper::exchange_and_execute_process_function(parse_data, config, state); } @@ -105,13 +106,13 @@ namespace JabyEngine { } static Progress parse_header(State::Configuration& config, SimpleTIMState& state) { - if(config.data_word_size >= (sizeof(SimpleTIMSize)/sizeof(uint32_t))) { + 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.getClutWidth() > 0) { //CLUTs are 16bit full color anyway - set_gpu_receive_data(config.data_adr, state, state.size_info.getClutWidth(), state.size_info.getClutHeight()); + set_gpu_receive_data(reinterpret_cast(config.data_adr), state, state.size_info.getClutWidth(), state.size_info.getClutHeight()); return Helper::exchange_and_execute_process_function(parse_clut, config, state); } @@ -125,7 +126,7 @@ namespace JabyEngine { } State create(const uint32_t* data_adr, const SimpleTIM& file) { - return State::from(SimpleTIMState(file), data_adr, parse_header); + return State::from(SimpleTIMState(file), reinterpret_cast(data_adr), parse_header); } } } diff --git a/src/Library/src/GPU/gpu.cpp b/src/Library/src/GPU/gpu.cpp index 31a1cc91..b4004e80 100644 --- a/src/Library/src/GPU/gpu.cpp +++ b/src/Library/src/GPU/gpu.cpp @@ -1,4 +1,4 @@ -#include "../include/GPU/gpu_internal.hpp" +#include "../../internal-include/GPU/gpu_internal.hpp" namespace JabyEngine { namespace GPU { @@ -16,7 +16,7 @@ namespace JabyEngine { void Screen :: exchange_buffer_and_display() { GPU::internal::set_draw_area(0, (Display::Height*PublicScreenClass::CurrentDisplayAreaID)); PublicScreenClass::CurrentDisplayAreaID ^= 1; - GPU_IO::GP1.write(GPU_IO::Command::GP1::DisplayArea(0, (Display::Height*PublicScreenClass::CurrentDisplayAreaID))); + GPU_IO::GP1 = GPU_IO::Command::DisplayArea(0, (Display::Height*PublicScreenClass::CurrentDisplayAreaID)); } } @@ -25,13 +25,13 @@ namespace JabyEngine { x += 78; y += 43; - GPU_IO::GP1.write(GPU_IO::Command::GP1::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3)); - GPU_IO::GP1.write(GPU_IO::Command::GP1::VerticalDisplayRange(y, y + Display::Height)); + GPU_IO::GP1 = GPU_IO::Command::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3); + GPU_IO::GP1 = GPU_IO::Command::VerticalDisplayRange(y, y + Display::Height); } #else void Screen :: set_offset(uint16_t x, uint16_t y) { - GP1.write(Command::GP1::HorizontalDisplayRange(x, (x + Display::Width*8))); - GP1.write(Command::GP1::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2))); + GPU_IO::GP1 = GPU_IO::Command::HorizontalDisplayRange(x, (x + Display::Width*8)); + GPU_IO::GP1 = GPU_IO::Command::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2)); } #endif //USE_NO$PSX } diff --git a/src/Library/src/run.cpp b/src/Library/src/run.cpp new file mode 100644 index 00000000..37038004 --- /dev/null +++ b/src/Library/src/run.cpp @@ -0,0 +1,12 @@ +#include + +extern void main(); + +namespace JabyEngine { + // Executes the game + void __no_return run() { + main(); + printf("Stop!!\n"); + while(true); + } +} \ No newline at end of file diff --git a/src/Library/src/startup.cpp b/src/Library/src/startup.cpp deleted file mode 100644 index cb3e9fae..00000000 --- a/src/Library/src/startup.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "../include/BootLoader/boot_loader.hpp" -#include - -namespace JabyEngine { - static NextRoutine execute(NextRoutine routine) { - // Support currently only direct call - return reinterpret_cast((routine.value & ~JabyEngine::NextRoutine::OverlayBit))(); - } - - void start() { - NextRoutine next_routine = JabyEngine::NextRoutine::from(boot::Start::setup); - - printf("Starting Planschbecken 0x%p\n", next_routine.value); - while(true) { - if(next_routine.is_null()) { - break; - } - - if(next_routine.is_overlay()) { - printf("Overlay not supported yet!\n"); - break; - } - - next_routine = execute(next_routine); - } - printf("Stop!\n"); - while(true); - } -} \ No newline at end of file diff --git a/src/Tools/.config_build_all/recommended.bat b/src/Tools/.config_build_all/recommended.bat index be37466e..4779c8f0 100644 --- a/src/Tools/.config_build_all/recommended.bat +++ b/src/Tools/.config_build_all/recommended.bat @@ -1,4 +1,4 @@ -set bin_projects=psxcdgen psxcdread psxcdgen_ex +set bin_projects=psxcdgen psxcdread psxcdgen_ex wslpath set bin_linux_projects=cpp_out jaby_engine_fconv mkoverlay set clean_projects=cdtypes set clean_projects_linux=tool_helper \ No newline at end of file diff --git a/src/Tools/Tools.code-workspace b/src/Tools/Tools.code-workspace index dd1e23fb..a1732433 100644 --- a/src/Tools/Tools.code-workspace +++ b/src/Tools/Tools.code-workspace @@ -59,7 +59,7 @@ { "id": "project", "type": "pickString", - "options": ["cdtypes", "cpp_out", "jaby_engine_fconv", "mkoverlay", "psxcdgen", "psxcdgen_ex", "psxcdread", "tool_helper"], + "options": ["cdtypes", "cpp_out", "jaby_engine_fconv", "mkoverlay", "psxcdgen", "psxcdgen_ex", "psxcdread", "tool_helper", "wslpath"], "description": "project to build" }, { diff --git a/src/Tools/mkoverlay/src/creator/ldscript.rs b/src/Tools/mkoverlay/src/creator/ldscript.rs index e256c270..7e636375 100644 --- a/src/Tools/mkoverlay/src/creator/ldscript.rs +++ b/src/Tools/mkoverlay/src/creator/ldscript.rs @@ -58,13 +58,23 @@ fn write_section(output: &mut Output, sections: &Vec, add_end_na for section in sections { writeln!(output, "\t\t.{} {{", section.name)?; writeln!(output, "\t\t\t__{}_start = .;", section.name)?; - section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\tKEEP({}(.header))", patr))?; writeln!(output, "\t\t\t__{}_lbas = .;", section.name)?; section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\tKEEP({}(.header.lbas))", patr))?; writeln!(output, "\t\t\t__{}_ctor = .;", section.name)?; - for section_type in [".text.startup._GLOBAL__*", ".ctors", ".text.*", ".rodata*", ".sdata*", ".data*", ".sbss*", ".bss*"] { - section.file_pattern.iter().try_for_each(|patr| writeln!(output, "\t\t\t{}({})", patr, section_type))?; + for (section_type, keep) in [(".text.startup._GLOBAL__*", false), (".ctors", false), (".text.*", false), (".rodata*", false), (".sdata*", false), (".data*", false), (".sbss*", false), (".bss*", false), (".keep.dummy", true)] { + section.file_pattern.iter().try_for_each(|patr| { + let section_entry = format!("{}({})", patr, section_type); + + write!(output, "\t\t\t")?; + if keep { + writeln!(output, "KEEP({})", section_entry) + } + + else { + writeln!(output, "{}", section_entry) + } + })?; } if add_end_name { diff --git a/src/Tools/psxcdgen_ex/Cargo.toml b/src/Tools/psxcdgen_ex/Cargo.toml index 1a5ed62b..5805d87c 100644 --- a/src/Tools/psxcdgen_ex/Cargo.toml +++ b/src/Tools/psxcdgen_ex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "psxcdgen_ex" -version = "0.1.0" +version = "0.2.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/Tools/psxcdgen_ex/src/config_reader/mod.rs b/src/Tools/psxcdgen_ex/src/config_reader/mod.rs index e497e2a7..566db654 100644 --- a/src/Tools/psxcdgen_ex/src/config_reader/mod.rs +++ b/src/Tools/psxcdgen_ex/src/config_reader/mod.rs @@ -2,6 +2,12 @@ use super::Error; use std::path::PathBuf; mod xml; +pub enum LZ4State { + None, + AlreadyCompressed, + Compress, +} + pub struct Configuration { pub publisher: Option, pub license_path: Option, @@ -17,6 +23,7 @@ impl Configuration { pub struct CommonProperties { pub name: String, pub is_hidden: bool, + pub lz4_state: LZ4State, pub padded_size: Option, } diff --git a/src/Tools/psxcdgen_ex/src/config_reader/xml.rs b/src/Tools/psxcdgen_ex/src/config_reader/xml.rs index 9f6c49bc..991e7eb8 100644 --- a/src/Tools/psxcdgen_ex/src/config_reader/xml.rs +++ b/src/Tools/psxcdgen_ex/src/config_reader/xml.rs @@ -2,13 +2,14 @@ use std::path::PathBuf; use tool_helper::{format_if_error, path_with_env_from}; use crate::config_reader::Directory; -use super::{CommonProperties, Configuration, Error, File, FileKind}; +use super::{CommonProperties, Configuration, Error, File, FileKind, LZ4State}; mod attribute_names { pub const NAME: &'static str = "name"; pub const HIDDEN: &'static str = "hidden"; pub const PADDED_SIZE: &'static str = "padded_size"; pub const LBA_SOURCE: &'static str = "lba_source"; + pub const LZ4_STATE: &'static str = "lz4"; } pub fn parse(xml: String) -> Result { @@ -57,27 +58,28 @@ fn parse_description(description: roxmltree::Node, config: &mut Configuration) - fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(), Error> { fn parse_regular_file(file: roxmltree::Node, is_hidden: bool) -> Result { - let common = read_common_properties(&file, is_hidden)?; + let common = read_common_properties(&file, is_hidden, None)?; let path = path_from_node(&file, &common.name)?; Ok(File{common, path, kind: FileKind::Regular}) } - fn parse_main_file(file: roxmltree::Node, is_hidden: bool) -> Result { + fn parse_main_file(file: roxmltree::Node) -> Result { if let Some(lba_path) = file.attribute(attribute_names::LBA_SOURCE) { - let common = read_common_properties(&file, is_hidden)?; + let common = read_common_properties(&file, false, Some(LZ4State::None))?; let path = path_from_node(&file, &common.name)?; Ok(File{common, path, kind: FileKind::Main(PathBuf::from(lba_path))}) } else { - parse_regular_file(file, is_hidden) + parse_regular_file(file, false) } } fn parse_overlay_file(file: roxmltree::Node, is_hidden: bool) -> Result { - let common = read_common_properties(&file, is_hidden)?; + // v they will be compressed automatically + let common = read_common_properties(&file, is_hidden, Some(LZ4State::AlreadyCompressed))?; let path = path_from_node(&file, &common.name)?; Ok(File{common, path, kind: FileKind::Overlay(PathBuf::from(file.attribute(attribute_names::LBA_SOURCE).unwrap_or_default()))}) @@ -88,7 +90,7 @@ fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(), if node.is_element() { match node.tag_name().name() { "File" => root.add_file(parse_regular_file(node, is_hidden)?), - "Main" => root.add_file(parse_main_file(node, is_hidden)?), + "Main" => root.add_file(parse_main_file(node)?), "Overlay" => root.add_file(parse_overlay_file(node, is_hidden)?), "Directory" => { is_hidden |= parse_boolean_attribute(&node, attribute_names::HIDDEN)?; @@ -108,10 +110,31 @@ fn parse_track(track: roxmltree::Node, config: &mut Configuration) -> Result<(), parse_file_system(track, &mut config.root, false) } -fn read_common_properties(xml: &roxmltree::Node, is_hidden: bool) -> Result { +fn read_common_properties(xml: &roxmltree::Node, is_hidden: bool, force_lz4_state: Option) -> Result { + let lz4_state = { + if let Some(forced_lz4_state) = force_lz4_state { + forced_lz4_state + } + + else { + if let Some(state_str) = xml.attribute(attribute_names::LZ4_STATE) { + match state_str.to_lowercase().as_str() { + "yes" => LZ4State::Compress, + "already" => LZ4State::AlreadyCompressed, + _ => LZ4State::None, + } + } + + else { + LZ4State::None + } + } + }; + Ok(CommonProperties{ name: String::from(xml.attribute(attribute_names::NAME).unwrap_or_default()), is_hidden: is_hidden | parse_boolean_attribute(&xml, attribute_names::HIDDEN)?, + lz4_state, padded_size: read_padded_size(&xml)? }) } diff --git a/src/Tools/psxcdgen_ex/src/lib.rs b/src/Tools/psxcdgen_ex/src/lib.rs index 388478f1..2525acd4 100644 --- a/src/Tools/psxcdgen_ex/src/lib.rs +++ b/src/Tools/psxcdgen_ex/src/lib.rs @@ -5,9 +5,11 @@ pub mod encoder; pub mod file_writer; pub mod types; +use config_reader::LZ4State; use encoder::{LbaCalculatorFunction, LengthCalculatorFunction}; use tool_helper::{format_if_error, Output, read_file}; use types::{layout::Layout, CDDesc, Directory, File, FileType, FileSystemMap, Properties, SharedPtr}; +use std::path::PathBuf; pub type LBAEmbeddedFiles = Vec>; @@ -156,16 +158,30 @@ fn parse_configuration(config: config_reader::Configuration) -> Result<(CDDesc, }, config_reader::DirMember::File(file) => { + let lz4_state = file.common.lz4_state; let (mut desc_file, needs_treatment) = { + fn handle_file_load(file_path: &PathBuf, lz4_state: &LZ4State) -> Result, Error> { + let file_content = read_file(file_path)?; + + if matches!(lz4_state, LZ4State::Compress) { + tool_helper::compress::psx_default::lz4(&file_content) + } + + else { + Ok(file_content) + } + } + match file.kind { - config_reader::FileKind::Regular => (types::File::new_regular(file.common.name.as_str(), read_file(&file.path)?)?, false), - config_reader::FileKind::Main(lba_source) => (types::overlay::load_for_main(file.common.name.as_str(), read_file(&file.path)?, lba_source)?, true), - config_reader::FileKind::Overlay(lba_source) => (types::overlay::load_from(file.common.name.as_str(), file.path, lba_source)?, true), + config_reader::FileKind::Regular => (types::File::new_regular(file.common.name.as_str(), handle_file_load(&file.path, &lz4_state)?)?, false), + config_reader::FileKind::Main(lba_source) => (types::overlay::load_for_main(file.common.name.as_str(), handle_file_load(&file.path, &lz4_state)?, lba_source)?, true), + config_reader::FileKind::Overlay(lba_source) => (types::overlay::load_from(file.common.name.as_str(), &file.path, lba_source)?, true), } }; desc_file.properties.padded_size_bytes = file.common.padded_size; desc_file.properties.is_hidden = file.common.is_hidden; + desc_file.properties.is_lz4 = !matches!(lz4_state, LZ4State::None); let new_file = dst_dir.add_file(desc_file); if needs_treatment { diff --git a/src/Tools/psxcdgen_ex/src/types/mod.rs b/src/Tools/psxcdgen_ex/src/types/mod.rs index 68d00414..cad43dd0 100644 --- a/src/Tools/psxcdgen_ex/src/types/mod.rs +++ b/src/Tools/psxcdgen_ex/src/types/mod.rs @@ -315,7 +315,8 @@ pub struct Properties { pub(super) lba: LBA, pub(super) size_bytes: usize, pub(super) padded_size_bytes: Option, - pub(super) is_hidden: bool + pub(super) is_hidden: bool, + pub(super) is_lz4: bool, } impl Properties { @@ -340,7 +341,7 @@ impl Properties { impl Default for Properties { fn default() -> Self { - Properties{lba: LBA::default(), size_bytes: 0, padded_size_bytes: None, is_hidden: false} + Properties{lba: LBA::default(), size_bytes: 0, padded_size_bytes: None, is_hidden: false, is_lz4: false} } } diff --git a/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs b/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs index de6aca16..58cf1b65 100644 --- a/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs +++ b/src/Tools/psxcdgen_ex/src/types/overlay/mod.rs @@ -2,56 +2,50 @@ use super::{layout::Layout, File, FileSystemMap}; use super::super::encoder::LengthCalculatorFunction; use std::path::PathBuf; use no_comment::{IntoWithoutComments as _, languages}; -use tool_helper::{Error, format_if_error, read_file, format_if_error_drop_cause}; +use tool_helper::{bits::{Bit, BitRange}, Error, format_if_error, read_file, read_file_to_string, format_if_error_drop_cause}; pub type LBANameVec = Vec; mod main; -#[repr(packed)] -struct OverlayHeader { - _start_adr: u32, - lba_count: u16, -} - -impl OverlayHeader { - pub fn read_lba_count(&self) -> usize { - u16::from_le(self.lba_count) as usize - } -} - #[repr(packed)] struct LBAEntry { - lba: u16, - size_words: u16, + raw: u32, } impl LBAEntry { - pub fn write_entry(&mut self, lba: u16, mut size_bytes: usize) -> Result<(), Error> { - const WORD_SIZE:usize = std::mem::size_of::(); + const SIZE_IN_SECTOR_RANGE:BitRange = BitRange::from_to(22, 31); + const IS_LZ4_COMPRESSED:Bit = Bit::at(19); + const LBA_VALUE_RANGE:BitRange = BitRange::from_to(0, 18); - if self.lba != 0 || self.size_words != 0 { + pub fn write_entry(&mut self, lba: usize, size_bytes: usize, is_lz4: bool) -> Result<(), Error> { + if lba > Self::LBA_VALUE_RANGE.max_value() { + return Err(Error::from_text(format!("LBA of value {} is impossible and can not be encoded! Maximum LBA value is: {}", lba, Self::LBA_VALUE_RANGE.max_value()))); + } + + let size_in_sectors = cdtypes::types::helper::sector_count_mode2_form1(size_bytes); + if size_in_sectors > Self::SIZE_IN_SECTOR_RANGE.max_value() { + return Err(Error::from_text(format!("{} sectors can not be encoded into 10bit", size_in_sectors))); + } + + let lba = usize::from_ne_bytes(lba.to_le_bytes()); + let size_in_sectors = usize::from_ne_bytes(size_in_sectors.to_le_bytes()); + + if self.raw != 0 { return Err(Error::from_str("LBA Entry will overwrite non-zero value!\nIs no space allocated for the LBA Entries?")); } - size_bytes = (size_bytes + (WORD_SIZE - 1))/WORD_SIZE; - - if (size_bytes as u16) as usize != size_bytes { - return Err(Error::from_text(format!("{} words can not be encoded into 16bit", size_bytes))); - } - - let lba = lba.to_le_bytes(); - let size_bytes = (size_bytes as u16).to_le_bytes(); - - self.lba = u16::from_ne_bytes(lba); - self.size_words = u16::from_ne_bytes(size_bytes); + let new_raw = Self::LBA_VALUE_RANGE.or_value(0, lba); + let new_raw = Self::SIZE_IN_SECTOR_RANGE.or_value(new_raw, size_in_sectors); + let new_raw = Self::IS_LZ4_COMPRESSED.or_value(new_raw, is_lz4); + self.raw = new_raw as u32; Ok(()) } } -pub fn load_from(file_name: &str, file_path: PathBuf, lba_source: PathBuf) -> Result { - let content = load_content(&file_path)?; +pub fn load_from(file_name: &str, file_path: &PathBuf, lba_source: PathBuf) -> Result { + let content = read_file(file_path)?; let lba_names = load_lba_names(lba_source)?; let content_size = format_if_error!(tool_helper::compress::psx_default::lz4(&content), "Compressing {} failed with \"{error_text}\"", file_path.to_string_lossy())?.len(); @@ -63,15 +57,11 @@ pub fn load_for_main(file_name: &str, content: Vec, lba_source: PathBuf) -> } pub fn update_content(content: &mut Vec, lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction) -> Result, Error> { - let (lba_header, lba_count) = skip_to_lba_header(content); - let lba_header = unsafe{std::slice::from_raw_parts_mut(lba_header.as_mut_ptr() as *mut LBAEntry, lba_count)}; + let lba_header = skip_to_lba_header(content); + let lba_header = unsafe{std::slice::from_raw_parts_mut(lba_header.as_mut_ptr() as *mut LBAEntry, lba_names.len())}; - for_each_lba_name(lba_names, file_map, length_func, |idx, (lba, bytes)| { - if idx >= lba_count { - return Err(Error::from_text(format!("Trying to write more LBAs then there is space!"))); - } - - lba_header[idx].write_entry(lba, bytes) + for_each_lba_name(lba_names, file_map, length_func, |idx, (lba, bytes), is_lz4| { + lba_header[idx].write_entry(lba, bytes, is_lz4) })?; Ok(tool_helper::compress::psx_default::lz4(content)?) @@ -80,20 +70,22 @@ pub fn update_content(content: &mut Vec, lba_names: &LBANameVec, file_map: & pub fn update_content_for_main(content: &mut Vec, lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction) -> Result, Error> { let lba_header = unsafe{std::slice::from_raw_parts_mut(main::skip_to_lba_area(content).as_mut_ptr() as *mut LBAEntry, lba_names.len())}; - for_each_lba_name(lba_names, file_map, length_func, |idx, (lba, bytes)| { - lba_header[idx].write_entry(lba, bytes) + for_each_lba_name(lba_names, file_map, length_func, |idx, (lba, bytes), is_lz4| { + lba_header[idx].write_entry(lba, bytes, is_lz4) })?; Ok(content.clone()) } -fn for_each_lba_name Result<(), Error>>(lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction, mut functor: F) -> Result<(), Error> { +fn for_each_lba_name Result<(), Error>>(lba_names: &LBANameVec, file_map: &FileSystemMap, length_func: LengthCalculatorFunction, mut functor: F) -> Result<(), Error> { let mut idx = 0; for lba_name in lba_names { if let Some(file) = file_map.get(lba_name) { - let (lba, bytes) = (format_if_error_drop_cause!(file.try_borrow(), "Failed accessing file \"{}\" for writing LBA information.\nNote: You can not inject the LBA information of a file into itself.", lba_name)?.get_absolute_lba(), length_func(&Layout::File(file.clone())).bytes); + let file_ref = format_if_error_drop_cause!(file.try_borrow(), "Failed accessing file \"{}\" for writing LBA information.\nNote: You can not inject the LBA information of a file into itself.", lba_name)?; + let (lba, bytes) = (file_ref.get_absolute_lba(), length_func(&Layout::File(file.clone())).bytes); + let is_lz4 = file_ref.properties.is_lz4; - functor(idx, (lba as u16, bytes.ok_or(Error::from_text(format!("{} does not contain a size!", lba_name)))?))?; + functor(idx, (lba, bytes.ok_or(Error::from_text(format!("{} does not contain a size!", lba_name)))?), is_lz4)?; idx += 1; } @@ -105,34 +97,10 @@ fn for_each_lba_name Result<(), Error>>(lba_nam Ok(()) } -fn load_content(file_path: &PathBuf) -> Result, Error> { - let mut content = read_file(&file_path)?; +fn skip_to_lba_header(content: &mut Vec) -> &mut [u8] { + let overlay_header_size = 0; - if content.len() < std::mem::size_of::() { - return Err(Error::from_text(format!("Overlay {} has no header!", file_path.to_string_lossy()))); - } - - let (lba_header, lba_count) = skip_to_lba_header(&mut content); - if lba_header.is_empty() { - return Err(Error::from_text(format!("LBA header of overlay {} is smaller then {} elements", file_path.to_string_lossy(), lba_count))); - } - - let mut count = 0; - for byte in lba_header { - *byte = count as u8; - count += 1; - } - - Ok(content) -} - -fn skip_to_lba_header(content: &mut Vec) -> (&mut [u8], usize) { - let overlay_header_size = std::mem::size_of::(); - - let lba_count = unsafe{std::mem::transmute::<&u8, &OverlayHeader>(&content[0])}.read_lba_count(); - let lba_header_size = lba_count*std::mem::size_of::(); - - (&mut content[overlay_header_size..(overlay_header_size+lba_header_size)], lba_count) + &mut content[overlay_header_size..] } fn load_lba_names(lba_source: PathBuf) -> Result { @@ -152,7 +120,7 @@ fn load_lba_names(lba_source: PathBuf) -> Result { Ok(file[start..end].to_owned()) } - let file = std::fs::read_to_string(&lba_source)?.chars().without_comments(languages::c()).collect::(); + let file = read_file_to_string(&lba_source)?.chars().without_comments(languages::c()).collect::(); let file = get_part_of_interest(file, &lba_source)?; let mut lba_names = Vec::new(); diff --git a/src/Tools/tool_helper/src/bits.rs b/src/Tools/tool_helper/src/bits.rs index 3f03cf56..7dec95a7 100644 --- a/src/Tools/tool_helper/src/bits.rs +++ b/src/Tools/tool_helper/src/bits.rs @@ -1,11 +1,43 @@ pub struct BitRange { - pub start: usize, - pub len: usize, + start: usize, + length: usize } impl BitRange { - pub const fn from_to(start: usize, end: usize) -> BitRange { - BitRange{start, len: (end - start + 1)} + pub const fn from_to(start_bit: usize, end_bit: usize) -> Self { + Self{start: start_bit, length: (end_bit - start_bit) + 1} + } + + pub const fn get_mask(&self) -> usize { + self.max_value() + } + + pub const fn max_value(&self) -> usize { + (1 << self.length) - 1 + } + + pub const fn or_value(&self, dst_value: usize, value: usize) -> usize { + dst_value | ((value & self.get_mask()) << self.start) + } +} + +pub struct Bit { + pos: usize +} + +impl Bit { + pub const fn at(pos: usize) -> Self { + Bit{pos} + } + + pub const fn or_value(&self, dst_value: usize, is_set: bool) -> usize { + if is_set { + dst_value | (1 << self.pos) + } + + else { + dst_value + } } } @@ -13,7 +45,7 @@ macro_rules! create_bit_functions { ($type_val:ty) => { paste::item! { const fn [< get_mask_ $type_val >](range: &BitRange) -> $type_val { - (1 << range.len) - 1 + range.get_mask() as $type_val } pub const fn [< clear_value_ $type_val >](dst: $type_val, range: &BitRange) -> $type_val { diff --git a/src/Tools/tool_helper/src/lib.rs b/src/Tools/tool_helper/src/lib.rs index 105e214c..bc5bc548 100644 --- a/src/Tools/tool_helper/src/lib.rs +++ b/src/Tools/tool_helper/src/lib.rs @@ -184,11 +184,18 @@ pub fn input_to_vec(input: Input) -> Result, Error> { pub fn read_file(file_path: &PathBuf) -> Result, Error> { match std::fs::read(file_path) { - Ok(data) => { - Ok(data) - }, - Err(error) => { - Err(Error::from_text(format!("Failed reading file {} with error: \"{}\"", file_path.display(), error))) - } + Ok(data) => Ok(data), + Err(error) => create_file_read_error(file_path, error), } +} + +pub fn read_file_to_string(file_path: &PathBuf) -> Result { + match std::fs::read_to_string(file_path) { + Ok(string) => Ok(string), + Err(error) => create_file_read_error(file_path, error), + } +} + +fn create_file_read_error(file_path: &PathBuf, error: std::io::Error) -> Result { + Err(Error::from_text(format!("Failed reading file {} with error: \"{}\"", file_path.display(), error))) } \ No newline at end of file diff --git a/src/Tools/wslpath/Cargo.toml b/src/Tools/wslpath/Cargo.toml new file mode 100644 index 00000000..38c5a00d --- /dev/null +++ b/src/Tools/wslpath/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "wslpath" +version = "1.0.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = {version = "*", features = ["derive"]} \ No newline at end of file diff --git a/src/Tools/wslpath/src/lib.rs b/src/Tools/wslpath/src/lib.rs new file mode 100644 index 00000000..28b2a23e --- /dev/null +++ b/src/Tools/wslpath/src/lib.rs @@ -0,0 +1,39 @@ +pub fn convert(path: String) -> String { + replace_drive_letter(convert_slashes(path)) +} + +fn convert_slashes(path: String) -> String { + path.replace('\\', "/") +} + +fn replace_drive_letter(mut path: String) -> String { + let has_drive_letter = { + let drive_letter = path.get(0..2); + + if let Some(drive_letter) = drive_letter { + let starts_with_letter = drive_letter.chars().nth(0).unwrap_or('1').is_alphabetic(); + let has_seperator = drive_letter.chars().nth(1).unwrap_or('x') == ':'; + + starts_with_letter && has_seperator + } + + else { + false + } + }; + + if has_drive_letter { + path.replace_range(1..2, ""); // Removes : + if let Some(start_char) = path.get(0..1) { // Convert drive letter to lower case + path.replace_range(0..1, start_char.to_lowercase().as_str()); + } + + if path.len() == 3 { + path.push('/'); + } + + path.insert_str(0, "/mnt/"); + } + + path +} \ No newline at end of file diff --git a/src/Tools/wslpath/src/main.rs b/src/Tools/wslpath/src/main.rs new file mode 100644 index 00000000..c9f05efe --- /dev/null +++ b/src/Tools/wslpath/src/main.rs @@ -0,0 +1,19 @@ +use clap::Parser; + +#[derive(Parser)] +#[clap(about = "A copy of the wslpath tool from wsl for faster execution", long_about = None)] +struct CommandLine { + #[clap(value_parser, help="The input path to convert to WSL")] + path_string: String +} + +fn main() { + match CommandLine::try_parse() { + Ok(cmd_line) => { + print!("{}", wslpath::convert(cmd_line.path_string)); + }, + Err(error) => { + eprintln!("{}", error); + } + } +} \ No newline at end of file