Add new methods to BasicBlock.
This commit is contained in:
parent
30ef4cd49d
commit
747209f744
9 changed files with 134 additions and 26 deletions
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
17
subprojects/memcard/include/memcard/country_code.hpp
Normal file
17
subprojects/memcard/include/memcard/country_code.hpp
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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],
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) :
|
||||
|
|
34
subprojects/memcard/src/country_code.cpp
Normal file
34
subprojects/memcard/src/country_code.cpp
Normal 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
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue