Skip to content

Instantly share code, notes, and snippets.

@Xymph
Last active February 26, 2022 16:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xymph/ffa52a765f738848b46d10db718b5726 to your computer and use it in GitHub Desktop.
Save Xymph/ffa52a765f738848b46d10db718b5726 to your computer and use it in GitHub Desktop.
Process a PLAYPAL lump (https://doomwiki.org/wiki/PLAYPAL) extracted from a Doom-engine WAD and count the number of unique colors, optionally skipping unused palettes and truncating 8-bits colors to 6-bits - see https://www.doomworld.com/vb/post/1839737 for example results
#!/usr/bin/php -q
<?php
// count total number of unique colors used in palettes of Doom-engine games,
// optionally skipping unused palettes and truncating 8-bits colors to 6-bits
// by Frans P. de Vries (Xymph)
define('PALSIZE', 3 * 256);
define('USAGE', "usage: {$argv[0]} [-u] [-t] -d|-h|-x|-s PLAYPAL-file\n");
// check options & file parameter
$game = ''; // 'd' = doom, 'h' = heretic, 'x' = hexen, 's' = strife
$unused = $truncate = false;
while (isset($argv[1]) && $argv[1][0] == '-') {
switch (substr($argv[1], 1)) {
case 'd':
case 'h':
case 'x':
case 's':
$game = substr($argv[1], 1);
break;
case 't':
$truncate = true;
break;
case 'u':
$unused = true;
break;
default:
echo USAGE;
exit(1);
}
unset($argv[1]);
$argc--;
$argv = array_merge($argv);
}
if ($game != '' && isset($argv[1]) && $argv[1] != '') {
$pname = $argv[1];
} else {
echo USAGE;
exit(1);
}
// check palette file
$PALSETS = ($game == 'x' ? 28 : 14);
if (!file_exists($pname)) {
echo "$pname: No such PLAYPAL file\n";
exit(1);
}
if (filesize($pname) != $PALSETS * PALSIZE) {
echo "$pname: Invalid PLAYPAL size for this game\n";
exit(1);
}
// process palette file
if (($fp = @fopen($pname, 'rb')) === FALSE) {
echo "$pname: Unable to open palette file\n";
exit(1);
}
$palused = 0;
// read all palettes and tally unique colors
$colors = array();
for ($palno = 0; $palno < $PALSETS; $palno++) {
if (($palette = fread($fp, PALSIZE)) === FALSE) {
echo "$pname: Unable to read palette file\n";
exit(1);
}
// skip unused palettes?
if ($unused &&
(($game != 'x' && ($palno == 1 || $palno == 9)) ||
($game == 'h' && $palno == 13)))
continue;
$palused++;
// tally unique colors
for ($i = 0; $i < PALSIZE; $i += 3)
// truncate to 6-bit colors?
if ($truncate)
$colors[ sprintf('%02X%02X%02X',
ord($palette[$i]) & 0xFC,
ord($palette[$i+1]) & 0xFC,
ord($palette[$i+2]) & 0xFC) ] = true;
else
$colors[ sprintf('%02X%02X%02X',
ord($palette[$i]),
ord($palette[$i+1]),
ord($palette[$i+2])) ] = true;
}
fclose($fp);
// report results
switch ($game) {
case 'd':
echo "Doom";
break;
case 'h':
echo "Heretic";
break;
case 'x':
echo "Hexen";
break;
case 's':
echo "Strife";
break;
}
echo " uses $palused palettes with " . count($colors) . " unique colors\n";
// vim: set noexpandtab tabstop=2 softtabstop=2 shiftwidth=2:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment