Skip to content

Commit

Permalink
Tasofro: add support for th135 encryption and memory objects.
Browse files Browse the repository at this point in the history
  • Loading branch information
brliron committed Aug 24, 2017
1 parent 7d1f521 commit 7b32736
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 94 deletions.
154 changes: 154 additions & 0 deletions thcrap_tasofro/src/crypt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Touhou Community Reliant Automatic Patcher
* Tasogare Frontier support plugin
*
* ----
*
* XOR-based encryption.
*/

#include <thcrap.h>
#include "thcrap_tasofro.h"
#include "crypt.h"

ICrypt* ICrypt::instance = nullptr;

DWORD CryptTh135::cryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key)
{
for (DWORD j = 0; j < FileSize / 4; j++)
{
*((DWORD*)Data + j) ^= Key[j % 4];
}

DWORD remain = FileSize % 4;
if (remain)
{
DWORD tk = Key[FileSize / 4 % 4];
for (DWORD j = 0; j < remain; j++)
{
Data[FileSize - remain + j] ^= tk & 0xFF;
tk >>= 8;
}
}
return 0;
}

void CryptTh135::uncryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key)
{
this->cryptBlock(Data, FileSize, Key);
}

// Normalized Hash
DWORD CryptTh135::SpecialFNVHash(const char *begin, const char *end, DWORD initHash)
{
DWORD hash; // eax@1
DWORD ch; // esi@2

int inMBCS = 0;
for (hash = initHash; begin != end; hash = ch ^ 0x1000193 * hash)
{
ch = *begin++;
if (!inMBCS && ((unsigned char)ch >= 0x81u && (unsigned char)ch <= 0x9Fu || (unsigned char)ch + 32 <= 0x1Fu)) inMBCS = 2;
if (!inMBCS)
{
ch = tolower(ch); // bad ass style but WORKS PERFECTLY!
if (ch == '/') ch = '\\';
}
else inMBCS--;
}
return hash;
}

void CryptTh135::convertKey(DWORD*)
{}



CryptTh145::CryptTh145()
: tempCopy(nullptr), tempCopySize(0)
{}

CryptTh145::~CryptTh145()
{
if (this->tempCopy) {
delete[] this->tempCopy;
}
}

DWORD CryptTh145::cryptBlockInternal(BYTE* Data, DWORD FileSize, DWORD* Key, DWORD Aux)
{
BYTE *key = (BYTE*)Key;
BYTE *aux = (BYTE*)&Aux;
int i;

for (i = FileSize - 1; i >= 0; i--) {
BYTE unencByte = Data[i];
BYTE encByte = aux[i % 4];
Data[i] = aux[i % 4];
aux[i % 4] = unencByte ^ encByte ^ key[i % 16];
}
return Aux;
}

DWORD CryptTh145::cryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key)
{
if (FileSize > this->tempCopySize) {
if (this->tempCopy) {
delete[] this->tempCopy;
}
this->tempCopy = new BYTE[FileSize];
this->tempCopySize = FileSize;
}

DWORD Aux;
memcpy(this->tempCopy, Data, FileSize);
Aux = this->cryptBlockInternal(tempCopy, FileSize, Key, Key[0]); // This call seems to give the correct Aux value.

return this->cryptBlockInternal(Data, FileSize, Key, Aux);
}

void CryptTh145::uncryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key)
{
BYTE *key = (BYTE*)Key;
BYTE aux[4];
DWORD i;

for (i = 0; i < 4; i++) {
aux[i] = key[i];
}

for (i = 0; i < FileSize; i++) {
BYTE tmp = Data[i];
Data[i] = Data[i] ^ key[i % 16] ^ aux[i % 4];
aux[i % 4] = tmp;
}
}

// Normalized Hash
DWORD CryptTh145::SpecialFNVHash(const char *begin, const char *end, DWORD initHash)
{
DWORD hash; // eax@1
DWORD ch; // esi@2

int inMBCS = 0;
for (hash = initHash; begin != end; hash = (hash ^ ch) * 0x1000193)
{
ch = *begin++;
if (!inMBCS && ((unsigned char)ch >= 0x81u && (unsigned char)ch <= 0x9Fu || (unsigned char)ch + 32 <= 0x1Fu)) inMBCS = 2;
if (!inMBCS)
{
ch = tolower(ch); // bad ass style but WORKS PERFECTLY!
if (ch == '/') ch = '\\';
}
else inMBCS--;
}
return hash * -1;
}

void CryptTh145::convertKey(DWORD* key)
{
key[0] = key[0] *-1;
key[1] = key[1] *-1;
key[2] = key[2] *-1;
key[3] = key[3] *-1;
}
50 changes: 50 additions & 0 deletions thcrap_tasofro/src/crypt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Touhou Community Reliant Automatic Patcher
* Tasogare Frontier support plugin
*
* ----
*
* Encryption and hashing.
*/

