Cleaned up includes

This commit is contained in:
Lucas Peter 2024-09-26 15:01:42 +02:00
parent 117da9d24a
commit b959059755
No known key found for this signature in database
10 changed files with 175 additions and 232 deletions

View file

@ -1,6 +1,7 @@
// Copyright Epic Games, Inc. All Rights Reserved. // Copyright Epic Games, Inc. All Rights Reserved.
#include "SkyPortal.h" #include "SkyPortal.h"
#include "SkyPortalSubsystem.h"
#define LOCTEXT_NAMESPACE "FSkyPortalModule" #define LOCTEXT_NAMESPACE "FSkyPortalModule"

View file

@ -2,20 +2,27 @@
#include "SkyPortalFigure.h" #include "SkyPortalFigure.h"
uint32 GetFigureID(const FigureDataBlock& DataBlock)
uint32 FigureData::GetFigureID()
{ {
int16_t OutFigureID; if (ID == 0) {
// Figure ID is stored in Block 0, bytes 0 to 3 (32-bit integer, little-endian) int16_t OutFigureID = 0;
OutFigureID = DataBlock.blockdata[0][0] |
(DataBlock.blockdata[0][1] << 8) | // The figure ID is stored in Block 1 of Sector 0 (i.e., data[1]), bytes 0 and 1 (16-bit integer, little-endian)
(DataBlock.blockdata[0][2] << 16) | OutFigureID = data[1][0] | // Least significant byte
(DataBlock.blockdata[0][3] << 24); (data[1][1] << 8); // Most significant byte, shifted left by 8 bits
ID = OutFigureID;// Return the 16-bit figure ID
return OutFigureID;
}
else { return ID; }
/* /*
// Variant ID is stored in Block 0, bytes 4 to 5 (16-bit integer, little-endian) // Variant ID is stored in Block 0, bytes 4 to 5 (16-bit integer, little-endian)
OutVariantID = (DataBlock.blockdata[0][5] << 8) | OutVariantID = (DataBlock.blockdata[0][5] << 8) |
DataBlock.blockdata[0][4]; DataBlock.blockdata[0][4];
*/ */
return OutFigureID;
}; };
/* /*

View file

@ -263,3 +263,58 @@ FPortalStatusData ParsePortalStatus(const uint8* StatusResponse)
return result; return result;
} }
FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex)
{
FigureData FigureData;
FigureData.dataError = false; // Initialize error flag
FWriteBlock command;
// Loop over all 64 blocks
for (uint8 BlockIndex = 0; BlockIndex < FIGURE_TOTAL_BLOCKS; ++BlockIndex)
{
memset(command.data, 0, write_buf_size); //maybe not needed here
command.data[1] = 'Q';
command.data[2] = FigureIndex; // Figure index (0x00-0x0F)
command.data[3] = BlockIndex;
uint8* output;
do {
Write(&command);
output = Read();
} while (output[0] != 'Q');
if (output[1] == (0x10 + 'Q')) // Successful query
{
// Extract the 16 bytes of block data
for (int i = 3; i < 19; i++)
{
FigureData.data[BlockIndex][i] = output[i];
}
}
else if (output[0] == 0x01) {
FigureData.dataError = true;
UE_LOG(LogSkyportalIO, Warning, TEXT("Error querying block %d from figure %d"), BlockIndex, FigureIndex);
break;
}
// Verify that the block index matches the requested block
uint8 ReturnedBlockIndex = output[3];
if (ReturnedBlockIndex != BlockIndex)
{
FigureData.dataError = true;
UE_LOG(LogSkyportalIO, Warning, TEXT("Mismatched block index. Expected %d, got %d"), BlockIndex, ReturnedBlockIndex);
break;
}
// Copy block data into FigureData
//memcpy(FigureData.blockdata[BlockIndex], &res.buf[4], FIGURE_BLOCK_SIZE);
}
// Some verifications should happen. Like if dataError is set.
return FigureData; // Return the complete figure data
}

View file

@ -52,6 +52,7 @@ void FPortalStatusChecker::CheckPortalStatus()
// Call the subsystem function to get portal status // Call the subsystem function to get portal status
uint8* output = PortalHandleRef->Read(); uint8* output = PortalHandleRef->Read();
EPortalCommand CommandResponse = GetPortalCommandFromChar(output[0]); EPortalCommand CommandResponse = GetPortalCommandFromChar(output[0]);
FigureData figData;
switch (CommandResponse) switch (CommandResponse)
{ {
case S: case S:
@ -71,15 +72,15 @@ void FPortalStatusChecker::CheckPortalStatus()
switch (CurrentStatusData.StatusArray[i]) switch (CurrentStatusData.StatusArray[i])
{ {
case EFigureStatus::NOT_PRESENT: case EFigureStatus::NOT_PRESENT:
subref->OnSkylanderRemoved.Broadcast(00, i);
break; break;
case EFigureStatus::PRESENT: case EFigureStatus::PRESENT:
//FigureData = ReadFigureBlocks(i); //FigureData = ReadFigureBlocks(i);
//subref->OnSkylanderAdded.Broadcast(GetFigureID(FigureData), i); //subref->OnSkylanderAdded.Broadcast(GetFigureID(FigureData), i);
break; break;
case EFigureStatus::ADDED: case EFigureStatus::ADDED:
//FigureData = ReadFigureBlocks(i); figData = PortalHandleRef->ReadFigureBlocks(i);
//subref->OnSkylanderAdded.Broadcast(GetFigureID(FigureData), i); subref->OnSkylanderAdded.Broadcast(figData.GetFigureID(), i);
break; break;
case EFigureStatus::REMOVED: case EFigureStatus::REMOVED:
subref->OnSkylanderRemoved.Broadcast(00, i); subref->OnSkylanderRemoved.Broadcast(00, i);

View file

@ -75,8 +75,12 @@ void USkyPortalSubsystem::PortalReady()
output = PortalHandle->Read(); output = PortalHandle->Read();
} while (output[0] != 'R'); } while (output[0] != 'R');
uint16 _PortalId = ((output[1] << 8) + output[2]); unsigned char _PortalId[2] = { output[1],output[2] };
PortalId = _PortalId; //Need a conversion as uint16 is not supported in BP int32 BE_PortalId = (_PortalId[0] << 8) | _PortalId[1]; // Big-endian format
uint32 BEU_PortalId = (_PortalId[0] << 8) | _PortalId[1]; // Big-endian format unsigned
int32 LE_PortalId = (_PortalId[1] << 8) | _PortalId[0]; //little endian
uint32 LEU_PortalId = (_PortalId[1] << 8) | _PortalId[0]; //little endian unsigned
PortalId = LE_PortalId; //Need a conversion as uint16 is not supported in BP
} }
@ -181,60 +185,6 @@ void USkyPortalSubsystem::ChangePortalColorSide(const FLinearColor& Color, const
FPortalStatusData USkyPortalSubsystem::OLDParsePortalStatus(const FWriteBlock& ResponseBlock)
{
FPortalStatusData PortalStatusData;
// Parse the figure status array (little-endian 32-bit integer)
uint32 FigureStatusArray = 0;
// Reading the 32-bit integer (character status array) from the buffer
FigureStatusArray |= ResponseBlock.data[1]; // 1st byte
FigureStatusArray |= (ResponseBlock.data[2] << 8); // 2nd byte
FigureStatusArray |= (ResponseBlock.data[3] << 16); // 3rd byte
FigureStatusArray |= (ResponseBlock.data[4] << 24); // 4th byte
TStaticArray<EFigureStatus, 16> tempArray;
// For each of the 16 entries, extract the 2-bit status and map it to EFigureStatus
for (int32 i = 0; i < 16; ++i)
{
uint8 StatusBits = (FigureStatusArray >> (i * 2)) & 0b11; // Extract 2 bits
EFigureStatus FigureStatus;
switch (StatusBits)
{
case 0b00:
FigureStatus = EFigureStatus::NOT_PRESENT;
break;
case 0b01:
FigureStatus = EFigureStatus::PRESENT;
break;
case 0b11:
FigureStatus = EFigureStatus::ADDED;
break;
case 0b10:
FigureStatus = EFigureStatus::REMOVED;
break;
default:
FigureStatus = EFigureStatus::NOT_PRESENT; // Default case
break;
}
// Add to the array of figure statuses
//PortalStatusData.StatusArray.Insert(FigureStatus, i);
tempArray[i] = FigureStatus;
}
PortalStatusData.StatusArray.SetNum(0);
PortalStatusData.StatusArray.Append(tempArray);
// The next byte is the response counter
PortalStatusData.Counter = ResponseBlock.data[5];
// The last byte is the boolean indicating whether the portal is ready
PortalStatusData.bIsReady = ResponseBlock.data[6] != 0; // 0 means not ready, non-zero means ready
return PortalStatusData;
}
void USkyPortalSubsystem::Sleep(int sleepMs) { void USkyPortalSubsystem::Sleep(int sleepMs) {
FPlatformProcess::Sleep(sleepMs * 0.0001); FPlatformProcess::Sleep(sleepMs * 0.0001);
} }
@ -268,69 +218,3 @@ SKYPORTAL_API void USkyPortalSubsystem::PortalMusic(const USoundWave* Sound)
{ {
return; return;
} }
/*
FigureDataBlock USkyPortalSubsystem::ReadFigureBlocks(uint8 FigureIndex)
{
FigureDataBlock FigureData;
FigureData.error = false; // Initialize error flag
FWriteBlock req, res;
// Loop over all 64 blocks
for (uint8 BlockIndex = 0; BlockIndex < FIGURE_TOTAL_BLOCKS; ++BlockIndex)
{
// Prepare the request buffer
memset(command.data, 0, rw_buf_size);
command.data[1] = 'Q'; // Command character
command.data[2] = FigureIndex; // Figure index (0x00 to 0x0F)
command.data[3] = BlockIndex; // Block index (0x00 to 0x3F)
// Send the request
Write(&req);
// Read the response
int BuffResponse = hid_read_timeout(PortalDevice, res.buf, rw_buf_size, TIMEOUT);
// Check if the response was received successfully
if (BuffResponse < rw_buf_size)
{
FigureData.error = true; // Mark error flag
UE_LOG(LogSkyportalIO, Warning, TEXT("Error receiving data for block %d of figure %d"), BlockIndex, FigureIndex);
break;
}
// Parse the response status
uint8 StatusByte = res.buf[2];
uint8 ReturnedBlockIndex = res.buf[3];
// Check for errors in the status byte
if (StatusByte == 0x01) // Error in response
{
FigureData.error = true;
UE_LOG(LogSkyportalIO, Warning, TEXT("Error reading block %d for figure %d"), BlockIndex, FigureIndex);
break;
}
else if (StatusByte != (0x10 + 'Q')) // Unexpected status byte
{
FigureData.error = true;
UE_LOG(LogSkyportalIO, Warning, TEXT("Unexpected status byte 0x%02X for block %d"), StatusByte, BlockIndex);
break;
}
// Verify that the block index matches the requested block
if (ReturnedBlockIndex != BlockIndex)
{
FigureData.error = true;
UE_LOG(LogSkyportalIO, Warning, TEXT("Mismatched block index. Expected %d, got %d"), BlockIndex, ReturnedBlockIndex);
break;
}
// Copy block data into FigureData
memcpy(FigureData.blockdata[BlockIndex], &res.buf[4], FIGURE_BLOCK_SIZE);
}
return FigureData; // Return the complete figure data
}
*/

