From 0b94626549542b8e4f82f25adf6db4e404d528e0 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Sat, 15 Feb 2025 02:45:02 +0000 Subject: [PATCH] Store individual multiblock saves into a separate in-mem db by value --- src/qt/block_db.cpp | 82 +++++++++++++++++++ src/qt/block_db.hpp | 57 +++++++++++++ src/qt/memoserv_win.cpp | 10 +++ src/qt/memoserv_win.hpp | 2 + src/qt/meson.build | 1 + subprojects/memcard/include/memcard/block.hpp | 25 ++++-- subprojects/memcard/src/block.cpp | 10 +++ 7 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 src/qt/block_db.cpp create mode 100644 src/qt/block_db.hpp diff --git a/src/qt/block_db.cpp b/src/qt/block_db.cpp new file mode 100644 index 0000000..4d63320 --- /dev/null +++ b/src/qt/block_db.cpp @@ -0,0 +1,82 @@ +/* Copyright 2020-2025, Michele Santullo + * This file is part of memoserv. + * + * Memoserv is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Memoserv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Memoserv. If not, see . + */ + +#include "block_db.hpp" +#include "memcard/block.hpp" +#include +#include +#include +#include +#include + +namespace duck { +BlockEntry::BlockEntry ( + std::vector>&& blocks, + std::unique_ptr&& data +) : + blocks(std::move(blocks)), + data(std::move(data)) +{ +} + +std::string_view BlockEntry::identifier() const { + return blocks.front().identifier(); +} + +std::string BlockEntry::title() const { + return blocks.front().title(); +} + +BlockDb::BlockDb() = default; +BlockDb::~BlockDb() noexcept = default; + +template +unsigned int BlockDb::add (const std::vector >& blocks) { + constexpr auto block_size = mc::psx::BasicBlock::BlockByteSize; + constexpr auto frame_size = mc::psx::BasicFrame::Size; + assert(not blocks.empty()); + + const auto block_count = blocks.size(); + assert(block_count == blocks.front().block_count()); + auto mem = std::make_unique(frame_size + block_size * block_count); + + uint8_t* dest = std::copy(blocks.front().toc().cbegin(), blocks.front().toc().cend(), mem.get()); + assert(std::distance(mem.get(), dest) == frame_size); + mc::psx::Frame toc(mem.get(), 0); + + std::vector> new_blocks; + new_blocks.reserve(block_count); + std::size_t index = 0; + for (const auto& block : blocks) { + assert(block_count == block.block_count() or block.block_count() == 0); + uint8_t* const curr_block_ptr = dest; + dest = std::copy(block.data(), block.data() + block_size, dest); + new_blocks.emplace_back(curr_block_ptr, toc, index++); + } + + const std::size_t new_id = m_next_id++; + m_saves.emplace( + std::piecewise_construct, + std::forward_as_tuple(new_id), + std::forward_as_tuple(std::move(new_blocks), std::move(mem)) + ); + return static_cast(m_saves.size() - 1u); +} + +template unsigned int BlockDb::add (const std::vector >&); +template unsigned int BlockDb::add (const std::vector >&); +} //namespace duck diff --git a/src/qt/block_db.hpp b/src/qt/block_db.hpp new file mode 100644 index 0000000..a8d8f50 --- /dev/null +++ b/src/qt/block_db.hpp @@ -0,0 +1,57 @@ +/* Copyright 2020-2025, Michele Santullo + * This file is part of memoserv. + * + * Memoserv is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Memoserv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Memoserv. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace mc::psx { +template class BasicBlock; +} //namespace mc::psx + +namespace duck { +struct BlockEntry { + BlockEntry ( + std::vector >&& blocks, + std::unique_ptr&& data + ); + + std::string_view identifier() const; + std::string title() const; + + std::vector > blocks; + std::unique_ptr data; +}; + +class BlockDb { +public: + BlockDb(); + ~BlockDb() noexcept; + + template + unsigned int add (const std::vector >& blocks); + +private: + std::map m_saves; + std::size_t m_next_id{0}; +}; +} //namespace duck diff --git a/src/qt/memoserv_win.cpp b/src/qt/memoserv_win.cpp index 373ac28..b650776 100644 --- a/src/qt/memoserv_win.cpp +++ b/src/qt/memoserv_win.cpp @@ -30,6 +30,7 @@ #include #include #include +#include class QApplication; @@ -105,7 +106,16 @@ void MemoservWin::load_memory_cards (const QStringList& paths) { auto& mc = m_memcards.back(); auto grid = std::make_unique(this, 5, 3, g_icon_fps); grid->set_icon_size(g_icon_size); + + std::vector blocks_for_db; for (const auto& block : mc) { + blocks_for_db.reserve(block.block_count()); + blocks_for_db.push_back(block); + if (blocks_for_db.size() == blocks_for_db.front().block_count()) { + m_block_db.add(blocks_for_db); + blocks_for_db.clear(); + } + for (std::size_t n = 0; block.has_magic() and n < block.block_count(); ++n) { grid->push_back(make_qt_animation(block, g_icon_size, g_icon_size)); } diff --git a/src/qt/memoserv_win.hpp b/src/qt/memoserv_win.hpp index 1af2d03..06e9173 100644 --- a/src/qt/memoserv_win.hpp +++ b/src/qt/memoserv_win.hpp @@ -17,6 +17,7 @@ #pragma once +#include "block_db.hpp" #include #include #include @@ -45,6 +46,7 @@ private: void open_file_from_dialog(); void load_memory_cards (const QStringList& paths); + duck::BlockDb m_block_db; std::list m_memcards; QGridLayout* m_main_lay; unsigned int m_grid_count; diff --git a/src/qt/meson.build b/src/qt/meson.build index 2d42924..f64b3be 100644 --- a/src/qt/meson.build +++ b/src/qt/meson.build @@ -38,6 +38,7 @@ executable(app_name, 'widgets/detail/block_drag_and_drop.cpp', 'make_qt_animation.cpp', 'animated_pixmap.cpp', + 'block_db.cpp', include_directories: inc, dependencies: [ qt6_dep, diff --git a/subprojects/memcard/include/memcard/block.hpp b/subprojects/memcard/include/memcard/block.hpp index d214625..dc46be0 100644 --- a/subprojects/memcard/include/memcard/block.hpp +++ b/subprojects/memcard/include/memcard/block.hpp @@ -48,12 +48,14 @@ public: static const constexpr std::size_t FrameCount = 64; static const constexpr std::size_t TOCBlockIndex = 0xFF; static const constexpr uint16_t LastLink = 0xFFFF; + static constexpr std::size_t BlockByteSize = BasicFrame::Size * FrameCount; BasicBlock() = default; + constexpr BasicBlock (const BasicBlock& other); + BasicBlock(BasicBlock&&) = default; BasicBlock (data_type* blk, std::size_t index); BasicBlock (data_type* blk, BasicFrame toc_entry, std::size_t index); - template BasicBlock (const BasicBlock& other); - BasicBlock(BasicBlock&&) = default; + template BasicBlock(const BasicBlock& other); ~BasicBlock(); iterator begin(); @@ -68,6 +70,8 @@ public: BasicFrame frame(unsigned int idx); ConstFrame frame(unsigned int idx) const; + BasicFrame toc(); + ConstFrame toc() const; static constexpr std::size_t size() { return FrameCount; } @@ -115,12 +119,21 @@ inline int32_t calc_icon_count (IconDisplayFlag idf) { } } +template +constexpr BasicBlock::BasicBlock (const BasicBlock& other) : + m_toc_entry(other.m_toc_entry), + m_index(other.m_index), + m_begin(other.m_begin) +{ +} + template template -inline BasicBlock::BasicBlock (const BasicBlock& other) { - m_index = other.m_index; - m_toc_entry = other.m_toc_entry; - m_begin = other.m_begin; +inline BasicBlock::BasicBlock(const BasicBlock& other) : + m_toc_entry(other.m_toc_entry), + m_index(other.m_index), + m_begin(other.m_begin) +{ } using Block = BasicBlock; diff --git a/subprojects/memcard/src/block.cpp b/subprojects/memcard/src/block.cpp index aeec600..27c55b4 100644 --- a/subprojects/memcard/src/block.cpp +++ b/subprojects/memcard/src/block.cpp @@ -145,6 +145,16 @@ ConstFrame BasicBlock::frame(unsigned int idx) const { return {this->data() + Frame::Size * idx, idx}; } +template +BasicFrame BasicBlock::toc() { + return m_toc_entry; +} + +template +ConstFrame BasicBlock::toc() const { + return m_toc_entry; +} + template std::vector BasicBlock::icon_palette() const { return extract_palette(frame(0));