diff --git a/rpcs3/Emu/Io/Skylander.cpp b/rpcs3/Emu/Io/Skylander.cpp index f7842f237b..cd94761e41 100644 --- a/rpcs3/Emu/Io/Skylander.cpp +++ b/rpcs3/Emu/Io/Skylander.cpp @@ -85,6 +85,11 @@ void usb_device_skylander::control_transfer(u8 bmRequestType, u8 bRequest, u16 w // Set LEDs colour verify(HERE), buf_size == 4; break; + case 'M': + q_result[0] = 0x4D; + q_result[1] = buf[1]; + q_queries.push(q_result); + break; case 'Q': // Queries a block verify(HERE), buf_size == 3; diff --git a/rpcs3/rpcs3qt/skylander_dialog.cpp b/rpcs3/rpcs3qt/skylander_dialog.cpp index 19b536666f..ee38310887 100644 --- a/rpcs3/rpcs3qt/skylander_dialog.cpp +++ b/rpcs3/rpcs3qt/skylander_dialog.cpp @@ -235,15 +235,19 @@ skylander_dialog::skylander_dialog(QWidget* parent) // clang-format off connect(combo_skylist, &QComboBox::currentTextChanged, this, [&]() { + u16 sky_id = combo_skylist->itemData(combo_skylist->currentIndex()).toInt(); + if (sky_id != 0xFFFF) { - std::lock_guard lock(g_skylander.sky_mutex); - u16 sky_id = combo_skylist->itemData(combo_skylist->currentIndex()).toInt(); - if (sky_id != 0xFFFF) { - reinterpret_cast&>(g_skylander.sky_dump[0]) = combo_skylist->itemData(combo_skylist->currentIndex()).toInt() & 0xffff; + std::lock_guard lock(g_skylander.sky_mutex); + reinterpret_cast&>(g_skylander.sky_dump[0]) = combo_skylist->itemData(combo_skylist->currentIndex()).toInt() & 0xffff; reinterpret_cast&>(g_skylander.sky_dump[0x10]) = combo_skylist->itemData(combo_skylist->currentIndex()).toInt() & 0xffff; reinterpret_cast&>(g_skylander.sky_dump[0x1E]) = skylander_crc16(0xFFFF, g_skylander.sky_dump, 0x1E); + } + if (is_initialized()) + { + std::lock_guard lock(g_skylander.sky_mutex); std::array zero_array = {}; for (u32 index = 8; index < 0x40; index++) { @@ -254,9 +258,9 @@ skylander_dialog::skylander_dialog(QWidget* parent) } set_checksums(); - - g_skylander.sky_reload = true; } + + g_skylander.sky_reload = true; } g_skylander.sky_save(); @@ -384,7 +388,7 @@ void skylander_dialog::set_checksums() // Type 4 reinterpret_cast&>(sub_header[0x0]) = 0x0106; - u16 res_crc = skylander_crc16(0xFFFF, sub_header.data(), 16); + u16 res_crc = skylander_crc16(0xFFFF, sub_header.data(), 16); reinterpret_cast&>(sub_header[0x0]) = do_crc_blocks(res_crc, {10, 12, 13}); // Type 3 @@ -397,7 +401,7 @@ void skylander_dialog::set_checksums() reinterpret_cast&>(decrypted_header[0xA]) = res_crc; // Type 2 - res_crc = do_crc_blocks(0xFFFF, {1, 2, 4}); + res_crc = do_crc_blocks(0xFFFF, {1, 2, 4}); reinterpret_cast&>(decrypted_header[0xC]) = res_crc; // Type 1 @@ -409,6 +413,22 @@ void skylander_dialog::set_checksums() } } +bool skylander_dialog::is_initialized() +{ + std::lock_guard lock(g_skylander.sky_mutex); + for (u32 index = 1; index < 0x10; index++) + { + for (u32 subdex = 0; subdex < (0x30 / sizeof(u64)); subdex++) + { + if (reinterpret_cast(g_skylander.sky_dump[(index * 0x40) + (subdex * sizeof(u64))]) != 0) + { + return true; + } + } + } + return false; +} + void skylander_dialog::new_skylander() { const QString file_path = QFileDialog::getSaveFileName(this, tr("Create Skylander File"), cur_sky_file_path, tr("Skylander Object (*.sky);;")); @@ -437,16 +457,7 @@ void skylander_dialog::new_skylander() reinterpret_cast&>(g_skylander.sky_dump[0x1E]) = skylander_crc16(0xFFFF, g_skylander.sky_dump, 0x1E); - std::array zero_array = {}; - for (u32 index = 8; index < 0x40; index++) - { - if ((index + 1) % 4) - { - set_block(index, zero_array); - } - } - - set_checksums(); + // On a new skylander everything is 0'd and no crc apart from the first one is set g_skylander.sky_reload = true; } @@ -481,26 +492,31 @@ void skylander_dialog::load_skylander() void skylander_dialog::update_edits() { // clang-format off - auto widget_enabler = [&](bool status) + auto widget_enabler = [&](bool status_noinit, bool status) { - combo_skylist->setEnabled(status); - edit_skyid->setEnabled(status); + combo_skylist->setEnabled(status_noinit); + edit_skyid->setEnabled(status_noinit); edit_skyxp->setEnabled(status); edit_skymoney->setEnabled(status); - button_update->setEnabled(status); + button_update->setEnabled(status_noinit); }; // clang-format on if (!g_skylander.sky_file) { - widget_enabler(false); + widget_enabler(false, false); return; } - else + + if (!is_initialized()) { - widget_enabler(true); + widget_enabler(true, false); + std::lock_guard lock(g_skylander.sky_mutex); + edit_skyid->setText(QString::number(reinterpret_cast&>(g_skylander.sky_dump[0x10]))); + return; } + widget_enabler(true, true); { std::lock_guard lock(g_skylander.sky_mutex); edit_skyid->setText(QString::number(reinterpret_cast&>(g_skylander.sky_dump[0x10]))); @@ -518,10 +534,10 @@ void skylander_dialog::update_edits() void skylander_dialog::process_edits() { + bool cast_success = false; { std::lock_guard lock(g_skylander.sky_mutex); - bool cast_success = false; u16 skyID = edit_skyid->text().toInt(&cast_success); if (cast_success) { @@ -530,7 +546,11 @@ void skylander_dialog::process_edits() } reinterpret_cast&>(g_skylander.sky_dump[0x1E]) = skylander_crc16(0xFFFF, g_skylander.sky_dump, 0x1E); + } + if (is_initialized()) + { + std::lock_guard lock(g_skylander.sky_mutex); u8 active = get_active_block(); std::array decrypted_header; diff --git a/rpcs3/rpcs3qt/skylander_dialog.h b/rpcs3/rpcs3qt/skylander_dialog.h index 6d0613c44b..45db18ea72 100644 --- a/rpcs3/rpcs3qt/skylander_dialog.h +++ b/rpcs3/rpcs3qt/skylander_dialog.h @@ -20,6 +20,8 @@ public: void operator=(skylander_dialog const&) = delete; protected: + // Checks if the skylander is initialized + bool is_initialized(); // Update the edits from skylander loaded in memory void update_edits(); // Parse edits and apply them to skylander in memory