Source: Metin2FileExtractor

Topic created · 3 Mensajes · 1619 Visitas
  • Recientemente me adentre al mundo de c++ y otros como delphi hace rato se habia hecho publica la source con la que hicieron el descompilador de metin2 hoy la dejo aqui lista para ser aplicada no la he podido testear ya que ningún programa de programación en c me quiere servir...

    Source code:
    /*
    Metin2FileExtractor
    pushedx
    edxLabs

    This program serves as a file extractor for the Metin2 data files. The
    EIX files are the header files and the EPK files are the data files.
    The data can be uncompressed, encrypted, and/or compressed. This code
    shows how the client performs the logic.

    This was a "for fun" project and done in about ~12 hours of work. I am
    releasing this tool and the source code to the elitepvperss' Metin2
    community to help spread new knowledge. I have no immediate plans for
    a file editor at this time as I'm not playing the game or doing
    anything with it. Maybe sometime later though.

    I hope you enjoy!
    */

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    #include
    #include
    #include

    //--------------------------------------------------------------------------

    // Dumps a complete archive
    bool DumpArchive(const char * inFolder, const char * name);

    //--------------------------------------------------------------------------

    int main(int argc, char * argv[])
    {
    system("cls");
    printf("Welcome to the Metin2 File Extractor!\n");
    printf("This program was made by pushedx for the elitepvpers' Metin2 community.\n");
    printf("This is a free tool for all to use.\n");
    printf("It should work on the US/DE version files but Korea is not tested.\n");
    printf("Enjoy :)\n\n");
    if(argc != 3)
    {
    printf("Usage: Metin2FileExtractor \n");
    printf("Examples:\n");
    printf("\tMetin2FileExtractor \"C:\\Program Files\\Subagames\\Metin2\\pack\" BGM\n");
    printf("\tMetin2FileExtractor \"C:\\Program Files\\Subagames\\Metin2\\pack\" PC\n");
    printf("\tMetin2FileExtractor \"C:\\Program Files\\Metin2_Germany\\pack\" ETC\n");
    printf("\tMetin2FileExtractor \"C:\\Program Files\\Metin2_Germany\\pack\" root\n");
    system("pause");
    return -1;
    }
    std::string safecheck = argv[2];
    if(safecheck.find_first_of("!@#$%^&*()+={}[]|\\:\";\'<>?,./") != std::string::npos)
    {
    printf("Error: The Archive title (%s) contains invalid characters. The program will now exit.\n", argv[2]);
    return -1;
    }
    printf("Beginning the archive dump. Please be patient while it finishes.\n\n");
    bool result = DumpArchive(argv[1], argv[2]);
    if(result == true)
    {
    printf("The archive dump was successful!\n");
    }
    else
    {
    printf("The archive dump was not successful.\n");
    }
    printf("Thank you for using the Metin2 File Extractor!\n");
    system("pause");
    return 0;
    }

    //--------------------------------------------------------------------------

    // The expected magic header value
    #define LZ_KEY 0x5A4F434D

    //--------------------------------------------------------------------------

    struct TEntry1
    {
    DWORD index;
    char filename[160];
    DWORD dw1;
    DWORD dw2;
    DWORD dw3;
    DWORD dwSrcSize;
    DWORD unpackedCRC;
    DWORD dwFileOffset;
    BYTE packedType;
    BYTE b2;
    BYTE b3;
    BYTE b4;
    };

    struct TEntry2
    {
    DWORD header;
    DWORD decryptedBlockSize;
    DWORD compressedBlockSize;
    DWORD decompressedBlockSize;
    };

    struct TEntry3
    {
    DWORD header;
    DWORD version;
    DWORD fileCount;
    };

    //--------------------------------------------------------------------------

    // For decompressing (ripped from client)
    BYTE gLZOData[] =
    {
    0xB9, 0x9E, 0xB0, 0x02, 0x6F, 0x69, 0x81, 0x05,
    0x63, 0x98, 0x9B, 0x28, 0x79, 0x18, 0x1A, 0x00,
    };

    // For decrypting (ripped from client)
    BYTE gLZOData2[] =
    {
    0x22, 0xB8, 0xB4, 0x04, 0x64, 0xB2, 0x6E, 0x1F,
    0xAE, 0xEA, 0x18, 0x00, 0xA6, 0xF6, 0xFB, 0x1C,
    };

    //--------------------------------------------------------------------------

    // Utility decompress function
    __declspec(naked) void ASM_LZO_FUNC1()
    {
    __asm
    {
    MOV EDX, DWORD PTR SS:[ESP + 0x08]
    MOV ECX, DWORD PTR SS:[ESP + 0x04]
    PUSH EBX
    PUSH EBP
    PUSH ESI
    MOV ESI, DWORD PTR SS:[ESP + 0x18]
    PUSH EDI
    MOV EAX, 0xC6EF3720
    MOV EDI, 0x20
    LEA EBX, DWORD PTR DS:[EBX]
    LABEL1:
    MOV EBX, EDX
    SHR EBX, 0x5
    MOV EBP, EDX
    SHL EBP, 0x4
    XOR EBX, EBP
    MOV EBP, EAX
    SHR EBP, 0x0B
    AND EBP, 0x03
    MOV EBP, DWORD PTR DS:[ESI + EBP * 0x04]
    ADD EBP, EAX
    ADD EBX, EDX
    XOR EBX, EBP
    SUB ECX, EBX
    MOV EBX, ECX
    SHR EBX, 0x05
    MOV EBP, ECX
    SHL EBP, 0x04
    XOR EBX, EBP
    ADD EAX, 0x61C88647
    MOV EBP, EAX
    AND EBP, 0x03
    MOV EBP, DWORD PTR DS:[ESI + EBP * 0x04]
    ADD EBX, ECX
    ADD EBP, EAX
    XOR EBX, EBP
    SUB EDX, EBX
    DEC EDI
    JNZ LABEL1
    MOV EAX, DWORD PTR SS:[ESP + 0x20]
    POP EDI
    POP ESI
    POP EBP
    MOV DWORD PTR DS:[EAX], EDX
    MOV DWORD PTR DS:[EAX + 0x04], ECX
    POP EBX
    RETN
    }
    }

    //--------------------------------------------------------------------------

    // Decompress function in the client
    __declspec(naked) void ASM_LZO_CHECKKEY()
    {
    __asm
    {
    MOV EAX,DWORD PTR SS:[ESP + 0x10]
    MOV ECX, EAX
    AND ECX, 0x80000007
    JNG LABEL1
    DEC ECX
    OR ECX, 0xFFFFFFF8
    INC ECX
    LABEL1:
    JE LABEL2
    SUB EAX, ECX
    ADD EAX, 8
    MOV DWORD PTR SS:[ESP + 0x10],EAX
    JMP LABEL3;
    LABEL2:
    MOV DWORD PTR SS:[ESP + 0x10],EAX
    LABEL3:
    PUSH EBX
    MOV EBX, EAX
    SAR EBX, 0x03
    TEST EBX, EBX
    JLE LABEL5

    PUSH EBP
    //MOV EBP, lzoData
    MOV EBP, [ESP + 0x14]

    PUSH ESI
    //MOV ESI, inData
    MOV ESI, [ESP + 0x14]

    PUSH EDI
    //MOV EDI, outBuffer
    MOV EDI, [ESP + 0x14]
    LABEL4:
    MOV EAX,DWORD PTR DS:[ESI]
    MOV ECX,[ESI + 0x04]
    PUSH EDI
    PUSH EBP
    PUSH EAX
    PUSH ECX
    CALL ASM_LZO_FUNC1
    ADD ESP, 0x10
    ADD EDI, 0x08
    ADD ESI, 0x08
    DEC EBX
    JNZ LABEL4
    MOV EAX,DWORD PTR SS:[ESP + 0x20]
    POP EDI
    POP ESI
    POP EBP
    LABEL5:
    POP EBX
    RET
    }
    }

    //--------------------------------------------------------------------------

    // Wrapper function to decompress data
    int LZObject_CheckKey(LPBYTE outBuffer, LPBYTE inData, LPBYTE lzoData, DWORD dwSize)
    {
    int result = 1;
    __asm
    {
    mov edx, dwSize

    mov ecx, inData
    sub ecx, 4

    mov eax, lzoData

    mov edi, outBuffer

    push edx
    push eax
    push ecx
    push edi

    call ASM_LZO_CHECKKEY

    MOV EDX, DWORD PTR DS:[EDI]
    MOV EAX, LZ_KEY
    ADD ESP, 0x10
    CMP EDX, EAX
    JE LABEL1
    mov result, 0
    LABEL1:
    NOP
    }
    return result;
    }

    //--------------------------------------------------------------------------

    // Ripped from the client via OllyDbg. It was tedious, but simple work since
    // you can set labels in OllyDbg for the new jump locations.
    __declspec(naked) void ASM_LZO_DECOMPRESS()
    {
    __asm
    {
    MOV EAX,DWORD PTR SS:[ESP+0x08]
    PUSH EBX
    MOV EBX,DWORD PTR SS:[ESP+0x14]
    PUSH EBP
    PUSH ESI
    MOV ESI,DWORD PTR SS:[ESP+0x10]
    MOV DWORD PTR DS:[EBX],0x00
    PUSH EDI
    MOV CL,BYTE PTR DS:[ESI]
    LEA EBP,DWORD PTR DS:[ESI+EAX]
    MOV EAX,DWORD PTR SS:[ESP+0x1C]
    CMP CL,0x11
    JBE label1
    AND ECX,0xFF
    SUB ECX,0x11
    INC ESI
    CMP ECX,0x04
    JB label2
    label3:
    MOV DL,BYTE PTR DS:[ESI]
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    INC ESI
    DEC ECX
    JNZ label3
    JMP label4
    label1:
    XOR ECX,ECX
    MOV CL,BYTE PTR DS:[ESI]
    INC ESI
    CMP ECX,0x10
    JNB label5
    TEST ECX,ECX
    JNZ label6
    CMP BYTE PTR DS:[ESI],0x00
    JNZ label7
    label8:
    MOV DL,BYTE PTR DS:[ESI+0x01]
    ADD ECX,0xFF
    INC ESI
    TEST DL,DL
    JE label8
    label7:
    XOR EDX,EDX
    MOV DL,BYTE PTR DS:[ESI]
    INC ESI
    LEA ECX,DWORD PTR DS:[ECX+EDX+0x0F]
    label6:
    MOV EDX,DWORD PTR DS:[ESI]
    ADD ESI,0x04
    MOV DWORD PTR DS:[EAX],EDX
    ADD EAX,0x04
    DEC ECX // Switch (cases 1..4)
    JE label4
    CMP ECX,0x04
    JB label9
    label10:
    MOV EDX,DWORD PTR DS:[ESI] // Default case of switch 0055BACA
    SUB ECX,0x04
    MOV DWORD PTR DS:[EAX],EDX
    ADD EAX,0x04
    ADD ESI,0x04
    CMP ECX,0x04
    JNB label10
    TEST ECX,ECX
    JBE label4
    label11:
    MOV DL,BYTE PTR DS:[ESI]
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    INC ESI
    DEC ECX
    JNZ label11
    JMP label4
    label9:
    MOV DL,BYTE PTR DS:[ESI] // Cases 2,3,4 of switch 0055BACA
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    INC ESI
    DEC ECX
    JNZ label9
    label4:
    XOR ECX,ECX // Case 1 of switch 0055BACA
    MOV CL,BYTE PTR DS:[ESI]
    INC ESI
    CMP ECX,0x10
    JNB label5
    SHR ECX,0x02
    MOV EDX,EAX
    SUB EDX,ECX
    XOR ECX,ECX
    MOV CL,BYTE PTR DS:[ESI]
    SHL ECX,0x02
    SUB EDX,ECX
    MOV CL,BYTE PTR DS:[EDX-0x801]
    SUB EDX,0x0801
    INC ESI
    MOV BYTE PTR DS:[EAX],CL
    INC EAX
    INC EDX
    lable28:
    MOV CL,BYTE PTR DS:[EDX]
    MOV BYTE PTR DS:[EAX],CL
    MOV DL,BYTE PTR DS:[EDX+0x01]
    INC EAX
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    label14:
    MOV CL,BYTE PTR DS:[ESI-0x02]
    AND ECX,0x03
    JE label1
    label2:
    MOV DL,BYTE PTR DS:[ESI]
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    INC ESI
    DEC ECX
    JNZ label2
    XOR ECX,ECX
    MOV CL,BYTE PTR DS:[ESI]
    INC ESI
    label5:
    CMP ECX,0x40 // Switch (cases 0..3F)
    JB label12
    MOV EDX,ECX // Default case of switch label5
    MOV EDI,EAX
    SHR EDX,0x02
    AND EDX,0x07
    SUB EDI,EDX
    XOR EDX,EDX
    MOV DL,BYTE PTR DS:[ESI]
    SHL EDX,0x03
    SUB EDI,EDX
    DEC EDI
    INC ESI
    SHR ECX,0x05
    DEC ECX
    label25:
    MOV DL,BYTE PTR DS:[EDI]
    MOV BYTE PTR DS:[EAX],DL
    MOV DL,BYTE PTR DS:[EDI+0x01]
    INC EAX
    INC EDI
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    INC EDI
    label13:
    MOV DL,BYTE PTR DS:[EDI]
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    INC EDI
    DEC ECX
    JNZ label13
    JMP label14
    label12:
    CMP ECX,0x20
    JB label15
    AND ECX,0x1F // Cases 20,21,22,23,24,25,26,27,28,29,2A,2B,2C,2D,2E,2F,30,31,32,33,34,35,36,37,38,39,3A,3B,3C,3D,3E,3F of switch label5
    JNZ label16
    CMP BYTE PTR DS:[ESI],0
    JNZ label17
    label18:
    MOV DL,BYTE PTR DS:[ESI+0x01]
    ADD ECX,0xFF
    INC ESI
    TEST DL,DL
    JE label18
    label17:
    XOR EDX,EDX
    MOV DL,BYTE PTR DS:[ESI]
    INC ESI
    LEA ECX,DWORD PTR DS:[ECX+EDX+0x1F]
    label16:
    XOR EDX,EDX
    MOV EDI,EAX
    MOV DX,WORD PTR DS:[ESI]
    SHR EDX,0x02
    SUB EDI,EDX
    DEC EDI
    ADD ESI,0x02
    JMP label19
    label15:
    CMP ECX,0x10
    JB label20
    MOV EDX,ECX // Cases 10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F of switch label5
    MOV EDI,EAX
    AND EDX,0x08
    SHL EDX,0x0B
    SUB EDI,EDX
    AND ECX,0x07
    JNZ label21
    CMP BYTE PTR DS:[ESI],0x00
    JNZ label22
    label23:
    MOV DL,BYTE PTR DS:[ESI+0x01]
    ADD ECX,0xFF
    INC ESI
    TEST DL,DL
    JE label23
    label22:
    XOR EDX,EDX
    MOV DL,BYTE PTR DS:[ESI]
    INC ESI
    LEA ECX,DWORD PTR DS:[ECX+EDX+0x07]
    label21:
    XOR EDX,EDX
    MOV DX,WORD PTR DS:[ESI]
    ADD ESI,0x02
    SHR EDX,0x02
    SUB EDI,EDX
    CMP EDI,EAX
    JE label24
    SUB EDI,0x4000
    label19:
    CMP ECX,0x06
    JB label25
    MOV EDX,EAX
    SUB EDX,EDI
    CMP EDX,0x04
    JL label25
    MOV EDX,DWORD PTR DS:[EDI]
    ADD EDI,0x04
    MOV DWORD PTR DS:[EAX],EDX
    ADD EAX,0x04
    SUB ECX,0x02
    label26:
    MOV EDX,DWORD PTR DS:[EDI]
    SUB ECX,0x04
    MOV DWORD PTR DS:[EAX],EDX
    ADD EAX,0x04
    ADD EDI,0x04
    CMP ECX,0x04
    JNB label26
    TEST ECX,ECX
    JBE label14
    label27:
    MOV DL,BYTE PTR DS:[EDI]
    MOV BYTE PTR DS:[EAX],DL
    INC EAX
    INC EDI
    DEC ECX
    JNZ label27
    JMP label14
    label20:
    SHR ECX,0x02 // Cases 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F of switch label5
    MOV EDX,EAX
    SUB EDX,ECX
    XOR ECX,ECX
    MOV CL,BYTE PTR DS:[ESI]
    SHL ECX,0x02
    SUB EDX,ECX
    DEC EDX
    INC ESI
    JMP lable28
    label24:
    MOV ECX,DWORD PTR SS:[ESP+0x1C]
    SUB EAX,ECX
    CMP ESI,EBP
    MOV DWORD PTR DS:[EBX],EAX
    JNZ label29
    POP EDI
    POP ESI
    POP EBP
    XOR EAX,EAX
    POP EBX
    RETN
    label29:
    SBB EAX,EAX
    POP EDI
    AND AL,0xFC
    POP ESI
    POP EBP
    ADD EAX, -4
    POP EBX
    RETN
    }
    }

    //--------------------------------------------------------------------------

    // Decompress wrapper function
    void LZObject_Decompress(LPBYTE src, DWORD srcLen, LPBYTE dst, DWORD * ptrNewLen, void * workMemory)
    {
    __asm
    {
    MOV EDI, src
    MOV EAX, dst
    push workMemory
    MOV EDX, ptrNewLen
    push EDX
    MOV EDX, srcLen
    PUSH EAX
    PUSH EDX
    ADD EDI, 4
    PUSH EDI
    call ASM_LZO_DECOMPRESS
    ADD ESP, 0x14
    TEST EAX, EAX
    JE LABEL1
    INT 3 // Error, don't continue
    LABEL1:
    NOP
    }
    }

    //--------------------------------------------------------------------------

    // Tokenizes a string into a vector
    std::vector TokenizeString(const std::string& str, const std::string& delim)
    {
    // [http://www.gamedev.net/community/forums/topic.asp?topic_id=381544#TokenizeString][0]">[http://www.gamedev.net/community/forums][1] ... nizeString
    using namespace std;
    vector tokens;
    size_t p0 = 0, p1 = string::npos;
    while(p0 != string::npos)
    {
    p1 = str.find_first_of(delim, p0);
    if(p1 != p0)
    {
    string token = str.substr(p0, p1 - p0);
    tokens.push_back(token);
    }
    p0 = str.find_first_not_of(delim, p1);
    }
    return tokens;
    }

    //--------------------------------------------------------------------------

    // Saves the file to a specific folder based on the path. The root
    // directory I choose to use is named 'output'.
    void SaveFile(const char * originalFilename, LPBYTE outBuffer, DWORD outBufferSize)
    {
    std::stringstream dirPath;
    std::vector pathTokens = TokenizeString(originalFilename, "\\/");

    dirPath << "output";
    CreateDirectoryA(dirPath.str().c_str(), NULL);
    dirPath << "\\";

    size_t index = 0;
    for(index = 0; index < pathTokens.size() - 1; ++index)
    {
    if(pathTokens[index].find_first_of(":") != std::string::npos)
    continue;
    dirPath << pathTokens[index];
    CreateDirectoryA(dirPath.str().c_str(), NULL);
    dirPath << "\\";
    }

    dirPath << pathTokens[index];

    FILE * of = fopen(dirPath.str().c_str(), "wb");
    if(of)
    {
    fwrite(outBuffer, 1, outBufferSize, of);
    fclose(of);
    }
    else
    {
    printf("Could not save the file %s\n", dirPath.str().c_str());
    }
    }

    //--------------------------------------------------------------------------

    // Dumps a complete archive. I have combined two sets of logic for this,
    // but you can separate them if you want a more unique tool that allows
    // you to extract individual files or explore the contents.
    bool DumpArchive(const char * inFolder, const char * name)
    {
    HANDLE eixHandle = INVALID_HANDLE_VALUE;
    HANDLE epkHandle = INVALID_HANDLE_VALUE;
    SECURITY_ATTRIBUTES eixSecurity = {0};
    SECURITY_ATTRIBUTES epkSecurity = {0};
    DWORD eixFileSize = 0;
    DWORD epkFileSize = 0;
    HANDLE eixFileMapping = NULL;
    HANDLE epkFileMapping = NULL;
    LPBYTE eixFileBufferPtr = NULL;
    LPBYTE epkFileBufferPtr = NULL;
    bool bWasError = false;

    std::string eixName_ = inFolder;
    if(!(eixName_[eixName_.size() - 1] == '\\' || eixName_[eixName_.size() - 1] == '/'))
    {
    eixName_ += "\\";
    }
    eixName_ += name;
    eixName_ += ".eix";

    std::string epkName_ = inFolder;
    if(!(epkName_[epkName_.size() - 1] == '\\' || epkName_[epkName_.size() - 1] == '/'))
    {
    epkName_ += "\\";
    }
    epkName_ += name;
    epkName_ += ".epk";

    const char * eixName = eixName_.c_str();
    const char * epkName = epkName_.c_str();

    eixSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
    eixSecurity.bInheritHandle = TRUE;
    eixSecurity.lpSecurityDescriptor = NULL;

    epkSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
    epkSecurity.bInheritHandle = TRUE;
    epkSecurity.lpSecurityDescriptor = NULL;

    // Open the files to access
    while(bWasError == false)
    {
    eixHandle = CreateFileA(eixName, GENERIC_READ, FILE_SHARE_READ, &eixSecurity, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(eixHandle == INVALID_HANDLE_VALUE)
    {
    printf("Could not open the %s file. The program will now exit.\n", eixName);
    bWasError = true;
    break;
    }

    epkHandle = CreateFileA(epkName, GENERIC_READ, FILE_SHARE_READ, &epkSecurity, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if(epkHandle == INVALID_HANDLE_VALUE)
    {
    printf("Could not open the %s file. The program will now exit.\n", epkName);
    bWasError = true;
    break;
    }
    break; // All done now
    }

    // Create the access handles for reading the files
    while(bWasError == false)
    {
    // We need to store the size of the file for file mapping
    eixFileSize = GetFileSize(eixHandle, NULL);
    if(eixFileSize == INVALID_FILE_SIZE)
    {
    DWORD dwError = GetLastError();
    if(dwError != NO_ERROR)
    {
    printf("There was an error [%i] getting the file size of the %s file. The program will now exit.\n", dwError, eixName);
    bWasError = true;
    break;
    }
    }

    // We need to store the size of the file for file mapping
    epkFileSize = GetFileSize(epkHandle, NULL);
    if(epkFileSize == INVALID_FILE_SIZE)
    {
    DWORD dwError = GetLastError();
    if(dwError != NO_ERROR)
    {
    printf("There was an error [%i] getting the file size of the %s file. The program will now exit.\n", dwError, epkName);
    bWasError = true;
    break;
    }
    }

    // Create a file mapping object
    eixFileMapping = CreateFileMapping(eixHandle, NULL, PAGE_READONLY, 0, eixFileSize, NULL);
    if(eixFileMapping == 0)
    {
    printf("Could not create a file mapping object for the %s file. The program will now exit.\n", eixName);
    bWasError = true;
    break;
    }

    // Create a file mapping object
    epkFileMapping = CreateFileMapping(epkHandle, NULL, PAGE_READONLY, 0, epkFileSize, NULL);
    if(epkFileMapping == 0)
    {
    printf("Could not create a file mapping object for the %s file. The program will now exit.\n", epkName);
    bWasError = true;
    break;
    }

    // Create a file mapping view
    eixFileBufferPtr = reinterpret_cast(MapViewOfFile(eixFileMapping, FILE_MAP_READ, 0, 0, eixFileSize));
    if(eixFileBufferPtr == 0)
    {
    printf("Could not create a view of the the %s file. The program will now exit.\n", eixName);
    bWasError = true;
    break;
    }

    // Create a file mapping view
    epkFileBufferPtr = reinterpret_cast(MapViewOfFile(epkFileMapping, FILE_MAP_READ, 0, 0, epkFileSize));
    if(epkFileBufferPtr == 0)
    {
    printf("Could not create a view of the the %s file. The program will now exit.\n", epkName);
    bWasError = true;
    break;
    }

    break; // All done now
    }

    // Now we need to verify the files we just loaded
    while(bWasError == false)
    {
    // We need at least 12 bytes
    if(eixFileSize < 0x0C)
    {
    printf("The file size for the %s file is too small. The program will now exit.\n", eixName);
    bWasError = true;
    break;
    }

    // Verify the header
    LPDWORD eixHeader = reinterpret_cast(eixFileBufferPtr);
    if(*eixHeader != 0x444B5045) // Some hard coded check
    {
    // Important: This value is read from the client itself. If the client updates, this value
    // would need to be updated as well if it ever changed.
    if(*eixHeader != LZ_KEY)
    {
    printf("The file header for the %s file is incorrect. The program will now exit.\n", eixName);
    bWasError = true;
    break;
    }

    // Get a file header pointer from the buffer
    TEntry2 * eixHeader = (TEntry2 *)eixFileBufferPtr;

    // Store a pointer to the encrypted data
    LPBYTE eixDataBuffer = eixFileBufferPtr + 0x14;

    // We don't care about this check because we will create the
    // buffers ourselves in dynamic memory. The game wants to be as
    // efficient as possible though.
    if(eixHeader->decompressedBlockSize

    [0]: <a href=
    [1]: http://www.gamedev.net/community/forums

  • puf pero está en ensablador, lo interesante del programa al menos.
    Ya vi ese código en epvp si no recuerdo mal, cuando intentaba hacer un comp/descomp en java para usarlo en mi programa.

    Prefiero usar un programa de un tercero antes que descifrar ese puto código infernal _xD_

    PD: usa el bbcode "codigo" en vez del bbcode "code", queda más bonito 😃

  • @Mrs.Troll said:

    Recientemente me adentre al mundo de c# y otros como delphi [...]

    LOL pero sabes que ese código no es C# sino C++, ¿no? O más bien, como dijo salva la parte interesante está en ensamblador, que a ver quien tiene huevos a descifrarlo xD. Aunque por cierto, me parece raro que el que creó el programa use clases y funciones de C++ propiamente dicho (como vector, bool y string) mezcladas con funciones importadas de C (como printf, en lugar de cout que es lo que se usa en C++, o fprintf, en lugar de ostream).