From 2001fe34ba72c385b974b4a2a1400e6513b56c07 Mon Sep 17 00:00:00 2001 From: avolkov Date: Thu, 22 Dec 2005 01:05:51 +0000 Subject: [PATCH] DOS SC2 colortab converter (to UQM) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2098 8092fc87-c524-0410-9efc-e669fe64eaf9 --- tools/dos-pal/Makefile | 32 +++ tools/dos-pal/config.h | 15 ++ tools/dos-pal/dos-pal.dsw | 29 +++ tools/dos-pal/main.pal | Bin 0 -> 770 bytes tools/dos-pal/pal2uqm.c | 417 ++++++++++++++++++++++++++++++++++++++ tools/dos-pal/pal2uqm.dsp | 106 ++++++++++ 6 files changed, 599 insertions(+) create mode 100755 tools/dos-pal/Makefile create mode 100755 tools/dos-pal/config.h create mode 100755 tools/dos-pal/dos-pal.dsw create mode 100755 tools/dos-pal/main.pal create mode 100755 tools/dos-pal/pal2uqm.c create mode 100755 tools/dos-pal/pal2uqm.dsp diff --git a/tools/dos-pal/Makefile b/tools/dos-pal/Makefile new file mode 100755 index 000000000..45f4651d2 --- /dev/null +++ b/tools/dos-pal/Makefile @@ -0,0 +1,32 @@ +######################################################################## +# This is a GNU makefile - tested on CYGWIN and Linux +# +# You may need to compile or install libpng and/or zlib before +# compiling this. +# + +TARGET = pal2uqm +# These flags are needed to get it to compile with libpngX.dll on CYGWIN +#CYGWINFLAGS = + +CC = gcc +CFLAGS = -W -Wall -O0 # -g +LIBS = -L/usr/local/lib -lm +LDFLAGS= + +BINS = $(TARGET) $(TARGET).exe +SRCS = pal2uqm.c +OBJS = pal2uqm.o + +.SUFFIXES: .c .o + +.c.o: + $(CC) -c $(CFLAGS) -o $@ $*.c $(CYGWINFLAGS) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -o $(TARGET) $(OBJS) $(LIBS) $(LDFLAGS) + +clean: + rm -f $(BINS) *.o diff --git a/tools/dos-pal/config.h b/tools/dos-pal/config.h new file mode 100755 index 000000000..0a70fe8f0 --- /dev/null +++ b/tools/dos-pal/config.h @@ -0,0 +1,15 @@ +/* Dummy compile-time configuration options + * Only used when compiling in MS VC++ using UQM's getopt.c + */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +/* Define if words are stored with the most significant byte first */ +#undef WORDS_BIGENDIAN + +/* Defined if your system has getopt.h */ +#undef HAVE_GETOPT_H + +#endif /* _CONFIG_H */ + diff --git a/tools/dos-pal/dos-pal.dsw b/tools/dos-pal/dos-pal.dsw new file mode 100755 index 000000000..9f95b4cd3 --- /dev/null +++ b/tools/dos-pal/dos-pal.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pal2uqm"=.\pal2uqm.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/tools/dos-pal/main.pal b/tools/dos-pal/main.pal new file mode 100755 index 0000000000000000000000000000000000000000..0a34bd15ee35d8b9dc3ada4185fd45ea11770495 GIT binary patch literal 770 zcmdUt(R!Ld5QWdeLL`WyLRAz|8W1pO6s1;8&-*`BJD7_+LudD!nZ4MZvok;bqO(dC zs;YAm!Y&OvqpXnZ+%rgezu&Ld>*aDe9*_I|ez)5dMUiD$nx;vT#Bm%&(R4Zuf?zZn z4Tr;izwbDXZQELFHVun{s}&~`Iu3yr*aJBb10mo6pD{lNB-o;@QD?}OSOy5{kfp~A zT%nnvnjjru?qJmZ;;~_UV7X(q<@zU=31&s+&bT{vMxiw~~3Rh}0#~_63qt~xkh72IOe*+Cr16x3zSv=MIz$^an zP1Lss)G6{Ak|AcIQiE6U11!N5T%dc#18qo4|7(-6_If?f^JLsY%zQo<1~!{bp65c5 z*y(f +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(WIN32) && defined(_MSC_VER) +# include +# include +# define makedir(d) _mkdir(d) +# define inline __inline +#else +# include +# define makedir(d) mkdir(d, 0777) +#endif +#if defined(__GNUC__) +# include +# define inline __inline__ +#endif + +#define countof(a) ( sizeof(a)/sizeof(*a) ) +#ifndef offsetof +# define offsetof(s,m) ( (size_t)(&((s*)0)->m) ) +#endif + +#if defined(_MSC_VER) +# define PACKED +# pragma pack(push, 1) +#elif defined(__GNUC__) +# define PACKED __attribute__((packed)) +#endif + +// File structure types +typedef struct +{ + int32_t PACKED compsize; // size after decompression, or -1 if already + uint16_t PACKED recs; // Number of records + uint16_t PACKED cbextra; // Size of extra data after rec sizes +} dos_header_t; + +typedef uint16_t dos_recsize_t; + +typedef struct +{ + int32_t PACKED compsize; // size after decompression, or -1 if already + uint32_t PACKED recs; // Number of records + uint32_t PACKED cbextra; // Size of extra data after rec sizes +} uqm_header_t; + +typedef uint32_t uqm_recsize_t; + +// Palette types +typedef uint8_t channel_t; + +typedef struct +{ + channel_t r, g, b; +} color_t; + +typedef struct +{ + uint8_t first; + uint8_t last; + union + { + color_t colors[1]; + channel_t chans[3]; + } pal; +} colormap_t; + +#define DOS_SIG_BITS 6 + +#define MAP_COLORS 0x100 + +typedef union +{ + color_t colors[MAP_COLORS]; + channel_t chans[MAP_COLORS * 3]; +} uqm_palette_t; + +typedef struct +{ + uint8_t first; + uint8_t last; + uqm_palette_t pal; +} uqm_colormap_t; + +#if defined(_MSC_VER) +# pragma pack(pop) +#endif + +struct options +{ + char *infile; + char *outfile; + int verbose; + int plut; + int num_palettefiles; + char **palettefiles; +}; + + +int verbose_level = 0; +void verbose(int level, const char* fmt, ...); +void parse_arguments(int argc, char* argv[], struct options* opts); +int loadPalette(uqm_palette_t* pal, const char* filename); +void setPalette(uqm_palette_t* pal, colormap_t* map); +dos_recsize_t* processHeader(dos_header_t* h); +int writeColortab(dos_header_t* h, const char* filename); + +inline channel_t conv_chan(uint8_t c); + +inline uint16_t get_16_be(uint16_t* val); +inline uint32_t get_32_be(uint32_t* val); +inline void put_16_be(uint16_t* into, uint16_t val); +inline void put_32_be(uint32_t* into, uint32_t val); + +uqm_colormap_t basemap; +int num_maps = 0; + + +int main(int argc, char* argv[]) +{ + struct options opts; + FILE* in; + size_t inlen; + uint8_t* buf; + dos_header_t* h; + dos_recsize_t* sizes; + int ret; + + parse_arguments(argc, argv, &opts); + verbose_level = opts.verbose; + + in = fopen(opts.infile, "rb"); + if (!in) + { + verbose(1, "Error: Could not open file %s: %s\n", + opts.infile, strerror(errno)); + return EXIT_FAILURE; + } + + fseek(in, 0, SEEK_END); + inlen = ftell(in); + fseek(in, 0, SEEK_SET); + + buf = malloc(inlen); + if (!buf) + { + verbose(1, "Out of memory reading file\n"); + return EXIT_FAILURE; + } + if (inlen != fread(buf, 1, inlen, in)) + { + verbose(1, "Cannot read file '%s'\n", opts.infile); + return EXIT_FAILURE; + } + fclose(in); + + h = (dos_header_t*)buf; + sizes = processHeader(h); + + { + int i; + + memset(&basemap, 0, sizeof(basemap)); + for (i = 0; i < opts.num_palettefiles; i++) + loadPalette(&basemap.pal, opts.palettefiles[i]); + } + basemap.first = opts.plut; + basemap.last = opts.plut; + + ret = writeColortab(h, opts.outfile); + + free(buf); + + return ret; +} + +void verbose(int level, const char* fmt, ...) +{ + va_list args; + + if (verbose_level < level) + return; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + +void usage() +{ + fprintf(stderr, + "pal2uqm [-m ] [-c ] [-o ] \n" + "Options:\n" + "\t-c load base palette in dos format (multiple -c allowed)\n" + "\t-o output .ct filename\n" + "\t-v increase verbosity level (use more than once)\n" + ); +} + +void parse_arguments(int argc, char* argv[], struct options* opts) +{ + char ch; + + memset(opts, 0, sizeof (struct options)); + + while (-1 != (ch = getopt(argc, argv, "h?c:o:m:v"))) + { + switch (ch) + { + case 'c': + opts->palettefiles = realloc(opts->palettefiles, + (opts->num_palettefiles + 1) * sizeof (char *)); + opts->palettefiles[opts->num_palettefiles] = optarg; + opts->num_palettefiles++; + break; + case 'o': + opts->outfile = optarg; + break; + case 'm': + opts->plut = atoi(optarg); + break; + case 'v': + opts->verbose++; + break; + case '?': + case 'h': + default: + usage(); + exit(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + if (argc != 1) + { + usage(); + exit(EXIT_FAILURE); + } + opts->infile = argv[0]; + if (!opts->outfile) + opts->outfile = opts->infile; +} + +dos_recsize_t* processHeader(dos_header_t* h) +{ + dos_recsize_t* sizes; + unsigned i; + + h->compsize = get_32_be(&h->compsize); + h->recs = get_16_be(&h->recs); + h->cbextra = get_16_be(&h->cbextra); + + sizes = (dos_recsize_t*)((uint8_t*)h + sizeof(*h)); + + for (i = 0; i < h->recs; ++i) + sizes[i] = get_16_be(sizes + i); + + return sizes; +} + +int loadPalette(uqm_palette_t* pal, const char* filename) +{ + FILE* in; + size_t inlen; + uint8_t *buf; + + in = fopen(filename, "rb"); + if (!in) + { + verbose(1, "Error: Could not open file %s: %s\n", filename, + strerror(errno)); + return EXIT_FAILURE; + } + + fseek(in, 0, SEEK_END); + inlen = ftell(in); + fseek(in, 0, SEEK_SET); + + buf = malloc(inlen); + if (!buf) + { + verbose(1, "Out of memory reading file\n"); + fclose(in); + return EXIT_FAILURE; + } + if (inlen != fread(buf, 1, inlen, in)) + { + verbose(1, "Cannot read file '%s'\n", filename); + fclose(in); + return EXIT_FAILURE; + } + fclose(in); + + verbose(2, "%s contains %d palette entries\n", + filename, (int)buf[1] - buf[0] + 1); + + setPalette(pal, (colormap_t*)buf); + + free(buf); + + return 0; +} + +void setPalette(uqm_palette_t* pal, colormap_t* map) +{ + int i; + color_t* sclr; + color_t* dclr; + + for (i = map->first, sclr = map->pal.colors, dclr = pal->colors + map->first; + i <= (int)map->last; + ++i, ++sclr, ++dclr) + { + dclr->r = conv_chan(sclr->r); + dclr->g = conv_chan(sclr->g); + dclr->b = conv_chan(sclr->b); + } +} + +int writeColortab(dos_header_t* h, const char* filename) +{ + FILE* f; + uqm_header_t uqmh; + dos_recsize_t* sizes; + uqm_recsize_t uqmsize; + colormap_t* map; + uqm_colormap_t uqmmap; + int i; + + put_32_be(&uqmh.compsize, -1); + put_32_be(&uqmh.recs, h->recs); + put_32_be(&uqmh.cbextra, 0); + // colortab sizes are fixed in uqm + put_32_be(&uqmsize, sizeof(uqmmap)); + + sizes = (dos_recsize_t*)((uint8_t*)h + sizeof(*h)); + + f = fopen(filename, "wb"); + if (!f) + { + verbose(1, "Error: Could not open file %s: %s\n", filename, + strerror(errno)); + return EXIT_FAILURE; + } + if (1 != fwrite(&uqmh, sizeof(uqmh), 1, f)) + { + verbose(1, "Cannot write file '%s'\n", filename); + fclose(f); + return EXIT_FAILURE; + } + for (i = 0; i < h->recs; ++i) + fwrite(&uqmsize, sizeof(uqmsize), 1, f); + + map = (colormap_t*)(sizes + h->recs); + for (i = 0; i < h->recs; ++i) + { + memcpy(&uqmmap, &basemap, sizeof(basemap)); + setPalette(&uqmmap.pal, map); + + if (1 != fwrite(&uqmmap, sizeof(uqmmap), 1, f)) + { + verbose(1, "Cannot write file '%s'\n", filename); + fclose(f); + return EXIT_FAILURE; + } + + map = (colormap_t*)((uint8_t*)map + sizes[i]); + } + + fclose(f); + + return EXIT_SUCCESS; +} + +inline channel_t conv_chan(uint8_t c) +{ // this uniformly distributes the lower 'unknown' bits + return (c << (8 - DOS_SIG_BITS)) | (c >> (DOS_SIG_BITS - (8 - DOS_SIG_BITS))); +} + +inline uint16_t get_16_be(uint16_t* val) +{ + return (uint16_t)(((uint8_t*)val)[0] << 8) | ((uint8_t*)val)[1]; +} + +inline uint32_t get_32_be(uint32_t* val) +{ + return (uint32_t)(get_16_be((uint16_t*)val) << 16) | get_16_be((uint16_t*)val + 1); +} + +inline void put_16_be(uint16_t* into, uint16_t val) +{ + ((uint8_t*)into)[0] = val >> 8; + ((uint8_t*)into)[1] = val & 0xff; +} + +inline void put_32_be(uint32_t* into, uint32_t val) +{ + put_16_be(((uint16_t*)into) + 0, val >> 16); + put_16_be(((uint16_t*)into) + 1, val & 0xffff); +} diff --git a/tools/dos-pal/pal2uqm.dsp b/tools/dos-pal/pal2uqm.dsp new file mode 100755 index 000000000..eb84fc53d --- /dev/null +++ b/tools/dos-pal/pal2uqm.dsp @@ -0,0 +1,106 @@ +# Microsoft Developer Studio Project File - Name="pal2uqm" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=pal2uqm - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pal2uqm.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pal2uqm.mak" CFG="pal2uqm - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pal2uqm - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "pal2uqm - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=xicl6.exe +RSC=rc.exe + +!IF "$(CFG)" == "pal2uqm - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\src\getopt" /I "." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "pal2uqm - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /I "..\..\src\getopt" /I "." /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=xilink6.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pal2uqm - Win32 Release" +# Name "pal2uqm - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=..\..\src\getopt\getopt.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\getopt\getopt.h +# End Source File +# Begin Source File + +SOURCE=.\pal2uqm.c +# End Source File +# End Group +# End Target +# End Project