summaryrefslogtreecommitdiff
path: root/3dc/win95/D3_IMAGE.CPP
diff options
context:
space:
mode:
authorRebellion Developments <rebellion@nomail>2000-03-16 11:25:00 +0100
committerPatryk Obara <dreamer.tan@gmail.com>2019-08-19 05:45:17 +0200
commit218ca90543758a20ac326e444ca0643174ca7384 (patch)
tree16bfe3e5307f9f515489000f28728224291a0e3b /3dc/win95/D3_IMAGE.CPP
Import Aliens vs Predator - Gold (Build 116)
Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format.
Diffstat (limited to '3dc/win95/D3_IMAGE.CPP')
-rw-r--r--3dc/win95/D3_IMAGE.CPP2491
1 files changed, 2491 insertions, 0 deletions
diff --git a/3dc/win95/D3_IMAGE.CPP b/3dc/win95/D3_IMAGE.CPP
new file mode 100644
index 0000000..c068b82
--- /dev/null
+++ b/3dc/win95/D3_IMAGE.CPP
@@ -0,0 +1,2491 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "d3_image.hpp"
+#include "platform.h"
+
+// define = 1 if you dont have pre-quantized images to load into palettized D3D texture surfaces
+#define QUANTISE_ON_LOAD 0
+
+#if debug
+#define DEBUG_TRANSPARENCY 1
+#else
+#define DEBUG_TRANSPARENCY 0
+#endif
+
+// image loader stuff
+
+#if OUTPUT_LOG
+#include "debuglog.hpp"
+LogFile CL_LogFile("DB_IMLD.LOG");
+#endif
+
+#if TIME_LOADS
+unsigned int OpenTime;
+unsigned int CloseTime;
+unsigned int ReadTime;
+#endif
+
+static inline unsigned long read_le_dword(D3I_FILE * f)
+{
+ unsigned char d1,d2,d3,d4;
+ d3i_fread(&d1,1,1,f);
+ d3i_fread(&d2,1,1,f);
+ d3i_fread(&d3,1,1,f);
+ d3i_fread(&d4,1,1,f);
+
+ return (unsigned long)d1 | (unsigned long)d2<<8 | (unsigned long)d3<<16 | (unsigned long)d4<<24;
+}
+
+static inline unsigned short read_le_word(D3I_FILE * f)
+{
+ unsigned char d1,d2;
+ d3i_fread(&d1,1,1,f);
+ d3i_fread(&d2,1,1,f);
+
+ return (unsigned short)d1 | (unsigned short)((unsigned short)d2<<8);
+}
+
+// some default globals
+CL_ImageMode CL_Image::imode = CLM_GLOBALPALETTE;
+CL_ImageMode CL_Image::imode_d3d = CLM_ATTACHEDPALETTE;
+CL_ImageMode CL_Image::imode_ddraw = CLM_GLOBALPALETTE;
+LPDDSURFACEDESC CL_Image::format = 0;
+unsigned int CL_Image::bitsperpixel;
+unsigned int CL_Image::bitsperpixel_d3d;
+unsigned int CL_Image::bitsperpixel_ddraw;
+CL_LoadMode CL_Image::lmode = CLL_DDSURFACE;
+
+CL_DX_Format CL_Pixel_32::f;
+CL_DX_Format CL_Pixel_32::f_d3d;
+CL_DX_Format CL_Pixel_32::f_ddraw;
+CL_DX_Format CL_Pixel_16::f;
+CL_DX_Format CL_Pixel_16::f_d3d;
+CL_DX_Format CL_Pixel_16::f_ddraw;
+
+
+void CL_Image::DeleteNotMips(void)
+{
+ if (im24)
+ {
+ delete[] *im24;
+ delete[] im24;
+ im24 = 0;
+ }
+ if (im16)
+ {
+ delete[] *im16;
+ delete[] im16;
+ im16 = 0;
+ }
+ if (im8)
+ {
+ delete[] *im8;
+ delete[] im8;
+ im8 = 0;
+ }
+ if (palette)
+ {
+ delete[] palette;
+ palette = 0;
+ palette_size = 0;
+ }
+ flags.loaded = 0;
+ flags.raw16bit = 0;
+}
+
+void CL_Image::Delete(void)
+{
+ DeleteNotMips();
+ while (mipmaps.size())
+ {
+ delete mipmaps.last_entry();
+ mipmaps.delete_last_entry();
+ }
+}
+
+
+void CL_Image::Copy(CL_Image const & i2)
+{
+ if (i2.im24)
+ {
+ im24 = new CL_Pixel_24 * [height];
+ *im24 = new CL_Pixel_24 [size];
+
+ CL_Pixel_24 const * sptr = *i2.im24;
+ CL_Pixel_24 * dptr = *im24;
+
+ for (int i=size; i; --i)
+ {
+ *dptr++ = *sptr++;
+ }
+
+ CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24;
+ CL_Pixel_24 const * aptr = *im24;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+
+ if (i2.im16)
+ {
+ im16 = new CL_Pixel_16 * [height];
+ *im16 = new CL_Pixel_16 [size];
+
+ CL_Pixel_16 const * sptr = *i2.im16;
+ CL_Pixel_16 * dptr = *im16;
+
+ for (int i=size; i; --i)
+ {
+ *dptr++ = *sptr++;
+ }
+
+ CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16;
+ CL_Pixel_16 const * aptr = *im16;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+
+ if (i2.im8)
+ {
+ im8 = new unsigned char * [height];
+ *im8 = new unsigned char [size];
+
+ unsigned char const * sptr = *i2.im8;
+ unsigned char * dptr = *im8;
+
+ for (int i=size; i; --i)
+ {
+ *dptr++ = *sptr++;
+ }
+
+ unsigned char const * * dptrptr = (unsigned char const * *) im8;
+ unsigned char const * aptr = *im8;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+
+ if (i2.palette)
+ {
+ palette = new CL_Pixel_24 [palette_size];
+
+ CL_Pixel_24 const * sptr = i2.palette;
+ CL_Pixel_24 * dptr = palette;
+
+ for (int i=palette_size; i; --i)
+ {
+ *dptr++ = *sptr;
+ }
+ }
+
+ if (i2.name)
+ {
+ name = new char [strlen(i2.name)+1];
+ strcpy(name,i2.name);
+ }
+
+ if (i2.fname)
+ {
+ fname = new char [strlen(i2.fname)+1];
+ strcpy(fname,i2.fname);
+ }
+
+ for (CLIF<CL_Image *> i_mip(&i2.mipmaps); !i_mip.done(); i_mip.next())
+ {
+ mipmaps.add_entry_end(new CL_Image(*i_mip()));
+ }
+}
+
+
+CL_Image::~CL_Image()
+{
+ Delete();
+ if (fname) delete[] fname;
+ if (name) delete[] name;
+}
+
+
+CL_Image::CL_Image(CL_Image const & i2)
+: width(i2.width)
+, height(i2.height)
+, size(i2.size)
+, im24(0)
+, im16(0)
+, im8(0)
+, palette(0)
+, palette_size(i2.palette_size)
+, fname(0)
+, name(0)
+, flags(i2.flags)
+{
+ Copy(i2);
+}
+
+
+CL_Image & CL_Image::operator = (CL_Image const & i2)
+{
+ if (&i2 != this)
+ {
+ Delete();
+ if (fname) delete[] fname;
+ if (name) delete[] name;
+
+ width = i2.width;
+ height = i2.height;
+ size = i2.size;
+ palette_size = i2.palette_size;
+
+ fname = 0;
+ name = 0;
+
+ flags = i2.flags;
+
+ Copy(i2);
+ }
+ return *this;
+}
+
+
+CL_Error CL_Image::Make(int const _width, int const _height)
+{
+ Delete();
+
+ width = _width;
+ height = _height;
+ palette_size = 0;
+ size = width*height;
+
+ switch (imode)
+ {
+ case CLM_ATTACHEDPALETTE:
+ {
+ palette_size = 256;
+ palette = new CL_Pixel_24 [palette_size];
+ }
+ case CLM_GLOBALPALETTE:
+ case CLM_TLTPALETTE:
+ {
+ im8 = new unsigned char * [height];
+ *im8 = new unsigned char [size];
+
+ unsigned char const * * dptrptr = (unsigned char const * *) im8;
+ unsigned char * dptr = *im8;
+ for (int i=height; i; --i, dptr+=width)
+ {
+ *dptrptr++ = dptr;
+ }
+
+ break;
+ }
+ case CLM_24BIT:
+ {
+ im24 = new CL_Pixel_24 * [height];
+ *im24 = new CL_Pixel_24 [size];
+
+ CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24;
+ CL_Pixel_24 const * aptr = *im24;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ break;
+ }
+ case CLM_16BIT:
+ {
+ im16 = new CL_Pixel_16 * [height];
+ *im16 = new CL_Pixel_16 [size];
+
+ CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16;
+ CL_Pixel_16 const * aptr = *im16;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ break;
+ }
+ case CLM_32BIT:
+ {
+ im32 = new CL_Pixel_32 * [height];
+ *im32 = new CL_Pixel_32 [size];
+
+ CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32;
+ CL_Pixel_32 const * aptr = *im32;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ break;
+ }
+ default:
+ return CLE_INVALIDDXMODE;
+ }
+
+ flags.loaded = 1;
+ return CLE_OK;
+}
+
+
+CL_Error CL_Image::MakeRandom(int const _width, int const _height, int const seed)
+{
+ Delete();
+
+ if (-1!=seed) srand((unsigned int)seed);
+
+ width = _width;
+ height = _height;
+ size = width*height;
+ palette_size = 0;
+
+ switch (imode)
+ {
+ case CLM_ATTACHEDPALETTE:
+ {
+ palette_size = 256;
+ palette = new CL_Pixel_24 [palette_size];
+ CL_Pixel_24 * palP = palette;
+ for (int i=palette_size; i; --i, ++palP)
+ {
+ *palP = CL_Pixel_24(rand()&255,rand()&255,rand()&255);
+ }
+ }
+ case CLM_GLOBALPALETTE:
+ case CLM_TLTPALETTE:
+ {
+ im8 = new unsigned char * [height];
+ *im8 = new unsigned char [size];
+
+ unsigned char const * * dptrptr = (unsigned char const * *) im8;
+ unsigned char * dptr = *im8;
+ for (int i=height; i; --i)
+ {
+ *dptrptr++ = dptr;
+ for (int j=width; j; --j, ++dptr)
+ *dptr = (unsigned char)(rand()&(palette_size-1));
+ }
+
+ break;
+ }
+ case CLM_24BIT:
+ {
+ im24 = new CL_Pixel_24 * [height];
+ *im24 = new CL_Pixel_24 [size];
+
+ CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24;
+ CL_Pixel_24 * aptr = *im24;
+ for (int i=height; i; --i)
+ {
+ *dptrptr++ = aptr;
+ for (int j=width; j; --j, ++aptr)
+ *aptr = CL_Pixel_24(rand()&255,rand()&255,rand()&255);
+ }
+
+ break;
+ }
+ case CLM_16BIT:
+ {
+ im16 = new CL_Pixel_16 * [height];
+ *im16 = new CL_Pixel_16 [size];
+
+ CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16;
+ CL_Pixel_16 * aptr = *im16;
+ for (int i=height; i; --i)
+ {
+ *dptrptr++ = aptr;
+ for (int j=width; j; --j, ++aptr)
+ *aptr = CL_Pixel_24(rand()&255,rand()&255,rand()&255);
+ }
+
+ break;
+ }
+ case CLM_32BIT:
+ {
+ im32 = new CL_Pixel_32 * [height];
+ *im32 = new CL_Pixel_32 [size];
+
+ CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32;
+ CL_Pixel_32 * aptr = *im32;
+ for (int i=height; i; --i)
+ {
+ *dptrptr++ = aptr;
+ for (int j=width; j; --j, ++aptr)
+ *aptr = CL_Pixel_24(rand()&255,rand()&255,rand()&255);
+ }
+
+ break;
+ }
+ default:
+ return CLE_INVALIDDXMODE;
+ }
+
+ flags.loaded = 1;
+ return CLE_OK;
+}
+
+
+CL_Error CL_Image::Load_BMP(D3I_FILE * f)
+{
+ if (!f) return CLE_OPENERROR;
+
+ DeleteNotMips();
+
+ switch (imode)
+ {
+ case CLM_ATTACHEDPALETTE:
+ case CLM_24BIT:
+ case CLM_16BIT:
+ case CLM_32BIT:
+ break;
+ default:
+ return CLE_INVALIDDXMODE;
+ }
+
+ d3i_fseek(f,0,SEEK_SET);
+ unsigned short magic;
+ d3i_fread(&magic,2,1,f);
+ if (magic != *(unsigned short const *)"BM") return CLE_LOADERROR;
+
+ size_t filesize = read_le_dword(f);
+ d3i_fseek(f,4,SEEK_CUR);
+ size_t offset = read_le_dword(f);
+ size_t headsize = read_le_dword(f);
+
+ unsigned short bitdepth;
+
+ if (12 == headsize) // OS/2 1.x
+ {
+ width = read_le_word(f);
+ height = read_le_word(f);
+ size = width * height;
+ if (!width || !height) return CLE_LOADERROR;
+ unsigned short planes = read_le_word(f);
+ if (1 != planes) return CLE_LOADERROR;
+ bitdepth = read_le_word(f);
+
+ if (bitdepth != 24)
+ {
+ palette_size = 1<<bitdepth;
+ palette = new CL_Pixel_24 [palette_size];
+ CL_Pixel_24 * rptr = palette;
+ for (int i=palette_size; i; --i)
+ {
+ rptr++->Read(f,CLF_BGR);
+ }
+ }
+ }
+ else if (40 == headsize || 64 == headsize) // Windows 3.x || OS/2 2.x
+ {
+ width = read_le_dword(f);
+ height = read_le_dword(f);
+ unsigned short planes = read_le_word(f);
+ if (1 != planes) return CLE_LOADERROR;
+ bitdepth = read_le_word(f);
+
+ if (read_le_dword(f)) return CLE_LOADERROR; // compressed bmps not supported
+
+ size = read_le_dword(f);
+
+ d3i_fseek(f,8,SEEK_CUR);
+ palette_size = read_le_dword(f);
+ if (!palette_size && bitdepth != 24) palette_size = 1<<bitdepth;
+
+ if (palette_size)
+ {
+ d3i_fseek(f,headsize+14,SEEK_SET);
+ palette = new CL_Pixel_24 [palette_size];
+ CL_Pixel_24 * rptr = palette;
+ for (int i=palette_size; i; --i)
+ {
+ rptr++->Read(f,CLF_BGRX);
+ }
+ }
+ }
+ else return CLE_LOADERROR;
+
+ d3i_fseek(f,offset,SEEK_SET);
+
+ if (palette_size)
+ {
+ if (bitdepth < 4)
+ {
+ delete[] palette;
+ palette_size = 0;
+ return CLE_LOADERROR;
+ }
+
+ im8 = new unsigned char * [height];
+ *im8 = new unsigned char [size];
+
+ unsigned char const * * dptrptr = (unsigned char const * *) im8;
+ unsigned char * dptr = *im8;
+ for (int i=height; i; --i, dptr+=width)
+ {
+ *dptrptr++ = dptr;
+ }
+
+ #if DEBUG_TRANSPARENCY
+ int num_tps=0;
+ #endif
+ for (i=height-1; i>=0; --i)
+ {
+ dptr = im8[i];
+
+ if (4==bitdepth)
+ {
+ for (int i=width>>1; i; --i)
+ {
+ unsigned char byte;
+ d3i_fread(&byte,1,1,f);
+ #if DEBUG_TRANSPARENCY
+ *dptr = (unsigned char)(byte >> 4 & 0xf);
+ if (!*dptr) num_tps++;
+ *++dptr = (unsigned char)(byte & 0xf);
+ if (!*dptr) num_tps++;
+ ++dptr;
+ #else
+ *dptr++ = (unsigned char)(byte >> 4 & 0xf);
+ *dptr++ = (unsigned char)(byte & 0xf);
+ #endif
+ }
+ if (width & 1)
+ {
+ d3i_fread(dptr,1,1,f);
+ *dptr &= 0xf;
+ #if DEBUG_TRANSPARENCY
+ if (!*dptr) num_tps++;
+ #endif
+ }
+
+ d3i_fseek(f,(~(width-1) & 7)>>1,SEEK_CUR);
+ }
+ else
+ {
+ for (int i=width; i; --i)
+ {
+ #if DEBUG_TRANSPARENCY
+ d3i_fread(dptr,1,1,f);
+ if (!*dptr) num_tps++;
+ dptr++;
+ #else
+ d3i_fread(dptr++,1,1,f);
+ #endif
+ }
+ d3i_fseek(f,~(width-1) & 3,SEEK_CUR);
+ }
+ }
+ #if DEBUG_TRANSPARENCY
+ if (num_tps) CL_LogFile.lprintf("-- %d TRANSPARENT PIXELS FOUND\n",num_tps);
+ #endif
+ }
+ else if (CLM_16BIT == imode)
+ {
+ im16 = new CL_Pixel_16 * [height];
+ *im16 = new CL_Pixel_16 [size];
+
+ CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16;
+ CL_Pixel_16 const * aptr = *im16;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ for (i=height-1; i>=0; --i)
+ {
+ CL_Pixel_16 * dptr = im16[i];
+
+ for (int i=width; i; --i)
+ {
+ dptr++->Read(f,CLF_BGR);
+ }
+ d3i_fseek(f,~(width*3-1) & 3,SEEK_CUR);
+ }
+
+ }
+ else if (CLM_32BIT == imode)
+ {
+ im32 = new CL_Pixel_32 * [height];
+ *im32 = new CL_Pixel_32 [size];
+
+ CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32;
+ CL_Pixel_32 const * aptr = *im32;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ for (i=height-1; i>=0; --i)
+ {
+ CL_Pixel_32 * dptr = im32[i];
+
+ for (int i=width; i; --i)
+ {
+ dptr++->Read(f,CLF_BGR);
+ }
+ d3i_fseek(f,~(width*3-1) & 3,SEEK_CUR);
+ }
+
+ }
+ else if (CLM_24BIT == imode)
+ {
+ im24 = new CL_Pixel_24 * [height];
+ *im24 = new CL_Pixel_24 [size];
+
+ CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24;
+ CL_Pixel_24 const * aptr = *im24;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ for (i=height-1; i>=0; --i)
+ {
+ CL_Pixel_24 * dptr = im24[i];
+
+ for (int i=width; i; --i)
+ {
+ dptr++->Read(f,CLF_BGR);
+ }
+ d3i_fseek(f,~(width*3-1) & 3,SEEK_CUR);
+ }
+
+ }
+ else return CLE_INVALIDDXMODE;
+
+ if (palette_size && CLM_ATTACHEDPALETTE != imode)
+ {
+ if (CLM_16BIT == imode)
+ {
+ im16 = new CL_Pixel_16 * [height];
+ *im16 = new CL_Pixel_16 [size];
+
+ unsigned char const * sptr = *im8;
+ CL_Pixel_16 * dptr = *im16;
+
+ for (int i=size; i; --i, ++dptr,++sptr)
+ {
+ if (*sptr && !palette[*sptr])
+ *dptr = dptr->f.dx_black;
+ else
+ *dptr = palette[*sptr];
+ }
+
+ CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16;
+ CL_Pixel_16 const * aptr = *im16;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+ else if (CLM_32BIT == imode)
+ {
+ im32 = new CL_Pixel_32 * [height];
+ *im32 = new CL_Pixel_32 [size];
+
+ unsigned char const * sptr = *im8;
+ CL_Pixel_32 * dptr = *im32;
+
+ for (int i=size; i; --i, ++dptr,++sptr)
+ {
+ if (*sptr && !palette[*sptr])
+ *dptr = dptr->f.dx_black;
+ else
+ *dptr = palette[*sptr];
+ }
+
+ CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32;
+ CL_Pixel_32 const * aptr = *im32;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+ else
+ {
+ im24 = new CL_Pixel_24 * [height];
+ *im24 = new CL_Pixel_24 [size];
+
+ unsigned char const * sptr = *im8;
+ CL_Pixel_24 * dptr = *im24;
+
+ for (int i=size; i; --i, ++dptr,++sptr)
+ {
+ if (*sptr && !palette[*sptr])
+ *dptr = CL_Pixel_24(0,1,0);
+ else
+ *dptr = palette[*sptr];
+ }
+
+ CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24;
+ CL_Pixel_24 const * aptr = *im24;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+
+ delete[] palette;
+ palette = 0;
+ palette_size = 0;
+ delete[] *im8;
+ delete[] im8;
+ im8 = 0;
+ }
+
+ if (d3i_ferror(f) || d3i_feof(f))
+ {
+ DeleteNotMips();
+ return CLE_LOADERROR;
+ }
+
+ flags.loaded = 1;
+ return CLE_OK;
+}
+
+
+CL_Error CL_Image::Load_PPM(D3I_FILE * f)
+{
+ if (!f) return CLE_OPENERROR;
+
+ DeleteNotMips();
+
+ switch (imode)
+ {
+ case CLM_24BIT:
+ case CLM_16BIT:
+ case CLM_32BIT:
+ break;
+ default:
+ return CLE_INVALIDDXMODE;
+ }
+
+ d3i_fseek(f,0,SEEK_SET);
+ unsigned short magic;
+ d3i_fread(&magic,2,1,f);
+ if (magic != *(unsigned short const *)"P6") return CLE_LOADERROR;
+
+ d3i_fseek(f,1,SEEK_CUR);
+ char buf[256];
+ char * bufptr = buf;
+ unsigned int fields[5];
+ unsigned int fields_read = 0;
+ while (fields_read < 3 && bufptr)
+ {
+ do bufptr = d3i_fgets(buf, sizeof buf, f);
+ while ('#'==buf[0] && bufptr);
+
+ int num_fields_read = sscanf(buf,"%u %u %u",&fields[fields_read],&fields[fields_read+1],&fields[fields_read+2]);
+ if (EOF != num_fields_read) fields_read += num_fields_read;
+ }
+ if (fields_read < 3) return CLE_LOADERROR;
+ width = fields[0];
+ height = fields[1];
+ unsigned int maxval = fields[2];
+ if (maxval > 255) return CLE_LOADERROR;
+
+ size = width * height;
+
+ if (CLM_16BIT == imode)
+ {
+ im16 = new CL_Pixel_16 * [height];
+ *im16 = new CL_Pixel_16 [size];
+
+ CL_Pixel_16 * rptr = *im16;
+ for (int i=size; i; --i)
+ {
+ rptr++->Read(f,CLF_RGB,maxval);
+ }
+
+ CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16;
+ CL_Pixel_16 const * aptr = *im16;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+ else if (CLM_32BIT == imode)
+ {
+ im32 = new CL_Pixel_32 * [height];
+ *im32 = new CL_Pixel_32 [size];
+
+ CL_Pixel_32 * rptr = *im32;
+ for (int i=size; i; --i)
+ {
+ rptr++->Read(f,CLF_RGB,maxval);
+ }
+
+ CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32;
+ CL_Pixel_32 const * aptr = *im32;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+ else
+ {
+ im24 = new CL_Pixel_24 * [height];
+ *im24 = new CL_Pixel_24 [size];
+
+ CL_Pixel_24 * rptr = *im24;
+ for (int i=size; i; --i)
+ {
+ rptr++->Read(f,CLF_RGB,maxval);
+ }
+
+ CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24;
+ CL_Pixel_24 const * aptr = *im24;
+ for (i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+ }
+
+ if (d3i_ferror(f) || d3i_feof(f))
+ {
+ DeleteNotMips();
+ return CLE_LOADERROR;
+ }
+
+ flags.loaded = 1;
+ return CLE_OK;
+}
+
+
+CL_Error CL_Image::Load_PGM(D3I_FILE * f)
+{
+ if (!f) return CLE_OPENERROR;
+
+ DeleteNotMips();
+
+ switch (imode)
+ {
+ case CLM_GLOBALPALETTE:
+ case CLM_TLTPALETTE:
+ break;
+ default:
+ return CLE_INVALIDDXMODE;
+ }
+
+ d3i_fseek(f,0,SEEK_SET);
+ unsigned short magic;
+ d3i_fread(&magic,2,1,f);
+ if (magic != *(unsigned short const *)"P5") return CLE_LOADERROR;
+
+ d3i_fseek(f,1,SEEK_CUR);
+ char buf[256];
+ char * bufptr = buf;
+ unsigned int fields[5];
+ unsigned int fields_read = 0;
+ while (fields_read < 3 && bufptr)
+ {
+ do bufptr = d3i_fgets(buf, sizeof buf, f);
+ while ('#'==buf[0] && bufptr);
+
+ int num_fields_read = sscanf(buf,"%u %u %u",&fields[fields_read],&fields[fields_read+1],&fields[fields_read+2]);
+ if (EOF != num_fields_read) fields_read += num_fields_read;
+ }
+ if (fields_read < 3) return CLE_LOADERROR;
+ width = fields[0];
+ height = fields[1];
+ unsigned int maxval = fields[2];
+ if (maxval > 255) return CLE_LOADERROR;
+
+ size = width * height;
+
+ im8 = new unsigned char * [height];
+ *im8 = new unsigned char [size];
+
+ d3i_fread(*im8,1,size,f);
+
+ unsigned char const * * dptrptr = (unsigned char const * *) im8;
+ unsigned char const * aptr = *im8;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ if (d3i_ferror(f) || d3i_feof(f))
+ {
+ DeleteNotMips();
+ return CLE_LOADERROR;
+ }
+
+ flags.loaded = 1;
+ return CLE_OK;
+}
+
+
+CL_Error CL_Image::Load_PWM(D3I_FILE * f)
+{
+ if (!f) return CLE_OPENERROR;
+
+ DeleteNotMips();
+
+ switch (imode)
+ {
+ case CLM_TLTPALETTE:
+ break;
+ default:
+ return CLE_INVALIDDXMODE;
+ }
+
+ d3i_fseek(f,0,SEEK_SET);
+ unsigned short magic;
+ d3i_fread(&magic,2,1,f);
+ if (magic != *(unsigned short const *)"P8") return CLE_LOADERROR;
+
+ d3i_fseek(f,1,SEEK_CUR);
+ char buf[256];
+ char * bufptr = buf;
+ unsigned int fields[5];
+ unsigned int fields_read = 0;
+ while (fields_read < 3 && bufptr)
+ {
+ do bufptr = d3i_fgets(buf, sizeof buf, f);
+ while ('#'==buf[0] && bufptr);
+
+ int num_fields_read = sscanf(buf,"%u %u %u",&fields[fields_read],&fields[fields_read+1],&fields[fields_read+2]);
+ if (EOF != num_fields_read) fields_read += num_fields_read;
+ }
+ if (fields_read < 3) return CLE_LOADERROR;
+ width = fields[0];
+ height = fields[1];
+ unsigned int maxval = fields[2];
+ if (maxval > 65535) return CLE_LOADERROR;
+
+ size = width * height;
+
+ im16raw = new unsigned short * [height];
+ *im16raw = new unsigned short [size];
+
+ d3i_fread(*im16raw,2,size,f);
+
+ unsigned short const * * dptrptr = (unsigned short const * *) im16raw;
+ unsigned short const * aptr = *im16raw;
+ for (int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ if (d3i_ferror(f) || d3i_feof(f))
+ {
+ DeleteNotMips();
+ return CLE_LOADERROR;
+ }
+
+ flags.loaded = 1;
+ flags.raw16bit = 1;
+ return CLE_OK;
+}
+
+
+
+CL_Error CL_Image::GetBitsPerPixel(unsigned int* bpp)
+{
+ *bpp = bitsperpixel;
+ return CLE_OK;
+}
+
+CL_Error CL_Image::Load_Image(D3I_FILE * f)
+{
+ if (!f) return CLE_OPENERROR;
+
+ CL_Error retval = CLE_LOADERROR;
+
+ START_TIMER
+
+ d3i_fseek(f,0,SEEK_SET);
+ unsigned short magic;
+ d3i_fread(&magic,2,1,f);
+
+ if ( *(unsigned short const *)"BM" == magic)
+ retval = Load_BMP(f);
+ else if ( *(unsigned short const *)"P6" == magic)
+ retval = Load_PPM(f);
+ else if ( *(unsigned short const *)"P5" == magic)
+ retval = Load_PGM(f);
+ else if ( *(unsigned short const *)"P8" == magic)
+ retval = Load_PWM(f);
+ #if OUTPUT_LOG
+ else CL_LogFile.lputs("** ERROR: Not a recognized file format\n");
+ #endif
+
+ END_TIMER(ReadTime)
+
+ #if OUTPUT_LOG
+ #if TIME_LOADS
+ CL_LogFile.lprintf("-- Timer Stats (ms): Open %d Read %d Close %d\n",OpenTime,ReadTime,CloseTime);
+ #endif
+ #endif
+
+ return retval;
+}
+
+
+void CL_Image::PadTo(int const width_unit,int const height_unit)
+{
+ if (!flags.loaded) return;
+
+ unsigned int const owidth = width;
+ unsigned int const oheight = height;
+
+ width += width_unit-1;
+ width &= ~(width_unit-1);
+ height += height_unit-1;
+ height &= ~(height_unit-1);
+
+ if (width == owidth && height == oheight) return; // already in spec
+
+ size = width * height;
+
+ CL_Pixel_32 * * const oim32 = im32;
+ CL_Pixel_16 * * const oim16 = im16;
+ unsigned char * * const oim8 = im8;
+
+ if (oim32)
+ {
+ im32 = new CL_Pixel_32 * [height];
+ *im32 = new CL_Pixel_32 [size];
+
+ CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32;
+ CL_Pixel_32 const * aptr = *im32;
+ for (unsigned int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ for (unsigned int y = 0; y < oheight; ++y)
+ {
+ CL_Pixel_32 const * sptr = oim32[y];
+ CL_Pixel_32 * dptr = im32[y];
+
+ for (unsigned int x = 0; x < owidth; ++x, ++dptr, ++sptr)
+ *dptr = *sptr;
+
+ for (; x < width; ++x, ++dptr)
+ *dptr = CL_Pixel_24(0,0,0);
+ }
+
+ for (; y < height; ++y)
+ {
+ CL_Pixel_32 * dptr = im32[y];
+ for (unsigned int x = 0; x < width; ++x, ++dptr)
+ *dptr = CL_Pixel_24(0,0,0);
+ }
+
+ delete[] *oim32;
+ delete[] oim32;
+ }
+
+ if (oim16)
+ {
+ im16 = new CL_Pixel_16 * [height];
+ *im16 = new CL_Pixel_16 [size];
+
+ CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16;
+ CL_Pixel_16 const * aptr = *im16;
+ for (unsigned int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ for (unsigned int y = 0; y < oheight; ++y)
+ {
+ CL_Pixel_16 const * sptr = oim16[y];
+ CL_Pixel_16 * dptr = im16[y];
+
+ for (unsigned int x = 0; x < owidth; ++x, ++dptr, ++sptr)
+ *dptr = *sptr;
+
+ for (; x < width; ++x, ++dptr)
+ *dptr = CL_Pixel_24(0,0,0);
+ }
+
+ for (; y < height; ++y)
+ {
+ CL_Pixel_16 * dptr = im16[y];
+ for (unsigned int x = 0; x < width; ++x, ++dptr)
+ *dptr = CL_Pixel_24(0,0,0);
+ }
+
+ delete[] *oim16;
+ delete[] oim16;
+ }
+
+ if (oim8)
+ {
+ im8 = new unsigned char * [height];
+ *im8 = new unsigned char [size];
+
+ unsigned char const * * dptrptr = (unsigned char const * *) im8;
+ unsigned char const * aptr = *im8;
+ for (unsigned int i=height; i; --i, aptr+=width)
+ {
+ *dptrptr++ = aptr;
+ }
+
+ for (unsigned int y = 0; y < oheight; ++y)
+ {
+ unsigned char const * sptr = oim8[y];
+ unsigned char * dptr = im8[y];
+
+ for (unsigned int x = 0; x < owidth; ++x, ++dptr, ++sptr)
+ *dptr = *sptr;
+
+ for (; x < width; ++x, ++dptr)
+ *dptr = 0;
+ }
+
+ for (; y < height; ++y)
+ {
+ unsigned char * dptr = im8[y];
+ for (unsigned int x = 0; x < width; ++x, ++dptr)
+ *dptr = 0;
+ }
+
+ delete[] *oim8;
+ delete[] oim8;
+ }
+}
+
+// implementation of the 'popularity algorithm' for reducing palette
+
+unsigned int CL_Pixel_24::FVD_Distance(CL_Pixel_24 const & p2) const
+{
+ unsigned int dg = g > p2.g ? g - p2.g : p2.g - g;
+ unsigned int db = b > p2.b ? b - p2.b : p2.b - b;
+
+ unsigned int dgb = dg + db + ((dg > db ? dg : db)<<1);
+
+ unsigned int dr = r > p2.r ? r - p2.r : p2.r - r;
+ dr += dr<<1; // *= 3
+
+ return dr + dgb + ((dr > dgb ? dr : dgb)<<1);
+}
+
+struct _CL_palpixcnt
+{
+ unsigned int cnt;
+ unsigned int palpos;
+};
+
+int _CL_cmp_palpixcnt(void const * e1, void const * e2)
+{
+ return ((_CL_palpixcnt *)e2)->cnt - ((_CL_palpixcnt *)e1)->cnt;
+}
+
+CL_Error CL_Image::ReducePalette(unsigned int const num_colours)
+{
+ if (!flags.loaded) return CLE_LOADERROR;
+
+ if (!palette) return CLE_INVALIDDXMODE;
+ if (!im8) return CLE_INVALIDDXMODE;
+
+ if (palette_size <= num_colours) return CLE_OK;
+
+ _CL_palpixcnt * const sortarray = new _CL_palpixcnt[palette_size];
+
+ for (unsigned int i=0; i<palette_size; ++i)
+ {
+ sortarray[i].cnt = 0;
+ sortarray[i].palpos = i;
+ }
+
+ for (unsigned int y=0; y<height; ++y)
+ {
+ unsigned char const * sptr = im8[y];
+
+ for (unsigned int x=width; x; --x, ++sptr)
+ ++ sortarray[*sptr].cnt;
+ }
+
+ unsigned int const palstart = CL_Pixel_24(0,0,0) == palette[0] ? 1 : 0;
+ qsort(sortarray + palstart, palette_size - palstart, sizeof(_CL_palpixcnt), _CL_cmp_palpixcnt);
+
+ CL_Pixel_24 * const opalette = palette;
+ unsigned int const opalette_size = palette_size;
+ palette = new CL_Pixel_24[num_colours];
+ palette_size = num_colours;
+
+ for (i=0; i<palette_size; ++i)
+ palette[i] = opalette[sortarray[i].palpos];
+
+ delete[] sortarray;
+
+ // umm - if theres black thats not transparent, make sure it doesnt become colour 0 in palette
+ for (unsigned int pswap=1; pswap<palette_size && 0==palstart && CL_Pixel_24(0,0,0)==palette[0]; ++pswap)
+ {
+ palette[0]=palette[pswap];
+ palette[pswap]=CL_Pixel_24(0,0,0);
+ }
+
+ // emergency?
+ if (0==palstart && CL_Pixel_24(0,0,0)==palette[0])
+ palette[0] = CL_Pixel_24(1,1,1);
+
+ unsigned int * const palmaps = new unsigned int [opalette_size];
+ palmaps[0] = 0;
+ for (i=palstart; i<opalette_size; ++i)
+ {
+ unsigned int closest = palstart;
+ unsigned int distance = opalette[i].FVD_Distance(palette[palstart]);
+
+ for (unsigned int j = palstart+1; j<palette_size; ++j)
+ {
+ unsigned int thisdist = opalette[i].FVD_Distance(palette[j]);
+ if (thisdist < distance)
+ {
+ distance = thisdist;
+ closest = j;
+ }
+ }
+
+ palmaps[i] = closest;
+ }
+
+ delete[] opalette;
+
+ for (y=0; y<height; ++y)
+ {
+ unsigned char * sptr = im8[y];
+
+ for (unsigned int x=width; x; --x, ++sptr)
+ *sptr = (unsigned char)palmaps[*sptr];
+ }
+
+ delete[] palmaps;
+
+ return CLE_OK;
+}
+
+// useful filename handling functions
+
+// returns pointer into string pointing to filename without dirname
+static char const * strip_path(char const * n)
+{
+ char const * rm = strrchr(n,':');
+ if (rm) n = rm+1;
+ rm = strrchr(n,'/');
+ if (rm) n = rm+1;
+ rm = strrchr(n,'\\');
+ if (rm) n = rm+1;
+
+ return n;
+}
+
+#if 0
+static char * strip_path(char * n)
+{
+ char * rm = strrchr(n,':');
+ if (rm) n = rm+1;
+ rm = strrchr(n,'/');
+ if (rm) n = rm+1;
+ rm = strrchr(n,'\\');
+ if (rm) n = rm+1;
+
+ return n;
+}
+#endif
+
+// removes any .extension from filename by inserting null character
+static void strip_file_extension(char * n)
+{
+ char * dotpos = strrchr(n,'.');
+ if (dotpos) *dotpos = 0;
+}
+
+static char * strip_file_extension(char const * n)
+{
+ char * nn = new char[strlen(n)+1];
+ strcpy(nn,n);
+ strip_file_extension(nn);
+ return nn;
+}
+
+// CL_Image functions
+
+CL_Error CL_Image::Locate(char const * iname, int const /* enum_id */)
+{
+ if (!iname) return CLE_RIFFERROR;
+
+ if (name)
+ delete[] name;
+ name = strip_file_extension(strip_path(iname));
+
+ if (fname)
+ delete[] fname;
+ fname = new char[strlen(iname)+1];
+ strcpy(fname,iname);
+
+ flags.located = 1;
+ return CLE_OK;
+}
+
+CL_Error CL_Image::Load(char const * const iname, int const enum_id)
+{
+ if (iname || CL_EID_INVALID != enum_id || !flags.located)
+ {
+ CL_Error locate_err = Locate(iname,enum_id);
+
+ if (locate_err != CLE_OK)
+ {
+ EXITONLOCATEFAIL(locate_err,iname,enum_id)
+ return locate_err;
+ }
+ }
+
+ #if OUTPUT_LOG
+ char const * texformat;
+ unsigned int redbits = 8;
+ unsigned int greenbits = 8;
+ unsigned int bluebits = 8;
+ switch (imode)
+ {
+ case CLM_GLOBALPALETTE:
+ texformat = "Palettized Display";
+ break;
+ case CLM_TLTPALETTE:
+ texformat = "Palettized Display with Abstract TLT Palette";
+ break;
+ case CLM_ATTACHEDPALETTE:
+ texformat = "Palettized Textures";
+ break;
+ case CLM_32BIT:
+ texformat = "32BIT DX";
+ redbits += CL_Pixel_32::f.red_bits_gt8;
+ redbits -= CL_Pixel_32::f.red_bits_lt8;
+ greenbits += CL_Pixel_32::f.green_bits_gt8;
+ greenbits -= CL_Pixel_32::f.green_bits_lt8;
+ bluebits += CL_Pixel_32::f.blue_bits_gt8;
+ bluebits -= CL_Pixel_32::f.blue_bits_lt8;
+ break;
+ case CLM_24BIT:
+ texformat = "24-bit for runtime conversion";
+ break;
+ case CLM_16BIT:
+ texformat = "16BIT DX";
+ redbits += CL_Pixel_16::f.red_bits_gt8;
+ redbits -= CL_Pixel_16::f.red_bits_lt8;
+ greenbits += CL_Pixel_16::f.green_bits_gt8;
+ greenbits -= CL_Pixel_16::f.green_bits_lt8;
+ bluebits += CL_Pixel_16::f.blue_bits_gt8;
+ bluebits -= CL_Pixel_16::f.blue_bits_lt8;
+ break;
+ }
+ CL_LogFile.lprintf("--%s %s (%u-bit, %u-%u-%u)\n",fname,texformat,bitsperpixel,redbits,greenbits,bluebits);
+ #endif
+
+ START_TIMER
+ D3I_FILE * fp = d3i_fopen(fname,"rb");
+ END_TIMER(OpenTime)
+
+ if (fp)
+ {
+ CL_Error retval = Load_Image(fp);
+ START_TIMER
+ d3i_fclose(fp);
+ END_TIMER(CloseTime)
+ if (CLE_OK != retval)
+ {
+ #if OUTPUT_LOG
+ CL_LogFile.lputs("** ERROR: unable to read\n");
+ #endif
+ EXITONREADFAIL(fname)
+ }
+ return retval;
+ }
+
+ #if OUTPUT_LOG
+ CL_LogFile.lputs("** ERROR: unable to open\n");
+ #endif
+ EXITONLOADFAIL(fname)
+ return CLE_OPENERROR;
+}
+
+CL_Error CL_Image::PreLoad(char const * const iname, int const enum_id)
+{
+ CL_Error locate_err = Locate(iname,enum_id);
+
+ if (locate_err != CLE_OK)
+ {
+ return locate_err;
+ }
+
+ return CLE_OK;
+}
+
+CL_Error CL_Image::LoadMipMaps(int const n_mips) // assumes locating has been done (ie. PreLoad or Load has been called)
+{
+ if (!flags.located) return CLE_FINDERROR;
+
+ while (mipmaps.size())
+ {
+ delete mipmaps.last_entry();
+ mipmaps.delete_last_entry();
+ }
+
+ for (int mip_idx = 1; mip_idx < n_mips; ++mip_idx)
+ {
+ CL_Image * mip_n = new CL_Image;
+
+ mip_n->name = new char[strlen(name)+1];
+ mip_n->fname = new char[strlen(fname)+1];
+ strcpy(mip_n->name,name);
+ strcpy(mip_n->fname,fname);
+
+ char * dotpos = strrchr(mip_n->fname,'.');
+ if (!dotpos)
+ {
+ delete mip_n;
+ break;
+ }
+ sprintf(dotpos+3,"%1d",mip_idx);
+
+ mip_n->flags.located = 1;
+
+ if (CLE_OK!=mip_n->Load())
+ {
+ delete mip_n;
+ break;
+ }
+
+ if (mip_n->width << mip_idx < width || mip_n->height << mip_idx < height)
+ {
+ delete mip_n;
+ #if OUTPUT_LOG
+ CL_LogFile.lputs("** Warning: less than half size\n");
+ #endif
+ break;
+ }
+
+ mipmaps.add_entry_end(mip_n);
+ }
+ return CLE_OK;
+}
+
+void CL_Select_Mode(CL_LoadMode const lmode)
+{
+ switch (lmode)
+ {
+ case CLL_D3DTEXTURE:
+ CL_Image::imode = CL_Image::imode_d3d;
+ CL_Image::bitsperpixel = CL_Image::bitsperpixel_d3d;
+ CL_Pixel_16::f = CL_Pixel_16::f_d3d;
+ CL_Pixel_32::f = CL_Pixel_32::f_d3d;
+ break;
+ case CLL_DDSURFACE:
+ CL_Image::imode = CL_Image::imode_ddraw;
+ CL_Image::bitsperpixel = CL_Image::bitsperpixel_ddraw;
+ CL_Pixel_16::f = CL_Pixel_16::f_ddraw;
+ CL_Pixel_32::f = CL_Pixel_32::f_ddraw;
+ break;
+ }
+ CL_Image::lmode = lmode;
+}
+
+// 3DC interface
+
+void CL_Init_DirectDrawMode(CL_VideoMode const vmode)
+{
+ switch (vmode)
+ {
+ case CLV_8:
+ CL_Image::bitsperpixel_ddraw = 8;
+ CL_Image::imode_ddraw = CLM_GLOBALPALETTE;
+ break;
+ case CLV_8TLT:
+ CL_Image::bitsperpixel_ddraw = 8;
+ CL_Image::imode_ddraw = CLM_TLTPALETTE;
+ break;
+ case CLV_15:
+ CL_Image::bitsperpixel_ddraw = 16;
+ CL_Image::imode_ddraw = CLM_16BIT;
+ CL_Pixel_16::f_ddraw.Init
+ (
+ DisplayPixelFormat.dwRBitMask,
+ DisplayPixelFormat.dwGBitMask,
+ DisplayPixelFormat.dwBBitMask
+ );
+ break;
+ case CLV_24:
+ CL_Image::bitsperpixel_ddraw = DisplayPixelFormat.dwRGBBitCount;
+ if (24 == CL_Image::bitsperpixel_ddraw)
+ CL_Image::imode_ddraw = CLM_24BIT;
+ else
+ {
+ CL_Image::imode_ddraw = CLM_32BIT;
+ CL_Pixel_32::f_ddraw.Init
+ (
+ DisplayPixelFormat.dwRBitMask,
+ DisplayPixelFormat.dwGBitMask,
+ DisplayPixelFormat.dwBBitMask
+ );
+ }
+ break;
+ case CLV_8T:
+ CL_Image::bitsperpixel_ddraw = 8;
+ CL_Image::imode_ddraw = CLM_16BIT;
+ CL_Pixel_16::f_ddraw.Init(7<<5,7<<2,3);
+ break;
+ }
+ CL_Select_Mode(CLL_DDSURFACE);
+}
+
+
+CL_Error CL_Image::CopyToScanDrawTexture(unsigned char * * const ImagePtrA [], unsigned int n_mips_max)
+{
+ if (!flags.loaded) return CLE_LOADERROR;
+
+ if (CLL_DDSURFACE != lmode) CL_Select_Mode(CLL_DDSURFACE);
+
+ if (n_mips_max > mipmaps.size()+1) n_mips_max = mipmaps.size()+1;
+
+ if (!*ImagePtrA[0])
+ {
+ if (flags.raw16bit)
+ {
+ if (n_mips_max>1)
+ *ImagePtrA[0] = (unsigned char *) AllocateMem((2*width+1)*(2*height+1)*2/3+(n_mips_max-3)*2); // slightly more than 4/3 w*h*bytedepth
+ else
+ *ImagePtrA[0] = (unsigned char *) AllocateMem(width*height*2);
+ }
+ else
+ {
+ if (n_mips_max>1)
+ *ImagePtrA[0] = (unsigned char *) AllocateMem((2*width+1)*(2*height+1)*bitsperpixel/24+(n_mips_max-3)*(bitsperpixel/8)); // slightly more than 4/3 w*h*bytedepth
+ else
+ *ImagePtrA[0] = (unsigned char *) AllocateMem(width*height*(bitsperpixel>>3));
+ }
+ }
+ if (!*ImagePtrA[0])
+ return CLE_ALLOCFAIL;
+
+ unsigned int my_bitsperpixel = bitsperpixel;
+
+ switch (imode)
+ {
+ unsigned char * tptr;
+ unsigned short * tSptr;
+ unsigned long * tLptr;
+
+ case CLM_GLOBALPALETTE:
+ case CLM_TLTPALETTE:
+ if (flags.raw16bit)
+ {
+ my_bitsperpixel = 16;
+ tSptr = (unsigned short *)*ImagePtrA[0];
+ if (tSptr)
+ {
+ for (int i=0; i<height; ++i)
+ {
+ memcpy(tSptr,im16raw[i],width*sizeof(unsigned short));
+ tSptr += width;
+ }
+ }
+ }
+ else
+ {
+ tptr = *ImagePtrA[0];
+ if (tptr)
+ {
+ for (int i=0; i<height; ++i)
+ {
+ memcpy(tptr,im8[i],width);
+ tptr += width;
+ }
+ }
+ }
+ break;
+ case CLM_16BIT:
+ switch (bitsperpixel)
+ {
+ case 8:
+ tptr = *ImagePtrA[0];
+ if (tptr)
+ {
+ for (int i=0; i<height; ++i)
+ {
+ unsigned char const * i8ptr = im8[i];
+ for (int j=width; j; --j)
+ {
+ *tptr++ = *i8ptr++;
+ }
+ }
+ }
+ break;
+ case 16:
+ tSptr = (unsigned short *)*ImagePtrA[0];
+ if (tSptr)
+ {
+ for (int i=0; i<height; ++i)
+ {
+ CL_Pixel_16 const * i16ptr = im16[i];
+ for (int j=width; j; --j)
+ {
+ *tSptr++ = *i16ptr++;
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case CLM_24BIT:
+ switch (bitsperpixel)
+ {
+ case 24:
+ tptr = *ImagePtrA[0];
+ if (tptr)
+ {
+ for (int i=0; i<height; ++i)
+ {
+ CL_Pixel_24 const * i24ptr = im24[i];
+ for (int j=width; j; --j)
+ {
+ *tptr++ = i24ptr->b;
+ *tptr++ = i24ptr->g;
+ *tptr++ = i24ptr->r;
+ i24ptr++;
+ }
+ }
+ }
+ break;
+ case 32:
+ tLptr = (unsigned long *)*ImagePtrA[0];
+ if (tLptr)
+ {
+ for (int i=0; i<height; ++i)
+ {
+ CL_Pixel_32 const * i32ptr = im32[i];
+ for (int j=width; j; --j)
+ {
+ *tLptr++ = *i32ptr++;
+ }
+ }
+ }
+ break;
+ }
+ break;
+ default:
+ return CLE_INVALIDDXMODE;
+ }
+
+ // now do mipmaps if avail
+
+ CL_Image * last_mipP = this;
+
+ LIF<CL_Image *> i_mip(&mipmaps);
+ for (int i=1; i<n_mips_max && !i_mip.done(); ++i, i_mip.next())
+ {
+ *ImagePtrA[i] = *ImagePtrA[i-1] + last_mipP->width*last_mipP->height*(my_bitsperpixel>>3);
+ CL_Error thismipmaperror = i_mip()->CopyToScanDrawTexture(&ImagePtrA[i],1);
+ if (CLE_OK != thismipmaperror) return thismipmaperror;
+ last_mipP = i_mip();
+ }
+ return CLE_OK;
+}
+
+
+
+// Direct X interface
+
+void CL_Init_D3DMode(LPDDSURFACEDESC const format)
+{
+ CL_Image::format = format;
+
+ if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
+ {
+ #if QUANTISE_ON_LOAD
+ CL_Image::imode_d3d = CLM_24BIT;
+ #else
+ CL_Image::imode_d3d = CLM_ATTACHEDPALETTE;
+ #endif
+ CL_Image::bitsperpixel_d3d = 8;
+ }
+ else if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
+ {
+ #if QUANTISE_ON_LOAD
+ CL_Image::imode_d3d = CLM_24BIT;
+ #else
+ CL_Image::imode_d3d = CLM_ATTACHEDPALETTE;
+ #endif
+ CL_Image::bitsperpixel_d3d = 4;
+ }
+ else if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2)
+ {
+ #if QUANTISE_ON_LOAD
+ CL_Image::imode_d3d = CLM_24BIT;
+ #else
+ CL_Image::imode_d3d = CLM_ATTACHEDPALETTE;
+ #endif
+ CL_Image::bitsperpixel_d3d = 2;
+ }
+ else if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1)
+ {
+ #if QUANTISE_ON_LOAD
+ CL_Image::imode_d3d = CLM_24BIT;
+ #else
+ CL_Image::imode_d3d = CLM_ATTACHEDPALETTE;
+ #endif
+ CL_Image::bitsperpixel_d3d = 1;
+ }
+ else
+ {
+ CL_Image::bitsperpixel_d3d = format->ddpfPixelFormat.dwRGBBitCount;
+ if (format->ddpfPixelFormat.dwRGBBitCount > 16)
+ {
+ CL_Image::imode_d3d = CLM_32BIT;
+ CL_Pixel_32::f_d3d.Init
+ (
+ format->ddpfPixelFormat.dwRBitMask,
+ format->ddpfPixelFormat.dwGBitMask,
+ format->ddpfPixelFormat.dwBBitMask
+ );
+ }
+ else
+ {
+ CL_Image::imode_d3d = CLM_16BIT;
+ CL_Pixel_16::f_d3d.Init
+ (
+ format->ddpfPixelFormat.dwRBitMask,
+ format->ddpfPixelFormat.dwGBitMask,
+ format->ddpfPixelFormat.dwBBitMask
+ );
+ }
+ }
+ CL_Select_Mode(CLL_D3DTEXTURE);
+}
+
+
+CL_Error CL_Image::CopyToD3DTexture(LPDIRECTDRAWSURFACE * const DDPtrA [], LPVOID * const DDSurfaceA [], int const MemoryType, unsigned int n_mips_max)
+{
+ if (!flags.loaded) return CLE_LOADERROR;
+
+ WaitForVRamReady(VWS_D3DTEXCREATE);
+
+ if (CLL_D3DTEXTURE != lmode) CL_Select_Mode(CLL_D3DTEXTURE);
+
+ LPDIRECTDRAWSURFACE lpDDS;
+ DDSURFACEDESC ddsd;
+ HRESULT ddrval;
+
+ // Check for image being 4 byte aligned
+ // and fail if it is not
+ if (width & 3 || height & 3)
+ {
+ // return error code
+ return CLE_DXERROR;
+ }
+
+
+ // Set up the surface description. starting
+ // with the passed texture format and then
+ // incorporating the information read from the
+ // ppm.
+ memcpy(&ddsd, format, sizeof(DDSURFACEDESC));
+ ddsd.dwSize = sizeof(DDSURFACEDESC);
+ ddsd.dwFlags = (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT);
+ ddsd.ddsCaps.dwCaps = (DDSCAPS_TEXTURE | MemoryType);
+ ddsd.dwHeight = height;
+ ddsd.dwWidth = width;
+
+ if (n_mips_max > mipmaps.size()+1) n_mips_max = mipmaps.size()+1;
+
+ if (n_mips_max>1)
+ {
+ ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
+ ddsd.dwMipMapCount = n_mips_max;
+ }
+
+ // Create the surface
+ ddrval = lpDD->CreateSurface(&ddsd, &lpDDS, NULL);
+
+ LOGDXERR(ddrval);
+ if (ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ return CLE_DXERROR;
+ #endif
+ }
+
+
+ // now do mipmaps if avail
+
+ if (n_mips_max>1)
+ {
+ // We must now traverse the mip-map chain from highest to lowest
+ // resolutions, For each surface AFTER the first one, we must
+ // load a new file, using a name obtained from the mip map number
+
+ int MipMapNum = 0;
+ LPDIRECTDRAWSURFACE lpThisMipMap, lpNextMipMap;
+ DDSCAPS ddsCaps;
+
+
+ lpThisMipMap = lpDDS;
+ // Component Object Model, increase reference count on
+ // mip-map surface by one.
+ lpThisMipMap->AddRef();
+ ddsCaps.dwCaps = (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP);
+ ddrval = DD_OK;
+
+ LIF<CL_Image *> i_mip(&mipmaps);
+
+ CL_Image * last_mipP = this;
+
+ while ((ddrval == DD_OK) && (MipMapNum < n_mips_max)) // both tests in case...
+ {
+ // Call LoadPPMIntoDDSurface with lpThisMipMap, new file name, and
+ // other values.
+
+ *DDSurfaceA[MipMapNum] = last_mipP->CopyToDDSurface(lpThisMipMap);
+
+ // Death trap
+ if (!*DDSurfaceA[MipMapNum])
+ {
+ return CLE_DXERROR;
+ }
+ *DDPtrA[MipMapNum] = lpThisMipMap;
+
+ // Proceed to the next level.
+ // Collect bonus rings.
+ ddrval = lpThisMipMap->GetAttachedSurface(&ddsCaps, &lpNextMipMap);
+ // Necessary to match the manual increment of the reference count on the
+ // COM texture. I think.
+ lpThisMipMap->Release();
+ // ?? lpNextMipMap = lpThisMipMap;
+ lpThisMipMap = lpNextMipMap;
+
+ MipMapNum++;
+ if (!i_mip.done())
+ {
+ last_mipP = i_mip();
+ i_mip.next();
+ }
+ }
+ }
+ else
+ {
+ *DDSurfaceA[0] = CopyToDDSurface(lpDDS);
+
+ if (!*DDSurfaceA[0]) return CLE_DXERROR;
+
+ *DDPtrA[0] = lpDDS;
+ }
+
+ return CLE_OK;
+}
+
+
+CL_Error CL_Image::CopyToDirectDrawSurface(LPDIRECTDRAWSURFACE * const DDPtrA [], LPVOID * const DDSurfaceA [], int const MemoryType, unsigned int n_mips_max)
+{
+ if (!flags.loaded) return CLE_LOADERROR;
+
+ WaitForVRamReady(VWS_DDCREATE);
+
+ if (CLL_DDSURFACE != lmode) CL_Select_Mode(CLL_DDSURFACE);
+
+ LPDIRECTDRAWSURFACE lpDDS;
+ DDSURFACEDESC ddsd;
+ HRESULT ddrval;
+
+ // Check for image being 4 byte aligned
+ // and fail if it is not
+ if (width & 3 || height & 3)
+ {
+ // return error code
+ return CLE_DXERROR;
+ }
+
+ if (n_mips_max > mipmaps.size()+1) n_mips_max = mipmaps.size()+1;
+
+ // Set up the surface description. starting
+ // with the passed texture format and then
+ // incorporating the information read from the
+ // ppm.
+ memset(&ddsd, 0, sizeof ddsd);
+ ddsd.dwSize = sizeof ddsd;
+ ddsd.dwFlags = (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT);
+ // Ensure that created surface has same pixel desription
+ // as primary
+ memcpy(&ddsd.ddpfPixelFormat, &DisplayPixelFormat, sizeof(DDPIXELFORMAT));
+ ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | MemoryType);
+ ddsd.dwHeight = height;
+ ddsd.dwWidth = width;
+
+ if (n_mips_max>1)
+ {
+ ddsd.dwFlags |= DDSD_MIPMAPCOUNT;
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX;
+ ddsd.dwMipMapCount = n_mips_max;
+ }
+
+ // Create the surface
+ ddrval = lpDD->CreateSurface(&ddsd, &lpDDS, NULL);
+
+ LOGDXERR(ddrval);
+ if (ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ return CLE_DXERROR;
+ #endif
+ }
+
+ DDCOLORKEY set_zero = {0,0};
+ ddrval = lpDDS->SetColorKey(DDCKEY_SRCBLT, &set_zero);
+
+ LOGDXERR(ddrval);
+ if(ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ return CLE_DXERROR;
+ #endif
+ }
+
+
+ // now do mipmaps if avail
+
+ if (n_mips_max>1)
+ {
+ // We must now traverse the mip-map chain from highest to lowest
+ // resolutions, For each surface AFTER the first one, we must
+ // load a new file, using a name obtained from the mip map number
+
+ int MipMapNum = 0;
+ LPDIRECTDRAWSURFACE lpThisMipMap, lpNextMipMap;
+ DDSCAPS ddsCaps;
+
+
+ lpThisMipMap = lpDDS;
+ // Component Object Model, increase reference count on
+ // mip-map surface by one.
+ lpThisMipMap->AddRef();
+ ddsCaps.dwCaps = (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP);
+ ddrval = DD_OK;
+
+ LIF<CL_Image *> i_mip(&mipmaps);
+
+ CL_Image * last_mipP = this;
+
+ while ((ddrval == DD_OK) && (MipMapNum < n_mips_max)) // both tests in case...
+ {
+ // Call LoadPPMIntoDDSurface with lpThisMipMap, new file name, and
+ // other values.
+
+ *DDSurfaceA[MipMapNum] = last_mipP->CopyToDDSurface(lpThisMipMap);
+
+ // Death trap
+ if (!*DDSurfaceA[MipMapNum])
+ {
+ return CLE_DXERROR;
+ }
+ *DDPtrA[MipMapNum] = lpThisMipMap;
+
+ // Proceed to the next level.
+ // Collect bonus rings.
+ ddrval = lpThisMipMap->GetAttachedSurface(&ddsCaps, &lpNextMipMap);
+ // Necessary to match the manual increment of the reference count on the
+ // COM texture. I think.
+ lpThisMipMap->Release();
+ // ?? lpNextMipMap = lpThisMipMap;
+ lpThisMipMap = lpNextMipMap;
+
+ MipMapNum++;
+ if (!i_mip.done())
+ {
+ last_mipP = i_mip();
+ i_mip.next();
+ }
+ }
+ }
+ else
+ {
+ *DDSurfaceA[0] = CopyToDDSurface(lpDDS);
+
+ if (!*DDSurfaceA[0]) return CLE_DXERROR;
+
+ *DDPtrA[0] = lpDDS;
+ }
+
+ return CLE_OK;
+}
+
+
+LPVOID CL_Image::CopyToDDSurface(LPDIRECTDRAWSURFACE lpDDS)
+{
+ if (!flags.loaded) return 0;
+
+ LPDIRECTDRAWPALETTE lpDDPPMPal;
+ PALETTEENTRY ppe[256];
+ DDSURFACEDESC ddsd;
+ #if QUANTISE_ON_LOAD
+ D3DCOLOR colors[256];
+ D3DCOLOR c;
+ int color_count;
+ #endif
+ int psize;
+ char *lpC;
+ HRESULT ddrval;
+ unsigned int i, j;
+ unsigned int pcaps;
+
+ // Lock the surface so it can be filled with the PPM file
+
+ memset(&ddsd, 0, sizeof(DDSURFACEDESC));
+ ddsd.dwSize = sizeof(DDSURFACEDESC);
+ ddrval = lpDDS->Lock(NULL, &ddsd, 0, NULL);
+
+ if (!ddsd.lpSurface)
+ {
+ lpDDS->Unlock(NULL);
+ lpDDS->Release();
+ LOGDXSTR("No surface");
+ return 0;
+ }
+
+ LOGDXERR(ddrval);
+ if (ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ return 0;
+ #endif
+ }
+
+ // The method of loading depends on the pixel format of the dest surface
+
+ switch (imode)
+ {
+ case CLM_32BIT:
+ switch (bitsperpixel)
+ {
+ case 32:
+ for (j = 0; j < height; j++)
+ {
+ // Point to next row in texture surface
+ unsigned long * lpLP = (unsigned long*)((char*)ddsd.lpSurface
+ + ddsd.lPitch * j);
+ CL_Pixel_32 * lpP32 = im32[j];
+ for (i = width; i; --i)
+ {
+ *lpLP++ = *lpP32++;
+ }
+ }
+ break;
+ case 24:
+ for (j = 0; j < height; j++)
+ {
+ // Point to next row in texture surface
+ unsigned char * lpCP = (unsigned char*)ddsd.lpSurface
+ + ddsd.lPitch * j;
+ CL_Pixel_32 * lpP32 = im32[j];
+ for (i = width; i; --i)
+ {
+ unsigned long lv = *lpP32++;
+ unsigned char const * lpSrcCP = (unsigned char const *)&lv;
+ // dodgy - makes assumtions about 24-bit values...
+ *lpCP++ = *lpSrcCP++;
+ *lpCP++ = *lpSrcCP++;
+ *lpCP++ = *lpSrcCP++;
+ }
+ }
+ break;
+ default:
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Unlock(NULL);
+ lpDDS->Release();
+ return 0;
+ #endif
+ }
+ lpDDS->Unlock(NULL);
+ break;
+ case CLM_16BIT:
+ switch (bitsperpixel)
+ {
+ case 16:
+ for (j = 0; j < height; j++)
+ {
+ // Point to next row in texture surface
+ unsigned short * lpSP = (unsigned short*)((char*)ddsd.lpSurface
+ + ddsd.lPitch * j);
+ CL_Pixel_16 * lpP16 = im16[j];
+ for (i = width; i; --i)
+ {
+ *lpSP++ = *lpP16++;
+ }
+ }
+ break;
+ case 8:
+ for (j = 0; j < height; j++)
+ {
+ // Point to next row in texture surface
+ unsigned char * lpCP = (unsigned char*)ddsd.lpSurface
+ + ddsd.lPitch * j;
+ CL_Pixel_16 * lpP16 = im16[j];
+ for (i = width; i; --i)
+ {
+ *lpCP++ = *lpP16++;
+ }
+ }
+ break;
+ default:
+ // Everything's gone pear-shaped...
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Unlock(NULL);
+ lpDDS->Release();
+ return 0;
+ #endif
+ }
+ lpDDS->Unlock(NULL);
+ break;
+ case CLM_24BIT:
+ if (24==bitsperpixel)
+ {
+ for (j = 0; j < height; j++)
+ {
+ // Point to next row in surface
+ unsigned char * lpCP = ((unsigned char*)ddsd.lpSurface) + ddsd.lPitch * j;
+ CL_Pixel_24 * lpP24 = im24[j];
+ for (i = 0; i < width; i++)
+ {
+ // making an assumption about the ordering of r,g,b on the video card
+ *lpCP++ = lpP24->b;
+ *lpCP++ = lpP24->g;
+ *lpCP++ = lpP24->r;
+ lpP24++;
+ }
+ }
+ lpDDS->Unlock(NULL);
+ }
+ else
+ {
+ #if QUANTISE_ON_LOAD // Neal's quantize on load stuff
+
+ // Paletted target texture surface
+ psize = 1<<bitsperpixel;
+ color_count = 0; // number of colors in the texture
+ for (j = 0; j < height; j++)
+ {
+ // Point to next row in surface
+ lpC = ((char*)ddsd.lpSurface) + ddsd.lPitch * j;
+ CL_Pixel_24 * lpP24 = im24[j];
+ for (i = 0; i < width; i++, lpP24++)
+ {
+ int k;
+ // Get the next red, green and blue values and turn them into a
+ // D3DCOLOR.
+ c = RGB_MAKE(lpP24->r, lpP24->g, lpP24->b);
+ // Search for this color in a table of colors in this texture
+ for (k = 0; k < color_count; k++)
+ if (c == colors[k]) break;
+ if (k == color_count)
+ {
+ // This is a new color, so add it to the list
+ color_count++;
+ // More than 256 and we fail (8-bit)
+ if (color_count > psize)
+ {
+ color_count--;
+ k = color_count - 1;
+ }
+ colors[k] = c;
+ }
+ // Set the "pixel" value on the surface to be the index into the
+ // color table
+ if (psize<256)
+ {
+ unsigned int bitmask;
+ switch (psize)
+ {
+ default:
+ bitmask = 1;
+ break;
+ case 4:
+ bitmask = 3;
+ break;
+ case 2:
+ bitmask = 7;
+ break;
+ }
+ if ((i & bitmask) == 0)
+ *lpC = (char)(k & (psize-1));
+ else
+ *lpC |= (char)((k & (psize-1)) << (i & (psize-1)));
+ if ((~i & bitmask) == 0)
+ lpC++;
+ }
+ else
+ {
+ *lpC = (char)k;
+ lpC++;
+ }
+ }
+ }
+
+ // Close the file and unlock the surface
+
+ lpDDS->Unlock(NULL);
+
+ if (color_count > psize)
+ {
+ // If there are more than 256 colors, we overran our palette
+ #if debug
+ ReleaseDirect3D();
+ exit(0x321123);
+ #else
+ lpDDS->Release();
+ return 0;
+ #endif
+ }
+
+ // Create a palette with the colors in our color table
+
+ memset(ppe, 0, sizeof(PALETTEENTRY) * 256);
+ for (i = 0; i < color_count; i++)
+ {
+ ppe[i].peRed = (unsigned char)RGB_GETRED(colors[i]);
+ ppe[i].peGreen = (unsigned char)RGB_GETGREEN(colors[i]);
+ ppe[i].peBlue = (unsigned char)RGB_GETBLUE(colors[i]);
+ }
+
+ // Set all remaining entry flags to D3DPAL_RESERVED, which are ignored by
+ // the renderer.
+
+ for (; i < 256; i++)
+ ppe[i].peFlags = D3DPAL_RESERVED;
+
+ // Create the palette with the DDPCAPS_ALLOW256 flag because we want to
+ // have access to all entries.
+
+ switch (bitsperpixel)
+ {
+ default:
+ pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
+ break;
+ case 4:
+ pcaps = DDPCAPS_4BIT;
+ break;
+ case 2:
+ pcaps = DDPCAPS_2BIT;
+ break;
+ case 1:
+ pcaps = DDPCAPS_1BIT;
+ break;
+ }
+
+ ddrval = lpDD->CreatePalette
+ (DDPCAPS_INITIALIZE | pcaps,
+ ppe, &lpDDPPMPal, NULL);
+ LOGDXERR(ddrval);
+
+ if (ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ return 0;
+ #endif
+ }
+
+ // Finally, bind the palette to the surface
+
+ ddrval = lpDDS->SetPalette(lpDDPPMPal);
+ LOGDXERR(ddrval);
+ if (ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ lpDDPPMPal->Release();
+ return 0;
+ #endif
+ }
+
+ lpDDPPMPal->Release();
+ }
+ break;
+ #else
+ // Everything's gone pear-shaped...
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Unlock(NULL);
+ lpDDS->Release();
+ return 0;
+ #endif
+ }
+ break;
+ case CLM_ATTACHEDPALETTE:
+ #endif
+ case CLM_GLOBALPALETTE:
+ case CLM_TLTPALETTE:
+ // Paletted target texture surface
+
+ psize = 1<<bitsperpixel;
+ ReducePalette(psize); // will do nothing if palette is already small enough
+ // ignore returned error code, because I don't care if it failed
+ for (j = 0; j < height; j++)
+ {
+ // Point to next row in surface
+ lpC = ((char*)ddsd.lpSurface) + ddsd.lPitch * j;
+ unsigned char * lpP8 = im8[j];
+
+ if (psize<256)
+ {
+ unsigned int bitmask;
+ unsigned int nextpixelshift;
+ switch (psize)
+ {
+ default:
+ nextpixelshift = 2;
+ break;
+ case 4:
+ nextpixelshift = 1;
+ break;
+ case 2:
+ nextpixelshift = 0;
+ break;
+ }
+ bitmask = 7 >> nextpixelshift;
+ for (i = 0; i < width; i++)
+ {
+ unsigned char k = *lpP8++;
+ // Set the "pixel" value on the surface to be the index into the
+ // color table
+ if ((i & bitmask) == 0)
+ *lpC = (char) (k & (psize-1));
+ else
+ *lpC |= (char) ((k & (psize-1)) << ((i & bitmask)<<nextpixelshift));
+ if ((~i & bitmask) == 0)
+ lpC++;
+ }
+ }
+ else
+ {
+ memcpy(lpC,lpP8,width);
+ }
+ }
+
+ // Close the file and unlock the surface
+
+ lpDDS->Unlock(NULL);
+
+ // Create a palette with the colors in our color table
+
+ memset(ppe, 0, sizeof(PALETTEENTRY) * 256);
+ for (i = 0; i < palette_size; i++)
+ {
+ ppe[i].peRed = palette[i].r;
+ ppe[i].peGreen = palette[i].g;
+ ppe[i].peBlue = palette[i].b;
+ }
+
+ // Set all remaining entry flags to D3DPAL_RESERVED, which are ignored by
+ // the renderer.
+
+ for (; i < 256; i++)
+ ppe[i].peFlags = D3DPAL_RESERVED;
+
+ // Create the palette with the DDPCAPS_ALLOW256 flag because we want to
+ // have access to all entries.
+
+ switch (bitsperpixel)
+ {
+ default:
+ pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
+ break;
+ case 4:
+ pcaps = DDPCAPS_4BIT;
+ break;
+ case 2:
+ pcaps = DDPCAPS_2BIT;
+ break;
+ case 1:
+ pcaps = DDPCAPS_1BIT;
+ break;
+ }
+
+ ddrval = lpDD->CreatePalette
+ (DDPCAPS_INITIALIZE | pcaps,
+ ppe, &lpDDPPMPal, NULL);
+ LOGDXERR(ddrval);
+
+ if (ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ return 0;
+ #endif
+ }
+
+ // Finally, bind the palette to the surface
+
+ ddrval = lpDDS->SetPalette(lpDDPPMPal);
+ LOGDXERR(ddrval);
+ if (ddrval != DD_OK)
+ {
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Release();
+ lpDDPPMPal->Release();
+ return 0;
+ #endif
+ }
+
+ lpDDPPMPal->Release();
+ break;
+ default:
+ // Everything's gone pear-shaped...
+ #if debug
+ ReleaseDirect3D();
+ exit(ddrval);
+ #else
+ lpDDS->Unlock(NULL);
+ lpDDS->Release();
+ return 0;
+ #endif
+
+
+ }
+
+ return ddsd.lpSurface;
+}
+
+