/* Copyright (C) 2008, 2009 TitanFiesta Dev Team * Licensed under GNU GPL v3 * For license details, see LICENCE in the root folder. */ class CSHN { public: struct SSHNColumn { SSHNColumn():showInHex(false){} ~SSHNColumn(){} char name[0x30]; dword type; dword columnSize; bool showInHex; }; struct SSHNRowData { SSHNRowData():data(NULL){} ~SSHNRowData(){DEL(data);} dword length; byte* data; }; struct SSHNRow { SSHNRow(){} ~SSHNRow(){DELVEC(data);} word rowSize; std::vector data; }; CSHN(){} ~CSHN(){ DELVEC(rows); DELVEC(columns); } void Open(char* path){ FILE* fh2; fopen_s(&fh2, path, "rb"); if(fh2 == NULL) return; fseek(fh2, 0, SEEK_END); long int filesize = ftell(fh2); fseek(fh2, 0, SEEK_SET); unsigned char* data = new unsigned char[filesize]; fread(data, filesize, 1, fh2); fclose(fh2); Decrypt(data + 0x24, filesize - 0x24); CTitanFile fh(data, filesize); fh.Skip(0x28); dword rowCount = fh.Read(); fh.Skip(4); dword cols = fh.Read(); for(dword i = 0; i < cols; i++){ SSHNColumn* curCol = new SSHNColumn(); fh.ReadBuffer(reinterpret_cast(curCol), 0x38); curCol->showInHex = false; columns.push_back(curCol); } for(dword i = 0; i < rowCount; i++){ SSHNRow* curRow = new SSHNRow(); curRow->rowSize = fh.Read(); for(dword j = 0; j < columns.size(); j++){ SSHNRowData* curData = new SSHNRowData(); SSHNColumn* curCol = columns[j]; switch(curCol->type){ case 1: curData->length = 1; curData->data = new byte[curData->length]; curData->data[0] = fh.Read(); break; case 2: curData->length = 2; curData->data = new byte[curData->length]; *reinterpret_cast(curData->data) = fh.Read(); break; case 3: curData->length = 4; curData->data = new byte[curData->length]; *reinterpret_cast(curData->data) = fh.Read(); break; case 9: curData->length = curCol->columnSize; curData->data = fh.ReadBytes(curCol->columnSize); break; case 11: curData->length = 4; curData->data = new byte[curData->length]; *reinterpret_cast(curData->data) = fh.Read(); break; case 18: curData->length = 4; curData->data = new byte[curData->length]; *reinterpret_cast(curData->data) = fh.Read(); break; case 26: curData->data = reinterpret_cast(fh.ReadNullString()); curData->length = strlen(reinterpret_cast(curData->data)); break; case 27: curData->length = 4; curData->data = new byte[curData->length]; *reinterpret_cast(curData->data) = fh.Read(); break; default: curData->length = curCol->columnSize; curData->data = fh.ReadBytes(curData->length); } curRow->data.push_back(curData); } rows.push_back(curRow); } fh.Close(); DEL(data); } std::vector columns; std::vector rows; private: unsigned char* Decrypt(unsigned char* data, long int filesize) { byte key = filesize & 0xFF; for(long int i = filesize - 1; i > 0; --i){ data[i] ^= key; byte tmp1 = ( 0x0b * (byte)i ); byte tmp2 = ( i & 0x0f ) + 0x55; key ^= (tmp1 ^ tmp2) ^ 0xaa; } return data; } };