View file

@ -4,7 +4,6 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Modules/ModuleManager.h" #include "Modules/ModuleManager.h"
#include "SkyPortalSubsystem.h"
class FSkyPortalModule : public IModuleInterface class FSkyPortalModule : public IModuleInterface
{ {

View file

@ -0,0 +1,83 @@
#pragma once
#include "CoreMinimal.h"
#include "SkyPortalDefinitions.generated.h"
// This file is not supposed to have a c++ counterpart. Use it as a library
UENUM(BlueprintType)
enum class EFigureStatus : uint8
{
NOT_PRESENT = 0b00 UMETA(DisplayName = "Not Present"),
PRESENT = 0b01 UMETA(DisplayName = "Present"),
ADDED = 0b11 UMETA(DisplayName = "Added"),
REMOVED = 0b10 UMETA(DisplayName = "Removed")
};
UENUM(BlueprintType)
enum EPortalSide {
LEFT UMETA(DisplayName = "Left side"),
RIGHT UMETA(DisplayName = "Right side"),
BOTH UMETA(DisplayName = "Both left and right"),
TRAP UMETA(DisplayName = "Trap")
};
UENUM(BlueprintType)
enum EPortalCommand {
A UMETA(DisplayName = "Activate"),
C UMETA(DisplayName = "Color"),
J UMETA(DisplayName = "Advanced color"),
L UMETA(DisplayName = "Trap color"),
M UMETA(DisplayName = "Music"),
Q UMETA(DisplayName = "Query"),
R UMETA(DisplayName = "Ready"),
S UMETA(DisplayName = "Status")
};
USTRUCT(BlueprintType)
struct FPortalStatusData
{
GENERATED_BODY()
// Array of statuses
UPROPERTY(BlueprintReadOnly, EditFixedSize, Category = "SkyPortal|Figure", meta = (EditFixedOrder))
TArray<EFigureStatus> StatusArray;
// timestamp.
// only one byte long. This means that after the value 0xFF, it overflows back to 0x00.
// Since these are so far apart, it can be assumed that 0x00 is newer than anything in the range 0xF0 - 0xFF.
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
uint8 Counter;
// Should always be true
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
bool bIsReady;
explicit FPortalStatusData(uint8 ArraySize = 16, EFigureStatus DefaultStatus = EFigureStatus::NOT_PRESENT) :
Counter(0),
bIsReady(true)
{
// Initialisation du tableau StatusArray avec 16 éléments par défaut
StatusArray.Init(DefaultStatus, ArraySize);
}
// Overload the == operator
// Different only between
bool operator==(const FPortalStatusData& Other) const
{
if (bIsReady == Other.bIsReady && Counter == Other.Counter) {
if (StatusArray == Other.StatusArray) {
return true;
}
}
return false;
}
// Overload the != operator
bool operator!=(const FPortalStatusData& Other) const
{
return !(*this == Other);
}
};

View file

@ -3,15 +3,6 @@
//#include "SkyPortalFigure.generated.h" //#include "SkyPortalFigure.generated.h"
UENUM(BlueprintType)
enum class EFigureStatus : uint8
{
NOT_PRESENT = 0b00 UMETA(DisplayName = "Not Present"),
PRESENT = 0b01 UMETA(DisplayName = "Present"),
ADDED = 0b11 UMETA(DisplayName = "Added"),
REMOVED = 0b10 UMETA(DisplayName = "Removed")
};
#define FIGURE_TOTAL_BLOCKS 64 #define FIGURE_TOTAL_BLOCKS 64
#define FIGURE_BLOCK_SIZE 16 #define FIGURE_BLOCK_SIZE 16
@ -26,6 +17,7 @@ public:
// Data Arrays // Data Arrays
uint8 data[64][16]; uint8 data[64][16];
uint8 decryptedData[64][16]; uint8 decryptedData[64][16];
bool dataError;
// Properties // Properties
#pragma region manufacturer #pragma region manufacturer
@ -56,7 +48,7 @@ public:
// Methods // Methods
UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure"))
uint32 GetFigureID(const FigureDataBlock& DataBlock); uint32 GetFigureID();
UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure"))
uint32 GetFigureIdByIndex(uint32 index); uint32 GetFigureIdByIndex(uint32 index);
@ -71,4 +63,6 @@ public:
uint16 GetShort(int block, int offset); uint16 GetShort(int block, int offset);
uint32 GetUInt(int block, int offset); uint32 GetUInt(int block, int offset);
void Dump(bool decrypted, FString filePath); void Dump(bool decrypted, FString filePath);
}; };

