Merge pull request #4209 from zhaowenlan1779/play-coin
service/ptm, citra_qt: Add Play Coins setting
This commit is contained in:
commit
892ca2a94a
|
@ -8,6 +8,7 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
#include "core/hle/service/cfg/cfg.h"
|
||||||
#include "core/hle/service/fs/archive.h"
|
#include "core/hle/service/fs/archive.h"
|
||||||
|
#include "core/hle/service/ptm/ptm.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "ui_configure_system.h"
|
#include "ui_configure_system.h"
|
||||||
|
|
||||||
|
@ -254,9 +255,9 @@ void ConfigureSystem::setConfiguration() {
|
||||||
// Temporarily register archive types and load the config savegame file to memory.
|
// Temporarily register archive types and load the config savegame file to memory.
|
||||||
Service::FS::RegisterArchiveTypes();
|
Service::FS::RegisterArchiveTypes();
|
||||||
cfg = std::make_shared<Service::CFG::Module>();
|
cfg = std::make_shared<Service::CFG::Module>();
|
||||||
|
ReadSystemSettings();
|
||||||
Service::FS::UnregisterArchiveTypes();
|
Service::FS::UnregisterArchiveTypes();
|
||||||
|
|
||||||
ReadSystemSettings();
|
|
||||||
ui->label_disable_info->hide();
|
ui->label_disable_info->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,6 +294,10 @@ void ConfigureSystem::ReadSystemSettings() {
|
||||||
u64 console_id = cfg->GetConsoleUniqueId();
|
u64 console_id = cfg->GetConsoleUniqueId();
|
||||||
ui->label_console_id->setText(
|
ui->label_console_id->setText(
|
||||||
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
|
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
|
||||||
|
|
||||||
|
// set play coin
|
||||||
|
play_coin = Service::PTM::Module::GetPlayCoins();
|
||||||
|
ui->spinBox_play_coins->setValue(play_coin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureSystem::applyConfiguration() {
|
void ConfigureSystem::applyConfiguration() {
|
||||||
|
@ -340,6 +345,15 @@ void ConfigureSystem::applyConfiguration() {
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// apply play coin
|
||||||
|
u16 new_play_coin = static_cast<u16>(ui->spinBox_play_coins->value());
|
||||||
|
if (play_coin != new_play_coin) {
|
||||||
|
// archive types must be registered to set play coins
|
||||||
|
Service::FS::RegisterArchiveTypes();
|
||||||
|
Service::PTM::Module::SetPlayCoins(new_play_coin);
|
||||||
|
Service::FS::UnregisterArchiveTypes();
|
||||||
|
}
|
||||||
|
|
||||||
// update the config savegame if any item is modified.
|
// update the config savegame if any item is modified.
|
||||||
if (modified)
|
if (modified)
|
||||||
cfg->UpdateConfigNANDSavegame();
|
cfg->UpdateConfigNANDSavegame();
|
||||||
|
|
|
@ -47,4 +47,5 @@ private:
|
||||||
int language_index;
|
int language_index;
|
||||||
int sound_index;
|
int sound_index;
|
||||||
u8 country_code;
|
u8 country_code;
|
||||||
|
u16 play_coin;
|
||||||
};
|
};
|
||||||
|
|
|
@ -264,13 +264,27 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_play_coins">
|
||||||
|
<property name="text">
|
||||||
|
<string>Play Coins:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBox_play_coins">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>300</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
<widget class="QLabel" name="label_console_id">
|
<widget class="QLabel" name="label_console_id">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Console ID:</string>
|
<string>Console ID:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="8" column="1">
|
||||||
<widget class="QPushButton" name="button_regenerate_console_id">
|
<widget class="QPushButton" name="button_regenerate_console_id">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
|
|
@ -135,12 +135,12 @@ void Module::Interface::CheckNew3DS(Kernel::HLERequestContext& ctx) {
|
||||||
Service::PTM::CheckNew3DS(rb);
|
Service::PTM::CheckNew3DS(rb);
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Module() {
|
static void WriteGameCoinData(GameCoin gamecoin_data) {
|
||||||
// Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't
|
|
||||||
// exist
|
|
||||||
FileSys::Path archive_path(ptm_shared_extdata_id);
|
FileSys::Path archive_path(ptm_shared_extdata_id);
|
||||||
auto archive_result =
|
auto archive_result =
|
||||||
Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
|
Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
|
||||||
|
|
||||||
|
FileSys::Path gamecoin_path("/gamecoin.dat");
|
||||||
// If the archive didn't exist, create the files inside
|
// If the archive didn't exist, create the files inside
|
||||||
if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) {
|
if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) {
|
||||||
// Format the archive to create the directories
|
// Format the archive to create the directories
|
||||||
|
@ -149,10 +149,12 @@ Module::Module() {
|
||||||
// Open it again to get a valid archive now that the folder exists
|
// Open it again to get a valid archive now that the folder exists
|
||||||
archive_result =
|
archive_result =
|
||||||
Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
|
Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
|
||||||
ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!");
|
// Create the game coin file
|
||||||
|
|
||||||
FileSys::Path gamecoin_path("/gamecoin.dat");
|
|
||||||
Service::FS::CreateFileInArchive(*archive_result, gamecoin_path, sizeof(GameCoin));
|
Service::FS::CreateFileInArchive(*archive_result, gamecoin_path, sizeof(GameCoin));
|
||||||
|
} else {
|
||||||
|
ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!");
|
||||||
|
}
|
||||||
|
|
||||||
FileSys::Mode open_mode = {};
|
FileSys::Mode open_mode = {};
|
||||||
open_mode.write_flag.Assign(1);
|
open_mode.write_flag.Assign(1);
|
||||||
// Open the file and write the default gamecoin information
|
// Open the file and write the default gamecoin information
|
||||||
|
@ -161,10 +163,60 @@ Module::Module() {
|
||||||
if (gamecoin_result.Succeeded()) {
|
if (gamecoin_result.Succeeded()) {
|
||||||
auto gamecoin = std::move(gamecoin_result).Unwrap();
|
auto gamecoin = std::move(gamecoin_result).Unwrap();
|
||||||
gamecoin->backend->Write(0, sizeof(GameCoin), true,
|
gamecoin->backend->Write(0, sizeof(GameCoin), true,
|
||||||
reinterpret_cast<const u8*>(&default_game_coin));
|
reinterpret_cast<const u8*>(&gamecoin_data));
|
||||||
gamecoin->backend->Close();
|
gamecoin->backend->Close();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GameCoin ReadGameCoinData() {
|
||||||
|
FileSys::Path archive_path(ptm_shared_extdata_id);
|
||||||
|
auto archive_result =
|
||||||
|
Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
|
||||||
|
if (!archive_result.Succeeded()) {
|
||||||
|
LOG_ERROR(Service_PTM, "Could not open the PTM SharedExtSaveData archive!");
|
||||||
|
return default_game_coin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileSys::Path gamecoin_path("/gamecoin.dat");
|
||||||
|
FileSys::Mode open_mode = {};
|
||||||
|
open_mode.read_flag.Assign(1);
|
||||||
|
|
||||||
|
auto gamecoin_result =
|
||||||
|
Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode);
|
||||||
|
if (!gamecoin_result.Succeeded()) {
|
||||||
|
LOG_ERROR(Service_PTM, "Could not open the game coin data file!");
|
||||||
|
return default_game_coin;
|
||||||
|
}
|
||||||
|
u16 result;
|
||||||
|
auto gamecoin = std::move(gamecoin_result).Unwrap();
|
||||||
|
GameCoin gamecoin_data;
|
||||||
|
gamecoin->backend->Read(0, sizeof(GameCoin), reinterpret_cast<u8*>(&gamecoin_data));
|
||||||
|
gamecoin->backend->Close();
|
||||||
|
return gamecoin_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module::Module() {
|
||||||
|
// Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't
|
||||||
|
// exist
|
||||||
|
FileSys::Path archive_path(ptm_shared_extdata_id);
|
||||||
|
auto archive_result =
|
||||||
|
Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
|
||||||
|
// If the archive didn't exist, write the default game coin file
|
||||||
|
if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) {
|
||||||
|
WriteGameCoinData(default_game_coin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 Module::GetPlayCoins() {
|
||||||
|
return ReadGameCoinData().total_coins;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::SetPlayCoins(u16 play_coins) {
|
||||||
|
GameCoin game_coin = ReadGameCoinData();
|
||||||
|
game_coin.total_coins = play_coins;
|
||||||
|
// TODO: This may introduce potential race condition if the game is reading the
|
||||||
|
// game coin data at the same time
|
||||||
|
WriteGameCoinData(game_coin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Interface::Interface(std::shared_ptr<Module> ptm, const char* name, u32 max_session)
|
Module::Interface::Interface(std::shared_ptr<Module> ptm, const char* name, u32 max_session)
|
||||||
|
|
|
@ -41,6 +41,8 @@ void CheckNew3DS(IPC::RequestBuilder& rb);
|
||||||
class Module final {
|
class Module final {
|
||||||
public:
|
public:
|
||||||
Module();
|
Module();
|
||||||
|
static u16 GetPlayCoins();
|
||||||
|
static void SetPlayCoins(u16 play_coins);
|
||||||
|
|
||||||
class Interface : public ServiceFramework<Interface> {
|
class Interface : public ServiceFramework<Interface> {
|
||||||
public:
|
public:
|
||||||
|
|
Reference in New Issue