bool isPCX(const unsigned char *header)//check whether file can be PCX according to 1st 12 bytes { int fSize = read_le_u32(header + 0); int width = read_le_u32(header + 4); int height = read_le_u32(header + 8); return fSize == width*height || fSize == width*height*3; }
std::array<CBitmapFont::Char, CBitmapFont::totalChars> CBitmapFont::loadChars() const { std::array<Char, totalChars> ret; size_t offset = 32; for (auto & elem : ret) { elem.leftOffset = read_le_u32(data.first.get() + offset); offset+=4; elem.width = read_le_u32(data.first.get() + offset); offset+=4; elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4; } for (auto & elem : ret) { int pixelOffset = read_le_u32(data.first.get() + offset); offset+=4; elem.pixels = data.first.get() + 4128 + pixelOffset; assert(pixelOffset + 4128 < data.second); } return ret; }
bool isPCX(const ui8 *header)//check whether file can be PCX according to header { int fSize = read_le_u32(header + 0); int width = read_le_u32(header + 4); int height = read_le_u32(header + 8); return fSize == width*height || fSize == width*height*3; }
CDefFile::CDefFile(std::string Name): data(nullptr), palette(nullptr) { //First 8 colors in def palette used for transparency static SDL_Color H3Palette[8] = { { 0, 0, 0, 0},// 100% - transparency { 0, 0, 0, 64},// 75% - shadow border, { 0, 0, 0, 128},// TODO: find exact value { 0, 0, 0, 128},// TODO: for transparency { 0, 0, 0, 128},// 50% - shadow body { 0, 0, 0, 0},// 100% - selection highlight { 0, 0, 0, 128},// 50% - shadow body below selection { 0, 0, 0, 64} // 75% - shadow border below selection }; data = animationCache.getCachedFile(ResourceID(std::string("SPRITES/") + Name, EResType::ANIMATION)); palette = new SDL_Color[256]; int it = 0; ui32 type = read_le_u32(data + it); it+=4; //int width = read_le_u32(data + it); it+=4;//not used //int height = read_le_u32(data + it); it+=4; it+=8; ui32 totalBlocks = read_le_u32(data + it); it+=4; for (ui32 i= 0; i<256; i++) { palette[i].r = data[it++]; palette[i].g = data[it++]; palette[i].b = data[it++]; CSDL_Ext::colorSetAlpha(palette[i],255); } if (type == 71 || type == 64)//Buttons/buildings don't have shadows\semi-transparency memset(palette, 0, sizeof(SDL_Color)*2); else memcpy(palette, H3Palette, sizeof(SDL_Color)*8);//initialize shadow\selection colors for (ui32 i=0; i<totalBlocks; i++) { size_t blockID = read_le_u32(data + it); it+=4; size_t totalEntries = read_le_u32(data + it); it+=12; //8 unknown bytes - skipping //13 bytes for name of every frame in this block - not used, skipping it+= 13 * totalEntries; for (ui32 j=0; j<totalEntries; j++) { size_t currOffset = read_le_u32(data + it); offset[blockID].push_back(currOffset); it += 4; } } }
static int handler_fmt (riff_context *ctxt) { uint8_t buf[1024] = { 0, }; const uint32_t size = read_le_u32 (ctxt); int i; vcd_assert (size < sizeof (buf)); fread (buf, 1, (size % 2) ? size + 1 : size, ctxt->fd); { char *strbuf = _vcd_malloc (1 + size * 6); strbuf[0] = '\0'; for (i = 0; i < size; i++) { char _buf[7] = { 0, }; snprintf (_buf, sizeof (_buf) - 1, "%.2x ", buf[i]); strcat (strbuf, _buf); } vcd_info ("CDXA fmt[%d] = 0x%s", size, strbuf); free (strbuf); } return 0; }
static int handler_RIFF (riff_context *ctxt) { const uint32_t size = read_le_u32 (ctxt); vcd_info ("RIFF data[%d]", size); ctxt->lsize = ctxt->size = size; return next_id (ctxt); }
static int handler_data (riff_context *ctxt) { const uint32_t size = read_le_u32 (ctxt); uint32_t sectors; if (size % 2352) vcd_warn ("size not a multiple of 2352 bytes!!"); sectors = size / 2352; vcd_info ("CDXA data[%d] (%d sectors)", size, sectors); if (ctxt->fd_out) { long first_nzero = -1, last_nzero = -1, s; struct { uint8_t sync[12]; uint8_t header[4]; uint8_t subheader[8]; uint8_t data[2324]; uint8_t edc[4]; } sbuf; vcd_assert (sizeof (sbuf) == 2352); vcd_info ("...converting..."); for (s = 0; s < sectors; s++) { int r = fread (&sbuf, 2352, 1, ctxt->fd); bool empty = true; { int i; for (i = 0; (i < 2324) && !sbuf.data[i]; i++); empty = i == 2324; } if (!r) { if (ferror (ctxt->fd)) vcd_error ("fread (): %s", strerror (errno)); if (feof (ctxt->fd)) vcd_warn ("premature end of file encountered after %ld sectors", s); fclose (ctxt->fd); fclose (ctxt->fd_out); exit (EXIT_FAILURE); } if (empty) { if (first_nzero == -1) continue; } else { last_nzero = s; if (first_nzero == -1) first_nzero = s; } fwrite (&sbuf.data, 2324, 1, ctxt->fd_out); } fflush (ctxt->fd_out); { const long allsecs = (last_nzero - first_nzero + 1); ftruncate (fileno (ctxt->fd_out), allsecs * 2324); vcd_info ("...stripped %ld leading and %ld trailing empty sectors...", first_nzero, (sectors - last_nzero - 1)); vcd_info ("...extraction done (%ld sectors extracted to file)!", allsecs); } } else vcd_warn ("no extraction done, since no output file was given"); return 0; }
SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size) { SDL_Surface * ret; Epcxformat format; int it=0; ui32 fSize = read_le_u32(pcx + it); it+=4; ui32 width = read_le_u32(pcx + it); it+=4; ui32 height = read_le_u32(pcx + it); it+=4; if (fSize==width*height*3) format=PCX24B; else if (fSize==width*height) format=PCX8B; else return nullptr; if (format==PCX8B) { ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0); it = 0xC; for (int i=0; i<height; i++) { memcpy((char*)ret->pixels + ret->pitch * i, pcx + it, width); it+= width; } //palette - last 256*3 bytes it = size-256*3; for (int i=0; i<256; i++) { SDL_Color tp; tp.r = pcx[it++]; tp.g = pcx[it++]; tp.b = pcx[it++]; tp.unused = SDL_ALPHA_OPAQUE; ret->format->palette->colors[i] = tp; } } else { #if (SDL_BYTEORDER == SDL_BIG_ENDIAN) int bmask = 0xff0000; int gmask = 0x00ff00; int rmask = 0x0000ff; #else int bmask = 0x0000ff; int gmask = 0x00ff00; int rmask = 0xff0000; #endif ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, rmask, gmask, bmask, 0); //it == 0xC; for (int i=0; i<height; i++) { memcpy((char*)ret->pixels + ret->pitch * i, pcx + it, width*3); it+= width*3; } } return ret; }
void CDefHandler::openFromMemory(ui8 *table, const std::string & name) { SDL_Color palette[256]; SDefEntry &de = * reinterpret_cast<SDefEntry *>(table); ui8 *p; defName = name; DEFType = read_le_u32(&de.DEFType); width = read_le_u32(&de.width); height = read_le_u32(&de.height); ui32 totalBlocks = read_le_u32(&de.totalBlocks); for (ui32 it=0;it<256;it++) { palette[it].r = de.palette[it].R; palette[it].g = de.palette[it].G; palette[it].b = de.palette[it].B; palette[it].unused = 255; } // The SDefEntryBlock starts just after the SDefEntry p = reinterpret_cast<ui8 *>(&de); p += sizeof(de); int totalEntries=0; for (ui32 z=0; z<totalBlocks; z++) { SDefEntryBlock &block = * reinterpret_cast<SDefEntryBlock *>(p); ui32 totalInBlock; totalInBlock = read_le_u32(&block.totalInBlock); for (ui32 j=SEntries.size(); j<totalEntries+totalInBlock; j++) SEntries.push_back(SEntry()); p = block.data; for (ui32 j=0; j<totalInBlock; j++) { char Buffer[13]; memcpy(Buffer, p, 12); Buffer[12] = 0; SEntries[totalEntries+j].name=Buffer; p += 13; } for (ui32 j=0; j<totalInBlock; j++) { SEntries[totalEntries+j].offset = read_le_u32(p); p += 4; } //totalEntries+=totalInBlock; for(ui32 hh=0; hh<totalInBlock; ++hh) { SEntries[totalEntries].group = z; ++totalEntries; } } for(auto & elem : SEntries) { elem.name = elem.name.substr(0, elem.name.find('.')+4); } //RWEntries = new ui32[height]; for(ui32 i=0; i < SEntries.size(); ++i) { Cimage nimg; nimg.bitmap = getSprite(i, table, palette); nimg.imName = SEntries[i].name; nimg.groupNumber = SEntries[i].group; ourImages.push_back(nimg); } }
SDL_Surface * CPCXConv::getSurface() const { SDL_Surface * ret; int width = -1, height = -1; Epcxformat format; int fSize,y; unsigned char add; int it=0; fSize = read_le_u32(pcx + it); it+=4; width = read_le_u32(pcx + it); it+=4; height = read_le_u32(pcx + it); it+=4; if (fSize==width*height*3) format=PCX24B; else if (fSize==width*height) format=PCX8B; else return NULL; add = 4 - width%4; if (add==4) add=0; if (format==PCX8B) { ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width+add, height, 8, 0, 0, 0, 0); it = pcxs-256*3; for (int i=0;i<256;i++) { SDL_Color tp; #if (SDL_BYTEORDER == SDL_BIG_ENDIAN) tp.b = pcx[it++]; tp.g = pcx[it++]; tp.r = pcx[it++]; #else tp.r = pcx[it++]; tp.g = pcx[it++]; tp.b = pcx[it++]; #endif tp.unused = 0; *(ret->format->palette->colors+i) = tp; } for (y=height; y>0; --y) { it = 0xC + (y-1)*width; memcpy((char*)ret->pixels + ret->pitch * (y-1), pcx + it, width); if (add>0) { memset((char*)ret->pixels + ret->pitch * (y-1) + width, 0, add); } } } else { #if (SDL_BYTEORDER == SDL_BIG_ENDIAN) int bmask = 0xff0000; int gmask = 0x00ff00; int rmask = 0x0000ff; #else int bmask = 0x0000ff; int gmask = 0x00ff00; int rmask = 0xff0000; #endif ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width+add, height, 24, rmask, gmask, bmask, 0); for (y=height; y>0; y--) { it = 0xC + (y-1)*width*3; memcpy((char*)ret->pixels + ret->pitch * (y-1), pcx + it, width*3); if (add>0) { memset((char*)ret->pixels + ret->pitch * (y-1) + width*3, 0, add*3); } } } return ret; }
void CDefFile::loadFrame(size_t frame, size_t group, ImageLoader &loader) const { std::map<size_t, std::vector <size_t> >::const_iterator it; it = offset.find(group); assert (it != offset.end()); const ui8 * FDef = data+it->second[frame]; const SSpriteDef sd = * reinterpret_cast<const SSpriteDef *>(FDef); SSpriteDef sprite; sprite.format = read_le_u32(&sd.format); sprite.fullWidth = read_le_u32(&sd.fullWidth); sprite.fullHeight = read_le_u32(&sd.fullHeight); sprite.width = read_le_u32(&sd.width); sprite.height = read_le_u32(&sd.height); sprite.leftMargin = read_le_u32(&sd.leftMargin); sprite.topMargin = read_le_u32(&sd.topMargin); ui32 currentOffset = sizeof(SSpriteDef); ui32 BaseOffset = sizeof(SSpriteDef); loader.init(Point(sprite.width, sprite.height), Point(sprite.leftMargin, sprite.topMargin), Point(sprite.fullWidth, sprite.fullHeight), palette); switch (sprite.format) { case 0: { //pixel data is not compressed, copy data to surface for (ui32 i=0; i<sprite.height; i++) { loader.Load(sprite.width, FDef[currentOffset]); currentOffset += sprite.width; loader.EndLine(); } break; } case 1: { //for each line we have offset of pixel data const ui32 * RWEntriesLoc = reinterpret_cast<const ui32 *>(FDef+currentOffset); currentOffset += sizeof(ui32) * sprite.height; for (ui32 i=0; i<sprite.height; i++) { //get position of the line currentOffset=BaseOffset + read_le_u32(RWEntriesLoc + i); ui32 TotalRowLength = 0; while (TotalRowLength<sprite.width) { ui8 type=FDef[currentOffset++]; ui32 length=FDef[currentOffset++] + 1; if (type==0xFF)//Raw data { loader.Load(length, FDef + currentOffset); currentOffset+=length; } else// RLE { loader.Load(length, type); } TotalRowLength += length; } loader.EndLine(); } break; } case 2: { currentOffset = BaseOffset + read_le_u16(FDef + BaseOffset); for (ui32 i=0; i<sprite.height; i++) { ui32 TotalRowLength=0; while (TotalRowLength<sprite.width) { ui8 SegmentType=FDef[currentOffset++]; ui8 code = SegmentType / 32; ui8 length = (SegmentType & 31) + 1; if (code==7)//Raw data { loader.Load(length, FDef[currentOffset]); currentOffset += length; } else//RLE { loader.Load(length, code); } TotalRowLength+=length; } loader.EndLine(); } break; } case 3: { for (ui32 i=0; i<sprite.height; i++) { currentOffset = BaseOffset + read_le_u16(FDef + BaseOffset+i*2*(sprite.width/32)); ui32 TotalRowLength=0; while (TotalRowLength<sprite.width) { ui8 segment = FDef[currentOffset++]; ui8 code = segment / 32; ui8 length = (segment & 31) + 1; if (code==7)//Raw data { loader.Load(length, FDef + currentOffset); currentOffset += length; } else//RLE { loader.Load(length, code); } TotalRowLength += length; } loader.EndLine(); } break; } default: logGlobal->errorStream()<<"Error: unsupported format of def file: "<<sprite.format; break; } };
void CDefHandler::openFromMemory(unsigned char *table, const std::string & name) { BMPPalette palette[256]; SDefEntry &de = * reinterpret_cast<SDefEntry *>(table); unsigned char *p; defName = name; DEFType = SDL_SwapLE32(de.DEFType); width = SDL_SwapLE32(de.width); height = SDL_SwapLE32(de.height); unsigned int totalBlocks = SDL_SwapLE32(de.totalBlocks); for (unsigned int it=0;it<256;it++) { palette[it].R = de.palette[it].R; palette[it].G = de.palette[it].G; palette[it].B = de.palette[it].B; palette[it].F = 0; } // The SDefEntryBlock starts just after the SDefEntry p = reinterpret_cast<unsigned char *>(&de); p += sizeof(de); int totalEntries=0; for (unsigned int z=0; z<totalBlocks; z++) { SDefEntryBlock &block = * reinterpret_cast<SDefEntryBlock *>(p); unsigned int totalInBlock; totalInBlock = read_le_u32(&block.totalInBlock); for (unsigned int j=SEntries.size(); j<totalEntries+totalInBlock; j++) SEntries.push_back(SEntry()); p = block.data; for (unsigned int j=0; j<totalInBlock; j++) { char Buffer[13]; memcpy(Buffer, p, 12); Buffer[12] = 0; SEntries[totalEntries+j].name=Buffer; p += 13; } for (unsigned int j=0; j<totalInBlock; j++) { SEntries[totalEntries+j].offset = read_le_u32(p); p += 4; } //totalEntries+=totalInBlock; for(unsigned int hh=0; hh<totalInBlock; ++hh) { SEntries[totalEntries].group = z; ++totalEntries; } } for(unsigned int j=0; j<SEntries.size(); ++j) { SEntries[j].name = SEntries[j].name.substr(0, SEntries[j].name.find('.')+4); } //RWEntries = new unsigned int[height]; for(unsigned int i=0; i < SEntries.size(); ++i) { Cimage nimg; nimg.bitmap = getSprite(i, table, palette); nimg.imName = SEntries[i].name; nimg.groupNumber = SEntries[i].group; ourImages.push_back(nimg); } }