#pragma once

#include <thcrap.h>
#include "thcrap_tasofro.h"

class ICrypt
{
public:
virtual ~ICrypt() {}
virtual DWORD cryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key) = 0;
virtual void uncryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key) = 0;
virtual DWORD SpecialFNVHash(const char *begin, const char *end, DWORD initHash = 0x811C9DC5u) = 0;
virtual void convertKey(DWORD *key) = 0;

static ICrypt *instance;
};

class CryptTh135 : public ICrypt
{
public:
virtual DWORD cryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key);
virtual void uncryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key);
virtual DWORD SpecialFNVHash(const char *begin, const char *end, DWORD initHash = 0x811C9DC5u);
virtual void convertKey(DWORD *key);
};

class CryptTh145 : public ICrypt
{
private:
BYTE *tempCopy;
DWORD tempCopySize;
DWORD cryptBlockInternal(BYTE* Data, DWORD FileSize, DWORD* Key, DWORD Aux);

public:
CryptTh145();
~CryptTh145();
virtual DWORD cryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key);
virtual void uncryptBlock(BYTE* Data, DWORD FileSize, DWORD* Key);
virtual DWORD SpecialFNVHash(const char *begin, const char *end, DWORD initHash = 0x811C9DC5u);
virtual void convertKey(DWORD *key);
};
54 changes: 0 additions & 54 deletions thcrap_tasofro/src/crypt_block.cpp

This file was deleted.

37 changes: 9 additions & 28 deletions thcrap_tasofro/src/files_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,7 @@
#include <thcrap.h>
#include <unordered_map>
#include "thcrap_tasofro.h"

// Normalized Hash
DWORD SpecialFNVHash(const char *begin, const char *end, DWORD initHash = 0x811C9DC5u)
{
DWORD hash; // eax@1
DWORD ch; // esi@2

int inMBCS = 0;
for (hash = initHash; begin != end; hash = (hash ^ ch) * 0x1000193)
{
ch = *begin++;
if (!inMBCS && ((unsigned char)ch >= 0x81u && (unsigned char)ch <= 0x9Fu || (unsigned char)ch + 32 <= 0x1Fu)) inMBCS = 2;
if (!inMBCS)
{
ch = tolower(ch); // bad ass style but WORKS PERFECTLY!
if (ch == '/') ch = '\\';
}
else inMBCS--;
}
return hash * -1;
}
#include "crypt.h"

std::unordered_map<DWORD, FileHeaderFull> fileHashToName;
int LoadFileNameList(const char* FileName)
Expand All @@ -42,7 +22,7 @@ int LoadFileNameList(const char* FileName)
{
int tlen = strlen(FilePath);
while (tlen && FilePath[tlen - 1] == '\n') FilePath[--tlen] = 0;
DWORD thash = SpecialFNVHash(FilePath, FilePath + tlen);
DWORD thash = ICrypt::instance->SpecialFNVHash(FilePath, FilePath + tlen);
strcpy(fileHashToName[thash].path, FilePath);
}
fclose(fp);
Expand All @@ -57,7 +37,7 @@ int LoadFileNameListFromMemory(char* list, size_t size)
while (len < size && list[len] != '\r' && list[len] != '\n') {
len++;
}
DWORD thash = SpecialFNVHash(list, list + len);
DWORD thash = ICrypt::instance->SpecialFNVHash(list, list + len);
strncpy(fileHashToName[thash].path, list, len);
list += len;
size -= len;
Expand All @@ -71,7 +51,7 @@ int LoadFileNameListFromMemory(char* list, size_t size)

DWORD filename_to_hash(const char* filename)
{
return SpecialFNVHash(filename, filename + strlen(filename));
return ICrypt::instance->SpecialFNVHash(filename, filename + strlen(filename));
}

struct FileHeaderFull* register_file_header(FileHeader* header, DWORD *key)
Expand All @@ -83,10 +63,11 @@ struct FileHeaderFull* register_file_header(FileHeader* header, DWORD *key)
full_header.offset = header->offset;
full_header.size = header->size;

full_header.key[0] = key[0] * -1;
full_header.key[1] = key[1] * -1;
full_header.key[2] = key[2] * -1;
full_header.key[3] = key[3] * -1;
full_header.key[0] = key[0];
full_header.key[1] = key[1];
full_header.key[2] = key[2];
full_header.key[3] = key[3];
ICrypt::instance->convertKey(full_header.key);
full_header.effective_offset = -1;
full_header.orig_size = header->size;

Expand Down
Loading

0 comments on commit 7b32736

Please sign in to comment.