bool CEGALatch::loadData( std::string &path, short episode, int version, unsigned char *data, bool compresseddata ) { std::string filename; byte *RawData; Uint16 width, height; SDL_Surface *sfc; filename = getResourceFilename("egalatch.ck" + itoa(episode), path); FILE* latchfile = OpenGameFile(filename,"rb"); if(!latchfile) return false; RawData = new byte[m_latchplanesize * 4]; // get the data out of the file into the memory, decompressing it if necessary. if (compresseddata) { if (lz_decompress(latchfile, (unsigned char*) RawData)) { return 1; } } else { for(int i=0 ; i<(m_latchplanesize*4) ; i++) RawData[i] = fgetc(latchfile); } 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). unsigned long plane1, plane2, plane3, plane4; plane1 = 0; plane2 = (m_latchplanesize * 1); plane3 = (m_latchplanesize * 2); plane4 = (m_latchplanesize * 3); // ** read the 8x8 tiles ** // set up the getbit() function of CPlanes class CPlanes Planes(RawData); Planes.setOffsets(plane1 + m_fontlocation, plane2 + m_fontlocation, plane3 + m_fontlocation, plane4 + m_fontlocation, 0); // Load these graphics into the CFont Class of CGfxEngine // The original vorticon engine only uses one fontmap, but we use another for // extra icons. For example sliders are in that map g_pGfxEngine->freeFonts(); g_pGfxEngine->createEmptyFontmaps(3); g_pGfxEngine->getFont(0).loadinternalFont(); CFont &Font = g_pGfxEngine->getFont(1); Font.destroySurface(); Font.CreateSurface( g_pGfxEngine->Palette.m_Palette, SDL_SWSURFACE ); sfc = Font.getSDLSurface(); g_pGfxEngine->getFont(2).loadAlternateFont(); if(SDL_MUSTLOCK(sfc)) SDL_LockSurface(sfc); Uint8 *pixel = (Uint8*) sfc->pixels; SDL_FillRect(sfc, NULL, 0); for(int p=0;p<4;p++) Planes.readPlaneofTiles(p, pixel, 16, 8, m_fonttiles); if(SDL_MUSTLOCK(sfc)) SDL_UnlockSurface(sfc); // ** read the 16x16 tiles ** Planes.setOffsets(plane1 + m_tiles16location, plane2 + m_tiles16location, plane3 + m_tiles16location, plane4 + m_tiles16location, 0); g_pGfxEngine->freeTilemap(); g_pGfxEngine->createEmptyTilemap(2); CTilemap &Tilemap = g_pGfxEngine->getTileMap(1); Tilemap.CreateSurface( g_pGfxEngine->Palette.m_Palette, SDL_SWSURFACE, m_num16tiles, 4, 13 ); sfc = Tilemap.getSDLSurface(); SDL_FillRect(sfc,NULL, 0); if(SDL_MUSTLOCK(sfc)) SDL_LockSurface(sfc); Uint8 *u_pixel = (Uint8*) sfc->pixels; for(int p=0;p<4;p++) Planes.readPlaneofTiles(p, u_pixel, 13, 16, m_num16tiles); if(SDL_MUSTLOCK(sfc)) SDL_UnlockSurface(sfc); // Load Hi-Colour, VGA, SVGA Tiles into the tilemap filename = getResourceFilename("gfx/ck" + itoa(episode) + "tiles.bmp", path, false); if(Tilemap.loadHiresTile(filename)) g_pLogFile->textOut(GREEN, "VGA Bitmap for Tileset has been loaded successfully!"); // Adapt the tilemap to the display, so they are faster blit Tilemap.optimizeSurface(); // make masked tiles according to it's surfaces applyMasks(); //////////////////// /// Load Bitmaps /// //////////////////// Planes.setOffsets(plane1 + m_bitmaplocation, plane2 + m_bitmaplocation, plane3 + m_bitmaplocation, plane4 + m_bitmaplocation, 0); // decode bitmaps into the BitmapData structure. The bitmaps are // loaded into one continuous stream of image data, with the bitmaps[] // array giving pointers to where each bitmap starts within the stream. for(int p=0 ; p<4 ; p++) { for(int b=0 ; b<m_bitmaps ; b++) { CBitmap &bitmap = g_pGfxEngine->getBitmap(b); // this points to the location that we're currently // decoding bitmap data to sfc= bitmap.getSDLSurface(); if(SDL_MUSTLOCK(sfc)) SDL_LockSurface(sfc); Uint8* pixel = (Uint8*) sfc->pixels; if(p==0) SDL_FillRect(sfc, NULL, 0); width = bitmap.getWidth(); height = bitmap.getHeight(); // Now read the raw data Planes.readPlane(p, pixel, width, height); if(SDL_MUSTLOCK(sfc)) SDL_UnlockSurface(sfc); } } // optimize the bitmaps and load hq bitmaps if there are some. for(int b=0 ; b<m_bitmaps ; b++) { CBitmap &bitmap = g_pGfxEngine->getBitmap(b); bitmap.optimizeSurface(); } std::set<std::string> filelist; FileListAdder fileListAdder; std::string gfxpath = JoinPaths(path, "gfx"); GetFileList(filelist, fileListAdder, gfxpath, false, FM_REG); FilterFilelist(filelist, "bitmap"); std::set<std::string>::iterator it = filelist.begin(); for( ; it != filelist.end() ; it++ ) { std::string filename=*it; int num = getRessourceID(filename, "bitmap"); CBitmap &bitmap = g_pGfxEngine->getBitmap(num); filename = getResourceFilename("gfx/" + filename, path, false); bitmap.loadHQBitmap(filename); } if(RawData){ delete[] RawData; RawData = NULL;} return true; }
bool CMapLoaderGalaxy::loadMap(CMap &Map, Uint8 level) { // Get the MAPHEAD Location from within the Exe File or an external file std::vector<char> mapHeadContainer; const std::string &path = gKeenFiles.gameDir; // Set Map position and some flags for the freshly loaded level Map.gotoPos(0,0); Map.setLevel(level); Map.isSecret = false; Map.mNumFuses = 0; // In case no external file was read, let's use data from the embedded data byte *Maphead = gKeenFiles.exeFile.getRawData() + getMapheadOffset(); // In case there is an external file read it into the container and replace the pointer const std::string mapHeadFilename = gKeenFiles.mapheadFilename; std::ifstream MapHeadFile; if(OpenGameFileR(MapHeadFile, getResourceFilename(mapHeadFilename,path,true,false), std::ios::binary)) { // get length of file: MapHeadFile.seekg (0, std::ios::end); unsigned int length = MapHeadFile.tellg(); MapHeadFile.seekg (0, std::ios::beg); mapHeadContainer.resize(length); MapHeadFile.read(&mapHeadContainer[0],length*sizeof(char)); Maphead = reinterpret_cast<byte*>(&mapHeadContainer[0]); } word magic_word; longword level_offset; // Get the magic number of the level data from MAPHEAD Located in the EXE-File. // This is used for the decompression. magic_word = READWORD(Maphead); // Get location of the level data from MAPHEAD Located in the EXE-File. Maphead += level*sizeof(longword); level_offset = READLONGWORD(Maphead); // Open the Gamemaps file std::string gamemapfile = gKeenFiles.gamemapsFilename; std::ifstream MapFile; if(OpenGameFileR(MapFile, getResourceFilename(gamemapfile,path,true,false), std::ios::binary)) { if(level_offset == 0 && mapHeadContainer.empty()) { MapFile.close(); gLogging.textOut("This Level doesn't exist in GameMaps"); return false; } // Then jump to that location and read the level map data MapFile.seekg (level_offset, std::ios::beg); int headbegin; // Get the level plane header if(gotoNextSignature(MapFile)) { /* * Plane Offsets: Long[3] Offset within GAMEMAPS to the start of the plane. The first offset is for the background plane, the * second for the foreground plane, and the third for the info plane (see below). * Plane Lengths: Word[3] Length (in bytes) of the compressed plane data. The first length is for the background plane, the * second for the foreground plane, and the third for the info plane (see below). * Width: Word Level width (in tiles). * Height: Word Level height (in tiles). Together with Width, this can be used to calculate the uncompressed * size of plane data, by multiplying Width by Height and multiplying the result by sizeof(Word). * Name: Byte[16] Null-terminated string specifying the name of the level. This name is used only by TED5, not by Keen. * Signature: Byte[4] Marks the end of the Level Header. Always "!ID!". */ int jumpback = 3*sizeof(longword) + 3*sizeof(word) + 2*sizeof(word) + 16*sizeof(byte) + 4*sizeof(byte); headbegin = static_cast<int>(MapFile.tellg()) - jumpback; } else { MapFile.clear(); headbegin = level_offset; } MapFile.seekg( headbegin, std::ios_base::beg); // Get the header of level data longword Plane_Offset[3]; longword Plane_Length[3]; word Width, Height; char name[17]; // Get the plane offsets Plane_Offset[0] = fgetl(MapFile); Plane_Offset[1] = fgetl(MapFile); Plane_Offset[2] = fgetl(MapFile); // Get the dimensions of the level Plane_Length[0] = fgetw(MapFile); Plane_Length[1] = fgetw(MapFile); Plane_Length[2] = fgetw(MapFile); Width = fgetw(MapFile); Height = fgetw(MapFile); if(Width>1024 || Height>1024) { gLogging.textOut("Sorry, but I cannot uncompress this map and must give up." "Please report this to the developers and send that version to them in order to fix it.<br>" ); return false; } for(int c=0 ; c<16 ; c++) { name[c] = MapFile.get(); } name[16] = '\0'; // Get and check the signature gLogging.textOut("Loading the Level \"" + static_cast<std::string>(name) + "\" (Level No. "+ itoa(level) + ")<br>" ); Map.setLevelName(name); mLevelName = name; // Then decompress the level data using rlew and carmack gLogging.textOut("Decompressing the Map...<br>" ); // Start with the Background Map.createEmptyDataPlane(0, Width, Height); Map.createEmptyDataPlane(1, Width, Height); Map.createEmptyDataPlane(2, Width, Height); unpackPlaneData(MapFile, Map, 0, Plane_Offset[0], Plane_Length[0], magic_word); unpackPlaneData(MapFile, Map, 1, Plane_Offset[1], Plane_Length[1], magic_word); unpackPlaneData(MapFile, Map, 2, Plane_Offset[2], Plane_Length[2], magic_word); Map.collectBlockersCoordiantes(); MapFile.close(); // Now that we have all the 3 planes (Background, Foreground, Foes) unpacked... // We only will show the first two of them in the screen, because the Foes one // is the one which will be used for spawning the foes (Keen, platforms, enemies, etc.) spawnFoes(Map); } else { return false; } // Set Scrollbuffer Map.drawAll(); gVideoDriver.updateScrollBuffer(Map.m_scrollx, Map.m_scrolly); return true; }
bool CSoundSlot::HQSndLoad(const std::string& gamepath, const std::string& soundname) { SDL_AudioSpec AudioFileSpec; const SDL_AudioSpec &audioSpec = g_pSound->getAudioSpec(); SDL_AudioCVT Audio_cvt; std::string buf; Uint32 length = 0; Uint8 *oggdata = nullptr; Uint8 *wavdata = nullptr; #if defined(OGG) || defined(TREMOR) buf = getResourceFilename("snd/" + soundname + ".OGG", gamepath, false, true); // Start with OGG if(buf != "") { openOGGSound(buf, &AudioFileSpec, oggdata, length); if(oggdata == nullptr) { gLogging.textOut(PURPLE,"Something is wrong with \"%s\"<br>", buf); return false; } #else gLogging.textOut(PURPLE,"NOTE: OGG-Support is disabled! Get another version or compile it yourself!<br>"); #endif #if defined(OGG) || defined(TREMOR) } else { #endif buf = getResourceFilename("snd/" + soundname + ".WAV", gamepath, false); // Start with OGG if(buf == "") return false; // Check, if it is a wav file or go back to classic sounds if (SDL_LoadWAV (Utf8ToSystemNative(GetFullFileName(buf)).c_str(), &AudioFileSpec, &wavdata, &length) == NULL) return false; #if defined(OGG) || defined(TREMOR) } #endif // Build AudioCVT (This is needed for the conversion from one format to the one used in the game) const int ret = SDL_BuildAudioCVT(&Audio_cvt, AudioFileSpec.format, AudioFileSpec.channels, AudioFileSpec.freq, audioSpec.format, audioSpec.channels, audioSpec.freq); // Check that the convert was built if(ret == -1) { gLogging.textOut(PURPLE,"Couldn't convert the sound correctly!<br>"); SDL_FreeWAV(wavdata); return false; } // Setup for conversion, copy original data to new buffer Audio_cvt.buf = (Uint8*) malloc(length * Audio_cvt.len_mult); Audio_cvt.len = length; if(oggdata) memcpy(Audio_cvt.buf, oggdata, length); else memcpy(Audio_cvt.buf, wavdata, length); // We can delete to original WAV data now if(oggdata) free(oggdata); else SDL_FreeWAV(wavdata); // And now we're ready to convert SDL_ConvertAudio(&Audio_cvt); // copy the converted stuff to the original soundbuffer Uint8 *buffer; if( !mHasCommonFreqBase ) { const float factor = float(audioSpec.freq)/mOggFreq; length = Audio_cvt.len_cvt; const unsigned long out_len = (float)length*factor; buffer = (Uint8*) malloc(out_len); resample(buffer, Audio_cvt.buf, out_len, length, audioSpec.format, audioSpec.channels); length = out_len; } else { length = Audio_cvt.len_cvt; buffer = (Uint8*) malloc(length); memcpy(buffer, Audio_cvt.buf, length); } setupWaveForm(buffer, length); free(buffer); // Structure Audio_cvt must be freed! free(Audio_cvt.buf); return true; }