Path: blob/master/RSDKv5/RSDK/Storage/Text.cpp
1163 views
#include "RSDK/Core/RetroEngine.hpp"12using namespace RSDK;34#if RETRO_REV0U5#include "Legacy/TextLegacy.cpp"6#endif78// From here: https://rosettacode.org/wiki/MD5#C910#include <stdlib.h>11#include <stdio.h>12#include <string.h>13#include <math.h>1415typedef union uwb {16unsigned w;17unsigned char b[4];18} WBunion;1920typedef unsigned digest[4];2122unsigned f0(unsigned abcd[]) { return (abcd[1] & abcd[2]) | (~abcd[1] & abcd[3]); }2324unsigned f1(unsigned abcd[]) { return (abcd[3] & abcd[1]) | (~abcd[3] & abcd[2]); }2526unsigned f2(unsigned abcd[]) { return abcd[1] ^ abcd[2] ^ abcd[3]; }2728unsigned f3(unsigned abcd[]) { return abcd[2] ^ (abcd[1] | ~abcd[3]); }2930typedef unsigned (*DgstFctn)(unsigned a[]);3132unsigned *calcKs(unsigned *k)33{34double s, pwr;35int32 i;3637pwr = pow(2, 32);38for (i = 0; i < 64; i++) {39s = fabs(sin(1 + i));40k[i] = (unsigned)(s * pwr);41}42return k;43}4445unsigned kspace[64];46unsigned *k = calcKs(kspace);4748// ROtate v Left by amt bits49unsigned rol(unsigned v, int16 amt)50{51unsigned msk1 = (1 << amt) - 1;52return ((v >> (32 - amt)) & msk1) | ((v << amt) & ~msk1);53}5455unsigned *md5(unsigned *h, const char *msg, int32 mlen)56{57static digest h0 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };58static DgstFctn ff[] = { &f0, &f1, &f2, &f3 };59static int16 M[] = { 1, 5, 3, 7 };60static int16 O[] = { 0, 1, 5, 0 };61static int16 rot0[] = { 7, 12, 17, 22 };62static int16 rot1[] = { 5, 9, 14, 20 };63static int16 rot2[] = { 4, 11, 16, 23 };64static int16 rot3[] = { 6, 10, 15, 21 };65static int16 *rots[] = { rot0, rot1, rot2, rot3 };6667digest abcd;68DgstFctn fctn;69int16 m, o, g;70unsigned f;71int16 *rotn;72union {73unsigned w[16];74char b[64];75} mm;76int32 os = 0;77int32 grp, grps, q, p;78unsigned char *msg2;7980if (k == NULL)81k = calcKs(kspace);8283for (q = 0; q < 4; q++) h[q] = h0[q]; // initialize8485{86grps = 1 + (mlen + 8) / 64;87msg2 = (unsigned char *)malloc(64 * grps);88memcpy(msg2, msg, mlen);89msg2[mlen] = (unsigned char)0x80;90q = mlen + 1;91while (q < 64 * grps) {92msg2[q] = 0;93q++;94}95{96// unsigned char t;97WBunion u;98u.w = 8 * mlen;99// t = u.b[0]; u.b[0] = u.b[3]; u.b[3] = t;100// t = u.b[1]; u.b[1] = u.b[2]; u.b[2] = t;101q -= 8;102#if !RETRO_USE_ORIGINAL_CODE103for (p = 0; p < 4; ++p) msg2[q + p] = (u.w >> (8 * p)) & 0xFF;104#else105// This only works as intended on little-endian CPUs.106memcpy(msg2 + q, &u.w, 4);107#endif108}109}110111for (grp = 0; grp < grps; grp++) {112#if !RETRO_USE_ORIGINAL_CODE113memset(&mm, 0, sizeof(mm));114for (p = 0; p < 64; ++p) mm.w[p / 4] |= msg2[os + p] << (8 * (p % 4));115#else116// This only works as intended on little-endian CPUs.117memcpy(mm.b, msg2 + os, 64);118#endif119for (q = 0; q < 4; q++) abcd[q] = h[q];120for (p = 0; p < 4; p++) {121fctn = ff[p];122rotn = rots[p];123m = M[p];124o = O[p];125for (q = 0; q < 16; q++) {126g = (m * q + o) % 16;127f = abcd[1] + rol(abcd[0] + fctn(abcd) + k[q + 16 * p] + mm.w[g], rotn[q % 4]);128129abcd[0] = abcd[3];130abcd[3] = abcd[2];131abcd[2] = abcd[1];132abcd[1] = f;133}134}135for (p = 0; p < 4; p++) h[p] += abcd[p];136os += 64;137}138139if (msg2)140free(msg2);141142return h;143}144145char RSDK::textBuffer[0x400];146// Buffer is expected to be at least 16 bytes long147void RSDK::GenerateHashMD5(uint32 *buffer, char *textBuffer, int32 textBufferLen)148{149digest h; // storage var150uint8 *buf = (uint8 *)buffer;151unsigned *d = md5(h, textBuffer, textBufferLen);152WBunion u;153154for (int32 i = 0; i < 4; ++i) {155u.w = d[i];156for (int32 c = 0; c < 4; ++c) buf[(i << 2) + c] = u.b[c];157}158}159160uint32 crc32_t[256] = {1610x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,1620x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,1630x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,1640x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,1650x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,1660x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,1670x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,1680x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,1690x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,1700x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,1710x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,1720xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,1730xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,1740xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,1750xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,1760xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,1770x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,1780x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,1790x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,1800xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,1810xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,1820xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d183};184185void RSDK::GenerateHashCRC(uint32 *id, char *inputString)186{187*id = -1;188if (!inputString)189return;190191int32 len = 0;192do ++len;193while (inputString[len]);194195for (uint32 i = 0; i < len; i++) {196*id = crc32_t[(uint8)(*id ^ *inputString)] ^ (*id >> 8);197inputString++;198}199*id = ~*id;200}201202uint8 utf8CharSizes[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,2031, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,2041, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,2051, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,2061, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,2071, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,2082, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6 };209210void RSDK::SetString(String *string, const char *text)211{212if (!*text)213return;214215int32 newLength = 0;216for (int32 c = 0; text[c]; ++newLength) c += utf8CharSizes[*text & 0xFF];217218if (!newLength)219return;220221if (string->size < newLength || !string->chars) {222string->size = newLength;223AllocateStorage((void **)&string->chars, sizeof(uint16) * string->size, DATASET_STR, false);224}225226string->length = newLength;227for (int32 pos = 0; pos < string->length; ++pos) {228uint16 c = 0;229switch (utf8CharSizes[*text & 0xFF]) {230default: break;231232case 1:233c = text[0];234++text;235break;236237case 2:238c = (text[1] & 0x3F) | ((text[0] & 0x1F) << 6);239text += 2;240break;241242case 3:243c = (text[2] & 0x3F) | ((text[1] & 0x3F) << 6) | (text[0] << 12);244text += 3;245break;246247case 4:248c = (text[3] & 0x3F) | ((text[2] & 0x3F) << 6) | (text[1] << 12);249text += 4;250break;251252case 5: text += 5; break;253254case 6: text += 6; break;255}256257string->chars[pos] = c;258}259}260261void RSDK::AppendText(String *string, const char *appendString)262{263if (!*appendString)264return;265266int32 len = 0;267const char *textBuf = appendString;268int32 pos;269for (pos = 0; *textBuf; ++len) pos += utf8CharSizes[*textBuf++ & 0xFF];270(void)pos;271272if (!len)273return;274275int32 newSize = len + string->size;276if (string->size < newSize || !string->chars) {277if (string->chars) {278uint16 *charsStore = string->chars;279AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);280281for (int32 c = 0; c < string->length; ++c) string->chars[c] = charsStore[c];282charsStore = NULL;283}284else {285AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);286}287288string->size = newSize;289}290291for (int32 c = string->length; c < string->length + len; ++c) {292uint16 curChar = 0;293switch (utf8CharSizes[*appendString & 0xFF]) {294default: break;295296case 1:297curChar = appendString[0];298++appendString;299break;300301case 2:302curChar = (appendString[1] & 0x3F) | ((appendString[0] & 0x1F) << 6);303appendString += 2;304break;305306case 3:307curChar = (appendString[2] & 0x3F) | ((appendString[1] & 0x3F) << 6) | (appendString[0] << 12);308appendString += 3;309break;310311case 4:312curChar = (appendString[3] & 0x3F) | ((appendString[2] & 0x3F) << 6) | (appendString[1] << 12);313appendString += 4;314break;315316case 5: appendString += 5; break;317318case 6: appendString += 6; break;319}320321string->chars[c] = curChar;322}323324string->length = newSize;325}326327void RSDK::AppendString(String *string, String *appendString)328{329uint32 newSize = appendString->length + string->length;330331if (string->size < newSize || !string->chars) {332if (string->chars) {333uint16 *charsStore = string->chars;334AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);335336for (int32 c = 0; c < string->length; ++c) string->chars[c] = charsStore[c];337charsStore = NULL;338}339else {340AllocateStorage((void **)&string->chars, sizeof(uint16) * newSize, DATASET_STR, false);341}342343string->size = newSize;344}345346int32 startOffset = string->length;347string->length += appendString->length;348for (int32 c = 0, pos = startOffset; pos < string->length; ++pos, ++c) string->chars[pos] = appendString->chars[c];349}350351bool32 RSDK::CompareStrings(String *string1, String *string2, bool32 exactMatch)352{353if (string1->length != string2->length)354return false;355356if (exactMatch) { // each character has to match357for (int32 i = 0; i < string1->length; ++i) {358if (string1->chars[i] != string2->chars[i])359return false;360}361}362else { // ignore case sensitivity when matching363if (string1->length <= 0)364return true;365366for (int32 i = 0; i < string1->length; ++i) {367if (string1->chars[i] != string2->chars[i]) {368if (string1->chars[i] != (string2->chars[i] + 0x20) && string1->chars[i] != (string2->chars[i] - 0x20))369return false;370}371}372}373374return true;375}376377void RSDK::InitStringList(String *stringList, int32 size)378{379uint16 *text = NULL;380381AllocateStorage((void **)&text, sizeof(uint16) * size, DATASET_STR, false);382383for (int32 c = 0; c < size && c < stringList->length; ++c) text[c] = stringList->chars[c];384385CopyStorage((uint32 **)&stringList->chars, (uint32 **)&text);386stringList->size = size;387if (stringList->length > (uint16)size)388stringList->length = size;389}390391void RSDK::LoadStringList(String *stringList, const char *filePath, uint32 charSize)392{393char fullFilePath[0x40];394sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Strings/%s", filePath);395396FileInfo info;397InitFileInfo(&info);398if (LoadFile(&info, fullFilePath, FMODE_RB)) {399#if RETRO_REV02400uint16 header = ReadInt16(&info);401if (header == 0xFEFF) {402// UTF-16403InitStringList(stringList, (info.fileSize >> 1) - 1);404#if !RETRO_USE_ORIGINAL_CODE405for (int32 c = 0; c < stringList->size; ++c) stringList->chars[c] = ReadInt16(&info);406#else407// This only works as intended on little-endian CPUs.408ReadBytes(&info, stringList->chars, stringList->size * sizeof(uint16));409#endif410stringList->length = stringList->size;411}412else {413// UTF-8414if (header == 0xEFBB)415ReadInt8(&info);416else417Seek_Set(&info, 0);418419InitStringList(stringList, info.fileSize);420421for (int32 pos = 0; pos < info.fileSize; ++pos) {422int32 curChar = 0;423424uint8 bit = ReadInt8(&info);425switch (utf8CharSizes[bit]) {426case 1: curChar = bit; break;427case 2:428curChar = ((bit & 0x1F) << 6);429curChar |= (ReadInt8(&info) & 0x3F);430break;431432case 3:433curChar = (bit << 12);434curChar |= ((ReadInt8(&info) & 0x3F) << 6);435curChar |= ReadInt8(&info) & 0x3F;436break;437438case 4:439curChar = ReadInt8(&info) << 12;440curChar |= ((ReadInt8(&info) & 0x3F) << 6);441curChar |= ReadInt8(&info) & 0x3F;442break;443444case 5:445pos += 4;446Seek_Cur(&info, 4);447break;448449case 6:450pos += 5;451Seek_Cur(&info, 5);452break;453454default: break;455}456457stringList->chars[stringList->length++] = curChar;458}459}460#else461switch (charSize) {462default:463case 8: // ASCII464if (stringList->size < info.fileSize) {465stringList->size = info.fileSize;466AllocateStorage((void **)&stringList->chars, sizeof(uint16) * stringList->size, DATASET_STR, false);467}468stringList->length = info.fileSize;469InitStringList(stringList, info.fileSize);470471for (int32 c = 0; c < stringList->length; ++c) stringList->chars[c] = ReadInt8(&info);472break;473474case 16: // UTF-16475if (stringList->size < info.fileSize) {476stringList->size = info.fileSize >> 1;477AllocateStorage((void **)&stringList->chars, sizeof(uint16) * stringList->size, DATASET_STR, false);478}479stringList->length = info.fileSize >> 1;480InitStringList(stringList, info.fileSize >> 1);481482for (int32 c = 0; c < stringList->length; ++c) stringList->chars[c] = ReadInt16(&info);483break;484}485#endif486487CloseFile(&info);488}489}490491bool32 RSDK::SplitStringList(String *splitStrings, String *stringList, int32 startStringID, int32 stringCount)492{493if (!stringList->size || !stringList->chars)494return false;495496int32 lastCharPos = 0;497int32 curStringID = 0;498499bool32 hasSplitString = false;500for (int32 curCharPos = 0; curCharPos < stringList->length && stringCount > 0; ++curCharPos) {501if (stringList->chars[curCharPos] == '\n') {502if (curStringID < startStringID) {503lastCharPos = curCharPos;504}505else {506uint16 length = curCharPos - lastCharPos;507if (splitStrings->size < length) {508splitStrings->size = length;509AllocateStorage((void **)&splitStrings->chars, sizeof(uint16) * length, DATASET_STR, true);510}511splitStrings->length = length;512513for (int32 i = 0; i < splitStrings->length; ++i) splitStrings->chars[i] = stringList->chars[lastCharPos++];514515++splitStrings;516--stringCount;517hasSplitString = true;518}519520++curStringID;521++lastCharPos;522}523}524525return hasSplitString;526}527528#if RETRO_REV0U529int32 RSDK::FindStringToken(const char *string, const char *token, uint8 stopID)530{531int32 tokenCharID = 0;532bool32 tokenMatch = true;533int32 stringCharID = 0;534int32 foundTokenID = 0;535536while (string[stringCharID]) {537tokenCharID = 0;538tokenMatch = true;539while (token[tokenCharID]) {540if (!string[tokenCharID + stringCharID])541return -1;542543if (string[tokenCharID + stringCharID] != token[tokenCharID])544tokenMatch = false;545546++tokenCharID;547}548if (tokenMatch && ++foundTokenID == stopID)549return stringCharID;550551++stringCharID;552}553return -1;554}555#endif556557