#include #include #include #define FALSE 0 #define TRUE 1 typedef struct { char header[4]; short int map_blk_size; short int map_x_size; short int map_y_size; } map_header; map_header current_map_header; char source_file[100]; char dest_file[100]; char *map_file = NULL; short int *compressed_mapdata = NULL; char *compressed_alienmapdata = NULL; long int compressed_mapdata_size; long int compressed_alienmapdata_size; void DisplayMenu() { printf("ABII MAP COMPRESSION UTILITY\n\n"); printf("1. Load Map File\n"); printf("2. Compress File\n"); printf("3. Save Compressed File\n"); printf("4. Quit\n\n"); printf("Enter Selected >"); } int GetYorN() { char c; int got_char = FALSE; while( !got_char ) { scanf("%c",&c); if ( c == 'Y' || c == 'y' ) return 1; else if ( c == 'N' || c == 'Y' ) return 0; } } int LoadMapFile() { FILE *ptr; int map_data_size; if ( ( ptr = fopen( source_file, "r" ) ) == NULL ) { printf("Failed to open file %s\n",source_file ); return 0; } /* FILE OPEN OK */ fread( (char*)¤t_map_header, sizeof( map_header ), 1, ptr ); printf("Map details : \n\n"); printf("%4s\n",current_map_header.header ); printf("Map Size X : %d\n", current_map_header.map_x_size); printf("Map Size Y : %d\n", current_map_header.map_y_size); map_data_size = current_map_header.map_x_size* current_map_header.map_y_size*3; map_file = malloc( map_data_size ); if ( map_file == NULL ) { printf("Error Allocating data\n"); return 0; } else fread( map_file, map_data_size, 1, ptr ); fclose( ptr ); return 1; } /************************************************ *** FIND REPEAT *** ************************************************/ int FindRepeat( string, scanlength ) char *string; int scanlength; { char ch; int pos = -1; int rep = 0; int count = 0; ch = *string; while( count != scanlength ) { if( *string == ch && ( count == 0 || count > 4 ) ) { if ( pos == -1 ) pos = count; rep++; if( rep > 4 ) return pos; } else { rep = 0; pos = -1; } ch = *(string++); count++; } return -1; } /************************************************ *** FIND REPEAT LENGTH ***** ************************************************/ int FindRepeatLength( string, max ) char *string; int max; { char ch; int size=0; ch = *string; while( size != max ) { if( *(string++) == ch ) size++; else return size; } return max; } /************************************************** **** COMPRESS *** **************************************************/ char *Compress( string, size_of_dat, new_size ) char *string; long int size_of_dat; long int *new_size; { int current_pos = 0; int rep_pos; int rep_length; int scan_length; int straight_written, rep_written; char *new_data = NULL; int crunched; int new_pos = 0; int loop; new_data = malloc( size_of_dat ); *new_size = 0; while( current_pos <= size_of_dat && *new_size < size_of_dat ) { straight_written = 0; rep_written = 0; scan_length = 127; if( (current_pos+scan_length) > size_of_dat ) scan_length = size_of_dat - current_pos; rep_pos = FindRepeat( &string[current_pos], scan_length ); if( rep_pos+current_pos != current_pos ) { if ( rep_pos == -1 ) straight_written = scan_length; else straight_written = rep_pos-1; new_data[new_pos++] = 128+straight_written; for (loop=0; loop< straight_written; loop++) new_data[new_pos++] = string[current_pos+loop]; *new_size += straight_written+1; } if( rep_pos != -1 ) { if ( (current_pos+rep_pos+127) > size_of_dat ) rep_length = size_of_dat - current_pos+rep_pos; else rep_length = 127; if ( rep_pos ) rep_pos--; rep_written = FindRepeatLength( &string[current_pos+rep_pos], rep_length); new_data[new_pos++] = rep_written; new_data[new_pos++] = string[current_pos+rep_pos]; *new_size += 2; } current_pos += straight_written+rep_written; crunched = (int) ( ( (double)current_pos / (double)size_of_dat)*100.0); printf("crunched %d\r",crunched ); } printf("\n"); if( *new_size >= size_of_dat ) { *new_size = 0; return NULL; } return new_data; } /************************************************ *** FIND WORD REPEAT *** ************************************************/ int FindWordRepeat( string, scanlength ) short int *string; int scanlength; { short int ch; int pos = -1; int rep = 0; int count = 0; ch = *string; while( count != scanlength ) { if( *string == ch && ( count == 0 || count > 4 ) ) { if ( pos == -1 ) pos = count; rep++; if( rep > 4 ) return pos; } else { rep = 0; pos = -1; } ch = *(string++); count++; } return -1; } /************************************************ *** FIND WORD REPEAT LENGTH ***** ************************************************/ int FindWordRepeatLength( string, max ) short int *string; int max; { short int ch; int size=0; ch = *string; while( size != max ) { if( *(string++) == ch ) size++; else return size; } return max; } /************************************************** **** WORD COMPRESS *** **************************************************/ short int *WordCompress( string, size_of_dat, new_size ) short int *string; long int size_of_dat; long int *new_size; { int current_pos = 0; int rep_pos; int rep_length; int scan_length; int straight_written, rep_written; short int *new_data = NULL; int crunched; int loop; int new_pos=0; new_data = (short int*)malloc( size_of_dat*2 ); *new_size = 0; while( current_pos <= size_of_dat && *new_size < size_of_dat ) { straight_written = 0; rep_written = 0; scan_length = 16384; if( (current_pos+scan_length) > size_of_dat ) scan_length = size_of_dat - current_pos; rep_pos = FindWordRepeat( &string[current_pos], scan_length ); if( rep_pos+current_pos != current_pos ) { if ( rep_pos == -1 ) straight_written = scan_length; else straight_written = rep_pos-1; new_data[new_pos++] = 32768+straight_written; for (loop=0; loop < straight_written; loop++) new_data[new_pos++] = string[current_pos+loop]; *new_size += straight_written+1; } if( rep_pos != -1 ) { if ( (current_pos+rep_pos+127) > size_of_dat ) rep_length = size_of_dat - current_pos+rep_pos; else rep_length = 16384; if ( rep_pos ) rep_pos--; rep_written = FindWordRepeatLength( &string[current_pos+rep_pos], rep_length); new_data[new_pos++] = rep_written; new_data[new_pos++] = string[current_pos+rep_pos]; *new_size += 2; } current_pos += straight_written+rep_written; crunched = (int) ( ( (double)current_pos / (double)size_of_dat)*100.0); printf("crunched %d\r",crunched ); } printf("\n"); if( *new_size >= size_of_dat ) { *new_size = 0; return NULL; } return new_data; } /*So remember - bit 8 - control bit, 0 - repeat, 1 = straight*/ int CompressFile() { long int size; long int new_size; compressed_mapdata = WordCompress( (short int*)map_file, (int)(current_map_header.map_x_size* current_map_header.map_y_size), &compressed_mapdata_size ); if ( compressed_mapdata == 0 ) { printf("No Gain\n"); return 0; } compressed_alienmapdata = Compress( map_file + current_map_header.map_x_size* current_map_header.map_y_size*2, (int)current_map_header.map_x_size* current_map_header.map_y_size, &compressed_alienmapdata_size); if ( compressed_alienmapdata == 0 ) { printf("No Gain\n"); return 0; } size = (int)current_map_header.map_x_size*current_map_header.map_y_size*3; printf("Original size %d\n",size); new_size = (compressed_mapdata_size*2)+compressed_alienmapdata_size; printf("New size %d\n",new_size); printf("Saving of %%%d\n",100-(int) ( ( (double)new_size/size )*100.0 ) ); } int SaveNewFile( void ) { FILE *ptr; long int filesize; if ( ( ptr = fopen( dest_file,"w" ) ) == NULL ) return 0; sprintf(current_map_header.header,"COMP"); fwrite((char*)¤t_map_header, sizeof( map_header ), 1, ptr ); filesize = (compressed_mapdata_size*2+compressed_alienmapdata_size)+8; fwrite((char*)&filesize, sizeof( long int ), 1, ptr ); /*write map data + size*/ filesize =(compressed_mapdata_size*2)+4; fwrite( (char*)&filesize, sizeof( long int ), 1, ptr); fwrite((char*)compressed_mapdata, compressed_mapdata_size*2, 1, ptr); /*write alien map data + size*/ filesize = compressed_alienmapdata_size+4; fwrite( (char*)&filesize, sizeof( long int ), 1, ptr); fwrite((char*)compressed_alienmapdata, compressed_alienmapdata_size, 1, ptr); fclose( ptr ); return 1; } void main( argc, argv) int argc; char *argv[]; { printf("ABII MAP COMPRESSION UTILITY\n"); printf("(C) GLEN CUMMING 1994\n"); if ( argc < 2 ) { printf("\nFormat - mapcompress \n " ); return; } strcpy( source_file, argv[1] ); if ( argc == 2 ) sprintf( dest_file, "%s.cmp",source_file); if ( !LoadMapFile() ) return; if ( CompressFile() ) SaveNewFile(); if ( compressed_mapdata != NULL ) free( compressed_mapdata ); if ( compressed_alienmapdata != NULL ) free( compressed_alienmapdata ); }