00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #if (defined(MAIN_XTABDAT8)||defined(MAIN_XTABJTY))
00022 #include <stdio.h>
00023 #endif
00024
00025 #include <stdlib.h>
00026 #include <string.h>
00027
00028 #include "bulcommn.h"
00029 #include "xtabdat8.h"
00030
00031
00032 #ifdef MAIN_XTABDAT8
00033
00034 int main (int argc, char **argv)
00035 {
00036 printf("\nBullfrog Engine DAT/TAB Pair Extractor for 8bpp graphic");
00037 printf("\n-------------------------------\n");
00038 if (argc<3)
00039 {
00040 printf("Not enought parameters.\n");
00041 printf("Usage:\n");
00042 printf(" %s <datafile> <palfile>\n","xtabdat8");
00043 printf("Output: pic????.bmp\n");
00044 return 1;
00045 }
00046
00047 printf("Loading palette ...");
00048
00049 char *palette=malloc(768);
00050 {
00051 char fname[255];
00052 sprintf (fname, "%s.pal", argv[2]);
00053 int retcode=read_palette_rgb(palette,fname,256);
00054 switch (retcode)
00055 {
00056 case ERR_NONE:
00057 break;
00058 case 1:
00059 printf("\nError - Cannot open PAL file: %s\n",fname);
00060 return XTABDAT8_CANT_OPEN;
00061 case 2:
00062 printf("\nError - Cannot read %d colors from PAL file: %s\n",256,fname);
00063 return XTABDAT8_CANT_READ;
00064 default:
00065 printf("\nError - Loading palette file %s returned fail code %d\n",fname,retcode);
00066 return XTABDAT8_INTERNAL;
00067 }
00068 }
00069 printf("Done.\n");
00070
00071
00072 IMAGELIST images;
00073 {
00074 char tabfname[255];
00075 sprintf (tabfname, "%s.tab", argv[1]);
00076 char datfname[255];
00077 sprintf (datfname, "%s.dat", argv[1]);
00078 int retcode=create_images_dattab_idx(&images,datfname,tabfname,1);
00079 if (retcode!=0) return retcode;
00080 }
00081
00082
00083 printf("Extracting images into bitmaps...");
00084 unsigned long picnum;
00085 for (picnum=0;picnum<images.count;picnum++)
00086 {
00087
00088 char fname[20];
00089 sprintf (fname, "pic%0*d.bmp", 4, picnum);
00090 IMAGEITEM *item=&(images.items[picnum]);
00091 if ((item->width*item->height)>0)
00092 write_bmp_idx(fname, item->width, item->height, palette, item->data, 0, 1, 2, 4);
00093 }
00094 printf("completed.\n");
00095
00096 free_dattab_images(&images);
00097 free(palette);
00098 return 0;
00099 }
00100
00101 #endif
00102
00103 int create_images_dattab_idx(struct IMAGELIST *images,const char *datfname,const char *tabfname,const int verbose)
00104 {
00105 if (verbose) msgprintf("Reading TAB file ...");
00106
00107 struct TABFILE tabf;
00108 {
00109 int retcode=read_tabfile_data(&tabf,tabfname);
00110 switch (retcode)
00111 {
00112 case ERR_NONE:
00113 break;
00114 case XTABDAT8_CANT_OPEN:
00115 if (verbose) msgprintf("\nError - Cannot open TAB file: %s\n",tabfname);
00116 return XTABDAT8_CANT_OPEN;
00117 default:
00118 if (verbose) msgprintf("\nError - Loading TAB file %s returned fail code %d\n",tabfname,retcode);
00119 return retcode;
00120 }
00121 }
00122 if (verbose) msgprintf("Done.\n");
00123
00124 if (verbose) msgprintf("Reading DAT file ...");
00125
00126 struct DATFILE datf;
00127 {
00128 int retcode=read_datfile_data(&datf,datfname);
00129 switch (retcode)
00130 {
00131 case ERR_NONE:
00132 break;
00133 case XTABDAT8_CANT_OPEN:
00134 if (verbose) msgprintf("\nError - Cannot open DAT file: %s\n",datfname);
00135 return XTABDAT8_CANT_OPEN;
00136 default:
00137 if (verbose) msgprintf("\nError - Loading DAT file %s returned fail code %d\n",datfname,retcode);
00138 return retcode;
00139 }
00140 }
00141 if (verbose) msgprintf("Done.\n");
00142
00143 if (verbose)
00144 {
00145 msgprintf("\n");
00146 msgprintf ("The TAB file informs of %lu pictures.\n", tabf.count);
00147 if (tabf.filelength!=(tabf.count+1)*6)
00148 {
00149 msgprintf("Warning - the TAB file contains incomplete entry at end.\n");
00150 msgprintf(" The truncated entry will be skipped.\n");
00151 }
00152 if (datf.count==-1)
00153 {
00154 msgprintf ("The DAT file informs of 4bpp content.\n");
00155 msgprintf ("Warning - this is 8bpp extractor!\n");
00156 } else
00157 {
00158 msgprintf ("The DAT file informs of %ld pictures with 8bpp.\n", datf.count);
00159 }
00160 }
00161
00162 if (verbose) msgprintf("Decoding images ...");
00163 unsigned long readcount=2;
00164 read_dattab_images(images,&readcount,&tabf,&datf,verbose);
00165 if (verbose) msgprintf("Done.\n");
00166
00167 if (verbose)
00168 {
00169 msgprintf("Processed %lu of %lu bytes of DAT file.\n",readcount,datf.filelength);
00170 long unused=datf.filelength-readcount;
00171 if (unused>=0)
00172 msgprintf("Bytes skipped: %ld\n",unused);
00173 else
00174 msgprintf("Bytes overlapping: %ld\n",-unused);
00175 }
00176 free_tabfile_data(&tabf);
00177 free_datfile_data(&datf);
00178 return 0;
00179 }
00180
00181 int read_tabfile_data(struct TABFILE *tabf,const char *srcfname)
00182 {
00183 FILE *tabfp;
00184 tabfp = fopen (srcfname, "rb");
00185 if (!tabfp)
00186 return XTABDAT8_CANT_OPEN;
00187 tabf->filelength=file_length_opened(tabfp);
00188 if (tabf->filelength<TABFILE_HEADER_SIZE)
00189 return XTABDAT8_CANT_READ;
00190 tabf->count=((tabf->filelength-TABFILE_HEADER_SIZE)/TABFILE_ENTRY_SIZE);
00191 tabf->items=malloc(tabf->count*sizeof(struct TABFILE_ITEM));
00192 if (!tabf->items) { fclose(tabfp);return XTABDAT8_CANT_READ; }
00193 unsigned char tabitm[TABFILE_ENTRY_SIZE];
00194
00195 fread (tabitm, TABFILE_HEADER_SIZE, 1, tabfp);
00196 int entrynum;
00197 for (entrynum=0;entrynum<tabf->count;entrynum++)
00198 {
00199 struct TABFILE_ITEM *curitm=&(tabf->items[entrynum]);
00200 unsigned long readed=fread (tabitm, 1, TABFILE_ENTRY_SIZE, tabfp);
00201 curitm->offset=read_int32_le_buf(tabitm);
00202 curitm->width=tabitm[4];
00203 curitm->height=tabitm[5];
00204 if (readed < TABFILE_ENTRY_SIZE) return XTABDAT8_CANT_READ;
00205 }
00206 fclose(tabfp);
00207 return ERR_NONE;
00208 }
00209
00210 short write_tabfile_data(const struct TABFILE *tabf,const char *dstfname)
00211 {
00212 FILE *tabfp;
00213 tabfp = fopen (dstfname, "wb");
00214 if (tabfp==NULL)
00215 return XTABDAT8_CANT_OPEN;
00216 int entrynum;
00217 for (entrynum=0;entrynum<TABFILE_HEADER_SIZE;entrynum++)
00218 fputc(0, tabfp);
00219 for (entrynum=0;entrynum<tabf->count;entrynum++)
00220 {
00221 struct TABFILE_ITEM *curitm=&(tabf->items[entrynum]);
00222 write_int32_le_file(tabfp,curitm->offset);
00223 fputc(curitm->width,tabfp);
00224 fputc(curitm->height,tabfp);
00225 }
00226 fclose(tabfp);
00227 return ERR_NONE;
00228 }
00229
00230 short free_tabfile_data(struct TABFILE *tabf)
00231 {
00232 free(tabf->items);
00233 tabf->items=NULL;
00234 tabf->filelength=0;
00235 tabf->count=0;
00236 return ERR_NONE;
00237 }
00238
00239 short alloc_datfile_data(struct DATFILE *datf,unsigned long filelength)
00240 {
00241 datf->filelength=filelength;
00242 datf->data=malloc(filelength);
00243 if (datf->data==NULL)
00244 {
00245 datf->filelength=0;
00246 return XTABDAT8_MALLOC_ERR;
00247 }
00248 return ERR_NONE;
00249 }
00250
00251
00252
00253
00254
00255 short read_datfile_data(struct DATFILE *datf,const char *srcfname)
00256 {
00257 FILE *datfp;
00258 datfp = fopen (srcfname, "rb");
00259 if (datfp==NULL) return XTABDAT8_CANT_OPEN;
00260 datf->count=read_int16_le_file(datfp)-1;
00261 datf->filelength=file_length_opened(datfp);
00262 datf->data=malloc(datf->filelength);
00263 if (datf->data==NULL) { fclose(datfp);return XTABDAT8_MALLOC_ERR; }
00264 fseek(datfp, 0, SEEK_SET);
00265 unsigned long readed=fread(datf->data, 1, datf->filelength, datfp);
00266 fclose(datfp);
00267 if (readed < datf->filelength) return XTABDAT8_CANT_READ;
00268 return ERR_NONE;
00269 }
00270
00271 short write_datfile_data(const struct DATFILE *datf,const char *dstfname)
00272 {
00273 FILE *datfp;
00274 datfp = fopen(dstfname, "wb");
00275 if (datfp==NULL)
00276 return XTABDAT8_CANT_OPEN;
00277 fwrite (datf->data, datf->filelength, 1, datfp);
00278 fclose(datfp);
00279 return ERR_NONE;
00280 }
00281
00282 short free_datfile_data(struct DATFILE *datf)
00283 {
00284 free(datf->data);
00285 datf->data=NULL;
00286 datf->filelength=0;
00287 datf->count=0;
00288 return ERR_NONE;
00289 }
00290
00291 int read_dattab_images(struct IMAGELIST *images,unsigned long *readcount,struct TABFILE *tabf,struct DATFILE *datf,const int verbose)
00292 {
00293 images->count=tabf->count;
00294 images->items=malloc(sizeof(struct IMAGEITEM)*(images->count));
00295 if (!images->items)
00296 {
00297 if (verbose) msgprintf(" Error - cannot allocate %lu bytes of memory.\n",(unsigned long)(sizeof(struct IMAGEITEM)*images->count));
00298 return 1;
00299 }
00300
00301 unsigned long picnum;
00302 unsigned long errnum=0;
00303 unsigned long skipnum=0;
00304 for (picnum=0;picnum<images->count;picnum++)
00305 {
00306 struct TABFILE_ITEM *tabitem=&(tabf->items[picnum]);
00307 struct IMAGEITEM *item=&(images->items[picnum]);
00308 item->width=0;
00309 item->height=0;
00310 item->data=NULL;
00311 item->alpha=NULL;
00312 if (verbose) msgprintf("\rPreparing picture%6lu from %06lx, %ux%u...",picnum,tabitem->offset,tabitem->width,tabitem->height);
00313 if (tabitem->offset >= datf->filelength)
00314 {
00315 if (verbose) msgprintf(" Skipped - Picture offset out of DAT filesize.\n");
00316 skipnum++;
00317 continue;
00318 }
00319 if ((tabitem->width*tabitem->height) < 1)
00320 {
00321 if (verbose) msgprintf(" Skipped - Picture dimensions are invalid.\n");
00322 skipnum++;
00323 continue;
00324 }
00325 unsigned long readedsize;
00326 int retcode;
00327 retcode=read_dat_image_idx(item,&readedsize,datf,tabitem->offset,tabitem->width,tabitem->height);
00328 *readcount+=readedsize;
00329 if ((retcode&XTABDAT8_COLOUR_LEAK))
00330 {
00331 if (verbose) msgprintf (" Error - colour leak out of picture size.\n");
00332 errnum++;
00333 }
00334 else if ((retcode&XTABDAT8_ENDOFBUFFER))
00335 {
00336 if (verbose) msgprintf (" Error - end of DAT buffer, picture truncated.\n");
00337 errnum++;
00338 }
00339 }
00340 if (verbose) msgprintf("\rImages decoded, %lu skipped, %lu errors.\n",skipnum,errnum);
00341 return errnum;
00342 }
00343
00344 int free_dattab_images(struct IMAGELIST *images)
00345 {
00346 unsigned long picnum;
00347 for (picnum=0;picnum<images->count;picnum++)
00348 {
00349 struct IMAGEITEM *item=&(images->items[picnum]);
00350 free(item->data);
00351 free(item->alpha);
00352 }
00353 free(images->items);
00354 images->items=NULL;
00355 images->count=0;
00356 }
00357
00358 int read_dat_image_idx(struct IMAGEITEM *image,unsigned long *readedsize,
00359 const struct DATFILE *datf,const unsigned long off,
00360 const unsigned int width,const unsigned int height)
00361 {
00362
00363 {
00364 image->width=width;
00365 image->height=height;
00366 unsigned long imgsize=width*height;
00367 image->data=malloc(imgsize);
00368 image->alpha=malloc(imgsize);
00369 if ((image->data==NULL)||(image->alpha==NULL))
00370 return XTABDAT8_NOMEMORY;
00371 unsigned long i;
00372 for (i=0;i<imgsize;i++)
00373 {
00374
00375 image->data[i]=0;
00376 image->alpha[i]=255;
00377 }
00378 }
00379
00380 int errorcode=0;
00381
00382 long endoff=off;
00383
00384 unsigned int r=0;
00385
00386 unsigned int c=0;
00387
00388 while (r < height)
00389 {
00390 char g;
00391 if (endoff < datf->filelength)
00392 g = (char) (datf->data[endoff]);
00393 else
00394 {g = 0;errorcode|=XTABDAT8_ENDOFBUFFER;}
00395 endoff++;
00396 if (g < 0)
00397 {
00398 c-=g;
00399 } else
00400 if (!g)
00401 {
00402 c=0;
00403 r++;
00404 } else
00405 {
00406 int i;
00407 for (i=0; i < g; i++)
00408 {
00409 if ((r >= height))
00410 {
00411
00412 errorcode|=XTABDAT8_COLOUR_LEAK;
00413 break;
00414 } else
00415 if ((c > width))
00416 {
00417
00418 r++;c=0;
00419 errorcode|=XTABDAT8_COLOUR_LEAK;
00420 } else
00421 if ((c >= width))
00422 {
00423
00424 errorcode|=XTABDAT8_COLOUR_LEAK;
00425 } else
00426 {
00427
00428 if (endoff < datf->filelength)
00429 {
00430 image->data[(width*r)+c]=datf->data[endoff];
00431 image->alpha[(width*r)+c]=0;
00432 }
00433 else
00434 {
00435 errorcode|=XTABDAT8_ENDOFBUFFER;
00436 }
00437 endoff++;
00438 c++;
00439 }
00440 }
00441 }
00442 }
00443 *readedsize=endoff-off;
00444 return errorcode;
00445 }
00446
00447 int read_dattab_encimages(struct ENCIMAGELIST *images,unsigned long *readcount,
00448 const struct TABFILE *tabf,const struct DATFILE *datf,const int verbose)
00449 {
00450 images->count=tabf->count;
00451 unsigned long all_items_size=sizeof(struct ENCIMAGEITEM)*(images->count);
00452 images->items=malloc(all_items_size);
00453 if (images->items==NULL)
00454 {
00455 if (verbose) msgprintf(" Error\ncannot allocate %lu bytes of memory.\n",all_items_size);
00456 return XTABDAT8_NOMEMORY;
00457 }
00458 if (verbose) msgprintf("Dividing DAT/TAB into list of images...");
00459
00460 unsigned long picnum;
00461 unsigned long errnum=0;
00462 unsigned long skipnum=0;
00463 for (picnum=0;picnum<images->count;picnum++)
00464 {
00465 struct TABFILE_ITEM *tabitem=&(tabf->items[picnum]);
00466 struct ENCIMAGEITEM *item=&(images->items[picnum]);
00467 item->width=tabitem->width;
00468 item->height=tabitem->height;
00469 item->data=NULL;
00470 item->datsize=0;
00471 memset(&(item->attrib),0,sizeof(struct IMGTAB_ATTRIB));
00472 if (verbose) msgprintf("\rPreparing picture%6lu from %06lx, %ux%u...",picnum,tabitem->offset,tabitem->width,tabitem->height);
00473 if (tabitem->offset > datf->filelength)
00474 {
00475 if (verbose) msgprintf(" Skipped - offset out of DAT filesize.\n");
00476 skipnum++;
00477 continue;
00478 }
00479
00480 unsigned long endoffs=datf->filelength;
00481 if (picnum+1<images->count)
00482 {
00483 unsigned long nendoffs=tabf->items[picnum+1].offset;
00484 if ((nendoffs<=endoffs)&&(nendoffs>=tabitem->offset))
00485 {
00486 endoffs=nendoffs;
00487 } else
00488 {
00489 if (verbose)
00490 msgprintf(" Truncated\nReason - Entry size exceeds DAT filesize.\n");
00491 }
00492 }
00493 item->datsize=endoffs-tabitem->offset;
00494 if (item->datsize>0)
00495 {
00496 item->data=malloc(item->datsize+1);
00497 if (item->data==NULL)
00498 {
00499 if (verbose) msgprintf(" Error\ncannot allocate %lu bytes of memory.\n",(unsigned long)(item->datsize));
00500 return XTABDAT8_NOMEMORY;
00501 }
00502 memcpy(item->data,datf->data+tabitem->offset,item->datsize);
00503 }
00504 (*readcount)+=(item->datsize);
00505 }
00506 if (verbose) msgprintf("\rImages prepared; %lu skipped, %lu errors. \n",skipnum,errnum);
00507 return errnum;
00508 }
00509
00510 int write_encimages_dattab(const struct ENCIMAGELIST *images,unsigned long *writecount,
00511 struct TABFILE *tabf,struct DATFILE *datf)
00512 {
00513 short retcode;
00514
00515 tabf->filelength=(images->count*TABFILE_ENTRY_SIZE);
00516 retcode=alloc_jtytabfile_data(tabf,images->count);
00517 if (retcode!=ERR_NONE) return retcode;
00518
00519 unsigned long datlength=0;
00520 int entrynum;
00521 for (entrynum=0;entrynum<images->count;entrynum++)
00522 datlength+=(images->items[entrynum].datsize);
00523 retcode=alloc_datfile_data(datf,datlength);
00524 if (retcode!=ERR_NONE) return retcode;
00525
00526 unsigned long datoffs=0;
00527 for (entrynum=0;entrynum<images->count;entrynum++)
00528 {
00529 struct TABFILE_ITEM *ctab=&(tabf->items[entrynum]);
00530 struct ENCIMAGEITEM *img=&(images->items[entrynum]);
00531 memcpy(datf->data+datoffs,img->data,img->datsize);
00532 ctab->offset=datoffs;
00533 ctab->width=img->width;
00534 ctab->height=img->height;
00535 datoffs+=img->datsize;
00536 }
00537 (*writecount)=datoffs;
00538 return ERR_NONE;
00539 }
00540
00541
00542
00543
00544 short create_images_dattab_enc(struct ENCIMAGELIST *images,const char *datfname,
00545 const char *tabfname,const int verbose)
00546 {
00547 if (verbose) msgprintf("Reading TAB file ...");
00548
00549 struct TABFILE tabf;
00550 {
00551 int retcode=read_tabfile_data(&tabf,tabfname);
00552 switch (retcode)
00553 {
00554 case ERR_NONE:
00555 break;
00556 case XTABDAT8_CANT_OPEN:
00557 if (verbose) msgprintf(" Error\nCannot open TAB file \"%s\"\n",tabfname);
00558 return XTABDAT8_CANT_OPEN;
00559 default:
00560 if (verbose) msgprintf(" Error\nLoading TAB file \"%s\" returned fail code %d\n",tabfname,retcode);
00561 return retcode;
00562 }
00563 }
00564 if (verbose) msgprintf(" Done.\n");
00565
00566 if (verbose) msgprintf("Reading DAT file ...");
00567
00568 struct DATFILE datf;
00569 {
00570 int retcode=read_datfile_data(&datf,datfname);
00571 switch (retcode)
00572 {
00573 case ERR_NONE:
00574 break;
00575 case XTABDAT8_CANT_OPEN:
00576 if (verbose) msgprintf(" Error\nCannot open DAT file \"%s\"\n",datfname);
00577 return XTABDAT8_CANT_OPEN;
00578 default:
00579 if (verbose) msgprintf(" Error\nLoading DAT file \"%s\" returned fail code %d\n",datfname,retcode);
00580 return retcode;
00581 }
00582 }
00583 if (verbose) msgprintf(" Done.\n");
00584
00585 if (verbose)
00586 {
00587 msgprintf ("The TAB file informs of %lu pictures.\n", tabf.count);
00588 if (tabf.filelength != (tabf.count*TABFILE_ENTRY_SIZE+TABFILE_HEADER_SIZE))
00589 {
00590 msgprintf("\n");
00591 msgprintf("Warning - the TAB file contains incomplete entry at end.\n");
00592 msgprintf(" The truncated entry will be skipped.\n");
00593 msgprintf("\n");
00594 }
00595 if (datf.count==-1)
00596 {
00597 msgprintf("\n");
00598 msgprintf ("The DAT file informs of 4bpp content.\n");
00599 msgprintf ("Warning - this is 8bpp extractor!\n");
00600 msgprintf("\n");
00601 }
00602 }
00603 unsigned long readcount=0;
00604 read_dattab_encimages(images,&readcount,&tabf,&datf,verbose);
00605
00606 if (verbose)
00607 {
00608 msgprintf("Processed %lu of %lu bytes of DAT file.\n",readcount,datf.filelength);
00609 long unused=datf.filelength-readcount;
00610 if (unused>0)
00611 {
00612 msgprintf("Bytes skipped: %ld\n",unused);
00613 } else
00614 if (unused<0)
00615 {
00616 msgprintf("Bytes overlapping: %ld\n",-unused);
00617 }
00618 }
00619
00620 free_tabfile_data(&tabf);
00621 free_datfile_data(&datf);
00622 return ERR_NONE;
00623 }
00624
00625
00626
00627
00628 short write_dattab_images_enc(const struct ENCIMAGELIST *images,const char *datfname,
00629 const char *tabfname,const int verbose)
00630 {
00631 struct TABFILE tabf;
00632 struct DATFILE datf;
00633 unsigned long writecount=0;
00634 write_encimages_dattab(images,&writecount,&tabf,&datf);
00635 if (verbose) msgprintf("Writing TAB file ...");
00636 write_tabfile_data(&tabf,tabfname);
00637 if (verbose) msgprintf(" Done.\n");
00638 if (verbose) msgprintf("Writing DAT file ...");
00639 write_datfile_data(&datf,datfname);
00640 if (verbose) msgprintf(" Done.\n");
00641 free_tabfile_data(&tabf);
00642 free_datfile_data(&datf);
00643 return ERR_NONE;
00644 }