Skip to content

Commit

Permalink
Better mutexes and Move Methods
Browse files Browse the repository at this point in the history
  • Loading branch information
deReeperJosh committed Oct 21, 2024
1 parent 73864db commit 62d3742
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 50 deletions.
105 changes: 63 additions & 42 deletions src/Cafe/OS/libs/nsyshid/Dimensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -609,10 +609,9 @@ namespace nsyshid
m_queries.push(q_result);
}

uint32 DimensionsUSB::LoadFigure(const std::array<uint8, 0x2D * 0x04>& buf, std::unique_ptr<FileStream> file, uint8 pad, uint8 index, bool lock)
uint32 DimensionsUSB::LoadFigure(const std::array<uint8, 0x2D * 0x04>& buf, std::unique_ptr<FileStream> file, uint8 pad, uint8 index)
{
if (lock)
std::shared_lock lock(m_dimensionsMutex);
std::lock_guard lock(m_dimensionsMutex);

const uint32 id = GetFigureId(buf);

Expand All @@ -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<uint8, 32> 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<uint8, 32> 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<uint8, 32> 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<uint8, 32> 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;
}
Expand All @@ -672,12 +699,11 @@ namespace nsyshid
{
FileStream* dimFile(FileStream::createFile2(pathName));
if (!dimFile)
{
return false;
}

std::array<uint8, 0x2D * 0x04> fileData{};
RandomUID(fileData);
fileData[7] = id & 0xFF;
fileData[3] = id & 0xFF;

std::array<uint8, 7> uid = {fileData[0], fileData[1], fileData[2], fileData[4], fileData[5], fileData[6], fileData[7]};

Expand Down Expand Up @@ -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<uint8, 32> 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<uint8, 32> 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<uint8, 0x2D * 0x04> data = figure.data;
std::unique_ptr<FileStream> 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;
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1076,17 +1097,17 @@ namespace nsyshid
void DimensionsUSB::RandomUID(std::array<uint8, 0x2D * 0x04>& uid_buffer)
{
uid_buffer[0] = 0x04;
uid_buffer[6] = 0x80;
uid_buffer[7] = 0x80;

std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> dist(0, 255);

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<uint8, 32>& data,
Expand Down
12 changes: 8 additions & 4 deletions src/Cafe/OS/libs/nsyshid/Dimensions.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <shared_mutex>
#include <mutex>

#include "nsyshid.h"
#include "Backend.h"
Expand Down Expand Up @@ -65,16 +65,18 @@ namespace nsyshid
void GetModel(std::span<const uint8, 8> buf, uint8 sequence,
std::array<uint8, 32>& replyBuf);

bool RemoveFigure(uint8 pad, uint8 index, bool save, bool lock);
uint32 LoadFigure(const std::array<uint8, 0x2D * 0x04>& buf, std::unique_ptr<FileStream> 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<uint8, 0x2D * 0x04>& buf, std::unique_ptr<FileStream> 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<const uint32, const char*> GetListMinifigs();
static std::map<const uint32, const char*> GetListTokens();
std::string FindFigure(uint32 figNum);

protected:
std::shared_mutex m_dimensionsMutex;
std::mutex m_dimensionsMutex;
std::array<DimensionsMini, 7> m_figures{};

private:
Expand All @@ -96,6 +98,8 @@ namespace nsyshid
uint32 m_randomC;
uint32 m_randomD;

bool m_isAwake = false;

std::queue<std::array<uint8, 32>> m_figureAddedRemovedResponses;
std::queue<std::array<uint8, 32>> m_queries;
};
Expand Down
16 changes: 12 additions & 4 deletions src/gui/EmulatedUSBDevices/EmulatedUSBDeviceFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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)
{
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 62d3742

Please sign in to comment.