Add new BasicFrame class.

This commit is contained in:
King_DuckZ 2020-03-20 16:21:17 +01:00
parent 4eaa2fc734
commit db70dead33
11 changed files with 115 additions and 38 deletions

View file

@ -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() << ']';

View file

@ -1,5 +1,6 @@
#pragma once
#include "memcard/frame.hpp"
#include <cstdint>
#include <type_traits>
#include <vector>
@ -20,26 +21,22 @@ enum class IconDisplayFlag {
template <bool Const>
class BasicBlock {
public:
using data_type = typename std::conditional<Const, const uint8_t, uint8_t>::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<Const> 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<uint8_t> icon_palette() const;
bool has_magic() const;

View file

@ -3,8 +3,8 @@
#include <cstdint>
namespace mc::psx {
template <bool Const> class BasicBlock;
using ConstBlock = BasicBlock<true>;
template <bool Const> class BasicFrame;
using ConstFrame = BasicFrame<true>;
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;

View file

@ -0,0 +1,39 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <type_traits>
namespace mc::psx {
template <bool Const>
class BasicFrame {
using data_type = typename std::conditional<Const, const uint8_t, uint8_t>::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<false>;
using ConstFrame = BasicFrame<true>;
} //namespace mc::psx

View file

@ -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<uint8_t> m_data;
};

View file

@ -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],
)

View file

@ -18,10 +18,12 @@ namespace {
}
#endif
std::vector<uint8_t> extract_palette (const uint8_t* b, const uint8_t* e) {
std::vector<uint8_t> extract_palette (const ConstFrame& frame) {
std::vector<uint8_t> 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 <bool Const>
BasicBlock<Const>::~BasicBlock() = default;
template <bool Const>
auto BasicBlock<Const>::frame(unsigned int idx) -> data_type* {
return const_cast<data_type*>(const_cast<const BasicBlock<Const>*>(this)->frame(idx));
BasicFrame<Const> BasicBlock<Const>::frame(unsigned int idx) {
assert(idx < size());
return {this->data() + Frame::Size * idx, idx};
}
template <bool Const>
auto BasicBlock<Const>::frame(unsigned int idx) const -> const data_type* {
assert(idx * FrameSize + FrameSize <= this->size());
return this->begin() + FrameSize * idx;
ConstFrame BasicBlock<Const>::frame(unsigned int idx) const {
assert(idx < size());
return {this->data() + Frame::Size * idx, idx};
}
template <bool Const>
std::vector<uint8_t> BasicBlock<Const>::icon_palette() const {
const auto ptr = frame(0);
return extract_palette(ptr, ptr + FrameSize);
return extract_palette(frame(0));
}
template <bool Const>
bool BasicBlock<Const>::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<uint16_t>((ptr[0] << 8) | ptr[1]);
}
@ -123,7 +125,7 @@ int BasicBlock<Const>::block_count() const {
template <bool Const>
std::string BasicBlock<Const>::title() const {
char mem[64 + 1];
std::strncpy(mem, reinterpret_cast<const char*>(frame(0) + 4), sizeof(mem) / sizeof(mem[0]));
std::strncpy(mem, reinterpret_cast<const char*>(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));

View file

@ -1,27 +1,27 @@
#include "memcard/content_info.hpp"
#include "memcard/block.hpp"
#include "memcard/frame.hpp"
#include <algorithm>
namespace mc::psx {
namespace {
template <typename T>
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<uint8_t*>(&retval)
);
return retval;
}
} //unnamed namespace
ContentInfo::ContentInfo (const ConstBlock& block) :
use_byte(read_as<uint32_t>(block, 0x84)),
magic(read_as<uint16_t>(block, 0x00)),
ContentInfo::ContentInfo (const ConstFrame& frame) :
use_byte(read_as<uint32_t>(frame, 0x84)),
magic(read_as<uint16_t>(frame, 0x00)),
available_blocks(BlockContent::Available)
{
auto block_content = read_as<uint8_t>(block, 0x80);
auto block_content = read_as<uint8_t>(frame, 0x80);
switch (block_content & 0xf) {
case 0x0:
available_blocks = BlockContent::Available;

View file

@ -0,0 +1,26 @@
#include "memcard/frame.hpp"
#include <cassert>
namespace mc::psx {
template <bool Const>
BasicFrame<Const>::BasicFrame (data_type* data, std::size_t index) :
m_index(index),
m_data(data)
{
}
template <bool Const>
auto BasicFrame<Const>::operator[] (std::size_t index) -> data_type& {
assert(index < size());
return m_data[index];
}
template <bool Const>
auto BasicFrame<Const>::operator[] (std::size_t index) const -> const data_type& {
assert(index < size());
return m_data[index];
}
template class BasicFrame<true>;
template class BasicFrame<false>;
} //namespace mc::psx

View file

@ -164,7 +164,7 @@ std::vector<std::vector<char>> 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);
}
}

View file

@ -1,5 +1,6 @@
#include "memcard/memorycard.hpp"
#include "memcard/block.hpp"
#include "memcard/frame.hpp"
#include <iterator>
#include <cassert>
@ -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<std::size_t> block_group (const MemoryCard& mc, std::size_t index) {
std::vector<std::size_t> retval;