home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 31 / CDASC_31_1996_juillet_aout.iso / vrac / d3dlvedt.zip / DN3D-DC.C < prev    next >
C/C++ Source or Header  |  1996-03-14  |  25KB  |  987 lines

  1. // duke hack- compile/decomile .grp/.art files
  2. //
  3. //    Format for PALETTE.DAT file:
  4. //
  5. //        768     system palette
  6. //        2        number of ppalette lookup tables
  7. //        256    palette lookup table
  8. //        ...
  9. //
  10. // format for *.ART file:
  11. //
  12. //        4        ??? (1)
  13. //        4        ???
  14. //        4        ???
  15. //        4        ???
  16. //
  17. //        512    256 widths (int)
  18. //        512    256 height (int)
  19. //        512    ??? (int)
  20. //        512    ??? (int)
  21. //
  22. //
  23. //    compiled using huge model
  24. //
  25. // syntax:
  26. //
  27. //        DN3D-DC <command> <grp/art file> <directory>
  28. //
  29. //    commands:
  30. //
  31. //        DG    : decompile individual files to directory and create GRP.LST
  32. //
  33. //        CG    : compile grp file from individual files in directory using GRP.LST (also backup old GRP file)
  34. //
  35. //        DA : decompile individual files to directory and create TILES0??.LST file
  36. //
  37. //    CA : compile art file from individual files in directory using TILES0??.LST file
  38.  
  39. // includes...
  40. #include <alloc.h>
  41. #include <conio.h>
  42. #include <ctype.h>
  43. #include <dir.h>
  44. #include <mem.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48.  
  49. // defines...
  50. // booleans
  51. #define FALSE    0
  52. #define TRUE    1
  53.  
  54. // commands
  55. #define CMD_DECOMPGRP    0
  56. #define CMD_DECOMPART    1
  57. #define CMD_COMPGRP        2
  58. #define CMD_COMPART        3
  59.  
  60.  
  61. // typedef...
  62. typedef struct
  63. {
  64.     char        szLabel[12];
  65.     long        nSize;
  66.  
  67. } DIRATOM, far* LPDIRATOM;
  68.  
  69. typedef struct
  70. {
  71.     char    szID[2];
  72.     long    nFileSize;
  73.     long    nReserved;
  74.     long    nHeaderSize;
  75.     long    nInfoSize;
  76.     long    nWidth;
  77.     long    nHeight;
  78.     short    nPlanes;
  79.     short    nBits;
  80.     long    nCompression;
  81.     long    nImageSize;
  82.     long    xPelsPerMeter;
  83.     long    yPelsPerMeter;
  84.     long    nClrUsed;
  85.     long    nClrImportant;
  86.  
  87. } BMPHEADER;
  88.  
  89. typedef struct
  90. {
  91.     char    nBlue;
  92.     char    nGreen;
  93.     char    nRed;
  94.     char    nFilter;
  95.  
  96. } RGBQUAD;
  97.  
  98. typedef struct
  99. {
  100.     char    nRed;
  101.     char    nGreen;
  102.     char    nBlue;
  103.  
  104. } RGBART;
  105.  
  106. typedef struct
  107. {
  108.     char    nIdx[256];
  109.  
  110. } LUTART, far* LPLUTART;
  111.  
  112. // global info...
  113. int        nCmd;
  114. char        szCommand[MAXPATH];        // the command
  115. char        szGrpPath[MAXPATH];        // the full grp/art file name
  116. char        szGrpDrive[MAXDRIVE];    // subpart of szGrpPath
  117. char        szGrpDir[MAXDIR];            // subpart of szGrpPath
  118. char        szGrpName[MAXFILE];        // subpart of szGrpPath
  119. char        szGrpExt[MAXEXT];            // subpart of szGrpPath
  120. char        szDirPath[MAXPATH];        // when the stuff goes/is
  121.  
  122. RGBART    pSysPal[256];                // system palette
  123. short        nPalLUT;                        // number of palette lookup tables
  124. LPLUTART    lpPalLUT;                    // pointer to palette lookup tables
  125. long        aArtHeader[4];                // the first 16 bytes of an art file.
  126. short        anWidth[256];                // the widths
  127. short        anHeight[256];                // the heights
  128. short        anVal1[256];                // unknown for now
  129. short        anVal2[256];                // unknown for now
  130.  
  131. char        pTempBuff[640];            // temp buffer
  132.  
  133. // prototypes...
  134. void     PrintInfo(void);
  135. void     PrintHelp(void);
  136. int     DecompileGrp(void);
  137. int     DecompileArt(void);
  138. int     CompileArt(void);
  139. int     CompileGrp(void);
  140.  
  141. extern unsigned _stklen = 16768u;
  142.  
  143. // the functions...
  144. int main(int nArgs, char* aszArg[])
  145. {
  146.     // a little info...
  147.     PrintInfo();
  148.  
  149.     //we running with 4 arguments?
  150.     if (nArgs != 4)
  151.     {
  152.         PrintHelp();
  153.         return -1;
  154.     }
  155.  
  156.     // get arguments.
  157.     strcpy(szCommand, aszArg[1]);
  158.     strupr(szCommand);
  159.     strcpy(szGrpPath, aszArg[2]);    // grp [drive:][\directory\]filename.ext
  160.     fnsplit(szGrpPath, szGrpDrive, szGrpDir, szGrpName, szGrpExt);
  161.     strcpy(szDirPath, aszArg[3]);    // destination [drive:][\directory[\]]
  162.     if (!strcmp(szCommand, "DG"))
  163.         nCmd = CMD_DECOMPGRP;
  164.     else if (!strcmp(szCommand, "DA"))
  165.         nCmd = CMD_DECOMPART;
  166.     else if (!strcmp(szCommand, "CG"))
  167.         nCmd = CMD_COMPGRP;
  168.     else if (!strcmp(szCommand, "CA"))
  169.         nCmd = CMD_COMPART;
  170.     else
  171.     {
  172.         // bad command
  173.         PrintHelp();
  174.         return -1;
  175.     }
  176.  
  177.     // be sure there is no / on end of dir
  178.     if (szDirPath[strlen(szDirPath) - 1] == '\\')
  179.         szDirPath[strlen(szDirPath) - 1] = '\0';
  180.  
  181.     // branch to do the tasks
  182.     switch (nCmd)
  183.     {
  184.         case CMD_COMPGRP:
  185.             // compile art file
  186.             printf("Compiling %s...\n", szGrpPath);
  187.             if (!CompileGrp())
  188.             {
  189.                 printf("Error in compiling\n");
  190.                 return -1;
  191.             }
  192.             break;
  193.  
  194.         case CMD_COMPART:
  195.             // compile art file
  196.             printf("Compiling %s...\n", szGrpPath);
  197.             if (!CompileArt())
  198.             {
  199.                 printf("Error in compiling\n");
  200.                 return -1;
  201.             }
  202.             break;
  203.  
  204.         case CMD_DECOMPART:
  205.             // decompile art file
  206.             printf("Decompiling %s...\n", szGrpPath);
  207.             if (!DecompileArt())
  208.             {
  209.                 printf("Error in decompiling\n");
  210.                 return -1;
  211.             }
  212.             break;
  213.  
  214.         case CMD_DECOMPGRP:
  215.             // decompile grp file
  216.             printf("Decompiling %s...\n", szGrpPath);
  217.             if (!DecompileGrp())
  218.             {
  219.                 printf("Error in decompiling\n");
  220.                 return -1;
  221.             }
  222.             break;
  223.  
  224.         default:
  225.             // we shouldn't get in here!
  226.             PrintHelp();
  227.             return -1;
  228.  
  229.     }
  230.     return 0;
  231. }
  232.  
  233. void PrintInfo(void)
  234. {
  235.     printf("┌┬┬──────────────────────────────────────────────────────────────────┬┬┐\n");
  236.     printf("│││          Duke Nukem 3D Decompiler/Compiler  Version 1.1          │││\n");
  237.     printf("│││ GRP/ART file compiler/decompiler for Duke Nukem 3D 1.1 shareware │││\n");
  238.     printf("│││      Written By Daniel Mecklenburg Jr, codewar@ns.cencom.net     │││\n");
  239.     printf("└┴┴──────────────────────────────────────────────────────────────────┴┴┘\n");
  240. }
  241.  
  242. void PrintHelp(void)
  243. {
  244.     printf("\n"
  245.         "Syntax:\n"
  246.         "  DN3D-DC <command> <file> <directory>\n"
  247.         "\n"
  248.         "Commands:\n"
  249.         "  DG : decompile individual files from grp file to directory and create .LST\n"
  250.         "  CG : backup/compile grp file from individual files in directory using .LST\n"
  251.         "  DA : decompile individual files from art file to directory and create .LST\n"
  252.         "  CA : backup/compile art file from individual files in directory using .LST\n"
  253.         "\n"
  254.         "Examples:\n"
  255.         "  DN3D-DC DG DUKE3D.GRP F:\\DUKERES\\ : will extract all files in DUKE3D.GRP\n"
  256.         "    and place them in F:\\DUKERES\\ (ending \\ on directories are optional).\n"
  257.         "    A text file called DUKE3D.LST will be created containing the GRP's\n"
  258.         "    packing list.\n"
  259.         "  DN3D-DC DA TILES000.ART F:\\DUKERES\\ : will extract all graphics from\n"
  260.         "    TILES000.ART and save them as BMP's in F:\\DUKERES\\ named 000-000.BMP\n"
  261.         "    though 000-255.BMP. A text file called TILES000.LST will be created\n"
  262.         "    containing the ART's packing list.\n"
  263.         "  DN3D-DC CA G:\\STUFF\\TILES000.ART E:\\BMPS : will create TILES000.ART\n"
  264.         "    from the TILES000.LST and BMP files located in E:\\BMP.\n");
  265. }
  266.  
  267. char* szComplete = "Completed!                           \n";
  268. char* szAbort = "Aborted!                             \n";
  269.  
  270. int DecompileGrp(void)
  271. {
  272.     // decompile the grp file (szGrpPath) to directory (szDirPath)
  273.  
  274.     FILE*            pFile;                    // the .grp file
  275.     FILE*            pOutFile;                // the grp.lst file
  276.     FILE*            pResFile;                // the individual files
  277.     char            pStr[13];                // holds the ken tag
  278.     long            nDirSize;                // entries in directory
  279.     LPDIRATOM    lpDir;                    // pointer to the dir list
  280.     char            szFilename[MAXPATH];    // filename work
  281.     int            nIdx;                        // dir index
  282.     long            nIdx2;                    // file byte index
  283.     int            c;                            // a byte read/written
  284.    char*            pDoneMsg = szComplete;
  285.  
  286.     // open the grp file...
  287.     if ((pFile = fopen(szGrpPath, "rb")) == NULL)
  288.     {
  289.         printf("Could not open %s.\n", szGrpPath);
  290.         return FALSE;
  291.     }
  292.  
  293.     // get/check the tag
  294.     if (fread(pStr, 12, 1, pFile) != 1)
  295.     {
  296.         printf("Error reading %s.\n", szGrpPath);
  297.         fclose(pFile);
  298.         return FALSE;
  299.     }
  300.     pStr[12] = '\0';
  301.     if (strcmp(pStr, "KenSilverman") != 0)
  302.     {
  303.         printf("%s is not a DukeNukem3d grp file.\n", szGrpPath);
  304.         fclose(pFile);
  305.         return FALSE;
  306.     }
  307.  
  308.     // get number of entries
  309.     if (fread(&nDirSize, sizeof (long), 1, pFile) != 1)
  310.     {
  311.         printf("I/O error.\n");
  312.         fclose(pFile);
  313.         return FALSE;
  314.     }
  315.  
  316.     // allocate directory structure
  317.     if ((lpDir = farmalloc(16 * (size_t)nDirSize)) == NULL)
  318.     {
  319.         printf("Out of memory.\n");
  320.         fclose(pFile);
  321.         return FALSE;
  322.     }
  323.  
  324.     // read directory  in
  325.     for (nIdx = 0; nIdx < nDirSize; nIdx++)
  326.     {
  327.         if (fread(&lpDir[nIdx], sizeof (DIRATOM), 1, pFile) != 1)
  328.         {
  329.             printf("I/O error.\n");
  330.             farfree(lpDir);
  331.             fclose(pFile);
  332.             return FALSE;
  333.         }
  334.     }
  335.  
  336.     // create .LST file
  337.     sprintf(szFilename, "%s\\%s.LST", szDirPath, szGrpName);
  338.     if ((pOutFile = fopen(szFilename, "w")) == NULL)
  339.     {
  340.         printf("Could not create %s file.\n", szFilename);
  341.         farfree(lpDir);
  342.         fclose(pFile);
  343.         return FALSE;
  344.     }
  345.     for (nIdx = 0; nIdx < nDirSize; nIdx++)
  346.     {
  347.         _fmemcpy(pStr, lpDir[nIdx].szLabel, 12);
  348.         pStr[12] = '\0';
  349.  
  350.         fprintf(pOutFile, "%s\n", pStr);
  351.         printf("%s           \r", pStr);
  352.  
  353.         // create this resource file
  354.         sprintf(szFilename, "%s\\%s", szDirPath, pStr);
  355.         if ((pResFile = fopen(szFilename, "wb")) == NULL)
  356.         {
  357.             printf("Could not create %s.\n", pStr);
  358.             farfree(lpDir);
  359.             fclose(pFile);
  360.             fclose(pOutFile);
  361.             return FALSE;
  362.         }
  363.         for (nIdx2 = 0; nIdx2 < lpDir[nIdx].nSize; nIdx2++)
  364.         {
  365.             if ((c = fgetc(pFile)) == EOF)
  366.             {
  367.                 printf("Unexpected EOF.\n");
  368.                 farfree(lpDir);
  369.                 fclose(pFile);
  370.                 fclose(pOutFile);
  371.                 return FALSE;
  372.             }
  373.             if (fputc(c, pResFile) == EOF)
  374.             {
  375.                 printf("Unable to write to %s.\n", pStr);
  376.                 farfree(lpDir);
  377.                 fclose(pFile);
  378.                 fclose(pOutFile);
  379.                 return FALSE;
  380.             }
  381.         }
  382.         fclose(pResFile);
  383.  
  384.         if (kbhit())
  385.         {
  386.             if (getch() == 27)
  387.             {
  388.                 pDoneMsg = szAbort;
  389.             break;
  390.             }
  391.         }
  392.     }
  393.     printf(pDoneMsg);
  394.     fclose(pOutFile);
  395.  
  396.     // free directory
  397.     farfree(lpDir);
  398.  
  399.     // and close the file...
  400.     fclose(pFile);
  401.  
  402.     return TRUE;
  403. }
  404.  
  405.  
  406. int DecompileArt(void)
  407. {
  408.     // decompile the art file (szGrpPath) to directory (szDirPath)
  409.  
  410.     long            nImageSize;
  411.     long            nPalSize;
  412.     long            nRasterSize;            // size of raster
  413.     FILE*            pFile;                    // the .grp file
  414.     FILE*            pOutFile;                // the grp.lst file
  415.     FILE*            pResFile;                // the individual files
  416.     FILE*            pPalFile;                // the palette.dat file
  417.     char            szFilename[MAXPATH];    // filename work
  418.     char            szBMPName[MAXPATH];    // BMP filename
  419.     char            szPalName[MAXPATH];    // Palette filename
  420.     int            nIdx;                        // dir index
  421.     int            nIdx2;                    // file byte index
  422.     int            nRow, nCol;                // bitmap index
  423.     RGBQUAD        rgb;                        // a BMP palette entry
  424.     BMPHEADER    bmpHeader;                // header for bmp file
  425.     char huge*    lpBitmap;                // the bitmap image read in
  426.     char huge*    lp;                        // temp pointer
  427.     char*            pDoneMsg = szComplete;
  428.  
  429.     // open the art file...
  430.     if ((pFile = fopen(szGrpPath, "rb")) == NULL)
  431.     {
  432.         printf("Could not open %s.\n", szGrpPath);
  433.         return FALSE;
  434.     }
  435.  
  436.     // get header
  437.     if (fread((void*)aArtHeader, sizeof (long), 4, pFile) < 4)
  438.     {
  439.         printf("Error reading %s.\n", szGrpPath);
  440.         fclose(pFile);
  441.         return FALSE;
  442.     }
  443.  
  444.     // read widths/heights/other info
  445.     if (fread(anWidth, sizeof (short), 256, pFile) < 256)
  446.     {
  447.         printf("I/O error.\n");
  448.         fclose(pFile);
  449.         return FALSE;
  450.     }
  451.     if (fread(anHeight, sizeof (short), 256, pFile) < 256)
  452.     {
  453.         printf("I/O error.\n");
  454.         fclose(pFile);
  455.         return FALSE;
  456.     }
  457.     if (fread(anVal1, sizeof (short), 256, pFile) < 256)
  458.     {
  459.         printf("I/O error.\n");
  460.         fclose(pFile);
  461.         return FALSE;
  462.     }
  463.     if (fread(anVal2, sizeof (short), 256, pFile) < 256)
  464.     {
  465.         printf("I/O error.\n");
  466.         fclose(pFile);
  467.         return FALSE;
  468.     }
  469.  
  470.     // go fetch the palette. must be called palette.dat and in the destination with the tiles.art file
  471.     sprintf(szPalName, "%sPALETTE.DAT", szGrpDir);
  472.     if ((pPalFile = fopen(szPalName, "rb")) == NULL)
  473.     {
  474.         printf("Unable to open palette file. Must reside with ART file.\n");
  475.         fclose(pFile);
  476.         return FALSE;
  477.     }
  478.     // read the main system palette
  479.     if (fread(pSysPal, sizeof (RGBART), 256, pPalFile) < 256)
  480.     {
  481.         printf("I/O error.\n");
  482.         fclose(pFile);
  483.         fclose(pPalFile);
  484.         return FALSE;
  485.     }
  486.     // get number of palette look up tables
  487.     if (fread(&nPalLUT, sizeof (short), 1, pPalFile) < 1)
  488.     {
  489.         printf("I/O error.\n");
  490.         fclose(pFile);
  491.         fclose(pPalFile);
  492.         return FALSE;
  493.     }
  494.     // allocate and read the pal luts
  495.     if ((lpPalLUT = farmalloc(nPalLUT * sizeof (LUTART))) == NULL)
  496.     {
  497.         printf("Out of memory.\n");
  498.         fclose(pFile);
  499.         fclose(pPalFile);
  500.         return FALSE;
  501.     }
  502.     if (fread(lpPalLUT, sizeof (LUTART), nPalLUT, pPalFile) < nPalLUT)
  503.     {
  504.         printf("I/O error.\n");
  505.         farfree(lpPalLUT);
  506.         fclose(pFile);
  507.         fclose(pPalFile);
  508.         return FALSE;
  509.     }
  510.     fclose(pPalFile);
  511.  
  512.     // create .LST file
  513.     sprintf(szFilename, "%s\\%s.LST", szDirPath, szGrpName);
  514.     if ((pOutFile = fopen(szFilename, "w")) == NULL)
  515.     {
  516.         printf("Could not create %s file.\n", szFilename);
  517.         fclose(pFile);
  518.         return FALSE;
  519.     }
  520.  
  521.     // write the header info
  522.     fprintf(pOutFile, "%ld %ld %ld %ld\n",
  523.         aArtHeader[0], aArtHeader[1], aArtHeader[2], aArtHeader[3]);
  524.  
  525.     for (nIdx = 0; nIdx < 256; nIdx++)
  526.     {
  527.         // create filename nnn-aaa.bmp where nnn is number (0-255) inside art file and
  528.         // aaa is last three digits of tiles???.art filename
  529.  
  530.         if (anWidth[nIdx] && anHeight[nIdx])
  531.         {
  532.             sprintf(szBMPName, "%03d-%c%c%c.BMP", nIdx, szGrpName[5], szGrpName[6], szGrpName[7]);
  533.             fprintf(pOutFile, "%3d %-16s %d %d %d %d\n", nIdx, szBMPName, anWidth[nIdx], anHeight[nIdx], anVal1[nIdx], anVal2[nIdx]);
  534.             printf("%3d %s           \r", nIdx, szBMPName);
  535.  
  536.             // create this resource file
  537.             sprintf(szFilename, "%s\\%s", szDirPath, szBMPName);
  538.             if ((pResFile = fopen(szFilename, "wb")) == NULL)
  539.             {
  540.                 printf("Could not create %s.\n", szBMPName);
  541.                 fclose(pFile);
  542.                 fclose(pOutFile);
  543.                 return FALSE;
  544.             }
  545.  
  546.             // write bmp header
  547.             nRasterSize = anWidth[nIdx];
  548.             if (nRasterSize & 0x00000003L)
  549.             {
  550.                 nRasterSize |= 0x00000003L;
  551.                 nRasterSize++;
  552.             }
  553.             nImageSize  = nRasterSize * (long)anHeight[nIdx];
  554.             nPalSize    = (long)sizeof (RGBQUAD) * 256L;
  555.             _fmemset(&bmpHeader, 0, sizeof (BMPHEADER));
  556.             bmpHeader.szID[0]     = 'B';
  557.             bmpHeader.szID[1]     = 'M';
  558.             bmpHeader.nFileSize   = sizeof (BMPHEADER) + nPalSize + nImageSize;
  559.             bmpHeader.nHeaderSize = sizeof (BMPHEADER) + nPalSize;
  560.             bmpHeader.nInfoSize   = 0x28;
  561.             bmpHeader.nWidth      = anWidth[nIdx];
  562.             bmpHeader.nHeight     = anHeight[nIdx];
  563.             bmpHeader.nPlanes     = 1;
  564.             bmpHeader.nBits       = 8;
  565.             bmpHeader.nImageSize  = nImageSize;
  566.  
  567.             if (fwrite(&bmpHeader, sizeof (BMPHEADER), 1, pResFile) < 1)
  568.             {
  569.                 printf("I/O error.\n");
  570.                 farfree(lpPalLUT);
  571.                 fclose(pFile);
  572.                 fclose(pResFile);
  573.                 return FALSE;
  574.             }
  575.  
  576.             // write the palette for this image
  577.             for (nIdx2 = 0; nIdx2 < 256; nIdx2++)
  578.             {
  579.                 rgb.nRed    = pSysPal[nIdx2].nRed   << 2;
  580.                 rgb.nGreen  = pSysPal[nIdx2].nGreen << 2;
  581.                 rgb.nBlue   = pSysPal[nIdx2].nBlue  << 2;
  582.                 rgb.nFilter = 0;
  583.                 if (fwrite(&rgb, sizeof (RGBQUAD), 1, pResFile) < 1)
  584.                 {
  585.                     printf("I/O error.\n");
  586.                     farfree(lpPalLUT);
  587.                     fclose(pFile);
  588.                     fclose(pResFile);
  589.                     return FALSE;
  590.                 }
  591.             }
  592.  
  593.             // read in the image
  594.             if ((lpBitmap = farmalloc((long)anWidth[nIdx] * (long)anHeight[nIdx])) == NULL)
  595.             {
  596.                 printf("Out of memory.\n");
  597.                 farfree(lpPalLUT);
  598.                 fclose(pFile);
  599.                 fclose(pResFile);
  600.                 return FALSE;
  601.             }
  602.             lp = lpBitmap;
  603.             for (nIdx2 = 0; nIdx2 < anWidth[nIdx]; nIdx2++)
  604.             {
  605.                 if (fread(pTempBuff, anHeight[nIdx], 1, pFile) < 1)
  606.                 {
  607.                     printf("Out of memory.\n");
  608.                     farfree(lpPalLUT);
  609.                     farfree(lpBitmap);
  610.                     fclose(pFile);
  611.                     fclose(pResFile);
  612.                     return FALSE;
  613.                 }
  614.                 _fmemcpy(lp, pTempBuff, anHeight[nIdx]);
  615.  
  616.                 lp += (long)anHeight[nIdx];
  617.             }
  618.  
  619.             // write the image
  620.             for (nRow = anHeight[nIdx] - 1; nRow >= 0; nRow--)
  621.             {
  622.                 for (nCol = 0; nCol < anWidth[nIdx]; nCol++)
  623.                 {
  624.                     lp = lpBitmap + ((long)nRow + ((long)nCol * (long)anHeight[nIdx]));
  625.                     fputc(*lp, pResFile);
  626.                 }
  627.                 // put odd bytes on end (BMP rasters must be on a dword boundary
  628.                 for (; nCol < nRasterSize; nCol++)
  629.                     fputc(0, pResFile);
  630.             }
  631.  
  632.             // close up this bitmap
  633.             fclose(pResFile);
  634.             farfree(lpBitmap);
  635.         }
  636.         else if (anWidth[nIdx] || anHeight[nIdx] || anVal1[nIdx] || anVal2[nIdx])
  637.         {
  638.             // no bitmap, but we have important info...
  639.             fprintf(pOutFile, "%3d **************** %d %d %d %d\n", nIdx, anWidth[nIdx], anHeight[nIdx], anVal1[nIdx], anVal2[nIdx]);
  640.         }
  641.  
  642.         if (kbhit())
  643.         {
  644.             if (getch() == 27)
  645.             {
  646.                 pDoneMsg = szAbort;
  647.                 break;
  648.             }
  649.         }
  650.     }
  651.     printf(pDoneMsg);
  652.     fclose(pOutFile);
  653.  
  654.     // free palette
  655.     farfree(lpPalLUT);
  656.  
  657.     // and close the file...
  658.     fclose(pFile);
  659.  
  660.     return TRUE;
  661. }
  662.  
  663. int CompileArt(void)
  664. {
  665.     // compile the art file (szGrpPath) from directory (szDirPath)
  666.  
  667.     long            nRasterSize;            // size of raster
  668.     FILE*            pArtFile;                // the .art file
  669.     FILE*            pLstFile;                // the .lst file
  670.     FILE*            pBMPFile;                // the individual files
  671.     char            szLstName[MAXPATH];    // LST filename
  672.     char            szFilename[MAXPATH];    // filename work
  673.     char            szBMPName[MAXPATH];    // BMP filename
  674.     int            nIdx;                        // dir index
  675.     int            nNum;                        // current bitmap number
  676.     int            nWidth, nHeight;        // size of bitmap
  677.     int            nVal1, nVal2;            // the unknown values (they look like bit fields)
  678.     int            nRow, nCol;                // bitmap index
  679.     BMPHEADER    bmpHeader;                // header for bmp file
  680.     char huge*    lpBitmap;                // the bitmap image read in
  681.     char huge*    lp;                        // temp pointer
  682.     char            pBuff[81];                // for reading input from lst
  683.     char far*    p;
  684.     char*            pDoneMsg = szComplete;
  685.  
  686.     // open the LST file (in dir)
  687.     sprintf(szLstName, "%s\\%s.LST", szDirPath, szGrpName);
  688.     if ((pLstFile = fopen(szLstName, "r")) == NULL)
  689.     {
  690.         printf("Could not open %s file.\n", szLstName);
  691.         return FALSE;
  692.     }
  693.  
  694.     // read header for art file
  695.     fgets(pBuff, 80, pLstFile);
  696.     p = _fstrtok(pBuff, " ");
  697.     aArtHeader[0] = atol(p);
  698.     p = _fstrtok(NULL, " ");
  699.     aArtHeader[1] = atol(p);
  700.     p = _fstrtok(NULL, " ");
  701.     aArtHeader[2] = atol(p);
  702.     p = _fstrtok(NULL, " ");
  703.     aArtHeader[3] = atol(p);
  704.  
  705.     // get all the values
  706.     _fmemset(anWidth, 0, sizeof (short) * 256);
  707.     _fmemset(anHeight, 0, sizeof (short) * 256);
  708.     _fmemset(anVal1, 0, sizeof (short) * 256);
  709.     _fmemset(anVal2, 0, sizeof (short) * 256);
  710.     while (fgets(pBuff, 80, pLstFile) != NULL)
  711.     {
  712.         // get the values
  713.         p = _fstrtok(pBuff, " ");
  714.         nNum = atoi(p);
  715.         p = _fstrtok(NULL, " ");
  716.         strcpy(szBMPName, p);
  717.         p = _fstrtok(NULL, " ");
  718.       nWidth = atoi(p);
  719.         p = _fstrtok(NULL, " ");
  720.         nHeight = atoi(p);
  721.         p = _fstrtok(NULL, " ");
  722.         nVal1 = atoi(p);
  723.         p = _fstrtok(NULL, " ");
  724.         nVal2 = atoi(p);
  725.  
  726.         // set values for this bitmap
  727.         anWidth[nNum] = nWidth;
  728.         anHeight[nNum] = nHeight;
  729.         anVal1[nNum] = nVal1;
  730.         anVal2[nNum] = nVal2;
  731.     }
  732.     rewind(pLstFile);
  733.  
  734.     // remove old backup. rename art file to bak.
  735.     sprintf(szFilename, "%s%s%s.BAK",
  736.         szGrpDrive, szGrpDir, szGrpName);
  737.     remove(szFilename);
  738.     rename(szGrpPath, szFilename);
  739.  
  740.     // open the art file
  741.     pArtFile = fopen(szGrpPath, "wb");
  742.  
  743.     // write the header/bitmap infos
  744.     fwrite(aArtHeader, sizeof (long), 4, pArtFile);
  745.     fwrite(anWidth, sizeof (short), 256, pArtFile);
  746.     fwrite(anHeight, sizeof (short), 256, pArtFile);
  747.     fwrite(anVal1, sizeof (short), 256, pArtFile);
  748.     fwrite(anVal2, sizeof (short), 256, pArtFile);
  749.  
  750.     // go though the LST file again and this time move the bitmaps
  751.     fgets(pBuff, 80, pLstFile);
  752.     while (fgets(pBuff, 80, pLstFile) != NULL)
  753.     {
  754.         // get the values from the LST file
  755.         p = _fstrtok(pBuff, " ");
  756.         nNum = atoi(p);
  757.         p = _fstrtok(NULL, " ");
  758.         strcpy(szBMPName, p);
  759.         p = _fstrtok(NULL, " ");
  760.       nWidth = atoi(p);
  761.         p = _fstrtok(NULL, " ");
  762.         nHeight = atoi(p);
  763.         p = _fstrtok(NULL, " ");
  764.         nVal1 = atoi(p);
  765.         p = _fstrtok(NULL, " ");
  766.         nVal2 = atoi(p);
  767.         printf("%3d %s           \r", nNum, szBMPName);
  768.  
  769.         // if it's info w/no bitmap, skip it.
  770.         if (!strcmp(szBMPName, "****************"))
  771.             continue;
  772.  
  773.         // get the header from the bitmap
  774.         sprintf(szFilename, "%s\\%s", szDirPath, szBMPName);
  775.         pBMPFile = fopen(szFilename, "rb");
  776.         fread(&bmpHeader, sizeof (BMPHEADER), 1, pBMPFile);
  777.  
  778.         // skip over the palette. bitmaps must use duke3d palette. future version
  779.       // may best fit bitmaps to duke3d palette.
  780.         fseek(pBMPFile, bmpHeader.nHeaderSize, SEEK_SET);
  781.  
  782.         // check size of bitmap. this version of dh will only allow you to replace
  783.         // bitmaps with the same size as the original...
  784.         if ((bmpHeader.nWidth != nWidth) || (bmpHeader.nHeight != nHeight))
  785.         {
  786.             printf("Bitmap not the same size as it's original! (%s)\n", szBMPName);
  787.             return FALSE;
  788.         }
  789.         nRasterSize = nWidth;
  790.         if (nRasterSize & 0x00000003L)
  791.         {
  792.             nRasterSize |= 0x00000003L;
  793.             nRasterSize++;
  794.         }
  795.  
  796.         // read in the bitmap
  797.         if ((lpBitmap = farmalloc(bmpHeader.nImageSize)) == NULL)
  798.         {
  799.             printf("Out of memory.\n");
  800.             return FALSE;
  801.         }
  802.         _fmemset(lpBitmap, 0, (size_t)bmpHeader.nImageSize);
  803.  
  804.         // read in the bitmap (bmps are bottom up)
  805.         lp = lpBitmap + ((long)(nHeight - 1) * (long)nRasterSize);
  806.         for (nIdx = 0; nIdx < nHeight; nIdx++)
  807.         {
  808.             if (fread(pTempBuff, (int)nRasterSize, 1, pBMPFile) < 1)
  809.             {
  810.                 printf("I/O error.\n");
  811.                 return FALSE;
  812.             }
  813.             _fmemcpy(lp, pTempBuff, (size_t)nRasterSize);
  814.             lp -= (long)nRasterSize;
  815.         }
  816.         fclose(pBMPFile);
  817.  
  818.         // write the bitmap to the art file. stored column wise
  819.         for (nCol = 0; nCol < nWidth; nCol++)
  820.         {
  821.             for (nRow = 0; nRow < nHeight; nRow++)
  822.             {
  823.                 lp = lpBitmap + ((long)nCol + ((long)nRow * (long)nRasterSize));
  824.                 fputc(*lp, pArtFile);
  825.             }
  826.         }
  827.         farfree(lpBitmap);
  828.  
  829.         if (kbhit())
  830.         {
  831.             if (getch() == 27)
  832.             {
  833.                 pDoneMsg = szAbort;
  834.                 break;
  835.             }
  836.         }
  837.     }
  838.     printf(pDoneMsg);
  839.     fclose(pArtFile);
  840.     fclose(pLstFile);
  841.    return TRUE;
  842. }
  843.  
  844.  
  845. int CompileGrp(void)
  846. {
  847.     // Compile the grp file (szGrpPath) to directory (szDirPath)
  848.  
  849.     FILE*            pGrpFile;                // the .grp file
  850.     FILE*            pLstFile;                // the grp.lst file
  851.     FILE*            pResFile;                // the individual files
  852.     char            pStr[13];                // holds the ken tag
  853.     long            nDirSize;                // entries in directory
  854.     LPDIRATOM    lpDir;                    // pointer to the dir list
  855.     char            szLstName[MAXPATH];    // filename work
  856.     char            szResName[MAXPATH];    // filename work
  857.     char            szFilename[MAXPATH];    // filename work
  858.     int            nIdx;                        // dir index
  859.     long            nIdx2;                    // file byte index
  860.     int            c;                            // a byte read/written
  861.     char            pBuff[81];                // for reading input from lst
  862.     char far*    p;
  863.     char*            pDoneMsg = szComplete;
  864.  
  865.     // open the LST file (in dir)
  866.     sprintf(szLstName, "%s\\%s.LST", szDirPath, szGrpName);
  867.     if ((pLstFile = fopen(szLstName, "r")) == NULL)
  868.     {
  869.         printf("Could not open %s file.\n", szLstName);
  870.         return FALSE;
  871.     }
  872.  
  873.     // count entries
  874.     nDirSize = 0;
  875.     while (fgets(pBuff, 80, pLstFile) != NULL)
  876.         nDirSize++;
  877.     rewind(pLstFile);
  878.  
  879.     // allocate directory structure
  880.     if ((lpDir = farmalloc(16 * (size_t)nDirSize)) == NULL)
  881.     {
  882.         printf("Out of memory.\n");
  883.         fclose(pLstFile);
  884.         return FALSE;
  885.     }
  886.  
  887.     // read directory  in
  888.     for (nIdx = 0; nIdx < nDirSize; nIdx++)
  889.     {
  890.         // get the name of the file & size
  891.         fgets(pBuff, 80, pLstFile);
  892.         p = strtok(pBuff, " \n\r");
  893.         strupr(p);
  894.         _fmemset(&lpDir[nIdx], 0, sizeof (DIRATOM));
  895.         strcpy(lpDir[nIdx].szLabel, p);
  896.         sprintf(szResName, "%s\\%s", szDirPath, p);
  897.         if ((pResFile = fopen(szResName, "rb")) == NULL)
  898.         {
  899.             printf("Can not open %s.\n", szResName);
  900.             fclose(pLstFile);
  901.             farfree(lpDir);
  902.             return FALSE;
  903.         }
  904.         fseek(pResFile, 0L, SEEK_END);
  905.         lpDir[nIdx].nSize = ftell(pResFile);
  906.       fclose(pResFile);
  907.     }
  908.     fclose(pLstFile);
  909.  
  910.     // remove old backup. rename art file to bak.
  911.     sprintf(szFilename, "%s%s%s.BAK",
  912.         szGrpDrive, szGrpDir, szGrpName);
  913.     remove(szFilename);
  914.     rename(szGrpPath, szFilename);
  915.  
  916.     // open the grp file...
  917.     if ((pGrpFile = fopen(szGrpPath, "wb")) == NULL)
  918.     {
  919.         printf("Could not open %s.\n", szGrpPath);
  920.         farfree(lpDir);
  921.         return FALSE;
  922.     }
  923.  
  924.     // write the tag & directory
  925.     fwrite("KenSilverman", 12, 1, pGrpFile);
  926.     fwrite(&nDirSize, sizeof (long), 1, pGrpFile);
  927.     for (nIdx = 0; nIdx < (int)nDirSize; nIdx++)
  928.     {
  929.         fwrite(&lpDir[nIdx], sizeof (DIRATOM), 1, pGrpFile);
  930.     }
  931.  
  932.     // dump the individual files to the grp file
  933.     for (nIdx = 0; nIdx < nDirSize; nIdx++)
  934.     {
  935.         // get name of this resource
  936.         _fmemcpy(pStr, lpDir[nIdx].szLabel, 12);
  937.         pStr[12] = '\0';
  938.         printf("%s           \r", pStr);
  939.  
  940.         // open the resource file
  941.         sprintf(szResName, "%s\\%s", szDirPath, pStr);
  942.         if ((pResFile = fopen(szResName, "rb")) == NULL)
  943.         {
  944.             printf("Could not open %s.\n", pStr);
  945.             farfree(lpDir);
  946.             fclose(pGrpFile);
  947.             return FALSE;
  948.         }
  949.         for (nIdx2 = 0; nIdx2 < lpDir[nIdx].nSize; nIdx2++)
  950.         {
  951.             if ((c = fgetc(pResFile)) == EOF)
  952.             {
  953.                 printf("Unexpected EOF.\n");
  954.                 farfree(lpDir);
  955.                 fclose(pResFile);
  956.                 fclose(pGrpFile);
  957.                 return FALSE;
  958.             }
  959.             if (fputc(c, pGrpFile) == EOF)
  960.             {
  961.                 printf("Unable to write to %s.\n", szGrpPath);
  962.                 farfree(lpDir);
  963.                 fclose(pResFile);
  964.                 fclose(pGrpFile);
  965.                 return FALSE;
  966.             }
  967.         }
  968.         fclose(pResFile);
  969.         if (kbhit())
  970.         {
  971.             if (getch() == 27)
  972.             {
  973.                 pDoneMsg = szAbort;
  974.                 break;
  975.             }
  976.         }
  977.     }
  978.     printf(pDoneMsg);
  979.     fclose(pGrpFile);
  980.  
  981.     // free directory
  982.     farfree(lpDir);
  983.  
  984.     return TRUE;
  985. }
  986.  
  987.