#ifdef JA2_PRECOMPILED_HEADERS #include "JA2 SGP ALL.H" #elif defined( WIZ8_PRECOMPILED_HEADERS ) #include "WIZ8 SGP ALL.H" #else #include #include #include "pcx.h" #include "memman.h" #include "fileman.h" #endif // Local typedefs #define PCX_NORMAL 1 #define PCX_RLE 2 #define PCX_256COLOR 4 #define PCX_TRANSPARENT 8 #define PCX_CLIPPED 16 #define PCX_REALIZEPALETTE 32 #define PCX_X_CLIPPING 64 #define PCX_Y_CLIPPING 128 #define PCX_NOTLOADED 256 #define PCX_ERROROPENING 1 #define PCX_INVALIDFORMAT 2 #define PCX_INVALIDLEN 4 #define PCX_OUTOFMEMORY 8 BOOLEAN SetPcxPalette( PcxObject *pCurrentPcxObject, HIMAGE hImage ); BOOLEAN BlitPcxToBuffer( PcxObject *pCurrentPcxObject, UINT8 *pBuffer, UINT16 usBufferWidth, UINT16 usBufferHeight, UINT16 usX, UINT16 usY, BOOLEAN fTransp); PcxObject *LoadPcx(UINT8 *pFilename); BOOLEAN LoadPCXFileToImage( HIMAGE hImage, UINT16 fContents ) { PcxObject *pPcxObject; // First Load a PCX Image pPcxObject = LoadPcx( hImage->ImageFile ); if ( pPcxObject == NULL ) { return( FALSE ); } // Set some header information hImage->usWidth = pPcxObject->usWidth; hImage->usHeight = pPcxObject->usHeight; hImage->ubBitDepth = 8; hImage->fFlags = hImage->fFlags | fContents; // Read and allocate bitmap block if requested if ( fContents & IMAGE_BITMAPDATA ) { // Allocate memory for buffer hImage->p8BPPData = MemAlloc( hImage->usWidth * hImage->usHeight ); if ( !BlitPcxToBuffer( pPcxObject, hImage->p8BPPData, hImage->usWidth, hImage->usHeight, 0, 0, FALSE ) ) { MemFree( hImage->p8BPPData ); return( FALSE ); } } if ( fContents & IMAGE_PALETTE ) { SetPcxPalette( pPcxObject, hImage ); // Create 16 BPP palette if flags and BPP justify hImage->pui16BPPPalette = Create16BPPPalette( hImage->pPalette ); } // Free and remove pcx object MemFree( pPcxObject->pPcxBuffer ); MemFree( pPcxObject ); return( TRUE ); } PcxObject *LoadPcx(UINT8 *pFilename) { PcxHeader Header; PcxObject *pCurrentPcxObject; HWFILE hFileHandle; UINT32 uiFileSize; UINT8 *pPcxBuffer; // Open and read in the file if ((hFileHandle = FileOpen(pFilename, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE)) == 0) { // damn we failed to open the file return NULL; } uiFileSize = FileGetSize(hFileHandle); if (uiFileSize == 0) { // we failed to size up the file return NULL; } // Create enw pCX object pCurrentPcxObject = MemAlloc( sizeof( PcxObject ) ); if ( pCurrentPcxObject == NULL ) { return( NULL ); } pCurrentPcxObject->pPcxBuffer = MemAlloc( uiFileSize - (sizeof(PcxHeader) + 768) ); if ( pCurrentPcxObject->pPcxBuffer == NULL ) { return( NULL ); } // Ok we now have a file handle, so let's read in the data FileRead(hFileHandle, &Header, sizeof(PcxHeader), NULL); if ((Header.ubManufacturer != 10)||(Header.ubEncoding != 1)) { // We have an invalid pcx format // Delete the object MemFree( pCurrentPcxObject->pPcxBuffer ); MemFree( pCurrentPcxObject ); return( NULL ); } if (Header.ubBitsPerPixel == 8) { pCurrentPcxObject->usPcxFlags = PCX_256COLOR; } else { pCurrentPcxObject->usPcxFlags = 0; } pCurrentPcxObject->usWidth = 1 + (Header.usRight - Header.usLeft); pCurrentPcxObject->usHeight = 1 + (Header.usBottom - Header.usTop); pCurrentPcxObject->uiBufferSize = uiFileSize - 768 - sizeof(PcxHeader); // We are ready to read in the pcx buffer data. Therefore we must lock the buffer pPcxBuffer = pCurrentPcxObject->pPcxBuffer; FileRead(hFileHandle, pPcxBuffer, pCurrentPcxObject->uiBufferSize, NULL); // Read in the palette FileRead(hFileHandle, &(pCurrentPcxObject->ubPalette[0]), 768, NULL); // Close file FileClose( hFileHandle ); return pCurrentPcxObject; } BOOLEAN BlitPcxToBuffer( PcxObject *pCurrentPcxObject, UINT8 *pBuffer, UINT16 usBufferWidth, UINT16 usBufferHeight, UINT16 usX, UINT16 usY, BOOLEAN fTransp) { UINT8 *pPcxBuffer; UINT8 ubRepCount; UINT16 usMaxX, usMaxY; UINT32 uiImageSize; UINT8 ubCurrentByte = 0; UINT8 ubMode; UINT16 usCurrentX, usCurrentY; UINT32 uiOffset, uiIndex; UINT32 uiNextLineOffset, uiStartOffset, uiCurrentOffset; pPcxBuffer = pCurrentPcxObject->pPcxBuffer; if (((pCurrentPcxObject->usWidth + usX) == usBufferWidth)&&((pCurrentPcxObject->usHeight + usY)== usBufferHeight)) { // Pre-compute PCX blitting aspects. uiImageSize = usBufferWidth * usBufferHeight; ubMode = PCX_NORMAL; uiOffset = 0; ubRepCount = 0; // Blit Pcx object. Two main cases, one for transparency (0's are skipped and for without transparency. if (fTransp == TRUE) { for (uiIndex = 0; uiIndex < uiImageSize; uiIndex++) { if (ubMode == PCX_NORMAL) { ubCurrentByte = *(pPcxBuffer + uiOffset++); if (ubCurrentByte > 0x0BF) { ubRepCount = ubCurrentByte & 0x03F; ubCurrentByte = *(pPcxBuffer + uiOffset++); if (--ubRepCount > 0) { ubMode = PCX_RLE; } } } else { if (--ubRepCount == 0) { ubMode = PCX_NORMAL; } } if (ubCurrentByte != 0) { *(pBuffer + uiIndex) = ubCurrentByte; } } } else { for (uiIndex = 0; uiIndex < uiImageSize; uiIndex++) { if (ubMode == PCX_NORMAL) { ubCurrentByte = *(pPcxBuffer + uiOffset++); if (ubCurrentByte > 0x0BF) { ubRepCount = ubCurrentByte & 0x03F; ubCurrentByte = *(pPcxBuffer + uiOffset++); if (--ubRepCount > 0) { ubMode = PCX_RLE; } } } else { if (--ubRepCount == 0) { ubMode = PCX_NORMAL; } } *(pBuffer + uiIndex) = ubCurrentByte; } } } else { // Pre-compute PCX blitting aspects. if ((pCurrentPcxObject->usWidth + usX) >= usBufferWidth) { pCurrentPcxObject->usPcxFlags |= PCX_X_CLIPPING; usMaxX = usBufferWidth - 1; } else { usMaxX = pCurrentPcxObject->usWidth + usX; } if ((pCurrentPcxObject->usHeight + usY) >= usBufferHeight) { pCurrentPcxObject->usPcxFlags |= PCX_Y_CLIPPING; uiImageSize = pCurrentPcxObject->usWidth * (usBufferHeight - usY); usMaxY = usBufferHeight - 1; } else { uiImageSize = pCurrentPcxObject->usWidth * pCurrentPcxObject->usHeight; usMaxY = pCurrentPcxObject->usHeight + usY; } ubMode = PCX_NORMAL; uiOffset = 0; ubRepCount = 0; usCurrentX = usX; usCurrentY = usY; // Blit Pcx object. Two main cases, one for transparency (0's are skipped and for without transparency. if (fTransp == TRUE) { for (uiIndex = 0; uiIndex < uiImageSize; uiIndex++) { if (ubMode == PCX_NORMAL) { ubCurrentByte = *(pPcxBuffer + uiOffset++); if (ubCurrentByte > 0x0BF) { ubRepCount = ubCurrentByte & 0x03F; ubCurrentByte = *(pPcxBuffer + uiOffset++); if (--ubRepCount > 0) { ubMode = PCX_RLE; } } } else { if (--ubRepCount == 0) { ubMode = PCX_NORMAL; } } if (ubCurrentByte != 0) { *(pBuffer + (usCurrentY*usBufferWidth) + usCurrentX) = ubCurrentByte; } usCurrentX++; if (usCurrentX > usMaxX) { usCurrentX = usX; usCurrentY++; } } } else { uiStartOffset = (usCurrentY*usBufferWidth) + usCurrentX; uiNextLineOffset = uiStartOffset + usBufferWidth; uiCurrentOffset = uiStartOffset; for (uiIndex = 0; uiIndex < uiImageSize; uiIndex++) { if (ubMode == PCX_NORMAL) { ubCurrentByte = *(pPcxBuffer + uiOffset++); if (ubCurrentByte > 0x0BF) { ubRepCount = ubCurrentByte & 0x03F; ubCurrentByte = *(pPcxBuffer + uiOffset++); if (--ubRepCount > 0) { ubMode = PCX_RLE; } } } else { if (--ubRepCount == 0) { ubMode = PCX_NORMAL; } } if (usCurrentX < usMaxX) { // We are within the visible bounds so we write the byte to buffer *(pBuffer + uiCurrentOffset) = ubCurrentByte; uiCurrentOffset++; usCurrentX++; } else { if ((uiCurrentOffset + 1)< uiNextLineOffset) { // Increment the uiCurrentOffset uiCurrentOffset++; } else { // Go to next line usCurrentX = usX; usCurrentY++; if (usCurrentY > usMaxY) { break; } uiStartOffset = (usCurrentY*usBufferWidth) + usCurrentX; uiNextLineOffset = uiStartOffset + usBufferWidth; uiCurrentOffset = uiStartOffset; } } } } } return( TRUE ); } BOOLEAN SetPcxPalette( PcxObject *pCurrentPcxObject, HIMAGE hImage ) { UINT16 Index; UINT8 *pubPalette; pubPalette = &(pCurrentPcxObject->ubPalette[0]); // Allocate memory for palette hImage->pPalette = MemAlloc( sizeof( SGPPaletteEntry ) * 256 ); if ( hImage->pPalette == NULL ) { return( FALSE ); } // Initialize the proper palette entries for (Index = 0; Index < 256; Index++) { hImage->pPalette[ Index ].peRed = *(pubPalette+(Index*3)); hImage->pPalette[ Index ].peGreen = *(pubPalette+(Index*3)+1); hImage->pPalette[ Index ].peBlue = *(pubPalette+(Index*3)+2); hImage->pPalette[ Index ].peFlags = 0; } return TRUE; }