diff --git a/Source/SkyPortal/Private/SkyPortal.cpp b/Source/SkyPortal/Private/SkyPortal.cpp index 162c591..4724a77 100644 --- a/Source/SkyPortal/Private/SkyPortal.cpp +++ b/Source/SkyPortal/Private/SkyPortal.cpp @@ -14,6 +14,10 @@ void FSkyPortalModule::ShutdownModule() { // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, // we call this function before unloading the module. + + if (GEngine->GetEngineSubsystem()) { + GEngine->GetEngineSubsystem()->Deinitialize(); + } } #undef LOCTEXT_NAMESPACE diff --git a/Source/SkyPortal/Private/SkyPortalFigure.cpp b/Source/SkyPortal/Private/SkyPortalFigure.cpp index 1b00736..6d927e7 100644 --- a/Source/SkyPortal/Private/SkyPortalFigure.cpp +++ b/Source/SkyPortal/Private/SkyPortalFigure.cpp @@ -9,7 +9,7 @@ uint32 FigureData::GetFigureID() int16_t OutFigureID = 0; // The figure ID is stored in Block 1 of Sector 0 (i.e., data[1]), bytes 0 and 1 (16-bit integer, little-endian) - OutFigureID = data[1][0] | // Least significant byte + OutFigureID = decryptedData[1][0] | // Least significant byte (data[1][1] << 8); // Most significant byte, shifted left by 8 bits ID = OutFigureID;// Return the 16-bit figure ID @@ -25,64 +25,6 @@ uint32 FigureData::GetFigureID() }; -/* -void FigureData::ReadData(uint8 index) -{ - ClearData(); - for (uint8 i = 0; i < 64; i++) - { - GEngine->GetEngineSubsystem(); - TArray output = SkySubsystem->QueryBlock(index, i); - - uint8[] blockData = new uint8[0x10]; - Array.Copy(output, 3, blockData, 0, 16); - - // block 1 is sometimes a duplicate of block 0 - if (i == 1) - { - if (blockData.SequenceEqual(data[0])) - { - i -= 1; - continue; - } - } - - Array.Copy(blockData, 0, data[i], 0, 16); - - if (((i + 1) % 4 == 0) || i < 8) - { - Array.Copy(data[i], 0, decryptedData[i], 0, 16); - } - else - { - uint8[] hashIn = new byte[0x56]; - data[0].CopyTo(hashIn, 0); - data[1].CopyTo(hashIn, 0x10); - hashIn[0x20] = i; - HASH_CONST.CopyTo(hashIn, 0x21); - - uint8[] key = MD5.Create().ComputeHash(hashIn); - - uint8[] decrypted = new byte[0x10]; - - using (Aes aesAlg = Aes.Create()) - { - aesAlg.Key = key; - aesAlg.Mode = CipherMode.ECB; - aesAlg.Padding = PaddingMode.Zeros; - - ICryptoTransform decryptor = aesAlg.CreateDecryptor(); - - decrypted = decryptor.TransformFinalBlock(data[i], 0, data[i].Length); - - } - - Array.Copy(decrypted, 0, decryptedData[i], 0, 16); - } - } -} -*/ - void FigureData::ClearData() { } diff --git a/Source/SkyPortal/Private/SkyPortalIO.cpp b/Source/SkyPortal/Private/SkyPortalIO.cpp index ae6d88a..7663a41 100644 --- a/Source/SkyPortal/Private/SkyPortalIO.cpp +++ b/Source/SkyPortal/Private/SkyPortalIO.cpp @@ -1,8 +1,9 @@ #include "SkyPortalIO.h" #include "Misc/AES.h" -#include "Misc/ArchiveMD5.h" -#include "Misc/ScopeLock.h" + #include "HAL/UnrealMemory.h" +#include "openssl/aes.h" + DEFINE_LOG_CATEGORY(LogHIDApi); @@ -281,12 +282,21 @@ FPortalStatusData ParsePortalStatus(const uint8* StatusResponse) } +void DecryptAES128(uint8* OutData, const uint8* InData, const uint8* Key) +{ + AES_KEY AesKey; + // Set the decryption key (16 bytes for AES-128) + AES_set_decrypt_key(Key, 128, &AesKey); + + // Perform AES-128 decryption (ECB mode) + AES_ecb_encrypt(InData, OutData, &AesKey, AES_DECRYPT); +} FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex) { - FigureData FigureData; - FigureData.dataError = false; // Initialize error flag + FigureData TempFigureData; + TempFigureData.dataError = false; // Initialize error flag @@ -297,12 +307,12 @@ FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex) uint8* output = QueryBlock(FigureIndex, BlockIndex); // Copy 16 bytes from the output, starting at the third byte - FMemory::Memcpy(FigureData.data, output + 3, FIGURE_BLOCK_SIZE); + FMemory::Memcpy(TempFigureData.data, output + 3, FIGURE_BLOCK_SIZE); // Block 1 is sometimes a duplicate of block 0 if (BlockIndex == 1) { - if (FMemory::Memcmp(FigureData.data, FigureData.data[0], FIGURE_BLOCK_SIZE) == 0) + if (FMemory::Memcmp(TempFigureData.data, TempFigureData.data[0], FIGURE_BLOCK_SIZE) == 0) { --BlockIndex; // Decrement index to reprocess continue; @@ -312,15 +322,15 @@ FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex) if (((BlockIndex + 1) % 4 == 0) || BlockIndex < 8) { // Direct copy from data to decryptedData for certain blocks - FMemory::Memcpy(FigureData.decryptedData[BlockIndex], FigureData.data[BlockIndex], FIGURE_BLOCK_SIZE); + FMemory::Memcpy(TempFigureData.decryptedData[BlockIndex], TempFigureData.data[BlockIndex], FIGURE_BLOCK_SIZE); } else { /***** MD5 Hash Calculation *****/ // Prepare the hash input buffer uint8 hashIn[0x56]; - FMemory::Memcpy(hashIn, FigureData.data[0], 16); - FMemory::Memcpy(hashIn + 0x10, FigureData.data[1], 16); + FMemory::Memcpy(hashIn, TempFigureData.data[0], 16); + FMemory::Memcpy(hashIn + 0x10, TempFigureData.data[1], 16); hashIn[0x20] = BlockIndex; // Append the 35-byte constant FMemory::Memcpy(hashIn + 0x21, HASH_CONST, sizeof(HASH_CONST)); @@ -337,39 +347,14 @@ FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex) FMemory::Memcpy(AesKey.Key, key, 16); //TODO: FAES implementation in Unreal is AES-256. We need AES-128 - //FAES::DecryptData(FigureData.decryptedData[BlockIndex], FigureData.data[BlockIndex], 16, AesKey); + //FAES::DecryptData(TempFigureData.decryptedData[BlockIndex], TempFigureData.data[BlockIndex], 16, AesKey); + DecryptAES128(TempFigureData.decryptedData[BlockIndex], TempFigureData.data[BlockIndex], key); } - /* - 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 + return TempFigureData; // Return the complete figure data } + diff --git a/Source/SkyPortal/Private/SkyPortalRunner.cpp b/Source/SkyPortal/Private/SkyPortalRunner.cpp index fce6818..c537dc7 100644 --- a/Source/SkyPortal/Private/SkyPortalRunner.cpp +++ b/Source/SkyPortal/Private/SkyPortalRunner.cpp @@ -72,15 +72,11 @@ void FPortalStatusChecker::CheckPortalStatus() switch (CurrentStatusData.StatusArray[i]) { case EFigureStatus::NOT_PRESENT: - - break; case EFigureStatus::PRESENT: - //FigureData = ReadFigureBlocks(i); - //subref->OnSkylanderAdded.Broadcast(GetFigureID(FigureData), i); break; case EFigureStatus::ADDED: - figData = PortalHandleRef->ReadFigureBlocks(i); - subref->OnSkylanderAdded.Broadcast(figData.GetFigureID(), i); + //figData = PortalHandleRef->ReadFigureBlocks(i); + subref->OnSkylanderAdded.Broadcast(00, i); break; case EFigureStatus::REMOVED: subref->OnSkylanderRemoved.Broadcast(00, i); diff --git a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp index 0e057d9..f48194c 100644 --- a/Source/SkyPortal/Private/SkyPortalSubsystem.cpp +++ b/Source/SkyPortal/Private/SkyPortalSubsystem.cpp @@ -2,10 +2,9 @@ #include "SkyPortalSubsystem.h" #include "Engine/Engine.h" -#include "SkyPortal.h" #include "HAL/RunnableThread.h" -#include "Misc/ScopeLock.h" +#include "SkyPortalFigure.h" void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection) @@ -213,7 +212,7 @@ void USkyPortalSubsystem::Sleep(int sleepMs) { bool USkyPortalSubsystem::PortalConnect() { PortalHandle = NewObject(); - if (IsValid(PortalHandle)) { + if (IsValid(PortalHandle) && PortalHandle->bPortalReady) { UE_LOG(LogSkyportalIO, Log, TEXT("Portal connected: ")); PortalReady(); PortalActivate(1); @@ -234,7 +233,22 @@ bool USkyPortalSubsystem::IsPortalReady() return false; } -SKYPORTAL_API void USkyPortalSubsystem::PortalMusic(const USoundWave* Sound) + void USkyPortalSubsystem::PortalMusic(const USoundWave* Sound) { return; } + + void USkyPortalSubsystem::PortalAnalyze(const uint8 index) + { + FigureArray[index] = PortalHandle->ReadFigureBlocks(index); + UE_LOG(LogSkyportalIO, Log, TEXT("Reading figure...")); + UE_LOG(LogSkyportalIO, Log, TEXT("decrypted Figure ID : %d"), FigureArray[index].GetFigureID()); + } + + void USkyPortalSubsystem::GetFigureArray() { + FigureArray; + for (int i = 0; 16; i++) { + FigureArray[i] = PortalHandle->ReadFigureBlocks(i); + } + return; +} \ No newline at end of file diff --git a/Source/SkyPortal/Public/SkyPortalFigure.h b/Source/SkyPortal/Public/SkyPortalFigure.h index a697300..5c3cd93 100644 --- a/Source/SkyPortal/Public/SkyPortalFigure.h +++ b/Source/SkyPortal/Public/SkyPortalFigure.h @@ -12,10 +12,11 @@ static const uint8 HASH_CONST[] = { #define FIGURE_TOTAL_BLOCKS 64 #define FIGURE_BLOCK_SIZE 16 +/* typedef struct { unsigned char blockdata[FIGURE_TOTAL_BLOCKS][FIGURE_BLOCK_SIZE]; bool error; } FigureDataBlock; - +*/ class FigureData { @@ -38,8 +39,8 @@ public: uint64 FullToyCodeNumber; FString ToyCode; #pragma endregion - int16 ID; - int16 VariantID; + int16 ID; //Skylander ID + int16 VariantID; //Skylander Variant ID #pragma region counters uint8 counter1; uint8 couter2; @@ -53,10 +54,7 @@ public: // Methods - UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) uint32 GetFigureID(); - - UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure")) uint32 GetFigureIdByIndex(uint32 index); //UFUNCTION() diff --git a/Source/SkyPortal/Public/SkyPortalSubsystem.h b/Source/SkyPortal/Public/SkyPortalSubsystem.h index ba065a1..9565cd3 100644 --- a/Source/SkyPortal/Public/SkyPortalSubsystem.h +++ b/Source/SkyPortal/Public/SkyPortalSubsystem.h @@ -1,14 +1,21 @@ #pragma once -#include "Subsystems/EngineSubsystem.h" -#include "SkyPortalRunner.h" +#include "CoreMinimal.h" +#include "SkyPortalFigure.h" #include "SkyPortalIO.h" +#include "SkyPortalRunner.h" +#include "Subsystems/EngineSubsystem.h" +#include "Delegates/DelegateCombinations.h" +#include + #include "SkyPortalSubsystem.generated.h" + #pragma region Definitions //// Delegates DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderAddedDelegate, int32, SkylanderID, int32, Index); + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, SkylanderID, int32, Index); #pragma endregion @@ -74,6 +81,12 @@ public: UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING")) SKYPORTAL_API void PortalMusic(const USoundWave* Sound); + UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|Figure|Debug")) + SKYPORTAL_API void PortalAnalyze(const uint8 index); + + UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|Commands|Figure")) + SKYPORTAL_API void GetFigureArray(); + /**/ UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands")) SKYPORTAL_API FPortalStatusData PortalStatus(); @@ -104,6 +117,8 @@ public: UPROPERTY(BlueprintReadOnly) FPortalStatusData StatusData; + TArray FigureArray; + UPROPERTY(BlueprintReadWrite) float RunnerInterval = 0.01f; //In seconds diff --git a/Source/SkyPortal/SkyPortal.Build.cs b/Source/SkyPortal/SkyPortal.Build.cs index 60e8bb3..d220ca2 100644 --- a/Source/SkyPortal/SkyPortal.Build.cs +++ b/Source/SkyPortal/SkyPortal.Build.cs @@ -62,9 +62,10 @@ public class SkyPortal : ModuleRules { "Core", "CoreUObject", - "Engine" - // ... add other public dependencies that you statically link with here ... - } + "Engine", + "OpenSSL", + "SSL" + } ); @@ -75,7 +76,7 @@ public class SkyPortal : ModuleRules "Engine", "Slate", "SlateCore", - // ... add private dependencies that you statically link with here ... + } );