View file

@ -4,6 +4,7 @@
*/ */
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "hidapi.h" #include "hidapi.h"
#include "SkyPortalDefinitions.h"
#include "SkyPortalFigure.h" #include "SkyPortalFigure.h"
#include "SkyPortalIO.generated.h" #include "SkyPortalIO.generated.h"
@ -19,63 +20,6 @@ constexpr auto TIMEOUT = 30000; //milliseconds
const int VendorIds[4] = { 0x12ba, 0x54c, 0x1430, 0x1430 }; const int VendorIds[4] = { 0x12ba, 0x54c, 0x1430, 0x1430 };
const int ProductIds[4] = { 0x150, 0x967, 0x1f17 }; const int ProductIds[4] = { 0x150, 0x967, 0x1f17 };
UENUM(BlueprintType)
enum EPortalCommand {
A UMETA(DisplayName = "Activate"),
C UMETA(DisplayName = "Color"),
J UMETA(DisplayName = "Advanced color"),
L UMETA(DisplayName = "Trap color"),
M UMETA(DisplayName = "Music"),
Q UMETA(DisplayName = "Query"),
R UMETA(DisplayName = "Ready"),
S UMETA(DisplayName = "Status")
};
USTRUCT(BlueprintType)
struct FPortalStatusData
{
GENERATED_BODY()
// Array of statuses
UPROPERTY(BlueprintReadOnly, EditFixedSize, Category = "SkyPortal|Figure", meta = (EditFixedOrder))
TArray<EFigureStatus> StatusArray;
// timestamp.
// only one byte long. This means that after the value 0xFF, it overflows back to 0x00.
// Since these are so far apart, it can be assumed that 0x00 is newer than anything in the range 0xF0 - 0xFF.
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
uint8 Counter;
// Should always be true
UPROPERTY(BlueprintReadOnly, Category = "SkyPortal|Figure")
bool bIsReady;
explicit FPortalStatusData(uint8 ArraySize = 16, EFigureStatus DefaultStatus = EFigureStatus::NOT_PRESENT) :
Counter(0),
bIsReady(true)
{
// Initialisation du tableau StatusArray avec 16 éléments par défaut
StatusArray.Init(DefaultStatus, ArraySize);
}
// Overload the == operator
// Different only between
bool operator==(const FPortalStatusData& Other) const
{
if (bIsReady == Other.bIsReady && Counter == Other.Counter) {
if (StatusArray == Other.StatusArray) {
return true;
}
}
return false;
}
// Overload the != operator
bool operator!=(const FPortalStatusData& Other) const
{
return !(*this == Other);
}
};
#pragma endregion #pragma endregion
@ -83,7 +27,7 @@ FPortalStatusData ParsePortalStatus(const uint8* StatusResponse);
EPortalCommand GetPortalCommandFromChar(unsigned char Char); EPortalCommand GetPortalCommandFromChar(unsigned char Char);
/* Contain all the data that pass inside hidapi write + the number of bytes in case of successful write /* Contain all the data that pass inside hidapi write + the number of bytes in case of successful write
* *
* @param data all the block data, should be 0x21 sized * @param data all the block data, should be 0x21 sized
* @param BytesTransferred In case of successful write, print the number of byte transfered. Could be used for verifications * @param BytesTransferred In case of successful write, print the number of byte transfered. Could be used for verifications
*/ */
@ -131,6 +75,8 @@ public:
UFUNCTION() UFUNCTION()
TArray<uint8> QueryBlock(uint8 characterIndex, uint8 block = 0x00); TArray<uint8> QueryBlock(uint8 characterIndex, uint8 block = 0x00);
FigureData ReadFigureBlocks(uint8 FigureIndex);
/* Close connection to Portal*/ /* Close connection to Portal*/
void Close(); void Close();

