Various fixes and new features

This commit is contained in:
fearlessTobi 2018-10-12 19:48:24 +02:00
parent 57e39cce9c
commit de437a4269
7 changed files with 121 additions and 10 deletions

View file

@ -489,6 +489,7 @@ void GMainWindow::ConnectMenuEvents() {
connect(ui.action_Install_CIA, &QAction::triggered, this, &GMainWindow::OnMenuInstallCIA); connect(ui.action_Install_CIA, &QAction::triggered, this, &GMainWindow::OnMenuInstallCIA);
connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close); connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close);
connect(ui.action_Load_Amiibo, &QAction::triggered, this, &GMainWindow::OnLoadAmiibo); connect(ui.action_Load_Amiibo, &QAction::triggered, this, &GMainWindow::OnLoadAmiibo);
connect(ui.action_Remove_Amiibo, &QAction::triggered, this, &GMainWindow::OnRemoveAmiibo);
// Emulation // Emulation
connect(ui.action_Start, &QAction::triggered, this, &GMainWindow::OnStartGame); connect(ui.action_Start, &QAction::triggered, this, &GMainWindow::OnStartGame);
@ -825,6 +826,7 @@ 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_Load_Amiibo->setEnabled(false); ui.action_Load_Amiibo->setEnabled(false);
ui.action_Remove_Amiibo->setEnabled(false);
ui.action_Report_Compatibility->setEnabled(false); ui.action_Report_Compatibility->setEnabled(false);
render_window->hide(); render_window->hide();
if (game_list->isEmpty()) if (game_list->isEmpty())
@ -1270,9 +1272,9 @@ void GMainWindow::OnLoadAmiibo() {
const QString file_filter = const QString file_filter =
tr("Amiibo File") + " (" + extensions + ");;" + tr("All Files (*.*)"); tr("Amiibo File") + " (" + extensions + ");;" + tr("All Files (*.*)");
const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), "", file_filter); const QString filename = QFileDialog::getOpenFileName(this, tr("Load Amiibo"), "", file_filter);
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
Core::System& system{Core::System::GetInstance()}; Core::System& system{Core::System::GetInstance()};
Service::SM::ServiceManager& sm = system.ServiceManager(); Service::SM::ServiceManager& sm = system.ServiceManager();
auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u"); auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u");
if (nfc != nullptr) { if (nfc != nullptr) {
@ -1281,11 +1283,27 @@ void GMainWindow::OnLoadAmiibo() {
nfc_module->nfc_filename = filename.toStdString(); nfc_module->nfc_filename = filename.toStdString();
nfc_module->nfc_tag_state = Service::NFC::TagState::TagInRange; nfc_module->nfc_tag_state = Service::NFC::TagState::TagInRange;
nfc_module->tag_in_range_event->Signal(); nfc_module->tag_in_range_event->Signal();
ui.action_Remove_Amiibo->setEnabled(true);
} }
} }
} }
} }
void GMainWindow::OnRemoveAmiibo() {
Core::System& system{Core::System::GetInstance()};
Service::SM::ServiceManager& sm = system.ServiceManager();
auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u");
if (nfc != nullptr) {
auto nfc_module = nfc->GetModule();
if (nfc_module != nullptr) {
nfc_module->nfc_filename = "";
nfc_module->nfc_tag_state = Service::NFC::TagState::TagOutOfRange;
nfc_module->tag_out_of_range_event->Signal();
ui.action_Remove_Amiibo->setEnabled(false);
}
}
}
void GMainWindow::OnToggleFilterBar() { void GMainWindow::OnToggleFilterBar() {
game_list->setFilterVisible(ui.action_Show_Filter_Bar->isChecked()); game_list->setFilterVisible(ui.action_Show_Filter_Bar->isChecked());
if (ui.action_Show_Filter_Bar->isChecked()) { if (ui.action_Show_Filter_Bar->isChecked()) {

View file

@ -167,6 +167,7 @@ private slots:
void OnMenuRecentFile(); void OnMenuRecentFile();
void OnConfigure(); void OnConfigure();
void OnLoadAmiibo(); void OnLoadAmiibo();
void OnRemoveAmiibo();
void OnToggleFilterBar(); void OnToggleFilterBar();
void OnDisplayTitleBars(bool); void OnDisplayTitleBars(bool);
void ToggleFullscreen(); void ToggleFullscreen();

View file

@ -62,7 +62,14 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="menu_recent_files"/> <addaction name="menu_recent_files"/>
<addaction name="separator"/> <addaction name="separator"/>
<widget class="QMenu" name="menu_Amiibo">
<property name="title">
<string>Amiibo</string>
</property>
<addaction name="action_Load_Amiibo"/> <addaction name="action_Load_Amiibo"/>
<addaction name="action_Remove_Amiibo"/>
</widget>
<addaction name="menu_Amiibo"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="action_Exit"/> <addaction name="action_Exit"/>
</widget> </widget>
@ -400,7 +407,15 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Load Amiibo...</string> <string>Load...</string>
</property>
</action>
<action name="action_Remove_Amiibo">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove</string>
</property> </property>
</action> </action>
</widget> </widget>

View file

@ -12,28 +12,49 @@
namespace Service::NFC { namespace Service::NFC {
struct TagInfo { struct TagInfo {
u16 id_offset_size; u16_le id_offset_size;
u8 unk1; u8 unk1;
u8 unk2; u8 unk2;
std::array<u8, 7> uuid; std::array<u8, 7> uuid;
INSERT_PADDING_BYTES(0x1D + 3); INSERT_PADDING_BYTES(0x20);
}; };
static_assert(sizeof(TagInfo) == 0x2C, "TagInfo is an invalid size"); static_assert(sizeof(TagInfo) == 0x2C, "TagInfo is an invalid size");
struct AmiiboConfig { struct AmiiboConfig {
u16 lastwritedate_year; u16_le lastwritedate_year;
u8 lastwritedate_month; u8 lastwritedate_month;
u8 lastwritedate_day; u8 lastwritedate_day;
u16 write_counter; u16_le write_counter;
std::array<u8, 3> characterID; std::array<u8, 3> characterID;
u16 amiiboID; u16_le amiiboID;
u8 type; u8 type;
u8 pagex4_byte3; u8 pagex4_byte3;
u16 appdata_size; u16_le appdata_size;
INSERT_PADDING_BYTES(0x30); INSERT_PADDING_BYTES(0x30);
}; };
static_assert(sizeof(AmiiboConfig) == 0x40, "AmiiboConfig is an invalid size"); static_assert(sizeof(AmiiboConfig) == 0x40, "AmiiboConfig is an invalid size");
struct IdentificationBlockRaw {
u16_le char_id;
u8 char_variant;
u8 figure_type;
u16_be model_number;
u8 series;
INSERT_PADDING_BYTES(0x2F);
};
static_assert(sizeof(IdentificationBlockRaw) == 0x36, "IdentificationBlockRaw is an invalid size");
struct IdentificationBlockReply {
u16_le char_id;
u8 char_variant;
u8 series;
u16_le model_number;
u8 figure_type;
INSERT_PADDING_BYTES(0x2F);
};
static_assert(sizeof(IdentificationBlockReply) == 0x36,
"IdentificationBlockReply is an invalid size");
void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) { void Module::Interface::Initialize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x01, 1, 0); IPC::RequestParser rp(ctx, 0x01, 1, 0);
u8 param = rp.Pop<u8>(); u8 param = rp.Pop<u8>();
@ -96,7 +117,7 @@ void Module::Interface::GetTagInfo(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(12, 0); IPC::RequestBuilder rb = rp.MakeBuilder(12, 0);
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushRaw<TagInfo>(tag_info); rb.PushRaw<TagInfo>(tag_info);
LOG_CRITICAL(Service_NFC, "called"); LOG_WARNING(Service_NFC, "(STUBBED) called");
} }
void Module::Interface::GetAmiiboConfig(Kernel::HLERequestContext& ctx) { void Module::Interface::GetAmiiboConfig(Kernel::HLERequestContext& ctx) {
@ -111,7 +132,7 @@ void Module::Interface::GetAmiiboConfig(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(17, 0); IPC::RequestBuilder rb = rp.MakeBuilder(17, 0);
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.PushRaw<AmiiboConfig>(amiibo_config); rb.PushRaw<AmiiboConfig>(amiibo_config);
LOG_CRITICAL(Service_NFC, "called"); LOG_WARNING(Service_NFC, "(STUBBED) called");
} }
void Module::Interface::StopTagScanning(Kernel::HLERequestContext& ctx) { void Module::Interface::StopTagScanning(Kernel::HLERequestContext& ctx) {
@ -180,6 +201,38 @@ void Module::Interface::CommunicationGetStatus(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NFC, "(STUBBED) called"); LOG_DEBUG(Service_NFC, "(STUBBED) called");
} }
void Module::Interface::Unknown0x1A(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x1A, 0, 0);
nfc->nfc_tag_state = TagState::Unknown6;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(RESULT_SUCCESS);
LOG_DEBUG(Service_NFC, "called");
}
void Module::Interface::Unknown0x1B(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx, 0x1B, 0, 0);
IdentificationBlockRaw identification_block_raw{};
auto nfc_file = FileUtil::IOFile(nfc->nfc_filename, "rb");
// go to offset of the Amiibo identification block
nfc_file.Seek(0x54, SEEK_SET);
nfc_file.ReadBytes(&identification_block_raw, 0x7);
IdentificationBlockReply identification_block_reply{};
identification_block_reply.char_id = identification_block_raw.char_id;
identification_block_reply.char_variant = identification_block_raw.char_variant;
identification_block_reply.series = identification_block_raw.series;
identification_block_reply.model_number = identification_block_raw.model_number;
identification_block_reply.figure_type = identification_block_raw.figure_type;
IPC::RequestBuilder rb = rp.MakeBuilder(0x1F, 0);
rb.Push(RESULT_SUCCESS);
rb.PushRaw<IdentificationBlockReply>(identification_block_reply);
LOG_DEBUG(Service_NFC, "called");
}
Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session) Module::Interface::Interface(std::shared_ptr<Module> nfc, const char* name, u32 max_session)
: ServiceFramework(name, max_session), nfc(std::move(nfc)) {} : ServiceFramework(name, max_session), nfc(std::move(nfc)) {}

View file

@ -32,6 +32,7 @@ enum class TagState : u8 {
TagInRange = 3, TagInRange = 3,
TagOutOfRange = 4, TagOutOfRange = 4,
TagDataLoaded = 5, TagDataLoaded = 5,
Unknown6 = 6,
}; };
enum class CommunicationStatus : u8 { enum class CommunicationStatus : u8 {
@ -189,6 +190,25 @@ public:
*/ */
void GetAmiiboConfig(Kernel::HLERequestContext& ctx); void GetAmiiboConfig(Kernel::HLERequestContext& ctx);
/**
* NFC::Unknown0x1A service function
* Inputs:
* 0 : Header code [0x001A0000]
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void Unknown0x1A(Kernel::HLERequestContext& ctx);
/**
* NFC::Unknown0x1B service function
* Inputs:
* 0 : Header code [0x001B0000]
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2-31 : 0x36-byte struct
*/
void Unknown0x1B(Kernel::HLERequestContext& ctx);
private: private:
std::shared_ptr<Module> nfc; std::shared_ptr<Module> nfc;
}; };

View file

@ -33,6 +33,8 @@ NFC_M::NFC_M(std::shared_ptr<Module> nfc) : Module::Interface(std::move(nfc), "n
{0x00170000, nullptr, "GetAmiiboSettings"}, {0x00170000, nullptr, "GetAmiiboSettings"},
{0x00180000, &NFC_M::GetAmiiboConfig, "GetAmiiboConfig"}, {0x00180000, &NFC_M::GetAmiiboConfig, "GetAmiiboConfig"},
{0x00190000, nullptr, "GetAppDataInitStruct"}, {0x00190000, nullptr, "GetAppDataInitStruct"},
{0x001A0000, &NFC_M::Unknown0x1A, "Unknown0x1A"},
{0x001B0000, &NFC_M::Unknown0x1B, "Unknown0x1B"},
// nfc:m // nfc:m
{0x04040A40, nullptr, "SetAmiiboSettings"} {0x04040A40, nullptr, "SetAmiiboSettings"}
// clang-format on // clang-format on

View file

@ -32,6 +32,8 @@ NFC_U::NFC_U(std::shared_ptr<Module> nfc) : Module::Interface(std::move(nfc), "n
{0x00170000, nullptr, "GetAmiiboSettings"}, {0x00170000, nullptr, "GetAmiiboSettings"},
{0x00180000, &NFC_U::GetAmiiboConfig, "GetAmiiboConfig"}, {0x00180000, &NFC_U::GetAmiiboConfig, "GetAmiiboConfig"},
{0x00190000, nullptr, "GetAppDataInitStruct"}, {0x00190000, nullptr, "GetAppDataInitStruct"},
{0x001A0000, &NFC_U::Unknown0x1A, "Unknown0x1A"},
{0x001B0000, &NFC_U::Unknown0x1B, "Unknown0x1B"},
// clang-format on // clang-format on
}; };
RegisterHandlers(functions); RegisterHandlers(functions);