diff --git a/src/cli/memcard.cpp b/src/cli/memcard.cpp index 939d702..f0f5d9f 100644 --- a/src/cli/memcard.cpp +++ b/src/cli/memcard.cpp @@ -19,7 +19,7 @@ void print_blocks (const std::string& mc_path) { for (const auto& blk : mc) { if (blk.has_magic()) { - std::cout << "Block " << std::setfill(' ') << std::setw(2) << blk.index() + 1 + std::cout << "Block " << std::setfill(' ') << std::setw(2) << blk.index() << ": \"" << blk.title() << '"'; if (blk.block_count() > 1) { std::cout << " [" << blk.block_count() << ']'; diff --git a/subprojects/memcard/include/memcard/block.hpp b/subprojects/memcard/include/memcard/block.hpp index cadca47..114ed30 100644 --- a/subprojects/memcard/include/memcard/block.hpp +++ b/subprojects/memcard/include/memcard/block.hpp @@ -1,5 +1,6 @@ #pragma once +#include "memcard/frame.hpp" #include #include #include @@ -20,26 +21,22 @@ enum class IconDisplayFlag { template class BasicBlock { -public: using data_type = typename std::conditional::type; +public: - static const constexpr unsigned int FrameSize = 128; - static const constexpr std::size_t ToCBlockIndex = 0xff; + static const constexpr std::size_t FrameCount = 64; + static const constexpr std::size_t TOCBlockIndex = 0; BasicBlock (data_type* beg, std::size_t index); ~BasicBlock(); - data_type* begin() { return m_begin; } - data_type* end() { return m_begin + size(); } - const data_type* cbegin() const { return m_begin; } - const data_type* cend() const { return m_begin + size(); } - const data_type* begin() const { return m_begin; } - const data_type* end() const { return m_begin + size(); } + data_type* data() { return m_begin; } + const data_type* data() const { return m_begin; } - data_type* frame(unsigned int idx); - const data_type* frame(unsigned int idx) const; + BasicFrame frame(unsigned int idx); + ConstFrame frame(unsigned int idx) const; - static constexpr std::size_t size() { return FrameSize * 64; } + static constexpr std::size_t size() { return FrameCount; } std::vector icon_palette() const; bool has_magic() const; diff --git a/subprojects/memcard/include/memcard/content_info.hpp b/subprojects/memcard/include/memcard/content_info.hpp index f30817b..121ea57 100644 --- a/subprojects/memcard/include/memcard/content_info.hpp +++ b/subprojects/memcard/include/memcard/content_info.hpp @@ -3,8 +3,8 @@ #include namespace mc::psx { -template class BasicBlock; -using ConstBlock = BasicBlock; +template class BasicFrame; +using ConstFrame = BasicFrame; enum class BlockContent : uint8_t { Available = 0xA0, @@ -15,7 +15,7 @@ enum class BlockContent : uint8_t { }; struct ContentInfo { - ContentInfo (const ConstBlock& block); + ContentInfo (const ConstFrame& block); uint32_t use_byte; uint16_t magic; diff --git a/subprojects/memcard/include/memcard/frame.hpp b/subprojects/memcard/include/memcard/frame.hpp new file mode 100644 index 0000000..1b183e2 --- /dev/null +++ b/subprojects/memcard/include/memcard/frame.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace mc::psx { +template +class BasicFrame { + using data_type = typename std::conditional::type; +public: + static const constexpr unsigned int Size = 128; + + BasicFrame (data_type* data, std::size_t index); + BasicFrame (const BasicFrame&) = default; + BasicFrame (BasicFrame&&) = default; + + data_type* begin() { return m_data; } + data_type* end() { return m_data + size(); } + const data_type* cbegin() const { return m_data; } + const data_type* cend() const { return m_data + size(); } + const data_type* begin() const { return m_data; } + const data_type* end() const { return m_data + size(); } + data_type& operator[] (std::size_t index); + const data_type& operator[] (std::size_t index) const; + + static constexpr std::size_t size() { return Size; } + + data_type* data() { return m_data; } + const data_type* data() const { return m_data; } + +private: + std::size_t m_index; + data_type* m_data; +}; + +using Frame = BasicFrame; +using ConstFrame = BasicFrame; +} //namespace mc::psx diff --git a/subprojects/memcard/include/memcard/memorycard.hpp b/subprojects/memcard/include/memcard/memorycard.hpp index deb1fa6..a90c318 100644 --- a/subprojects/memcard/include/memcard/memorycard.hpp +++ b/subprojects/memcard/include/memcard/memorycard.hpp @@ -33,6 +33,9 @@ public: const_iterator end() const; private: + Block block_at_index(std::size_t index); + ConstBlock block_at_index(std::size_t index) const; + std::vector m_data; }; diff --git a/subprojects/memcard/meson.build b/subprojects/memcard/meson.build index 0573737..7e0a403 100644 --- a/subprojects/memcard/meson.build +++ b/subprojects/memcard/meson.build @@ -14,6 +14,7 @@ memcard = shared_library('memcard', 'src/content_info.cpp', 'src/make_memory_card.cpp', 'src/part_iterator.cpp', + 'src/frame.cpp', install: true, include_directories: [private_incl, library_incl], ) diff --git a/subprojects/memcard/src/block.cpp b/subprojects/memcard/src/block.cpp index 5a0bdc5..485ac9e 100644 --- a/subprojects/memcard/src/block.cpp +++ b/subprojects/memcard/src/block.cpp @@ -18,10 +18,12 @@ namespace { } #endif - std::vector extract_palette (const uint8_t* b, const uint8_t* e) { + std::vector extract_palette (const ConstFrame& frame) { std::vector retval; retval.reserve(16 * 4); + auto b = frame.cbegin(); + const auto e = frame.cend(); { if (e - b < 96) throw std::runtime_error("Not enough data to advance and extract an icon palette"); @@ -86,26 +88,26 @@ template BasicBlock::~BasicBlock() = default; template -auto BasicBlock::frame(unsigned int idx) -> data_type* { - return const_cast(const_cast*>(this)->frame(idx)); +BasicFrame BasicBlock::frame(unsigned int idx) { + assert(idx < size()); + return {this->data() + Frame::Size * idx, idx}; } template -auto BasicBlock::frame(unsigned int idx) const -> const data_type* { - assert(idx * FrameSize + FrameSize <= this->size()); - return this->begin() + FrameSize * idx; +ConstFrame BasicBlock::frame(unsigned int idx) const { + assert(idx < size()); + return {this->data() + Frame::Size * idx, idx}; } template std::vector BasicBlock::icon_palette() const { - const auto ptr = frame(0); - return extract_palette(ptr, ptr + FrameSize); + return extract_palette(frame(0)); } template bool BasicBlock::has_magic() const { const constexpr uint16_t magic = ('S' << 8) | 'C'; //0x5343 "SC" - const data_type* const ptr = frame(0); + const data_type* const ptr = frame(0).data(); return magic == static_cast((ptr[0] << 8) | ptr[1]); } @@ -123,7 +125,7 @@ int BasicBlock::block_count() const { template std::string BasicBlock::title() const { char mem[64 + 1]; - std::strncpy(mem, reinterpret_cast(frame(0) + 4), sizeof(mem) / sizeof(mem[0])); + std::strncpy(mem, reinterpret_cast(frame(0).data() + 4), sizeof(mem) / sizeof(mem[0])); std::string_view temp(mem, std::strlen(mem)); auto name = full_to_halfwidth_ascii(shiftjis_to_utf8(temp)); diff --git a/subprojects/memcard/src/content_info.cpp b/subprojects/memcard/src/content_info.cpp index 5436d1b..2142ebd 100644 --- a/subprojects/memcard/src/content_info.cpp +++ b/subprojects/memcard/src/content_info.cpp @@ -1,27 +1,27 @@ #include "memcard/content_info.hpp" -#include "memcard/block.hpp" +#include "memcard/frame.hpp" #include namespace mc::psx { namespace { template - T read_as (const ConstBlock& block, std::size_t offset) { + T read_as (const ConstFrame& frame, std::size_t offset) { T retval; std::copy( - block.begin() + offset, - block.begin() + offset + sizeof(T), + frame.begin() + offset, + frame.begin() + offset + sizeof(T), reinterpret_cast(&retval) ); return retval; } } //unnamed namespace -ContentInfo::ContentInfo (const ConstBlock& block) : - use_byte(read_as(block, 0x84)), - magic(read_as(block, 0x00)), +ContentInfo::ContentInfo (const ConstFrame& frame) : + use_byte(read_as(frame, 0x84)), + magic(read_as(frame, 0x00)), available_blocks(BlockContent::Available) { - auto block_content = read_as(block, 0x80); + auto block_content = read_as(frame, 0x80); switch (block_content & 0xf) { case 0x0: available_blocks = BlockContent::Available; diff --git a/subprojects/memcard/src/frame.cpp b/subprojects/memcard/src/frame.cpp new file mode 100644 index 0000000..82cb11c --- /dev/null +++ b/subprojects/memcard/src/frame.cpp @@ -0,0 +1,26 @@ +#include "memcard/frame.hpp" +#include + +namespace mc::psx { +template +BasicFrame::BasicFrame (data_type* data, std::size_t index) : + m_index(index), + m_data(data) +{ +} + +template +auto BasicFrame::operator[] (std::size_t index) -> data_type& { + assert(index < size()); + return m_data[index]; +} + +template +auto BasicFrame::operator[] (std::size_t index) const -> const data_type& { + assert(index < size()); + return m_data[index]; +} + +template class BasicFrame; +template class BasicFrame; +} //namespace mc::psx diff --git a/subprojects/memcard/src/icon_fetch.cpp b/subprojects/memcard/src/icon_fetch.cpp index f2f2db0..035b481 100644 --- a/subprojects/memcard/src/icon_fetch.cpp +++ b/subprojects/memcard/src/icon_fetch.cpp @@ -164,7 +164,7 @@ std::vector> icon_fetch (const psx::ConstBlock& block, int wid orig_rgb.resize(in_scan_sz * in_height); for (int y = 0; y < in_height; ++y) { for (int x = 0; x < in_width / 2; ++x) { - const uint8_t curr = *(block.frame(1 + icon_num) + (in_width / 2 * y) + x); + const uint8_t curr = *(block.frame(1 + icon_num).data() + (in_width / 2 * y) + x); orig_rgb[y * in_scan_sz + x] = ((curr bitand 0xf0) >> 4) bitor ((curr bitand 0x0f) << 4); } } diff --git a/subprojects/memcard/src/memorycard.cpp b/subprojects/memcard/src/memorycard.cpp index 54af80b..586109a 100644 --- a/subprojects/memcard/src/memorycard.cpp +++ b/subprojects/memcard/src/memorycard.cpp @@ -1,5 +1,6 @@ #include "memcard/memorycard.hpp" #include "memcard/block.hpp" +#include "memcard/frame.hpp" #include #include @@ -17,16 +18,16 @@ MemoryCard::~MemoryCard() = default; Block MemoryCard::operator[] (std::size_t index) { assert(index < 15); - return Block(m_data.data() + (index + 1) * Block::size(), index); + return block_at_index(index + 1); } ConstBlock MemoryCard::operator[] (std::size_t index) const { assert(index < 15); - return ConstBlock(m_data.data() + (index + 1) * Block::size(), index); + return block_at_index(index + 1); } ContentInfo MemoryCard::content_info() const { - return {ConstBlock(m_data.data(), ConstBlock::ToCBlockIndex)}; + return {block_at_index(0).frame(0)}; } std::size_t MemoryCard::size() const { @@ -61,6 +62,14 @@ auto MemoryCard::end() const -> const_iterator { return const_iterator(this, size()); } +Block MemoryCard::block_at_index(std::size_t index) { + return Block(m_data.data() + index * Block::size() * Frame::size(), index); +} + +ConstBlock MemoryCard::block_at_index(std::size_t index) const { + return ConstBlock(m_data.data() + index * Block::size() * Frame::size(), index); +} + std::vector block_group (const MemoryCard& mc, std::size_t index) { std::vector retval;