diff --git a/src/CLatch.cpp b/src/CLatch.cpp new file mode 100644 index 000000000..bb6165230 --- /dev/null +++ b/src/CLatch.cpp @@ -0,0 +1,531 @@ +/* + * CLatch.cpp + * + * Created on: 02.05.2009 + * Author: gerstrong + */ + +#include +#include +#include +#include "CLatch.h" +#include "vorticon/CPlanes.h" +#include "fileio.h" +#include "keen.h" +#include "keenext.h" +#include "StringUtils.h" + +#include "CLogFile.h" +//#include "vorticon/CEGAGraphics.h" + +CLatch::CLatch() { + SpriteTable = NULL; + BitmapTable = NULL; + BitmapData = NULL; + RawData = NULL; +} + +CLatch::~CLatch() { + + if (SpriteTable){ delete[] SpriteTable; SpriteTable = NULL;} + if (BitmapTable){ delete[] BitmapTable; BitmapTable = NULL;} + if (RawData){ delete[] RawData; RawData = NULL;} + if (BitmapData) + { + delete[] BitmapData; BitmapData = NULL; + g_pLogFile->textOut(BLACK," Bitmap data released to system.
"); + } +} + +char CLatch::loadGraphics(int episode, const char *path) +{ + int retval = 0; + + if (SpriteTable){ delete[] SpriteTable; SpriteTable = NULL;} + if (BitmapTable){ delete[] BitmapTable; BitmapTable = NULL;} + if (BitmapData){ delete[] BitmapData; BitmapData = NULL;} + if (RawData){ delete[] RawData; RawData = NULL;} + + if (loadHeader(episode, path)) { retval = 1; } + if (load(episode, path)) { retval = 1; } + if (loadSprites(episode, path)) { retval = 1; } + + return retval; +} + +// load the EGAHEAD file +char CLatch::loadHeader(int episode, const char *path) +{ + FILE *headfile; + unsigned long SpriteTableRAMSize; + unsigned long BitmapTableRAMSize; + std::string buf; + int i,j,k; + std::string fname; + std::string buffer; + + buffer = formatPathString(path); + buffer += "egahead.ck"; + + fname = buffer + itoa(episode); + + /*CEGAGraphics *EGAGraphics; + + EGAGraphics = new CEGAGraphics(episode); + + EGAGraphics->loadData(); + + delete EGAGraphics;*/ + + headfile = fopen(fname.c_str(), "rb"); + if (!headfile) + { + g_pLogFile->ftextOut("latch_loadheader(): unable to open '%s'.
", fname.c_str()); + return 1; + } + + g_pLogFile->ftextOut("latch_loadheader(): reading main header from '%s'...
", fname.c_str()); + + // read the main header data from EGAHEAD + LatchHeader.LatchPlaneSize = fgetl(headfile); + LatchHeader.SpritePlaneSize = fgetl(headfile); + LatchHeader.OffBitmapTable = fgetl(headfile); + LatchHeader.OffSpriteTable = fgetl(headfile); + LatchHeader.Num8Tiles = fgeti(headfile); + LatchHeader.Off8Tiles = fgetl(headfile); + LatchHeader.Num32Tiles = fgeti(headfile); + LatchHeader.Off32Tiles = fgetl(headfile); + LatchHeader.Num16Tiles = fgeti(headfile); + LatchHeader.Off16Tiles = fgetl(headfile); + LatchHeader.NumBitmaps = fgeti(headfile); + LatchHeader.OffBitmaps = fgetl(headfile); + LatchHeader.NumSprites = fgeti(headfile); + LatchHeader.OffSprites = fgetl(headfile); + LatchHeader.Compressed = fgeti(headfile); + + g_pLogFile->ftextOut(" LatchPlaneSize = 0x%04x
", LatchHeader.LatchPlaneSize); + g_pLogFile->ftextOut(" SpritePlaneSize = 0x%04x
", LatchHeader.SpritePlaneSize); + g_pLogFile->ftextOut(" OffBitmapTable = 0x%04x
", LatchHeader.OffBitmapTable); + g_pLogFile->ftextOut(" OffSpriteTable = 0x%04x
", LatchHeader.OffSpriteTable); + g_pLogFile->ftextOut(" Num8Tiles = %d
", LatchHeader.Num8Tiles); + g_pLogFile->ftextOut(" Off8Tiles = 0x%04x
", LatchHeader.Off8Tiles); + g_pLogFile->ftextOut(" Num32Tiles = %d
", LatchHeader.Num32Tiles); + g_pLogFile->ftextOut(" Off32Tiles = 0x%04x
", LatchHeader.Off32Tiles); + g_pLogFile->ftextOut(" Num16Tiles = %d
", LatchHeader.Num16Tiles); + g_pLogFile->ftextOut(" Off16Tiles = 0x%04x
", LatchHeader.Off16Tiles); + g_pLogFile->ftextOut(" NumBitmaps = %d
", LatchHeader.NumBitmaps); + g_pLogFile->ftextOut(" OffBitmaps = 0x%04x
", LatchHeader.OffBitmaps); + g_pLogFile->ftextOut(" NumSprites = %d
", LatchHeader.NumSprites); + g_pLogFile->ftextOut(" OffSprites = 0x%04x
", LatchHeader.OffSprites); + g_pLogFile->ftextOut(" Compressed = %d
", LatchHeader.Compressed); + + /// read in the sprite table + + // allocate memory for the sprite table + SpriteTableRAMSize = sizeof(SpriteHead) * (LatchHeader.NumSprites + 1); + g_pLogFile->ftextOut("latch_loadheader(): Allocating %d bytes for sprite table.
", SpriteTableRAMSize); + + SpriteTable = new SpriteHead[SpriteTableRAMSize]; + if (!SpriteTable) + { + g_pLogFile->ftextOut("latch_loadheader(): Can't allocate sprite table!
"); + return 1; + } + + g_pLogFile->ftextOut("latch_loadheader(): Reading sprite table from '%s'...
", fname.c_str()); + + fseek(headfile, LatchHeader.OffSpriteTable, SEEK_SET); + for(i=0;i> 8); + SpriteTable[i].Ry1 = (fgeti(headfile) >> 8); + SpriteTable[i].Rx2 = (fgeti(headfile) >> 8); + SpriteTable[i].Ry2 = (fgeti(headfile) >> 8); + for(j=0;j<16;j++) SpriteTable[i].Name[j] = fgetc(headfile); + // for some reason each sprite occurs 4 times in the table. + // we're only interested in the first occurance. + // These are copies for smoother rendering. Not needed since SDL and HW_SURFACE + for(j=0;j<3;j++) + { + for(k=0;k < static_cast(sizeof(SpriteHead));k++) fgetc(headfile); + } + + } + + // read in the bitmap table + + // allocate memory for the bitmap table + BitmapTableRAMSize = sizeof(BitmapHead) * (LatchHeader.NumBitmaps + 1); + g_pLogFile->ftextOut("latch_loadheader(): Allocating %d bytes for bitmap table.
", BitmapTableRAMSize); + + BitmapTable = new BitmapHead[BitmapTableRAMSize]; + if (!BitmapTable) + { + g_pLogFile->ftextOut("latch_loadheader(): Can't allocate bitmap table!
"); + return 1; + } + + g_pLogFile->ftextOut("latch_loadheader(): reading bitmap table from '%s'...
", fname.c_str()); + + fseek(headfile, LatchHeader.OffBitmapTable, SEEK_SET); + + BitmapBufferRAMSize = 0; + for(i=0;iftextOut(" Bitmap '%s': %dx%d at offset %04x. RAMAllocSize=0x%04x
", buf.c_str(),BitmapTable[i].Width,BitmapTable[i].Height,BitmapTable[i].Offset,BitmapBufferRAMSize); + } + BitmapBufferRAMSize++; + + fclose(headfile); + return 0; +} + + +// load the EGALATCH file + +char CLatch::load(int episode, const char *path) +{ +FILE *latchfile; +unsigned long plane1, plane2, plane3, plane4; + std::string fname; +int x,y,t,b,c,p; +char *bmdataptr; +unsigned long RawDataSize; +//unsigned char ch; + + std::string buffer; + + buffer = formatPathString(path); + buffer += "egalatch.ck"; + fname = buffer + itoa(episode); + + g_pLogFile->ftextOut("latch_loadlatch(): Opening file '%s'.
", fname.c_str()); + + latchfile = fopen(fname.c_str(), "rb"); + if (!latchfile) + { + g_pLogFile->ftextOut("latch_loadlatch(): Unable to open '%s'!
", fname.c_str()); + return 1; + } + + // figure out how much RAM we'll need to read all 4 planes of + // latch data into memory. + RawDataSize = (LatchHeader.LatchPlaneSize * 4); + RawData = new char[RawDataSize]; + if (!RawData) + { + g_pLogFile->ftextOut("latch_loadlatch(): Unable to allocate RawData buffer!
"); + return 1; + } + + // get the data out of the file into memory, decompressing if necessary. + if (LatchHeader.Compressed) + { + g_pLogFile->ftextOut("latch_loadlatch(): Decompressing...
"); + if (lz_decompress(latchfile, (unsigned char*) RawData)) return 1; + } + else + { + g_pLogFile->ftextOut("latch_loadlatch(): Reading %d bytes...
", RawDataSize); + if(!fread(RawData, 1, RawDataSize, latchfile)) + { + g_pLogFile->ftextOut(RED,"latch_loadlatch(): Error reading the file...
"); + return 1; + } + } + fclose(latchfile); + + // these are the offsets of the different video planes as + // relative to each other--that is if a pixel in plane1 + // is at N, the byte for that same pixel in plane3 will be + // at (N + plane3). + plane1 = 0; + plane2 = (LatchHeader.LatchPlaneSize * 1); + plane3 = (LatchHeader.LatchPlaneSize * 2); + plane4 = (LatchHeader.LatchPlaneSize * 3); + + // ** read the 8x8 tiles ** + g_pLogFile->ftextOut("latch_loadlatch(): Decoding 8x8 tiles...
", fname.c_str()); + + // set up the getbit() function + + CPlanes *Planes = new CPlanes(plane1 + LatchHeader.Off8Tiles, \ + plane2 + LatchHeader.Off8Tiles, \ + plane3 + LatchHeader.Off8Tiles, \ + plane4 + LatchHeader.Off8Tiles, \ + 0); + + for(p=0;p<4;p++) + { + for(t=0;tgetbit(RawData, p) << p); + // map black pixels to color 16 because of the way the + // vorticon death sequence works in ep1 + if (p==3 && c==0) c = 16; + font[t][y][x] = c; + } + } + } + } + + delete Planes; + + // ** read the 16x16 tiles ** + g_pLogFile->ftextOut("latch_loadlatch(): Decoding 16x16 tiles...
", fname.c_str()); + + // set up the getbit() function + Planes = new CPlanes(plane1 + LatchHeader.Off16Tiles, \ + plane2 + LatchHeader.Off16Tiles, \ + plane3 + LatchHeader.Off16Tiles, \ + plane4 + LatchHeader.Off16Tiles, \ + 0); + + for(p=0;p<4;p++) + { + for(t=0;tgetbit(RawData, p) << p); + if (p==3 && c==0) c = 16; + + tiledata[t][y][x] = c; + } + } + } + } + + delete Planes; + + // ** read the bitmaps ** + g_pLogFile->ftextOut("latch_loadlatch(): Allocating %d bytes for bitmap data...
", BitmapBufferRAMSize); + BitmapData = new char[BitmapBufferRAMSize]; + if (!BitmapData) + { + g_pLogFile->ftextOut("Cannot allocate memory for bitmaps.
"); + return 1; + } + + g_pLogFile->ftextOut("latch_loadlatch(): Decoding bitmaps...
", fname.c_str()); + + // set up the getbit() function + Planes = new CPlanes(plane1 + LatchHeader.OffBitmaps, \ + plane2 + LatchHeader.OffBitmaps, \ + plane3 + LatchHeader.OffBitmaps, \ + plane4 + LatchHeader.OffBitmaps, \ + 0); + + // decode bitmaps into the BitmapData structure. The bitmaps are + // loaded into one continous stream of image data, with the bitmaps[] + // array giving pointers to where each bitmap starts within the stream. + + for(p=0;p<4;p++) + { + // this points to the location that we're currently + // decoding bitmap data to + bmdataptr = &BitmapData[0]; + + for(b=0;bgetbit(RawData, p) << p); + if (p==3 && c==0) c = 16; + *bmdataptr = c; + bmdataptr++; + } + } + } + } + + delete Planes; + + if(RawData){ delete[] RawData; RawData = NULL;} + + return 0; +} + + + +// retrieves a bit from plane "plane". the positions of the planes +// should have been previously initilized with setplanepositions() + + +char CLatch::loadSprites(int episode, const char *path) +{ +FILE *spritfile; +unsigned long plane1, plane2, plane3, plane4, plane5; + std::string fname; +int x,y,s,c,p; +unsigned long RawDataSize; + std::string buffer; +CPlanes *Planes; + + buffer = formatPathString(path); + buffer += "egasprit.ck"; + fname = buffer + itoa(episode); + + g_pLogFile->ftextOut("latch_loadsprites(): Opening file '%s'.
", fname.c_str()); + + spritfile = fopen(fname.c_str(), "rb"); + if (!spritfile) + { + g_pLogFile->ftextOut("latch_loadsprites(): Unable to open '%s'!
", fname.c_str()); + return 1; + } + + RawDataSize = (LatchHeader.SpritePlaneSize * 5); + RawData = new char[RawDataSize]; + if (!RawData) + { + g_pLogFile->ftextOut("latch_loadlatch(): Unable to allocate RawData buffer!
"); + return 1; + } + + if (LatchHeader.Compressed) + { + g_pLogFile->ftextOut("latch_loadsprites(): Decompressing...
"); + if (lz_decompress(spritfile, (unsigned char*) RawData)) return 1; + } + else + { + g_pLogFile->ftextOut("latch_loadsprites(): Reading %d bytes...
", RawDataSize); + if(!fread(RawData, 1, RawDataSize, spritfile)) + { + g_pLogFile->ftextOut(RED,"latch_loadsprites(): Error reading the file...
"); + return 1; + } + } + fclose(spritfile); + + // these are the offsets of the different video planes as + // relative to each other--that is if a pixel in plane1 + // is at N, the byte for that same pixel in plane3 will be + // at (N + plane3). + plane1 = 0; + plane2 = (LatchHeader.SpritePlaneSize * 1); + plane3 = (LatchHeader.SpritePlaneSize * 2); + plane4 = (LatchHeader.SpritePlaneSize * 3); + plane5 = (LatchHeader.SpritePlaneSize * 4); + + // ** read the sprites ** + g_pLogFile->ftextOut("latch_loadsprites(): Decoding sprites...
", fname.c_str()); + + // set up the getbit() function + Planes = new CPlanes(plane1 + LatchHeader.OffSprites, \ + plane2 + LatchHeader.OffSprites, \ + plane3 + LatchHeader.OffSprites, \ + plane4 + LatchHeader.OffSprites, \ + plane5 + LatchHeader.OffSprites); + + // load the image data + for(p=0;p<4;p++) + { + for(s=0;sgetbit(RawData, p) << p); + if (p==3 && c==0) c = 16; + sprites[s].imgdata[y][x] = c; + } + } + } + } + + // now load the 5th plane, which contains the sprite masks. + // note that we invert the mask because our graphics functions + // use white on black masks whereas keen uses black on white. + for(s=0;sgetbit(RawData, 4)); + } + } + } + + delete Planes; + + return 0; +} + +EgaHead *CLatch::getLatchHeader(void){ return &LatchHeader;} + diff --git a/src/CLatch.h b/src/CLatch.h new file mode 100644 index 000000000..e3bfecee9 --- /dev/null +++ b/src/CLatch.h @@ -0,0 +1,76 @@ +/* + * CLatch.h + * + * Created on: 02.05.2009 + * Author: gerstrong + */ + +#ifndef CLATCH_H_ +#define CLATCH_H_ + + +// First declare the structure +typedef struct stEgaHead { + long LatchPlaneSize; //Size of one plane of latch data + long SpritePlaneSize; //Size of one plane of sprite data + long OffBitmapTable; //Offset in EGAHEAD to bitmap table + long OffSpriteTable; //Offset in EGAHEAD to sprite table + short Num8Tiles; //Number of 8x8 tiles + long Off8Tiles; //Offset of 8x8 tiles (relative to plane data) + short Num32Tiles; //Number of 32x32 tiles (always 0) + long Off32Tiles; //Offset of 32x32 tiles (relative to plane data) + short Num16Tiles; //Number of 16x16 tiles + long Off16Tiles; //Offset of 16x16 tiles (relative to plane data) + short NumBitmaps; //Number of bitmaps in table + long OffBitmaps; //Offset of bitmaps (relative to plane data) + short NumSprites; //Number of sprites + long OffSprites; //Offset of sprites (relative to plane data) + short Compressed; //(Keen 1 only) Nonzero: LZ compressed data +} EgaHead; + +typedef struct stBitmapHead { + short Width; // width of bitmap + short Height; // height of bitmap + long Offset; // offset from start of bitmap data + char Name[8]; // bitmap name +} BitmapHead; + +typedef struct stSpriteHead { + short Width; // width of sprite + short Height; // height of sprite + short OffsetDelta; // i don't know what this is + short OffsetParas; // don't know about this either + short Rx1, Ry1, Rx2, Ry2; // bounding box for hit detection + char Name[16]; // sprite name +} SpriteHead; + +// The Class begins here!! +class CLatch { +public: + CLatch(); + virtual ~CLatch(); + + char loadGraphics(int episode, const char *path); + + EgaHead *getLatchHeader(void); + +private: + + unsigned long BitmapBufferRAMSize; + + EgaHead LatchHeader; + SpriteHead *SpriteTable; + BitmapHead *BitmapTable; + char *BitmapData; + char *RawData; + + char loadHeader(int episode, const char *path); + char load(int episode, const char *path); + char loadSprites(int episode, const char *path); + unsigned char getbit(char *buf, unsigned char plane); + void setplanepositions(unsigned long p1, unsigned long p2, unsigned long p3,\ + unsigned long p4, unsigned long p5); + +}; + +#endif /* CLATCH_H_ */