static BOOL DLL_CALLCONV Validate(FreeImageIO *io, fi_handle handle) { DWORD type = 0; // read chunk type io->read_proc(&type, 4, 1, handle); #ifndef FREEIMAGE_BIGENDIAN SwapLong(&type); #endif if(type != ID_FORM) return FALSE; // skip 4 bytes io->read_proc(&type, 4, 1, handle); // read chunk type io->read_proc(&type, 4, 1, handle); #ifndef FREEIMAGE_BIGENDIAN SwapLong(&type); #endif // File format : ID_PBM = Packed Bitmap, ID_ILBM = Interleaved Bitmap return (type == ID_ILBM) || (type == ID_PBM); }
// // R_LoadVoxelResource // // Loads a .vox-format voxel model into an rvoxelmodel_t structure. // rvoxelmodel_t *R_LoadVoxelResource(int lumpnum) { rvoxelmodel_t *model = NULL; byte *buffer = NULL, *rover = NULL; int lumplen = W_LumpLength(lumpnum); int xsize, ysize, zsize, voxsize; int i; // minimum size test if(lumplen < 12) return NULL; // cache the lump rover = buffer = (byte *)(wGlobalDir.cacheLumpNum(lumpnum, PU_STATIC)); // get sizes xsize = SwapLong(*(int32_t *)rover); rover += 4; ysize = SwapLong(*(int32_t *)rover); rover += 4; zsize = SwapLong(*(int32_t *)rover); rover += 4; voxsize = xsize*ysize*zsize; // true size test if(lumplen < 12 + voxsize + 768) { Z_ChangeTag(buffer, PU_CACHE); return NULL; } // create the model and its voxel buffer model = (rvoxelmodel_t *)(Z_Calloc(1, sizeof(rvoxelmodel_t), PU_RENDERER, NULL)); model->voxels = (byte *)(Z_Calloc(voxsize, sizeof(byte), PU_RENDERER, NULL)); model->xsize = xsize; model->ysize = ysize; model->zsize = zsize; // get voxel data memcpy(model->voxels, rover, voxsize); rover += voxsize; // get original palette data memcpy(model->palette, rover, 768); // transform palette data into 0-255 range // TODO: verify color component order for(i = 0; i < 768; i++) model->palette[i] <<= 2; // TODO: run V_FindBestColor to create translated palette? // done with lump Z_ChangeTag(buffer, PU_CACHE); return model; }
static void SwapFileHeader(BITMAPFILEHEADER *header) { SwapShort(&header->bfType); SwapLong(&header->bfSize); SwapShort(&header->bfReserved1); SwapShort(&header->bfReserved2); SwapLong(&header->bfOffBits); }
static void SwapHeader(SGIHeader *header) { SwapShort(&header->magic); SwapShort(&header->dimension); SwapShort(&header->xsize); SwapShort(&header->ysize); SwapShort(&header->zsize); SwapLong((DWORD*)&header->pixmin); SwapLong((DWORD*)&header->pixmax); SwapLong((DWORD*)&header->colormap); }
static void F_DrawPatchCol(int x, patch_t* patch, int col) { const column_t* column = (const column_t*)((byte*) patch + SwapLong(patch->columnofs[col])); // step through the posts in a column if (hires) while (column->topdelta != 0xff) { byte* desttop = screens[0] + x * 2; const byte* source = (byte*) column + 3; byte* dest = desttop + column->topdelta * SCREENWIDTH * 4; int count = column->length; for (; count--; dest += SCREENWIDTH * 4) dest[0] = dest[SCREENWIDTH * 2] = dest[1] = dest[SCREENWIDTH * 2 + 1] = *source++; column = (column_t*)(source + 1); } else while (column->topdelta != 0xff) { byte* desttop = screens[0] + x; const byte* source = (byte*) column + 3; byte* dest = desttop + column->topdelta * SCREENWIDTH; int count = column->length; for (; count--; dest += SCREENWIDTH) * dest = *source++; column = (column_t*)(source + 1); } }
static void SwapCoreHeader(BITMAPCOREHEADER *header) { SwapLong(&header->bcSize); SwapShort(&header->bcWidth); SwapShort(&header->bcHeight); SwapShort(&header->bcPlanes); SwapShort(&header->bcBitCnt); }
static void SwapOS21XHeader(BITMAPINFOOS2_1X_HEADER *header) { SwapLong(&header->biSize); SwapShort(&header->biWidth); SwapShort(&header->biHeight); SwapShort(&header->biPlanes); SwapShort(&header->biBitCount); }
/******************************************************************** * ConvertUnsignedLongBuffer ********************************************************************/ void ConvertUnsignedLongBuffer(unsigned long *buffer, unsigned long nbLongs) { while (nbLongs-- > 0) { *buffer = SwapLong(*buffer); buffer++; } }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { if (handle != NULL) { BITMAPFILEHEADER bitmapfileheader; DWORD type = 0; BYTE magic[2]; // we use this offset value to make seemingly absolute seeks relative in the file long offset_in_file = io->tell_proc(handle); // read the magic io->read_proc(&magic, sizeof(magic), 1, handle); // compare the magic with the number we know // somebody put a comment here explaining the purpose of this loop while (memcmp(&magic, "BA", 2) == 0) { io->read_proc(&bitmapfileheader.bfSize, sizeof(DWORD), 1, handle); io->read_proc(&bitmapfileheader.bfReserved1, sizeof(WORD), 1, handle); io->read_proc(&bitmapfileheader.bfReserved2, sizeof(WORD), 1, handle); io->read_proc(&bitmapfileheader.bfOffBits, sizeof(DWORD), 1, handle); io->read_proc(&magic, sizeof(magic), 1, handle); } // read the fileheader io->seek_proc(handle, 0 - sizeof(magic), SEEK_CUR); io->read_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapFileHeader(&bitmapfileheader); #endif // read the first byte of the infoheader io->read_proc(&type, sizeof(DWORD), 1, handle); io->seek_proc(handle, 0 - sizeof(DWORD), SEEK_CUR); #ifdef FREEIMAGE_BIGENDIAN SwapLong(&type); #endif // call the appropriate load function for the found bitmap type if (type == 40) return LoadWindowsBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); if (type == 12) return LoadOS21XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); if (type <= 64) return LoadOS22XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); FreeImage_OutputMessageProc(s_format_id, "unknown bmp subtype with id %d", type); } return NULL; }
static void SwapInfoHeader(BITMAPINFOHEADER *header) { SwapLong(&header->biSize); SwapLong((DWORD *)&header->biWidth); SwapLong((DWORD *)&header->biHeight); SwapShort(&header->biPlanes); SwapShort(&header->biBitCount); SwapLong(&header->biCompression); SwapLong(&header->biSizeImage); SwapLong((DWORD *)&header->biXPelsPerMeter); SwapLong((DWORD *)&header->biYPelsPerMeter); SwapLong(&header->biClrUsed); SwapLong(&header->biClrImportant); }
/******************************************************************** * ConvertUnsignedLongBuffer ********************************************************************/ void ConvertUnsignedLongBuffer(void * ptr, size_t length) { uint32_t * buffer = (uint32_t *)ptr; uint32_t nbLongs = (uint32_t)(length / sizeof(uint32_t)); while (nbLongs-- > 0) { *buffer = SwapLong(*buffer); buffer++; } }
static void SwapExtensionArea(TGAEXTENSIONAREA *ex) { SwapShort(&ex->extension_size); SwapShort(&ex->datetime_stamp[0]); SwapShort(&ex->datetime_stamp[1]); SwapShort(&ex->datetime_stamp[2]); SwapShort(&ex->datetime_stamp[3]); SwapShort(&ex->datetime_stamp[4]); SwapShort(&ex->datetime_stamp[5]); SwapShort(&ex->job_time[0]); SwapShort(&ex->job_time[1]); SwapShort(&ex->job_time[2]); SwapLong (&ex->key_color); SwapShort(&ex->pixel_aspect_ratio[0]); SwapShort(&ex->pixel_aspect_ratio[1]); SwapShort(&ex->gamma_value[0]); SwapShort(&ex->gamma_value[1]); SwapLong (&ex->color_correction_offset); SwapLong (&ex->postage_stamp_offset); SwapLong (&ex->scan_line_offset); }
long input_long_pci_config(int nHandle, long *p) { CARRIERDATA_STRUCT* pCarrier; /* local carrier */ unsigned long data[3]; pCarrier = GetCarrier(nHandle); if(pCarrier == NULL) return 0; /* place address to read from in data[0]; */ data[0] = (unsigned long) p; /* place device instance to read from @ data[1]; */ data[1] = (unsigned long) pCarrier->nDevInstance; /* pram3 = function: 1=read8bits,2=read16bits,4=read32bits, 0x40=readconfig32bits */ read( pCarrier->nCarrierDeviceHandle, &data[0], 0x40 ); return( SwapLong( (long)data[1] ) ); }
void output_long_pci_config(int nHandle, long *p, long v) { CARRIERDATA_STRUCT* pCarrier; /* local carrier */ unsigned long data[3]; pCarrier = GetCarrier(nHandle); if(pCarrier == NULL) return; /* place address to write data[0]; */ data[0] = (unsigned long) p; /* place value to write @ address data[1]; */ data[1] = (unsigned long) SwapLong( v ); /* place device instance @ data[2]; */ data[2] = (unsigned long) pCarrier->nDevInstance; /* pram3 = function: 1=write8bits,2=write16bits,4=write32bits, 0x40=writeconfig32bits */ write( pCarrier->nCarrierDeviceHandle, &data[0], 0x40 ); }
void output_long(int nHandle, long *p, long v) { CARRIERDATA_STRUCT* pCarrier; /* local carrier */ unsigned long data[2]; pCarrier = GetCarrier(nHandle); if(pCarrier == NULL) return; if( p ) { /* place address to write word in data [0]; */ data[0] = (unsigned long) p; /* place value to write @ address data [1]; */ data[1] = (unsigned long) SwapLong( v ); /* pram3 = function: 1=write8bits,2=write16bits,4=write32bits */ write( pCarrier->nCarrierDeviceHandle, &data[0], 4 ); } }
long input_long(int nHandle, long *p) { CARRIERDATA_STRUCT* pCarrier; /* local carrier */ unsigned long data[2]; pCarrier = GetCarrier(nHandle); if(pCarrier == NULL) return 0; if( p ) { /* place address to read word from in data [0]; */ data[0] = (unsigned long) p; /* pram3 = function: 1=read8bits,2=read16bits,4=read32bits */ read( pCarrier->nCarrierDeviceHandle, &data[0], 4 ); return( SwapLong( (long)data[1] ) ); } return((long)0); }
// // ACS_readOpACS0 // static int32_t ACS_readOpACS0(acs0_tracer_t *tracer, uint32_t *opSize, uint32_t index) { int32_t op; if(tracer->compressed) { *opSize = 1; if((op = tracer->data[index]) >= 240) { ++*opSize; op = 240 + ((op - 240) << 8) + tracer->data[index + 1]; } } else { *opSize = 4; op = SwapLong(*(int32_t *)(tracer->data + index)); } return op; }
//////////////////////////////////////////////////////////////////////////// // // LoadLIBShape() // int LoadLIBShape(char *SLIB_Filename, char *Filename,struct Shape *SHP) { #define CHUNK(Name) (*ptr == *Name) && \ (*(ptr+1) == *(Name+1)) && \ (*(ptr+2) == *(Name+2)) && \ (*(ptr+3) == *(Name+3)) int RT_CODE; FILE *fp; char CHUNK[5]; char far *ptr; memptr IFFfile = NULL; unsigned long FileLen, size, ChunkLen; int loop; RT_CODE = 1; // Decompress to ram and return ptr to data and return len of data in // passed variable... if (!LoadLIBFile(SLIB_Filename,Filename,&IFFfile)) Quit("Error Loading Compressed lib shape!"); // Evaluate the file // ptr = MK_FP(IFFfile,0); if (!CHUNK("FORM")) goto EXIT_FUNC; ptr += 4; FileLen = *(long far *)ptr; SwapLong((long far *)&FileLen); ptr += 4; if (!CHUNK("ILBM")) goto EXIT_FUNC; ptr += 4; FileLen += 4; while (FileLen) { ChunkLen = *(long far *)(ptr+4); SwapLong((long far *)&ChunkLen); ChunkLen = (ChunkLen+1) & 0xFFFFFFFE; if (CHUNK("BMHD")) { ptr += 8; SHP->bmHdr.w = ((struct BitMapHeader far *)ptr)->w; SHP->bmHdr.h = ((struct BitMapHeader far *)ptr)->h; SHP->bmHdr.x = ((struct BitMapHeader far *)ptr)->x; SHP->bmHdr.y = ((struct BitMapHeader far *)ptr)->y; SHP->bmHdr.d = ((struct BitMapHeader far *)ptr)->d; SHP->bmHdr.trans = ((struct BitMapHeader far *)ptr)->trans; SHP->bmHdr.comp = ((struct BitMapHeader far *)ptr)->comp; SHP->bmHdr.pad = ((struct BitMapHeader far *)ptr)->pad; SwapWord(&SHP->bmHdr.w); SwapWord(&SHP->bmHdr.h); SwapWord(&SHP->bmHdr.x); SwapWord(&SHP->bmHdr.y); ptr += ChunkLen; } else if (CHUNK("BODY")) { ptr += 4; size = *((long far *)ptr); ptr += 4; SwapLong((long far *)&size); SHP->BPR = (SHP->bmHdr.w+7) >> 3; MM_GetPtr(&SHP->Data,size); if (!SHP->Data) goto EXIT_FUNC; movedata(FP_SEG(ptr),FP_OFF(ptr),FP_SEG(SHP->Data),0,size); ptr += ChunkLen; break; } else
static void SwapFooter(TGAFOOTER *footer) { SwapLong(&footer->extension_offset); SwapLong(&footer->developer_offset); }
FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { FIBITMAP *Bitmap = NULL; if(handle != NULL) { BYTE ShortValue[2]; int n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); short nCompression = (short)psdGetValue( ShortValue, sizeof(ShortValue) ); switch ( nCompression ) { case PSD_COMPRESSION_NONE: // raw data { int nWidth = _headerInfo._Width; int nHeight = _headerInfo._Height; int bytes = _headerInfo._BitsPerPixel / 8; int nPixels = nWidth * nHeight; int nTotalBytes = nPixels * bytes * _headerInfo._Channels; if(_headerInfo._BitsPerPixel == 1) { // special case for PSD_BITMAP mode bytes = 1; nWidth = (nWidth + 7) / 8; nWidth = ( nWidth > 0 ) ? nWidth : 1; nPixels = nWidth * nHeight; nTotalBytes = nWidth * nHeight; } BYTE * plData = 0; BYTE * plPixel = 0; int nBytes = 0; switch (_headerInfo._ColourMode) { case PSD_BITMAP: { plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; while(nBytes < nTotalBytes) { n = (int)io->read_proc(plPixel, bytes, 1, handle); memcpy(plData+nBytes, plPixel, bytes ); nBytes += n * bytes; } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_INDEXED: // Indexed { assert( (-1 != _ColourCount) && (0 < _ColourCount) ); assert( NULL != _colourModeData._plColourData ); plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; while(nBytes < nTotalBytes) { n = (int)io->read_proc(plPixel, bytes, 1, handle); memcpy(plData+nBytes, plPixel, bytes ); nBytes += n * bytes; } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_GRAYSCALE: // Grayscale case PSD_DUOTONE: // Duotone case PSD_RGB: // RGB { plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; int nPixelCounter = 0; int nChannels = _headerInfo._Channels; for(int c = 0; c < nChannels; c++) { nPixelCounter = c * bytes; for(int nPos = 0; nPos < nPixels; ++nPos) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } if(2 == bytes) { // swap for uint16 SwapShort((WORD*)&plPixel[0]); } else if(4 == bytes) { // swap for float SwapLong((DWORD*)&plPixel[0]); } memcpy( plData + nPixelCounter, plPixel, bytes ); nBytes += n * bytes; nPixelCounter += nChannels*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_CMYK: // CMYK case PSD_MULTICHANNEL: // Multichannel { plPixel = new BYTE[bytes]; plData = new BYTE[nTotalBytes]; int nPixelCounter = 0; for (int c=0; c<_headerInfo._Channels; c++) { nPixelCounter = c*bytes; for ( int nPos = 0; nPos < nPixels; ++nPos ) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } memcpy(plData + nPixelCounter, plPixel, bytes ); nBytes += n * bytes; nPixelCounter += _headerInfo._Channels*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_LAB: // Lab { plPixel = new BYTE[bytes]; plData = new BYTE[nTotalBytes]; int nPixelCounter = 0; for(int c = 0; c < 3; c++) { nPixelCounter = c*bytes; for ( int nPos = 0; nPos < nPixels; ++nPos ) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } memcpy(plData + nPixelCounter, plPixel, bytes); nBytes += n * bytes; nPixelCounter += 3*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; } assert( nBytes == nTotalBytes ); if (nBytes == nTotalBytes) { if (plData) { switch (_headerInfo._BitsPerPixel) { case 1: case 8: case 16: case 32: Bitmap = ProcessBuffer(plData); break; default: // Unsupported break; } } } SAFE_DELETE_ARRAY(plData); } break; case PSD_COMPRESSION_RLE: // RLE compression { int nWidth = _headerInfo._Width; int nHeight = _headerInfo._Height; int bytes = _headerInfo._BitsPerPixel / 8; int nPixels = nWidth * nHeight; int nTotalBytes = nPixels * bytes * _headerInfo._Channels; if(_headerInfo._BitsPerPixel == 1) { // special case for PSD_BITMAP mode bytes = 1; nWidth = (nWidth + 7) / 8; nWidth = ( nWidth > 0 ) ? nWidth : 1; nPixels = nWidth * nHeight; nTotalBytes = nWidth * nHeight; } BYTE * plData = new BYTE[nTotalBytes]; BYTE * p = plData; int nValue = 0; BYTE ByteValue[1]; int Count = 0; // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, // which we're going to just skip. io->seek_proc(handle, nHeight * _headerInfo._Channels * 2, SEEK_CUR); for (int channel = 0; channel < _headerInfo._Channels; channel++) { // Read the RLE data. Count = 0; while (Count < nPixels) { io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); int len = psdGetValue( ByteValue, sizeof(ByteValue) ); if ( 128 > len ) { len++; Count += len; while (len) { io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); nValue = psdGetValue( ByteValue, sizeof(ByteValue) ); *p = (BYTE)nValue; p += sizeof(ByteValue); len--; } } else if ( 128 < len ) { // Next -len+1 bytes in the dest are replicated from next source byte. // (Interpret len as a negative 8-bit int.) len ^= 0x0FF; len += 2; io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); nValue = psdGetValue( ByteValue, sizeof(ByteValue) ); Count += len; while (len) { *p = (BYTE)nValue; p += sizeof(ByteValue); len--; } } else if ( 128 == len ) { // Do nothing } } } BYTE * prSource = plData; BYTE * plDest = new BYTE[nTotalBytes]; memset(plDest, 254, nTotalBytes); int nPixelCounter = 0; for(int c=0; c<_headerInfo._Channels; c++) { nPixelCounter = c*bytes; for (int nPos = 0; nPos<nPixels; ++nPos) { memcpy( plDest + nPixelCounter, prSource, bytes ); prSource++; nPixelCounter += _headerInfo._Channels*bytes; } } SAFE_DELETE_ARRAY(plData); if (plDest) { switch (_headerInfo._BitsPerPixel) { case 1: case 8: case 16: Bitmap = ProcessBuffer(plDest); break; default: // Unsupported format break; } } SAFE_DELETE_ARRAY(plDest); } break; case 2: // ZIP without prediction, no specification break; case 3: // ZIP with prediction, no specification break; default: // Unknown format break; } } return Bitmap; }
// // ACS_LoadScriptACS0 // void ACS_LoadScriptACS0(ACSVM *vm, WadDirectory *dir, int lump, byte *data) { uint32_t lumpAvail; // Used in bounds checking. uint32_t lumpLength = dir->lumpLength(lump); int32_t *rover; uint32_t tableIndex; // Header + table index + script count + string count = 16 bytes. if (lumpLength < 16) return; lumpAvail = lumpLength - 16; rover = (int32_t *)data + 1; // Find script table. tableIndex = SwapLong(*rover); // Aha, but there might really be an ACSE header here! if(tableIndex >= 8 && tableIndex <= lumpLength) { uint32_t fakeHeader = SwapULong(*(uint32_t *)(data + tableIndex - 4)); if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'E')) { ACS_LoadScriptACSE(vm, dir, lump, data, tableIndex - 8); return; } else if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'e')) { ACS_LoadScriptACSe(vm, dir, lump, data, tableIndex - 8); return; } } // At the index there must be at least the script count and string count. // Subtracting from lumpLength instead of adding to tableIndex in case the // latter would cause an overflow. if (tableIndex > lumpLength - 8) return; rover = (int32_t *)(data + tableIndex); // Read script count. vm->numScripts = SwapLong(*rover++); // Verify that there is enough space for the given number of scripts. if (vm->numScripts * 12 > lumpAvail) return; lumpAvail -= vm->numScripts * 12; // Also verify that the string count will be inside the lump. if (tableIndex + 8 > lumpLength - (vm->numScripts * 12)) return; tableIndex += 8 + (vm->numScripts * 12); // Read scripts. vm->scripts = estructalloctag(ACSScript, vm->numScripts, PU_LEVEL); for(ACSScript *itr = vm->scripts, *end = itr + vm->numScripts; itr != end; ++itr) { itr->number = SwapLong(*rover++); itr->codeIndex = SwapLong(*rover++); itr->numArgs = SwapLong(*rover++); itr->numVars = ACS_NUM_LOCALVARS; itr->vm = vm; if(itr->number >= 1000) { itr->type = ACS_STYPE_OPEN; itr->number -= 1000; } else itr->type = ACS_STYPE_CLOSED; } // Read string count. vm->numStrings = SwapLong(*rover++); // Again, verify that there is enough space for the table first. if (vm->numStrings * 4 > lumpAvail) return; lumpAvail -= vm->numStrings * 4; // This time, just verify the end of the table is in bounds. if (tableIndex > lumpLength - (vm->numStrings * 4)) return; // Read strings. vm->strings = (uint32_t *)Z_Malloc(vm->numStrings * sizeof(uint32_t), PU_LEVEL, NULL); for(uint32_t *itr = vm->strings, *end = itr + vm->numStrings; itr != end; ++itr) { tableIndex = SwapLong(*rover++); if (tableIndex < lumpLength) *itr = ACS_LoadStringACS0(data + tableIndex, data + lumpLength); else *itr = ACS_LoadStringACS0(data + lumpLength, data + lumpLength); } // The first part of the global string table must match VM-0 for compatibility. if(vm->id == 0 && ACSVM::GlobalNumStrings < vm->numStrings) vm->addStrings(); // Read code. ACS_LoadScriptCodeACS0(vm, data, lumpLength, false); vm->loaded = true; }
// // WadDirectory::addMemoryWad // // haleyjd 10/31/12: Add an id wadlink file stored in memory into the directory. // bool WadDirectory::addMemoryWad(openwad_t &openData, wfileadd_t &addInfo, int startlump) { // haleyjd 04/07/11 wadinfo_t header; ZAutoBuffer fileinfo2free; // killough filelump_t *fileinfo; size_t length; size_t info_offset; lumpinfo_t *lump_p; // Read in the header memcpy(&header, openData.base, sizeof(header)); header.numlumps = SwapLong(header.numlumps); header.infotableofs = SwapLong(header.infotableofs); // allocate enough fileinfo_t's to hold the wad directory length = header.numlumps * sizeof(filelump_t); fileinfo2free.alloc(length, true); // killough fileinfo = fileinfo2free.getAs<filelump_t *>(); info_offset = static_cast<size_t>(header.infotableofs); // seek to the directory if(info_offset + header.numlumps * sizeof(filelump_t) > openData.size) { if(addInfo.flags & WFA_OPENFAILFATAL) I_Error("Failed reading directory for in-memory file\n"); else { printf("Failed reading directory for in-memory file\n"); return false; } } // read it in. byte *directoryBase = static_cast<byte *>(openData.base) + info_offset; memcpy(fileinfo, directoryBase, header.numlumps * sizeof(filelump_t)); // Add lumpinfo_t's for all lumps in the wad file lump_p = reAllocLumpInfo(header.numlumps, startlump); // Merge into the directory for(int i = startlump; i < numlumps; i++, lump_p++, fileinfo++) { lump_p->type = lumpinfo_t::lump_memory; // haleyjd lump_p->size = (size_t)(SwapLong(fileinfo->size)); lump_p->source = source; // haleyjd // setup for memory IO lump_p->memory.data = openData.base; lump_p->memory.position = (size_t)(SwapLong(fileinfo->filepos)); lump_p->li_namespace = addInfo.li_namespace; // killough 4/17/98 strncpy(lump_p->name, fileinfo->name, 8); } incrementSource(openData); return true; }
/** Write a FIBITMAP to a JNG stream @param format_id ID of the caller @param io Stream i/o functions @param dib Image to be saved @param handle Stream handle @param flags Saving flags @return Returns TRUE if successful, returns FALSE otherwise */ BOOL mng_WriteJNG(int format_id, FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int flags) { DWORD jng_width = 0; DWORD jng_height = 0; BYTE jng_color_type = 0; BYTE jng_image_sample_depth = 8; BYTE jng_image_compression_method = 8; // 8: ISO-10918-1 Huffman-coded baseline JPEG. BYTE jng_image_interlace_method = 0; BYTE jng_alpha_sample_depth = 0; BYTE jng_alpha_compression_method = 0; BYTE jng_alpha_filter_method = 0; BYTE jng_alpha_interlace_method = 0; BYTE buffer[16]; FIMEMORY *hJngMemory = NULL; FIMEMORY *hJpegMemory = NULL; FIMEMORY *hPngMemory = NULL; FIBITMAP *dib_rgb = NULL; FIBITMAP *dib_alpha = NULL; if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { return FALSE; } unsigned bpp = FreeImage_GetBPP(dib); switch(bpp) { case 8: if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGGRAY; } else { // JPEG plugin will convert other types (FIC_MINISWHITE, FIC_PALETTE) to 24-bit on the fly //dib_rgb = FreeImage_ConvertTo24Bits(dib); dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGCOLOR; } break; case 24: dib_rgb = dib; jng_color_type = MNG_COLORTYPE_JPEGCOLOR; break; case 32: dib_rgb = FreeImage_ConvertTo24Bits(dib); jng_color_type = MNG_COLORTYPE_JPEGCOLORA; jng_alpha_sample_depth = 8; break; default: return FALSE; } jng_width = (DWORD)FreeImage_GetWidth(dib); jng_height = (DWORD)FreeImage_GetHeight(dib); try { hJngMemory = FreeImage_OpenMemory(); // --- write JNG file signature --- FreeImage_WriteMemory(g_jng_signature, 1, 8, hJngMemory); // --- write a JHDR chunk --- SwapLong(&jng_width); SwapLong(&jng_height); memcpy(&buffer[0], &jng_width, 4); memcpy(&buffer[4], &jng_height, 4); SwapLong(&jng_width); SwapLong(&jng_height); buffer[8] = jng_color_type; buffer[9] = jng_image_sample_depth; buffer[10] = jng_image_compression_method; buffer[11] = jng_image_interlace_method; buffer[12] = jng_alpha_sample_depth; buffer[13] = jng_alpha_compression_method; buffer[14] = jng_alpha_filter_method; buffer[15] = jng_alpha_interlace_method; mng_WriteChunk(mng_JHDR, &buffer[0], 16, hJngMemory); // --- write a sequence of JDAT chunks --- hJpegMemory = FreeImage_OpenMemory(); flags |= JPEG_BASELINE; if(!FreeImage_SaveToMemory(FIF_JPEG, dib_rgb, hJpegMemory, flags)) { throw (const char*)NULL; } if(dib_rgb != dib) { FreeImage_Unload(dib_rgb); dib_rgb = NULL; } { BYTE *jpeg_data = NULL; DWORD size_in_bytes = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hJpegMemory, &jpeg_data, &size_in_bytes); // write chunks for(DWORD k = 0; k < size_in_bytes;) { DWORD bytes_left = size_in_bytes - k; DWORD chunk_size = MIN(JPEG_CHUNK_SIZE, bytes_left); mng_WriteChunk(mng_JDAT, &jpeg_data[k], chunk_size, hJngMemory); k += chunk_size; } } FreeImage_CloseMemory(hJpegMemory); hJpegMemory = NULL; // --- write alpha layer as a sequence of IDAT chunk --- if((bpp == 32) && (jng_color_type == MNG_COLORTYPE_JPEGCOLORA)) { dib_alpha = FreeImage_GetChannel(dib, FICC_ALPHA); hPngMemory = FreeImage_OpenMemory(); if(!FreeImage_SaveToMemory(FIF_PNG, dib_alpha, hPngMemory, PNG_DEFAULT)) { throw (const char*)NULL; } FreeImage_Unload(dib_alpha); dib_alpha = NULL; // get the IDAT chunk { BOOL bResult = FALSE; DWORD start_pos = 0; DWORD next_pos = 0; long offset = 8; do { // find the next IDAT chunk from 'offset' position bResult = mng_FindChunk(hPngMemory, mng_IDAT, offset, &start_pos, &next_pos); if(!bResult) break; BYTE *png_data = NULL; DWORD size_in_bytes = 0; // get a pointer to the stream buffer FreeImage_AcquireMemory(hPngMemory, &png_data, &size_in_bytes); // write the IDAT chunk mng_WriteChunk(mng_IDAT, &png_data[start_pos+8], next_pos - start_pos - 12, hJngMemory); offset = next_pos; } while(bResult); } FreeImage_CloseMemory(hPngMemory); hPngMemory = NULL; } // --- write a IEND chunk --- mng_WriteChunk(mng_IEND, NULL, 0, hJngMemory); // write the JNG on output stream { BYTE *jng_data = NULL; DWORD size_in_bytes = 0; FreeImage_AcquireMemory(hJngMemory, &jng_data, &size_in_bytes); io->write_proc(jng_data, 1, size_in_bytes, handle); } FreeImage_CloseMemory(hJngMemory); FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); return TRUE; } catch(const char *text) { FreeImage_CloseMemory(hJngMemory); FreeImage_CloseMemory(hJpegMemory); FreeImage_CloseMemory(hPngMemory); if(dib_rgb && (dib_rgb != dib)) { FreeImage_Unload(dib_rgb); } FreeImage_Unload(dib_alpha); if(text) { FreeImage_OutputMessageProc(format_id, text); } return FALSE; } }
XGWindow *XGWindowFactory::CreateFromData(const unsigned char *data, XGForm *form) { XGSViewHeader h; const unsigned char *nptr; XGWindow *nwindow; long i,len; XGView *view; XGSViewHeader *ptr; /* * Get and parse the header, initialize the data stream */ h = *((XGSViewHeader *)data); #if OPT_NATIVEORDER != 1 h.type = SwapLong(h.type); h.sibling = SwapLong(h.sibling); h.children = SwapLong(h.children); h.length = SwapLong(h.length); #endif ptr = (XGSViewHeader *)data; XGArgStream stream((unsigned char *)&(ptr->type),h.length + sizeof(long)); /* * Now create the window. If not found, this will alert the * user and will create the generic 'window' instead. */ nwindow = NULL; len = gList.Length(); for (i = 0; i < len; i++) { if (h.type == gList[i].type) { nwindow = (gList[i].proc)(stream, form); break; } } if (nwindow == NULL) { Warning(KXGWindowFactoryError,h.type); nwindow = new XGWindow(stream, form); } /* * I have the window. This will only have one child, the view * object which is to be contained in this window. Scan for * the child object and construct. */ if (h.children) { nptr = data + h.children; for (;;) { view = XGViewFactory::CreateFromData(nptr,nwindow); h = *((XGSViewHeader *)nptr); #if OPT_NATIVEORDER != 1 h.sibling = SwapLong(h.sibling); #endif if (!h.sibling) break; nptr += h.sibling; } } /* * Done creating me and my children. */ return nwindow; }
// // ACS_traceScriptACS0 // static void ACS_traceScriptACS0(acs0_tracer_t *tracer, uint32_t index) { uint32_t indexNext, opSize; int32_t op; acs0_opdata_t const *opdata; for(;;) { // Read next instruction from file. op = ACS_readOpACS0(tracer, &opSize, index); // Invalid opcode terminates tracer. if(op >= ACS0_OPMAX || op < 0) { // But flag it so that a KILL gets generated by the translator. ACS_touchScriptACS0(tracer->codeTouched + index, tracer->codeTouched + index + opSize); ++tracer->vm->numCode; return; } opdata = &ACS0opdata[op]; // Calculate next index. indexNext = index + ACS_countOpSizeACS0(tracer, index, opSize, opdata); // Leaving the bounds of the lump also terminates the tracer. if(indexNext > tracer->lumpLength) return; // If already touched this instruction, stop tracing. if(ACS_touchScriptACS0(tracer->codeTouched + index, tracer->codeTouched + indexNext)) return; // Determine how many internal codes this counts for. switch(op) { case ACS0_OP_LINESPEC1_IMM: case ACS0_OP_LINESPEC2_IMM: case ACS0_OP_LINESPEC3_IMM: case ACS0_OP_LINESPEC4_IMM: case ACS0_OP_LINESPEC5_IMM: case ACS0_OP_LINESPEC1_IMM_BYTE: case ACS0_OP_LINESPEC2_IMM_BYTE: case ACS0_OP_LINESPEC3_IMM_BYTE: case ACS0_OP_LINESPEC4_IMM_BYTE: case ACS0_OP_LINESPEC5_IMM_BYTE: case ACS0_OP_GET2_IMM_BYTE: case ACS0_OP_GET3_IMM_BYTE: case ACS0_OP_GET4_IMM_BYTE: case ACS0_OP_GET5_IMM_BYTE: tracer->vm->numCode += opdata->args + 2; break; case ACS0_OP_GETARR_IMM_BYTE: tracer->vm->numCode += *(tracer->data + index + opSize) + 2; break; case ACS0_OP_ACTIVATORHEALTH: case ACS0_OP_ACTIVATORARMOR: case ACS0_OP_ACTIVATORFRAGS: case ACS0_OP_BRANCH_RETURNVOID: case ACS0_OP_PLAYERNUMBER: case ACS0_OP_ACTIVATORTID: case ACS0_OP_SIGILPIECES: tracer->vm->numCode += opdata->opdata->args + 1 + 2; // GET_IMM 0 break; case ACS0_OP_GAMETYPE_ONEFLAGCTF: tracer->vm->numCode += 2; // GET_IMM break; case ACS0_OP_GAMETYPE_SINGLEPLAYER: tracer->vm->numCode += 4; // GAMETYPE + GET_IMM + CMP_EQ break; case ACS0_OP_BRANCH_CALLDISCARD: tracer->vm->numCode += opdata->opdata->args + 1 + 1; // DROP break; case ACS0_OP_BRANCH_CASETABLE: tracer->vm->numCode += 2; // More alignment stuff. (Wow, that's a mouthfull.) tracer->vm->numCode += SwapULong(*(uint32_t *)(((uintptr_t)tracer->data + index + opSize + 3) & ~3)) * 2; break; case ACS0_OP_CALLFUNC: if(tracer->compressed) { uint8_t argc = tracer->data[index + opSize]; uint16_t func = SwapUShort(*(uint16_t *)(tracer->data + index + opSize + 1)); tracer->vm->numCode += ACS_traceFuncACS0(func, argc); } else { uint32_t argc = SwapULong(*(uint32_t *)(tracer->data + index + opSize + 0)); uint32_t func = SwapULong(*(uint32_t *)(tracer->data + index + opSize + 4)); tracer->vm->numCode += ACS_traceFuncACS0(func, argc); } break; default: // Translation to CALLFUNC. if(opdata->opdata->op == ACS_OP_CALLFUNC_IMM) { // Adds the func and argc arguments. tracer->vm->numCode += opdata->args + 1 + 2; break; } // Direct translation. #ifdef RANGECHECK // This should never happen. if(opdata->opdata->args == -1) I_Error("Unknown translation for opcode. opcode %i", (int)op); #endif tracer->vm->numCode += opdata->opdata->args + 1; break; } // Advance the index past the instruction. switch(op) { case ACS0_OP_SCRIPT_TERMINATE: case ACS0_OP_BRANCH_RETURN: case ACS0_OP_BRANCH_RETURNVOID: return; case ACS0_OP_BRANCH_IMM: ++tracer->jumpCount; index = SwapLong(*(int32_t *)(tracer->data + index + opSize)); continue; case ACS0_OP_BRANCH_NOTZERO: case ACS0_OP_BRANCH_ZERO: ++tracer->jumpCount; ACS_traceScriptACS0(tracer, SwapLong(*(int32_t *)(tracer->data + index + opSize))); break; case ACS0_OP_BRANCH_CASE: ++tracer->jumpCount; ACS_traceScriptACS0(tracer, SwapLong(*(int32_t *)(tracer->data + index + opSize + 4))); break; case ACS0_OP_BRANCH_CASETABLE: { uint32_t jumps, *rover; rover = (uint32_t *)(tracer->data + index + opSize); // And alignment again. rover = (uint32_t *)(((uintptr_t)rover + 3) & ~3); jumps = SwapULong(*rover++); tracer->jumpCount += jumps; // Trace all of the jump targets. // Start by incrementing rover to point to address. for(++rover; jumps--; rover += 2) ACS_traceScriptACS0(tracer, SwapULong(*rover)); } break; } index = indexNext; } }
XGView *XGViewFactory::CreateFromData(const unsigned char *data, XGView *parent) { XGSViewHeader h; XGSViewHeader *ptr; const unsigned char *nptr; XGView *nview; long i,len; /* * Get and parse the header, initialize the data stream */ h = *((XGSViewHeader *)data); #if OPT_NATIVEORDER != 1 h.type = SwapLong(h.type); h.sibling = SwapLong(h.sibling); h.children = SwapLong(h.children); h.length = SwapLong(h.length); #endif ptr = (XGSViewHeader *)data; XGArgStream stream((unsigned char *)&(ptr->type),h.length + sizeof(long)); /* * Now create the view. If not found, this will alert the * user and will create the generic 'view' instead. */ nview = NULL; len = gList.Length(); for (i = 0; i < len; i++) { if (h.type == gList[i].type) { nview = (gList[i].proc)(parent,stream); break; } } if (nview == NULL) { Warning(KXGViewFactoryError,h.type); nview = new XGView(parent,stream); } /* * I have the view. Start looking for the children of this * thing. (The default view constructor will add the child * view to the specified parent view, so nothing needs to be * done here.) */ if (h.children) { nptr = data + h.children; for (;;) { CreateFromData(nptr,nview); h = *((XGSViewHeader *)nptr); #if OPT_NATIVEORDER != 1 h.sibling = SwapLong(h.sibling); #endif if (!h.sibling) break; nptr += h.sibling; } } /* * Done creating me and my children. Return */ return nview; }
// // WadDirectory::addWadFile // // haleyjd 10/28/12: Add an id wadlink file into the directory. // bool WadDirectory::addWadFile(openwad_t &openData, wfileadd_t &addInfo, int startlump) { // haleyjd 04/07/11 //HashData wadHash = HashData(HashData::SHA1); bool showHash = false; bool doHacks = (addInfo.flags & WFA_ALLOWHACKS) == WFA_ALLOWHACKS; long baseoffset = static_cast<long>(addInfo.baseoffset); wadinfo_t header; ZAutoBuffer fileinfo2free; // killough filelump_t *fileinfo; size_t length; long info_offset; lumpinfo_t *lump_p; // check for in-memory wads if(addInfo.flags & WFA_INMEMORY) return addMemoryWad(openData, addInfo, startlump); // haleyjd: seek to baseoffset first when loading a subfile if(addInfo.flags & WFA_SUBFILE) fseek(openData.handle, baseoffset, SEEK_SET); // -nowadhacks disables all wad directory hacks, in case of unforeseen // compatibility problems that would last until the next release if(M_CheckParm("-nowadhacks")) doHacks = false; // -showhashes enables display of the computed SHA-1 hash used to apply // wad directory hacks. Quite useful for when a new hack needs to be added. if(M_CheckParm("-showhashes")) showHash = true; if(fread(&header, sizeof(header), 1, openData.handle) < 1) { if(addInfo.flags & WFA_OPENFAILFATAL) I_Error("Failed reading header for wad file %s\n", openData.filename); else { fclose(openData.handle); printf("Failed reading header for wad file %s\n", openData.filename); return false; } } // Feed the wad header data into the hash computation //if(doHacks || showHash) // wadHash.addData((const uint8_t *)&header, (uint32_t)sizeof(header)); header.numlumps = SwapLong(header.numlumps); header.infotableofs = SwapLong(header.infotableofs); // allocate enough fileinfo_t's to hold the wad directory length = header.numlumps * sizeof(filelump_t); fileinfo2free.alloc(length, true); // killough fileinfo = fileinfo2free.getAs<filelump_t *>(); info_offset = static_cast<long>(header.infotableofs); // subfile wads may exist at a positive base offset in the container file if(addInfo.flags & WFA_SUBFILE) info_offset += baseoffset; // seek to the directory fseek(openData.handle, info_offset, SEEK_SET); // read it in. if(fread(fileinfo, length, 1, openData.handle) < 1) { if(addInfo.flags & WFA_OPENFAILFATAL) I_Error("Failed reading directory for wad file %s\n", openData.filename); else { fclose(openData.handle); printf("Failed reading directory for wad file %s\n", openData.filename); return false; } } // Feed the wad directory into the hash computation, wrap it up, and if requested, // output it to the console. #if 0 if(doHacks || showHash) { wadHash.addData((const uint8_t *)fileinfo, (uint32_t)length); wadHash.wrapUp(); if(in_textmode && showHash) printf("\thash = %s\n", wadHash.digestToString()); // haleyjd 04/08/11: apply wad directory hacks as needed if(doHacks) W_CheckDirectoryHacks(wadHash, fileinfo, header.numlumps); } #endif // update IWAD handle? // haleyjd: Must be a public wad file. if(!(addInfo.flags & WFA_PRIVATE) && this->ispublic) { // haleyjd 06/21/04: track handle of first wad added also if(ResWADSource == -1) ResWADSource = source; // haleyjd 07/13/09: only track the first IWAD found // haleyjd 11/03/12: Status as the IWAD is now determined by how the file // was added to the game (ie., -iwad or -disk, vs. -file, autoloads, etc.) if(IWADSource < 0 && (addInfo.flags & WFA_ISIWADFILE)) IWADSource = source; } // Add lumpinfo_t's for all lumps in the wad file lump_p = reAllocLumpInfo(header.numlumps, startlump); // Merge into the directory for(int i = startlump; i < this->numlumps; i++, lump_p++, fileinfo++) { strncpy(lump_p->name, fileinfo->name, 8); if(lump_p->name[0] & 0x80) // For psxwadgen, detect compressed lumps { lump_p->name[0] &= 0x7f; lump_p->type = lumpinfo_t::lump_direct_jag; } else lump_p->type = lumpinfo_t::lump_direct; // haleyjd lump_p->size = (size_t)(SwapLong(fileinfo->size)); lump_p->source = source; // haleyjd // setup for direct IO lump_p->direct.file = openData.handle; lump_p->direct.position = (size_t)(SwapLong(fileinfo->filepos)); // for subfiles, add baseoffset to the lump offset if(addInfo.flags & WFA_SUBFILE) lump_p->direct.position += static_cast<size_t>(baseoffset); lump_p->li_namespace = addInfo.li_namespace; // killough 4/17/98 } #if 0 if(ispublic) D_NewWadLumps(source); #endif incrementSource(openData); return true; }
inline void mng_SwapLong(DWORD *lp) { #ifndef FREEIMAGE_BIGENDIAN SwapLong(lp); #endif }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { SUNHEADER header; // Sun file header WORD linelength; // Length of raster line in bytes WORD fill; // Number of fill bytes per raster line BOOL rle; // TRUE if RLE file BOOL isRGB; // TRUE if file type is RT_FORMAT_RGB BYTE fillchar; FIBITMAP *dib = NULL; BYTE *bits; // Pointer to dib data WORD x, y; if(!handle) { return NULL; } BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; try { // Read SUN raster header io->read_proc(&header, sizeof(SUNHEADER), 1, handle); #ifndef FREEIMAGE_BIGENDIAN // SUN rasterfiles are big endian only SwapLong(&header.magic); SwapLong(&header.width); SwapLong(&header.height); SwapLong(&header.depth); SwapLong(&header.length); SwapLong(&header.type); SwapLong(&header.maptype); SwapLong(&header.maplength); #endif // Verify SUN identifier if (header.magic != RAS_MAGIC) { throw FI_MSG_ERROR_MAGIC_NUMBER; } // Allocate a new DIB switch(header.depth) { case 1: case 8: dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth); break; case 24: dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); break; case 32: dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); break; } if (dib == NULL) { throw FI_MSG_ERROR_DIB_MEMORY; } // Check the file format rle = FALSE; isRGB = FALSE; switch(header.type) { case RT_OLD: case RT_STANDARD: case RT_FORMAT_TIFF: // I don't even know what these format are... case RT_FORMAT_IFF: //The TIFF and IFF format types indicate that the raster //file was originally converted from either of these file formats. //so lets at least try to process them as RT_STANDARD break; case RT_BYTE_ENCODED: rle = TRUE; break; case RT_FORMAT_RGB: isRGB = TRUE; break; default: throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } // set up the colormap if needed switch(header.maptype) { case RMT_NONE : { if (header.depth < 24) { // Create linear color ramp RGBQUAD *pal = FreeImage_GetPalette(dib); int numcolors = 1 << header.depth; for (int i = 0; i < numcolors; i++) { pal[i].rgbRed = (BYTE)((255 * i) / (numcolors - 1)); pal[i].rgbGreen = (BYTE)((255 * i) / (numcolors - 1)); pal[i].rgbBlue = (BYTE)((255 * i) / (numcolors - 1)); } } break; } case RMT_EQUAL_RGB: { BYTE *r, *g, *b; // Read SUN raster colormap int numcolors = 1 << header.depth; if((DWORD)(3 * numcolors) > header.maplength) { // some RAS may have less colors than the full palette numcolors = header.maplength / 3; } else { throw "Invalid palette"; } r = (BYTE*)malloc(3 * numcolors * sizeof(BYTE)); g = r + numcolors; b = g + numcolors; RGBQUAD *pal = FreeImage_GetPalette(dib); io->read_proc(r, 3 * numcolors, 1, handle); for (int i = 0; i < numcolors; i++) { pal[i].rgbRed = r[i]; pal[i].rgbGreen = g[i]; pal[i].rgbBlue = b[i]; } free(r); break; } case RMT_RAW: { BYTE *colormap; // Read (skip) SUN raster colormap. colormap = (BYTE *)malloc(header.maplength * sizeof(BYTE)); io->read_proc(colormap, header.maplength, 1, handle); free(colormap); break; } } if(header_only) { // header only mode return dib; } // Calculate the line + pitch // Each row is multiple of 16 bits (2 bytes). if (header.depth == 1) { linelength = (WORD)((header.width / 8) + (header.width % 8 ? 1 : 0)); } else { linelength = (WORD)header.width; } fill = (linelength % 2) ? 1 : 0; unsigned pitch = FreeImage_GetPitch(dib); // Read the image data switch(header.depth) { case 1: case 8: { bits = FreeImage_GetBits(dib) + (header.height - 1) * pitch; for (y = 0; y < header.height; y++) { ReadData(io, handle, bits, linelength, rle); bits -= pitch; if (fill) { ReadData(io, handle, &fillchar, fill, rle); } } break; } case 24: { BYTE *buf, *bp; buf = (BYTE*)malloc(header.width * 3); for (y = 0; y < header.height; y++) { bits = FreeImage_GetBits(dib) + (header.height - 1 - y) * pitch; ReadData(io, handle, buf, header.width * 3, rle); bp = buf; if (isRGB) { for (x = 0; x < header.width; x++) { bits[FI_RGBA_RED] = *(bp++); // red bits[FI_RGBA_GREEN] = *(bp++); // green bits[FI_RGBA_BLUE] = *(bp++); // blue bits += 3; } } else { for (x = 0; x < header.width; x++) { bits[FI_RGBA_RED] = *(bp + 2); // red bits[FI_RGBA_GREEN] = *(bp + 1);// green bits[FI_RGBA_BLUE] = *bp; // blue bits += 3; bp += 3; } } if (fill) { ReadData(io, handle, &fillchar, fill, rle); } } free(buf); break; } case 32: { BYTE *buf, *bp; buf = (BYTE*)malloc(header.width * 4); for (y = 0; y < header.height; y++) { bits = FreeImage_GetBits(dib) + (header.height - 1 - y) * pitch; ReadData(io, handle, buf, header.width * 4, rle); bp = buf; if (isRGB) { for (x = 0; x < header.width; x++) { bits[FI_RGBA_ALPHA] = *(bp++); // alpha bits[FI_RGBA_RED] = *(bp++); // red bits[FI_RGBA_GREEN] = *(bp++); // green bits[FI_RGBA_BLUE] = *(bp++); // blue bits += 4; } } else { for (x = 0; x < header.width; x++) { bits[FI_RGBA_RED] = *(bp + 3); // red bits[FI_RGBA_GREEN] = *(bp + 2); // green bits[FI_RGBA_BLUE] = *(bp + 1); // blue bits[FI_RGBA_ALPHA] = *bp; // alpha bits += 4; bp += 4; } } if (fill) { ReadData(io, handle, &fillchar, fill, rle); } } free(buf); break; } } return dib; } catch (const char *text) { if(dib) { FreeImage_Unload(dib); } FreeImage_OutputMessageProc(s_format_id, text); } return NULL; }
// // ACS_translateScriptACS0 // static void ACS_translateScriptACS0(acs0_tracer_t *tracer, int32_t *codeIndexMap) { byte *brover; int32_t *codePtr = tracer->vm->code, *rover; uint32_t index, opSize; int32_t op, temp; acs0_opdata_t const *opdata; int32_t **jumps, **jumpItr; // This is used to store all of the places that need to have a jump target // translated. The count was determined by the tracer. jumps = (int32_t **)Z_Malloc(tracer->jumpCount * sizeof(int32_t *), PU_STATIC, NULL); jumpItr = jumps; // Set the first instruction to a KILL. *codePtr++ = ACS_OP_KILL; for(index = 0; index < tracer->lumpLength;) { // Search for code. if(!tracer->codeTouched[index]) { ++index; continue; } // Read next instruction from file. op = ACS_readOpACS0(tracer, &opSize, index); rover = (int32_t *)(tracer->data + index + opSize); // Unrecognized instructions need to stop execution. if(op >= ACS0_OPMAX || op < 0) { *codePtr++ = ACS_OP_KILL; index += opSize; continue; } opdata = &ACS0opdata[op]; // Record jump target. codeIndexMap[index] = codePtr - tracer->vm->code; // Calculate next index. index += ACS_countOpSizeACS0(tracer, index, opSize, opdata); switch(op) { case ACS0_OP_LINESPEC1: case ACS0_OP_LINESPEC2: case ACS0_OP_LINESPEC3: case ACS0_OP_LINESPEC4: case ACS0_OP_LINESPEC5: temp = op - ACS0_OP_LINESPEC1 + 1; *codePtr++ = opdata->opdata->op; *codePtr++ = SwapLong(*rover++); *codePtr++ = temp; break; case ACS0_OP_LINESPEC1_IMM: case ACS0_OP_LINESPEC2_IMM: case ACS0_OP_LINESPEC3_IMM: case ACS0_OP_LINESPEC4_IMM: case ACS0_OP_LINESPEC5_IMM: temp = opdata->args - 1; *codePtr++ = opdata->opdata->op; *codePtr++ = SwapLong(*rover++); *codePtr++ = temp; while(temp--) *codePtr++ = SwapLong(*rover++); break; case ACS0_OP_LINESPEC5_RET: temp = op - ACS0_OP_LINESPEC5_RET + 5; *codePtr++ = opdata->opdata->op; *codePtr++ = SwapLong(*rover++); *codePtr++ = temp; break; case ACS0_OP_LINESPEC1_IMM_BYTE: case ACS0_OP_LINESPEC2_IMM_BYTE: case ACS0_OP_LINESPEC3_IMM_BYTE: case ACS0_OP_LINESPEC4_IMM_BYTE: case ACS0_OP_LINESPEC5_IMM_BYTE: brover = (byte *)rover; temp = opdata->args - 1; *codePtr++ = opdata->opdata->op; *codePtr++ = *brover++; *codePtr++ = temp; while(temp--) *codePtr++ = *brover++; break; case ACS0_OP_GET_IMM_BYTE: *codePtr++ = opdata->opdata->op; *codePtr++ = *(byte *)rover; break; case ACS0_OP_GET2_IMM_BYTE: case ACS0_OP_GET3_IMM_BYTE: case ACS0_OP_GET4_IMM_BYTE: case ACS0_OP_GET5_IMM_BYTE: brover = (byte *)rover; temp = op - ACS0_OP_GET2_IMM_BYTE + 2; *codePtr++ = opdata->opdata->op; *codePtr++ = temp; while(temp--) *codePtr++ = *brover++; break; case ACS0_OP_GET_THINGX: case ACS0_OP_GET_THINGY: case ACS0_OP_GET_THINGZ: case ACS0_OP_GET_THINGFLOORZ: case ACS0_OP_GET_THINGANGLE: case ACS0_OP_SET_THINGANGLE: case ACS0_OP_GET_THINGCEILINGZ: case ACS0_OP_GET_THINGPITCH: case ACS0_OP_SET_THINGPITCH: case ACS0_OP_CHK_THINGCEILINGTEXTURE: case ACS0_OP_CHK_THINGFLOORTEXTURE: case ACS0_OP_GET_THINGLIGHTLEVEL: *codePtr++ = opdata->opdata->op; *codePtr++ = ACS_translateThingVarACS0(opdata); break; case ACS0_OP_GETARR_IMM_BYTE: brover = (byte *)rover; temp = *brover++; *codePtr++ = opdata->opdata->op; *codePtr++ = temp; while(temp--) *codePtr++ = *brover++; break; case ACS0_OP_BRANCH_IMM: case ACS0_OP_BRANCH_NOTZERO: case ACS0_OP_BRANCH_ZERO: *jumpItr++ = codePtr + 1; goto case_direct; case ACS0_OP_BRANCH_CASE: *jumpItr++ = codePtr + 2; goto case_direct; case ACS0_OP_CHANGEFLOOR_IMM: case ACS0_OP_CHANGECEILING_IMM: ACS_translateFuncACS0(codePtr, opdata); *codePtr++ = SwapLong(*rover++); *codePtr++ = tracer->vm->getStringIndex(SwapLong(*rover++)); // tag string for(int i = opdata->args - 2; i--;) *codePtr++ = SwapLong(*rover++); break; case ACS0_OP_DELAY_IMM_BYTE: brover = (byte *)rover; *codePtr++ = opdata->opdata->op; for(int i = opdata->args; i--;) *codePtr++ = *brover++; break; case ACS0_OP_ACTIVATORHEALTH: case ACS0_OP_ACTIVATORARMOR: case ACS0_OP_ACTIVATORFRAGS: case ACS0_OP_PLAYERNUMBER: case ACS0_OP_ACTIVATORTID: *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = 0; *codePtr++ = opdata->opdata->op; *codePtr++ = ACS_translateThingVarACS0(opdata); break; case ACS0_OP_GAMETYPE_ONEFLAGCTF: *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = 0; break; case ACS0_OP_GAMETYPE_SINGLEPLAYER: *codePtr++ = opdata->opdata->op; *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = gt_single; *codePtr++ = ACS_OP_CMP_EQ; break; case ACS0_OP_RANDOM_IMM_BYTE: brover = (byte *)rover; ACS_translateFuncACS0(codePtr, opdata); for(int i = opdata->args; i--;) *codePtr++ = *brover++; break; case ACS0_OP_SETMUSIC_IMM: case ACS0_OP_SETMUSICLOCAL_IMM: case ACS0_OP_SPAWNPOINT_IMM: case ACS0_OP_SPAWNSPOT_IMM: ACS_translateFuncACS0(codePtr, opdata); *codePtr++ = tracer->vm->getStringIndex(SwapLong(*rover++)); // tag string for(int i = opdata->args - 1; i--;) *codePtr++ = SwapLong(*rover++); break; case ACS0_OP_BRANCH_CALLDISCARD: *codePtr++ = opdata->opdata->op; if(tracer->compressed) *codePtr++ = *(byte *)rover; else *codePtr++ = SwapLong(*rover); *codePtr++ = ACS_OP_STACK_DROP; break; case ACS0_OP_BRANCH_RETURNVOID: *codePtr++ = ACS_OP_GET_IMM; *codePtr++ = 0; *codePtr++ = opdata->opdata->op; break; case ACS0_OP_BRANCH_CASETABLE: // Align rover. rover = (int32_t *)(((uintptr_t)rover + 3) & ~3); temp = SwapLong(*rover++); *codePtr++ = opdata->opdata->op; *codePtr++ = temp; while(temp--) { *codePtr++ = SwapLong(*rover++); *jumpItr++ = codePtr; *codePtr++ = SwapLong(*rover++); } break; case ACS0_OP_CALLFUNC: if(tracer->compressed) { brover = (uint8_t *)rover; uint8_t argc = *brover++; uint16_t func = SwapUShort(*(uint16_t *)brover); ACS_translateFuncACS0(codePtr, func, argc); } else ACS_translateFuncACS0(codePtr, SwapLong(rover[1]), SwapLong(rover[0])); break; default: case_direct: // Direct translation. if(opdata->opdata->op == ACS_OP_CALLFUNC || opdata->opdata->op == ACS_OP_CALLFUNC_IMM) { ACS_translateFuncACS0(codePtr, opdata); } else *codePtr++ = opdata->opdata->op; if(tracer->compressed && opdata->compressed) { brover = (byte *)rover; for(int i = opdata->args; i--;) *codePtr++ = *brover++; } else { for(int i = opdata->args; i--;) *codePtr++ = SwapLong(*rover++); } break; } } // Set the last instruction to a KILL. *codePtr++ = ACS_OP_KILL; #ifdef RANGECHECK // If this isn't true, something very wrong has happened internally. if(codePtr != tracer->vm->code + tracer->vm->numCode) { I_Error("Incorrect code count. %i/%i/%i", (int)(codePtr - tracer->vm->code), (int)tracer->vm->numCode, (int)(tracer->lumpLength / 4)); } // Same here, this is just a sanity check. if(jumpItr != jumps + tracer->jumpCount) { I_Error("Incorrect jump count. %i/%i", (int)(jumpItr - jumps), (int)tracer->jumpCount); } #endif // Translate jumps. Has to be done after code in order to jump forward. while(jumpItr != jumps) { codePtr = *--jumpItr; if ((uint32_t)*codePtr < tracer->lumpLength) *codePtr = codeIndexMap[*codePtr]; else *codePtr = 0; } }