99
1010#include < string.h>
1111#include < nstd/String.hpp>
12+ #include < nstd/Array.hpp>
1213
1314#include " math/Vector.h"
1415
1516const int SKY_CLUT_START_Y = 252 ;
1617const int SKY_SIZE_W = 256 / 4 ;
1718const int SKY_SIZE_H = 84 ;
1819
20+ const int BG_SPLICE_W = 64 ;
21+ const int BG_SPLICE_H = 256 ;
22+ const int BG_SPLICE_SIZE = BG_SPLICE_W * 2 * BG_SPLICE_H;
23+
1924void CopyTpageImage (ushort* tp_src, ushort* dst, int x, int y, int dst_w, int dst_h)
2025{
2126 ushort* src = tp_src + x + 128 * y;
@@ -234,7 +239,7 @@ void ExportExtraImage(const char* filename, ubyte* data, ubyte* clut_data, int n
234239
235240// In frontend, extra poly has a preview image drawn
236241void ConvertBackgroundRaw (const char * filename, const char * extraFilename)
237- {
242+ {
238243 FILE* bgFp = fopen (filename, " rb" );
239244
240245 if (!bgFp)
@@ -255,7 +260,7 @@ void ConvertBackgroundRaw(const char* filename, const char* extraFilename)
255260
256261 fclose (bgFp);
257262
258- ubyte* imageClut = bgData + 11 * 0x8000 ;
263+ ubyte* imageClut = bgData + 11 * BG_SPLICE_SIZE ;
259264
260265 // convert background image and store
261266 {
@@ -275,7 +280,7 @@ void ConvertBackgroundRaw(const char* filename, const char* extraFilename)
275280
276281 for (int i = 0 ; i < 6 ; i++)
277282 {
278- ubyte* bgImagePiece = bgData + i * 0x8000 ;
283+ ubyte* bgImagePiece = bgData + i * BG_SPLICE_SIZE ;
279284
280285 int rect_y = i / 3 ;
281286 int rect_x = (i - (rect_y & 1 ) * 3 ) * 128 ;
@@ -297,7 +302,7 @@ void ConvertBackgroundRaw(const char* filename, const char* extraFilename)
297302 // check if it's GFX.RAW
298303 // if(str.find("gfx"))
299304 {
300- imageClut = bgData + 0x30000 + 5 * 0x8000 + 128 ;
305+ imageClut = bgData + 0x30000 + 5 * BG_SPLICE_SIZE + 128 ;
301306
302307 // extract font
303308 ubyte* bgImagePiece = bgData + 0x30000 ;
@@ -306,18 +311,19 @@ void ConvertBackgroundRaw(const char* filename, const char* extraFilename)
306311 bgImagePiece, 64 *2 *256 , 0 , 0 , 256 , 256 , imageClut, 1 );
307312
308313 imageClut += 128 ;
309- bgImagePiece += 0x8000 ;
314+ bgImagePiece += BG_SPLICE_SIZE ;
310315
311316 // extract selection texture
312317 SaveTIM_4bit (varargs (" %s_SEL.TIM" , filename),
313318 bgImagePiece, 64 * 2 * 36 , 0 , 0 , 256 , 36 , imageClut, 1 );
314319 }
315- /* else // pointless to have font and selection texture as tpage, but i'll leave it here as reference code
320+
321+ // else // pointless to have font and selection texture as tpage, but i'll leave it here as reference code
316322 {
317323 // try extract the rest
318324 for (int i = 0 ; i < 6 ; i++)
319325 {
320- ubyte* bgImagePiece = bgData + 0x30000 + i * 0x8000 ;
326+ ubyte* bgImagePiece = bgData + 0x30000 + i * BG_SPLICE_SIZE ;
321327
322328 int rect_y = i / 3 ;
323329 int rect_x = (i - (rect_y & 1 ) * 3 ) * 128 ;
@@ -334,7 +340,7 @@ void ConvertBackgroundRaw(const char* filename, const char* extraFilename)
334340
335341 SaveTIM_4bit (varargs (" %s_REST.TIM" , filename),
336342 timData, 64 * 6 * 512 , 0 , 0 , 384 * 2 , 512 , (ubyte*)imageClut, 1 );
337- }*/
343+ }
338344 }
339345
340346 // load extra file if specified
@@ -361,9 +367,9 @@ void ConvertBackgroundRaw(const char* filename, const char* extraFilename)
361367
362368 for (int i = 0 ; i < 16 ; i++)
363369 {
364- ubyte* imageAddr = data + i * 0x8000 ;
370+ ubyte* imageAddr = data + i * BG_SPLICE_SIZE ;
365371
366- if ((i * 0x8000 ) < size)
372+ if ((i * BG_SPLICE_SIZE ) < size)
367373 ExportExtraImage (extraFilename, imageAddr, imageClut, i);
368374 }
369375
@@ -377,12 +383,122 @@ void ConvertBackgroundRaw(const char* filename, const char* extraFilename)
377383
378384// -----------------------------------------------------
379385
386+ // builds image out of separate TIM slices
387+ bool BuildBackgroundRaw (char * out, const Array<char *>& timFileNames)
388+ {
389+ Array<usize> size_cd;
390+ Array<ubyte*> clut_data;
391+
392+ // TODO: check for maximum number of images
393+
394+ clut_data.resize (timFileNames.size ());
395+ size_cd.resize (timFileNames.size ());
396+
397+ FILE* fp = fopen (out, " wb" );
398+
399+ if (!fp)
400+ {
401+ MsgError (" Unable to open '%s' file\n " , out);
402+ return false ;
403+ }
404+
405+ for (usize i = 0 ; i < timFileNames.size (); i++)
406+ {
407+ FILE* inFp = fopen (timFileNames[i], " rb" );
408+ if (!inFp)
409+ {
410+ MsgError (" Unable to open '%s' file\n " , timFileNames[i]);
411+ return false ;
412+ }
413+
414+ MsgInfo (" Adding file: '%s'\n " , timFileNames[i]);
415+
416+ TIMHDR timHdr;
417+ TIMIMAGEHDR cluthdr;
418+ TIMIMAGEHDR header;
419+ ubyte* image_data;
420+
421+ // Check header
422+ fread (&timHdr, 1 , sizeof (timHdr), inFp);
423+ if (timHdr.magic != 0x10 )
424+ {
425+ MsgError (" Input file is not a TIM file!\n " );
426+ fclose (inFp);
427+ return false ;
428+ }
429+
430+ if (timHdr.flags != 0x08 )
431+ {
432+ MsgError (" Input image must be 4-bit!\n " );
433+ fclose (inFp);
434+ return false ;
435+ }
436+
437+ // FIXME: need to check background image size properties!!!
438+
439+ // Parsing CLUT Header
440+ fread (&cluthdr, 1 , sizeof (cluthdr), inFp);
441+ clut_data[i] = static_cast <ubyte*>(malloc (cluthdr.len - sizeof (cluthdr)));
442+ fread (clut_data[i], 1 , cluthdr.len - sizeof (cluthdr), inFp);
443+
444+ // Parsing image data header
445+ fread (&header, 1 , sizeof (header), inFp);
446+ image_data = static_cast <ubyte*>(malloc (header.len - sizeof (header)));
447+ fread (image_data, 1 , header.len - sizeof (header), inFp);
448+
449+ size_cd[i] = cluthdr.len - sizeof (cluthdr);
450+
451+ fclose (inFp);
452+ MsgInfo (" Writing image data of file '%s' to '%s'\n " , timFileNames[i], out);
453+
454+ ubyte* bgImagePiece = static_cast <ubyte*>(malloc (BG_SPLICE_SIZE));
455+
456+ for (int j = 0 ; j < 6 ; j++)
457+ {
458+ int rect_y = j / 3 ;
459+ int rect_x = (j - (rect_y & 1 ) * 3 ) * (BG_SPLICE_W * 2 );
460+ rect_y *= BG_SPLICE_H;
461+
462+ for (int y = 0 ; y < BG_SPLICE_H; y++)
463+ {
464+ for (int x = 0 ; x < BG_SPLICE_W * 2 ; x++)
465+ {
466+ bgImagePiece[y * BG_SPLICE_W * 2 + x] = image_data[(rect_y + y) * BG_SPLICE_W * 6 + rect_x + x];
467+ }
468+ }
469+
470+ fwrite (bgImagePiece, 1 , BG_SPLICE_SIZE, fp);
471+ }
472+
473+ free (bgImagePiece);
474+ free (image_data);
475+ }
476+
477+ // Set offset to start of CLUT data
478+ fseek (fp, 0x58000 , SEEK_SET);
479+ for (usize i = 0 ; i < timFileNames.size (); i++)
480+ {
481+ MsgInfo (" Writting CLUT data to '%s'\n " , timFileNames[i]);
482+ fwrite (clut_data[i], 1 , size_cd[i], fp);
483+
484+ free (clut_data[i]);
485+ }
486+
487+ fclose (fp);
488+ MsgAccept (" '%s' compiled with success !\n " , out);
489+
490+ return true ;
491+ }
492+
493+ // -----------------------------------------------------
494+
380495void PrintCommandLineArguments ()
381496{
382497 MsgInfo (" Example usage:\n " );
383498 MsgInfo (" \t DriverImageTool -sky2tim SKY0.RAW\n " );
384499 MsgInfo (" \t DriverImageTool -sky2tga SKY1.RAW\n " );
385500 MsgInfo (" \t DriverImageTool -bg2tim CARBACK.RAW <CCARS.RAW>\n " );
501+ MsgInfo (" \t DriverImageTool -tim2raw GFX.RAW BG.tim <FontAndSelection.tim Image3.tim ..>\n " );
386502}
387503
388504int main (int argc, char ** argv)
@@ -432,7 +548,27 @@ int main(int argc, char** argv)
432548 ConvertBackgroundRaw (argv[i + 1 ], nullptr );
433549 }
434550 else
435- MsgWarning (" -bg2tim must have an argument!" );
551+ MsgWarning (" -bg2tim must have argument!" );
552+ }
553+ else if (!stricmp (argv[i], " -tim2raw" ))
554+ {
555+ if (i + 2 <= argc)
556+ {
557+ Array<char *> filenames;
558+ const char * outputFilename = argv[i + 1 ];
559+
560+ for (int j = i + 2 ; j < argc; j++)
561+ {
562+ if (*argv[j] == ' -' || *argv[j] == ' +' || *argv[j] == ' /' || *argv[j] == ' \\ ' ) // encountered new option?
563+ break ;
564+
565+ filenames.append (argv[j]);
566+ }
567+
568+ BuildBackgroundRaw (argv[i + 1 ], filenames);
569+ }
570+ else
571+ MsgWarning (" -tim2raw must have at least two arguments!" );
436572 }
437573 }
438574
0 commit comments