splitshp.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001  The Exult Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #include <iostream>
00024 
00025 #ifndef ALPHA_LINUX_CXX
00026 #  include <cstdio>
00027 #  include <cstring>
00028 #  include <string>
00029 #endif
00030 
00031 #include "exult_types.h"
00032 
00033 
00034 using std::cout;
00035 using std::endl;
00036 using std::cerr;
00037 using std::string;
00038 using std::strlen;
00039 using std::strrchr;
00040 using std::strcpy;
00041 using std::memcpy;
00042 using std::exit;
00043 
00044 struct u7frame {
00045   bool tile;
00046   uint32 datalen;
00047   uint8 *data;
00048 };
00049 
00050 struct u7shape {
00051   int num_frames;
00052   struct u7frame *frames;
00053 };
00054 
00055 unsigned int read1(FILE *f)
00056 {
00057   unsigned char b0;
00058   b0 = fgetc(f);
00059   return b0;
00060 }
00061 
00062 unsigned int read2(FILE *f)
00063 {
00064   unsigned char b0, b1;
00065   b0 = fgetc(f);
00066   b1 = fgetc(f);
00067   return (b0 + (b1<<8));
00068 }
00069 
00070 signed int read2signed(FILE *f)
00071 {
00072   unsigned char b0, b1;
00073   signed int i0;
00074   b0 = fgetc(f);
00075   b1 = fgetc(f);
00076   i0 = b0 + (b1<<8);
00077   if (i0 >= 32768) { i0 -= 65536; }
00078   return (i0);
00079 }
00080 
00081 unsigned int read4(FILE *f)
00082 {
00083   unsigned char b0, b1, b2, b3;
00084   b0 = fgetc(f);
00085   b1 = fgetc(f);
00086   b2 = fgetc(f);
00087   b3 = fgetc(f);
00088   return (b0 + (b1<<8) + (b2<<16) + (b3<<24));
00089 }
00090 
00091 void write4(FILE *f, unsigned int b)
00092 {
00093   fputc(b & 0xFF, f);
00094   fputc((b >> 8) & 0xFF, f);
00095   fputc((b >> 16) & 0xFF, f);
00096   fputc((b >> 24) & 0xFF, f);
00097 }
00098 
00099 char* framefilename(char * shapefilename, int frame)
00100 {
00101   char *fn = new char[strlen(shapefilename)+5];  //_xxx\0
00102   char *dot = strrchr(shapefilename, '.');
00103 #ifdef WIN32
00104   char *slash = strrchr(shapefilename, '\\');
00105 #else
00106   char *slash = strrchr(shapefilename, '/');
00107 #endif
00108   int dotpos;
00109 
00110   if (dot == 0 || slash > dot)
00111     dotpos = strlen(shapefilename);
00112   else
00113     dotpos = dot - shapefilename;
00114 
00115   memcpy(fn, shapefilename, dotpos);
00116   sprintf(fn + dotpos, "_%03i", frame);
00117   strcpy(fn + dotpos + 4, shapefilename + dotpos);
00118 
00119   return fn;
00120 }
00121 
00122 void split_shape(char* filename)
00123 {
00124   FILE *shpfile, *framefile;
00125   int file_size, shape_size, hdr_size;
00126   int frame_offset, next_frame_offset;
00127   int num_frames;
00128   int datalen;
00129   uint8 *data;
00130   char *framename;
00131   int i;
00132   
00133   shpfile = fopen (filename, "rb");
00134   if (!shpfile) {
00135     cerr << "Can't open " << filename << endl;
00136     return;
00137   }
00138   fseek(shpfile, 0, SEEK_END);
00139   file_size = ftell(shpfile);
00140   fseek(shpfile, 0, SEEK_SET);
00141   
00142   shape_size = read4(shpfile);
00143   
00144   if(file_size!=shape_size) { /* 8x8 tile */
00145     num_frames = file_size/64;
00146     fseek(shpfile, 0, SEEK_SET);    /* Return to start of file */
00147     cout << "num_frames = " << num_frames << endl;
00148     data = new uint8[64];
00149     for(i=0; i<num_frames; i++) {
00150       framename = framefilename(filename, i);
00151       cout << "writing " << framename << "..." << endl;
00152       framefile = fopen(framename, "wb");
00153       fread(data, 1, 64, shpfile);
00154       fwrite(data, 1, 64, framefile);
00155       fclose(framefile);
00156       delete[] framename;
00157     }
00158     delete[] data;
00159   } else {
00160     hdr_size = read4(shpfile);
00161     num_frames = (hdr_size-4)/4;
00162     
00163     cout << "num_frames = "<< num_frames << endl;
00164     
00165     for(i=0; i<num_frames; i++) {
00166       framename = framefilename(filename, i);
00167       cout << "writing " << framename << "..." << endl;
00168       framefile = fopen(framename, "wb");
00169 
00170       // Go to where frame offset is stored
00171       fseek(shpfile, (i+1)*4, SEEK_SET);
00172       frame_offset = read4(shpfile);
00173 
00174       if (i+1 < num_frames)
00175         next_frame_offset = read4(shpfile);
00176       else
00177         next_frame_offset = shape_size;
00178 
00179       fseek(shpfile, frame_offset, SEEK_SET);
00180       datalen = next_frame_offset - frame_offset;
00181 
00182       write4(framefile, datalen+8);
00183       write4(framefile, 8);
00184 
00185       data = new uint8[datalen];
00186       fread(data, 1, datalen, shpfile);
00187       fwrite(data, 1, datalen, framefile);
00188       fclose(framefile);
00189       delete[] framename;
00190       delete[] data;
00191     }
00192   }
00193   cout << "done" << endl;
00194 
00195   fclose(shpfile);
00196 }
00197 
00198 void merge_frames(char *shapefile, char** framefiles, int numframefiles)
00199 {
00200   FILE *shpfile, *framefile;
00201   int i;
00202   bool tiles = false;
00203   int file_size, shape_size, hdr_size, frame_size;
00204   int total_size;
00205   uint8 *data;
00206 
00207   shpfile = fopen(shapefile, "wb");
00208 
00209   total_size = 4 + 4*numframefiles;
00210 
00211   for (i=0; i<numframefiles; i++) {
00212     framefile = fopen(framefiles[i], "rb");
00213 
00214     cout << "reading " << framefiles[i] << "..." << endl;
00215     
00216     fseek(framefile, 0, SEEK_END);
00217     file_size = ftell(framefile);
00218     fseek(framefile, 0, SEEK_SET);
00219     shape_size = read4(framefile);
00220 
00221     if (file_size != shape_size) { // 8x8 tile
00222       if (i > 0 && !tiles) {
00223         cout << "Error: can't mix 8x8 tiles and non-tile shapes!" << endl;
00224         exit(1);
00225       }
00226 
00227       tiles = true;
00228 
00229       fseek(framefile, 0, SEEK_SET);
00230       fseek(shpfile, 64*i, SEEK_SET);
00231 
00232       data = new uint8[64];
00233 
00234       fread(data, 1, 64, framefile);
00235       fwrite(data, 1, 64, shpfile);
00236       fclose(framefile);
00237 
00238       delete [] data;
00239     } else {
00240       if (tiles) {
00241         cout << "Error: can't mix 8x8 tiles and non-tile shapes!" << endl;
00242         exit(1);
00243       }
00244 
00245       hdr_size = read4(framefile);
00246       
00247       if (hdr_size > 8) {
00248         frame_size = read4(framefile);
00249         frame_size -= hdr_size;
00250       } else {
00251         frame_size = shape_size - hdr_size;
00252       }
00253 
00254       data = new uint8[frame_size];
00255       fseek(framefile, hdr_size, SEEK_SET);
00256       fread(data, 1, frame_size, framefile);
00257       fclose(framefile);
00258 
00259       fseek(shpfile, 4 + (i*4), SEEK_SET);
00260       write4(shpfile, total_size);
00261       fseek(shpfile, total_size, SEEK_SET);
00262       fwrite(data, 1, frame_size, shpfile);
00263 
00264       total_size += frame_size;
00265       delete [] data;
00266     }
00267   }
00268 
00269   if (!tiles) {
00270     fseek(shpfile, 0, SEEK_SET);
00271     write4(shpfile, total_size);
00272   }
00273 
00274   cout << "done" << endl;
00275 
00276   fclose(shpfile);
00277 }
00278 
00279 int main(int argc, char *argv[])
00280 {
00281   char* shapefile;
00282   int numframefiles;
00283   char* framefiles[255];
00284   u7shape* sh;
00285   
00286   if (argc < 2) {
00287     cout << "Usage: To split: splitshp [shape file]" << endl
00288            << "     or to pack: splitshp [shape file] [frame files]" << endl;
00289     return 0;
00290   }
00291   
00292   shapefile = argv[1];
00293 
00294   if (argc > 2) {
00295     numframefiles = argc - 2;
00296     for (int i=0; i<numframefiles; i++)
00297       framefiles[i] = argv[i+2];
00298     merge_frames(shapefile, framefiles, numframefiles);
00299   } else {
00300     split_shape(shapefile);
00301   }
00302 
00303   return 0;
00304 }

Generated on Mon Jul 9 14:42:50 2007 for ExultEngine by  doxygen 1.5.1