mirror of
https://github.com/Lime3DS/Lime3DS
synced 2024-12-28 01:52:29 -06:00
Added basic UI; misc memory fixes
This commit is contained in:
parent
558e710e17
commit
26e90a99cd
13 changed files with 90 additions and 36 deletions
13
TODO
13
TODO
|
@ -1,8 +1,11 @@
|
||||||
☐ Save/load UI
|
☐ Save/load UI
|
||||||
|
✔ Basic version @done(20-01-03 15:27)
|
||||||
|
☐ Multiple slots etc.
|
||||||
✔ CPU @done(19-08-13 15:41)
|
✔ CPU @done(19-08-13 15:41)
|
||||||
✔ Memory @done(19-08-13 15:41)
|
✔ Memory @done(19-08-13 15:41)
|
||||||
☐ Page tables
|
☐ 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)
|
✔ DSP @done(19-12-28 16:57)
|
||||||
Memory only
|
Memory only
|
||||||
✔ Service manager @started(19-12-23 00:36) @done(19-12-23 11:38) @lasted(11h2m3s)
|
✔ 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)
|
✔ Mutex @done(19-08-13 16:43)
|
||||||
✔ Object @done(19-08-13 15:41)
|
✔ Object @done(19-08-13 15:41)
|
||||||
✔ Process @started(19-08-13 16:43) @done(19-12-22 18: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)
|
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)
|
✔ Resource limit @done(19-08-13 16:43)
|
||||||
✔ Semaphore @done(19-08-13 16:44)
|
✔ Semaphore @done(19-08-13 16:44)
|
||||||
✔ Server port @done(19-08-13 16:44)
|
✔ Server port @done(19-08-13 16:44)
|
||||||
✔ Server session @done(19-08-13 16:44)
|
✔ Server session @done(19-08-13 16:44)
|
||||||
☐ Mapped buffer context
|
✔ Mapped buffer context @done(20-01-03 15:25)
|
||||||
This may not be needed!
|
This is needed because IPC can take as long as it takes
|
||||||
|
Changed the unique_ptr<u8[]> to vector<u8>
|
||||||
✔ Session @done(19-08-13 16:44)
|
✔ Session @done(19-08-13 16:44)
|
||||||
☐ Shared memory @started(19-12-22 21:20)
|
☐ Shared memory @started(19-12-22 21:20)
|
||||||
Need to figure out backing memory (a u8*)
|
Need to figure out backing memory (a u8*)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
|
@ -606,6 +607,8 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
&GMainWindow::OnMenuReportCompatibility);
|
&GMainWindow::OnMenuReportCompatibility);
|
||||||
connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure);
|
connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure);
|
||||||
connect(ui.action_Cheats, &QAction::triggered, this, &GMainWindow::OnCheats);
|
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
|
// View
|
||||||
connect(ui.action_Single_Window_Mode, &QAction::triggered, this,
|
connect(ui.action_Single_Window_Mode, &QAction::triggered, this,
|
||||||
|
@ -1033,6 +1036,8 @@ void GMainWindow::ShutdownGame() {
|
||||||
ui.action_Stop->setEnabled(false);
|
ui.action_Stop->setEnabled(false);
|
||||||
ui.action_Restart->setEnabled(false);
|
ui.action_Restart->setEnabled(false);
|
||||||
ui.action_Cheats->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_Load_Amiibo->setEnabled(false);
|
||||||
ui.action_Remove_Amiibo->setEnabled(false);
|
ui.action_Remove_Amiibo->setEnabled(false);
|
||||||
ui.action_Report_Compatibility->setEnabled(false);
|
ui.action_Report_Compatibility->setEnabled(false);
|
||||||
|
@ -1343,6 +1348,8 @@ void GMainWindow::OnStartGame() {
|
||||||
ui.action_Stop->setEnabled(true);
|
ui.action_Stop->setEnabled(true);
|
||||||
ui.action_Restart->setEnabled(true);
|
ui.action_Restart->setEnabled(true);
|
||||||
ui.action_Cheats->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_Load_Amiibo->setEnabled(true);
|
||||||
ui.action_Report_Compatibility->setEnabled(true);
|
ui.action_Report_Compatibility->setEnabled(true);
|
||||||
ui.action_Enable_Frame_Advancing->setEnabled(true);
|
ui.action_Enable_Frame_Advancing->setEnabled(true);
|
||||||
|
@ -1496,6 +1503,23 @@ void GMainWindow::OnCheats() {
|
||||||
cheat_dialog.exec();
|
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() {
|
void GMainWindow::OnConfigure() {
|
||||||
ConfigureDialog configureDialog(this, hotkey_registry,
|
ConfigureDialog configureDialog(this, hotkey_registry,
|
||||||
!multiplayer_state->IsHostingPublicRoom());
|
!multiplayer_state->IsHostingPublicRoom());
|
||||||
|
|
|
@ -163,6 +163,8 @@ private slots:
|
||||||
void OnStartGame();
|
void OnStartGame();
|
||||||
void OnPauseGame();
|
void OnPauseGame();
|
||||||
void OnStopGame();
|
void OnStopGame();
|
||||||
|
void OnSave();
|
||||||
|
void OnLoad();
|
||||||
void OnMenuReportCompatibility();
|
void OnMenuReportCompatibility();
|
||||||
/// Called whenever a user selects a game in the game list widget.
|
/// Called whenever a user selects a game in the game list widget.
|
||||||
void OnGameListLoadFile(QString game_path);
|
void OnGameListLoadFile(QString game_path);
|
||||||
|
|
|
@ -88,6 +88,8 @@
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_Configure"/>
|
<addaction name="action_Configure"/>
|
||||||
<addaction name="action_Cheats"/>
|
<addaction name="action_Cheats"/>
|
||||||
|
<addaction name="action_Save"/>
|
||||||
|
<addaction name="action_Load"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menu_View">
|
<widget class="QMenu" name="menu_View">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -217,6 +219,22 @@
|
||||||
<string>&Stop</string>
|
<string>&Stop</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_Save">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Save</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_Load">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Load</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="action_FAQ">
|
<action name="action_FAQ">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>FAQ</string>
|
<string>FAQ</string>
|
||||||
|
|
|
@ -86,7 +86,6 @@ add_library(common STATIC
|
||||||
misc.cpp
|
misc.cpp
|
||||||
param_package.cpp
|
param_package.cpp
|
||||||
param_package.h
|
param_package.h
|
||||||
pod.h
|
|
||||||
quaternion.h
|
quaternion.h
|
||||||
ring_buffer.h
|
ring_buffer.h
|
||||||
scm_rev.cpp
|
scm_rev.cpp
|
||||||
|
|
|
@ -61,8 +61,7 @@ private:
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int file_version) {
|
void serialize(Archive& ar, const unsigned int file_version) {
|
||||||
auto o_config_mem = boost::serialization::binary_object(&config_mem, sizeof(config_mem));
|
ar& boost::serialization::make_binary_object(&config_mem, sizeof(config_mem));
|
||||||
ar& o_config_mem;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -193,19 +193,19 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
||||||
// TODO(Subv): Perform permission checks.
|
// TODO(Subv): Perform permission checks.
|
||||||
|
|
||||||
// Reserve a page of memory before the mapped buffer
|
// Reserve a page of memory before the mapped buffer
|
||||||
auto reserve_buffer = std::make_unique<u8[]>(Memory::PAGE_SIZE);
|
auto reserve_buffer = std::vector<u8>(Memory::PAGE_SIZE);
|
||||||
dst_process->vm_manager.MapBackingMemoryToBase(
|
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);
|
Memory::PAGE_SIZE, Kernel::MemoryState::Reserved);
|
||||||
|
|
||||||
auto buffer = std::make_unique<u8[]>(num_pages * Memory::PAGE_SIZE);
|
auto buffer = std::vector<u8>(num_pages * Memory::PAGE_SIZE);
|
||||||
memory.ReadBlock(*src_process, source_address, buffer.get() + page_offset, size);
|
memory.ReadBlock(*src_process, source_address, buffer.data() + page_offset, size);
|
||||||
|
|
||||||
// Map the page(s) into the target process' address space.
|
// Map the page(s) into the target process' address space.
|
||||||
target_address =
|
target_address =
|
||||||
dst_process->vm_manager
|
dst_process->vm_manager
|
||||||
.MapBackingMemoryToBase(Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE,
|
.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)
|
Kernel::MemoryState::Shared)
|
||||||
.Unwrap();
|
.Unwrap();
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
||||||
|
|
||||||
// Reserve a page of memory after the mapped buffer
|
// Reserve a page of memory after the mapped buffer
|
||||||
dst_process->vm_manager.MapBackingMemoryToBase(
|
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);
|
Memory::PAGE_SIZE, Kernel::MemoryState::Reserved);
|
||||||
|
|
||||||
mapped_buffer_context.push_back({permissions, size, source_address,
|
mapped_buffer_context.push_back({permissions, size, source_address,
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/serialization/unique_ptr.hpp>
|
#include <boost/serialization/vector.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/ipc.h"
|
#include "core/hle/ipc.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
|
@ -25,8 +25,8 @@ struct MappedBufferContext {
|
||||||
VAddr source_address;
|
VAddr source_address;
|
||||||
VAddr target_address;
|
VAddr target_address;
|
||||||
|
|
||||||
std::unique_ptr<u8[]> buffer;
|
std::vector<u8> buffer;
|
||||||
std::unique_ptr<u8[]> reserve_buffer;
|
std::vector<u8> reserve_buffer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
|
@ -35,10 +35,8 @@ private:
|
||||||
ar& size;
|
ar& size;
|
||||||
ar& source_address;
|
ar& source_address;
|
||||||
ar& target_address;
|
ar& target_address;
|
||||||
// TODO: Check whether we need these. If we do, add a field for the size and/or change to a
|
ar& buffer;
|
||||||
// 'vector'
|
ar& reserve_buffer;
|
||||||
// ar & buffer;
|
|
||||||
// ar & reserve_buffer;
|
|
||||||
}
|
}
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,7 +29,7 @@ template <class Archive>
|
||||||
void Process::serialize(Archive& ar, const unsigned int file_version) {
|
void Process::serialize(Archive& ar, const unsigned int file_version) {
|
||||||
ar& boost::serialization::base_object<Object>(*this);
|
ar& boost::serialization::base_object<Object>(*this);
|
||||||
ar& handle_table;
|
ar& handle_table;
|
||||||
ar& codeset;
|
ar& codeset; // TODO: Replace with apploader reference
|
||||||
ar& resource_limit;
|
ar& resource_limit;
|
||||||
ar& svc_access_mask;
|
ar& svc_access_mask;
|
||||||
ar& handle_table_size;
|
ar& handle_table_size;
|
||||||
|
|
|
@ -133,7 +133,7 @@ private:
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int file_version) {
|
void serialize(Archive& ar, const unsigned int file_version) {
|
||||||
ar& boost::serialization::base_object<Object>(*this);
|
ar& boost::serialization::base_object<Object>(*this);
|
||||||
// TODO: memory reference
|
ar& memory;
|
||||||
ar& segments;
|
ar& segments;
|
||||||
ar& entrypoint;
|
ar& entrypoint;
|
||||||
ar& name;
|
ar& name;
|
||||||
|
|
|
@ -301,8 +301,7 @@ private:
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int) {
|
||||||
auto obj = boost::serialization::binary_object(this, sizeof(Regs));
|
ar& boost::serialization::make_binary_object(this, sizeof(Regs));
|
||||||
ar& obj;
|
|
||||||
}
|
}
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,18 +84,15 @@ private:
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int file_version) {
|
void serialize(Archive& ar, const unsigned int file_version) {
|
||||||
// TODO: Skip n3ds ram when not used?
|
ar& boost::serialization::make_binary_object(fcram.get(), Memory::FCRAM_N3DS_SIZE);
|
||||||
auto s_fcram = boost::serialization::binary_object(fcram.get(), Memory::FCRAM_N3DS_SIZE);
|
ar& boost::serialization::make_binary_object(vram.get(), Memory::VRAM_SIZE);
|
||||||
auto s_vram = boost::serialization::binary_object(vram.get(), Memory::VRAM_SIZE);
|
// TODO: When n3ds support is added, put this back in
|
||||||
auto s_extra =
|
// ar& boost::serialization::make_binary_object(n3ds_extra_ram.get(),
|
||||||
boost::serialization::binary_object(n3ds_extra_ram.get(), Memory::N3DS_EXTRA_RAM_SIZE);
|
// Memory::N3DS_EXTRA_RAM_SIZE);
|
||||||
ar& s_fcram;
|
ar& current_page_table;
|
||||||
ar& s_vram;
|
|
||||||
ar& s_extra;
|
|
||||||
ar& cache_marker;
|
ar& cache_marker;
|
||||||
// TODO: How the hell to do page tables..
|
ar& page_table_list;
|
||||||
// ar & page_table_list;
|
// dsp is set from Core::System at startup
|
||||||
// ar & current_page_table;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "boost/serialization/access.hpp"
|
#include <boost/serialization/access.hpp>
|
||||||
|
#include <boost/serialization/array.hpp>
|
||||||
|
#include <boost/serialization/vector.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/mmio.h"
|
#include "core/mmio.h"
|
||||||
|
|
||||||
|
@ -54,12 +56,14 @@ struct SpecialRegion {
|
||||||
u32 size;
|
u32 size;
|
||||||
MMIORegionPointer handler;
|
MMIORegionPointer handler;
|
||||||
|
|
||||||
|
private:
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int file_version) {
|
void serialize(Archive& ar, const unsigned int file_version) {
|
||||||
ar& base;
|
ar& base;
|
||||||
ar& size;
|
ar& size;
|
||||||
ar& handler;
|
ar& handler;
|
||||||
}
|
}
|
||||||
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,6 +90,15 @@ struct PageTable {
|
||||||
* the corresponding entry in `pointers` MUST be set to null.
|
* the corresponding entry in `pointers` MUST be set to null.
|
||||||
*/
|
*/
|
||||||
std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes;
|
std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <class Archive>
|
||||||
|
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
|
/// Physical memory regions as seen from the ARM11
|
||||||
|
|
Loading…
Reference in a new issue