Hier wird nur der Sourcecode zur Verfügung gestellt. Alles weitere bitte in den verlinkten Artikeln lesen.
Code
///
/// Dateiname: restricted-area-pak-generator.cpp
///
/// Diese Datei gehört zu dem Artikel:
/// - http://www.naden.de/public/articles/restricted-area-pak-file-dumper.php
///
/// Dieser Code ist (c) 2004 naden.de - Der Code darf frei gelesen, empfohlen, verlinkt, compiliert und teilweise in anderen
/// Programmen - nichtkommerzieller Art - verwendet werden, solange die Quelle angegeben wird.
/// Eine darüber hinausgehender Nutzung welcher Art und Weise auch immer bedarf der schriftlichen Genehmigung des Autors.
/// Bei Zuwiderhandlungen ist der Schuldige damit einverstanden, Schadenersatzforderungen nachzukommen.
///
#include
#include
#include "restricted_area_pak_types.h"
#include "jcalg1.h"
LPVOID _stdcall AllocFunc( DWORD dwMemSize)
{
return( (LPVOID)GlobalAlloc( GMEM_FIXED, dwMemSize ) );
}
bool _stdcall DeallocFunc( LPVOID lpBuffer )
{
GlobalFree( (HGLOBAL)lpBuffer );
return( true );
}
bool _stdcall CallbackFunc( DWORD dwSourcePos, DWORD dwDestinationPos )
{
// printf("\r %u", (UINT)dwSourcePos );
return( true );
}
UINT AddFileToPak( HANDLE hFileOut, char szFilename[ MAX_PATH ], DWORD dwFilesize )
{
HANDLE hFileIn;
UINT uException = 1;
LPSTR lpData;
LPSTR lpBuffer;
try
{
/// Datei zum lesen öffnen
if( ( hFileIn = CreateFile( szFilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0 ) ) == INVALID_HANDLE_VALUE )
{
throw 2;
}
lpData = new char[ dwFilesize ];
if( !lpData )
{
throw 3;
}
DWORD dwBytesRead;
DWORD dwTotalread = 0;
bool bRead;
UINT uIndex = 0;
/// Lese Datei in Buffer
while( ( bRead = ReadFile( hFileIn, (lpData+uIndex), dwFilesize, &dwBytesRead, 0 ) ) )
{
dwTotalread += dwBytesRead;
if( bRead && dwBytesRead == 0 )
{
/// Ende der Datei?
break;
}
}
if( dwTotalread != dwFilesize )
{
throw 4;
}
lpBuffer = new char[ JCALG1_GetNeededBufferSize( dwFilesize ) ];
if( !lpBuffer )
{
throw 5;
}
DWORD dwCompressedSize = JCALG1_Compress(
(LPVOID)lpData, dwFilesize, (LPVOID)lpBuffer, dwFilesize, &AllocFunc, &DeallocFunc, &CallbackFunc, 0 );
printf( " %u", dwCompressedSize );
if(!dwCompressedSize)
{
printf( "\n4 %u", dwFilesize );
throw 3;
}
/* printf( "\n5%u", dwFilesize );
printf("\r Original Size: %u Compressed Size: %u Ratio: %.02f",
dwFilesize, dwCompressedSize, (float)dwCompressedSize/dwFilesize);
*/
/// schreibe header
ra_pak.dwPackedSize = dwCompressedSize;
ra_pak.dwRealSize = dwFilesize;
DWORD dwBytesWritten;
WriteFile( hFileOut, &ra_pak, 8, &dwBytesWritten, 0 );
/// schreibe gepackte Daten
WriteFile( hFileOut,(LPVOID)lpBuffer, dwCompressedSize, &dwBytesWritten, 0 );
}
catch( UINT uException )
{
if( lpBuffer )
{
delete[] lpBuffer;
}
if( lpData )
{
delete[] lpData;
}
if( hFileIn != INVALID_HANDLE_VALUE )
{
CloseHandle( hFileIn );
}
return( uException );
}
CloseHandle( hFileIn );
delete[] lpBuffer;
delete[] lpData;
return( uException );
}
int main( int argc, char** argv )
{
printf( "\nResticted Area - .PAK-Generator (c)2004 www.naden.de - v0.1\n" );
if( argc != 2 )
{
printf( "\n Syntax: %s \\pfad\n", argv[ 0 ] );
}
char szBasepath[ MAX_PATH ] = { 0 };
wsprintf( szBasepath, "%s\\*.*", argv[ 1 ] );
printf( "\n Lese aus Verzeichnis: %s\n", szBasepath );
HANDLE hFileOut;
DWORD dwFlags = FILE_ATTRIBUTE_NORMAL;
/// Erstelle Ausgabedatei
if( ( hFileOut = CreateFile( OUTFILE_MASK, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, dwFlags, 0 ) ) == INVALID_HANDLE_VALUE )
{
printf( "\n Fehler: Kann "OUTFILE_MASK" nicht anlegen!" );
return( 1 );
}
///
char szFilename[ MAX_PATH ] = { 0 };
char szPathname[ MAX_PATH ] = { 0 };
char szFullname[ MAX_PATH ] = { 0 };
char *ptr;
HANDLE hFind;
BOOL bFind = true;
DWORD dwTotalcount = 0;
DWORD dwTotalsize = 0;
// define and initialize struct
WIN32_FIND_DATA w32fd;
ZeroMemory( &w32fd, sizeof( WIN32_FIND_DATA ) );
// find first entry
hFind = FindFirstFile( szBasepath, &w32fd );
if( hFind == INVALID_HANDLE_VALUE )
{
printf( "\n Fehler: Kann keine Dateien finden!" );
return( 1 );
}
while( ( hFind != INVALID_HANDLE_VALUE ) && bFind )
{
if( ( ptr = strrchr( szBasepath, (int)'\\' ) ) != NULL )
{
/// extrahiere Pfadname
strncpy( szPathname, szBasepath, (ptr-szBasepath)+1 );
/// extrahiere Dateiname
strncpy( szFilename+(ptr-szBasepath), szBasepath+(ptr-szBasepath), strlen( szBasepath )-(ptr-szBasepath) );
}
dwTotalcount++;
/// Wenn es kein Verzeichnis ist
if( !( w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
{
// supports up to 0xffff bytes wau!!
sprintf( szFullname, "%s%s", szPathname, w32fd.cFileName );
printf( "\n %s %u", w32fd.cFileName, REAL_FILESIZE( w32fd ) );
if( AddFileToPak( hFileOut, szFullname, REAL_FILESIZE( w32fd ) ) == 1 )
{
printf( " OK" );
}
else
{
printf( " Fehler" );
}
dwTotalsize += REAL_FILESIZE( w32fd );
}
// find next entry
bFind = FindNextFile( hFind, &w32fd );
}
CloseHandle( hFileOut );
printf( "\n\n Fertig, Datei "OUTFILE_MASK" wurde erstellt!\n\n" );
return( 0 );
}
Die Header-Datei definiert einen benötigten Struct, einige Hilfsmacros und die Fehlermeldungen.
///
/// Dateiname: restricted_area_pak_types.h
///
/// Diese Datei gehört zu dem Artikel:
/// - http://www.naden.de/public/articles/restricted-area-pak-file-dumper.php
///
/// Dieser Code ist (c) 2004 naden.de - Der Code darf frei gelesen, empfohlen, verlinkt, compiliert und teilweise in anderen
/// Programmen - nichtkommerzieller Art - verwendet werden, solange die Quelle angegeben wird.
/// Eine darüber hinausgehender Nutzung welcher Art und Weise auch immer bedarf der schriftlichen Genehmigung des Autors.
/// Bei Zuwiderhandlungen ist der Schuldige damit einverstanden, Schadenersatzforderungen nachzukommen.
///
typedef struct __restricted_area_pak {
DWORD dwRealSize;
DWORD dwPackedSize;
} __restricted_area_pak_type;
__restricted_area_pak_type ra_pak;
#define GET_ERRORMESSAGE_BY_INDEX( i ) __restricted_area_pak_errors[ i-2 ]
#define OUTFILE_MASK "0.pak"
#define GET_PERCENT( p ) ( (double)p.dwPackedSize / ( (double)p.dwRealSize / 100.0 ) )
#define REAL_FILESIZE_KB( p ) ( ( ( p.nFileSizeHigh * MAXDWORD ) + p.nFileSizeLow ) / 1024 )
#define REAL_FILESIZE( p ) ( ( p.nFileSizeHigh * MAXDWORD ) + p.nFileSizeLow )
char __restricted_area_pak_errors[ 7 ][ 70 ] = {
/// 2
{ "Hauptspeicher konnte nicht reserviert werden!\0" },
/// 3
{ "Die angeforderte Menge an Bytes konnte nicht gelesen werden!\0" },
/// 4
{ "Speicher für den Buffer konnte nicht reserviert werden!\0" },
/// 5
{ "Block konnte nicht entpackt werden!\0" },
/// 6
{ "Ausgabedatei konnte nicht erstellt werden!\0" },
/// 7
{ "Es konnten nicht alle Daten geschrieben werden!\0" }
};
Beim kompilieren des Codes muss die Datei "jcalg1_static.lib" mit in das Programm gelinkt werden.
Begriffserkärungen
DWORD : Datentyp, ein D(OUBLE)WORD, belegt 4 Bytes. Der Wertebereich geht von -2.147.483.648 <= X <= 2.147.483.64 bzw. 0 <= X <= 4.294.967.295 wenn unsigned.
Offset : Position innerhalb einer Datei.
0x: Eine Zahl die mit 0xbeginnt, bezeichnet eine hexadezimale Zahl, eine Zahl zur Basis 16 mit den Ziffern 0123456789abcdef.
Struct: Begriff aus der Programmierung, ein Struct bezeichnet eine selbst definierte Variable, die mehrere Einzelwerte enthalten kann.
Danke allen Lesern, von denen ich so viel positives Feadback bekommen habe.
Mit den obigen Informationen sollte jeder in der Lage sein, den Entpacker zu erweitern und auf dem Code aufzubauen. Feadback ist wie immer willkommen.
Ich hoffe, das dieses Tutorial Leute dazu animiert, weiter in die Richtung zu forschen, um schnellstmöglich schöne Erweiterungen für Restricted Area zu erstellen. Anregungen, konstruktive Verbesserungsvorschläge und allgemeines Feadback sind wie immer willkommen.
Der direkte Link zu diesem artikel lautet: http://www.naden.de/public/articles/restricted-area-pak-file-generator.php
Alle Angaben ohne Anspruch auf Richtigkeit oder Vollständigkeit. Die Manipulation der Dateien erfolgt auf eigene Verantwortung. Es ist ausgeschlossen, dass der Autor für etwaige Schäden am System oder den Programmen zur Rechenschaft gezogen werden kann.
Alle Markenrechte liegen bei den jeweiligen Eigentümern. Der Autor ist in keiner Weise mit den Herstellern oder dem Distributor des Spiels verbunden.