From 26e90a99cd25685ee96184a8e21ff010913d8895 Mon Sep 17 00:00:00 2001 From: Hamish Milne Date: Fri, 3 Jan 2020 17:19:59 +0000 Subject: [PATCH] Added basic UI; misc memory fixes --- TODO | 13 +++++++++---- src/citra_qt/main.cpp | 24 ++++++++++++++++++++++++ src/citra_qt/main.h | 2 ++ src/citra_qt/main.ui | 18 ++++++++++++++++++ src/common/CMakeLists.txt | 1 - src/core/hle/kernel/config_mem.h | 3 +-- src/core/hle/kernel/ipc.cpp | 12 ++++++------ src/core/hle/kernel/ipc.h | 12 +++++------- src/core/hle/kernel/process.cpp | 2 +- src/core/hle/kernel/process.h | 2 +- src/core/hw/gpu.h | 3 +-- src/core/memory.cpp | 19 ++++++++----------- src/core/memory.h | 15 ++++++++++++++- 13 files changed, 90 insertions(+), 36 deletions(-) diff --git a/TODO b/TODO index bc4003d44..ad64a0084 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,11 @@ ☐ Save/load UI + ✔ Basic version @done(20-01-03 15:27) + ☐ Multiple slots etc. ✔ CPU @done(19-08-13 15:41) ✔ Memory @done(19-08-13 15:41) ☐ Page tables - ☐ Skip N3DS RAM if unused + ✘ Skip N3DS RAM if unused @cancelled(20-01-03 15:26) + Since no n3ds support, leave this for now ✔ DSP @done(19-12-28 16:57) Memory only ✔ Service manager @started(19-12-23 00:36) @done(19-12-23 11:38) @lasted(11h2m3s) @@ -67,14 +70,16 @@ ✔ Mutex @done(19-08-13 16:43) ✔ Object @done(19-08-13 15:41) ✔ Process @started(19-08-13 16:43) @done(19-12-22 18:41) - ☐ Code set @started(19-12-22 18:41) + ✔ Code set @started(19-12-22 18:41) @done(20-01-03 15:15) @lasted(1w4d20h34m2s) Needs a way to reference loaded images (so we don't serialize the entire ROM as well) + ☐ Serialize codeset with an apploader reference instead ✔ Resource limit @done(19-08-13 16:43) ✔ Semaphore @done(19-08-13 16:44) ✔ Server port @done(19-08-13 16:44) ✔ Server session @done(19-08-13 16:44) - ☐ Mapped buffer context - This may not be needed! + ✔ Mapped buffer context @done(20-01-03 15:25) + This is needed because IPC can take as long as it takes + Changed the unique_ptr to vector ✔ Session @done(19-08-13 16:44) ☐ Shared memory @started(19-12-22 21:20) Need to figure out backing memory (a u8*) diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index daccbb083..08e3cac02 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include #include #include @@ -606,6 +607,8 @@ void GMainWindow::ConnectMenuEvents() { &GMainWindow::OnMenuReportCompatibility); connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); connect(ui.action_Cheats, &QAction::triggered, this, &GMainWindow::OnCheats); + connect(ui.action_Save, &QAction::triggered, this, &GMainWindow::OnSave); + connect(ui.action_Load, &QAction::triggered, this, &GMainWindow::OnLoad); // View connect(ui.action_Single_Window_Mode, &QAction::triggered, this, @@ -1033,6 +1036,8 @@ void GMainWindow::ShutdownGame() { ui.action_Stop->setEnabled(false); ui.action_Restart->setEnabled(false); ui.action_Cheats->setEnabled(false); + ui.action_Save->setEnabled(false); + ui.action_Load->setEnabled(false); ui.action_Load_Amiibo->setEnabled(false); ui.action_Remove_Amiibo->setEnabled(false); ui.action_Report_Compatibility->setEnabled(false); @@ -1343,6 +1348,8 @@ void GMainWindow::OnStartGame() { ui.action_Stop->setEnabled(true); ui.action_Restart->setEnabled(true); ui.action_Cheats->setEnabled(true); + ui.action_Save->setEnabled(true); + ui.action_Load->setEnabled(true); ui.action_Load_Amiibo->setEnabled(true); ui.action_Report_Compatibility->setEnabled(true); ui.action_Enable_Frame_Advancing->setEnabled(true); @@ -1496,6 +1503,23 @@ void GMainWindow::OnCheats() { cheat_dialog.exec(); } +void GMainWindow::OnSave() { + Core::System& system{Core::System::GetInstance()}; + auto fs = std::ofstream("save0.citrasave"); + emu_thread->SetRunning(false); + Core::System::GetInstance().Save(fs); + emu_thread->SetRunning(true); +} + +void GMainWindow::OnLoad() { + if (QFileInfo("save0.citrasave").exists()) { + auto fs = std::ifstream("save0.citrasave"); + emu_thread->SetRunning(false); + Core::System::GetInstance().Load(fs); + emu_thread->SetRunning(true); + } +} + void GMainWindow::OnConfigure() { ConfigureDialog configureDialog(this, hotkey_registry, !multiplayer_state->IsHostingPublicRoom()); diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 91d7eed1b..1858d5988 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -163,6 +163,8 @@ private slots: void OnStartGame(); void OnPauseGame(); void OnStopGame(); + void OnSave(); + void OnLoad(); void OnMenuReportCompatibility(); /// Called whenever a user selects a game in the game list widget. void OnGameListLoadFile(QString game_path); diff --git a/src/citra_qt/main.ui b/src/citra_qt/main.ui index 6011b0e7f..c0c38e4c8 100644 --- a/src/citra_qt/main.ui +++ b/src/citra_qt/main.ui @@ -88,6 +88,8 @@ + + @@ -217,6 +219,22 @@ &Stop + + + false + + + Save + + + + + false + + + Load + + FAQ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 39ddffbcc..c6294c464 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -86,7 +86,6 @@ add_library(common STATIC misc.cpp param_package.cpp param_package.h - pod.h quaternion.h ring_buffer.h scm_rev.cpp diff --git a/src/core/hle/kernel/config_mem.h b/src/core/hle/kernel/config_mem.h index e4e895516..ef1c889a0 100644 --- a/src/core/hle/kernel/config_mem.h +++ b/src/core/hle/kernel/config_mem.h @@ -61,8 +61,7 @@ private: friend class boost::serialization::access; template void serialize(Archive& ar, const unsigned int file_version) { - auto o_config_mem = boost::serialization::binary_object(&config_mem, sizeof(config_mem)); - ar& o_config_mem; + ar& boost::serialization::make_binary_object(&config_mem, sizeof(config_mem)); } }; diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp index 3dacb9831..e45b87e49 100644 --- a/src/core/hle/kernel/ipc.cpp +++ b/src/core/hle/kernel/ipc.cpp @@ -193,19 +193,19 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy // TODO(Subv): Perform permission checks. // Reserve a page of memory before the mapped buffer - auto reserve_buffer = std::make_unique(Memory::PAGE_SIZE); + auto reserve_buffer = std::vector(Memory::PAGE_SIZE); dst_process->vm_manager.MapBackingMemoryToBase( - Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.get(), + Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.data(), Memory::PAGE_SIZE, Kernel::MemoryState::Reserved); - auto buffer = std::make_unique(num_pages * Memory::PAGE_SIZE); - memory.ReadBlock(*src_process, source_address, buffer.get() + page_offset, size); + auto buffer = std::vector(num_pages * Memory::PAGE_SIZE); + memory.ReadBlock(*src_process, source_address, buffer.data() + page_offset, size); // Map the page(s) into the target process' address space. target_address = dst_process->vm_manager .MapBackingMemoryToBase(Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, - buffer.get(), num_pages * Memory::PAGE_SIZE, + buffer.data(), num_pages * Memory::PAGE_SIZE, Kernel::MemoryState::Shared) .Unwrap(); @@ -213,7 +213,7 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy // Reserve a page of memory after the mapped buffer dst_process->vm_manager.MapBackingMemoryToBase( - Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.get(), + Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer.data(), Memory::PAGE_SIZE, Kernel::MemoryState::Reserved); mapped_buffer_context.push_back({permissions, size, source_address, diff --git a/src/core/hle/kernel/ipc.h b/src/core/hle/kernel/ipc.h index 2c69617d4..f9fd1a00e 100644 --- a/src/core/hle/kernel/ipc.h +++ b/src/core/hle/kernel/ipc.h @@ -6,7 +6,7 @@ #include #include -#include +#include #include "common/common_types.h" #include "core/hle/ipc.h" #include "core/hle/kernel/thread.h" @@ -25,8 +25,8 @@ struct MappedBufferContext { VAddr source_address; VAddr target_address; - std::unique_ptr buffer; - std::unique_ptr reserve_buffer; + std::vector buffer; + std::vector reserve_buffer; private: template @@ -35,10 +35,8 @@ private: ar& size; ar& source_address; ar& target_address; - // TODO: Check whether we need these. If we do, add a field for the size and/or change to a - // 'vector' - // ar & buffer; - // ar & reserve_buffer; + ar& buffer; + ar& reserve_buffer; } friend class boost::serialization::access; }; diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 78b695e97..18de2cd91 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -29,7 +29,7 @@ template void Process::serialize(Archive& ar, const unsigned int file_version) { ar& boost::serialization::base_object(*this); ar& handle_table; - ar& codeset; + ar& codeset; // TODO: Replace with apploader reference ar& resource_limit; ar& svc_access_mask; ar& handle_table_size; diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index f9aa76c67..576cf7e15 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -133,7 +133,7 @@ private: template void serialize(Archive& ar, const unsigned int file_version) { ar& boost::serialization::base_object(*this); - // TODO: memory reference + ar& memory; ar& segments; ar& entrypoint; ar& name; diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index fcf7a3137..9169bf9ae 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h @@ -301,8 +301,7 @@ private: template void serialize(Archive& ar, const unsigned int) { - auto obj = boost::serialization::binary_object(this, sizeof(Regs)); - ar& obj; + ar& boost::serialization::make_binary_object(this, sizeof(Regs)); } friend class boost::serialization::access; }; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 6a41ca957..92bce0b69 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -84,18 +84,15 @@ private: friend class boost::serialization::access; template void serialize(Archive& ar, const unsigned int file_version) { - // TODO: Skip n3ds ram when not used? - auto s_fcram = boost::serialization::binary_object(fcram.get(), Memory::FCRAM_N3DS_SIZE); - auto s_vram = boost::serialization::binary_object(vram.get(), Memory::VRAM_SIZE); - auto s_extra = - boost::serialization::binary_object(n3ds_extra_ram.get(), Memory::N3DS_EXTRA_RAM_SIZE); - ar& s_fcram; - ar& s_vram; - ar& s_extra; + ar& boost::serialization::make_binary_object(fcram.get(), Memory::FCRAM_N3DS_SIZE); + ar& boost::serialization::make_binary_object(vram.get(), Memory::VRAM_SIZE); + // TODO: When n3ds support is added, put this back in + // ar& boost::serialization::make_binary_object(n3ds_extra_ram.get(), + // Memory::N3DS_EXTRA_RAM_SIZE); + ar& current_page_table; ar& cache_marker; - // TODO: How the hell to do page tables.. - // ar & page_table_list; - // ar & current_page_table; + ar& page_table_list; + // dsp is set from Core::System at startup } }; diff --git a/src/core/memory.h b/src/core/memory.h index aac57af26..564191d89 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -9,7 +9,9 @@ #include #include #include -#include "boost/serialization/access.hpp" +#include +#include +#include #include "common/common_types.h" #include "core/mmio.h" @@ -54,12 +56,14 @@ struct SpecialRegion { u32 size; MMIORegionPointer handler; +private: template void serialize(Archive& ar, const unsigned int file_version) { ar& base; ar& size; ar& handler; } + friend class boost::serialization::access; }; /** @@ -86,6 +90,15 @@ struct PageTable { * the corresponding entry in `pointers` MUST be set to null. */ std::array attributes; + +private: + template + void serialize(Archive& ar, const unsigned int) { + // TODO: Pointers; same as VMA backing regions we need to serialize the u8* + ar& special_regions; + ar& attributes; + } + friend class boost::serialization::access; }; /// Physical memory regions as seen from the ARM11