Add new methods to BasicBlock.

This commit is contained in:
King_DuckZ 2020-03-20 18:24:54 +01:00
parent 30ef4cd49d
commit 747209f744
9 changed files with 134 additions and 26 deletions

View file

@ -22,8 +22,10 @@ void print_blocks (const std::string& mc_path) {
std::cout << "Block " << std::setfill(' ') << std::setw(2) << blk.index()
<< ": \"" << blk.title() << '"';
if (blk.block_count() > 1) {
std::cout << " [" << blk.block_count() << ']';
std::cout << " (x" << blk.block_count() << ')';
}
std::cout << " [" << to_char(blk.country_code()) << ']';
std::cout << ' ' << blk.product_code();
std::cout << '\n';
}
}

View file

@ -2,6 +2,7 @@
#include "memcard/frame.hpp"
#include "memcard/frame_iterator.hpp"
#include "memcard/country_code.hpp"
#include <cstdint>
#include <type_traits>
#include <vector>
@ -20,15 +21,16 @@ enum class IconDisplayFlag {
template <bool Const>
class BasicBlock {
using data_type = typename std::conditional<Const, const uint8_t, uint8_t>::type;
public:
using data_type = typename std::conditional<Const, const uint8_t, uint8_t>::type;
typedef FrameIterator<Const, Const> iterator;
typedef FrameIterator<true, Const> const_iterator;
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* blk, std::size_t index);
BasicBlock (data_type* blk, BasicFrame<Const> toc_entry, std::size_t index);
~BasicBlock();
iterator begin();
@ -52,8 +54,14 @@ public:
int block_count() const;
std::size_t index() const { return m_index; }
std::string title() const;
std::size_t available_blocks() const;
uint16_t link_order() const;
CountryCode country_code() const;
std::string product_code() const;
bool has_pocket_station_content() const;
private:
BasicFrame<Const> m_toc_entry;
std::size_t m_index;
data_type* m_begin;
};

View file

@ -0,0 +1,17 @@
#pragma once
#include <string>
namespace mc::psx {
enum class CountryCode : uint16_t {
Japan = 'B' | ('I' << 8),
America = 'B' | ('A' << 8),
Europe = 'B' | ('E' << 8),
Unknown = 0
};
std::string to_string (CountryCode code);
char to_char (CountryCode code);
uint16_t to_uint16 (CountryCode code);
CountryCode to_country_code (uint16_t code);
} //namespace mc::psx

View file

@ -3,6 +3,7 @@
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <algorithm>
namespace mc::psx {
template <bool Const>
@ -29,11 +30,27 @@ public:
data_type* data() { return m_data; }
const data_type* data() const { return m_data; }
template <typename T>
T extract (std::size_t offset) const;
private:
void extract (std::size_t offset, std::size_t sz, uint8_t* out);
std::size_t m_index;
data_type* m_data;
};
template <typename T, bool Const>
inline T read_as (const BasicFrame<Const>& frame, std::size_t offset) {
T retval;
std::copy(
frame.begin() + offset,
frame.begin() + offset + sizeof(T),
reinterpret_cast<uint8_t*>(&retval)
);
return retval;
}
using Frame = BasicFrame<false>;
using ConstFrame = BasicFrame<true>;
} //namespace mc::psx

View file

@ -15,6 +15,7 @@ memcard = shared_library('memcard',
'src/make_memory_card.cpp',
'src/part_iterator.cpp',
'src/frame.cpp',
'src/country_code.cpp',
install: true,
include_directories: [private_incl, library_incl],
)

View file

