diff --git a/src/Cafe/OS/libs/nsyshid/Dimensions.cpp b/src/Cafe/OS/libs/nsyshid/Dimensions.cpp index 7139fe6b8..4547ce85c 100644 --- a/src/Cafe/OS/libs/nsyshid/Dimensions.cpp +++ b/src/Cafe/OS/libs/nsyshid/Dimensions.cpp @@ -508,16 +508,16 @@ namespace nsyshid bool responded = false; do { - if (!m_figureAddedRemovedResponses.empty()) + if (!m_queries.empty()) { - response = m_figureAddedRemovedResponses.front(); - m_figureAddedRemovedResponses.pop(); + response = m_queries.front(); + m_queries.pop(); responded = true; } - else if (!m_queries.empty()) + else if (!m_figureAddedRemovedResponses.empty() && m_isAwake) { - response = m_queries.front(); - m_queries.pop(); + response = m_figureAddedRemovedResponses.front(); + m_figureAddedRemovedResponses.pop(); responded = true; } else @@ -609,10 +609,9 @@ namespace nsyshid m_queries.push(q_result); } - uint32 DimensionsUSB::LoadFigure(const std::array& buf, std::unique_ptr file, uint8 pad, uint8 index, bool lock) + uint32 DimensionsUSB::LoadFigure(const std::array& buf, std::unique_ptr file, uint8 pad, uint8 index) { - if (lock) - std::shared_lock lock(m_dimensionsMutex); + std::lock_guard lock(m_dimensionsMutex); const uint32 id = GetFigureId(buf); @@ -628,42 +627,70 @@ namespace nsyshid figureChangeResponse[13] = GenerateChecksum(figureChangeResponse, 13); m_figureAddedRemovedResponses.push(figureChangeResponse); - if (lock) - std::shared_lock unlock(m_dimensionsMutex); - return id; } - bool DimensionsUSB::RemoveFigure(uint8 pad, uint8 index, bool save, bool lock) + bool DimensionsUSB::RemoveFigure(uint8 pad, uint8 index, bool fullRemove) { + std::lock_guard lock(m_dimensionsMutex); + DimensionsMini& figure = GetFigureByIndex(index); if (figure.index == 255) - { return false; - } - - if (lock) - std::shared_lock lock(m_dimensionsMutex); // When a figure is removed from the toypad, respond to the game with the pad they were removed from, their index, // the direction (0x01 in byte 6 for removed) and their UID - std::array figureChangeResponse = {0x56, 0x0b, figure.pad, 0x00, figure.index, 0x01, - figure.data[0], figure.data[1], figure.data[2], - figure.data[4], figure.data[5], figure.data[6], figure.data[7]}; - if (save) + if (fullRemove) { + std::array figureChangeResponse = {0x56, 0x0b, figure.pad, 0x00, figure.index, 0x01, + figure.data[0], figure.data[1], figure.data[2], + figure.data[4], figure.data[5], figure.data[6], figure.data[7]}; + figureChangeResponse[13] = GenerateChecksum(figureChangeResponse, 13); + m_figureAddedRemovedResponses.push(figureChangeResponse); figure.Save(); figure.dimFile.reset(); } + figure.index = 255; figure.pad = 255; figure.id = 0; - memcpy(&figureChangeResponse[6], figure.data.data(), 7); + + return true; + } + + bool DimensionsUSB::TempRemove(uint8 index) + { + std::lock_guard lock(m_dimensionsMutex); + + DimensionsMini& figure = GetFigureByIndex(index); + if (figure.index == 255) + return false; + + // Send a response to the game that the figure has been "Picked up" from existing slot, + // until either the movement is cancelled, or user chooses a space to move to + std::array figureChangeResponse = {0x56, 0x0b, figure.pad, 0x00, figure.index, 0x01, + figure.data[0], figure.data[1], figure.data[2], + figure.data[4], figure.data[5], figure.data[6], figure.data[7]}; + figureChangeResponse[13] = GenerateChecksum(figureChangeResponse, 13); m_figureAddedRemovedResponses.push(figureChangeResponse); + } + + bool DimensionsUSB::CancelRemove(uint8 index) + { + std::lock_guard lock(m_dimensionsMutex); + + DimensionsMini& figure = GetFigureByIndex(index); + if (figure.index == 255) + return false; - if (lock) - std::shared_lock unlock(m_dimensionsMutex); + // Cancel the previous movement of the figure + std::array figureChangeResponse = {0x56, 0x0b, figure.pad, 0x00, figure.index, 0x00, + figure.data[0], figure.data[1], figure.data[2], + figure.data[4], figure.data[5], figure.data[6], figure.data[7]}; + + figureChangeResponse[13] = GenerateChecksum(figureChangeResponse, 13); + m_figureAddedRemovedResponses.push(figureChangeResponse); return true; } @@ -672,12 +699,11 @@ namespace nsyshid { FileStream* dimFile(FileStream::createFile2(pathName)); if (!dimFile) - { return false; - } + std::array fileData{}; RandomUID(fileData); - fileData[7] = id & 0xFF; + fileData[3] = id & 0xFF; std::array uid = {fileData[0], fileData[1], fileData[2], fileData[4], fileData[5], fileData[6], fileData[7]}; @@ -715,32 +741,24 @@ namespace nsyshid bool DimensionsUSB::MoveFigure(uint8 pad, uint8 index, uint8 oldPad, uint8 oldIndex) { - std::lock_guard lock(m_dimensionsMutex); - if (oldIndex == index) { // Don't bother removing and loading again, just send response to the game - const DimensionsMini& figure = GetFigureByIndex(oldIndex); - std::array figureRemoveResponse = {0x56, 0x0b, pad, 0x00, figure.index, 0x01, figure.data[0], figure.data[1], figure.data[2], figure.data[4], figure.data[5], figure.data[6], figure.data[7]}; - figureRemoveResponse[13] = GenerateChecksum(figureRemoveResponse, 13); - std::array figureAddResponse = {0x56, 0x0b, pad, 0x00, figure.index, 0x00, figure.data[0], figure.data[1], figure.data[2], figure.data[4], figure.data[5], figure.data[6], figure.data[7]}; - figureAddResponse[13] = GenerateChecksum(figureAddResponse, 13); - m_figureAddedRemovedResponses.push(std::move(figureRemoveResponse)); - m_figureAddedRemovedResponses.push(std::move(figureAddResponse)); + CancelRemove(index); return true; } // When moving figures between spaces on the toypad, remove any figure from the space they are moving to, // then remove them from their current space, then load them to the space they are moving to - RemoveFigure(pad, index, true, false); + RemoveFigure(pad, index, true); DimensionsMini& figure = GetFigureByIndex(oldIndex); const std::array data = figure.data; std::unique_ptr inFile = std::move(figure.dimFile); - RemoveFigure(oldPad, oldIndex, false, false); + RemoveFigure(oldPad, oldIndex, false); - LoadFigure(data, std::move(inFile), pad, index, false); + LoadFigure(data, std::move(inFile), pad, index); return true; } @@ -788,6 +806,9 @@ namespace nsyshid // Copy encrypted value to response data memcpy(&replyBuf[3], encrypted.data(), encrypted.size()); replyBuf[11] = GenerateChecksum(replyBuf, 11); + + if (!m_isAwake) + m_isAwake = true; } void DimensionsUSB::InitializeRNG(uint32 seed) @@ -1076,7 +1097,7 @@ namespace nsyshid void DimensionsUSB::RandomUID(std::array& uid_buffer) { uid_buffer[0] = 0x04; - uid_buffer[6] = 0x80; + uid_buffer[7] = 0x80; std::random_device rd; std::mt19937 mt(rd()); @@ -1084,9 +1105,9 @@ namespace nsyshid uid_buffer[1] = dist(mt); uid_buffer[2] = dist(mt); - uid_buffer[3] = dist(mt); uid_buffer[4] = dist(mt); uid_buffer[5] = dist(mt); + uid_buffer[6] = dist(mt); } uint8 DimensionsUSB::GenerateChecksum(const std::array& data, diff --git a/src/Cafe/OS/libs/nsyshid/Dimensions.h b/src/Cafe/OS/libs/nsyshid/Dimensions.h index 0902c8327..d5a2a5292 100644 --- a/src/Cafe/OS/libs/nsyshid/Dimensions.h +++ b/src/Cafe/OS/libs/nsyshid/Dimensions.h @@ -1,4 +1,4 @@ -#include +#include #include "nsyshid.h" #include "Backend.h" @@ -65,8 +65,10 @@ namespace nsyshid void GetModel(std::span buf, uint8 sequence, std::array& replyBuf); - bool RemoveFigure(uint8 pad, uint8 index, bool save, bool lock); - uint32 LoadFigure(const std::array& buf, std::unique_ptr file, uint8 pad, uint8 index, bool lock); + bool RemoveFigure(uint8 pad, uint8 index, bool fullRemove); + bool TempRemove(uint8 index); + bool CancelRemove(uint8 index); + uint32 LoadFigure(const std::array& buf, std::unique_ptr file, uint8 pad, uint8 index); bool CreateFigure(fs::path pathName, uint32 id); bool MoveFigure(uint8 pad, uint8 index, uint8 oldPad, uint8 oldIndex); static std::map GetListMinifigs(); @@ -74,7 +76,7 @@ namespace nsyshid std::string FindFigure(uint32 figNum); protected: - std::shared_mutex m_dimensionsMutex; + std::mutex m_dimensionsMutex; std::array m_figures{}; private: @@ -96,6 +98,8 @@ namespace nsyshid uint32 m_randomC; uint32 m_randomD; + bool m_isAwake = false; + std::queue> m_figureAddedRemovedResponses; std::queue> m_queries; }; diff --git a/src/gui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp b/src/gui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp index d8ec111e3..af1e4d153 100644 --- a/src/gui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp +++ b/src/gui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp @@ -638,14 +638,14 @@ void EmulatedUSBDeviceFrame::LoadMinifigPath(wxString path_name, uint8 pad, uint ClearMinifig(pad, index); - uint32 id = nsyshid::g_dimensionstoypad.LoadFigure(file_data, std::move(dim_file), pad, index, true); + uint32 id = nsyshid::g_dimensionstoypad.LoadFigure(file_data, std::move(dim_file), pad, index); m_dimensionSlots[index]->ChangeValue(nsyshid::g_dimensionstoypad.FindFigure(id)); m_dimSlots[index] = id; } void EmulatedUSBDeviceFrame::ClearMinifig(uint8 pad, uint8 index) { - nsyshid::g_dimensionstoypad.RemoveFigure(pad, index, true, true); + nsyshid::g_dimensionstoypad.RemoveFigure(pad, index, true); m_dimensionSlots[index]->ChangeValue("None"); m_dimSlots[index] = std::nullopt; } @@ -662,7 +662,11 @@ void EmulatedUSBDeviceFrame::CreateMinifig(uint8 pad, uint8 index) void EmulatedUSBDeviceFrame::MoveMinifig(uint8 pad, uint8 index) { + if (!m_dimSlots[index]) + return; + MoveDimensionFigureDialog move_dlg(this, index); + nsyshid::g_dimensionstoypad.TempRemove(index); move_dlg.ShowModal(); if (move_dlg.GetReturnCode() == 1) { @@ -675,6 +679,10 @@ void EmulatedUSBDeviceFrame::MoveMinifig(uint8 pad, uint8 index) m_dimensionSlots[index]->ChangeValue("None"); } } + else + { + nsyshid::g_dimensionstoypad.CancelRemove(index); + } } CreateDimensionFigureDialog::CreateDimensionFigureDialog(wxWindow* parent) @@ -778,8 +786,8 @@ MoveDimensionFigureDialog::MoveDimensionFigureDialog(EmulatedUSBDeviceFrame* par sizer->Add(new wxStaticText(this, wxID_ANY, ""), 1, wxALL, 5); sizer->Add(AddMinifigSlot(3, 2, currentIndex, ids[2]), 1, wxALL, 5); - sizer->Add(AddMinifigSlot(1, 3, currentIndex, ids[3]), 1, wxALL, 5); - sizer->Add(AddMinifigSlot(1, 4, currentIndex, ids[4]), 1, wxALL, 5); + sizer->Add(AddMinifigSlot(2, 3, currentIndex, ids[3]), 1, wxALL, 5); + sizer->Add(AddMinifigSlot(2, 4, currentIndex, ids[4]), 1, wxALL, 5); sizer->Add(new wxStaticText(this, wxID_ANY, ""), 1, wxALL, 5); sizer->Add(AddMinifigSlot(3, 5, currentIndex, ids[5]), 1, wxALL, 5); sizer->Add(AddMinifigSlot(3, 6, currentIndex, ids[6]), 1, wxALL, 5);