/* VOLX by Lance Ewing */ /* Modifications for OBJECT file and ALL extraction made by Joakim Moller 96-08-20 */ /* Modifications for WORDS.TOK file made by Martin Tillenius 96-08-20 */ /* This file is under constant development, and still very unstable.. */ #include #include #include #include // not ANSI-C, but mkdir() is very common #include "agi.h" const char dirNames[4][8] = { "LOGDIR", "PICDIR", "VIEWDIR", "SNDDIR" }; // I changed this.. Please notice. const char fileNames[4][9] = { "LOGIC", "PICTURE", "VIEW", "SOUND" }; // have to declare functions in BC4.5.. void extractFile( int, int ); void extractAll( int ); void extractObjFile( void ); void extractWordsTok( void ); void extractComplete( void ); void decryptText( char *, long ); long getLength( FILE * ); void extractObjFile() { FILE *objfile, *outfile; long objlength; char *buffer, ctxt[2][10] = { "encrypted", "decrypted" }; int flag; if( NULL == ( objfile = fopen( "OBJECT", "rb" ) ) ) { printf( "Couldn't open file: OBJECT\n" ); return; } objlength = getLength( objfile ); if( NULL == ( outfile = fopen( "OBJECT.NEW", "wb" ) ) ) { printf( "Couldn't create outfile!\n" ); fclose( objfile ); return; } if( NULL == ( buffer = malloc( objlength ) ) ) { printf( "Couldn't allocate %ld bytes of memory!\n", objlength ); fclose( objfile ); fclose( outfile ); } if( NULL == fread( buffer, objlength, 1, objfile ) ) { printf( "Read error!\n" ); fclose( objfile ); fclose( outfile ); free( buffer ); } flag = buffer[5] == 0 ? 0 : 1; printf( "\nConverting %s OBJECT file to OBJECT.NEW... ", ctxt[flag] ); decryptText( buffer, objlength ); if( NULL == fwrite( buffer, objlength, 1, outfile ) ) { printf( "Error!\nWrite error!\n" ); fclose( objfile ); fclose( outfile ); free( buffer ); } printf( "Done." ); fclose( objfile ); fclose( outfile ); free( buffer ); } void decryptText( char *buffer, long length ) { char avis[] = "Avis Durgan"; long i, cnt; for( i = 0, cnt = 0; i <= length; i++ ) { buffer[i] = buffer[i] ^ avis[cnt++]; if( cnt > 10 ) cnt = 0; } } void extractFile(int fileNameNum, int fileNum) { FILE *volFile, *dirFile, *dumpFile; long volFilePos; unsigned char firstByte, secondByte, thirdByte; char volFileName[80], dumpFileName[80]; unsigned char *buffer; unsigned int fLen; if ((dirFile = fopen(dirNames[fileNameNum], "rb")) == NULL) { printf("Cannot open %s.", dirNames[fileNameNum]); exit(1); } printf( "\nExtracting %s.%d... ", fileNames[fileNameNum], fileNum ); fseek(dirFile, fileNum*3, SEEK_SET); firstByte = fgetc(dirFile); secondByte = fgetc(dirFile); thirdByte = fgetc(dirFile); fclose(dirFile); if ((firstByte == 0xFF) && (secondByte == 0xFF) && (thirdByte == 0xFF)) { printf("Error!\nFile doesn't exist.\n"); exit(1); } else { volFilePos = ((firstByte & 0x0F) * (unsigned long)0x10000) + (secondByte * (unsigned long)0x100) + thirdByte; sprintf( volFileName, "VOL.%d", (firstByte & 0xF0) >> 4 ); if ((volFile = fopen(volFileName, "rb")) == NULL) { printf("Error!\nCannot open %s.", volFileName); exit(1); } fseek(volFile, volFilePos + 3, SEEK_SET); fLen = lhconv( fgetc(volFile), fgetc(volFile) ); if( fLen <= 30000 ) { if( NULL == ( buffer = malloc( fLen ) ) ) { printf( "Error!\nNot enough memory!\n" ); exit(1); } sprintf( dumpFileName, "%s.%d", fileNames[fileNameNum], fileNum ); if ((dumpFile = fopen(dumpFileName, "wb")) == NULL) { printf("Error!\nCannot open %s.\n", dumpFileName); free( buffer ); exit(1); } fread( buffer, fLen, 1, volFile ); fwrite( buffer, fLen, 1, dumpFile ); free( buffer ); fclose(dumpFile); } else printf( "Error!\n %s.%d - file too big!\n", fileNames[fileNameNum], fileNum ); } printf( "Done." ); fclose(volFile); } void extractAll(int fileNameNum) { FILE *volFile, *dirFile, *dumpFile; long volFilePos, filelength; unsigned char byte[3]; char volFileName[80], dumpFileName[80]; unsigned char *buffer; int fLen; int fileNum; if ((dirFile = fopen(dirNames[fileNameNum], "rb")) == NULL) { printf("Cannot open %s.", dirNames[fileNameNum]); exit(1); } printf( "\nExtracting %s files... ", fileNames[fileNameNum] ); mkdir( fileNames[fileNameNum] ); filelength = getLength( dirFile ); for( fileNum = 0; fileNum*3 < filelength; fileNum++ ) { fread( byte, sizeof( unsigned char ), 3, dirFile ); if ( (byte[0] != 0xFF) && (byte[1] != 0xFF) && (byte[2] != 0xFF) ) { volFilePos = ((byte[0] & 0x0F) * (unsigned long)0x10000) + (byte[1] * (unsigned long)0x100) + byte[2]; sprintf( volFileName, "VOL.%d", (byte[0] & 0xF0) >> 4 ); if ((volFile = fopen(volFileName, "rb")) == NULL) { printf("Error!\nCannot open %s.", volFileName); exit(1); } fseek(volFile, volFilePos + 3, SEEK_SET); fLen = lhconv( fgetc(volFile), fgetc(volFile) ); if( (fLen <= 30000) && (fLen > 0) ) { if( NULL == ( buffer = malloc( fLen ) ) ) { printf( "Error!\nNot enough memory!\n" ); exit(1); } sprintf( dumpFileName, "%s/%s.%d", fileNames[fileNameNum], fileNames[fileNameNum], fileNum ); if ((dumpFile = fopen(dumpFileName, "wb")) == NULL) { printf("Error!\nCannot open %s.\n", dumpFileName); free( buffer ); exit(1); } fread( buffer, fLen, 1, volFile ); fwrite( buffer, fLen, 1, dumpFile ); free( buffer ); fclose(dumpFile); } else printf( "\nError! %s.%d - extreme filesize (%d bytes)!\n", fileNames[fileNameNum], fileNum, fLen ); fclose(volFile); } } printf( "Done." ); fclose(dirFile); } /* Routine written by Martin Tillenius.. Don't blame me for errors.. =) */ void extractWordsTok() { int i; int same; char letter; char w_name[50]; int w_nr; int index[26]; FILE *in, *ut; in = fopen( "WORDS.TOK", "rb" ); ut = fopen( "WORDS.TXT", "wb" ); printf( "\nConverting WORDS.TOK to WORDS.TXT... " ); for(i = 0; i < 26; index[i++] = (fgetc(in) << 8) + fgetc(in)); for(i = 0; i < 26; i++) { fprintf(ut, "*** %c\n", i + 65); if(index[i] != 0) { fseek(in, index[i], SEEK_SET); same = fgetc(in); do { do { letter = fgetc(in); w_name[same++] = (letter ^ 0x7f) & 0x7f; } while( !feof(in) && ((letter & 0x80) == 0)); w_name[same] = 0; w_nr = (fgetc(in) << 8) + fgetc(in); fprintf(ut, "%03d %s\n", w_nr, w_name); same = fgetc(in); } while( !feof(in) && (same != 0)); } } fclose(in); fclose(ut); printf( "Done." ); } void main(int argc, char **argv) { int fileNum; printf( "VOLX - AGI system extractor\n" ); switch( argc ) { case 0: case 1: printf("\nUsage: volx -l logicnumber\n"); printf(" volx -s soundnumber\n"); printf(" volx -v viewnumber\n"); printf(" volx -p picturenumber\n"); printf(" volx -o\n"); printf(" volx -w\n"); printf(" volx -a\n\n"); printf("You can use \"ALL\" instead of number to extract all files..\n"); break; case 2: switch( argv[1][1] ) { case 'w': extractWordsTok(); break; case 'o': extractObjFile(); break; case 'a': extractComplete(); break; default: printf( "Unknown option: %s", argv[1] ); } break; case 3: if (argv[1][0] == '-') { fileNum = atoi(argv[2]); if ( (fileNum >= 0) && strcmp( argv[2], "ALL" ) ) { switch (argv[1][1]) { case 'l': extractFile(0, fileNum); break; case 's': extractFile(3, fileNum); break; case 'v': extractFile(2, fileNum); break; case 'p': extractFile(1, fileNum); break; default: printf("Invalid option : %s\n", argv[1]); } } else { if( !strcmp( argv[2], "ALL" ) ) switch( argv[1][1] ) { case 'l': extractAll(0); break; case 's': extractAll(3); break; case 'v': extractAll(2); break; case 'p': extractAll(1); break; default: printf("Invalid option : %s\n", argv[1]); } else printf("File number must be a postive number\n"); } } else { printf("Invalid option : %s\n", argv[1]); } } printf( "\n" ); } void extractComplete() { char i; printf( "\nPlease wait while extracting...\n" ); /* extract all LOGIC, VIEW, PIC and SOUND files */ for( i = 0; i <= 3; i++ ) extractAll(i); /* en-/decrypt OBJECT file */ extractObjFile(); /* convert WORDS.TOK to text */ extractWordsTok(); printf( "\n\nAll done!" ); } long getLength( FILE *file ) { long tmp; fseek( file, 0L, SEEK_END ); tmp = ftell( file ); fseek( file, 0L, SEEK_SET ); return( tmp ); }