@ -12,6 +12,8 @@
namespace mc::psx {
namespace {
uint8_t g_dummy_data[Frame::size()] = {0};
#if defined(FLOAT_PALETTE_CONV)
uint8_t _5bit_to_8bit(int n) {
return static_cast<uint8_t>(static_cast<float>(n) / 0x1F * 255.0f + 0.5f);
@ -68,20 +70,18 @@ namespace {
} //unnamed namespace
template <bool Const>
BasicBlock<Const>::BasicBlock (data_type* beg, std::size_t index) :
BasicBlock<Const>::BasicBlock (data_type* blk, std::size_t index) :
BasicBlock(blk, BasicFrame<Const>(g_dummy_data, 0), index)
{
}
template <bool Const>
BasicBlock<Const>::BasicBlock (data_type* blk, BasicFrame<Const> toc_entry, std::size_t index) :
m_toc_entry(toc_entry),
m_index(index),
m_begin(beg)
m_begin(blk)
{
assert(m_begin);
if (has_magic()) {
uint32_t use_byte;
static_assert(sizeof(use_byte) == 4, "Wrong type size");
const constexpr int offs = 0x84;
std::copy(m_begin + offs, m_begin + offs + 4, reinterpret_cast<unsigned char*>(&use_byte));
//std::clog << "Use byte for block " << title() << " (" << title().size() << ')' <<
// ": 0x" << std::hex << use_byte << std::dec << '\n';
}
}
template <bool Const>
@ -183,6 +183,34 @@ std::string BasicBlock<Const>::title() const {
return name;
}
template <bool Const>
std::size_t BasicBlock<Const>::available_blocks() const {
return m_toc_entry.data()[0];
}
template <bool Const>
uint16_t BasicBlock<Const>::link_order() const {
return read_as<uint16_t>(m_toc_entry, 0x08);
}
template <bool Const>
CountryCode BasicBlock<Const>::country_code() const {
const auto cc = read_as<uint16_t>(m_toc_entry, 0x0A);
return to_country_code(cc);
}
template <bool Const>
std::string BasicBlock<Const>::product_code() const {
std::string retval{reinterpret_cast<const char*>(m_toc_entry.data() + 0x0C), 10};
retval[4] = '-';
return retval;
}
template <bool Const>
bool BasicBlock<Const>::has_pocket_station_content() const {
return (m_toc_entry.data()[0x0C + 4] == 'P');
}
template class BasicBlock<true>;
template class BasicBlock<false>;
} //namespace mc::psx

View file

@ -4,16 +4,6 @@
namespace mc::psx {
namespace {
template <typename T>
T read_as (const ConstFrame& frame, std::size_t offset) {
T retval;
std::copy(
frame.begin() + offset,
frame.begin() + offset + sizeof(T),
reinterpret_cast<uint8_t*>(&retval)
);
return retval;
}
} //unnamed namespace
ContentInfo::ContentInfo (const ConstFrame& frame) :

View file

@ -0,0 +1,34 @@
#include "memcard/country_code.hpp"
namespace mc::psx {
std::string to_string (CountryCode code) {
switch (code) {
case CountryCode::Japan: return "Japan";
case CountryCode::America: return "America";
case CountryCode::Europe: return "Europe";
default: return "Unknown";
};
}
char to_char (CountryCode code) {
switch (code) {
case CountryCode::Japan: return 'J';
case CountryCode::America: return 'U';
case CountryCode::Europe: return 'E';
default: return 'X';
};
}
uint16_t to_uint16 (CountryCode code) {
return static_cast<uint16_t>(code);
}
CountryCode to_country_code (uint16_t code) {
switch (code) {
case static_cast<uint16_t>(CountryCode::Japan): return CountryCode::Japan;
case static_cast<uint16_t>(CountryCode::America): return CountryCode::America;
case static_cast<uint16_t>(CountryCode::Europe): return CountryCode::Europe;
default: return CountryCode::Unknown;
}
}
} //namespace mc::psx

View file

@ -7,6 +7,17 @@
namespace mc::psx {
namespace {
const constexpr std::size_t MemoryCardSize = 8192 * 16;
template <bool Const>
BasicBlock<Const> make_block_for_index (typename BasicBlock<Const>::data_type* data, std::size_t index) {
const auto retptr = data + index * Block::size() * Frame::size();
if (index > 0) {
return {retptr, BasicFrame<Const>(data + index * Frame::size(), index), index};
}
else {
return {data + index, index};
}
}
} //unnamed namespace
MemoryCard::MemoryCard() :
@ -63,11 +74,11 @@ auto MemoryCard::end() const -> const_iterator {
}
Block MemoryCard::block_at_index(std::size_t index) {
return Block(m_data.data() + index * Block::size() * Frame::size(), index);
return make_block_for_index<false>(m_data.data(), index);
}
ConstBlock MemoryCard::block_at_index(std::size_t index) const {
return ConstBlock(m_data.data() + index * Block::size() * Frame::size(), index);
return make_block_for_index<true>(m_data.data(), index);
}
std::vector<std::size_t> block_group (const MemoryCard& mc, std::size_t index) {