PALTOOL.CPP 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <io.h>
  5. #include <fcntl.h>
  6. #include "screen.h"
  7. #include "palette.h"
  8. #include "debug4g.h"
  9. #include "textio.h"
  10. #include "inifile.h"
  11. #include "getopt.h"
  12. #include "misc.h"
  13. #define kMistLevels 32
  14. #define kMistValue 180
  15. RGB gamePalette[256];
  16. int rdist[256], gdist[256], bdist[256];
  17. int nPalLookups;
  18. int nWeightR, nWeightG, nWeightB;
  19. int nMaxDark;
  20. IniFile paltoolINI("PALTOOL.INI");
  21. /*******************************************************************************
  22. FUNCTION: ShowBanner()
  23. DESCRIPTION: Show application banner
  24. *******************************************************************************/
  25. void ShowBanner( void )
  26. {
  27. tioPrint("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
  28. tioPrint(" PalTool Version 1.0 Copyright (c) 1995 Q Studios Corporation");
  29. tioPrint("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");
  30. }
  31. /*******************************************************************************
  32. FUNCTION: ShowUsage()
  33. DESCRIPTION: Display command-line parameter usage, then exit
  34. *******************************************************************************/
  35. void ShowUsage(void)
  36. {
  37. tioPrint("Syntax: PALTOOL destfile command");
  38. tioPrint("-c filename create color LUT (CLU) using specified palette file");
  39. tioPrint("-f N[,O] create fog LUT (FLU) with gray level of N, opacity O");
  40. tioPrint("-s filename create shade LUT (PLU) using specified palette file");
  41. tioPrint("-p filename create palette (PAL) from specified lookup table (CLU/PLU)");
  42. tioPrint("-t N create translucency LUT (TLU) with opacity of N%");
  43. tioPrint("-? this help");
  44. exit(0);
  45. }
  46. /*******************************************************************************
  47. FUNCTION: QuitMessage()
  48. DESCRIPTION: Display a printf() style message, the exit with code 1
  49. *******************************************************************************/
  50. void QuitMessage(char * fmt, ...)
  51. {
  52. char msg[80];
  53. va_list argptr;
  54. va_start( argptr, fmt );
  55. vsprintf( msg, fmt, argptr );
  56. va_end(argptr);
  57. tioPrint(msg);
  58. exit(1);
  59. }
  60. /*******************************************************************************
  61. FUNCTION: FindClosestColor()
  62. DESCRIPTION: Finds the closest color in RGB using the weights in
  63. nWeightR, nWeightG, and nWeightB.
  64. RETURNS: Index of the closest color
  65. *******************************************************************************/
  66. BYTE FindClosestColor( int r, int g, int b )
  67. {
  68. int i;
  69. int dist, matchDist, match;
  70. matchDist = 0x7FFFFFFF;
  71. for ( i = 0; i < 256; i++ )
  72. {
  73. dist = 0;
  74. dist += gdist[qabs((int)gamePalette[i].g - g)];
  75. if ( dist >= matchDist )
  76. continue;
  77. dist += rdist[qabs((int)gamePalette[i].r - r)];
  78. if ( dist >= matchDist )
  79. continue;
  80. dist += bdist[qabs((int)gamePalette[i].b - b)];
  81. if ( dist >= matchDist )
  82. continue;
  83. matchDist = dist;
  84. match = i;
  85. if (dist == 0)
  86. break;
  87. }
  88. return (BYTE)match;
  89. }
  90. void BuildCLU( char *filename, RGB *palette)
  91. {
  92. int i;
  93. char cluName[_MAX_PATH];
  94. BYTE *table = (BYTE *)malloc(256);
  95. for ( i = 0; tioGauge(i, 256); i++ )
  96. table[i] = FindClosestColor(palette[i].r, palette[i].g, palette[i].b);
  97. strcpy(cluName, filename);
  98. ChangeExtension(cluName, ".CLU");
  99. FileSave(cluName, table, 256);
  100. free(table);
  101. }
  102. void BuildPLU( char *filename, RGB *palette, int grayLevel)
  103. {
  104. int i, j;
  105. int r, g, b;
  106. char pluName[_MAX_PATH];
  107. BYTE *table = (BYTE *)malloc(256 * nPalLookups);
  108. BYTE *p = table;
  109. for ( i = 0; tioGauge(i, nPalLookups); i++ )
  110. {
  111. for ( j = 0; j < 256; j++ )
  112. {
  113. int n = muldiv(i, nMaxDark, nPalLookups);
  114. r = dmulscale16r(0x10000 - n, palette[j].r, n, grayLevel);
  115. g = dmulscale16r(0x10000 - n, palette[j].g, n, grayLevel);
  116. b = dmulscale16r(0x10000 - n, palette[j].b, n, grayLevel);
  117. p[j] = FindClosestColor(r, g, b);
  118. }
  119. p += 256;
  120. }
  121. strcpy(pluName, filename);
  122. ChangeExtension(pluName, ".PLU");
  123. FileSave(pluName, table, 256 * nPalLookups);
  124. free(table);
  125. }
  126. void BuildFLU( char *filename, RGB *palette, int grayLevel, int nOpacity)
  127. {
  128. int i, j, k;
  129. int r, g, b;
  130. char fluName[_MAX_PATH];
  131. int nDepthLevels = 16;
  132. int nBrightLevels = 16;
  133. // convert to 16:16 fixed point fraction
  134. nOpacity = divscale16(nOpacity, 100);
  135. BYTE *table = (BYTE *)malloc(nDepthLevels * nBrightLevels * 256);
  136. BYTE *p = table;
  137. for ( i = 0; tioGauge(i, nDepthLevels); i++ )
  138. {
  139. int nDepth = muldiv(i, nOpacity, nDepthLevels);
  140. for ( j = 0; j < nBrightLevels; j++ )
  141. {
  142. int nShade = muldiv(j, 0x0F000, nBrightLevels);
  143. for ( k = 0; k < 256; k++ )
  144. {
  145. r = mulscale16r(0x10000 - nShade, palette[k].r);
  146. r = dmulscale16r(0x10000 - nDepth, r, nDepth, grayLevel);
  147. g = mulscale16r(0x10000 - nShade, palette[k].g);
  148. g = dmulscale16r(0x10000 - nDepth, g, nDepth, grayLevel);
  149. b = mulscale16r(0x10000 - nShade, palette[k].b);
  150. b = dmulscale16r(0x10000 - nDepth, b, nDepth, grayLevel);
  151. p[k] = FindClosestColor(r, g, b);
  152. }
  153. p += 256;
  154. }
  155. }
  156. strcpy(fluName, filename);
  157. ChangeExtension(fluName, ".FLU");
  158. FileSave(fluName, table, nDepthLevels * nBrightLevels * 256);
  159. free(table);
  160. }
  161. /*
  162. ** lucWeight range = 0 - 256
  163. */
  164. void BuildTLU( char *filename, RGB *palette, int nPercent)
  165. {
  166. char tluName[_MAX_PATH];
  167. int i, j;
  168. int r, g, b;
  169. int lucWeight = divscale16(nPercent, 100);
  170. BYTE *table = (BYTE *)malloc(65536);
  171. BYTE *p = table;
  172. for ( i = 0; tioGauge(i, 256); i++ )
  173. {
  174. for ( j = 0; j < 256; j++ )
  175. {
  176. r = dmulscale16r(0x10000 - lucWeight, palette[i].r, lucWeight, palette[j].r);
  177. g = dmulscale16r(0x10000 - lucWeight, palette[i].g, lucWeight, palette[j].g);
  178. b = dmulscale16r(0x10000 - lucWeight, palette[i].b, lucWeight, palette[j].b);
  179. p[j] = FindClosestColor(r, g, b);
  180. }
  181. p += 256;
  182. }
  183. strcpy(tluName, filename);
  184. ChangeExtension(tluName, ".TLU");
  185. FileSave(tluName, table, 65536);
  186. free(table);
  187. }
  188. void LUTtoPAL( BYTE *table, RGB *palette )
  189. {
  190. dassert(table != NULL);
  191. dassert(palette != NULL);
  192. for ( int i = 0; i < 256; i++ )
  193. {
  194. palette[i] = gamePalette[ table[i] ];
  195. }
  196. }
  197. /***********************************************************************
  198. * Process command line arguments
  199. **********************************************************************/
  200. void ParseOptions( void )
  201. {
  202. enum {
  203. kSwitchColor,
  204. kSwitchFog,
  205. kSwitchPal,
  206. kSwitchShade,
  207. kSwitchTrans,
  208. kSwitchHelp,
  209. };
  210. static SWITCH switches[] = {
  211. { "?", kSwitchHelp, FALSE },
  212. { "C", kSwitchColor, TRUE },
  213. { "F", kSwitchFog, TRUE },
  214. { "P", kSwitchPal, TRUE },
  215. { "S", kSwitchShade, TRUE },
  216. { "T", kSwitchTrans, TRUE },
  217. { NULL, 0, FALSE },
  218. };
  219. char destName[_MAX_PATH] = "";
  220. int r;
  221. while ( (r = GetOptions(switches)) != GO_EOF )
  222. {
  223. switch (r)
  224. {
  225. case GO_INVALID:
  226. QuitMessage("Invalid argument: %s", OptArgument);
  227. case GO_FULL:
  228. if (destName[0] != '\0')
  229. QuitMessage("Invalid argument: %s", OptArgument);
  230. strcpy(destName, OptArgument);
  231. break;
  232. case kSwitchColor:
  233. {
  234. char palName[_MAX_PATH];
  235. RGB palette[256];
  236. strcpy(palName, OptArgument);
  237. AddExtension(palName, "PAL");
  238. if ( !FileLoad(palName, palette, sizeof(palette)) )
  239. QuitMessage("Error loading %s", palName);
  240. tioPrint("Building color LUT from %s", palName);
  241. BuildCLU(destName, palette);
  242. break;
  243. }
  244. case kSwitchFog:
  245. {
  246. int nGrayLevel = 0, nOpacity = 100;
  247. sscanf(OptArgument, "%d,%d", &nGrayLevel, &nOpacity);
  248. tioPrint("Building fog LUT, gray level = %d, opacity = %d%%",
  249. nGrayLevel, nOpacity);
  250. BuildFLU(destName, gamePalette, nGrayLevel, nOpacity);
  251. break;
  252. }
  253. case kSwitchPal:
  254. {
  255. char zName[_MAX_PATH];
  256. char *ext;
  257. char buffer[_MAX_PATH2];
  258. RGB palette[256];
  259. strcpy( zName, OptArgument );
  260. _splitpath2(zName, buffer, NULL, NULL, NULL, &ext);
  261. if ( strcmpi(ext, ".CLU") == 0 || strcmpi(ext, ".PLU") == 0 )
  262. {
  263. BYTE *table = (BYTE *)malloc(256);
  264. if ( !FileLoad(zName, table, 256) )
  265. QuitMessage("Error loading %s", zName);
  266. LUTtoPAL(table, palette);
  267. ChangeExtension(zName, ".PAL");
  268. FileSave(zName, palette, sizeof(palette));
  269. free(table);
  270. }
  271. else
  272. QuitMessage(".PLU or .CLU extension required for parameter %s", zName);
  273. break;
  274. }
  275. case kSwitchShade:
  276. {
  277. char palName[_MAX_PATH];
  278. RGB palette[256];
  279. strcpy(palName, OptArgument);
  280. AddExtension(palName, "PAL");
  281. if ( !FileLoad(palName, palette, sizeof(palette)) )
  282. QuitMessage("Error loading %s", palName);
  283. tioPrint("Building shade LUT from %s", palName);
  284. BuildPLU(destName, palette, 0);
  285. break;
  286. }
  287. case kSwitchTrans:
  288. {
  289. int nPercent = strtol(OptArgument, NULL, 0);
  290. tioPrint("Building translucency LUT, opacity = %d%%", nPercent);
  291. BuildTLU(destName, gamePalette, nPercent);
  292. break;
  293. }
  294. case kSwitchHelp:
  295. ShowUsage();
  296. break;
  297. }
  298. }
  299. }
  300. void main( int argc )
  301. {
  302. char sGamePal[_MAX_PATH];
  303. tioInit(0);
  304. ShowBanner();
  305. nPalLookups = paltoolINI.GetKeyInt(NULL, "NumPalLookups", 32);
  306. nWeightR = paltoolINI.GetKeyInt(NULL, "WeightR", 1);
  307. nWeightG = paltoolINI.GetKeyInt(NULL, "WeightG", 1);
  308. nWeightB = paltoolINI.GetKeyInt(NULL, "WeightB", 1);
  309. strcpy(sGamePal, paltoolINI.GetKeyString(NULL, "GamePal", ""));
  310. nMaxDark = paltoolINI.GetKeyInt(NULL, "MaxDark", 0xE000);
  311. if ( !FileLoad(sGamePal, gamePalette, sizeof(gamePalette)) )
  312. QuitMessage("Error loading %s", sGamePal);
  313. if (argc == 1)
  314. ShowUsage();
  315. tioPrint("nPalLookups = %d, WeightR = %d, WeightG = %d, WeightB = %d",
  316. nPalLookups, nWeightR, nWeightG, nWeightB);
  317. tioPrint("Creating distance lookup table");
  318. for (int i = 0; tioGauge(i, 256); i++)
  319. {
  320. int square = i * i;
  321. rdist[i] = nWeightR * square;
  322. gdist[i] = nWeightG * square;
  323. bdist[i] = nWeightB * square;
  324. }
  325. ParseOptions();
  326. tioPrint("");
  327. tioTerm();
  328. }
  329. /*
  330. void InverseColor(int *r, int *g, int *b)
  331. {
  332. int gray = (*r * 2 + *g * 5 + *b) / 8;
  333. *r = 255 - gray;
  334. *g = 255 - gray;
  335. *b = 255 - gray;
  336. }
  337. void BeastColor(int *r, int *g, int *b)
  338. {
  339. *r = gammaTable[1][*r];
  340. *g = gammaTable[1][*g / 2];
  341. *b = gammaTable[1][*b / 2];
  342. }
  343. void ScopeColor(int *r, int *g, int *b)
  344. {
  345. int i;
  346. i = ClipLow(*r - *g / 4 - *b / 2, 0);
  347. *r = gammaTable[3][i / 2];
  348. *g = gammaTable[3][i];
  349. *b = gammaTable[3][i / 2];
  350. }
  351. void WaterColor(int *r, int *g, int *b)
  352. {
  353. *r = gammaTable[1][*r / 2];
  354. *g = gammaTable[1][*g / 2];
  355. *b = gammaTable[1][*b];
  356. }
  357. void GrayColor(int *r, int *g, int *b)
  358. {
  359. int gray = (*r * 2 + *g * 5 + *b) / 8;
  360. *r = gray;
  361. *g = gray;
  362. *b = gray;
  363. }
  364. void GrayishColor(int *r, int *g, int *b)
  365. {
  366. int gray = (*r * 2 + *g * 5 + *b) / 8;
  367. *r = (*r + gray) / 2;
  368. *g = (*g + gray) / 2;
  369. *b = (*b + gray) / 2;
  370. }
  371. */