123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624 |
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <dos.h>
- #include <io.h>
- #include <fcntl.h>
- #include <conio.h>
- #include <helix.h>
- #include "error.h"
- #include "getopt.h"
- #include "palette.h"
- #include "inifile.h"
- #include "pcx.h"
- #include "lbm.h"
- #include "misc.h"
- #include "gfx.h"
- #include "debug4g.h"
- #include "textio.h"
- #define kMaxTiles 4096
- short tilesizx[kMaxTiles];
- short tilesizy[kMaxTiles];
- long picanm[kMaxTiles];
- struct FNODE
- {
- FNODE *next;
- char name[1];
- };
- FNODE head = { &head, "" };
- FNODE *tail = &head;
- enum FILE_TYPE
- {
- FT_NONE,
- FT_PAL,
- FT_PCX,
- FT_LBM,
- FT_ART,
- };
- static struct
- {
- char *ext;
- FILE_TYPE fileType;
- } ftTable[] =
- {
- { ".ART", FT_ART },
- { ".LBM", FT_LBM },
- { ".PAL", FT_PAL },
- { ".PCX", FT_PCX },
- { ".PCC", FT_PCX },
- };
- int nWeightR, nWeightG, nWeightB;
- BOOL ExcludeColor[256];
- BYTE RemapColor[256];
- int URemapColor[256];
- PALETTE srcPal, destPal, thisPal;
- IniFile paltoolINI("PALTOOL.INI");
- char palName[_MAX_PATH];
- char bakname[_MAX_PATH], tempName[_MAX_PATH];
- BOOL showImages = FALSE;
- /*******************************************************************************
- FUNCTION: ShowBanner()
- DESCRIPTION: Show application banner
- *******************************************************************************/
- void ShowBanner( void )
- {
- tioPrint("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
- tioPrint(" Image Remap Tool Version 2.0 Copyright (c) 1995 Q Studios Corporation");
- tioPrint("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
- }
- /*******************************************************************************
- FUNCTION: ShowUsage()
- DESCRIPTION: Display command-line parameter usage, then exit
- *******************************************************************************/
- void ShowUsage(void)
- {
- tioPrint("Syntax: REMAP [options] files");
- tioPrint(" /Fxxx Load palette from file [.PAL]");
- tioPrint(" /Mx,y Map color x to color y");
- tioPrint(" /Oa[-b] Color(s) in dest palette is off limits");
- tioPrint("");
- tioPrint("Supported file types are: PCX, LBM, ART");
- tioPrint("");
- exit(0);
- }
- /*******************************************************************************
- FUNCTION: QuitMessage()
- DESCRIPTION: Display a printf() style message, the exit with code 1
- *******************************************************************************/
- void QuitMessage(char * fmt, ...)
- {
- char msg[80];
- va_list argptr;
- va_start( argptr, fmt );
- vsprintf( msg, fmt, argptr );
- va_end(argptr);
- tioPrint(msg);
- exit(1);
- }
- /*******************************************************************************
- FUNCTION: FindClosestColor()
- DESCRIPTION: Finds the closest color in RGB using the weights in
- nWeightR, nWeightG, and nWeightB.
- RETURNS: Index of the closest color
- NOTES: Colors marked with a TRUE in ExcludeColor[n] are not
- considered.
- *******************************************************************************/
- BYTE FindClosestColor( int r, int g, int b )
- {
- int i;
- int dr, dg, db, dist, matchDist, match;
- matchDist = 0x7FFFFFFF;
- for ( i = 0; i < 256; i++ )
- {
- if ( ExcludeColor[i] )
- continue;
- dist = 0;
- dg = (int)destPal[i].g - g;
- dist += nWeightG * dg * dg;
- if ( dist >= matchDist )
- continue;
- dr = (int)destPal[i].r - r;
- dist += nWeightR * dr * dr;
- if ( dist >= matchDist )
- continue;
- db = (int)destPal[i].b - b;
- dist += nWeightB * db * db;
- if ( dist >= matchDist )
- continue;
- matchDist = dist;
- match = i;
- if (dist == 0)
- break;
- }
- return (BYTE)match;
- }
- /*******************************************************************************
- FUNCTION: BuildRemapTable()
- DESCRIPTION: Create the lookup table to remap from srcPal to destPal
- *******************************************************************************/
- void BuildRemapTable(void)
- {
- for (int i = 0; i < 256; i++)
- {
- if ( URemapColor[i] < 0 )
- RemapColor[i] = FindClosestColor(srcPal[i].r, srcPal[i].g, srcPal[i].b);
- else
- RemapColor[i] = (BYTE)URemapColor[i];
- }
- }
- void RemapBuffer( BYTE *buffer, int length, BYTE *remapTable );
- #pragma aux RemapBuffer =\
- " xor eax,eax",\
- "loop1:",\
- " mov al,[edx]",\
- " mov al,[ebx+eax]",\
- " mov [edx],al",\
- " inc edx",\
- " dec ecx",\
- " jnz loop1",\
- parm [edx][ecx][ebx]\
- modify [eax edx]\
- FILE_TYPE GetFileType( char *filename )
- {
- char ext[_MAX_EXT];
- _splitpath(filename, NULL, NULL, NULL, ext);
- for ( int i = 0; i < LENGTH(ftTable); i++ )
- {
- if ( stricmp(ext, ftTable[i].ext) == 0 )
- return ftTable[i].fileType;
- }
- return FT_NONE;
- }
- void GetNewPalette(void)
- {
- int width = 0, height = 0; // not really used, but necessary for ReadXXX call
- switch( GetFileType(palName) )
- {
- case FT_PAL:
- if ( !FileLoad(palName, destPal, sizeof(destPal)) )
- QuitMessage("Couldn't open palette file '%s'", palName);
- break;
- case FT_PCX:
- {
- int r = ReadPCX(palName, destPal, &width, &height, NULL);
- if ( r != PCX_OKAY )
- QuitMessage("Error reading palette from %s: code = %d", palName, r);
- break;
- }
- case FT_LBM:
- {
- int r = ReadLBM(palName, destPal, &width, &height, NULL);
- if ( r != LBM_OKAY )
- QuitMessage("Error reading palette from %s: code = %d", palName, r);
- break;
- }
- }
- }
- void DisplayImage( BYTE *bits, int width, int height )
- {
- int size = width * height;
- QBITMAP *qbmSource = (QBITMAP *)malloc(sizeof(QBITMAP) + size);
- dassert(qbmSource != NULL);
- memcpy(qbmSource->data, bits, size);
- qbmSource->bitModel = BM_RAW;
- qbmSource->tcolor = 0;
- qbmSource->cols = (short)width;
- qbmSource->rows = (short)height;
- qbmSource->stride = (short)width;
- gfxDrawBitmap(qbmSource, 160 - width / 2, 100 - height / 2);
- free(qbmSource);
- }
- void RemapART( char *filename )
- {
- int hInFile, hOutFile;
- int tileStart, tileEnd;
- long artversion, numtiles;
- char artPalName[_MAX_PATH];
- strcpy(artPalName, paltoolINI.GetKeyString(NULL, "GamePal", ""));
- if ( !FileLoad(artPalName, thisPal, sizeof(thisPal)) )
- QuitMessage("Couldn't open palette file '%s'", artPalName);
- if ( memcmp(srcPal, thisPal, sizeof(PALETTE)) != 0 )
- {
- memcpy(srcPal, thisPal, sizeof(PALETTE));
- BuildRemapTable();
- }
- hInFile = open(filename, O_BINARY | O_RDWR);
- if (hInFile == -1)
- QuitMessage("Error opening %s", filename);
- tmpnam(tempName);
- hOutFile = open(tempName, O_CREAT | O_WRONLY | O_BINARY | O_TRUNC, S_IWUSR);
- if ( hOutFile == -1 )
- QuitMessage("Error creating temporary file");
- read(hInFile, &artversion, sizeof(artversion));
- read(hInFile, &numtiles, sizeof(numtiles));
- read(hInFile, &tileStart, sizeof(tileStart));
- read(hInFile, &tileEnd, sizeof(tileEnd));
- int nTiles = tileEnd - tileStart + 1;
- read(hInFile, &tilesizx[tileStart], nTiles * sizeof(tilesizx[0]));
- read(hInFile, &tilesizy[tileStart], nTiles * sizeof(tilesizy[0]));
- read(hInFile, &picanm[tileStart], nTiles * sizeof(picanm[0]));
- write(hOutFile, &artversion, sizeof(artversion));
- write(hOutFile, &numtiles, sizeof(numtiles));
- write(hOutFile, &tileStart, sizeof(tileStart));
- write(hOutFile, &tileEnd, sizeof(tileEnd));
- write(hOutFile, &tilesizx[tileStart], nTiles * sizeof(tilesizx[0]));
- write(hOutFile, &tilesizy[tileStart], nTiles * sizeof(tilesizy[0]));
- write(hOutFile, &picanm[tileStart], nTiles * sizeof(picanm[0]));
- for (int i = tileStart; tioGauge(i - tileStart, nTiles); i++)
- {
- int nSize = tilesizx[i] * tilesizy[i];
- if (nSize == 0)
- continue;
- BYTE *pBits = (BYTE *)malloc(nSize);
- dassert(pBits != NULL);
- read(hInFile, pBits, nSize);
- RemapBuffer(pBits, nSize, RemapColor);
- write(hOutFile, pBits, nSize);
- if ( showImages )
- DisplayImage(pBits, tilesizy[i], tilesizx[i]);
- free(pBits);
- }
- close(hInFile);
- close(hOutFile);
- // backup the existing sequence
- strcpy(bakname, filename);
- ChangeExtension(bakname, ".BAK");
- unlink(bakname);
- rename(filename, bakname);
- rename(tempName, filename);
- }
- void RemapPCX( char *filename )
- {
- int srcWidth = 0, srcHeight = 0;
- int nResult;
- nResult = ReadPCX(filename, NULL, &srcWidth, &srcHeight, NULL);
- if (nResult != 0)
- QuitMessage("Problem reading PCX file %s: error=%d", filename, nResult);
- BYTE *pBits = NULL;
- nResult = ReadPCX(filename, thisPal, &srcWidth, &srcHeight, &pBits);
- if (nResult != 0)
- QuitMessage("Problem reading PCX file %s: error=%d", filename, nResult);
- if ( memcmp(srcPal, thisPal, sizeof(PALETTE)) != 0 )
- {
- memcpy(srcPal, thisPal, sizeof(PALETTE));
- BuildRemapTable();
- }
- RemapBuffer(pBits, srcWidth * srcHeight, RemapColor);
- if ( showImages )
- DisplayImage(pBits, srcWidth, srcHeight);
- tmpnam(tempName);
- nResult = WritePCX(tempName, destPal, srcWidth, srcHeight, pBits);
- if (nResult != 0)
- QuitMessage("Problem writing temporary PCX: error=%d", nResult);
- // backup the existing sequence
- strcpy(bakname, filename);
- ChangeExtension(bakname, ".BAK");
- unlink(bakname);
- rename(filename, bakname);
- rename(tempName, filename);
- free(pBits);
- }
- void RemapLBM( char *filename )
- {
- int srcWidth = 0, srcHeight = 0;
- int nResult;
- nResult = ReadLBM(filename, NULL, &srcWidth, &srcHeight, NULL);
- if (nResult != 0)
- QuitMessage("Problem reading LBM file %s: error=%d", filename, nResult);
- BYTE *pBits = NULL;
- nResult = ReadLBM(filename, thisPal, &srcWidth, &srcHeight, &pBits);
- if (nResult != 0)
- QuitMessage("Problem reading LBM file %s: error=%d", filename, nResult);
- if ( memcmp(srcPal, thisPal, sizeof(PALETTE)) != 0 )
- {
- memcpy(srcPal, thisPal, sizeof(PALETTE));
- BuildRemapTable();
- }
- RemapBuffer(pBits, srcWidth * srcHeight, RemapColor);
- if ( showImages )
- DisplayImage(pBits, srcWidth, srcHeight);
- free(pBits);
- }
- void ProcessFile( char *filename )
- {
- tioPrint("Processing %s", filename);
- FILE_TYPE fileType = GetFileType(filename);
- if ( fileType == FT_NONE )
- QuitMessage("Don't know how to handle file %s", filename);
- // determine the size of the source image
- switch ( fileType )
- {
- case FT_ART:
- RemapART(filename);
- break;
- case FT_LBM:
- RemapLBM(filename);
- break;
- case FT_PCX:
- RemapPCX(filename);
- break;
- }
- }
- void Initialize(void)
- {
- for (int i = 0; i < 256; i++)
- {
- ExcludeColor[i] = FALSE;
- URemapColor[i] = -1;
- }
- }
- void InsertFilename( char *filename )
- {
- FNODE *n = (FNODE *)malloc(sizeof(FNODE) + strlen(filename));
- strcpy(n->name, filename);
- // insert the node at the tail, so it stays in order
- n->next = tail->next;
- tail->next = n;
- tail = n;
- }
- void ProcessArgument(char *s)
- {
- char filespec[_MAX_PATH];
- char buffer[_MAX_PATH2];
- char path[_MAX_PATH];
- strcpy(filespec, s);
- char *drive, *dir;
- // separate the path from the filespec
- _splitpath2(s, buffer, &drive, &dir, NULL, NULL);
- _makepath(path, drive, dir, NULL, NULL);
- struct find_t fileinfo;
- unsigned r = _dos_findfirst(s, _A_NORMAL, &fileinfo);
- if (r != 0)
- tioPrint("%s not found", s);
- while ( r == 0 )
- {
- strcpy(filespec, path);
- strcat(filespec, fileinfo.name);
- InsertFilename(filespec);
- r = _dos_findnext( &fileinfo );
- }
- _dos_findclose(&fileinfo);
- }
- /***********************************************************************
- * Process command line arguments
- **********************************************************************/
- void ParseOptions( void )
- {
- enum {
- kSwitchHelp,
- kSwitchFile,
- kSwitchMap,
- kSwitchOmit,
- };
- static SWITCH switches[] = {
- { "?", kSwitchHelp, FALSE },
- { "F", kSwitchFile, TRUE },
- { "M", kSwitchMap, TRUE },
- { "O", kSwitchOmit, TRUE },
- { NULL, 0, FALSE },
- };
- char buffer[256];
- int r;
- while ( (r = GetOptions(switches)) != GO_EOF )
- {
- switch (r)
- {
- case GO_INVALID:
- sprintf(buffer, "Invalid argument: %s", OptArgument);
- ThrowError(buffer, ES_ERROR);
- break;
- case GO_FULL:
- ProcessArgument(OptArgument);
- break;
- case kSwitchHelp:
- ShowUsage();
- break;
- case kSwitchFile:
- strcpy(palName, OptArgument);
- AddExtension(palName, ".PAL");
- break;
- case kSwitchMap:
- {
- int nFrom, nTo;
- if ( sscanf(OptArgument, "%i,%i", &nFrom, &nTo) != 2 )
- QuitMessage("Syntax error: %s", OptArgument);
- URemapColor[nFrom] = nTo;
- break;
- }
- case kSwitchOmit:
- {
- int nFrom, nTo;
- switch ( sscanf(OptArgument, "%i-%i", &nFrom, &nTo) )
- {
- case 1:
- ExcludeColor[nFrom] = TRUE;
- break;
- case 2:
- while (nFrom <= nTo)
- ExcludeColor[nFrom++] = TRUE;
- break;
- default:
- QuitMessage("Syntax error: %s", OptArgument);
- }
- break;
- }
- }
- }
- }
- void main( int argc /*, char *argv[]*/)
- {
- tioInit(0);
- ShowBanner();
- if (argc < 2)
- ShowUsage();
- nWeightR = paltoolINI.GetKeyInt(NULL, "WeightR", 1);
- nWeightG = paltoolINI.GetKeyInt(NULL, "WeightG", 1);
- nWeightB = paltoolINI.GetKeyInt(NULL, "WeightB", 1);
- Initialize();
- ParseOptions();
- if ( head.next == &head )
- QuitMessage("No source file specified");
- if ( palName[0] == '\0' )
- QuitMessage("You must specify a new palette.");
- GetNewPalette();
- int oldMode = gGetMode();
- if (!gFindMode(320, 200, 256, CHAIN256))
- QuitMessage("Helix driver not found");
- if ( showImages )
- {
- Video.SetMode();
- gfxSetClip(0, 0, 320, 200);
- gSetDACRange(0, 256, destPal);
- }
- // process the file list
- for (FNODE *n = head.next; n != &head; n = n->next)
- ProcessFile(n->name);
- if ( showImages )
- gSetMode(oldMode);
- }
|