#include #include #include #include char statname[256]; unsigned long keys[256] = { 0x697A5, 0x6045C, 0xAB4E2, 0x409E4, 0x71209, 0x32392, 0xA7292, 0xB09FC, 0x4B658, 0xAAAD5, 0x9B9CF, 0xA326A, 0x8DD12, 0x38150, 0x8E14D, 0x2EB7F, 0xE0A56, 0x7E6FA, 0xDFC27, 0xB1301, 0x8B4F7, 0xA7F70, 0xAA713, 0x6CC0F, 0x6FEDF, 0x2EC87, 0xC0F1C, 0x45CA4, 0x30DF8, 0x60E99, 0xBC13E, 0x4E0B5, 0x6318B, 0x82679, 0x26EF2, 0x79C95, 0x86DDC, 0x99BC0, 0xB7167, 0x72532, 0x68765, 0xC7446, 0xDA70D, 0x9D132, 0xE5038, 0x2F755, 0x9171F, 0xCB49E, 0x6F925, 0x601D3, 0x5BD8A, 0x2A4F4, 0x9B022, 0x706C3, 0x28C10, 0x2B24B, 0x7CD55, 0xCA355, 0xD95F4, 0x727BC, 0xB1138, 0x9AD21, 0xC0ACA, 0xCD928, 0x953E5, 0x97A20, 0x345F3, 0xBDC03, 0x7E157, 0x96C99, 0x968EF, 0x92AA9, 0xC2276, 0xA695D, 0x6743B, 0x2723B, 0x58980, 0x66E08, 0x51D1B, 0xB97D2, 0x6CAEE, 0xCC80F, 0x3BA6C, 0xB0BF5, 0x9E27B, 0xD122C, 0x48611, 0x8C326, 0xD2AF8, 0xBB3B7, 0xDED7F, 0x4B236, 0xD298F, 0xBE912, 0xDC926, 0xC873F, 0xD0716, 0x9E1D3, 0x48D94, 0x9BD91, 0x5825D, 0x55637, 0xB2057, 0xBCC6C, 0x460DE, 0xAE7FB, 0x81B03, 0x34D8F, 0xC0528, 0xC9B59, 0x3D260, 0x6051D, 0x93757, 0x8027F, 0xB7C34, 0x4A14E, 0xB12B8, 0xE4945, 0x28203, 0xA1C0F, 0xAA382, 0x46ABB, 0x330B9, 0x5A114, 0xA754B, 0xC68D0, 0x9040E, 0x6C955, 0xBB1EF, 0x51E6B, 0x9FF21, 0x51BCA, 0x4C879, 0xDFF70, 0x5B5EE, 0x29936, 0xB9247, 0x42611, 0x2E353, 0x26F3A, 0x683A3, 0xA1082, 0x67333, 0x74EB7, 0x754BA, 0x369D5, 0x8E0BC, 0xABAFD, 0x6630B, 0xA3A7E, 0xCDBB1, 0x8C2DE, 0x92D32, 0x2F8ED, 0x7EC54, 0x572F5, 0x77461, 0xCB3F5, 0x82C64, 0x35FE0, 0x9203B, 0xADA2D, 0xBAEBD, 0xCB6AF, 0xC8C9A, 0x5D897, 0xCB727, 0xA13B3, 0xB4D6D, 0xC4929, 0xB8732, 0xCCE5A, 0xD3E69, 0xD4B60, 0x89941, 0x79D85, 0x39E0F, 0x6945B, 0xC37F8, 0x77733, 0x45D7D, 0x25565, 0xA3A4E, 0xB9F9E, 0x316E4, 0x36734, 0x6F5C3, 0xA8BA6, 0xC0871, 0x42D05, 0x40A74, 0x2E7ED, 0x67C1F, 0x28BE0, 0xE162B, 0xA1C0F, 0x2F7E5, 0xD505A, 0x9FCC8, 0x78381, 0x29394, 0x53D6B, 0x7091D, 0xA2FB1, 0xBB942, 0x29906, 0xC412D, 0x3FCD5, 0x9F2EB, 0x8F0CC, 0xE25C3, 0x7E519, 0x4E7D9, 0x5F043, 0xBBA1B, 0x6710A, 0x819FB, 0x9A223, 0x38E47, 0xE28AD, 0xB690B, 0x42328, 0x7CF7E, 0xAE108, 0xE54BA, 0xBA5A1, 0xA09A6, 0x9CAB7, 0xDB2B3, 0xA98CC, 0x5CEBA, 0x9245D, 0x5D083, 0x8EA21, 0xAE349, 0x54940, 0x8E557, 0x83EFD, 0xDC504, 0xA6059, 0xB85C9, 0x9D162, 0x7AEB6, 0xBED34, 0xB4963, 0xE367B, 0x4C891, 0x9E42C, 0xD4304, 0x96EAA, 0xD5D69, 0x866B8, 0x83508, 0x7BAEC, 0xD03FD, 0xDA122 }; unsigned long MakeStrHash(const char *str){ register unsigned long result = 0xDEADC0DE; register unsigned long tkey = 0x7FED7FED; register char c = 0; while (*(str)){ c = (*str<'a'||*str>'z')?*str:*str-32; result += tkey; tkey *= 0x21; result ^= keys[c]; tkey += result + c + 3; str++; } return result; } FILE* logfile; void bprintf( char* format, ... ) { va_list args; va_start( args, format ); //vprintf( format, args ); vfprintf( logfile, format, args ); va_end( args ); }; struct qsdentry { unsigned conditioncount; unsigned rewardcount; char name[128]; void* data; }; struct qsdblock { unsigned entrycount; char name[128]; qsdentry* entries; }; char* GetStatName( unsigned statid ) { switch( statid ) { { case 2: return "Gender"; case 3: return "Union"; case 10: return "Strength"; case 11: return "Dexterity"; case 12: return "Intelligence"; case 13: return "Concentration"; case 14: return "Charm"; case 15: return "Sensibility"; case 16: return "HP"; case 17: return "MP"; case 18: return "Attack Power"; case 19: return "Defence Power"; case 20: return "Hit Rate"; case 21: return "Magic Resistance"; case 22: return "Dodge Rate"; case 23: return "MSpeed"; case 31: return "Level"; case 40: return "Money"; default: { sprintf_s( statname, 256, "STAT: %u", statid ); return statname; } }; } } char* GetOperator( unsigned operatorid ) { switch( operatorid ) { case 0: return "=="; case 1: return "<="; case 2: return ">="; case 3: return "<"; case 4: return ">"; case 5: return "="; case 6: return "+="; case 7: return "-="; default: return "???"; } } int ReadQSD( char* filename ) { FILE* myqsd; unsigned fileversion; unsigned blockcount; unsigned tmp; unsigned short strreadlen; unsigned questhash; char buffer[2048]; qsdblock* blocks; fopen_s( &myqsd, filename, "rb" ); if( !myqsd ) { printf( "Could not open the qsd file '%s'", filename ); system( "pause" ); return 0; } fread( &fileversion, 4, 1, myqsd ); fread( &blockcount, 4, 1, myqsd ); fread( &strreadlen, 2, 1, myqsd ); fread( &buffer[0], 1, strreadlen, myqsd ); blocks = new qsdblock[blockcount]; for( unsigned i = 0; i < blockcount; i++ ) { fread( &blocks[i].entrycount, 4, 1, myqsd ); fread( &strreadlen, 2, 1, myqsd ); fread( &blocks[i].name[0], 1, strreadlen, myqsd ); bprintf( "|-Block %u - Name: %s\n", i, blocks[i].name ); blocks[i].entries = new qsdentry[blocks[i].entrycount]; for( unsigned j = 0; j < blocks[i].entrycount; j++ ) { fseek( myqsd, 1, SEEK_CUR ); fread( &blocks[i].entries[j].conditioncount, 4, 1, myqsd ); fread( &blocks[i].entries[j].rewardcount, 4, 1, myqsd ); fread( &strreadlen, 2, 1, myqsd ); fread( &blocks[i].entries[j].name, 1, strreadlen, myqsd ); bprintf( "| |-Entry %u - Name: %s\n", j, blocks[i].entries[j].name ); questhash = MakeStrHash( blocks[i].entries[j].name ); bprintf( "| | |-Hash: %08x\n", questhash ); bprintf( "| | |-%c730 3 0 %02x %02x %02x %02x\n", '%', questhash & 0xFF, ( questhash >> 8 ) & 0xFF, ( questhash >> 16 ) & 0xFF, ( questhash >> 24 ) & 0xFF ); for( unsigned k = 0; k < blocks[i].entries[j].conditioncount + blocks[i].entries[j].rewardcount; k++ ) { if( k == 0 && blocks[i].entries[j].conditioncount > 0 ) { bprintf( "| | |-Conditions\n" ); } if( k == blocks[i].entries[j].conditioncount ) { bprintf( "| | |-Rewards\n" ); } fread( &tmp, 4, 1, myqsd ); fread( &buffer[0], 1, tmp - 4, myqsd ); switch( *((unsigned*)&buffer[0]) ) { case 0x00000000: { bprintf( "| | | |- Must have quest id: %u\n", *((unsigned*)&buffer[4]) ); break; } case 0x00000003: { // Check Stat bprintf( "| | | |- %s MUST BE %s %u\n", GetStatName( *((unsigned*)&buffer[8]) ), GetOperator( buffer[16] ), *((unsigned*)&buffer[12]) ); break; } case 0x00000004: { // Check for item bprintf( "| | | |- MUST HAVE ITEM - TYPE:%u ID:%u COUNT:%u\n", *((unsigned*)&buffer[8])/1000, *((unsigned*)&buffer[8])%1000, *((unsigned*)&buffer[16]) ); break; } case 0x00000009: { // Check for Skill bprintf( "| | | |- MUST HAVE SKILL %u\n", *((unsigned*)&buffer[4]) ); break; } case 0x0000000E: { // Check Quest Flag bprintf( "| | | |- Flag ID: %u MUST BE %u\n", *((unsigned short*)&buffer[4]), *((unsigned short*)&buffer[6]) ); break; } case 0x01000000: { // Activate quest?? bprintf( "| | | |- Quest %u activated\n", *((unsigned short*)&buffer[4]) ); break; } case 0x01000001: { // Remove item?? bprintf( "| | | |- Remove item - TYPE:%u ID:%u\n", *((unsigned*)&buffer[4])/1000, *((unsigned*)&buffer[4])%1000 ); break; } case 0x01000003: { // Set Stat bprintf( "| | | |- SET %s %s %u\n", GetStatName( *((unsigned*)&buffer[8]) ), GetOperator( buffer[16] ), *((unsigned*)&buffer[12]) ); break; } case 0x01000005: { if( *((unsigned short*)&buffer[4]) == 0x502 ) { bprintf( "| | | |- Give Item - TYPE:%u ID:%u COUNT:%u\n", *((unsigned*)&buffer[12])/1000, *((unsigned*)&buffer[12])%1000,*((unsigned*)&buffer[8]) ); }else if( *((unsigned short*)&buffer[4]) == 0 ) { bprintf( "| | | |- Give EXP: %u\n", *((unsigned*)&buffer[8]) ); }else{ bprintf( "| | | |- Unknown Item Opcode\n" ); } break; } case 0x01000007: { float telex = (float)*((unsigned*)&buffer[8]) / 100; float teley = (float)*((unsigned*)&buffer[12]) / 100; bprintf( "| | | |- Teleport to: %u %.2f,%.2f\n", *((unsigned short*)&buffer[4]), telex, teley ); break; } case 0x01000009: { bprintf( "| | | |- Activate quest trigger: '%s'\n", &buffer[6] ); break; } case 0x0100000E: { // Learn Skill? bprintf( "| | | |- Learn skill %u\n", *((unsigned*)&buffer[8]) ); break; } case 0x0100000F: { // Set Quest Flag bprintf( "| | | |- Flag ID: %u SET TO %u\n", *((unsigned short*)&buffer[4]), *((unsigned short*)&buffer[6]) ); break; } case 0x0100001D: { // Activate external function? bprintf( "| | | |- Activate External function: '%s'\n", &buffer[6] ); break; } default: { bprintf( "| | | |- Unknown Opcode: %08x\n", *((unsigned*)&buffer[0]) ); break; } } } } } fclose( myqsd ); return 1; } int main( int argc, char* argv[] ) { FILE* mylist; unsigned curbyte = 0; char buffer[200]; fopen_s( &logfile, "C:\\qsddec.log", "wt" ); if( !logfile ) { printf( "Could not open the log file..." ); system( "pause" ); return 0; } fopen_s( &mylist, "qsdlist.txt", "rb" ); while( !feof( mylist ) ) { fread( &buffer[curbyte], 1, 1, mylist ); if( buffer[curbyte] == 0x0A ) { buffer[curbyte] = 0; ReadQSD( &buffer[0] ); curbyte = 0; }else{ curbyte++; } } fclose( mylist ); fclose( logfile ); system( "pause" ); return 0; }