// This method returns the name of the slot
std::string CSaveGameController::getSlotName(const std::string &filename)
{
    char version;
    std::ifstream StateFile;
    std::string SlotName;
    OpenGameFileR( StateFile, filename, std::ofstream::binary );

    // Check Savegame version
    version = StateFile.get();

    if(version != SAVEGAMEVERSION)
    {
        SlotName = "- File Incompatible -";
    }
    else
    {
        // read the slot name
        Uint32 size = StateFile.get();
        std::vector<char> buf(size + 1);
        readData( &buf[0], size, StateFile);
        buf[size] = '\0';
        SlotName = &buf[0];
    }

    StateFile.close();

    return SlotName;
}
/**
 * \brief This will load for you a text from a file into memory and of course automatically format it for you :-)
 * \parm	filename	filename to open
 */
bool CTextViewer::loadTextfromFile(const std::string &filename)
{
	std::string text;
    std::ifstream endfile;

    OpenGameFileR(endfile, filename);
    if (endfile.is_open())
    {
        while(!endfile.eof())
        {
        	text.push_back(endfile.get());
        }
        endfile.close();
        text.push_back('\0');
    }
    else
    {
    	g_pLogFile->textOut("Error reading \"" + filename + "\". Check if this file is in your directory!");
    	return false;
    }

    formatText(text);

    return true;
}
bool CSaveGameController::load()
{
    Uint32 size;
    std::ifstream StateFile;
    std::string fullpath = GetFullFileName(m_statefilename);
    OpenGameFileR( StateFile, m_statefilename, std::ofstream::binary );

    if (!StateFile.is_open())
    {
        g_pLogFile->textOut("Error loading \"" + fullpath + "\". Please check the status of that file.\n" );
        return false;
    }

    // Skip the header as we already chose the game
    StateFile.get(); // Skip the version info
    size = StateFile.get(); // get the size of the slotname and...
    for(Uint32 i=0 ; i<size ; i++)	// skip that name string
        StateFile.get();

    while(!StateFile.eof()) // read it everything in
        m_datablock.push_back(StateFile.get());

    // TODO: Decompression has still to be done!

    // Now write all the data to the file
    StateFile.close();

    // Done!
    g_pLogFile->textOut("File \""+ fullpath +"\" was sucessfully loaded. Size: "+itoa(m_datablock.size())+"\n");
    m_offset = 0;
    m_statefilename.clear();
    m_statename.clear();

    return true;
}
Beispiel #4
0
bool CMusic::LoadfromMusicTable(const std::string &gamepath, const std::string &levelfilename)
{
    bool fileloaded = false;
    std::ifstream Tablefile;

    std::string musicpath = getResourceFilename(JoinPaths("music", "table.cfg"), gamepath, false, true);

    if(musicpath != "")
    	fileloaded = OpenGameFileR(Tablefile, musicpath);

    if(fileloaded)
    {
    	std::string str_buf;

    	while(!Tablefile.eof())
    	{
    		getline(Tablefile, str_buf, ' ');
    		str_buf.erase(0, str_buf.find_first_not_of('\n'));
    		if( str_buf == levelfilename )	// found the level! Load the song!
    		{
    			// Get the song filename and load it!
    			getline(Tablefile, str_buf);
    			TrimSpaces(str_buf);
    			std::string filename = getResourceFilename(JoinPaths("music", str_buf), gamepath, false, true);
    			if( load(filename) )
    				play();
    			return true;
    		}
    		Tablefile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    	}
    }
	return false;
}
Beispiel #5
0
bool CHuffman::readDictionaryFromFile( const std::string &filename )
{
	std::ifstream file;

	if(!OpenGameFileR(file, filename, std::ios::binary))
	{
		return false;
	}

	file.read(reinterpret_cast<char*>(m_nodes), DICT_SIZE*sizeof(nodestruct));

	return true;
}
// This function checks if the file we want to read or save already exists
bool CSaveGameController::alreadyExits()
{
    std::ifstream StateFile;
    std::string fullpath = GetFullFileName(m_statefilename);
    OpenGameFileR( StateFile, m_statefilename, std::ofstream::binary );

    if (!StateFile.is_open())
        return false;
    else
    {
        StateFile.close();
        return true;
    }
}
void CGameLauncher::getLabels()
{
    bool found;
    Uint16 i;
    std::string line, dir;
    std::ifstream gamescfg;

    m_Names.clear();
    m_Paths.clear();

    OpenGameFileR(gamescfg, GAMESCFG);
    if (gamescfg.is_open())
    {
        while ( !gamescfg.eof() )
        {
            getline(gamescfg,line);

            if (strncmp(line.c_str(),GAMESCFG_DIR,strlen(GAMESCFG_DIR)) == 0)
            {
                dir = line.substr(strlen(GAMESCFG_DIR));

                // Check for duplicates
                found = false;
                for ( i=0; i<m_Paths.size(); i++ )
                {
                    if (strncmp(m_Paths.at(i).c_str(),dir.c_str(),dir.length()) == 0)
                    {
                        found = true;
                        break;
                    }
                }

                // If not a duplicate get the custom name
                if (!found)
                {
                    getline(gamescfg,line);
                    if (strncmp(line.c_str(),GAMESCFG_NAME,strlen(GAMESCFG_NAME)) == 0)
                    {
                        m_Paths.push_back( dir );

                        std::string gamePath = line.substr(strlen(GAMESCFG_NAME));

                        m_Names.push_back( filterGameName(gamePath) );
                    }
                }
            }
        }
        gamescfg.close();
    }
}
Beispiel #8
0
bool CMusic::LoadfromSonglist(const std::string &gamepath, const int &level)
{
    bool fileloaded = false;
    std::ifstream Tablefile;

    std::string musicpath = getResourceFilename("songlist.lst", gamepath, false, false);

    if(musicpath != "")
    	fileloaded = OpenGameFileR(Tablefile, musicpath);

    if(fileloaded)
    {
    	std::string str_buf;
    	std::string music_filename;
    	int detected_level=-1;
    	size_t next_pos = 0;

    	while(!Tablefile.eof())
    	{
    		getline(Tablefile, str_buf);

        	next_pos = str_buf.find(' ')+1;
        	str_buf = str_buf.substr(next_pos);
        	next_pos = str_buf.find(' ');

        	// Get level number            
            detected_level = atoi(str_buf.substr(0, next_pos).c_str());

        	str_buf = str_buf.substr(next_pos);
        	next_pos = str_buf.find('"')+1;
        	str_buf = str_buf.substr(next_pos);
        	next_pos = str_buf.find('"');

        	// Get the music filename to be read
        	music_filename = str_buf.substr(0, next_pos);

    		if( detected_level == level )	// found the level! Load the song!
    		{
    			// Get the song filename and load it!
    			std::string filename = getResourceFilename( music_filename, gamepath, false, true);
    			if( load(filename) )
    				play();
    			return true;
    		}
    	}
    }
	return false;
}
Beispiel #9
0
CHelp::CHelp(CExeFile &ExeFile, const std::string &type) :
mp_TextViewer(NULL)
{
	std::string Text;
	std::string DataDirectory = ExeFile.getDataDirectory();
	char episode = ExeFile.getEpisode();
	
	// Read the Storytext
	if(type == "Game")
	{
		if(episode==1)
		{
			// We suppose that we are using version 131. Maybe it must be extended
			std::string filename = DataDirectory;
			if(DataDirectory != "")
				filename += "/";
			
			filename += "helptext.ck1";
			
			std::ifstream File; OpenGameFileR(File, filename, std::ios::binary);
			
			if(!File) return;
			
			while(!File.eof())
				Text.push_back(File.get());
			
			File.close();
			Text.erase(Text.size()-1);
		}
		else
		{
			// Here the Text file is within the EXE-File
			unsigned long startflag=0, endflag=0;
			unsigned char *text_data = NULL;
			
			
			if(!ExeFile.getHeaderData()) return;
			
			if(episode == 2)
			{
				startflag = 0x15DC0;
				endflag = 0x1659F;
			}
			else // Episode 3
			{
				startflag = 0x17BD0;
				endflag = 0x1839B;
			}
			
			text_data = ExeFile.getRawData();
			
			for(unsigned long i=startflag ; i<endflag ; i++ )
				Text.push_back(text_data[i]);
		}
	}
	else
	{
		std::string filename = "HELPTEXT.CKP";

		std::ifstream File; OpenGameFileR(File, filename, std::ios::binary);

		if(!File) return;

		while(!File.eof())
			Text.push_back(File.get());

		File.close();
		Text.erase(Text.size()-1);
	}

	// Create the Text ViewerBox and stores the text there!
	mp_TextViewer = new CTextViewer(g_pVideoDriver->mp_VideoEngine->getFGLayerSurface(), 0, 8, 320, 160);
	mp_TextViewer->formatText(Text);
}
Beispiel #10
0
bool gusOpenGameFileR(std::ifstream& f, const std::string& path, std::ios_base::openmode mode) {
	return OpenGameFileR(f, path, mode);
}
Beispiel #11
0
bool CExeFile::readData(const char episode, const std::string& datadirectory)
{
	crc32_init();

	std::string filename = datadirectory + "/keen" + itoa(episode) + ".exe";

	std::ifstream File;
	OpenGameFileR(File, filename, std::ios::binary);

	if(!File)
	{
		// try another filename (Used in Episode 4-6)
		filename = datadirectory + "/keen" + itoa(episode) + "e.exe";
		OpenGameFileR(File, filename, std::ios::binary);
	}

	if(!File)
	{
		// try another filename (Used in Episode 4-6) for demo versions
		filename = datadirectory + "/k" + itoa(episode) + "demo.exe";
		OpenGameFileR(File, filename, std::ios::binary);
	}
	
	if(!File)
		return false;	

	m_filename = filename;
	m_episode = episode;
	m_datadirectory = datadirectory;
	if( m_datadirectory != "") if(*(m_datadirectory.end()-1) != '/') m_datadirectory += "/";
		
	File.seekg(0,std::ios::end);
	m_datasize = File.tellg();
	File.seekg(0,std::ios::beg);

	SAFE_DELETE_ARRAY(m_data);
	unsigned char* m_data_temp = new unsigned char[m_datasize];
	File.read((char*)m_data_temp, m_datasize);

	File.close();

	Cunlzexe UnLZEXE;

	std::vector<unsigned char> decdata;
	if(UnLZEXE.decompress(m_data_temp, decdata))
	{
		m_datasize = decdata.size();
		m_data = new unsigned char[m_datasize];
		m_headersize = UnLZEXE.HeaderSize();
		memcpy(m_data, &decdata[0], m_datasize);
	}
	else
	{
		m_data = new unsigned char[m_datasize];
		memcpy(m_data, m_data_temp,m_datasize);
	}

	m_headerdata = m_data;
	m_headersize = UnLZEXE.HeaderSize();
	if(!m_headersize) m_headersize = 512;
	m_rawdata = m_data + m_headersize;

	const size_t offset_map[] = {
			/*Dummy:*/ 0x0,
			/*Keen 1:*/ 0x13050,
			/*Keen 2:*/ 0x17780,
			/*Keen 3:*/ 0x19820,
			/*Keen 4:*/ 0x2EE70,
			/*Keen 5:*/ 0x30340,
			/*Keen 6:*/ 0x30D30,
			/*Keen D:*/ 0x23A70
	};
	m_data_segment = m_rawdata+offset_map[m_episode];

	delete[] m_data_temp;

	m_crc = getcrc32( m_data, m_datasize );

	g_pLogFile->ftextOut( "EXE processed with size of %d and crc of %X\n", m_datasize, m_crc );

	return true;
}
void CStory::init()
{
    CInfoScene::init();
    CExeFile &ExeFile = gKeenFiles.exeFile;
	const char episode = ExeFile.getEpisode();
    std::string DataDirectory = gKeenFiles.gameDir;

	mpMap.reset(new CMap());
	CVorticonMapLoaderBase Maploader(mpMap);

	std::string Text;

	// Read the Storytext
	if(episode==1)
	{
		// We suppose that we are using version 131. Maybe it must be extended
        std::string filename = DataDirectory;
		if(DataDirectory != "")
			filename += "/";
		
		filename += "storytxt.ck1";
		
		std::ifstream File; OpenGameFileR(File, filename, std::ios::binary);
		
		if(!File) return;
		
		while(!File.eof())
			Text.push_back(File.get());
		
		File.close();
		Text.erase(Text.size()-1);
	}
	else
	{
		// Here the Text file is within the EXE-File
		unsigned long startflag=0, endflag=0;
		unsigned char *text_data = NULL;

		if(episode == 2)
		{
			startflag = 0x16CC0-512;
			endflag = 0x17958-512;
		}
		else // Episode 3
		{
			startflag = 0x18DD0-512;
			endflag = 0x199F3-512;
		}
		
		text_data = ExeFile.getRawData();
		if(!text_data) return;

		for(unsigned long i=startflag ; i<endflag ; i++ )
			Text.push_back(text_data[i]);
	}
	
	Maploader.load(episode, 90, DataDirectory, false);
	
	// Create the Text ViewerBox and stores the text there!
	mpTextViewer.reset(new CTextViewer(0, 0, 320, 136));

	mpTextViewer->formatText(Text);
	
	// Scroll to the map where you see Keen with his rocket.
	mpMap->gotoPos( 32+2*320, 32 );
	mpMap->drawAll();
}
bool LieroXLevelLoader::load(CMap* level, std::string const& path)
{
	std::ifstream f;
	OpenGameFileR(f, path, std::ios::binary);
	if(!f)
		return false;
		
	static const char magic[] = "LieroX Level";
	char check[sizeof(magic)];
	f.read(check, sizeof(check));
	if(memcmp(check, magic, sizeof(magic)))
		return false; //File magic check failed
		
	long width = 0, height = 0; //long has to be at least 32-bit, static_assert?
	f.seekg(0x64); //Level size position
	f.read((char *)&width, 4);
	f.read((char *)&height, 4);
	
	//TODO: Read level name
	
	f.seekg(0x9c); //Level data position
	
	const size_t ChunkBits = 14;
	const size_t ChunkSize = 1 << ChunkBits;
	
	size_t have;
	z_stream strm;
	unsigned char in[ChunkSize];

	// allocate inflate state
	strm.zalloc = Z_NULL;
	strm.zfree = Z_NULL;
	strm.opaque = Z_NULL;
	strm.avail_in = 0;
	strm.next_in = Z_NULL;
	int ret = inflateInit(&strm);
	if (ret != Z_OK)
		return false;

	size_t totalDataSize = (2 * 3 + 1) * (width * height);
	
	// Add an extra chunk size to be sure not to overflow
	totalDataSize = totalDataSize + ChunkSize;

	std::vector<unsigned char> data(totalDataSize);
	unsigned char *p = &data[0];
	
	do
	{
		f.read((char *)in, ChunkSize);
		strm.avail_in = (uInt)f.gcount();

		if (strm.avail_in == 0)
		    break;
		strm.next_in = (Bytef *)in;
		
		// run inflate() on input until output buffer not full
		do
		{
			if(totalDataSize < ChunkSize)
				return false; // We got too much data from the stream
			strm.avail_out = ChunkSize;
		    strm.next_out = (Bytef *)p;
		    ret = inflate(&strm, Z_NO_FLUSH);

		    switch (ret)
		    {
				case Z_NEED_DICT:
				case Z_DATA_ERROR:
				case Z_MEM_ERROR:
				case Z_STREAM_ERROR:
					inflateEnd(&strm);
					return false;
		    }
		    
		    have = ChunkSize - strm.avail_out;
		    totalDataSize -= have;
		    p += have;
		} while (strm.avail_out == 0);

	} while (ret != Z_STREAM_END);
	
	inflateEnd(&strm); // Clean up
	
	level->material = create_bitmap_ex(8, width, height);

#ifndef DEDICATED_ONLY
	level->image = create_bitmap(width, height);
	level->background = create_bitmap(width, height);
#endif
	unsigned char *pbackground = &data[0];
	unsigned char *pimage = pbackground + width*height*3;
	unsigned char *pmaterial = pimage + width*height*3;
	
	for (int y = 0; y < height; y++)
	{
		for (int x = 0; x < width; x++)
		{
			
#ifndef DEDICATED_ONLY
			int backgroundc = makecol(pbackground[0], pbackground[1], pbackground[2]);
#endif
			int m = pmaterial[0];

#ifndef DEDICATED_ONLY
			if(m == 1)
				putpixel(level->image, x, y, backgroundc);
			else
			{
				int imagec = makecol(pimage[0], pimage[1], pimage[2]);
				putpixel(level->image, x, y, imagec);
			}
				
			putpixel(level->background, x, y, backgroundc);
#endif

			switch(m)
			{
				default: m = 1; break; // Background
				case 2:  m = 2; break; // Dirt
				case 4:  m = 0; break; // Rock
			}
			
			putpixel(level->material, x, y, m);
			
#ifndef DEDICATED_ONLY
			pimage += 3;
			pbackground += 3;
#endif
			++pmaterial;
		}
	}
	
	level->loaderSucceeded();
	return true;
}
Beispiel #14
0
bool CVorticonMapLoaderBase::loadBase(  Uint8 episode, 
					Uint8 level, 
					const std::string& path, 
					bool loadNewMusic )
{
    
	std::vector<Uint16> planeitems;
    
    std::string levelname = "level";
	if(level < 10) levelname += "0";
	levelname += itoa(level) + ".ck" + itoa(episode);

    mpMap->resetScrolls();
	mpMap->m_gamepath = path;
	mpMap->m_worldmap = (level == 80);

	// HQ Music. Load Music for a level if you have HQP
	if(loadNewMusic)
	{
		gMusicPlayer.stop();

		// If no music from the songlist could be loaded try the normal table which
		// has another format. It is part of HQP
		if(!gMusicPlayer.LoadfromSonglist(path, level))
			gMusicPlayer.LoadfromMusicTable(path, levelname);
	}

	// decompress map RLEW data
	std::ifstream MapFile;
	bool fileopen = OpenGameFileR(MapFile, getResourceFilename(levelname,path,true,false), std::ios::binary);

	if (!fileopen)
	{
		// only record this error message on build platforms that log errors
		// to a file and not to the screen.
		gLogging.ftextOut("MapLoader: unable to open file %s<br>", levelname.c_str());
		return false;
	}
	gLogging.ftextOut("MapLoader: file %s opened. Loading...<br>", levelname.c_str());

	MapFile.seekg (0, std::ios::beg);

	// load the compressed data into the memory
	std::vector<Uint8>	compdata;
	while( !MapFile.eof() )
	{
		compdata.push_back(static_cast<Uint8>(MapFile.get()));
	}

	MapFile.close();

	CRLE RLE;
    RLE.expandSwapped(planeitems, compdata, 0xFEFE);

	// Here goes the memory allocation function
	const Uint16 w =  planeitems.at(1);
	const Uint16 h =  planeitems.at(2);
    mpMap->setupEmptyDataPlanes(3, w, h);

	unsigned int planesize = 0;
	planesize = planeitems.at(8);
	planesize /= 2; // We have two planes

	blitPlaneToMap( planeitems, planesize, 0, 0);
	blitPlaneToMap( planeitems, planesize, 0, 1);
	blitPlaneToMap( planeitems, planesize, 1, 2);
	
	mpMap->collectBlockersCoordiantes();
    mpMap->setupAnimationTimer();
	return true;
}
// Loads the map into the memory
bool CMapLoader::load( Uint8 episode, Uint8 level, const std::string& path, bool loadNewMusic, bool stategame )
{
    std::string levelname = "level";
    if(level < 10) levelname += "0";
    levelname += itoa(level) + ".ck" + itoa(episode);

    mp_map->resetScrolls();
    mp_map->m_gamepath = path;
    mp_map->m_worldmap = (level == 80);

    // HQ Music. Load Music for a level if you have HQP
    if(loadNewMusic)
    {
        g_pMusicPlayer->stop();

        // If no music from the songlist could be loaded try the normal table which
        // has another format. It is part of HQP
        if(!g_pMusicPlayer->LoadfromSonglist(path, level))
            g_pMusicPlayer->LoadfromMusicTable(path, levelname);
    }

    // decompress map RLEW data
    std::ifstream MapFile;
    bool fileopen = OpenGameFileR(MapFile, getResourceFilename(levelname,path,true,false), std::ios::binary);

    if (!fileopen)
    {
        // only record this error message on build platforms that log errors
        // to a file and not to the screen.
        g_pLogFile->ftextOut("MapLoader: unable to open file %s<br>", levelname.c_str());
        return 0;
    }
    g_pLogFile->ftextOut("MapLoader: file %s opened. Loading...<br>", levelname.c_str());

    MapFile.seekg (0, std::ios::beg);

    // load the compressed data into the memory
    std::vector<Uint8>	compdata;
    while( !MapFile.eof() )
    {
        compdata.push_back(static_cast<Uint8>(MapFile.get()));
    }

    MapFile.close();

    CRLE RLE;
    std::vector<Uint16> planeitems;
    RLE.expandSwapped(planeitems,compdata, 0xFEFE);

    // Here goes the memory allocation function
    mp_map->createEmptyDataPlane(1, planeitems.at(1), planeitems.at(2));

    int t;
    unsigned int planesize = 0;
    unsigned int curmapx=0, curmapy=0;
    planesize = planeitems.at(8);
    planesize /= 2; // Size of two planes, but we only need one


    const char &fixlevel_error = g_pBehaviorEngine->m_option[OPT_FIXLEVELERRORS].value;

    Uint32 c;
    for( c=17 ; c<planesize+17 ; c++ ) // Check against Tilesize
    {
        t = planeitems.at(c);

        if( fixlevel_error )
            fixLevelTiles(t, curmapx, curmapy, episode, level);

        addTile(t, curmapx, curmapy);

        curmapx++;
        if (curmapx >= mp_map->m_width)
        {
            curmapx = 0;
            curmapy++;
            if (curmapy >= mp_map->m_height) break;
        }

        if(t > 255)
            t=0; // If there are some invalid values in the file
    }

    // now do the sprites
    // get sprite data
    int resetcnt, resetpt;
    curmapx = curmapy = 0;
    resetcnt = resetpt = 0;

    if(mp_objvect && stategame == false)
    {
        std::vector<CObject*>::iterator obj = mp_objvect->begin();
        for( ; obj != mp_objvect->end() ; obj++ )
        {
            delete *obj;
            mp_objvect->pop_back();
        }

        mp_objvect->reserve(2000);

        for( c=planesize+17 ; c<2*planesize+16 ; c++ )
        {
            // in case the planesizes are bigger than the actual file content itself
            if(planeitems.size() <= c) break;

            t = planeitems.at(c);

            if (mp_map->m_worldmap) addWorldMapObject(t, curmapx, curmapy,  episode );
            else addEnemyObject(t, curmapx, curmapy, episode, level);

            curmapx++;
            if (curmapx >= mp_map->m_width)
            {
                curmapx = 0;
                curmapy++;
                if (curmapy >= mp_map->m_height) break;
            }

            if (++resetcnt==resetpt) curmapx = curmapy = 0;
        }
    }
    planeitems.clear();

    // Do some post calculations
    // Limit the scroll screens so the blocking (blue in EP1) tiles are3 never seen
    SDL_Rect gamerect = g_pVideoDriver->getGameResolution();
    mp_map->m_maxscrollx = (mp_map->m_width<<4) - gamerect.w - 32;
    mp_map->m_maxscrolly = (mp_map->m_height<<4) - gamerect.h - 32;

    // Set Scrollbuffer
    g_pVideoDriver->setScrollBuffer(&mp_map->m_scrollx_buf, &mp_map->m_scrolly_buf);

    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;
}
Beispiel #17
0
bool LOSPFontLoader::load(Font* font, std::string const& path)
{
	font->free();

	std::ifstream f;
	OpenGameFileR(f, path, std::ios::binary);
	if(!f)
		return false;
		
	long bitmapWidth = 0, bitmapHeight = 0;
	f.read((char *)&bitmapWidth, 4);
	f.read((char *)&bitmapHeight, 4);
		
	if(!f)
		return false;
		
	bool full = false;
		
	if(bitmapWidth < 0)
	{
		bitmapWidth = -bitmapWidth;
		full = true;
	}

	font->m_bitmap = create_bitmap_ex(8, bitmapWidth, bitmapHeight);
	if(!font->m_bitmap)
		return false;
		
	font->m_supportColoring = true;
	
	int max = 224;
	if(full)
	{
		max = 256;
	}
	else
		font->m_chars.assign(32, Font::CharInfo(Rect(0, 0, 1, 1), 0));
	
	for(int i = 0; i < max; ++i)
	{
		int x, y, w, h;
		f.read((char *)&x, 4);
		f.read((char *)&y, 4);
		f.read((char *)&w, 4);
		f.read((char *)&h, 4);
		
		if(!f)
			return false;

		font->m_chars.push_back(Font::CharInfo(Rect(x, y, x + w, y + h), 0));
	}
	
	if(!full)
		font->m_chars[11] = font->m_chars[(unsigned char)'^'];
	
	for(int y = 0; y < bitmapWidth; ++y)
	{
		for(int x = 0; x < bitmapHeight; ++x)
		{
			char v;
			if(!f.get(v))
				return false;
				
			int c = (unsigned char)v;

			putpixel(font->m_bitmap, x, y, c);
		}
	}
	
	font->buildSubBitmaps();
	
	return true;
}