View file

@ -3,27 +3,10 @@
#include "Subsystems/EngineSubsystem.h" #include "Subsystems/EngineSubsystem.h"
#include "SkyPortalRunner.h" #include "SkyPortalRunner.h"
#include "SkyPortalIO.h" #include "SkyPortalIO.h"
#include "SkyPortalSubsystem.generated.h" #include "SkyPortalSubsystem.generated.h"
#pragma region Definitions #pragma region Definitions
UENUM(BlueprintType)
enum EPortalSide {
LEFT UMETA(DisplayName = "Left side"),
RIGHT UMETA(DisplayName = "Right side"),
BOTH UMETA(DisplayName = "Both left and right"),
TRAP UMETA(DisplayName = "Trap")
};
//// Delegates //// Delegates
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderAddedDelegate, int32, SkylanderID, int32, Index); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderAddedDelegate, int32, SkylanderID, int32, Index);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, SkylanderID, int32, Index); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, SkylanderID, int32, Index);
@ -95,7 +78,7 @@ public:
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands")) UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands"))
SKYPORTAL_API FPortalStatusData PortalStatus(); SKYPORTAL_API FPortalStatusData PortalStatus();
/* Change the color of the portal, can separate side and even trap ligth /* Change the color of the portal, can separate side and even trap ligth
@ -106,7 +89,7 @@ public:
UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Commands|Cosmetic", HideAlphaChannel)) UFUNCTION(BlueprintCallable, CallInEditor, meta = (AutoCreateRefTerm = "NextColor", Category = "SkyPortal|Commands|Cosmetic", HideAlphaChannel))
SKYPORTAL_API void ChangePortalColorSide(const FLinearColor& NextColor = FLinearColor::Green, const EPortalSide PortalSide = EPortalSide::BOTH, const float BlendTime = 500.0f); SKYPORTAL_API void ChangePortalColorSide(const FLinearColor& NextColor = FLinearColor::Green, const EPortalSide PortalSide = EPortalSide::BOTH, const float BlendTime = 500.0f);
// Blueprint-assignable event property // Blueprint-assignable event property
UPROPERTY(BlueprintAssignable, Category = "SkyPortal|Skylander") UPROPERTY(BlueprintAssignable, Category = "SkyPortal|Skylander")
@ -146,22 +129,12 @@ public:
private: private:
// deprecated
FPortalStatusData OLDParsePortalStatus(const FWriteBlock& ResponseBlock); // deprecated
EPortalCommand GetPortalCommandFromChar(unsigned char Char); // deprecated
/* Sleep the system /* Sleep the system
* *
* @param sleepMs Sleep time (in milliseconds) * @param sleepMs Sleep time (in milliseconds)
*/ */
static void Sleep(int sleepMs); static void Sleep(int sleepMs);
bool FalsePositive() const;
// Pointer to the status checker thread // Pointer to the status checker thread
FPortalStatusChecker* StatusChecker; FPortalStatusChecker* StatusChecker;
FRunnableThread* StatusCheckerThread; FRunnableThread* StatusCheckerThread;