diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/xwad/lbmlib.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/xwad/lbmlib.cpp')
| -rw-r--r-- | utils/xwad/lbmlib.cpp | 741 |
1 files changed, 741 insertions, 0 deletions
diff --git a/utils/xwad/lbmlib.cpp b/utils/xwad/lbmlib.cpp new file mode 100644 index 0000000..c3dfad8 --- /dev/null +++ b/utils/xwad/lbmlib.cpp @@ -0,0 +1,741 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +// lbmlib.c + +#include <WINDOWS.H> +#include <STDIO.H> +#include "lbmlib.h" +#include "goldsrc_standin.h" + + + +/* +============================================================================ + + LBM STUFF + +============================================================================ +*/ + + +#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24)) +#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24)) +#define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24)) +#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24)) +#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24)) +#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24)) + + +bmhd_t bmhd; + +int Align (int l) +{ + if (l&1) + return l+1; + return l; +} + + + +/* +================ += += LBMRLEdecompress += += Source must be evenly aligned! += +================ +*/ + +byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth) +{ + int count; + byte b,rept; + + count = 0; + + do + { + rept = *source++; + + if (rept > 0x80) + { + rept = (rept^0xff)+2; + b = *source++; + memset(unpacked,b,rept); + unpacked += rept; + } + else if (rept < 0x80) + { + rept++; + memcpy(unpacked,source,rept); + unpacked += rept; + source += rept; + } + else + rept = 0; // rept of 0x80 is NOP + + count += rept; + + } while (count<bpwidth); + + if (count>bpwidth) + Error ("Decompression exceeded width!\n"); + + + return source; +} + + +#define BPLANESIZE 128 +byte bitplanes[9][BPLANESIZE]; // max size 1024 by 9 bit planes + + +/* +================= += += MungeBitPlanes8 += += This destroys the bit plane data! += +================= +*/ + +void MungeBitPlanes8 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes8 not rewritten!"); +#if 0 +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm shl [BYTE PTR bitplanes + BPLANESIZE*7 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*6 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*5 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*4 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + + +void MungeBitPlanes4 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes4 not rewritten!"); +#if 0 + +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + + +void MungeBitPlanes2 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes2 not rewritten!"); +#if 0 +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + + +void MungeBitPlanes1 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes1 not rewritten!"); +#if 0 +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + +int LoadBMP (const char* szFile, BYTE** ppbBits, BYTE** ppbPalette) +{ + int i, rc = 0; + FILE *pfile = NULL; + BITMAPFILEHEADER bmfh; + BITMAPINFOHEADER bmih; + RGBQUAD rgrgbPalette[256]; + ULONG cbBmpBits; + BYTE* pbBmpBits; + byte *pb, *pbPal = NULL; + ULONG cbPalBytes; + ULONG biTrueWidth; + + // Bogus parameter check + if (!(ppbPalette != NULL && ppbBits != NULL)) + { fprintf(stderr, "invalid BMP file\n"); rc = -1000; goto GetOut; } + + // File exists? + if ((pfile = fopen(szFile, "rb")) == NULL) + { fprintf(stderr, "unable to open BMP file\n"); rc = -1; goto GetOut; } + + // Read file header + if (fread(&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1) + { rc = -2; goto GetOut; } + + // Bogus file header check + if (!(bmfh.bfReserved1 == 0 && bmfh.bfReserved2 == 0)) + { rc = -2000; goto GetOut; } + + // Read info header + if (fread(&bmih, sizeof bmih, 1/*count*/, pfile) != 1) + { rc = -3; goto GetOut; } + + // Bogus info header check + if (!(bmih.biSize == sizeof bmih && bmih.biPlanes == 1)) + { fprintf(stderr, "invalid BMP file header\n"); rc = -3000; goto GetOut; } + + // Bogus bit depth? Only 8-bit supported. + if (bmih.biBitCount != 8) + { fprintf(stderr, "BMP file not 8 bit\n"); rc = -4; goto GetOut; } + + // Bogus compression? Only non-compressed supported. + if (bmih.biCompression != BI_RGB) + { fprintf(stderr, "invalid BMP compression type\n"); rc = -5; goto GetOut; } + + // Figure out how many entires are actually in the table + if (bmih.biClrUsed == 0) + { + bmih.biClrUsed = 256; + cbPalBytes = (1 << bmih.biBitCount) * sizeof( RGBQUAD ); + } + else + { + cbPalBytes = bmih.biClrUsed * sizeof( RGBQUAD ); + } + + // Read palette (bmih.biClrUsed entries) + if (fread(rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1) + { rc = -6; goto GetOut; } + + // convert to a packed 768 byte palette + pbPal = (unsigned char*)malloc(768); + if (pbPal == NULL) + { rc = -7; goto GetOut; } + + pb = pbPal; + + // Copy over used entries + for (i = 0; i < (int)bmih.biClrUsed; i++) + { + *pb++ = rgrgbPalette[i].rgbRed; + *pb++ = rgrgbPalette[i].rgbGreen; + *pb++ = rgrgbPalette[i].rgbBlue; + } + + // Fill in unused entires will 0,0,0 + for (i = bmih.biClrUsed; i < 256; i++) + { + *pb++ = 0; + *pb++ = 0; + *pb++ = 0; + } + + // Read bitmap bits (remainder of file) + cbBmpBits = bmfh.bfSize - ftell(pfile); + pb = (unsigned char*)malloc(cbBmpBits); + if (fread(pb, cbBmpBits, 1/*count*/, pfile) != 1) + { rc = -7; goto GetOut; } + + pbBmpBits = (unsigned char*)malloc(cbBmpBits); + + // data is actually stored with the width being rounded up to a multiple of 4 + biTrueWidth = (bmih.biWidth + 3) & ~3; + + // reverse the order of the data. + pb += (bmih.biHeight - 1) * biTrueWidth; + for(i = 0; i < bmih.biHeight; i++) + { + memmove(&pbBmpBits[biTrueWidth * i], pb, biTrueWidth); + pb -= biTrueWidth; + } + + pb += biTrueWidth; + free(pb); + + bmhd.w = (WORD)bmih.biWidth; + bmhd.h = (WORD)bmih.biHeight; + // Set output parameters + *ppbPalette = pbPal; + *ppbBits = pbBmpBits; + +GetOut: + if (pfile) + fclose(pfile); + + return rc; +} + + +int WriteBMPfile (char *szFile, byte *pbBits, int width, int height, byte *pbPalette) +{ + int i, rc = 0; + FILE *pfile = NULL; + BITMAPFILEHEADER bmfh; + BITMAPINFOHEADER bmih; + RGBQUAD rgrgbPalette[256]; + ULONG cbBmpBits; + BYTE* pbBmpBits; + byte *pb, *pbPal = NULL; + ULONG cbPalBytes; + ULONG biTrueWidth; + + // Bogus parameter check + if (!(pbPalette != NULL && pbBits != NULL)) + { rc = -1000; goto GetOut; } + + // File exists? + if ((pfile = fopen(szFile, "wb")) == NULL) + { rc = -1; goto GetOut; } + + biTrueWidth = ((width + 3) & ~3); + cbBmpBits = biTrueWidth * height; + cbPalBytes = 256 * sizeof( RGBQUAD ); + + // Bogus file header check + bmfh.bfType = MAKEWORD( 'B', 'M' ); + bmfh.bfSize = sizeof bmfh + sizeof bmih + cbBmpBits + cbPalBytes; + bmfh.bfReserved1 = 0; + bmfh.bfReserved2 = 0; + bmfh.bfOffBits = sizeof bmfh + sizeof bmih + cbPalBytes; + + // Write file header + if (fwrite(&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1) + { rc = -2; goto GetOut; } + + // Size of structure + bmih.biSize = sizeof bmih; + // Width + bmih.biWidth = biTrueWidth; + // Height + bmih.biHeight = height; + // Only 1 plane + bmih.biPlanes = 1; + // Only 8-bit supported. + bmih.biBitCount = 8; + // Only non-compressed supported. + bmih.biCompression = BI_RGB; + bmih.biSizeImage = 0; + + // huh? + bmih.biXPelsPerMeter = 0; + bmih.biYPelsPerMeter = 0; + + // Always full palette + bmih.biClrUsed = 256; + bmih.biClrImportant = 0; + + // Write info header + if (fwrite(&bmih, sizeof bmih, 1/*count*/, pfile) != 1) + { rc = -3; goto GetOut; } + + + // convert to expanded palette + pb = pbPalette; + + // Copy over used entries + for (i = 0; i < (int)bmih.biClrUsed; i++) + { + rgrgbPalette[i].rgbRed = *pb++; + rgrgbPalette[i].rgbGreen = *pb++; + rgrgbPalette[i].rgbBlue = *pb++; + rgrgbPalette[i].rgbReserved = 0; + } + + // Write palette (bmih.biClrUsed entries) + cbPalBytes = bmih.biClrUsed * sizeof( RGBQUAD ); + if (fwrite(rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1) + { rc = -6; goto GetOut; } + + + pbBmpBits = (unsigned char*)malloc(cbBmpBits); + + pb = pbBits; + // reverse the order of the data. + pb += (height - 1) * width; + for(i = 0; i < bmih.biHeight; i++) + { + memmove(&pbBmpBits[biTrueWidth * i], pb, width); + pb -= width; + } + + // Write bitmap bits (remainder of file) + if (fwrite(pbBmpBits, cbBmpBits, 1/*count*/, pfile) != 1) + { rc = -7; goto GetOut; } + + free(pbBmpBits); + +GetOut: + if (pfile) + fclose(pfile); + + return rc; +} + +/* +================= += += LoadLBM += +================= +*/ + +void LoadLBM (char *filename, byte **picture, byte **palette) +{ + byte *LBMbuffer, *picbuffer, *cmapbuffer; + int y,p,planes; + byte *LBM_P, *LBMEND_P; + byte *pic_p; + byte *body_p; + unsigned rowsize; + + int formtype,formlength; + int chunktype,chunklength; + void (*mungecall) (int, byte *); + +// qiet compiler warnings + picbuffer = NULL; + cmapbuffer = NULL; + mungecall = NULL; + +// +// load the LBM +// + LoadFile (filename, (void **)&LBMbuffer); + +// +// parse the LBM header +// + LBM_P = LBMbuffer; + if ( *(int *)LBMbuffer != LittleLong(FORMID) ) + Error ("No FORM ID at start of file!\n"); + + LBM_P += 4; + formlength = BigLong( *(int *)LBM_P ); + LBM_P += 4; + LBMEND_P = LBM_P + Align(formlength); + + formtype = LittleLong(*(int *)LBM_P); + + if (formtype != ILBMID && formtype != PBMID) + Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff + ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); + + LBM_P += 4; + +// +// parse chunks +// + + while (LBM_P < LBMEND_P) + { + chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24); + LBM_P += 4; + chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24); + LBM_P += 4; + + switch ( chunktype ) + { + case BMHDID: + memcpy (&bmhd,LBM_P,sizeof(bmhd)); + bmhd.w = BigShort(bmhd.w); + bmhd.h = BigShort(bmhd.h); + bmhd.x = BigShort(bmhd.x); + bmhd.y = BigShort(bmhd.y); + bmhd.pageWidth = BigShort(bmhd.pageWidth); + bmhd.pageHeight = BigShort(bmhd.pageHeight); + break; + + case CMAPID: + cmapbuffer = (unsigned char*)malloc (768); + memset (cmapbuffer, 0, 768); + memcpy (cmapbuffer, LBM_P, chunklength); + break; + + case BODYID: + body_p = LBM_P; + + pic_p = picbuffer = (unsigned char*)malloc (bmhd.w*bmhd.h); + if (formtype == PBMID) + { + // + // unpack PBM + // + for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w) + { + if (bmhd.compression == cm_rle1) + body_p = LBMRLEDecompress ((byte *)body_p + , pic_p , bmhd.w); + else if (bmhd.compression == cm_none) + { + memcpy (pic_p,body_p,bmhd.w); + body_p += Align(bmhd.w); + } + } + + } + else + { + // + // unpack ILBM + // + planes = bmhd.nPlanes; + if (bmhd.masking == ms_mask) + planes++; + rowsize = (bmhd.w+15)/16 * 2; + switch (bmhd.nPlanes) + { + case 1: + mungecall = MungeBitPlanes1; + break; + case 2: + mungecall = MungeBitPlanes2; + break; + case 4: + mungecall = MungeBitPlanes4; + break; + case 8: + mungecall = MungeBitPlanes8; + break; + default: + Error ("Can't munge %i bit planes!\n",bmhd.nPlanes); + } + + for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w) + { + for (p=0 ; p<planes ; p++) + if (bmhd.compression == cm_rle1) + body_p = LBMRLEDecompress ((byte *)body_p + , bitplanes[p] , rowsize); + else if (bmhd.compression == cm_none) + { + memcpy (bitplanes[p],body_p,rowsize); + body_p += rowsize; + } + + mungecall (bmhd.w , pic_p); + } + } + break; + } + + LBM_P += Align(chunklength); + } + + free (LBMbuffer); + + *picture = picbuffer; + *palette = cmapbuffer; +} + + +/* +============================================================================ + + WRITE LBM + +============================================================================ +*/ + +/* +============== += += WriteLBMfile += +============== +*/ + +void WriteLBMfile (char *filename, byte *data, int width, int height, byte *palette) +{ + byte *lbm, *lbmptr; + int *formlength, *bmhdlength, *cmaplength, *bodylength; + int length; + bmhd_t basebmhd; + + lbm = lbmptr = (unsigned char*)malloc (width*height+1000); + +// +// start FORM +// + *lbmptr++ = 'F'; + *lbmptr++ = 'O'; + *lbmptr++ = 'R'; + *lbmptr++ = 'M'; + + formlength = (int*)lbmptr; + lbmptr+=4; // leave space for length + + *lbmptr++ = 'P'; + *lbmptr++ = 'B'; + *lbmptr++ = 'M'; + *lbmptr++ = ' '; + +// +// write BMHD +// + *lbmptr++ = 'B'; + *lbmptr++ = 'M'; + *lbmptr++ = 'H'; + *lbmptr++ = 'D'; + + bmhdlength = (int *)lbmptr; + lbmptr+=4; // leave space for length + + memset (&basebmhd,0,sizeof(basebmhd)); + basebmhd.w = BigShort((short)width); + basebmhd.h = BigShort((short)height); + basebmhd.nPlanes = (BYTE)BigShort(8); + basebmhd.xAspect = (BYTE)BigShort(5); + basebmhd.yAspect = (BYTE)BigShort(6); + basebmhd.pageWidth = BigShort((short)width); + basebmhd.pageHeight = BigShort((short)height); + + memcpy (lbmptr,&basebmhd,sizeof(basebmhd)); + lbmptr += sizeof(basebmhd); + + length = lbmptr-(byte *)bmhdlength-4; + *bmhdlength = BigLong(length); + if (length&1) + *lbmptr++ = 0; // pad chunk to even offset + +// +// write CMAP +// + *lbmptr++ = 'C'; + *lbmptr++ = 'M'; + *lbmptr++ = 'A'; + *lbmptr++ = 'P'; + + cmaplength = (int *)lbmptr; + lbmptr+=4; // leave space for length + + memcpy (lbmptr,palette,768); + lbmptr += 768; + + length = lbmptr-(byte *)cmaplength-4; + *cmaplength = BigLong(length); + if (length&1) + *lbmptr++ = 0; // pad chunk to even offset + +// +// write BODY +// + *lbmptr++ = 'B'; + *lbmptr++ = 'O'; + *lbmptr++ = 'D'; + *lbmptr++ = 'Y'; + + bodylength = (int *)lbmptr; + lbmptr+=4; // leave space for length + + memcpy (lbmptr,data,width*height); + lbmptr += width*height; + + length = lbmptr-(byte *)bodylength-4; + *bodylength = BigLong(length); + if (length&1) + *lbmptr++ = 0; // pad chunk to even offset + +// +// done +// + length = lbmptr-(byte *)formlength-4; + *formlength = BigLong(length); + if (length&1) + *lbmptr++ = 0; // pad chunk to even offset + +// +// write output file +// + SaveFile (filename, lbm, lbmptr-lbm); + free (lbm); +} + |