applied changes from 0.3pre6 (patch from rev40 to rev49)
git-svn-id: https://clonekeenplus.svn.sourceforge.net/svnroot/clonekeenplus/cgenius/trunk@79 4df4b0f3-56ce-47cb-b001-ed939b7d65a6
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
#Sat Jan 10 20:53:00 CET 2009
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
||||
@@ -19,17 +19,25 @@
|
||||
#include "vorticon/CCredits.h"
|
||||
#include "CLogFile.h"
|
||||
#include "fileio.h"
|
||||
#include "fileio/CExeFile.h"
|
||||
#include "fileio/CTileLoader.h"
|
||||
#include "fileio/CPatcher.h"
|
||||
#include "sdl/sound/CSound.h"
|
||||
#include "sdl/CVideoDriver.h"
|
||||
|
||||
CGame::CGame() {
|
||||
m_Episode = 0;
|
||||
memset(m_DataDirectory,0,256);
|
||||
Latch = new CLatch();
|
||||
|
||||
TileLoader = NULL;
|
||||
EGAGraphics = NULL;
|
||||
m_Messages = NULL;
|
||||
}
|
||||
|
||||
CGame::~CGame() {
|
||||
if(Latch){ delete Latch; Latch = NULL;}
|
||||
if(EGAGraphics) delete EGAGraphics;
|
||||
if(TileLoader) delete TileLoader;
|
||||
if(m_Messages) delete m_Messages;
|
||||
}
|
||||
|
||||
short CGame::runCycle(stCloneKeenPlus *pCKP)
|
||||
@@ -39,7 +47,7 @@ short CGame::runCycle(stCloneKeenPlus *pCKP)
|
||||
int eseq = 0;
|
||||
int defaultopt = 0;
|
||||
|
||||
initgamefirsttime(pCKP, Latch->getLatchHeader()->NumSprites);
|
||||
initgamefirsttime(pCKP, EGAGraphics->getNumSprites());
|
||||
initgame(pCKP);
|
||||
|
||||
g_pLogFile->ftextOut("Game starting...<br>");
|
||||
@@ -107,7 +115,7 @@ short CGame::runCycle(stCloneKeenPlus *pCKP)
|
||||
numplayers = 1;
|
||||
defaultopt = 0;
|
||||
current_demo = 1;
|
||||
initgamefirsttime(pCKP, Latch->getLatchHeader()->NumSprites);
|
||||
initgamefirsttime(pCKP, EGAGraphics->getNumSprites());
|
||||
loadinggame = 0;
|
||||
playgame_levelmanager(pCKP);
|
||||
break;
|
||||
@@ -115,7 +123,7 @@ short CGame::runCycle(stCloneKeenPlus *pCKP)
|
||||
defaultopt = 0;
|
||||
current_demo = 1;
|
||||
numplayers = 2;
|
||||
initgamefirsttime(pCKP, Latch->getLatchHeader()->NumSprites);
|
||||
initgamefirsttime(pCKP, EGAGraphics->getNumSprites());
|
||||
loadinggame = 0;
|
||||
playgame_levelmanager(pCKP);
|
||||
break;
|
||||
@@ -126,7 +134,7 @@ short CGame::runCycle(stCloneKeenPlus *pCKP)
|
||||
defaultopt = 0;
|
||||
current_demo = 1;
|
||||
numplayers = 1; // here was 2. Why was that? I don't understand
|
||||
initgamefirsttime(pCKP, Latch->getLatchHeader()->NumSprites);
|
||||
initgamefirsttime(pCKP, EGAGraphics->getNumSprites());
|
||||
playgame_levelmanager(pCKP);
|
||||
}
|
||||
break;
|
||||
@@ -159,7 +167,7 @@ short CGame::runCycle(stCloneKeenPlus *pCKP)
|
||||
|
||||
case MAINMNU_TIMEOUT:
|
||||
case MAINMNU_DEMO:
|
||||
retval = play_demo(current_demo, pCKP, Latch->getLatchHeader()->NumSprites);
|
||||
retval = play_demo(current_demo, pCKP, EGAGraphics->getNumSprites());
|
||||
|
||||
if (retval==DEMO_RESULT_FILE_BAD)
|
||||
{
|
||||
@@ -215,11 +223,39 @@ int CGame::loadResources(unsigned short Episode, char *DataDirectory)
|
||||
m_Episode = Episode;
|
||||
memcpy(m_DataDirectory, DataDirectory, 256);
|
||||
|
||||
// Decode the graphics for the game (EGALATCH, EGASPRIT)
|
||||
if (Latch->loadGraphics(Episode, DataDirectory)) return 1;
|
||||
if( ( *(DataDirectory+strlen(DataDirectory)-1) != '/' ) && strlen(DataDirectory) > 0)
|
||||
strcat(DataDirectory,"/");
|
||||
|
||||
// Decode the entire graphics for the game (EGALATCH, EGASPRIT)
|
||||
EGAGraphics = new CEGAGraphics(Episode, DataDirectory); // Path is relative to the data dir
|
||||
if(!EGAGraphics) return 1;
|
||||
|
||||
EGAGraphics->loadData();
|
||||
|
||||
// Get the EXE of the game and decompress it if needed.
|
||||
CExeFile *ExeFile = new CExeFile(Episode, DataDirectory);
|
||||
ExeFile->readData();
|
||||
int version = ExeFile->getEXEVersion();
|
||||
g_pLogFile->ftextOut("Commander Keen Episode %d (Version %d.%d) was detected.<br>", Episode, version/100,version%100);
|
||||
if(version == 134) g_pLogFile->ftextOut("This version of the game is not supported!<br>");
|
||||
|
||||
// Patch the EXE-File-Data directly in the memory.
|
||||
CPatcher *Patcher = new CPatcher(Episode, ExeFile->getEXEVersion(), ExeFile->getData(), DataDirectory);
|
||||
Patcher->patchMemory();
|
||||
delete Patcher;
|
||||
|
||||
// Load tile attributes.
|
||||
if(TileLoader) delete TileLoader;
|
||||
TileLoader = new CTileLoader(Episode, ExeFile->getEXEVersion(), ExeFile->getData());
|
||||
if(!TileLoader->load()) return 1;
|
||||
|
||||
// load the strings. TODO: After that this one will replace loadstrings
|
||||
//m_Messages = new CMessages(); delete ExeFile;
|
||||
//m_Messages->readData(char *buf, int episode, int version);
|
||||
loadstrings("strings.dat");
|
||||
|
||||
delete ExeFile;
|
||||
|
||||
// Load the sound data
|
||||
int ok;
|
||||
ok = g_pSound->loadSoundData(m_Episode, DataDirectory);
|
||||
@@ -227,14 +263,17 @@ int CGame::loadResources(unsigned short Episode, char *DataDirectory)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CGame::freeResources(void)
|
||||
{
|
||||
if(EGAGraphics) { delete EGAGraphics; EGAGraphics = NULL; }
|
||||
}
|
||||
|
||||
void CGame::preallocateCKP(stCloneKeenPlus *pCKP)
|
||||
{
|
||||
// This function prepares the CKP Structure so that the it is allocated in the memory.
|
||||
pCKP->numGames = 0;
|
||||
pCKP->Resources.GameSelected = 0;
|
||||
|
||||
TileProperty = NULL;
|
||||
|
||||
pCKP->GameData = NULL;
|
||||
pCKP->GameData = new stGameData[1];
|
||||
|
||||
@@ -254,9 +293,3 @@ void CGame::preallocateCKP(stCloneKeenPlus *pCKP)
|
||||
|
||||
player[0].x = player[0].y = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CLatch *CGame::getLatch(void)
|
||||
{ return Latch; }
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
#define CGAME_H_
|
||||
|
||||
#include <string.h>
|
||||
#include "CLatch.h"
|
||||
#include "vorticon/CEGAGraphics.h"
|
||||
#include "vorticon/CMessages.h"
|
||||
|
||||
class CGame {
|
||||
public:
|
||||
@@ -17,9 +18,9 @@ public:
|
||||
virtual ~CGame();
|
||||
|
||||
int loadResources(unsigned short Episode, char *DataDirectory);
|
||||
void freeResources(void);
|
||||
short runCycle(stCloneKeenPlus *pCKP);
|
||||
void preallocateCKP(stCloneKeenPlus *pCKP);
|
||||
CLatch *getLatch(void);
|
||||
|
||||
private:
|
||||
static const unsigned short MAX_TEXT_LENGTH = 256;
|
||||
@@ -27,7 +28,9 @@ private:
|
||||
char m_DataDirectory[MAX_TEXT_LENGTH];
|
||||
int current_demo;
|
||||
|
||||
CLatch *Latch;
|
||||
CEGAGraphics *EGAGraphics;
|
||||
CMessages *m_Messages;
|
||||
CTileLoader *TileLoader;
|
||||
};
|
||||
|
||||
#endif /* CGAME_H_ */
|
||||
|
||||
@@ -115,6 +115,9 @@ void CGraphics::drawTile(int x, int y, unsigned int t)
|
||||
memset(offset, COLOUR_MASK, 16);
|
||||
offset+=512;
|
||||
}
|
||||
|
||||
//HQBitmap->updateHQBitmap(g_pVideoDriver->getScrollSurface(),x,y);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -161,7 +164,7 @@ unsigned int xstart,ystart;
|
||||
{
|
||||
if (tiledata[tmask][ya][xa] != 15)
|
||||
{
|
||||
//scrollbuffer[bufoffY+bufoffX] = tiledata[til][ya][xa];
|
||||
scrollbuffer[bufoffY+bufoffX] = tiledata[til][ya][xa];
|
||||
}
|
||||
bufoffX = (bufoffX+1)&511;
|
||||
}
|
||||
@@ -552,9 +555,7 @@ unsigned char *bmdataptr;
|
||||
|
||||
int CGraphics::getBitmapNumberFromName(const char *bmname)
|
||||
{
|
||||
|
||||
// TODO: Implement Code for Introduction Screen
|
||||
int i;
|
||||
int i;
|
||||
for(i=0;i<MAX_BITMAPS;i++)
|
||||
{
|
||||
bitmaps[i].name[8] = 0; // ensure null-terminated
|
||||
@@ -563,6 +564,11 @@ int i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// If the Bitmap was not found,
|
||||
// try to take one basing on the position
|
||||
// where it should be
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -706,7 +712,17 @@ Uint8 *CGraphics::getScrollbuffer(void)
|
||||
void CGraphics::renderHQBitmap()
|
||||
{
|
||||
if(HQBitmap)
|
||||
HQBitmap->updateHQBitmap(g_pVideoDriver->getBGLayerSurface(),scroll_x-32,scroll_y-32);
|
||||
{
|
||||
SDL_Rect srcrect;
|
||||
//SDL_Rect dstrect;
|
||||
|
||||
srcrect.x = scroll_x-32;
|
||||
srcrect.y = scroll_y-32;
|
||||
srcrect.w = g_pVideoDriver->getBGLayerSurface()->w;
|
||||
srcrect.h = g_pVideoDriver->getBGLayerSurface()->h;
|
||||
|
||||
HQBitmap->updateHQBitmap(g_pVideoDriver->getBGLayerSurface(), &srcrect, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics::loadHQGraphics(unsigned char episode, unsigned char level, char *datadir)
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "CLatch.h"
|
||||
#include "vorticon/CPlanes.h"
|
||||
#include "fileio.h"
|
||||
#include "keen.h"
|
||||
#include "keenext.h"
|
||||
|
||||
#include "CLogFile.h"
|
||||
//#include "vorticon/CEGAGraphics.h"
|
||||
|
||||
CLatch::CLatch() {
|
||||
SpriteTable = NULL;
|
||||
@@ -70,6 +72,13 @@ char CLatch::loadHeader(int episode, const char *path)
|
||||
|
||||
sprintf(fname, "%s%d", buffer,episode);
|
||||
|
||||
/*CEGAGraphics *EGAGraphics;
|
||||
|
||||
EGAGraphics = new CEGAGraphics(episode);
|
||||
|
||||
EGAGraphics->loadData();
|
||||
|
||||
delete EGAGraphics;*/
|
||||
|
||||
headfile = fopen(fname, "rb");
|
||||
if (!headfile)
|
||||
@@ -142,6 +151,7 @@ char CLatch::loadHeader(int episode, const char *path)
|
||||
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<int>(sizeof(SpriteHead));k++) fgetc(headfile);
|
||||
@@ -190,7 +200,7 @@ char CLatch::loadHeader(int episode, const char *path)
|
||||
}
|
||||
|
||||
|
||||
// load the EGAHEAD file
|
||||
// load the EGALATCH file
|
||||
|
||||
char CLatch::load(int episode, const char *path)
|
||||
{
|
||||
@@ -204,7 +214,6 @@ unsigned long RawDataSize;
|
||||
|
||||
char buffer[256];
|
||||
|
||||
|
||||
formatPathString(buffer,path);
|
||||
|
||||
strcat(buffer,"egalatch.ck");
|
||||
@@ -234,7 +243,6 @@ char buffer[256];
|
||||
if (LatchHeader.Compressed)
|
||||
{
|
||||
g_pLogFile->ftextOut("latch_loadlatch(): Decompressing...<br>");
|
||||
fseek(latchfile, 6, SEEK_SET);
|
||||
if (lz_decompress(latchfile, (unsigned char*) RawData)) return 1;
|
||||
}
|
||||
else
|
||||
@@ -261,7 +269,8 @@ char buffer[256];
|
||||
g_pLogFile->ftextOut("latch_loadlatch(): Decoding 8x8 tiles...<br>", fname);
|
||||
|
||||
// set up the getbit() function
|
||||
setplanepositions(plane1 + LatchHeader.Off8Tiles, \
|
||||
|
||||
CPlanes *Planes = new CPlanes(plane1 + LatchHeader.Off8Tiles, \
|
||||
plane2 + LatchHeader.Off8Tiles, \
|
||||
plane3 + LatchHeader.Off8Tiles, \
|
||||
plane4 + LatchHeader.Off8Tiles, \
|
||||
@@ -287,7 +296,7 @@ char buffer[256];
|
||||
}
|
||||
// read a bit out of the current plane, shift it into the
|
||||
// correct position and merge it
|
||||
c |= (getbit(RawData, p) << p);
|
||||
c |= (Planes->getbit(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;
|
||||
@@ -297,11 +306,13 @@ char buffer[256];
|
||||
}
|
||||
}
|
||||
|
||||
delete Planes;
|
||||
|
||||
// ** read the 16x16 tiles **
|
||||
g_pLogFile->ftextOut("latch_loadlatch(): Decoding 16x16 tiles...<br>", fname);
|
||||
|
||||
// set up the getbit() function
|
||||
setplanepositions(plane1 + LatchHeader.Off16Tiles, \
|
||||
Planes = new CPlanes(plane1 + LatchHeader.Off16Tiles, \
|
||||
plane2 + LatchHeader.Off16Tiles, \
|
||||
plane3 + LatchHeader.Off16Tiles, \
|
||||
plane4 + LatchHeader.Off16Tiles, \
|
||||
@@ -323,7 +334,7 @@ char buffer[256];
|
||||
{
|
||||
c = tiledata[t][y][x];
|
||||
}
|
||||
c |= (getbit(RawData, p) << p);
|
||||
c |= (Planes->getbit(RawData, p) << p);
|
||||
if (p==3 && c==0) c = 16;
|
||||
|
||||
tiledata[t][y][x] = c;
|
||||
@@ -332,6 +343,8 @@ char buffer[256];
|
||||
}
|
||||
}
|
||||
|
||||
delete Planes;
|
||||
|
||||
// ** read the bitmaps **
|
||||
g_pLogFile->ftextOut("latch_loadlatch(): Allocating %d bytes for bitmap data...<br>", BitmapBufferRAMSize);
|
||||
BitmapData = new char[BitmapBufferRAMSize];
|
||||
@@ -344,7 +357,7 @@ char buffer[256];
|
||||
g_pLogFile->ftextOut("latch_loadlatch(): Decoding bitmaps...<br>", fname);
|
||||
|
||||
// set up the getbit() function
|
||||
setplanepositions(plane1 + LatchHeader.OffBitmaps, \
|
||||
Planes = new CPlanes(plane1 + LatchHeader.OffBitmaps, \
|
||||
plane2 + LatchHeader.OffBitmaps, \
|
||||
plane3 + LatchHeader.OffBitmaps, \
|
||||
plane4 + LatchHeader.OffBitmaps, \
|
||||
@@ -380,7 +393,7 @@ char buffer[256];
|
||||
{
|
||||
c = *bmdataptr;
|
||||
}
|
||||
c |= (getbit(RawData, p) << p);
|
||||
c |= (Planes->getbit(RawData, p) << p);
|
||||
if (p==3 && c==0) c = 16;
|
||||
*bmdataptr = c;
|
||||
bmdataptr++;
|
||||
@@ -389,55 +402,17 @@ char buffer[256];
|
||||
}
|
||||
}
|
||||
|
||||
delete Planes;
|
||||
|
||||
if(RawData){ delete[] RawData; RawData = NULL;}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initilizes the positions getbit will retrieve data from
|
||||
void CLatch::setplanepositions(unsigned long p1, unsigned long p2, unsigned long p3,\
|
||||
unsigned long p4, unsigned long p5)
|
||||
{
|
||||
int i;
|
||||
getbit_bytepos[0] = p1;
|
||||
getbit_bytepos[1] = p2;
|
||||
getbit_bytepos[2] = p3;
|
||||
getbit_bytepos[3] = p4;
|
||||
getbit_bytepos[4] = p5;
|
||||
|
||||
for(i=0;i<=4;i++)
|
||||
{
|
||||
getbit_bitmask[i] = 128;
|
||||
}
|
||||
}
|
||||
|
||||
// retrieves a bit from plane "plane". the positions of the planes
|
||||
// should have been previously initilized with setplanepositions()
|
||||
unsigned char CLatch::getbit(char *buf, unsigned char plane)
|
||||
{
|
||||
int retval;
|
||||
int byt;
|
||||
if (!getbit_bitmask[plane])
|
||||
{
|
||||
getbit_bitmask[plane] = 128;
|
||||
getbit_bytepos[plane]++;
|
||||
}
|
||||
|
||||
byt = buf[getbit_bytepos[plane]];
|
||||
|
||||
if (byt & getbit_bitmask[plane])
|
||||
{
|
||||
retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
getbit_bitmask[plane] >>= 1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
char CLatch::loadSprites(int episode, const char *path)
|
||||
@@ -447,10 +422,8 @@ unsigned long plane1, plane2, plane3, plane4, plane5;
|
||||
char fname[80];
|
||||
int x,y,s,c,p;
|
||||
unsigned long RawDataSize;
|
||||
/*int i;
|
||||
unsigned char ch;*/
|
||||
|
||||
char buffer[256];
|
||||
CPlanes *Planes;
|
||||
|
||||
formatPathString(buffer,path);
|
||||
|
||||
@@ -478,7 +451,6 @@ char buffer[256];
|
||||
if (LatchHeader.Compressed)
|
||||
{
|
||||
g_pLogFile->ftextOut("latch_loadsprites(): Decompressing...<br>");
|
||||
fseek(spritfile, 6, SEEK_SET);
|
||||
if (lz_decompress(spritfile, (unsigned char*) RawData)) return 1;
|
||||
}
|
||||
else
|
||||
@@ -506,7 +478,7 @@ char buffer[256];
|
||||
g_pLogFile->ftextOut("latch_loadsprites(): Decoding sprites...<br>", fname);
|
||||
|
||||
// set up the getbit() function
|
||||
setplanepositions(plane1 + LatchHeader.OffSprites, \
|
||||
Planes = new CPlanes(plane1 + LatchHeader.OffSprites, \
|
||||
plane2 + LatchHeader.OffSprites, \
|
||||
plane3 + LatchHeader.OffSprites, \
|
||||
plane4 + LatchHeader.OffSprites, \
|
||||
@@ -535,7 +507,7 @@ char buffer[256];
|
||||
{
|
||||
c = sprites[s].imgdata[y][x];
|
||||
}
|
||||
c |= (getbit(RawData, p) << p);
|
||||
c |= (Planes->getbit(RawData, p) << p);
|
||||
if (p==3 && c==0) c = 16;
|
||||
sprites[s].imgdata[y][x] = c;
|
||||
}
|
||||
@@ -552,11 +524,12 @@ char buffer[256];
|
||||
{
|
||||
for(x=0;x<sprites[s].xsize;x++)
|
||||
{
|
||||
sprites[s].maskdata[y][x] = (1 - getbit(RawData, 4));
|
||||
sprites[s].maskdata[y][x] = (1 - Planes->getbit(RawData, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete Planes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -58,9 +58,6 @@ private:
|
||||
|
||||
unsigned long BitmapBufferRAMSize;
|
||||
|
||||
unsigned long getbit_bytepos[5];
|
||||
unsigned char getbit_bitmask[5];
|
||||
|
||||
EgaHead LatchHeader;
|
||||
SpriteHead *SpriteTable;
|
||||
BitmapHead *BitmapTable;
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
#ifndef CLOGFILE_H_
|
||||
#define CLOGFILE_H_
|
||||
|
||||
#define REVISION "CloneKeenPlus Beta v0.2.9.7 (Commander Genius)"
|
||||
|
||||
#include <stdio.h>
|
||||
#define REVISION "Commander Genius Prerelease v0.3"
|
||||
#include "CSingleton.h"
|
||||
#define g_pLogFile CLogFile::Get()
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#define MOTHER_HURT 2
|
||||
#define MOTHER_DEAD 3
|
||||
|
||||
#define MOTHER_WALK_ANIM_RATE 40
|
||||
#define MOTHER_WALK_SPD 4
|
||||
#define MOTHER_WALK_ANIM_RATE 30
|
||||
#define MOTHER_WALK_SPD 3
|
||||
|
||||
#define MOTHER_SPIT_PROB 1000
|
||||
#define MOTHER_SPIT_SHOW_TIME 100
|
||||
|
||||
@@ -81,7 +81,7 @@ char numlooks;
|
||||
// half of the yorp
|
||||
if ((player[objects[o].touchedBy].y>>CSF)+16 < (objects[o].y>>CSF)+12)
|
||||
{
|
||||
player[objects[o].touchedBy].ppogostick = 0; // No pogo, You get it disabled at this point
|
||||
player[objects[o].touchedBy].ppogostick = false; // No pogo, You get it disabled at this point
|
||||
g_pSound->playStereofromCoord(SOUND_YORP_STUN, PLAY_NOW, objects[o].scrx);
|
||||
objects[o].ai.yorp.state = YORP_STUNNED;
|
||||
objects[o].ai.yorp.looktimes = 0;
|
||||
|
||||
@@ -58,6 +58,8 @@ int x, y, t, o, i;
|
||||
int tantalus_animframe, tantalus_animtimer;
|
||||
int state, timer, spawnedcount;
|
||||
|
||||
o=0;
|
||||
|
||||
fade.mode = FADE_GO;
|
||||
fade.rate = FADE_NORM;
|
||||
fade.dir = FADE_OUT;
|
||||
|
||||
355
src/fileio.cpp
355
src/fileio.cpp
@@ -10,18 +10,16 @@
|
||||
#include "sdl/sound/CSound.h"
|
||||
#include "hqp/CMusic.h"
|
||||
#include "include/fileio.h"
|
||||
#include "include/fileio/lzexe.h"
|
||||
#include "include/fileio/rle.h"
|
||||
#include "vorticon/CPlayer.h"
|
||||
#include "CLogFile.h"
|
||||
#include "CGraphics.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
extern CPlayer *Player;
|
||||
|
||||
int numtiles;
|
||||
int **TileProperty; // This version will replace the old stTile Structure and save memory
|
||||
|
||||
unsigned int curmapx, curmapy;
|
||||
unsigned char mapdone;
|
||||
void addmaptile(unsigned int t)
|
||||
@@ -37,6 +35,56 @@ void addmaptile(unsigned int t)
|
||||
}
|
||||
}
|
||||
|
||||
bool renameFilenamesLowerCase(const char *dir_name)
|
||||
{
|
||||
#ifdef TARGET_WIN32
|
||||
return true;
|
||||
#else
|
||||
DIR *p_Dir;
|
||||
char newname[256];
|
||||
char buf[256];
|
||||
struct dirent *dp;
|
||||
|
||||
memset(newname,0,256);
|
||||
strcpy(buf,dir_name);
|
||||
|
||||
if(buf[0] == '\0')
|
||||
strcpy(buf,"./");
|
||||
|
||||
chdir("data");
|
||||
|
||||
if((p_Dir = opendir(buf))==NULL)
|
||||
return false;
|
||||
|
||||
bool retval = true;
|
||||
// This function checks if all the files in the directory are lower case.
|
||||
// If they aren't rename them
|
||||
while((dp = readdir(p_Dir)) != NULL)
|
||||
{
|
||||
if(dp->d_type == DT_REG)
|
||||
{
|
||||
strcpy(newname,dp->d_name);
|
||||
|
||||
int len = strlen(newname);
|
||||
for(int pos=0 ; pos < len ; pos++ )
|
||||
if(newname[pos] >= 'A' && newname[pos] <= 'Z')
|
||||
newname[pos] += ('a'-'A');
|
||||
|
||||
if(strncmp(newname,dp->d_name,strlen(dp->d_name)) != 0)
|
||||
if(rename(dp->d_name,newname) != -1)
|
||||
retval &= true;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(p_Dir);
|
||||
|
||||
chdir("../");
|
||||
|
||||
return retval;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
short checkConsistencyofGameData(stGameData *p_GameData)
|
||||
{
|
||||
short ok = 0;
|
||||
@@ -79,7 +127,14 @@ short checkConsistencyofGameData(stGameData *p_GameData)
|
||||
sprintf(p_GameData->FileList[24],"sounds.ck%d",p_GameData->Episode);
|
||||
}
|
||||
|
||||
// Now check if they really exist!
|
||||
// Rename all the the files in the directory to lower case
|
||||
if(!renameFilenamesLowerCase(p_GameData->DataDirectory))
|
||||
{
|
||||
g_pLogFile->ftextOut(PURPLE,"WARNING: There was an error while trying to format correctly the game data.");
|
||||
g_pLogFile->ftextOut(PURPLE,"Please check, if you have write permissions on the game data directory and it is accessible<br>");
|
||||
}
|
||||
|
||||
// Finally check if they really exist!
|
||||
char buf[MAX_STRING_LENGTH];
|
||||
int c=0;
|
||||
for(c = 0 ; c < MAX_NUMBER_OF_FILES ; c++)
|
||||
@@ -94,7 +149,6 @@ short checkConsistencyofGameData(stGameData *p_GameData)
|
||||
strcat(buf,"/");
|
||||
strcat(buf,p_GameData->FileList[c]);
|
||||
|
||||
|
||||
if((fp = fopen(buf,"r")) != NULL)
|
||||
{
|
||||
fclose(fp);
|
||||
@@ -145,8 +199,50 @@ int o;
|
||||
levelmarker: ;
|
||||
if ((t&0x7fff) < 256 && pCKP->Control.levelcontrol.levels_completed[t&0x00ff])
|
||||
{
|
||||
map.objectlayer[curmapx][curmapy] = 0;
|
||||
map.mapdata[curmapx][curmapy] = tiles[map.mapdata[curmapx][curmapy]].chgtile;
|
||||
if(!options[OPT_LVLREPLAYABILITY].value)
|
||||
map.objectlayer[curmapx][curmapy] = 0;
|
||||
else
|
||||
map.objectlayer[curmapx][curmapy] = t;
|
||||
|
||||
int newtile = tiles[map.mapdata[curmapx][curmapy]].chgtile;
|
||||
|
||||
// Consistency check! Some Mods have issues with that.
|
||||
if(pCKP->Control.levelcontrol.episode == 1 || pCKP->Control.levelcontrol.episode == 2)
|
||||
{
|
||||
if(newtile<77 || newtile>81)
|
||||
// something went wrong. Use default tile
|
||||
newtile = 77;
|
||||
|
||||
// try to guess, if it is a 32x32 (4 16x16) Tile
|
||||
if(map.mapdata[curmapx-1][curmapy-1] == (unsigned int) newtile &&
|
||||
map.mapdata[curmapx][curmapy-1] == (unsigned int) newtile &&
|
||||
map.mapdata[curmapx-1][curmapy] == (unsigned int) newtile)
|
||||
{
|
||||
map.mapdata[curmapx-1][curmapy-1] = 78; //ul
|
||||
map.mapdata[curmapx][curmapy-1] = 79; //ur
|
||||
map.mapdata[curmapx-1][curmapy] = 80; //bl
|
||||
newtile = 81; // br. this one
|
||||
}
|
||||
}
|
||||
else if(pCKP->Control.levelcontrol.episode == 3)
|
||||
{
|
||||
if(newtile<52 || newtile>56)
|
||||
// something went wrong. Use default tile
|
||||
newtile = 56;
|
||||
// try to guess, if it is a 32x32 (4 16x16) Tile
|
||||
if(map.mapdata[curmapx-1][curmapy-1] == (unsigned int) newtile &&
|
||||
map.mapdata[curmapx][curmapy-1] == (unsigned int) newtile &&
|
||||
map.mapdata[curmapx-1][curmapy] == (unsigned int) newtile)
|
||||
{
|
||||
map.mapdata[curmapx-1][curmapy-1] = 52; //bl
|
||||
map.mapdata[curmapx][curmapy-1] = 53; //ur
|
||||
map.mapdata[curmapx-1][curmapy] = 54; //ul
|
||||
newtile = 55; // br. this one
|
||||
}
|
||||
}
|
||||
|
||||
map.mapdata[curmapx][curmapy] = newtile;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -196,7 +292,6 @@ int o,x;
|
||||
x = curmapx;
|
||||
|
||||
if (TileProperty[map.mapdata[x][curmapy+1]][BLEFT]) x--;
|
||||
//if (tiles[map.mapdata[x][curmapy+1]].solidl) x--;
|
||||
spawn_object(x<<4<<CSF, ((curmapy<<4)+8)<<CSF, OBJ_YORP);
|
||||
}
|
||||
else
|
||||
@@ -204,7 +299,6 @@ int o,x;
|
||||
// in ep2 level 16 there a vorticon embedded in the floor for
|
||||
// some reason! that's what the if() is for--to fix it.
|
||||
if (TileProperty[map.mapdata[curmapx][curmapy+1]][BLEFT])
|
||||
//if (tiles[map.mapdata[curmapx][curmapy+1]].solidl)
|
||||
{
|
||||
spawn_object(curmapx<<4<<CSF, ((curmapy<<4)-16)<<CSF, OBJ_VORT);
|
||||
}
|
||||
@@ -277,7 +371,6 @@ int o,x;
|
||||
else if (pCKP->Control.levelcontrol.episode==3)
|
||||
{
|
||||
if(TileProperty[map.mapdata[curmapx][curmapy+1]][BLEFT])
|
||||
//if (tiles[map.mapdata[curmapx][curmapy+1]].solidl)
|
||||
{
|
||||
spawn_object(curmapx<<4<<CSF, (curmapy-1)<<4<<CSF, OBJ_NINJA);
|
||||
}
|
||||
@@ -501,7 +594,6 @@ int resetcnt, resetpt;
|
||||
|
||||
c=18;
|
||||
|
||||
//while(!mapdone)
|
||||
while(c < ((filebuf[9] / 2)+18)) // Check against Tilesize
|
||||
{
|
||||
t = filebuf[c];
|
||||
@@ -609,245 +701,6 @@ int resetcnt, resetpt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char loadtileattributes(int episode, char *extrapath)
|
||||
{
|
||||
FILE *fp;
|
||||
int t,a,b;
|
||||
char fname[MAX_STRING_LENGTH];
|
||||
char buf[MAX_STRING_LENGTH];
|
||||
int bufsize;
|
||||
|
||||
unsigned char *filebuf;
|
||||
int i,j; // standard counters
|
||||
|
||||
FILE *fin;
|
||||
|
||||
filebuf = (unsigned char*) malloc(500000*sizeof(unsigned char));
|
||||
|
||||
// We need a function that autodetects tli files in a directory...
|
||||
sprintf(buf,"tiles.tli");
|
||||
|
||||
formatPathString(fname,extrapath);
|
||||
|
||||
strcat(fname,buf);
|
||||
|
||||
g_pLogFile->ftextOut("loadtileattributes() : Trying to read the tiles from \"%s\"<br>", fname);
|
||||
|
||||
if( (fin = fopen(fname,"rb")) == NULL )
|
||||
{
|
||||
// No, try to read it from the exe-file
|
||||
|
||||
sprintf(buf,"keen%d.exe",episode);
|
||||
|
||||
formatPathString(fname,extrapath);
|
||||
|
||||
strcat(fname,buf);
|
||||
|
||||
g_pLogFile->ftextOut("loadtileattributes() : Extracting tile attributes from the exe file \"%s\"<br>", fname);
|
||||
|
||||
if( (fin = fopen(fname,"rb")) != NULL )
|
||||
{
|
||||
int version;
|
||||
int offset;
|
||||
|
||||
bufsize = unlzexe(fin, filebuf);
|
||||
|
||||
rewind(fin);
|
||||
|
||||
if ( bufsize == 0 ) // Program was not unpacked, so read it normally
|
||||
{
|
||||
for(i = 0; i < 512 ; i++) // I don't why this value (512), but it makes read mods correctly. At last Yorpius II
|
||||
getc(fin);
|
||||
|
||||
while(!feof(fin))
|
||||
{
|
||||
filebuf[bufsize] = getc(fin);
|
||||
bufsize++;
|
||||
}
|
||||
|
||||
bufsize--;
|
||||
}
|
||||
|
||||
|
||||
fclose(fin);
|
||||
|
||||
version = getEXEVersion(episode, bufsize);
|
||||
|
||||
g_pLogFile->ftextOut("Commander Keen Episode %d (Version %d.%d) was detected.<br>",episode,version/100,version%100);
|
||||
|
||||
if(version < 0)
|
||||
{
|
||||
why_term_ptr = "loadtileattributes(): Unknown EXE-File. It is possible, that the exe-file is a mod. Please use an original exe-file.\nNot all Mods work with CKP";
|
||||
}
|
||||
else if(version == 134)
|
||||
{
|
||||
why_term_ptr = "loadtileattributes(): Sorry, but version 1.34 isn't supported! please use version 1.31";
|
||||
}
|
||||
|
||||
if( episode == 1 && version == 110 )
|
||||
{
|
||||
offset = 0x131F8;
|
||||
numtiles = 611;
|
||||
}
|
||||
else if( episode == 1 && version == 131 )
|
||||
{
|
||||
offset = 0x130F8;
|
||||
numtiles = 611;
|
||||
}
|
||||
else if( episode == 1 && version == 134 )
|
||||
{
|
||||
offset = 0x00000;
|
||||
numtiles = 611;
|
||||
return -1;
|
||||
}
|
||||
else if( episode == 2 && version == 100 )
|
||||
{
|
||||
offset = 0x17938;
|
||||
numtiles = 689;
|
||||
}
|
||||
else if( episode == 2 && version == 131 )
|
||||
{
|
||||
offset = 0x17828;
|
||||
numtiles = 689;
|
||||
}
|
||||
else if( episode == 3 && version == 100 )
|
||||
{
|
||||
offset = 0x199F8;
|
||||
numtiles = 715;
|
||||
}
|
||||
else if( episode == 3 && version == 131 )
|
||||
{
|
||||
offset = 0x198C8;
|
||||
numtiles = 715;
|
||||
}
|
||||
else
|
||||
{
|
||||
crashflag = 1;
|
||||
why_term_ptr = "loadtileattributes(): Algorithm for extracting tiles is not supported for this version!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(filebuf, filebuf + offset, 6*2*numtiles);
|
||||
}
|
||||
else
|
||||
{
|
||||
crashflag = 1;
|
||||
why_term_ptr = "loadtileattributes(): Error reading tiles!";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// read from the tli file
|
||||
int bufsize;
|
||||
|
||||
bufsize = 0;
|
||||
|
||||
while(!feof(fin))
|
||||
{
|
||||
filebuf[bufsize] = getc(fin);
|
||||
bufsize++;
|
||||
}
|
||||
fclose(fin);
|
||||
}
|
||||
|
||||
// Here we really start reading the tiles
|
||||
if(TileProperty != NULL)
|
||||
{
|
||||
for(i = 0 ; i < 1000 ; i++)
|
||||
{
|
||||
if(TileProperty[i] != NULL)
|
||||
free(TileProperty[i]);
|
||||
}
|
||||
free(TileProperty);
|
||||
}
|
||||
|
||||
TileProperty = (int**) malloc(1000*sizeof(int*));
|
||||
|
||||
for(i = 0 ; i < 1000 ; i++)
|
||||
{
|
||||
TileProperty[i] = NULL;
|
||||
TileProperty[i] = (int*) malloc(6*sizeof(int));
|
||||
}
|
||||
|
||||
for(j=0 ; j < 1000 ; j++ )
|
||||
{
|
||||
for(i=0; i < 6 ; i++)
|
||||
TileProperty[j][i]=0;
|
||||
}
|
||||
|
||||
if(TileProperty == NULL)
|
||||
{
|
||||
crashflag = 1;
|
||||
why_term_ptr = "loadtileattributes(): The memory couldn't be allocated for this version of game!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(i=0 ; i < 6 ; i++)
|
||||
{
|
||||
for(j=0 ; j < numtiles ; j++)
|
||||
{
|
||||
TileProperty[j][i] = filebuf[i*2*(numtiles)+2*j];
|
||||
TileProperty[j][i] += 256*filebuf[i*2*(numtiles)+2*j+1];
|
||||
}
|
||||
}
|
||||
|
||||
free(filebuf);
|
||||
|
||||
int value;
|
||||
|
||||
for( j=0 ; j < (numtiles) ; j++ )
|
||||
{
|
||||
value = TileProperty[j][0];
|
||||
|
||||
// stuff for animated tiles
|
||||
if(value == 1)
|
||||
{
|
||||
tiles[j].animOffset = 0; // starting offset from the base frame
|
||||
}
|
||||
else if( value == 2 )
|
||||
{
|
||||
tiles[j].animOffset = 0; // starting offset from the base frame
|
||||
j++;
|
||||
tiles[j].animOffset = 1; // starting offset from the base frame
|
||||
}
|
||||
else
|
||||
{
|
||||
tiles[j].animOffset = 0; // starting offset from the base frame
|
||||
j++;
|
||||
tiles[j].animOffset = 1; // starting offset from the base frame
|
||||
j++;
|
||||
tiles[j].animOffset = 2; // starting offset from the base frame
|
||||
j++;
|
||||
tiles[j].animOffset = 3; // starting offset from the base frame
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(fname, "ep%dattr.dat", episode);
|
||||
|
||||
|
||||
fp = fopen(fname, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
crashflag = 1;
|
||||
crashflag2 = episode;
|
||||
why_term_ptr = "loadtileattributes(): Cannot open tile attribute file! Episode in flag2.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// load in the tile attributes
|
||||
for(t=0;t<numtiles-1;t++)
|
||||
{
|
||||
a = fgetc(fp); b = fgetc(fp);
|
||||
tiles[t].chgtile = (a*256)+b;
|
||||
if(tiles[t].chgtile > numtiles)
|
||||
tiles[t].chgtile = 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char loadstrings_AddAttr(char *attr, int stringIndex)
|
||||
{
|
||||
char stAttrName[80];
|
||||
|
||||
222
src/fileio/CExeFile.cpp
Normal file
222
src/fileio/CExeFile.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* CExeFile.cpp
|
||||
*
|
||||
* Created on: 17.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CExeFile.h"
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
CExeFile::CExeFile(int episode, char *datadirectory) {
|
||||
m_episode = episode;
|
||||
m_datadirectory = datadirectory;
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
CExeFile::~CExeFile() {
|
||||
if(m_data) delete m_data;
|
||||
}
|
||||
|
||||
bool CExeFile::readData()
|
||||
{
|
||||
char filename[256];
|
||||
unsigned char *m_data_temp;
|
||||
|
||||
sprintf(filename, "data/%skeen%d.exe", m_datadirectory, m_episode);
|
||||
|
||||
ifstream File(filename,ios::binary);
|
||||
|
||||
if(!File) return false;
|
||||
|
||||
File.seekg(0,ios::end);
|
||||
m_datasize = File.tellg();
|
||||
File.seekg(0,ios::beg);
|
||||
|
||||
m_data_temp = new unsigned char[m_datasize];
|
||||
File.read((char*)m_data_temp, m_datasize);
|
||||
|
||||
File.close();
|
||||
|
||||
vector<unsigned char> *decdata;
|
||||
decdata = new vector<unsigned char>;
|
||||
|
||||
if(unlzexe(m_data_temp, decdata))
|
||||
{
|
||||
m_datasize = decdata->size();
|
||||
m_data = new unsigned char[m_datasize];
|
||||
memcpy(m_data, decdata->data(), m_datasize);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_datasize -= 512; // if already decompressed subtract the header
|
||||
m_data = new unsigned char[m_datasize];
|
||||
memcpy(m_data, m_data_temp+512,m_datasize);
|
||||
}
|
||||
delete m_data_temp;
|
||||
|
||||
if(!decdata->empty()) decdata->clear();
|
||||
delete decdata;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CExeFile::get_bit(int *p_bit_count, unsigned char *fin, int *posin)
|
||||
{
|
||||
static unsigned short bits;
|
||||
int bit;
|
||||
|
||||
bit = bits & 1;
|
||||
(*p_bit_count)--;
|
||||
|
||||
if ((*p_bit_count) <= 0)
|
||||
{
|
||||
unsigned short a,b;
|
||||
a = (unsigned char) fin[(*posin)++];
|
||||
b = (unsigned char) fin[(*posin)++] << 8;
|
||||
bits = a | b;
|
||||
|
||||
if ((*p_bit_count) == -1) /* special case for first bit word */
|
||||
{
|
||||
bit = bits & 1;
|
||||
bits >>= 1;
|
||||
}
|
||||
|
||||
(*p_bit_count) += 16;
|
||||
}
|
||||
else
|
||||
bits >>= 1;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
// return how much was unpacked or zero if nothing was unpacked
|
||||
int CExeFile::unlzexe(unsigned char *fin, vector<unsigned char> *outbuffer)
|
||||
{
|
||||
int bit_count;
|
||||
short offset;
|
||||
int pos, repeat;
|
||||
int posin = 0; // position of input
|
||||
|
||||
pos = 0;
|
||||
bit_count = 0;
|
||||
|
||||
/* skip header */
|
||||
posin = 32;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
if (get_bit(&bit_count, fin, &posin))
|
||||
{
|
||||
outbuffer->push_back(fin[posin]);
|
||||
//outbuffer[pos] = fin[posin];
|
||||
pos++;
|
||||
posin++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_bit(&bit_count, fin, &posin))
|
||||
{
|
||||
unsigned char tmp[2];
|
||||
memcpy(tmp,fin+posin,2);
|
||||
posin+=2;
|
||||
repeat = (tmp[1] & 0x07);
|
||||
|
||||
offset = ((tmp[1] & ~0x07) << 5) | tmp[0] | 0xE000;
|
||||
|
||||
if (repeat == 0)
|
||||
{
|
||||
repeat = fin[posin++];
|
||||
|
||||
if (repeat == 0)
|
||||
break;
|
||||
else if (repeat == 1)
|
||||
continue;
|
||||
else
|
||||
repeat++;
|
||||
}
|
||||
else
|
||||
repeat += 2;
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
repeat = get_bit(&bit_count, fin, &posin) << 1;
|
||||
repeat |= get_bit(&bit_count, fin, &posin);
|
||||
repeat += 2;
|
||||
offset = fin[posin++] | 0xFF00;
|
||||
}
|
||||
|
||||
while (repeat > 0)
|
||||
{
|
||||
outbuffer->push_back(outbuffer->at(pos + offset));
|
||||
//outbuffer[pos] = outbuffer[pos + offset];
|
||||
pos++;
|
||||
repeat--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
int CExeFile::getEXEVersion()
|
||||
{
|
||||
switch (m_datasize)
|
||||
{
|
||||
case 99762:
|
||||
if(m_episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 110;
|
||||
case 99972:
|
||||
if(m_episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 398:
|
||||
if(m_episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 134;
|
||||
|
||||
case 118114:
|
||||
if(m_episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 118160:
|
||||
|
||||
if(m_episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 127086:
|
||||
|
||||
if(m_episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 127104:
|
||||
if(m_episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
default: return -2;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* CExeFile::getData()
|
||||
{ return m_data; }
|
||||
|
||||
36
src/fileio/CExeFile.h
Normal file
36
src/fileio/CExeFile.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* CExeFile.h
|
||||
*
|
||||
* Created on: 17.07.2009
|
||||
* Author: gerstrong
|
||||
*
|
||||
* This special class reads the whole exe-file
|
||||
* into the memory and decompresses if necessary
|
||||
*/
|
||||
|
||||
#ifndef CEXEFILE_H_
|
||||
#define CEXEFILE_H_
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
class CExeFile {
|
||||
public:
|
||||
CExeFile(int episode, char *datadirectory);
|
||||
virtual ~CExeFile();
|
||||
|
||||
bool readData();
|
||||
int getEXEVersion();
|
||||
unsigned char* getData();
|
||||
|
||||
private:
|
||||
int m_datasize;
|
||||
int m_episode;
|
||||
unsigned char *m_data;
|
||||
char *m_datadirectory;
|
||||
|
||||
int get_bit(int *p_bit_count, unsigned char *fin, int *posin);
|
||||
int unlzexe(unsigned char *fin, vector<unsigned char> *outbuffer);
|
||||
};
|
||||
|
||||
#endif /* CEXEFILE_H_ */
|
||||
@@ -60,7 +60,7 @@ bool CParser::loadParseFile(void) // Open, read the list and close the file
|
||||
while(!feof(fp))
|
||||
{
|
||||
line = (char*) calloc(256,sizeof(char));
|
||||
fgets(line,256,fp);
|
||||
fgets(line,256,fp); // No return value assigned. Be careful!
|
||||
//fscanf(fp,"%s\n",line);
|
||||
m_filebuffer.push_back(line);
|
||||
m_isOpen = true;
|
||||
|
||||
182
src/fileio/CPatcher.cpp
Normal file
182
src/fileio/CPatcher.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* CPatcher.cpp
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CPatcher.h"
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <fstream>
|
||||
|
||||
CPatcher::CPatcher(int episode, int version,unsigned char *data, char *datadir) {
|
||||
m_episode = episode;
|
||||
m_version = version;
|
||||
m_data = data;
|
||||
strcpy(m_datadirectory, datadir);
|
||||
}
|
||||
|
||||
CPatcher::~CPatcher() {
|
||||
while(!m_TextList.empty())
|
||||
{
|
||||
delete *(m_TextList.begin());
|
||||
m_TextList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void CPatcher::patchMemory()
|
||||
{
|
||||
if(!loadPatchfile()) return;
|
||||
|
||||
// If the file was found and read into the m_TextList,
|
||||
// then read out of the list the patch commands and apply them to the
|
||||
// Exe-file data m_data
|
||||
|
||||
// change to the proper directory
|
||||
chdir("data");
|
||||
chdir(m_datadirectory);
|
||||
|
||||
// TODO: Extend this part further with more commands
|
||||
while(!m_TextList.empty())
|
||||
{
|
||||
char line[256];
|
||||
|
||||
strcpy(line,*(m_TextList.begin()));
|
||||
|
||||
if(strncmp(line,"\%version",strlen("\%version")) == 0)
|
||||
{
|
||||
char *verstring;
|
||||
char detected_version[5];
|
||||
|
||||
verstring = line + strlen("\%version");
|
||||
|
||||
sscanf(verstring,"%s",detected_version);
|
||||
|
||||
if((!strcmp(detected_version,"1.31") && m_version == 131 )
|
||||
|| (!strcmp(detected_version,"1.1") && m_version == 110 )
|
||||
|| !strcmp(detected_version,"ALL"))
|
||||
{
|
||||
while(!m_TextList.empty())
|
||||
{
|
||||
// Get the next line
|
||||
strcpy(line,*(m_TextList.begin()));
|
||||
|
||||
// Now we really start to process the commands
|
||||
if( strncmp(line,"\%patchfile",strlen("\%patchfile")) == 0 )
|
||||
{
|
||||
unsigned long offset;
|
||||
char *newbuf;
|
||||
char patch_file_name[256];
|
||||
newbuf = line + strlen("\%patchfile");
|
||||
sscanf(newbuf,"%lx %s",&offset,patch_file_name); // Only hexadecimal numbers supported
|
||||
patchMemfromFile((const char*)patch_file_name,offset);
|
||||
}
|
||||
|
||||
if(!m_TextList.empty())
|
||||
{
|
||||
delete *(m_TextList.begin());
|
||||
m_TextList.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_TextList.empty())
|
||||
{
|
||||
delete *(m_TextList.begin());
|
||||
m_TextList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
// change back to "data" dir
|
||||
char curdir[256];
|
||||
while(1)
|
||||
{
|
||||
char *reldir;
|
||||
getcwd(curdir,256);
|
||||
reldir = curdir+strlen(curdir)-strlen("data");
|
||||
if(strcmp(reldir,"data"))
|
||||
chdir("..");
|
||||
else
|
||||
break;
|
||||
}
|
||||
chdir("..");
|
||||
}
|
||||
|
||||
bool CPatcher::loadPatchfile()
|
||||
{
|
||||
bool ret = false;
|
||||
chdir("data");
|
||||
chdir(m_datadirectory);
|
||||
// Detect the patchfile
|
||||
DIR *dir = opendir(".");
|
||||
struct dirent *dp;
|
||||
|
||||
if(dir)
|
||||
{
|
||||
while( ( dp = readdir(dir) ) )
|
||||
{
|
||||
if(strstr(dp->d_name,".pat"))
|
||||
{
|
||||
// The file was found! now read it into the memory!
|
||||
|
||||
char* buf;
|
||||
ifstream Patchfile(dp->d_name);
|
||||
|
||||
while(!Patchfile.eof())
|
||||
{
|
||||
buf = new char[256];
|
||||
Patchfile.getline(buf,256);
|
||||
m_TextList.push_back(buf);
|
||||
}
|
||||
|
||||
Patchfile.close();
|
||||
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char curdir[256];
|
||||
while(1)
|
||||
{
|
||||
char *reldir;
|
||||
getcwd(curdir,256);
|
||||
reldir = curdir+strlen(curdir)-strlen("data");
|
||||
if(strcmp(reldir,"data"))
|
||||
chdir("..");
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
chdir("..");
|
||||
closedir(dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CPatcher::patchMemfromFile(const char *patch_file_name, int offset)
|
||||
{
|
||||
unsigned char *buf_to_patch;
|
||||
unsigned char byte;
|
||||
|
||||
ifstream Patchfile(patch_file_name, ios::binary);
|
||||
|
||||
if(!Patchfile) return;
|
||||
|
||||
buf_to_patch = m_data + offset;
|
||||
|
||||
// TODO: Add a routine which checks the sizes of the file.
|
||||
long counter = 0;
|
||||
|
||||
while(!Patchfile.eof())
|
||||
{
|
||||
byte = (unsigned char) Patchfile.get();
|
||||
memcpy(buf_to_patch+counter,&byte,1); // one byte every time ;-)
|
||||
counter++;
|
||||
}
|
||||
|
||||
Patchfile.close();
|
||||
}
|
||||
35
src/fileio/CPatcher.h
Normal file
35
src/fileio/CPatcher.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* CPatcher.h
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CPATCHER_H_
|
||||
#define CPATCHER_H_
|
||||
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
class CPatcher {
|
||||
public:
|
||||
CPatcher(int episode, int version,unsigned char *data, char *datadir);
|
||||
virtual ~CPatcher();
|
||||
|
||||
void patchMemory();
|
||||
void patchMemfromFile(const char *patch_file_name, int offset);
|
||||
|
||||
private:
|
||||
|
||||
bool loadPatchfile();
|
||||
|
||||
int m_episode;
|
||||
int m_version;
|
||||
unsigned char *m_data;
|
||||
char m_datadirectory[256];
|
||||
|
||||
list<char*> m_TextList;
|
||||
|
||||
};
|
||||
|
||||
#endif /* CPATCHER_H_ */
|
||||
203
src/fileio/CTileLoader.cpp
Normal file
203
src/fileio/CTileLoader.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* CTileLoader.cpp
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CTileLoader.h"
|
||||
#include "../CLogFile.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_STRING_LENGTH 256
|
||||
extern stTile tiles[MAX_TILES+1];
|
||||
|
||||
CTileLoader::CTileLoader(int episode, int version, unsigned char *data) {
|
||||
TileProperty = NULL;
|
||||
m_episode = episode;
|
||||
m_version = version;
|
||||
m_data = data;
|
||||
m_offset = 0;
|
||||
}
|
||||
|
||||
CTileLoader::~CTileLoader() {
|
||||
// Here we really start reading the tiles
|
||||
if(TileProperty != NULL)
|
||||
{
|
||||
for(int i = 0 ; i < 1000 ; i++)
|
||||
{
|
||||
if(TileProperty[i] != NULL)
|
||||
{
|
||||
delete [] TileProperty[i];
|
||||
TileProperty[i] = NULL;
|
||||
}
|
||||
}
|
||||
delete [] TileProperty;
|
||||
TileProperty = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CTileLoader::setProperOffset()
|
||||
{
|
||||
// Identify the offset
|
||||
switch (m_episode)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
numtiles = 611;
|
||||
switch(m_version)
|
||||
{
|
||||
case 110: m_offset = 0x131F8; break;
|
||||
case 131: m_offset = 0x130F8; break;
|
||||
case 134: m_offset = 0x130F8; // This is incorrect!
|
||||
g_pLogFile->textOut(PURPLE,"If you want to use Episode 1 Version 1.34, assure that is was unpacked before (with unpklite for example).<br>");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
numtiles = 689;
|
||||
switch(m_version)
|
||||
{
|
||||
case 100: m_offset = 0x17938; break;
|
||||
case 131: m_offset = 0x17828; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
numtiles = 715;
|
||||
switch(m_version)
|
||||
{
|
||||
case 100: m_offset = 0x199F8; break;
|
||||
case 131: m_offset = 0x198C8; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"CAUTION: The version was not detected correctly. The game muy be unplayable!<br>");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_data += m_offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CTileLoader::load()
|
||||
{
|
||||
int t,a,b;
|
||||
char fname[MAX_STRING_LENGTH];
|
||||
int i,j; // standard counters
|
||||
|
||||
if(!setProperOffset()) return false;
|
||||
|
||||
//TileProperty = (int**) malloc(1000*sizeof(int*));
|
||||
TileProperty = new int*[1000];
|
||||
|
||||
for(i = 0 ; i < 1000 ; i++)
|
||||
{
|
||||
TileProperty[i] = NULL;
|
||||
TileProperty[i] = new int[6];
|
||||
}
|
||||
|
||||
for(j=0 ; j < 1000 ; j++ )
|
||||
{
|
||||
for(i=0; i < 6 ; i++)
|
||||
TileProperty[j][i]=0;
|
||||
}
|
||||
|
||||
if(TileProperty == NULL)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"TileLoader: The memory couldn't be allocated for this version of game!<br>");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(i=0 ; i < 6 ; i++)
|
||||
{
|
||||
for(j=0 ; j < numtiles ; j++)
|
||||
{
|
||||
TileProperty[j][i] = m_data[i*2*(numtiles)+2*j];
|
||||
TileProperty[j][i] += m_data[i*2*(numtiles)+2*j+1]<<8;
|
||||
}
|
||||
}
|
||||
|
||||
int value;
|
||||
|
||||
for( j=0 ; j < numtiles ; j++ )
|
||||
{
|
||||
value = TileProperty[j][0];
|
||||
|
||||
// stuff for animated tiles
|
||||
if(value == 1)
|
||||
{
|
||||
tiles[j].animOffset = 0; // starting offset from the base frame
|
||||
}
|
||||
else if( value == 2 )
|
||||
{
|
||||
tiles[j++].animOffset = 0; // starting offset from the base frame
|
||||
tiles[j].animOffset = 1; // starting offset from the base frame
|
||||
}
|
||||
else
|
||||
{
|
||||
tiles[j++].animOffset = 0; // starting offset from the base frame
|
||||
tiles[j++].animOffset = 1; // starting offset from the base frame
|
||||
tiles[j++].animOffset = 2; // starting offset from the base frame
|
||||
tiles[j].animOffset = 3; // starting offset from the base frame
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(fname, "ep%dattr.dat", m_episode);
|
||||
|
||||
FILE *fp;
|
||||
fp = fopen(fname, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"TileLoader: Cannot open tile attribute file!<br>");
|
||||
return false;
|
||||
}
|
||||
|
||||
// load additional information the tiles
|
||||
for(t=0;t<numtiles-1;t++)
|
||||
{
|
||||
a = fgetc(fp); b = fgetc(fp);
|
||||
tiles[t].chgtile = (a<<8)+b;
|
||||
if(tiles[t].chgtile > numtiles)
|
||||
tiles[t].chgtile = 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
// Those Tile data files are an good option, but they are not very well seen.
|
||||
// Especially in mods. The one of Episode 2 has an error with items already
|
||||
// I'm to lazy to write a program which fixes the file so a new assignTilePointer is
|
||||
// used, which in future will replace the files making them obsolete
|
||||
assignChangeTileAttribute(tiles);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTileLoader::assignChangeTileAttribute(stTile *tile)
|
||||
{
|
||||
// This special call is used for workarounds which are wrong in the tiles attributes file of CG.
|
||||
// I hope those attributes can be read out of the exe-files in future.
|
||||
switch(m_episode)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
for(int i=306 ; i<=311 ; i++) // Workaround in Level 12 of Episode 2, where the tiles are solid after a taken item.
|
||||
tile[i].chgtile = 276;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/fileio/CTileLoader.h
Normal file
41
src/fileio/CTileLoader.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* CTileLoader.h
|
||||
*
|
||||
* Created on: 19.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CTILELOADER_H_
|
||||
#define CTILELOADER_H_
|
||||
|
||||
#define MAX_TILES 800
|
||||
|
||||
extern int numtiles;
|
||||
extern int **TileProperty; // This version will replace the old stTile Structure and save memory
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int masktile; // if nonzero, specifies a mask for this tile
|
||||
int chgtile; // tile to change to when level completed (for wm)
|
||||
// or tile to change to when picked up (in-level)
|
||||
unsigned int animOffset; // starting offset from the base frame
|
||||
} stTile;
|
||||
|
||||
class CTileLoader {
|
||||
public:
|
||||
CTileLoader(int episode, int version, unsigned char *data);
|
||||
virtual ~CTileLoader();
|
||||
|
||||
bool load();
|
||||
|
||||
private:
|
||||
int m_episode;
|
||||
int m_version;
|
||||
long m_offset;
|
||||
unsigned char *m_data;
|
||||
|
||||
void assignChangeTileAttribute(stTile *tile);
|
||||
bool setProperOffset();
|
||||
};
|
||||
|
||||
#endif /* CTILELOADER_H_ */
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* lzexe.c
|
||||
*
|
||||
* Created on: 24.01.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int get_bit(int *p_bit_count, FILE **fin)
|
||||
{
|
||||
static unsigned short bits;
|
||||
int bit;
|
||||
|
||||
bit = bits & 1;
|
||||
(*p_bit_count)--;
|
||||
|
||||
if ((*p_bit_count) <= 0)
|
||||
{
|
||||
bits = getc(*fin) | getc(*fin) << 8;
|
||||
|
||||
if ((*p_bit_count) == -1) /* special case for first bit word */
|
||||
{
|
||||
bit = bits & 1;
|
||||
bits >>= 1;
|
||||
}
|
||||
|
||||
(*p_bit_count) += 16;
|
||||
}
|
||||
else
|
||||
bits >>= 1;
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
int getEXEVersion(int episode, int bufsize)
|
||||
{
|
||||
switch (bufsize)
|
||||
{
|
||||
case 99762:
|
||||
if(episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 110;
|
||||
case 99972:
|
||||
if(episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 398:
|
||||
if(episode != 1)
|
||||
return -1;
|
||||
else
|
||||
return 134;
|
||||
|
||||
case 118114:
|
||||
if(episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 118160:
|
||||
|
||||
if(episode != 2)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
case 127086:
|
||||
|
||||
if(episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 100;
|
||||
|
||||
case 127104:
|
||||
if(episode != 3)
|
||||
return -1;
|
||||
else
|
||||
return 131;
|
||||
|
||||
default: return -2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// return how much was unpacked or zero if nothing was unpacked
|
||||
int unlzexe(FILE *fin, unsigned char *outbuffer)
|
||||
{
|
||||
int bit_count;
|
||||
short offset;
|
||||
int pos, repeat;
|
||||
|
||||
pos = 0;
|
||||
bit_count = 0;
|
||||
|
||||
/* skip header */
|
||||
fseek(fin, 32, SEEK_SET);
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
if (get_bit(&bit_count, &fin))
|
||||
{
|
||||
outbuffer[pos++] = getc(fin);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_bit(&bit_count, &fin))
|
||||
{
|
||||
unsigned char tmp[2];
|
||||
fread(tmp, 1, 2, fin);
|
||||
repeat = (tmp[1] & 0x07);
|
||||
|
||||
offset = ((tmp[1] & ~0x07) << 5) | tmp[0] | 0xE000;
|
||||
|
||||
if (repeat == 0)
|
||||
{
|
||||
repeat = getc (fin);
|
||||
|
||||
|
||||
if (repeat == 0)
|
||||
break;
|
||||
else if (repeat == 1)
|
||||
continue;
|
||||
else
|
||||
repeat++;
|
||||
}
|
||||
else
|
||||
repeat += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
repeat = ((get_bit(&bit_count, &fin) << 1) | get_bit(&bit_count, &fin)) + 2;
|
||||
offset = getc(fin) | 0xFF00;
|
||||
}
|
||||
|
||||
while (repeat > 0)
|
||||
{
|
||||
outbuffer[pos] = outbuffer[pos + offset];
|
||||
pos++;
|
||||
repeat--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
*/
|
||||
|
||||
#include "../keen.h"
|
||||
#include "../include/fileio/lzexe.h"
|
||||
#include "../include/fileio.h"
|
||||
#include "../fileio/CExeFile.h"
|
||||
#include "../CLogFile.h"
|
||||
|
||||
int readStoryText(char **ptext, int episode, char *path)
|
||||
@@ -32,27 +32,11 @@ int readStoryText(char **ptext, int episode, char *path)
|
||||
if((fp=fopen(buf,"rb"))!=NULL)
|
||||
{
|
||||
unsigned char *filebuf;
|
||||
int bufsize;
|
||||
int startflag=0, endflag=0; // where story begins and ends!
|
||||
|
||||
filebuf = (unsigned char*) malloc(500000*sizeof(unsigned char));
|
||||
|
||||
bufsize = unlzexe(fp, filebuf);
|
||||
|
||||
rewind(fp);
|
||||
|
||||
if ( bufsize == 0 ) // Program was not unpacked, so read it normally
|
||||
{
|
||||
while(!feof(fp))
|
||||
{
|
||||
filebuf[bufsize] = getc(fp);
|
||||
bufsize++;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
int startflag=0, endflag=0, version=0; // where story begins and ends!
|
||||
|
||||
version = getEXEVersion(episode, bufsize);
|
||||
CExeFile *ExeFile = new CExeFile(episode, buf2);
|
||||
ExeFile->readData();
|
||||
filebuf = ExeFile->getData();
|
||||
|
||||
if(episode == 2)
|
||||
{
|
||||
@@ -74,8 +58,7 @@ int readStoryText(char **ptext, int episode, char *path)
|
||||
*ptext = (char*) malloc((endflag-startflag+10)*sizeof(char));
|
||||
strncpy((*ptext),(char*)filebuf+startflag,(endflag-startflag)*sizeof(char));
|
||||
}
|
||||
|
||||
free(filebuf);
|
||||
delete ExeFile;
|
||||
|
||||
return (endflag-startflag);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ void gamedo_fades(void);
|
||||
//void gamepdo_wm_HandlePlayer(int cp);
|
||||
//void gamepdo_InertiaAndFriction_Y(int cp);
|
||||
//void gamepdo_wm_AllowEnterLevel(int cp);
|
||||
char wm_issolid(int xb, int yb);
|
||||
char wm_issolid(int xb, int yb, int *levels_completed);
|
||||
|
||||
// game.c
|
||||
//void SetGameOver(void);
|
||||
@@ -110,11 +110,8 @@ void sb_font_draw_inverse(unsigned char *text, int xoff, int yoff);
|
||||
//unsigned long fgetl(FILE *fp);
|
||||
//unsigned int loadmap(char *filename, char *path, int lvlnum, int isworldmap);
|
||||
#include "fileio.h"
|
||||
char loadtiles(char *fname);
|
||||
char loadsprites(char *spritename);
|
||||
char loadfont(char *fontname);
|
||||
//char loadstrings(const char *fname);
|
||||
char loadtileattributes(int episode, char *extrapath);
|
||||
|
||||
bool loadtileattributes(int episode, int version, unsigned char *filebuf);
|
||||
int freestrings(void);
|
||||
char* getstring(const char *name);
|
||||
int GetStringAttribute(const char *stringName, const char *attrName);
|
||||
|
||||
2987
src/game.cpp
2987
src/game.cpp
File diff suppressed because it is too large
Load Diff
200
src/gamepdo.cpp
200
src/gamepdo.cpp
@@ -59,7 +59,6 @@ char doFall;
|
||||
|
||||
gamepdo_keencicle(cp, pCKP);
|
||||
|
||||
|
||||
if(!player[cp].pjumping && !player[cp].pfalling)
|
||||
{
|
||||
gamepdo_walking(cp, pCKP);
|
||||
@@ -373,7 +372,7 @@ void gamepdo_setblockedlru(unsigned int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
|
||||
// set psliding if we're on ice
|
||||
if (TileProperty[getmaptileat(tx,ty+PLAYERHEIGHT)][BUP] == 3)
|
||||
if (TileProperty[getmaptileat(tx,ty+PLAYERHEIGHT)][BUP] == 3 && !player[cp].ppogostick)
|
||||
{
|
||||
player[cp].psliding = 1;
|
||||
player[cp].pshowdir = player[cp].pdir;
|
||||
@@ -520,7 +519,7 @@ void gamepdo_walkinganim(int cp, stCloneKeenPlus *pCKP)
|
||||
// make walk noise
|
||||
if (!player[cp].pjumping && !player[cp].pfalling)
|
||||
{
|
||||
if (!player[cp].pfrozentime)
|
||||
if (!player[cp].pfrozentime && player[cp].pwalking)
|
||||
{
|
||||
if (player[cp].pwalkframea&1)
|
||||
{
|
||||
@@ -620,7 +619,6 @@ void gamepdo_playpushed(int cp, stCloneKeenPlus *pCKP)
|
||||
// (this is where the inertia/playpushed_x is actually applied to playx)
|
||||
void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
|
||||
{
|
||||
|
||||
stLevelControl *p_levelcontrol;
|
||||
int friction_rate;
|
||||
|
||||
@@ -640,7 +638,7 @@ void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
|
||||
// Check walking boost and pogoing. It is similar to inertia
|
||||
if(player[cp].pjumping || player[cp].pfalling)
|
||||
{
|
||||
if (player[cp].playcontrol[PA_X] < 0)
|
||||
if (player[cp].playcontrol[PA_X] < 0 && !player[cp].pfrozentime)
|
||||
{
|
||||
if(player[cp].pboost_x > 0 && !player[cp].ppogostick)
|
||||
{
|
||||
@@ -649,10 +647,10 @@ void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
else
|
||||
{
|
||||
player[cp].pboost_x--;
|
||||
player[cp].pboost_x-= player[cp].ppogostick ? 2 : 1;
|
||||
}
|
||||
}
|
||||
if (player[cp].playcontrol[PA_X] > 0)
|
||||
if (player[cp].playcontrol[PA_X] > 0 && !player[cp].pfrozentime)
|
||||
{
|
||||
if(player[cp].pboost_x < 0 && !player[cp].ppogostick)
|
||||
{
|
||||
@@ -661,7 +659,7 @@ void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
else
|
||||
{
|
||||
player[cp].pboost_x++;
|
||||
player[cp].pboost_x+= player[cp].ppogostick ? 2 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,7 +694,8 @@ void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
|
||||
// Calculate Threshold of your analog device for walking animation speed!
|
||||
player[cp].treshold = player[cp].playcontrol[PA_X];
|
||||
if(!player[cp].pfrozentime)
|
||||
player[cp].treshold = player[cp].playcontrol[PA_X];
|
||||
|
||||
int pmaxspeed = 0;
|
||||
|
||||
@@ -818,7 +817,7 @@ void gamepdo_InertiaAndFriction_X(unsigned int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
|
||||
}
|
||||
void gamepdo_Jump(int cp, stCloneKeenPlus *pCKP)
|
||||
void gamepdo_Jump(int cp)
|
||||
{
|
||||
// handle the JUMP key, both for normal jumps and (high) pogo jumps
|
||||
if (!player[cp].pjumping && !player[cp].pfalling && !player[cp].pfiring)
|
||||
@@ -907,87 +906,80 @@ p_levelcontrol = &(pCKP->Control.levelcontrol);
|
||||
// toggle pogo when KPOGO key is pressed
|
||||
if (player[cp].playcontrol[PA_POGO] && !player[cp].lastplaycontrol[PA_POGO] && !player[cp].pfrozentime)
|
||||
{
|
||||
if (p_levelcontrol->episode==2)
|
||||
{
|
||||
// if we are at a switch hit the switch instead
|
||||
mx = (player[cp].x>>CSF)+8;
|
||||
my = (player[cp].y>>CSF)+9;
|
||||
try2 = 0;
|
||||
retry: ;
|
||||
t = getmaptileat(mx, my);
|
||||
if (player[cp].ppogostick==0 && (t==TILE_SWITCH_UP || t==TILE_SWITCH_DOWN))
|
||||
{ // switch to extend platform
|
||||
// if we are at a switch hit the switch instead
|
||||
mx = (player[cp].x>>CSF)+8;
|
||||
my = (player[cp].y>>CSF)+9;
|
||||
try2 = 0;
|
||||
retry: ;
|
||||
t = getmaptileat(mx, my);
|
||||
if (!player[cp].ppogostick && (t==TILE_SWITCH_UP || t==TILE_SWITCH_DOWN))
|
||||
{ // switch to extend platform
|
||||
|
||||
// figure out where the platform is supposed to extend
|
||||
// (this is coded in the object layer...high byte is the Y offset
|
||||
// and the low byte is the X offset)
|
||||
l = getlevelat(mx, my);
|
||||
// if zero it's the switch on a tantalus ray!
|
||||
if (l==0)
|
||||
{
|
||||
g_pSound->playStereofromCoord(SOUND_SWITCH_TOGGLE, PLAY_NOW, objects[player[cp].useObject].scrx);
|
||||
// figure out where the platform is supposed to extend
|
||||
// (this is coded in the object layer...high byte is the Y offset
|
||||
// and the low byte is the X offset)
|
||||
l = getlevelat(mx, my);
|
||||
// if zero it's the switch on a tantalus ray!
|
||||
if (l==0)
|
||||
{
|
||||
g_pSound->playStereofromCoord(SOUND_SWITCH_TOGGLE, PLAY_NOW, objects[player[cp].useObject].scrx);
|
||||
|
||||
map_chgtile(mx>>4,my>>4,TILE_SWITCH_DOWN);
|
||||
p_levelcontrol->success = 0;
|
||||
p_levelcontrol->command = LVLC_TANTALUS_RAY;
|
||||
return;
|
||||
}
|
||||
pxoff = (l & 0x00ff);
|
||||
pyoff = (l & 0xff00) >> 8;
|
||||
platx = (mx >> 4) + pxoff;
|
||||
platy = (my >> 4) + pyoff;
|
||||
map_chgtile(mx>>4,my>>4,TILE_SWITCH_DOWN);
|
||||
p_levelcontrol->success = 0;
|
||||
p_levelcontrol->command = LVLC_TANTALUS_RAY;
|
||||
return;
|
||||
}
|
||||
pxoff = (l & 0x00ff);
|
||||
pyoff = (l & 0xff00) >> 8;
|
||||
platx = (mx >> 4) + pxoff;
|
||||
platy = (my >> 4) + pyoff;
|
||||
|
||||
if (PlatExtending) // don't allow player to hit switch again while
|
||||
{ // plat is moving as this will glitch the plat
|
||||
return;
|
||||
}
|
||||
else PlatExtending = 1;
|
||||
if (PlatExtending) // don't allow player to hit switch again while
|
||||
{ // plat is moving as this will glitch the plat
|
||||
return;
|
||||
}
|
||||
else PlatExtending = 1;
|
||||
|
||||
g_pSound->playStereofromCoord(SOUND_SWITCH_TOGGLE, PLAY_NOW, objects[player[cp].useObject].scrx);
|
||||
g_pSound->playStereofromCoord(SOUND_SWITCH_TOGGLE, PLAY_NOW, objects[player[cp].useObject].scrx);
|
||||
|
||||
if (t==TILE_SWITCH_UP)
|
||||
{ // switch toggled from up to down--extend platform
|
||||
map_chgtile(mx>>4,my>>4,TILE_SWITCH_DOWN);
|
||||
o = spawn_object((mx>>4<<4)<<CSF,(my>>4<<4)<<CSF,OBJ_SECTOREFFECTOR);
|
||||
objects[o].ai.se.type = SE_EXTEND_PLATFORM;
|
||||
objects[o].ai.se.platx = platx;
|
||||
objects[o].ai.se.platy = platy;
|
||||
}
|
||||
else
|
||||
{ // switch toggled from down to up--remove platform
|
||||
map_chgtile(mx>>4,my>>4,TILE_SWITCH_UP);
|
||||
o = spawn_object((mx>>4<<4)<<CSF,(my>>4<<4)<<CSF,OBJ_SECTOREFFECTOR);
|
||||
objects[o].ai.se.type = SE_RETRACT_PLATFORM;
|
||||
objects[o].ai.se.platx = platx;
|
||||
objects[o].ai.se.platy = platy;
|
||||
}
|
||||
}
|
||||
else if (player[cp].ppogostick==0 && t==TILE_LIGHTSWITCH)
|
||||
{ // lightswitch
|
||||
p_levelcontrol->dark ^= 1;
|
||||
g_pGraphics->initPalette(p_levelcontrol->dark);
|
||||
g_pGraphics->fadePalette(PAL_FADE_SHADES);
|
||||
g_pSound->playStereofromCoord(SOUND_SWITCH_TOGGLE, PLAY_NOW, objects[player[cp].useObject].scrx);
|
||||
}
|
||||
else
|
||||
{ // toggle pogo stick
|
||||
if (!try2)
|
||||
{
|
||||
my = (player[cp].y>>CSF)+1;
|
||||
try2 = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
player[cp].ppogostick = 1 - player[cp].ppogostick;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // not episode 2...don't bother with all of this
|
||||
if (player[cp].inventory.HasPogo)
|
||||
{
|
||||
player[cp].ppogostick = 1 - player[cp].ppogostick;
|
||||
}
|
||||
}
|
||||
if (t==TILE_SWITCH_UP)
|
||||
{ // switch toggled from up to down--extend platform
|
||||
map_chgtile(mx>>4,my>>4,TILE_SWITCH_DOWN);
|
||||
o = spawn_object((mx>>4<<4)<<CSF,(my>>4<<4)<<CSF,OBJ_SECTOREFFECTOR);
|
||||
objects[o].ai.se.type = SE_EXTEND_PLATFORM;
|
||||
objects[o].ai.se.platx = platx;
|
||||
objects[o].ai.se.platy = platy;
|
||||
}
|
||||
else
|
||||
{ // switch toggled from down to up--remove platform
|
||||
map_chgtile(mx>>4,my>>4,TILE_SWITCH_UP);
|
||||
o = spawn_object((mx>>4<<4)<<CSF,(my>>4<<4)<<CSF,OBJ_SECTOREFFECTOR);
|
||||
objects[o].ai.se.type = SE_RETRACT_PLATFORM;
|
||||
objects[o].ai.se.platx = platx;
|
||||
objects[o].ai.se.platy = platy;
|
||||
}
|
||||
}
|
||||
else if (!player[cp].ppogostick && t==TILE_LIGHTSWITCH)
|
||||
{ // lightswitch
|
||||
p_levelcontrol->dark ^= 1;
|
||||
g_pGraphics->initPalette(p_levelcontrol->dark);
|
||||
g_pGraphics->fadePalette(PAL_FADE_SHADES);
|
||||
g_pSound->playStereofromCoord(SOUND_SWITCH_TOGGLE, PLAY_NOW, objects[player[cp].useObject].scrx);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!try2)
|
||||
{
|
||||
my = (player[cp].y>>CSF)+1;
|
||||
try2 = 1;
|
||||
goto retry;
|
||||
}
|
||||
// toggle pogo
|
||||
if (player[cp].inventory.HasPogo)
|
||||
{
|
||||
player[cp].ppogostick = !player[cp].ppogostick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handle the JUMP key, both for normal jumps and (high) pogo jumps
|
||||
@@ -1036,7 +1028,7 @@ p_levelcontrol = &(pCKP->Control.levelcontrol);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(player[cp].ppogostick != 0)
|
||||
if(player[cp].ppogostick)
|
||||
{
|
||||
player[cp].pjumpupspeed = PJUMPUP_SPEED;
|
||||
player[cp].pjumptime = PJUMP_NORMALTIME_POGO_SHORT;
|
||||
@@ -1053,10 +1045,20 @@ p_levelcontrol = &(pCKP->Control.levelcontrol);
|
||||
case PPREPAREJUMP:
|
||||
player[cp].widejump = true;
|
||||
|
||||
if(g_pInput->getHoldedCommand(IC_LEFT))
|
||||
player[cp].chargedjump-=2;
|
||||
else if(g_pInput->getHoldedCommand(IC_RIGHT))
|
||||
player[cp].chargedjump+=2;
|
||||
if(player[cp].psliding)
|
||||
{
|
||||
if(player[cp].pdir == LEFT)
|
||||
player[cp].chargedjump-=2;
|
||||
else if(player[cp].pdir == RIGHT)
|
||||
player[cp].chargedjump+=2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(g_pInput->getHoldedCommand(IC_LEFT))
|
||||
player[cp].chargedjump-=2;
|
||||
else if(g_pInput->getHoldedCommand(IC_RIGHT))
|
||||
player[cp].chargedjump+=2;
|
||||
}
|
||||
|
||||
player[cp].pinertia_x = 0; // prevent moving while preparing to jump
|
||||
if (player[cp].pjumpanimtimer > PJUMP_PREPARE_ANIM_RATE)
|
||||
@@ -1070,31 +1072,31 @@ p_levelcontrol = &(pCKP->Control.levelcontrol);
|
||||
case PPREPAREJUMPFRAME:
|
||||
player[cp].pjumptime = PJUMP_NORMALTIME_6;
|
||||
player[cp].pjumpupdecreaserate = PJUMP_UPDECREASERATE_6;
|
||||
player[cp].pjumpupspeed = 6;
|
||||
player[cp].pjumpupspeed = 1;
|
||||
player[cp].chargedjump = player[cp].chargedjump >> 5;
|
||||
break;
|
||||
case PPREPAREJUMPFRAME+1:
|
||||
player[cp].pjumptime = PJUMP_NORMALTIME_5;
|
||||
player[cp].pjumpupdecreaserate = PJUMP_UPDECREASERATE_5;
|
||||
player[cp].pjumpupspeed = 8;
|
||||
player[cp].pjumpupspeed = 2;
|
||||
player[cp].chargedjump = player[cp].chargedjump >> 4;
|
||||
break;
|
||||
case PPREPAREJUMPFRAME+2:
|
||||
player[cp].pjumptime = PJUMP_NORMALTIME_4;
|
||||
player[cp].pjumpupdecreaserate = PJUMP_UPDECREASERATE_4;
|
||||
player[cp].pjumpupspeed = 10;
|
||||
player[cp].pjumpupspeed = 4;
|
||||
player[cp].chargedjump = player[cp].chargedjump >> 3;
|
||||
break;
|
||||
case PPREPAREJUMPFRAME+3:
|
||||
player[cp].pjumptime = PJUMP_NORMALTIME_3;
|
||||
player[cp].pjumpupdecreaserate = PJUMP_UPDECREASERATE_3;
|
||||
player[cp].pjumpupspeed = 14;
|
||||
player[cp].pjumpupspeed = 8;
|
||||
player[cp].chargedjump = player[cp].chargedjump >> 2;
|
||||
break;
|
||||
case PPREPAREJUMPFRAME+4:
|
||||
player[cp].pjumptime = PJUMP_NORMALTIME_2;
|
||||
player[cp].pjumpupdecreaserate = PJUMP_UPDECREASERATE_2;
|
||||
player[cp].pjumpupspeed = 18;
|
||||
player[cp].pjumpupspeed = 16;
|
||||
player[cp].chargedjump = player[cp].chargedjump >> 1;
|
||||
break;
|
||||
default:
|
||||
@@ -1349,7 +1351,7 @@ int canRefire;
|
||||
{
|
||||
player[cp].inhibitwalking = 1; // prevent moving
|
||||
player[cp].pfiring = 1; // flag that we're firing
|
||||
player[cp].ppogostick = 0; // put away pogo stick if out
|
||||
player[cp].ppogostick = false; // put away pogo stick if out
|
||||
|
||||
if (!player[cp].lastplaycontrol[PA_FIRE] || pCKP->Option[OPT_FULLYAUTOMATIC].value)
|
||||
{ // fire is newly pressed
|
||||
@@ -1509,7 +1511,7 @@ void gamepdo_walking(int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
|
||||
// if we fall onto a semislide tile with no inertia
|
||||
// start moving a little
|
||||
// don't move!.
|
||||
if (player[cp].pjustfell && player[cp].psemisliding)
|
||||
{
|
||||
if (player[cp].pdir==RIGHT)
|
||||
@@ -1521,7 +1523,6 @@ void gamepdo_walking(int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!player[cp].pinertia_x) player[cp].pinertia_x = 1;
|
||||
player[cp].pshowdir = player[cp].pdir;
|
||||
}
|
||||
}
|
||||
@@ -1534,7 +1535,6 @@ void gamepdo_walking(int cp, stCloneKeenPlus *pCKP)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!player[cp].pinertia_x) player[cp].pinertia_x = -1;
|
||||
player[cp].pshowdir = player[cp].pdir;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,35 +84,35 @@ void gamepdo_wm_setblockedlrud(int cp, stCloneKeenPlus *pCKP)
|
||||
if ((pCKP->Option[OPT_CHEATS].value && g_pInput->getHoldedKey(KTAB)) || player[cp].godmode) return;
|
||||
|
||||
// R
|
||||
if (wm_issolid((player[cp].x>>CSF)+8, (player[cp].y>>CSF)+1))
|
||||
if (wm_issolid((player[cp].x>>CSF)+8, (player[cp].y>>CSF)+1, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedr = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+8, (player[cp].y>>CSF)+8))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+8, (player[cp].y>>CSF)+8, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedr = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+8, (player[cp].y>>CSF)+13))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+8, (player[cp].y>>CSF)+13, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedr = 1; }
|
||||
|
||||
// L
|
||||
if (wm_issolid((player[cp].x>>CSF)+0, (player[cp].y>>CSF)+1))
|
||||
if (wm_issolid((player[cp].x>>CSF)+0, (player[cp].y>>CSF)+1, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedl = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+0, (player[cp].y>>CSF)+8))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+0, (player[cp].y>>CSF)+8, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedl = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+0, (player[cp].y>>CSF)+13))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+0, (player[cp].y>>CSF)+13, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedl = 1; }
|
||||
|
||||
// U
|
||||
if (wm_issolid((player[cp].x>>CSF)+1, (player[cp].y>>CSF)-1))
|
||||
if (wm_issolid((player[cp].x>>CSF)+1, (player[cp].y>>CSF)-1, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedu = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+4, (player[cp].y>>CSF)-1))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+4, (player[cp].y>>CSF)-1, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedu = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+7, (player[cp].y>>CSF)-1))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+7, (player[cp].y>>CSF)-1, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedu = 1; }
|
||||
|
||||
// D
|
||||
if (wm_issolid((player[cp].x>>CSF)+1, (player[cp].y>>CSF)+14))
|
||||
if (wm_issolid((player[cp].x>>CSF)+1, (player[cp].y>>CSF)+14, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedd = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+4, (player[cp].y>>CSF)+14))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+4, (player[cp].y>>CSF)+14, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedd = 1; }
|
||||
else if (wm_issolid((player[cp].x>>CSF)+7, (player[cp].y>>CSF)+14))
|
||||
else if (wm_issolid((player[cp].x>>CSF)+7, (player[cp].y>>CSF)+14, pCKP->Control.levelcontrol.levels_completed))
|
||||
{ player[cp].blockedd = 1; }
|
||||
|
||||
}
|
||||
@@ -314,7 +314,7 @@ p_levelcontrol = &(pCKP->Control.levelcontrol);
|
||||
break;
|
||||
|
||||
default: // a regular level
|
||||
p_levelcontrol->chglevelto = (lvl & 0x7fff);
|
||||
p_levelcontrol->chglevelto = (lvl & 0x7fff);
|
||||
endlevel(1, pCKP);
|
||||
g_pMusicPlayer->stop();
|
||||
g_pSound->playStereofromCoord(SOUND_ENTER_LEVEL, PLAY_NOW, objects[player[cp].useObject].scrx);
|
||||
@@ -329,14 +329,22 @@ p_levelcontrol = &(pCKP->Control.levelcontrol);
|
||||
player[cp].wm_lastenterstate = (player[cp].playcontrol[PA_JUMP] || player[cp].playcontrol[PA_POGO]);
|
||||
}
|
||||
|
||||
char wm_issolid(int xb, int yb)
|
||||
char wm_issolid(int xb, int yb, int *levels_completed)
|
||||
{
|
||||
|
||||
// for map tiles solidl and solidr are always gonna be the same...
|
||||
// so we can get away with this.
|
||||
if ( TileProperty[getmaptileat(xb, yb)][BLEFT] ) return 1;
|
||||
//if (tiles[getmaptileat(xb, yb)].solidl) return 1;
|
||||
if (getlevelat(xb, yb) & 0x8000)
|
||||
|
||||
unsigned int level;
|
||||
level = getlevelat(xb, yb);
|
||||
|
||||
if (level & 0x8000)
|
||||
{
|
||||
if(levels_completed[map.objectlayer[xb>>4][yb>>4] & 0x7fff] && options[OPT_LVLREPLAYABILITY].value) // check if level is done, but can be replayed
|
||||
return 0;
|
||||
|
||||
if(g_pInput->getHoldedKey(KTAB) && g_pInput->getHoldedKey(KLSHIFT))
|
||||
{
|
||||
return 0;
|
||||
@@ -392,19 +400,19 @@ int objmarker;
|
||||
// is he trying to mount?
|
||||
if (player[cp].y>>CSF>>4 < map.ysize>>2)
|
||||
{ // at mortimer's castle mount point
|
||||
/*if ( (player[cp].keytable[KRIGHT] && player[cp].blockedr) || \
|
||||
(player[cp].keytable[KDOWN] && player[cp].blockedd))
|
||||
if ( (player[cp].playcontrol[PA_X] > 0 && player[cp].blockedr) ||
|
||||
(player[cp].playcontrol[PA_Y] > 0 && player[cp].blockedd))
|
||||
{
|
||||
// YES! if nessie is at that mount point, mount her!!
|
||||
MountNessieIfAvailable(cp);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // at secret island mount point
|
||||
/*if (player[cp].keytable[KUP] && player[cp].blockedu)
|
||||
if (player[cp].playcontrol[PA_Y] < 0 && player[cp].blockedu)
|
||||
{
|
||||
MountNessieIfAvailable(cp);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -413,17 +421,17 @@ int objmarker;
|
||||
{ // nessie is paused
|
||||
if (objects[NessieObjectHandle].y>>CSF>>4 < map.ysize>>2)
|
||||
{ // nessie is at mortimer's castle mount point
|
||||
/*if (player[cp].keytable[KUP])
|
||||
if (player[cp].playcontrol[PA_Y] < 0)
|
||||
{
|
||||
// unmount nessie
|
||||
objects[NessieObjectHandle].ai.nessie.mounted[cp] = 0;
|
||||
player[cp].mounted = 0;
|
||||
player[cp].hideplayer = 0;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else if (objects[NessieObjectHandle].y>>CSF>>4 > map.ysize>>1)
|
||||
{ // nessie is at secret island mount point
|
||||
/*if (player[cp].keytable[KDOWN])
|
||||
if (player[cp].playcontrol[PA_Y] > 0)
|
||||
{
|
||||
// unmount nessie
|
||||
objects[NessieObjectHandle].ai.nessie.mounted[cp] = 0;
|
||||
@@ -431,7 +439,7 @@ int objmarker;
|
||||
player[cp].hideplayer = 0;
|
||||
player[cp].y += (18<<CSF);
|
||||
player[cp].x += (8<<CSF);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,39 +24,50 @@ CHQBitmap::~CHQBitmap() {
|
||||
|
||||
bool CHQBitmap::loadImage(const char *pFilename, int wsize, int hsize)
|
||||
{
|
||||
m_scrimg = SDL_LoadBMP(pFilename);
|
||||
SDL_Surface *BitmapSurface = SDL_LoadBMP(pFilename);
|
||||
|
||||
m_active = false;
|
||||
|
||||
if(m_scrimg)
|
||||
if(BitmapSurface)
|
||||
{
|
||||
|
||||
if( ((m_scrimg->h>>4) > hsize) || ((m_scrimg->w>>4) > wsize) )
|
||||
if((m_scrimg = SDL_DisplayFormat(BitmapSurface)))
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"HQBitmapLoader : The dimensions of the bitmap don't match to the dimensions of the level.<br>");
|
||||
g_pLogFile->ftextOut("Please use a proper bitmap with %dx%d dimensions.<br>", m_scrimg->w, m_scrimg->h);
|
||||
g_pLogFile->ftextOut("Your bitmap is of %dx%d.<br>", wsize, hsize);
|
||||
g_pLogFile->textOut(BLUE,"HQBitmapLoader : Loading the level without HQBitmap.<br>");
|
||||
SDL_FreeSurface(BitmapSurface);
|
||||
|
||||
if( ((m_scrimg->h>>4) > hsize) || ((m_scrimg->w>>4) > wsize) )
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"HQBitmapLoader : The dimensions of the bitmap don't match to the dimensions of the level.<br>");
|
||||
g_pLogFile->ftextOut("Please use a proper bitmap with %dx%d dimensions.<br>", m_scrimg->w, m_scrimg->h);
|
||||
g_pLogFile->ftextOut("Your bitmap is of %dx%d.<br>", wsize, hsize);
|
||||
g_pLogFile->textOut(BLUE,"HQBitmapLoader : Loading the level without HQBitmap.<br>");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_active = true;
|
||||
// Create a empty black surface for alpha blending with black
|
||||
SDL_Surface *BlackScreenCreation = SDL_CreateRGBSurface(0, 320,240,32,0,0,0,0);
|
||||
m_blackscreen = SDL_DisplayFormat(BlackScreenCreation);
|
||||
SDL_FreeSurface(BlackScreenCreation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_active = true;
|
||||
// Create a empty black surface for alpha blending with black
|
||||
m_blackscreen = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
320,240,32,0,0,0,0);
|
||||
g_pLogFile->textOut(PURPLE,"Error: The HQBitmap could not be loaded to the memory!");
|
||||
return m_active;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return m_active;
|
||||
}
|
||||
|
||||
void CHQBitmap::updateHQBitmap(SDL_Surface *m_surface, unsigned int x, unsigned int y)
|
||||
void CHQBitmap::updateHQBitmap(SDL_Surface *m_surface, SDL_Rect *p_srcrect, SDL_Rect *p_dstrect)
|
||||
{
|
||||
m_imagerect.x = x;
|
||||
m_imagerect.y = y;
|
||||
m_imagerect.w = m_surface->w;
|
||||
m_imagerect.h = m_surface->h;
|
||||
|
||||
SDL_BlitSurface(m_scrimg, &m_imagerect, m_surface, NULL);
|
||||
SDL_BlitSurface(m_scrimg, p_srcrect, m_surface, p_dstrect);
|
||||
|
||||
if(m_alpha == 255)
|
||||
return;
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
virtual ~CHQBitmap();
|
||||
|
||||
void setScrollposition(unsigned int xpos, unsigned int ypos);
|
||||
void updateHQBitmap(SDL_Surface *m_surface, unsigned int x, unsigned int y);
|
||||
void updateHQBitmap(SDL_Surface *m_surface, SDL_Rect *p_srcrect, SDL_Rect *p_dstrect);
|
||||
bool loadImage(const char *pFilename, int wsize, int hsize);
|
||||
void setAlphaBlend(Uint8 alpha);
|
||||
void offsetAlphaBlend(Uint8 alpha);
|
||||
|
||||
@@ -41,7 +41,7 @@ int CMusic::load(SDL_AudioSpec AudioSpec, char *musicfile)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(openOGGSound(fp, &AudioFileSpec, &pOggAudio) != 0)
|
||||
if(openOGGSound(fp, &AudioFileSpec, AudioSpec.format, &pOggAudio) != 0)
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"Music Driver(): OGG file could not be opened: \"%s\". File is damaged or something is wrong with your soundcard!<br>", musicfile);
|
||||
return 1;
|
||||
@@ -50,7 +50,8 @@ int CMusic::load(SDL_AudioSpec AudioSpec, char *musicfile)
|
||||
g_pLogFile->ftextOut("Music Driver(): File \"%s\" opened successfully!<br>", musicfile);
|
||||
|
||||
int ret;
|
||||
ret = SDL_BuildAudioCVT(&Audio_cvt,
|
||||
|
||||
ret = SDL_BuildAudioCVT(&Audio_cvt,
|
||||
AudioFileSpec.format, AudioFileSpec.channels, AudioFileSpec.freq,
|
||||
AudioSpec.format, AudioSpec.channels, AudioSpec.freq);
|
||||
|
||||
@@ -65,8 +66,7 @@ int CMusic::load(SDL_AudioSpec AudioSpec, char *musicfile)
|
||||
}
|
||||
|
||||
music_len = pOggAudio.sound_len;
|
||||
|
||||
Audio_cvt.buf = (Uint8*) malloc(music_len * Audio_cvt.len_mult * sizeof(Uint8));
|
||||
Audio_cvt.buf = (Uint8*) malloc(music_len * (Audio_cvt.len_mult) * sizeof(Uint8));
|
||||
Audio_cvt.len = music_len;
|
||||
memcpy(Audio_cvt.buf, pOggAudio.sound_buffer, music_len*sizeof(Uint8));
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ short HQSndDrv_Load(SDL_AudioSpec *AudioSpec, stHQSound *psound, const char *sou
|
||||
if((fp = fopen(buf,"rb")) != NULL)
|
||||
{
|
||||
#ifdef BUILD_WITH_OGG
|
||||
if(openOGGSound(fp, &AudioFileSpec, psound) != 0)
|
||||
if(openOGGSound(fp, &AudioFileSpec, AudioSpec->format, psound) != 0)
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"OGG file could not be opened: \"%s\". The file was detected, but appears to be damaged. Trying to load the classical sound<br>", soundfile);
|
||||
return 1;
|
||||
|
||||
@@ -10,3 +10,5 @@ void addmaptile(unsigned int t);
|
||||
void addenemytile(unsigned int t, stCloneKeenPlus *pCKP);
|
||||
short checkConsistencyofGameData(stGameData *p_GameData);
|
||||
void formatPathString(char *output, const char *path);
|
||||
bool renameFilenamesLowerCase(const char *dir_name);
|
||||
void assignChangeTileAttribute(stTile *tile, int episode);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* lzexe.h
|
||||
*
|
||||
* Created on: 24.01.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int get_bit(int *p_bit_count, FILE **fin); /* only used for the conversion of sounds from episode 2 and 3 by sound_extraction_of_exe_files */
|
||||
|
||||
int unlzexe(FILE *fin, unsigned char *outbuffer);
|
||||
|
||||
int getEXEVersion(int episode, int bufsize);
|
||||
@@ -16,7 +16,7 @@ void gamepdo_walkinganim(int cp, stCloneKeenPlus *pCKP);
|
||||
void gamepdo_walking(int cp, stCloneKeenPlus *pCKP);
|
||||
void gamepdo_playpushed(int cp, stCloneKeenPlus *pCKP);
|
||||
void gamepdo_JumpAndPogo(int cp, stCloneKeenPlus *pCKP);
|
||||
void gamepdo_Jump(int cp, stCloneKeenPlus *pCKP);
|
||||
void gamepdo_Jump(int cp);
|
||||
//void gamepdo_falling(int cp, stCommand command[MAX_COMMANDS]);
|
||||
void gamepdo_raygun(int cp, stCloneKeenPlus *pCKP);
|
||||
void gamepdo_special(int cp, stCloneKeenPlus *pCKP);
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
|
||||
#ifdef BUILD_WITH_OGG
|
||||
|
||||
short openOGGSound(FILE *fp, SDL_AudioSpec *pspec, stHQSound *psound);
|
||||
short openOGGSound(FILE *fp, SDL_AudioSpec *pspec, Uint16 format, stHQSound *psound);
|
||||
|
||||
#endif
|
||||
|
||||
13
src/keen.h
13
src/keen.h
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "vorticon/sounds.h"
|
||||
#include "funcdefs.h"
|
||||
#include "CLatch.h"
|
||||
#include "fileio/CTileLoader.h"
|
||||
|
||||
#include "include/playeraction.h"
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
|
||||
#define WM_MAP_NUM 80
|
||||
|
||||
#define MAX_TILES 700
|
||||
#define MAX_SPRITES 300
|
||||
#define MAX_FONT 256
|
||||
#define MAX_BITMAPS 20
|
||||
@@ -110,13 +109,6 @@ typedef struct stMap
|
||||
unsigned int objectlayer[256][256];
|
||||
char firsttime; // used when generating multiplayer positions on world map
|
||||
} stMap;
|
||||
typedef struct stTile
|
||||
{
|
||||
int masktile; // if nonzero, specifies a mask for this tile
|
||||
int chgtile; // tile to change to when level completed (for wm)
|
||||
// or tile to change to when picked up (in-level)
|
||||
unsigned int animOffset; // starting offset from the base frame
|
||||
} stTile;
|
||||
|
||||
|
||||
// Tile information planes
|
||||
@@ -134,6 +126,7 @@ typedef struct stBitmap
|
||||
unsigned char *bmptr;
|
||||
char name[9];
|
||||
} stBitmap;
|
||||
|
||||
typedef struct stSprite
|
||||
{
|
||||
char xsize, ysize;
|
||||
@@ -712,7 +705,7 @@ typedef struct stPlayer
|
||||
int psupportingtile, psupportingobject, lastsupportingobject;
|
||||
char psliding;
|
||||
char psemisliding;
|
||||
char ppogostick;
|
||||
bool ppogostick;
|
||||
int pfrozentime,pfrozenframe,pfrozenanimtimer;
|
||||
|
||||
unsigned char keytable[50];
|
||||
|
||||
@@ -6,7 +6,7 @@ extern stMap map;
|
||||
extern unsigned int AnimTileInUse[ATILEINUSE_SIZEX][ATILEINUSE_SIZEY];
|
||||
extern stTile tiles[MAX_TILES+1];
|
||||
extern unsigned char tiledata[MAX_TILES+1][16][16];
|
||||
extern stSprite sprites[MAX_SPRITES+1];
|
||||
extern stSprite *sprites;
|
||||
extern stBitmap bitmaps[MAX_BITMAPS+1];
|
||||
extern stAnimTile animtiles[MAX_ANIMTILES+1];
|
||||
extern char font[MAX_FONT+1][8][8];
|
||||
@@ -68,17 +68,10 @@ extern int blockedby;
|
||||
extern int gunfiretimer, gunfirefreq;
|
||||
extern char cheatmode;
|
||||
|
||||
extern int numtiles;
|
||||
extern int **TileProperty; // This version will replace the old stTile Structure and save memory
|
||||
|
||||
extern short usedinfobox; // If statue was used...
|
||||
|
||||
|
||||
extern int NessieObjectHandle;
|
||||
extern int DemoObjectHandle;
|
||||
extern int BlankSprite;
|
||||
extern int DemoSprite;
|
||||
//extern EgaHead LatchHeader;
|
||||
|
||||
extern stShipQueue shipqueue[32];
|
||||
extern int ShipQueuePtr;
|
||||
|
||||
232
src/lz.cpp
232
src/lz.cpp
@@ -6,12 +6,10 @@
|
||||
#include "CLogFile.h"
|
||||
|
||||
#define LZ_STARTBITS 9
|
||||
#define LZ_MAXBITS 12
|
||||
#define LZ_ERRORCODE 256
|
||||
#define LZ_EOFCODE 257
|
||||
#define LZ_DICTSTARTCODE 258
|
||||
|
||||
#define LZ_MAXDICTSIZE ((1<<LZ_MAXBITS)+1)
|
||||
#define LZ_MAXSTRINGSIZE 72
|
||||
|
||||
unsigned char *lz_outbuffer;
|
||||
@@ -22,7 +20,7 @@ typedef struct stLZDictionaryEntry
|
||||
unsigned char string[LZ_MAXSTRINGSIZE];
|
||||
} stLZDictionaryEntry;
|
||||
|
||||
stLZDictionaryEntry *lzdict[LZ_MAXDICTSIZE];
|
||||
stLZDictionaryEntry **lzdict;
|
||||
|
||||
// reads a word of length numbits from file lzfile.
|
||||
unsigned int lz_readbits(FILE *lzfile, unsigned char numbits, unsigned char reset)
|
||||
@@ -66,6 +64,12 @@ void lz_outputdict(int entry)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*for(i=0;i<lzdict[entry].stringlen;i++)
|
||||
{
|
||||
*lz_outbuffer = lzdict[entry].string[i];
|
||||
lz_outbuffer++;
|
||||
}*/
|
||||
|
||||
for(i=0;i<lzdict[entry]->stringlen;i++)
|
||||
{
|
||||
*lz_outbuffer = lzdict[entry]->string[i];
|
||||
@@ -77,128 +81,142 @@ int i;
|
||||
// returns nonzero if an error occurs
|
||||
char lz_decompress(FILE *lzfile, unsigned char *outbuffer)
|
||||
{
|
||||
int i;
|
||||
int numbits;
|
||||
unsigned int dictindex, maxdictindex;
|
||||
unsigned int lzcode,lzcode_save,lastcode;
|
||||
char addtodict;
|
||||
unsigned int i;
|
||||
unsigned int numbits;
|
||||
unsigned int decsize;
|
||||
unsigned short maxdictcodewords;
|
||||
unsigned int maxdictsize;
|
||||
unsigned int dictindex, maxdictindex;
|
||||
unsigned int lzcode,lzcode_save,lastcode;
|
||||
char addtodict;
|
||||
|
||||
/* allocate memory for the LZ dictionary */
|
||||
for(i=0;i<LZ_MAXDICTSIZE;i++)
|
||||
{
|
||||
lzdict[i] = (stLZDictionaryEntry*) malloc(sizeof(stLZDictionaryEntry));
|
||||
if (!lzdict[i])
|
||||
{
|
||||
g_pLogFile->textOut("lz_decompress(): unable to allocate memory for dictionary!<br>");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// Get the decompressed file-size
|
||||
decsize = fgetc(lzfile);
|
||||
decsize += fgetc(lzfile) << 8;
|
||||
decsize += fgetc(lzfile) << 16;
|
||||
decsize += fgetc(lzfile) << 24;
|
||||
|
||||
/* initilize the dictionary */
|
||||
// Get the length of the maximum dictionary size
|
||||
|
||||
// entries 0-255 start with a single character corresponding
|
||||
// to their entry number
|
||||
for(i=0;i<256;i++)
|
||||
{
|
||||
lzdict[i]->stringlen = 1;
|
||||
lzdict[i]->string[0] = i;
|
||||
}
|
||||
// 256+ start undefined
|
||||
for(i=256;i<LZ_MAXDICTSIZE;i++)
|
||||
{
|
||||
lzdict[i]->stringlen = 0;
|
||||
}
|
||||
maxdictcodewords = fgetc(lzfile);
|
||||
maxdictcodewords += fgetc(lzfile) << 8;
|
||||
|
||||
// reset readbits
|
||||
lz_readbits(NULL, 0, 1);
|
||||
maxdictsize = ((1<<maxdictcodewords)+1);
|
||||
|
||||
// set starting # of bits-per-code
|
||||
numbits = LZ_STARTBITS;
|
||||
maxdictindex = (1 << numbits) - 1;
|
||||
lzdict = new stLZDictionaryEntry*[maxdictsize];
|
||||
// allocate memory for the LZ dictionary
|
||||
for(i=0;i<maxdictsize;i++)
|
||||
{
|
||||
//lzdict[i] = (stLZDictionaryEntry*) malloc(sizeof(stLZDictionaryEntry));
|
||||
lzdict[i] = new stLZDictionaryEntry;
|
||||
if (!lzdict[i])
|
||||
{
|
||||
g_pLogFile->textOut("lz_decompress(): unable to allocate memory for dictionary!<br>");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// point the global pointer to the buffer we were passed
|
||||
lz_outbuffer = outbuffer;
|
||||
/* initilize the dictionary */
|
||||
|
||||
// setup where to start adding strings to the dictionary
|
||||
dictindex = LZ_DICTSTARTCODE;
|
||||
addtodict = 1; // enable adding to dictionary
|
||||
// entries 0-255 start with a single character corresponding
|
||||
// to their entry number
|
||||
for(i=0;i<256;i++)
|
||||
{
|
||||
lzdict[i]->stringlen = 1;
|
||||
lzdict[i]->string[0] = i;
|
||||
}
|
||||
// 256+ start undefined
|
||||
for(i=256;i<maxdictsize;i++)
|
||||
{
|
||||
lzdict[i]->stringlen = 0;
|
||||
}
|
||||
|
||||
// read first code
|
||||
lastcode = lz_readbits(lzfile, numbits, 0);
|
||||
lz_outputdict(lastcode);
|
||||
do
|
||||
{
|
||||
// read the next code from the compressed data stream
|
||||
lzcode = lz_readbits(lzfile, numbits, 0);
|
||||
lzcode_save = lzcode;
|
||||
// reset readbits
|
||||
lz_readbits(NULL, 0, 1);
|
||||
|
||||
if (lzcode==LZ_ERRORCODE || lzcode==LZ_EOFCODE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// set starting # of bits-per-code
|
||||
numbits = LZ_STARTBITS;
|
||||
maxdictindex = (1 << numbits) - 1;
|
||||
|
||||
// if the code is present in the dictionary,
|
||||
// lookup and write the string for that code, then add the
|
||||
// last string + the first char of the just-looked-up string
|
||||
// to the dictionary at dictindex
|
||||
// point the global pointer to the buffer we were passed
|
||||
lz_outbuffer = outbuffer;
|
||||
|
||||
// if not in dict, add the last string + the first char of the
|
||||
// last string to the dictionary at dictindex (which will be equal
|
||||
// to lzcode), then lookup and write string lzcode.
|
||||
// setup where to start adding strings to the dictionary
|
||||
dictindex = LZ_DICTSTARTCODE;
|
||||
addtodict = 1; // enable adding to dictionary
|
||||
|
||||
if (lzdict[lzcode]->stringlen==0)
|
||||
{ // code is not present in dictionary
|
||||
lzcode = lastcode;
|
||||
}
|
||||
// read first code
|
||||
lastcode = lz_readbits(lzfile, numbits, 0);
|
||||
lz_outputdict(lastcode);
|
||||
do
|
||||
{
|
||||
// read the next code from the compressed data stream
|
||||
lzcode = lz_readbits(lzfile, numbits, 0);
|
||||
lzcode_save = lzcode;
|
||||
|
||||
if (addtodict) // room to add more entries to the dictionary?
|
||||
{
|
||||
// copies string lastcode to string dictindex, then
|
||||
// concatenates the first character of string lzcode.
|
||||
for(i=0;i<lzdict[lastcode]->stringlen;i++)
|
||||
{
|
||||
lzdict[dictindex]->string[i] = lzdict[lastcode]->string[i];
|
||||
}
|
||||
lzdict[dictindex]->string[i] = lzdict[lzcode]->string[0];
|
||||
lzdict[dictindex]->stringlen = (lzdict[lastcode]->stringlen + 1);
|
||||
if (lzcode==LZ_ERRORCODE || lzcode==LZ_EOFCODE)
|
||||
break;
|
||||
|
||||
// ensure we haven't overflowed the buffer
|
||||
if (lzdict[dictindex]->stringlen >= (LZ_MAXSTRINGSIZE-1))
|
||||
{
|
||||
g_pLogFile->ftextOut("lz_decompress(): lzdict[%d]->stringlen is too long...max length is %d<br>", dictindex, LZ_MAXSTRINGSIZE);
|
||||
return 1;
|
||||
}
|
||||
// if the code is present in the dictionary,
|
||||
// lookup and write the string for that code, then add the
|
||||
// last string + the first char of the just-looked-up string
|
||||
// to the dictionary at dictindex
|
||||
|
||||
dictindex++;
|
||||
if (dictindex >= maxdictindex)
|
||||
{ // no more entries can be specified with current code bit-width
|
||||
if (numbits < LZ_MAXBITS)
|
||||
{ // increase width of codes
|
||||
numbits++;
|
||||
maxdictindex = (1 << numbits) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reached maximum bit width, can't increase.
|
||||
// use the final entry (4095) before we shut off
|
||||
// adding items to the dictionary.
|
||||
if (dictindex>=(LZ_MAXDICTSIZE-1)) addtodict = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if not in dict, add the last string + the first char of the
|
||||
// last string to the dictionary at dictindex (which will be equal
|
||||
// to lzcode), then lookup and write string lzcode.
|
||||
|
||||
// write the string associated with the original code read.
|
||||
// if the code wasn't present, it now should have been added.
|
||||
lz_outputdict(lzcode_save);
|
||||
if (lzdict[lzcode]->stringlen==0)
|
||||
// code is not present in dictionary
|
||||
lzcode = lastcode;
|
||||
|
||||
lastcode = lzcode_save;
|
||||
} while(1);
|
||||
if (addtodict) // room to add more entries to the dictionary?
|
||||
{
|
||||
// copies string lastcode to string dictindex, then
|
||||
// concatenates the first character of string lzcode.
|
||||
for(i=0 ; i< (unsigned int) lzdict[lastcode]->stringlen ; i++)
|
||||
lzdict[dictindex]->string[i] = lzdict[lastcode]->string[i];
|
||||
|
||||
/* free the memory used by the LZ dictionary */
|
||||
for(i=0;i<LZ_MAXDICTSIZE;i++)
|
||||
{
|
||||
free(lzdict[i]);
|
||||
}
|
||||
lzdict[dictindex]->string[i] = lzdict[lzcode]->string[0];
|
||||
lzdict[dictindex]->stringlen = (lzdict[lastcode]->stringlen + 1);
|
||||
|
||||
// ensure we haven't overflowed the buffer
|
||||
if (lzdict[dictindex]->stringlen >= (LZ_MAXSTRINGSIZE-1))
|
||||
{
|
||||
g_pLogFile->ftextOut("lz_decompress(): lzdict[%d]->stringlen is too long...max length is %d<br>", dictindex, LZ_MAXSTRINGSIZE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dictindex++;
|
||||
if (dictindex >= maxdictindex)
|
||||
{ // no more entries can be specified with current code bit-width
|
||||
if (numbits < maxdictcodewords)
|
||||
{ // increase width of codes
|
||||
numbits++;
|
||||
maxdictindex = (1 << numbits) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reached maximum bit width, can't increase.
|
||||
// use the final entry (4095) before we shut off
|
||||
// adding items to the dictionary.
|
||||
if (dictindex>=(maxdictsize-1)) addtodict = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write the string associated with the original code read.
|
||||
// if the code wasn't present, it now should have been added.
|
||||
lz_outputdict(lzcode_save);
|
||||
|
||||
lastcode = lzcode_save;
|
||||
} while(1);
|
||||
|
||||
/* free the memory used by the LZ dictionary */
|
||||
for(i=0;i<maxdictsize;i++)
|
||||
delete lzdict[i];
|
||||
|
||||
delete [] lzdict;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
5
src/lz.h
5
src/lz.h
@@ -1,2 +1,3 @@
|
||||
long lz_decompress( FILE *fin, char *pout );
|
||||
long lz_compress( FILE *inf, FILE *outf );
|
||||
//long lz_decompress( FILE *fin, char *pout );
|
||||
char lz_decompress(FILE *lzfile, unsigned char *outbuffer);
|
||||
//long lz_compress( FILE *inf, FILE *outf );
|
||||
|
||||
28
src/main.cpp
28
src/main.cpp
@@ -7,10 +7,6 @@
|
||||
the original author, Caitlin Shaw and to the new author
|
||||
Gerstrong.
|
||||
|
||||
Please go ahead and port this game to other platforms.
|
||||
I would love to see it on Linux, Mac, or CE but I do
|
||||
not have the platforms/knowledge to port to these platforms.
|
||||
|
||||
If you make any changes or improvements to the code that
|
||||
you feel merit inclusion in the source tree email them
|
||||
to me at gerstrong@gmail.com or get my latest email
|
||||
@@ -19,15 +15,16 @@
|
||||
Thanks to ID Software for the "Commander Keen: Invasion of
|
||||
the Vorticons" games. "Commander Keen" and it's associated
|
||||
graphics, level, and sound files are the property of ID
|
||||
Software. CloneKeen requires the original version of a
|
||||
Software. Commander Genius requires the original version of a
|
||||
Commander Keen game in order to be able to emulate that
|
||||
episode.
|
||||
|
||||
Enjoy the Code
|
||||
-Caitlin and Gerstrong
|
||||
- The Commander Genius Team
|
||||
|
||||
CloneKeen 2003-2005 Caitlin Shaw
|
||||
CloneKeenPlus 2008-2009 Gerstrong
|
||||
CloneKeen 2003-2005 Caitlin Shaw
|
||||
CloneKeenPlus 2008-2009 Gerstrong
|
||||
Commander Genius 2009 Tulip, Pickle and DaVince
|
||||
*/
|
||||
|
||||
#include "keen.h"
|
||||
@@ -96,8 +93,10 @@ stFade fade;
|
||||
stMap map;
|
||||
unsigned int AnimTileInUse[ATILEINUSE_SIZEX][ATILEINUSE_SIZEY];
|
||||
stTile tiles[MAX_TILES+1];
|
||||
int numtiles;
|
||||
int **TileProperty; // This version will replace the old stTile Structure and save memory
|
||||
unsigned char tiledata[MAX_TILES+1][16][16];
|
||||
stSprite sprites[MAX_SPRITES+1];
|
||||
stSprite *sprites;
|
||||
stBitmap bitmaps[MAX_BITMAPS+1];
|
||||
stObject objects[MAX_OBJECTS+1];
|
||||
char font[MAX_FONT+1][8][8];
|
||||
@@ -302,8 +301,6 @@ void playgame_levelmanager(stCloneKeenPlus *pCKP)
|
||||
p_levelcontrol->success = 0;
|
||||
map.firsttime = 1;
|
||||
|
||||
usedinfobox = 0;
|
||||
|
||||
do
|
||||
{
|
||||
initgame(pCKP);
|
||||
@@ -382,6 +379,7 @@ void playgame_levelmanager(stCloneKeenPlus *pCKP)
|
||||
// Now load HQ Stuff, because the game could have been loaded too.
|
||||
g_pGraphics->loadHQGraphics(p_levelcontrol->episode,p_levelcontrol->chglevelto,pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory);
|
||||
|
||||
g_pInput->flushAll();
|
||||
|
||||
if (wm)
|
||||
{ // entering map from normal level, or first time around
|
||||
@@ -654,14 +652,6 @@ short readCommandLine(int argc, char *argv[], stCloneKeenPlus *pCKP)
|
||||
{
|
||||
g_pVideoDriver->setZoom(2);
|
||||
}
|
||||
else if (strcmp(tempbuf, "-acc")==0) // Hardware Acceleration
|
||||
{
|
||||
//pCKP->Device.Display.Mode = VIDEO_MODE_SOFTWARE;
|
||||
}
|
||||
else if (strcmp(tempbuf, "-ogl")==0) // Early OpenGL Support
|
||||
{
|
||||
//pCKP->Device.Display.Mode = VIDEO_MODE_OPENGL;
|
||||
}
|
||||
else if (strcmp(tempbuf, "-stereo")==0) // Enable Stereo Sound
|
||||
{
|
||||
g_pSound->setSoundmode(0,true);
|
||||
|
||||
22
src/map.cpp
22
src/map.cpp
@@ -223,13 +223,10 @@ int y;
|
||||
// changes the tile at (x,y) in real time
|
||||
void map_chgtile(unsigned int x, unsigned int y, int newtile)
|
||||
{
|
||||
/*char buf[80];*/
|
||||
map.mapdata[x][y] = newtile;
|
||||
|
||||
if (x>=mapx && y>=mapy && x<mapx+64 && y<mapy+64)
|
||||
{
|
||||
g_pGraphics->drawTile(((mapxstripepos+((x-mapx)<<4))&511), ((mapystripepos+((y-mapy)<<4))&511), newtile);
|
||||
}
|
||||
}
|
||||
|
||||
// searches for animated tiles at the map position (X,Y) and
|
||||
@@ -242,6 +239,8 @@ int i;
|
||||
px = ((mapxstripepos+((x-mapx)<<4))&511);
|
||||
py = ((mapystripepos+((y-mapy)<<4))&511);
|
||||
|
||||
TileProperty[map.mapdata[x][y]][ANIMATION] = 1;
|
||||
|
||||
// find it!
|
||||
for(i=1;i<MAX_ANIMTILES-1;i++)
|
||||
{
|
||||
@@ -294,21 +293,22 @@ int c, i;
|
||||
px = ((mapxstripepos+((x-mapx)<<4))&511);
|
||||
py = ((mapystripepos+((y-mapy)<<4))&511);
|
||||
c = map.mapdata[x][y];
|
||||
//if (tiles[c].isAnimated)
|
||||
if ( TileProperty[c][ANIMATION] > 1 )
|
||||
if ( TileProperty[c][ANIMATION] == 1 ) // In case the tile mustn't be animated
|
||||
{
|
||||
/*crashflag = 1;
|
||||
crashflag2 = x;
|
||||
crashflag3 = y;
|
||||
why_term_ptr = "map_animate(): you told me to animate x/y=crashflag1/2 but that tile isn't supposed to be animated!";*/
|
||||
crashflag = x;
|
||||
crashflag2 = y;
|
||||
why_term_ptr = "sorry, but tile at x/y=crashflag1/2 isn't supposed to be animated!";
|
||||
crashflag = 0;
|
||||
crashflag2 = 0;
|
||||
// TODO: Try to remove the crashflags. They really mess up the system!
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// don't reanimate a tile that's already registered--then we'd
|
||||
// have multiple entries for it in animtiles[] (that's not good).
|
||||
if (AnimTileInUse[px>>4][py>>4])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// find an unused slot in animtiles
|
||||
for(i=1;i<MAX_ANIMTILES-1;i++)
|
||||
|
||||
50
src/menu.cpp
50
src/menu.cpp
@@ -128,7 +128,8 @@ short loadResourcesforStartMenu(stCloneKeenPlus *pCKP, CGame *Game)
|
||||
pCKP->Control.levelcontrol.episode = pCKP->GameData[pCKP->Resources.GameSelected-1].Episode;
|
||||
|
||||
//if (latch_loadgraphics(pCKP->Control.levelcontrol.episode, pCKP->GameData[0].DataDirectory)) return abortCKP(pCKP);
|
||||
if (Game->getLatch()->loadGraphics(pCKP->Control.levelcontrol.episode, pCKP->GameData[0].DataDirectory)) return abortCKP(pCKP);
|
||||
//if (Game->getLatch()->loadGraphics(pCKP->Control.levelcontrol.episode, pCKP->GameData[0].DataDirectory)) return abortCKP(pCKP);
|
||||
Game->loadResources(pCKP->Control.levelcontrol.episode, pCKP->GameData[0].DataDirectory);
|
||||
|
||||
player[0].x = player[0].y = 0;
|
||||
if(initgamefirsttime(pCKP, 0) != 0)
|
||||
@@ -563,7 +564,7 @@ void OptionsDlg(stCloneKeenPlus *pCKP)
|
||||
|
||||
// Prepare the Games Menu
|
||||
OptionsMenu = new CDialog();
|
||||
OptionsMenu->setDimensions(4,4,32,11);
|
||||
OptionsMenu->setDimensions(3,3,34,12);
|
||||
|
||||
for( i = 0 ; i < NUM_OPTIONS ; i++ )
|
||||
{
|
||||
@@ -773,35 +774,10 @@ short GraphicsDlg(stCloneKeenPlus *pCKP)
|
||||
if(selection == 0)
|
||||
{
|
||||
// Now the part of the resolution list
|
||||
switch(width)
|
||||
{
|
||||
case 320:
|
||||
width = 640;
|
||||
height = 480;
|
||||
break;
|
||||
case 640:
|
||||
width = 800;
|
||||
height = 600;
|
||||
break;
|
||||
case 800:
|
||||
width = 1024;
|
||||
height = 768;
|
||||
break;
|
||||
case 1024:
|
||||
width = 1280;
|
||||
height = 1024;
|
||||
break;
|
||||
case 1280:
|
||||
width = 1680;
|
||||
height = 1050;
|
||||
break;
|
||||
default:
|
||||
width = 320;
|
||||
height = 240;
|
||||
break;
|
||||
}
|
||||
st_resolution Resolution;
|
||||
Resolution = g_pVideoDriver->setNextResolution();
|
||||
|
||||
sprintf(buf,"Resolution: %dx%dx%d",width,height,depth);
|
||||
sprintf(buf,"Resolution: %dx%dx%d", Resolution.width, Resolution.height, Resolution.depth);
|
||||
DisplayMenu->setOptionText(selection,buf);
|
||||
}
|
||||
else if(selection == 1)
|
||||
@@ -878,7 +854,7 @@ short GraphicsDlg(stCloneKeenPlus *pCKP)
|
||||
}
|
||||
else if(selection == 6)
|
||||
{
|
||||
if(autoframeskip < 70 && autoframeskip >= 0)
|
||||
if(autoframeskip < 70)
|
||||
{
|
||||
autoframeskip += 10;
|
||||
sprintf(buf,"Auto-Frameskip : %d fps", autoframeskip);
|
||||
@@ -912,23 +888,23 @@ short GraphicsDlg(stCloneKeenPlus *pCKP)
|
||||
|
||||
g_pVideoDriver->enableOpenGL(opengl);
|
||||
g_pVideoDriver->setOGLFilter(gl_filter);
|
||||
g_pVideoDriver->setMode(width,height,depth);
|
||||
g_pVideoDriver->setZoom(zoom);
|
||||
g_pVideoDriver->setFilter(filter);
|
||||
g_pVideoDriver->setFrameskip(frameskip);
|
||||
g_pVideoDriver->setTargetFPS(autoframeskip);
|
||||
g_pVideoDriver->setAspectCorrection(aspect);
|
||||
|
||||
CSettings *Settings;
|
||||
Settings = new CSettings();
|
||||
Settings->saveDrvCfg();
|
||||
delete Settings; Settings = NULL;
|
||||
|
||||
// initialize/activate all drivers
|
||||
g_pLogFile->ftextOut("Restarting graphics driver... (Menu)<br>");
|
||||
if (g_pVideoDriver->start())
|
||||
retval = 1;
|
||||
|
||||
CSettings *Settings;
|
||||
Settings = new CSettings();
|
||||
|
||||
Settings->saveDrvCfg();
|
||||
delete Settings; Settings = NULL;
|
||||
|
||||
showmapatpos(90, MAINMENU_X, MENUS_Y, 0, pCKP);
|
||||
|
||||
fade.mode = FADE_GO;
|
||||
|
||||
218
src/misc.cpp
218
src/misc.cpp
@@ -39,7 +39,7 @@ char buf[80];
|
||||
printf("%s", buf);
|
||||
printf(" (%d bit)", static_cast<int> (sizeof(int*)*8));
|
||||
|
||||
printf("\nby Caitlin Shaw, 2003-2005\nand Gerstrong 2008-2009\n");
|
||||
printf("\nby The CloneKeenPlus Team 2009\n");
|
||||
printf("\n");
|
||||
printf("BY A FAN, FOR FANS. ALL \"COMMANDER KEEN\" GRAPHICS,\n");
|
||||
printf("SOUND, AND LEVEL FILES ARE THE PROPERTY OF ID SOFTWARE.\n");
|
||||
@@ -165,11 +165,6 @@ int i;
|
||||
if(map.mapdata[mpx][mpy] >= 435 && map.mapdata[mpx][mpy] <= 438)
|
||||
isgarg = true;
|
||||
|
||||
for(i=0; i < 4 ; i++)
|
||||
{
|
||||
player[0].playcontrol[PA_JUMP+i] = 0;
|
||||
}
|
||||
|
||||
if (!isgarg)
|
||||
{
|
||||
if(!map_isanimated(mpx, mpy))
|
||||
@@ -181,10 +176,12 @@ int i;
|
||||
return;
|
||||
}
|
||||
|
||||
#define TWIRL_SPEED 50
|
||||
for(i=0; i < 4 ; i++)
|
||||
{
|
||||
player[0].playcontrol[PA_JUMP+i] = 0;
|
||||
}
|
||||
|
||||
|
||||
//sound_pause();
|
||||
const int twirl_speed = 100;
|
||||
|
||||
// get the name of the string we need to display
|
||||
sprintf(strname, "EP1_YSIYM_LVL%d", pCKP->Control.levelcontrol.curlevel);
|
||||
@@ -200,14 +197,11 @@ int i;
|
||||
g_pGraphics->drawFont((unsigned char*) getstring(strname), (dlgX+1)<<3, (dlgY+1)<<3,0);
|
||||
|
||||
twirlframe = 0;
|
||||
twirltimer = TWIRL_SPEED+1;
|
||||
twirltimer = twirl_speed+1;
|
||||
// wait for enter
|
||||
do
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (twirltimer>TWIRL_SPEED)
|
||||
if (twirltimer>twirl_speed)
|
||||
{
|
||||
g_pGraphics->drawCharacter((dlgX+twirlX)<<3, (dlgY+twirlY)<<3, 9+twirlframe);
|
||||
g_pVideoDriver->update_screen();
|
||||
@@ -232,27 +226,19 @@ int i;
|
||||
map_chgtile(mpx, mpy, 434);
|
||||
map_deanimate(mpx, mpy);
|
||||
}
|
||||
|
||||
//sound_resume();
|
||||
|
||||
}
|
||||
|
||||
void VorticonElder(int mpx, int mpy, stCloneKeenPlus *pCKP)
|
||||
{
|
||||
int twirlframe, twirltimer;
|
||||
int dlgX,dlgY,dlgW,dlgH,twirlX,twirlY;
|
||||
const char *strName;
|
||||
int twirlframe, twirltimer;
|
||||
int dlgX,dlgY,dlgW,dlgH,twirlX,twirlY;
|
||||
const char *strName;
|
||||
const int twirl_speed = 100;
|
||||
|
||||
int i;
|
||||
for(i=0; i < 4 ; i++)
|
||||
{
|
||||
player[0].playcontrol[PA_JUMP+i] = 0;
|
||||
}
|
||||
|
||||
#define TWIRL_SPEED 50
|
||||
|
||||
if(usedinfobox == 1)
|
||||
return;
|
||||
for(int i=0; i < 4 ; i++)
|
||||
{
|
||||
player[0].playcontrol[PA_JUMP+i] = 0;
|
||||
}
|
||||
|
||||
g_pSound->pauseSound();
|
||||
|
||||
@@ -282,11 +268,11 @@ for(i=0; i < 4 ; i++)
|
||||
g_pGraphics->drawFont( (unsigned char*) getstring(strName), (dlgX+1)<<3, (dlgY+1)<<3,0);
|
||||
|
||||
twirlframe = 0;
|
||||
twirltimer = TWIRL_SPEED+1;
|
||||
twirltimer = twirl_speed+1;
|
||||
// wait for enter
|
||||
do
|
||||
{
|
||||
if (twirltimer>TWIRL_SPEED)
|
||||
if (twirltimer>twirl_speed)
|
||||
{
|
||||
g_pGraphics->drawCharacter((dlgX+twirlX)<<3, (dlgY+twirlY)<<3, 9+twirlframe);
|
||||
g_pVideoDriver->update_screen();
|
||||
@@ -297,17 +283,14 @@ for(i=0; i < 4 ; i++)
|
||||
g_pInput->pollEvents();
|
||||
g_pTimer->SpeedThrottle();
|
||||
g_pVideoDriver->update_screen();
|
||||
} while(!g_pInput->getPressedKey(KENTER) /*&& !immediate_keytable[KQUIT] && !getanyevent(pCKP)*/);
|
||||
} while(!g_pInput->getPressedKey(KENTER) );
|
||||
|
||||
// make the switch stop glowing
|
||||
map_chgtile(mpx, mpy+1, 432);
|
||||
|
||||
//tiles[432].isAnimated = 0;
|
||||
map_deanimate(mpx, mpy+1);
|
||||
|
||||
g_pSound->resumeSounds();
|
||||
|
||||
usedinfobox = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -335,10 +318,47 @@ int dlgX,dlgY,dlgW,dlgH;
|
||||
// pogo
|
||||
if (player[p].inventory.HasPogo) g_pGraphics->drawTile_direct(((dlgX+12)<<3)+4, ((dlgY+9)<<3)+3, 415);
|
||||
// cards
|
||||
if (player[p].inventory.HasCardYellow) g_pGraphics->drawTile_direct((dlgX+21)<<3, ((dlgY+8)<<3)+3, 424);
|
||||
if (player[p].inventory.HasCardRed) g_pGraphics->drawTile_direct((dlgX+25)<<3, ((dlgY+8)<<3)+3, 425);
|
||||
if (player[p].inventory.HasCardGreen) g_pGraphics->drawTile_direct((dlgX+21)<<3, ((dlgY+10)<<3)+4, 426);
|
||||
if (player[p].inventory.HasCardBlue) g_pGraphics->drawTile_direct((dlgX+25)<<3, ((dlgY+10)<<3)+4, 427);
|
||||
if (player[p].inventory.HasCardYellow)
|
||||
{
|
||||
g_pGraphics->drawTile_direct((dlgX+21)<<3, ((dlgY+8)<<3)+3, 424);
|
||||
if(player[p].inventory.HasCardYellow > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardYellow);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+20)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardRed)
|
||||
{
|
||||
g_pGraphics->drawTile_direct((dlgX+25)<<3, ((dlgY+8)<<3)+3, 425);
|
||||
if(player[p].inventory.HasCardRed > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardRed);
|
||||
g_pGraphics->drawFont((unsigned char*) buf,(dlgX+24)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardGreen)
|
||||
{
|
||||
g_pGraphics->drawTile_direct((dlgX+21)<<3, ((dlgY+10)<<3)+4, 426);
|
||||
|
||||
if (player[p].inventory.HasCardGreen > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardGreen);
|
||||
g_pGraphics->drawFont((unsigned char*) buf,(dlgX+20)<<3,((dlgY+10)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardBlue)
|
||||
{
|
||||
g_pGraphics->drawTile_direct((dlgX+25)<<3, ((dlgY+10)<<3)+4, 427);
|
||||
if(player[p].inventory.HasCardBlue > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardBlue);
|
||||
g_pGraphics->drawFont((unsigned char*) buf,(dlgX+24)<<3,((dlgY+10)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
// ship parts
|
||||
if (player[p].inventory.HasJoystick) t=448; else t=321;
|
||||
g_pGraphics->drawTile_direct((dlgX+18)<<3, ((dlgY+4)<<3)+3, t);
|
||||
@@ -392,10 +412,46 @@ int dlgX,dlgY,dlgW,dlgH;
|
||||
g_pGraphics->drawFont( (unsigned char*) getstring("EP2_StatusBox"), (dlgX+1)<<3, (dlgY+1)<<3, 0);
|
||||
|
||||
// cards
|
||||
if (player[p].inventory.HasCardYellow) g_pGraphics->drawTile_direct(((dlgX+21)<<3)-4, ((dlgY+8)<<3)+3, 424);
|
||||
if (player[p].inventory.HasCardRed) g_pGraphics->drawTile_direct(((dlgX+25)<<3)-4, ((dlgY+8)<<3)+3, 425);
|
||||
if (player[p].inventory.HasCardGreen) g_pGraphics->drawTile_direct(((dlgX+21)<<3)-4, ((dlgY+10)<<3)+4, 426);
|
||||
if (player[p].inventory.HasCardBlue) g_pGraphics->drawTile_direct(((dlgX+25)<<3)-4, ((dlgY+10)<<3)+4, 427);
|
||||
if (player[p].inventory.HasCardYellow)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+21)<<3)-4, ((dlgY+8)<<3)+3, 424);
|
||||
if(player[p].inventory.HasCardYellow > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardYellow);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+20)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardRed)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+25)<<3)-4, ((dlgY+8)<<3)+3, 425);
|
||||
if(player[p].inventory.HasCardRed > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardRed);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+24)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardGreen)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+21)<<3)-4, ((dlgY+10)<<3)+4, 426);
|
||||
if(player[p].inventory.HasCardGreen > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardGreen);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+20)<<3,((dlgY+10)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardBlue)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+25)<<3)-4, ((dlgY+10)<<3)+4, 427);
|
||||
if(player[p].inventory.HasCardBlue > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardBlue);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+24)<<3,((dlgY+10)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
// cities saved
|
||||
if (p_levelcontrol->levels_completed[4]) g_pGraphics->drawFont( (unsigned char*) getstring("EP2_LVL4_TargetName"), (dlgX+1)<<3, (dlgY+8)<<3, 0);
|
||||
if (p_levelcontrol->levels_completed[6]) g_pGraphics->drawFont( (unsigned char*) getstring("EP2_LVL6_TargetName"), (dlgX+8)<<3, (dlgY+8)<<3, 0);
|
||||
@@ -468,10 +524,46 @@ int dlgX,dlgY,dlgW,dlgH;
|
||||
g_pGraphics->drawFont( (unsigned char*) tempbuf, (dlgX+26)<<3, ((dlgY+5)<<3)-1, 0);
|
||||
|
||||
// cards
|
||||
if (player[p].inventory.HasCardYellow) g_pGraphics->drawTile_direct(((dlgX+14)<<3)+4, ((dlgY+8)<<3)+4, 217);
|
||||
if (player[p].inventory.HasCardRed) g_pGraphics->drawTile_direct(((dlgX+18)<<3)+4, ((dlgY+8)<<3)+4, 218);
|
||||
if (player[p].inventory.HasCardGreen) g_pGraphics->drawTile_direct(((dlgX+22)<<3)+4, ((dlgY+8)<<3)+4, 219);
|
||||
if (player[p].inventory.HasCardBlue) g_pGraphics->drawTile_direct(((dlgX+26)<<3)+4, ((dlgY+8)<<3)+4, 220);
|
||||
if (player[p].inventory.HasCardYellow)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+14)<<3)+4, ((dlgY+8)<<3)+4, 217);
|
||||
if(player[p].inventory.HasCardYellow > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardYellow);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+13)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardRed)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+18)<<3)+4, ((dlgY+8)<<3)+4, 218);
|
||||
if(player[p].inventory.HasCardRed > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardRed);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+17)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardGreen)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+22)<<3)+4, ((dlgY+8)<<3)+4, 219);
|
||||
if(player[p].inventory.HasCardGreen > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardGreen);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+21)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
if (player[p].inventory.HasCardBlue)
|
||||
{
|
||||
g_pGraphics->drawTile_direct(((dlgX+26)<<3)+4, ((dlgY+8)<<3)+4, 220);
|
||||
if(player[p].inventory.HasCardBlue > 1)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",player[p].inventory.HasCardBlue);
|
||||
g_pGraphics->drawFont((unsigned char*)buf,(dlgX+25)<<3,((dlgY+8)<<3)+3,0);
|
||||
}
|
||||
}
|
||||
|
||||
// score
|
||||
i = player[p].inventory.score;
|
||||
@@ -565,7 +657,7 @@ int x,y;
|
||||
|
||||
void YourShipNeedsTheseParts(stCloneKeenPlus *pCKP)
|
||||
{
|
||||
int cp;
|
||||
int cp = 0;
|
||||
int dlgX,dlgY,dlgW,dlgH;
|
||||
|
||||
dlgX = GetStringAttribute("EP1_SHIP", "LEFT");
|
||||
@@ -573,8 +665,6 @@ int dlgX,dlgY,dlgW,dlgH;
|
||||
dlgW = GetStringAttribute("EP1_SHIP", "WIDTH");
|
||||
dlgH = GetStringAttribute("EP1_SHIP", "HEIGHT");
|
||||
|
||||
cp = 0; // Fixme
|
||||
|
||||
dialogbox(dlgX,dlgY,dlgW,dlgH);
|
||||
|
||||
g_pGraphics->drawFont( (unsigned char*) getstring("EP1_SHIP"), (dlgX+1)<<3, (dlgY+1)<<3,0);
|
||||
@@ -610,8 +700,7 @@ void ShipEp3(stCloneKeenPlus *pCKP)
|
||||
char strname[80];
|
||||
int twirlframe, twirltimer;
|
||||
int dlgX,dlgY,dlgW,dlgH,twirlX,twirlY;
|
||||
|
||||
g_pSound->pauseSound();
|
||||
const int twirlspeed = 100;
|
||||
|
||||
// display one of four random strings
|
||||
sprintf(strname, "EP3_SHIP%d", (rand()%4)+1);
|
||||
@@ -628,14 +717,15 @@ int dlgX,dlgY,dlgW,dlgH,twirlX,twirlY;
|
||||
|
||||
g_pVideoDriver->update_screen();
|
||||
|
||||
// wait for ctrl/space/enter released then pressed again then released
|
||||
g_pInput->flushAll();
|
||||
|
||||
twirlframe = 0;
|
||||
twirltimer = TWIRL_SPEED+1;
|
||||
twirltimer = twirlspeed+1;
|
||||
g_pInput->flushKeys();
|
||||
// wait for any key
|
||||
// wait for any command or key
|
||||
do
|
||||
{
|
||||
if (twirltimer>TWIRL_SPEED)
|
||||
if (twirltimer>twirlspeed)
|
||||
{
|
||||
g_pGraphics->drawCharacter((dlgX+twirlX)<<3, (dlgY+twirlY)<<3, twirlframe+9);
|
||||
g_pVideoDriver->update_screen();
|
||||
@@ -647,8 +737,6 @@ int dlgX,dlgY,dlgW,dlgH,twirlX,twirlY;
|
||||
g_pInput->pollEvents();
|
||||
g_pTimer->SpeedThrottle();
|
||||
} while(!g_pInput->getPressedAnyKey());
|
||||
|
||||
g_pSound->resumeSounds();
|
||||
}
|
||||
|
||||
void game_save(char *fname, stCloneKeenPlus *pCKP)
|
||||
@@ -1265,15 +1353,7 @@ void showTextMB(int lines, char **text, stCloneKeenPlus *pCKP)
|
||||
twirlframe = 0;
|
||||
twirltimer = TWIRL_SPEED+1;
|
||||
|
||||
while(g_pInput->getPressedKey(KENTER))
|
||||
{
|
||||
//poll_events(pCKP);
|
||||
|
||||
/*if (immediate_keytable[KQUIT])
|
||||
{
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
g_pInput->flushAll();
|
||||
|
||||
// wait for enter
|
||||
do
|
||||
@@ -1289,5 +1369,5 @@ void showTextMB(int lines, char **text, stCloneKeenPlus *pCKP)
|
||||
g_pInput->pollEvents();
|
||||
g_pTimer->SpeedThrottle();
|
||||
g_pVideoDriver->update_screen();
|
||||
} while(!g_pInput->getPressedKey(KENTER)/* && !immediate_keytable[KQUIT]*/);
|
||||
} while(!g_pInput->getPressedKey(KENTER));
|
||||
}
|
||||
|
||||
29
src/patch2
Normal file
29
src/patch2
Normal file
@@ -0,0 +1,29 @@
|
||||
Index: src/sdl/CVideoDriver.cpp
|
||||
===================================================================
|
||||
--- src/sdl/CVideoDriver.cpp (revision 30)
|
||||
+++ src/sdl/CVideoDriver.cpp (working copy)
|
||||
@@ -161,7 +161,9 @@
|
||||
Mode = SDL_HWPALETTE;
|
||||
|
||||
// Support for doublebuffering
|
||||
+#ifndef WIZ
|
||||
Mode |= SDL_DOUBLEBUF;
|
||||
+#endif
|
||||
|
||||
// Enable OpenGL
|
||||
#ifdef USE_OPENGL
|
||||
Index: src/sdl/CVideoDriver.h
|
||||
===================================================================
|
||||
--- src/sdl/CVideoDriver.h (revision 30)
|
||||
+++ src/sdl/CVideoDriver.h (working copy)
|
||||
@@ -69,9 +69,9 @@
|
||||
void setFrameskip(unsigned short value);
|
||||
void setFilter(short value);
|
||||
void setZoom(short vale);
|
||||
+ bool initOpenGL();
|
||||
#ifdef USE_OPENGL
|
||||
void enableOpenGL(bool value) { m_opengl = value; }
|
||||
- bool initOpenGL();
|
||||
void setOGLFilter(unsigned char value) { m_opengl_filter = (value==1) ? GL_LINEAR : GL_NEAREST ; }
|
||||
#else
|
||||
void enableOpenGL(bool value) { m_opengl = false; }
|
||||
29
src/patch20092006
Normal file
29
src/patch20092006
Normal file
@@ -0,0 +1,29 @@
|
||||
Index: src/sdl/CVideoDriver.cpp
|
||||
===================================================================
|
||||
--- src/sdl/CVideoDriver.cpp (revision 30)
|
||||
+++ src/sdl/CVideoDriver.cpp (working copy)
|
||||
@@ -161,7 +161,9 @@
|
||||
Mode = SDL_HWPALETTE;
|
||||
|
||||
// Support for doublebuffering
|
||||
+#ifndef WIZ
|
||||
Mode |= SDL_DOUBLEBUF;
|
||||
+#endif
|
||||
|
||||
// Enable OpenGL
|
||||
#ifdef USE_OPENGL
|
||||
Index: src/sdl/CVideoDriver.h
|
||||
===================================================================
|
||||
--- src/sdl/CVideoDriver.h (revision 30)
|
||||
+++ src/sdl/CVideoDriver.h (working copy)
|
||||
@@ -69,9 +69,9 @@
|
||||
void setFrameskip(unsigned short value);
|
||||
void setFilter(short value);
|
||||
void setZoom(short vale);
|
||||
+ bool initOpenGL();
|
||||
#ifdef USE_OPENGL
|
||||
void enableOpenGL(bool value) { m_opengl = value; }
|
||||
- bool initOpenGL();
|
||||
void setOGLFilter(unsigned char value) { m_opengl_filter = (value==1) ? GL_LINEAR : GL_NEAREST ; }
|
||||
#else
|
||||
void enableOpenGL(bool value) { m_opengl = false; }
|
||||
@@ -40,7 +40,6 @@ short CSettings::saveDrvCfg(void)
|
||||
else
|
||||
Parser.saveIntValue("OpenGL","Video",0);
|
||||
|
||||
|
||||
Parser.saveIntValue("width","Video",g_pVideoDriver->getWidth());
|
||||
Parser.saveIntValue("height","Video",g_pVideoDriver->getHeight());
|
||||
Parser.saveIntValue("scale","Video",g_pVideoDriver->getZoomValue());
|
||||
@@ -79,8 +78,7 @@ short CSettings::loadDrvCfg(void)
|
||||
if(depth*width*height < 0)
|
||||
g_pLogFile->ftextOut(RED,"Error reading the configuration file. It appears to be damaged!");
|
||||
|
||||
g_pVideoDriver->setMode(width, height, depth);
|
||||
|
||||
g_pVideoDriver->setMode(width,height,depth);
|
||||
g_pVideoDriver->setFrameskip(Parser.getIntValue("frameskip","Video"));
|
||||
|
||||
if((Parser.getIntValue("fullscreen","Video")) == 1)
|
||||
@@ -123,6 +121,7 @@ void CSettings::loadDefaultGameCfg(stOption *Option)
|
||||
setOption(Option,OPT_TWOBUTTON, "two-button-firing", 0);
|
||||
setOption(Option,OPT_KEYCARDSTACK, "keycard-stacking", 0);
|
||||
setOption(Option,OPT_ANALOGJOYSTICK, "analog-joystick", 1);
|
||||
setOption(Option,OPT_LVLREPLAYABILITY, "level replayability", 0);
|
||||
}
|
||||
|
||||
short CSettings::loadGameCfg(stOption *Option)
|
||||
|
||||
@@ -8,15 +8,13 @@
|
||||
#ifndef CSETTINGS_H_
|
||||
#define CSETTINGS_H_
|
||||
|
||||
#define OPT_FULLYAUTOMATIC 0
|
||||
#define OPT_SUPERPOGO 1
|
||||
#define OPT_ALLOWPKING 2
|
||||
#define OPT_CHEATS 3
|
||||
#define OPT_TWOBUTTON 4
|
||||
#define OPT_KEYCARDSTACK 5
|
||||
#define OPT_ANALOGJOYSTICK 6
|
||||
enum e_OptionKeywords
|
||||
{ OPT_FULLYAUTOMATIC, OPT_SUPERPOGO,
|
||||
OPT_ALLOWPKING, OPT_CHEATS,
|
||||
OPT_TWOBUTTON, OPT_KEYCARDSTACK,
|
||||
OPT_ANALOGJOYSTICK, OPT_LVLREPLAYABILITY };
|
||||
|
||||
#define NUM_OPTIONS 7
|
||||
#define NUM_OPTIONS 8
|
||||
|
||||
typedef struct stOption
|
||||
{
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include "../scale2x/scalebit.h"
|
||||
#include "../CLogFile.h"
|
||||
#include "../CGraphics.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
#define CKLOGFILENAME "genius.log"
|
||||
|
||||
@@ -48,9 +51,9 @@ CVideoDriver::CVideoDriver() {
|
||||
|
||||
showfps=true;
|
||||
#ifdef WIZ
|
||||
Width=320;
|
||||
Height=240;
|
||||
Depth=16;
|
||||
m_Resolution.width=320;
|
||||
m_Resolution.height=240;
|
||||
m_Resolution.depth=16;
|
||||
Mode=0;
|
||||
Fullscreen=true;
|
||||
Filtermode=0;
|
||||
@@ -58,9 +61,9 @@ CVideoDriver::CVideoDriver() {
|
||||
FrameSkip=0;
|
||||
m_targetfps = 30; // Enable automatic frameskipping by default at 30
|
||||
#else
|
||||
Width=640;
|
||||
Height=480;
|
||||
Depth=0;
|
||||
m_Resolution.width=640;
|
||||
m_Resolution.height=480;
|
||||
m_Resolution.depth=0;
|
||||
Mode=0;
|
||||
Fullscreen=false;
|
||||
Filtermode=1;
|
||||
@@ -84,12 +87,79 @@ CVideoDriver::CVideoDriver() {
|
||||
FGLayerSurface=NULL; // Scroll buffer for Messages
|
||||
BGLayerSurface=NULL;
|
||||
BlitSurface=NULL;
|
||||
|
||||
m_Resolution_pos = m_Resolutionlist.begin();
|
||||
|
||||
initResolutionList();
|
||||
}
|
||||
|
||||
CVideoDriver::~CVideoDriver() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void CVideoDriver::initResolutionList()
|
||||
{
|
||||
st_resolution resolution;
|
||||
char buf[256];
|
||||
|
||||
ifstream ResolutionFile("resolutions.cfg");
|
||||
if(!ResolutionFile)
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"Warning: resolutions.cfg could not be read! Maybe your files weren't extracted correctly!<br>");
|
||||
|
||||
resolution.width = 320;
|
||||
resolution.height = 240;
|
||||
resolution.depth = 16;
|
||||
m_Resolutionlist.push_back(resolution);
|
||||
|
||||
resolution.depth = 32;
|
||||
m_Resolutionlist.push_back(resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
while(!ResolutionFile.eof())
|
||||
{
|
||||
ResolutionFile.getline(buf,256);
|
||||
if(sscanf(buf,"%hdx%hdx%hd", &resolution.width,
|
||||
&resolution.height,
|
||||
&resolution.depth) == 3)
|
||||
m_Resolutionlist.push_back(resolution);
|
||||
}
|
||||
}
|
||||
ResolutionFile.close();
|
||||
}
|
||||
|
||||
st_resolution CVideoDriver::setNextResolution()
|
||||
{
|
||||
m_Resolution_pos++;
|
||||
|
||||
if(m_Resolution_pos == m_Resolutionlist.end())
|
||||
m_Resolution_pos = m_Resolutionlist.begin();
|
||||
|
||||
return *m_Resolution_pos;
|
||||
}
|
||||
|
||||
void CVideoDriver::setMode(int width, int height,int depth)
|
||||
{
|
||||
m_Resolution.width = width;
|
||||
m_Resolution.height = height;
|
||||
m_Resolution.depth = depth;
|
||||
|
||||
// TODO: Cycle through the list until the matching resolution is matched. If it doesn't exist
|
||||
// add it;
|
||||
for(m_Resolution_pos = m_Resolutionlist.begin() ; m_Resolution_pos != m_Resolutionlist.end() ; m_Resolution_pos++)
|
||||
if( m_Resolution_pos->width == width )
|
||||
if( m_Resolution_pos->height == height )
|
||||
if( m_Resolution_pos->depth == depth )
|
||||
break;
|
||||
|
||||
if(m_Resolution_pos == m_Resolutionlist.end())
|
||||
{
|
||||
m_Resolutionlist.push_back(m_Resolution);
|
||||
m_Resolution_pos--;
|
||||
}
|
||||
}
|
||||
|
||||
void CVideoDriver::stop(void)
|
||||
{
|
||||
if(screen) { SDL_FreeSurface(screen); g_pLogFile->textOut("freed screen<br>"); screen = NULL; }
|
||||
@@ -137,7 +207,8 @@ bool CVideoDriver::initOpenGL()
|
||||
if(m_opengl) // If OpenGL could be set, initialize the matrices
|
||||
{
|
||||
mp_OpenGL = new COpenGL();
|
||||
if(!(mp_OpenGL->initGL(Width, Height, Depth, m_opengl_filter, Filtermode+1, m_aspect_correction)))
|
||||
if(!(mp_OpenGL->initGL(m_Resolution.width, m_Resolution.height, m_Resolution.depth,
|
||||
m_opengl_filter, Filtermode+1, m_aspect_correction)))
|
||||
{
|
||||
delete mp_OpenGL;
|
||||
mp_OpenGL = NULL;
|
||||
@@ -155,12 +226,15 @@ bool CVideoDriver::applyMode(void)
|
||||
{
|
||||
// Check if some zoom/filter modes are illogical
|
||||
// TODO: Make this call clearer to understand
|
||||
// TODO: Improve this function.
|
||||
// It must be able to change the resolution, and if it fails, roll back.
|
||||
if( (Zoom == 3 && Filtermode == 1) && !m_opengl )
|
||||
Zoom = 2;
|
||||
|
||||
// Grab a surface on the screen
|
||||
Mode = SDL_HWPALETTE;
|
||||
Mode = SDL_HWPALETTE | SDL_HWSURFACE;
|
||||
|
||||
m_Resolution = *m_Resolution_pos;
|
||||
|
||||
#ifndef WIZ
|
||||
// Support for doublebuffering
|
||||
@@ -182,24 +256,26 @@ bool CVideoDriver::applyMode(void)
|
||||
Mode |= SDL_FULLSCREEN;
|
||||
|
||||
// Before the resolution is set, check, if the zoom factor is too high!
|
||||
while(((Width/GAME_STD_WIDTH) < Zoom || (Height/GAME_STD_HEIGHT) < Zoom) && (Zoom > 1))
|
||||
while(((m_Resolution.width/GAME_STD_WIDTH) < Zoom || (m_Resolution.height/GAME_STD_HEIGHT) < Zoom) && (Zoom > 1))
|
||||
Zoom--;
|
||||
|
||||
// Try to center the screen!
|
||||
screenrect.w = blitrect.w = GAME_STD_WIDTH*Zoom;
|
||||
screenrect.h = blitrect.h = GAME_STD_HEIGHT*Zoom;
|
||||
screenrect.x = (Width-screenrect.w)>>1;
|
||||
if(Width == 320)
|
||||
screenrect.x = (m_Resolution.width-screenrect.w)>>1;
|
||||
|
||||
if(m_Resolution.width == 320)
|
||||
screenrect.y = 0;
|
||||
else
|
||||
screenrect.y = (Height-screenrect.h)>>1;
|
||||
screenrect.y = (m_Resolution.height-screenrect.h)>>1;
|
||||
blitrect.x = 0;
|
||||
blitrect.y = 0;
|
||||
|
||||
// And Display can be setup.
|
||||
screen = SDL_SetVideoMode(Width,Height,Depth,Mode);
|
||||
screen = SDL_SetVideoMode(m_Resolution.width,m_Resolution.height,m_Resolution.depth,Mode);
|
||||
|
||||
m_Resolution.depth = screen->format->BitsPerPixel;
|
||||
|
||||
Depth = screen->format->BitsPerPixel;
|
||||
|
||||
if( !screen )
|
||||
{
|
||||
@@ -214,14 +290,6 @@ bool CVideoDriver::applyMode(void)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CVideoDriver::setMode(unsigned int srcW, unsigned int srcH,
|
||||
unsigned short srcD)
|
||||
{
|
||||
Width = srcW;
|
||||
Height = srcH;
|
||||
Depth = srcD;
|
||||
}
|
||||
void CVideoDriver::setFrameskip(unsigned short value)
|
||||
{
|
||||
FrameSkip = value;
|
||||
@@ -250,7 +318,7 @@ bool CVideoDriver::createSurfaces(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
BGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, Depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
BGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
if (!BGLayerSurface)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VideoDriver: Couldn't create BGLayerSurface!<br>");
|
||||
@@ -258,7 +326,7 @@ bool CVideoDriver::createSurfaces(void)
|
||||
}
|
||||
|
||||
|
||||
FGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, Depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
FGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
if (!FGLayerSurface)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VideoDriver: Couldn't create FGLayerSurface!<br>");
|
||||
@@ -270,24 +338,26 @@ bool CVideoDriver::createSurfaces(void)
|
||||
//Set surface alpha
|
||||
SDL_SetAlpha( FGLayerSurface, SDL_SRCALPHA, 225 );
|
||||
|
||||
if(Width == 320 && !m_opengl)
|
||||
if(m_Resolution.width == 320 && !m_opengl)
|
||||
{
|
||||
g_pLogFile->textOut("Blitsurface = Screen<br>");
|
||||
BlitSurface = screen;
|
||||
blitsurface_alloc = 0;
|
||||
VRAMPtr = (unsigned char*)screen->pixels + ((Width * stretch_blit_yoff * Depth)>>3)+screenrect.y*screen->pitch + (screenrect.x*Depth>>3);
|
||||
VRAMPtr = (unsigned char*)screen->pixels +
|
||||
((m_Resolution.width * stretch_blit_yoff * m_Resolution.depth)>>3)+
|
||||
screenrect.y*screen->pitch + (screenrect.x*m_Resolution.depth>>3);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pLogFile->textOut("Blitsurface = creatergbsurfacefrom<br>");
|
||||
BlitSurface = SDL_CreateRGBSurface(Mode,GAME_STD_WIDTH, GAME_STD_HEIGHT, Depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
BlitSurface = SDL_CreateRGBSurface(Mode,GAME_STD_WIDTH, GAME_STD_HEIGHT, m_Resolution.depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
if (!BlitSurface)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VidDrv_Start(): Couldn't create BlitSurface!<br>");
|
||||
return false;
|
||||
}
|
||||
blitsurface_alloc = 1;
|
||||
VRAMPtr = (unsigned char*)screen->pixels + ((Width * stretch_blit_yoff * Depth)>>3)+screenrect.y*screen->pitch + (screenrect.x*Depth>>3);
|
||||
VRAMPtr = (unsigned char*)screen->pixels + ((m_Resolution.width * stretch_blit_yoff * m_Resolution.depth)>>3)+screenrect.y*screen->pitch + (screenrect.x*m_Resolution.depth>>3);
|
||||
}
|
||||
|
||||
dstrect.x = 0; dstrect.y = 0;
|
||||
@@ -324,13 +394,14 @@ char wraphoz, wrapvrt;
|
||||
int save_dstx, save_dstw, save_srcx, save_srcw;
|
||||
char tempbuf[80];
|
||||
|
||||
blitBGLayer();
|
||||
|
||||
dstrect.x = 0; dstrect.y = 0;
|
||||
dstrect.w = 320; dstrect.h = 200;
|
||||
|
||||
srcrect.x = scrollx_buf;
|
||||
srcrect.y = scrolly_buf;
|
||||
|
||||
blitBGLayer();
|
||||
|
||||
if (scrollx_buf > (512-320))
|
||||
{ // need to wrap right side
|
||||
srcrect.w = (512-scrollx_buf);
|
||||
@@ -367,6 +438,7 @@ char tempbuf[80];
|
||||
srcrect.x = 0;
|
||||
srcrect.w = (320 - srcrect.w);
|
||||
SDL_BlitSurface(ScrollSurface, &srcrect, BlitSurface, &dstrect);
|
||||
|
||||
// now repeat for the bottom
|
||||
// (lower-right square)
|
||||
dstrect.y = srcrect.h;
|
||||
@@ -440,14 +512,14 @@ void CVideoDriver::update_screen(void)
|
||||
|
||||
// if we're doing zoom then we have copied the scroll buffer into
|
||||
// another offscreen buffer, and must now stretchblit it to the screen
|
||||
if (Zoom == 1 && Width != 320 )
|
||||
if (Zoom == 1 && m_Resolution.width != 320 )
|
||||
{
|
||||
LockSurface(BlitSurface);
|
||||
LockSurface(screen);
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
noscale((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
noscale((char*)VRAMPtr, (char*)BlitSurface->pixels, (m_Resolution.depth>>3));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -465,12 +537,12 @@ void CVideoDriver::update_screen(void)
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
scale2xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
scale2xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (m_Resolution.depth>>3));
|
||||
}
|
||||
else if(Filtermode == 1)
|
||||
{
|
||||
scale(2, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
scale(2, VRAMPtr, m_Resolution.width*(m_Resolution.depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(m_Resolution.depth>>3), (m_Resolution.depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -489,17 +561,17 @@ void CVideoDriver::update_screen(void)
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
scale3xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
scale3xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (m_Resolution.depth>>3));
|
||||
}
|
||||
else if(Filtermode == 1)
|
||||
{
|
||||
scale(2, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
scale(2, VRAMPtr, m_Resolution.width*(m_Resolution.depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(m_Resolution.depth>>3), (m_Resolution.depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else if(Filtermode == 2)
|
||||
{
|
||||
scale(3, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
scale(3, VRAMPtr, m_Resolution.width*(m_Resolution.depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(m_Resolution.depth>>3), (m_Resolution.depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -517,22 +589,22 @@ void CVideoDriver::update_screen(void)
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
scale4xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
scale4xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (m_Resolution.depth>>3));
|
||||
}
|
||||
else if(Filtermode == 1)
|
||||
{
|
||||
scale(2, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
scale(2, VRAMPtr, m_Resolution.width*(m_Resolution.depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(m_Resolution.depth>>3), (m_Resolution.depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else if(Filtermode == 2)
|
||||
{
|
||||
scale(3, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
scale(3, VRAMPtr, m_Resolution.width*(m_Resolution.depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(m_Resolution.depth>>3), (m_Resolution.depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else if(Filtermode == 3)
|
||||
{
|
||||
scale(4, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
scale(4, VRAMPtr, m_Resolution.width*(m_Resolution.depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(m_Resolution.depth>>3), (m_Resolution.depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -562,7 +634,7 @@ void CVideoDriver::noscale(char *dest, char *src, short bbp)
|
||||
// just passes a blitsurface to the screen
|
||||
int i;
|
||||
for(i=0 ; i < 200 ; i++)
|
||||
memcpy(dest+(i*Width)*bbp,src+(i*GAME_STD_WIDTH)*bbp,320*bbp);
|
||||
memcpy(dest+(i*m_Resolution.width)*bbp,src+(i*GAME_STD_WIDTH)*bbp,320*bbp);
|
||||
}
|
||||
|
||||
void CVideoDriver::scale2xnofilter(char *dest, char *src, short bbp)
|
||||
@@ -577,10 +649,10 @@ void CVideoDriver::scale2xnofilter(char *dest, char *src, short bbp)
|
||||
{
|
||||
for(j = 0; j < 320 ; j++)
|
||||
{
|
||||
memcpy(dest+((j<<1)<<bbp)+(((i<<1)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+1)<<bbp)+(((i<<1)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+((j<<1)<<bbp)+(((i<<1)*m_Resolution.width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+1)<<bbp)+(((i<<1)*m_Resolution.width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
}
|
||||
memcpy(dest+(((i<<1)+1)*(Width<<bbp)),(dest+(i<<1)*(Width<<bbp)),(bbp<<2)*GAME_STD_WIDTH);
|
||||
memcpy(dest+(((i<<1)+1)*(m_Resolution.width<<bbp)),(dest+(i<<1)*(m_Resolution.width<<bbp)),(bbp<<2)*GAME_STD_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,12 +669,12 @@ void CVideoDriver::scale3xnofilter(char *dest, char *src, short bbp)
|
||||
for(j = 0; j < 320 ; j++)
|
||||
{
|
||||
// j*3 = (j<<1) + j
|
||||
memcpy(dest+(((j<<1)+j)<<bbp)+((((i<<1) + i)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+j+1)<<bbp)+((((i<<1) + i)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+j+2)<<bbp)+((((i<<1) + i)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+j)<<bbp)+((((i<<1) + i)*m_Resolution.width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+j+1)<<bbp)+((((i<<1) + i)*m_Resolution.width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+j+2)<<bbp)+((((i<<1) + i)*m_Resolution.width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
}
|
||||
memcpy(dest+((i<<1)+i+1)*(Width<<bbp),dest+((i<<1)+i)*(Width<<bbp),(3<<bbp)*GAME_STD_WIDTH);
|
||||
memcpy(dest+((i<<1)+i+2)*(Width<<bbp),dest+((i<<1)+i)*(Width<<bbp),(3<<bbp)*GAME_STD_WIDTH);
|
||||
memcpy(dest+((i<<1)+i+1)*(m_Resolution.width<<bbp),dest+((i<<1)+i)*(m_Resolution.width<<bbp),(3<<bbp)*GAME_STD_WIDTH);
|
||||
memcpy(dest+((i<<1)+i+2)*(m_Resolution.width<<bbp),dest+((i<<1)+i)*(m_Resolution.width<<bbp),(3<<bbp)*GAME_STD_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,19 +696,19 @@ void CVideoDriver::scale4xnofilter(char *dest, char *src, short bbp)
|
||||
{
|
||||
// j*4 = (j<<2)
|
||||
srctemp = src+((j+(i*GAME_STD_WIDTH))<<bbp);
|
||||
desttemp = dest+((4*(j+(i*Width)))<<bbp);
|
||||
desttemp = dest+((4*(j+(i*m_Resolution.width)))<<bbp);
|
||||
memcpy(desttemp,srctemp,bbp<<1);
|
||||
memcpy(desttemp+(1<<bbp),srctemp,bbp<<1);
|
||||
memcpy(desttemp+(2<<bbp),srctemp,bbp<<1);
|
||||
memcpy(desttemp+(3<<bbp),srctemp,bbp<<1);
|
||||
}
|
||||
srctemp = dest+(((i<<2)*Width)<<bbp);
|
||||
desttemp = dest+((((i<<2)+1)*Width)<<bbp);
|
||||
srctemp = dest+(((i<<2)*m_Resolution.width)<<bbp);
|
||||
desttemp = dest+((((i<<2)+1)*m_Resolution.width)<<bbp);
|
||||
size = GAME_STD_WIDTH*(bbp<<1<<2);
|
||||
|
||||
memcpy(desttemp,srctemp,size);
|
||||
memcpy(desttemp+(Width<<bbp),srctemp,size);
|
||||
memcpy(desttemp+((Width<<bbp)<<1),srctemp,size);
|
||||
memcpy(desttemp+(m_Resolution.width<<bbp),srctemp,size);
|
||||
memcpy(desttemp+((m_Resolution.width<<bbp)<<1),srctemp,size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,11 +818,11 @@ short CVideoDriver::getFiltermode(void)
|
||||
bool CVideoDriver::getFullscreen(void)
|
||||
{ return Fullscreen; }
|
||||
unsigned int CVideoDriver::getWidth(void)
|
||||
{ return Width; }
|
||||
{ return m_Resolution.width; }
|
||||
unsigned int CVideoDriver::getHeight(void)
|
||||
{ return Height; }
|
||||
{ return m_Resolution.height; }
|
||||
unsigned short CVideoDriver::getDepth(void)
|
||||
{ return Depth; }
|
||||
{ return m_Resolution.depth; }
|
||||
SDL_Surface *CVideoDriver::getScrollSurface(void)
|
||||
{ return ScrollSurface; }
|
||||
SDL_Surface *CVideoDriver::getBGLayerSurface(void)
|
||||
|
||||
756
src/sdl/CVideoDriver.cpp.orig
Normal file
756
src/sdl/CVideoDriver.cpp.orig
Normal file
@@ -0,0 +1,756 @@
|
||||
|
||||
/*
|
||||
* CVideoDriver.cpp
|
||||
*
|
||||
* Created on: 17.03.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
#include "CVideoDriver.h"
|
||||
#include "CInput.h"
|
||||
|
||||
#include "../keen.h"
|
||||
#include "video/colourconvert.h"
|
||||
#include "video/colourtable.h"
|
||||
#include "../scale2x/scalebit.h"
|
||||
#include "../CLogFile.h"
|
||||
#include "../CGraphics.h"
|
||||
|
||||
#define CKLOGFILENAME "genius.log"
|
||||
|
||||
#define MAX_CONSOLE_MESSAGES 3
|
||||
#define CONSOLE_MESSAGE_X 3
|
||||
#define CONSOLE_MESSAGE_Y 3
|
||||
#define CONSOLE_MESSAGE_SPACING 9
|
||||
#define CONSOLE_EXPIRE_RATE 250
|
||||
|
||||
#define GAME_STD_WIDTH 320
|
||||
#define GAME_STD_HEIGHT 200
|
||||
|
||||
// pointer to the line in VRAM to start blitting to when stretchblitting.
|
||||
// this may not be the first line on the display as it is adjusted to
|
||||
// center the image on the screen when in fullscreen.
|
||||
unsigned char *VRAMPtr;
|
||||
char blitsurface_alloc = 0;
|
||||
|
||||
SDL_Rect dstrect;
|
||||
|
||||
typedef struct stConsoleMessage
|
||||
{
|
||||
char msg[80];
|
||||
} stConsoleMessage;
|
||||
stConsoleMessage cmsg[MAX_CONSOLE_MESSAGES];
|
||||
int NumConsoleMessages = 0;
|
||||
int ConsoleExpireTimer = 0;
|
||||
|
||||
|
||||
CVideoDriver::CVideoDriver() {
|
||||
// Default values
|
||||
|
||||
showfps=true;
|
||||
#ifdef WIZ
|
||||
Width=320;
|
||||
Height=240;
|
||||
Depth=16;
|
||||
Mode=0;
|
||||
Fullscreen=true;
|
||||
Filtermode=0;
|
||||
Zoom=1;
|
||||
FrameSkip=0;
|
||||
m_targetfps = 30; // Enable automatic frameskipping by default at 30
|
||||
#else
|
||||
Width=640;
|
||||
Height=480;
|
||||
Depth=0;
|
||||
Mode=0;
|
||||
Fullscreen=false;
|
||||
Filtermode=1;
|
||||
Zoom=2;
|
||||
FrameSkip=2;
|
||||
m_targetfps = 0; // Disable automatic frameskipping by default
|
||||
#endif
|
||||
m_opengl = false;
|
||||
#ifdef USE_OPENGL
|
||||
m_opengl_filter = GL_NEAREST;
|
||||
mp_OpenGL = NULL;
|
||||
#endif
|
||||
m_aspect_correction = true;
|
||||
|
||||
screenrect.x=0;
|
||||
screenrect.y=0;
|
||||
screenrect.h=0;
|
||||
screenrect.w=0;
|
||||
|
||||
ScrollSurface=NULL; // 512x512 scroll buffer
|
||||
FGLayerSurface=NULL; // Scroll buffer for Messages
|
||||
BGLayerSurface=NULL;
|
||||
BlitSurface=NULL;
|
||||
}
|
||||
|
||||
CVideoDriver::~CVideoDriver() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void CVideoDriver::stop(void)
|
||||
{
|
||||
if(screen) { SDL_FreeSurface(screen); g_pLogFile->textOut("freed screen<br>"); screen = NULL; }
|
||||
if(ScrollSurface && (ScrollSurface->map != NULL)) { SDL_FreeSurface(ScrollSurface); g_pLogFile->textOut("freed scrollsurface<br>"); ScrollSurface = NULL; }
|
||||
if(blitsurface_alloc) { blitsurface_alloc = 0; SDL_FreeSurface(BlitSurface); g_pLogFile->textOut("freed blitsurface<br>"); BlitSurface=NULL; }
|
||||
#ifdef USE_OPENGL
|
||||
if(mp_OpenGL) { delete mp_OpenGL; mp_OpenGL = NULL; }
|
||||
#endif
|
||||
g_pLogFile->textOut(GREEN,"CVideoDriver Close%s<br>", SDL_GetError());
|
||||
}
|
||||
|
||||
|
||||
bool CVideoDriver::start(void)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"Could not initialize SDL: %s<br>", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
g_pLogFile->textOut(GREEN,"SDL was successfully initialized!<br>");
|
||||
|
||||
SDL_WM_SetCaption("Commander Genius (CKP)", NULL);
|
||||
// When the program is through executing, call SDL_Quit
|
||||
atexit(SDL_Quit);
|
||||
|
||||
if(!applyMode())
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VideoDriver: Error applying mode! Your Videocard doesn't seem to work on CKP<br>");
|
||||
g_pLogFile->textOut(RED,"Check, if you have the most recent drivers installed!<br>");
|
||||
return false;
|
||||
}
|
||||
|
||||
retval = createSurfaces();
|
||||
initOpenGL();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CVideoDriver::initOpenGL()
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if(m_opengl) // If OpenGL could be set, initialize the matrices
|
||||
{
|
||||
mp_OpenGL = new COpenGL();
|
||||
if(!(mp_OpenGL->initGL(Width, Height, Depth, m_opengl_filter, Filtermode+1, m_aspect_correction)))
|
||||
{
|
||||
delete mp_OpenGL;
|
||||
mp_OpenGL = NULL;
|
||||
m_opengl = false;
|
||||
}
|
||||
else
|
||||
mp_OpenGL->setSurface(BlitSurface);
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_opengl;
|
||||
}
|
||||
|
||||
bool CVideoDriver::applyMode(void)
|
||||
{
|
||||
// Check if some zoom/filter modes are illogical
|
||||
// TODO: Make this call clearer to understand
|
||||
if( (Zoom == 3 && Filtermode == 1) && !m_opengl )
|
||||
Zoom = 2;
|
||||
|
||||
// Grab a surface on the screen
|
||||
Mode = SDL_HWPALETTE;
|
||||
|
||||
// Support for doublebuffering
|
||||
Mode |= SDL_DOUBLEBUF;
|
||||
|
||||
// Enable OpenGL
|
||||
#ifdef USE_OPENGL
|
||||
if(m_opengl)
|
||||
{
|
||||
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
|
||||
Mode |= SDL_OPENGL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now we decide if it will be fullscreen or windowed mode.
|
||||
if(Fullscreen)
|
||||
Mode |= SDL_FULLSCREEN;
|
||||
|
||||
// Before the resolution is set, check, if the zoom factor is too high!
|
||||
while(((Width/GAME_STD_WIDTH) < Zoom || (Height/GAME_STD_HEIGHT) < Zoom) && (Zoom > 1))
|
||||
Zoom--;
|
||||
|
||||
// Try to center the screen!
|
||||
screenrect.w = blitrect.w = GAME_STD_WIDTH*Zoom;
|
||||
screenrect.h = blitrect.h = GAME_STD_HEIGHT*Zoom;
|
||||
screenrect.x = (Width-screenrect.w)>>1;
|
||||
if(Width == 320)
|
||||
screenrect.y = 0;
|
||||
else
|
||||
screenrect.y = (Height-screenrect.h)>>1;
|
||||
blitrect.x = 0;
|
||||
blitrect.y = 0;
|
||||
|
||||
// And Display can be setup.
|
||||
screen = SDL_SetVideoMode(Width,Height,Depth,Mode);
|
||||
|
||||
Depth = screen->format->BitsPerPixel;
|
||||
|
||||
if( !screen )
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VidDrv_Start(): Couldn't create a SDL surface: %s<br>", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!Fullscreen)
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
else
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CVideoDriver::setMode(unsigned int srcW, unsigned int srcH,
|
||||
unsigned short srcD)
|
||||
{
|
||||
Width = srcW;
|
||||
Height = srcH;
|
||||
Depth = srcD;
|
||||
}
|
||||
void CVideoDriver::setFrameskip(unsigned short value)
|
||||
{
|
||||
FrameSkip = value;
|
||||
}
|
||||
void CVideoDriver::setFilter(short value)
|
||||
{
|
||||
Filtermode = value;
|
||||
}
|
||||
void CVideoDriver::setZoom(short value)
|
||||
{
|
||||
Zoom = value;
|
||||
}
|
||||
|
||||
bool CVideoDriver::createSurfaces(void)
|
||||
{
|
||||
// This function creates the surfaces which are needed for the game.
|
||||
unsigned stretch_blit_yoff;
|
||||
|
||||
stretch_blit_yoff = 0;
|
||||
|
||||
ScrollSurface = SDL_CreateRGBSurfaceFrom(g_pGraphics->getScrollbuffer(), 512, 512, 8, 512, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
SDL_SetColorKey(ScrollSurface, SDL_SRCCOLORKEY, COLOUR_MASK);
|
||||
if (!ScrollSurface)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VideoDriver: Couldn't create ScrollSurface!<br>");
|
||||
return false;
|
||||
}
|
||||
|
||||
BGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, Depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
if (!BGLayerSurface)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VideoDriver: Couldn't create BGLayerSurface!<br>");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
FGLayerSurface = SDL_CreateRGBSurface(Mode,320, 200, Depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
if (!FGLayerSurface)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VideoDriver: Couldn't create FGLayerSurface!<br>");
|
||||
return false;
|
||||
}
|
||||
SDL_SetColorKey( FGLayerSurface, SDL_SRCCOLORKEY,
|
||||
SDL_MapRGB(FGLayerSurface->format, 0, 0, 0) );
|
||||
|
||||
//Set surface alpha
|
||||
SDL_SetAlpha( FGLayerSurface, SDL_SRCALPHA, 225 );
|
||||
|
||||
if(Width == 320 && !m_opengl)
|
||||
{
|
||||
g_pLogFile->textOut("Blitsurface = Screen<br>");
|
||||
BlitSurface = screen;
|
||||
blitsurface_alloc = 0;
|
||||
VRAMPtr = (unsigned char*)screen->pixels + ((Width * stretch_blit_yoff * Depth)>>3)+screenrect.y*screen->pitch + (screenrect.x*Depth>>3);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pLogFile->textOut("Blitsurface = creatergbsurfacefrom<br>");
|
||||
BlitSurface = SDL_CreateRGBSurface(Mode,GAME_STD_WIDTH, GAME_STD_HEIGHT, Depth, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
|
||||
if (!BlitSurface)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"VidDrv_Start(): Couldn't create BlitSurface!<br>");
|
||||
return false;
|
||||
}
|
||||
blitsurface_alloc = 1;
|
||||
VRAMPtr = (unsigned char*)screen->pixels + ((Width * stretch_blit_yoff * Depth)>>3)+screenrect.y*screen->pitch + (screenrect.x*Depth>>3);
|
||||
}
|
||||
|
||||
dstrect.x = 0; dstrect.y = 0;
|
||||
dstrect.w = GAME_STD_WIDTH;
|
||||
dstrect.h = GAME_STD_HEIGHT;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// alter the color palette. the palette is not actually altered
|
||||
// on-screen until pal_apply() is called.
|
||||
void CVideoDriver::pal_set(short colour, char red, char green, char blue)
|
||||
{
|
||||
MyPalette[colour].r = red;
|
||||
MyPalette[colour].g = green;
|
||||
MyPalette[colour].b = blue;
|
||||
}
|
||||
|
||||
// applies all changes to the palette made with pal_set
|
||||
void CVideoDriver::pal_apply(void)
|
||||
{
|
||||
SDL_SetColors(screen, (SDL_Color *) &MyPalette, 0, 256);
|
||||
SDL_SetColors(ScrollSurface, (SDL_Color *) &MyPalette, 0, 256);
|
||||
if (blitsurface_alloc)
|
||||
{
|
||||
SDL_SetColors(BlitSurface, (SDL_Color *) &MyPalette, 0, 256);
|
||||
}
|
||||
}
|
||||
|
||||
void CVideoDriver::sb_blit(void)
|
||||
{
|
||||
SDL_Rect srcrect;
|
||||
char wraphoz, wrapvrt;
|
||||
int save_dstx, save_dstw, save_srcx, save_srcw;
|
||||
char tempbuf[80];
|
||||
|
||||
blitBGLayer();
|
||||
|
||||
dstrect.x = 0; dstrect.y = 0;
|
||||
dstrect.w = 320; dstrect.h = 200;
|
||||
|
||||
srcrect.x = scrollx_buf;
|
||||
srcrect.y = scrolly_buf;
|
||||
if (scrollx_buf > (512-320))
|
||||
{ // need to wrap right side
|
||||
srcrect.w = (512-scrollx_buf);
|
||||
wraphoz = 1;
|
||||
}
|
||||
else
|
||||
{ // single blit for whole horizontal copy
|
||||
srcrect.w = 320;
|
||||
wraphoz = 0;
|
||||
}
|
||||
|
||||
if (scrolly_buf > (512-200))
|
||||
{ // need to wrap on bottom
|
||||
srcrect.h = (512-scrolly_buf);
|
||||
wrapvrt = 1;
|
||||
}
|
||||
else
|
||||
{ // single blit for whole bottom copy
|
||||
srcrect.h = 200;
|
||||
wrapvrt = 0;
|
||||
}
|
||||
|
||||
SDL_BlitSurface(ScrollSurface, &srcrect, BlitSurface, &dstrect);
|
||||
|
||||
if (wraphoz && wrapvrt)
|
||||
{
|
||||
// first do same thing we do for wraphoz
|
||||
save_dstx = dstrect.x;
|
||||
save_dstw = dstrect.w;
|
||||
save_srcx = srcrect.x;
|
||||
save_srcw = srcrect.w;
|
||||
dstrect.x = srcrect.w;
|
||||
dstrect.w = 320 - dstrect.x;
|
||||
srcrect.x = 0;
|
||||
srcrect.w = (320 - srcrect.w);
|
||||
SDL_BlitSurface(ScrollSurface, &srcrect, BlitSurface, &dstrect);
|
||||
// now repeat for the bottom
|
||||
// (lower-right square)
|
||||
dstrect.y = srcrect.h;
|
||||
dstrect.h = 200 - dstrect.y;
|
||||
srcrect.y = 0;
|
||||
srcrect.h = (200 - srcrect.h);
|
||||
SDL_BlitSurface(ScrollSurface, &srcrect, BlitSurface, &dstrect);
|
||||
// (lower-left square)
|
||||
dstrect.x = save_dstx;
|
||||
dstrect.w = save_dstw;
|
||||
srcrect.x = save_srcx;
|
||||
srcrect.w = save_srcw;
|
||||
SDL_BlitSurface(ScrollSurface, &srcrect, BlitSurface, &dstrect);
|
||||
}
|
||||
else if (wraphoz)
|
||||
{
|
||||
dstrect.x = srcrect.w;
|
||||
dstrect.w = 320 - dstrect.x;
|
||||
srcrect.x = 0;
|
||||
srcrect.w = (320 - srcrect.w);
|
||||
SDL_BlitSurface(ScrollSurface, &srcrect, BlitSurface, &dstrect);
|
||||
}
|
||||
else if (wrapvrt)
|
||||
{
|
||||
dstrect.y = srcrect.h;
|
||||
dstrect.h = 200 - dstrect.y;
|
||||
srcrect.y = 0;
|
||||
srcrect.h = (200 - srcrect.h);
|
||||
SDL_BlitSurface(ScrollSurface, &srcrect, BlitSurface, &dstrect);
|
||||
}
|
||||
|
||||
drawConsoleMessages();
|
||||
if (showfps)
|
||||
{
|
||||
|
||||
#ifdef DEBUG
|
||||
sprintf(tempbuf, "FPS: %03d; x = %ld ; y = %d", fps, player[0].x >>CSF, player[0].y >>CSF);
|
||||
|
||||
#else
|
||||
sprintf(tempbuf, "FPS: %03d", fps);
|
||||
#endif
|
||||
g_pGraphics->drawFont( (unsigned char *) tempbuf, 320-3-(strlen( (char *) tempbuf)<<3), 3, 1);
|
||||
}
|
||||
|
||||
update_screen();
|
||||
}
|
||||
void CVideoDriver::blitBGLayer(void)
|
||||
{
|
||||
SDL_BlitSurface(BGLayerSurface, NULL, BlitSurface, NULL);
|
||||
}
|
||||
|
||||
void CVideoDriver::update_screen(void)
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if(m_opengl)
|
||||
{
|
||||
SDL_BlitSurface(FGLayerSurface, NULL, BlitSurface, NULL);
|
||||
|
||||
mp_OpenGL->render();
|
||||
|
||||
SDL_LockSurface(FGLayerSurface);
|
||||
// Flush the layers
|
||||
memset(FGLayerSurface->pixels,SDL_MapRGB(FGLayerSurface->format, 0, 0, 0),
|
||||
GAME_STD_WIDTH*GAME_STD_HEIGHT*FGLayerSurface->format->BytesPerPixel);
|
||||
SDL_UnlockSurface(FGLayerSurface);
|
||||
}
|
||||
else // No OpenGL but Software Rendering
|
||||
{
|
||||
#endif
|
||||
SDL_BlitSurface(FGLayerSurface, NULL, BlitSurface, NULL);
|
||||
|
||||
// if we're doing zoom then we have copied the scroll buffer into
|
||||
// another offscreen buffer, and must now stretchblit it to the screen
|
||||
if (Zoom == 1 && Width != 320 )
|
||||
{
|
||||
SDL_LockSurface(BlitSurface);
|
||||
SDL_LockSurface(screen);
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
noscale((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"Sorry, but this filter doesn't work at that zoom mode<br>");
|
||||
g_pLogFile->textOut(PURPLE,"Try to use a higher zoom factor. Switching to no-filter<br>");
|
||||
Filtermode = 0;
|
||||
}
|
||||
SDL_UnlockSurface(screen);
|
||||
SDL_UnlockSurface(BlitSurface);
|
||||
}
|
||||
if (Zoom == 2)
|
||||
{
|
||||
SDL_LockSurface(BlitSurface);
|
||||
SDL_LockSurface(screen);
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
scale2xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
}
|
||||
else if(Filtermode == 1)
|
||||
{
|
||||
scale(2, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"Sorry, but this filter doesn't work at that zoom mode<br>");
|
||||
g_pLogFile->textOut(PURPLE,"Try to use a higher zoom factor. Switching to no-filter<br>");
|
||||
Filtermode = 0;
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(screen);
|
||||
SDL_UnlockSurface(BlitSurface);
|
||||
}
|
||||
else if (Zoom == 3)
|
||||
{
|
||||
SDL_LockSurface(BlitSurface);
|
||||
SDL_LockSurface(screen);
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
scale3xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
}
|
||||
else if(Filtermode == 1)
|
||||
{
|
||||
scale(2, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else if(Filtermode == 2)
|
||||
{
|
||||
scale(3, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"Sorry, but this filter doesn't work at that zoom mode<br>");
|
||||
g_pLogFile->textOut(PURPLE,"Try to use a higher zoom factor. Switching to no-filter<br>");
|
||||
Filtermode = 0;
|
||||
}
|
||||
SDL_UnlockSurface(screen);
|
||||
SDL_UnlockSurface(BlitSurface);
|
||||
}
|
||||
else if (Zoom == 4)
|
||||
{
|
||||
SDL_LockSurface(BlitSurface);
|
||||
SDL_LockSurface(screen);
|
||||
|
||||
if(Filtermode == 0)
|
||||
{
|
||||
scale4xnofilter((char*)VRAMPtr, (char*)BlitSurface->pixels, (Depth>>3));
|
||||
}
|
||||
else if(Filtermode == 1)
|
||||
{
|
||||
scale(2, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else if(Filtermode == 2)
|
||||
{
|
||||
scale(3, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else if(Filtermode == 3)
|
||||
{
|
||||
scale(4, VRAMPtr, Width*(Depth>>3), BlitSurface->pixels,
|
||||
GAME_STD_WIDTH*(Depth>>3), (Depth>>3), GAME_STD_WIDTH, GAME_STD_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pLogFile->textOut(PURPLE,"Sorry, but this filter doesn't work at that zoom mode<br>");
|
||||
g_pLogFile->textOut(PURPLE,"Try to use a higher zoom factor. Switching to no-filter<br>");
|
||||
Filtermode = 0;
|
||||
}
|
||||
SDL_UnlockSurface(screen);
|
||||
SDL_UnlockSurface(BlitSurface);
|
||||
}
|
||||
|
||||
SDL_Flip(screen);
|
||||
//SDL_UpdateRect(screen, screenrect.x, screenrect.y, screenrect.w, screenrect.h);
|
||||
|
||||
SDL_LockSurface(FGLayerSurface);
|
||||
// Flush the layers
|
||||
memset(FGLayerSurface->pixels,SDL_MapRGB(FGLayerSurface->format, 0, 0, 0),
|
||||
GAME_STD_WIDTH*GAME_STD_HEIGHT*FGLayerSurface->format->BytesPerPixel);
|
||||
SDL_UnlockSurface(FGLayerSurface);
|
||||
#ifdef USE_OPENGL
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CVideoDriver::noscale(char *dest, char *src, short bbp)
|
||||
{
|
||||
// just passes a blitsurface to the screen
|
||||
int i;
|
||||
for(i=0 ; i < 200 ; i++)
|
||||
memcpy(dest+(i*Width)*bbp,src+(i*GAME_STD_WIDTH)*bbp,320*bbp);
|
||||
}
|
||||
|
||||
void CVideoDriver::scale2xnofilter(char *dest, char *src, short bbp)
|
||||
{
|
||||
// workaround for copying correctly stuff to the screen, so the screen is scaled normally
|
||||
// to 2x (without filter). This applies to 16 and 32-bit colour depth.
|
||||
// use bit shifting method for faster blit!
|
||||
bbp >>= 1;
|
||||
|
||||
int i,j;
|
||||
for(i=0 ; i < 200 ; i++)
|
||||
{
|
||||
for(j = 0; j < 320 ; j++)
|
||||
{
|
||||
memcpy(dest+((j<<1)<<bbp)+(((i<<1)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+1)<<bbp)+(((i<<1)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
}
|
||||
memcpy(dest+(((i<<1)+1)*(Width<<bbp)),(dest+(i<<1)*(Width<<bbp)),(bbp<<2)*GAME_STD_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
void CVideoDriver::scale3xnofilter(char *dest, char *src, short bbp)
|
||||
{
|
||||
// workaround for copying correctly stuff to the screen, so the screen is scaled normally
|
||||
// to 2x (without filter). This applies to 16 and 32-bit colour depth.
|
||||
// Optimization of using bit shifting
|
||||
bbp >>= 1;
|
||||
|
||||
int i,j;
|
||||
for(i=0 ; i < 200 ; i++)
|
||||
{
|
||||
for(j = 0; j < 320 ; j++)
|
||||
{
|
||||
// j*3 = (j<<1) + j
|
||||
memcpy(dest+(((j<<1)+j)<<bbp)+((((i<<1) + i)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+j+1)<<bbp)+((((i<<1) + i)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
memcpy(dest+(((j<<1)+j+2)<<bbp)+((((i<<1) + i)*Width)<<bbp),src+(j<<bbp)+((i*GAME_STD_WIDTH)<<bbp),bbp<<1);
|
||||
}
|
||||
memcpy(dest+((i<<1)+i+1)*(Width<<bbp),dest+((i<<1)+i)*(Width<<bbp),(3<<bbp)*GAME_STD_WIDTH);
|
||||
memcpy(dest+((i<<1)+i+2)*(Width<<bbp),dest+((i<<1)+i)*(Width<<bbp),(3<<bbp)*GAME_STD_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
void CVideoDriver::scale4xnofilter(char *dest, char *src, short bbp)
|
||||
{
|
||||
// workaround for copying correctly stuff to the screen, so the screen is scaled normally
|
||||
// to 2x (without filter). This applies to 16 and 32-bit colour depth.
|
||||
// use bit shifting method for faster blit!
|
||||
bbp >>= 1;
|
||||
|
||||
char *srctemp;
|
||||
char *desttemp;
|
||||
int size;
|
||||
|
||||
int i,j;
|
||||
for(i=0 ; i < GAME_STD_HEIGHT ; i++)
|
||||
{
|
||||
for(j = 0; j < GAME_STD_WIDTH ; j++)
|
||||
{
|
||||
// j*4 = (j<<2)
|
||||
srctemp = src+((j+(i*GAME_STD_WIDTH))<<bbp);
|
||||
desttemp = dest+((4*(j+(i*Width)))<<bbp);
|
||||
memcpy(desttemp,srctemp,bbp<<1);
|
||||
memcpy(desttemp+(1<<bbp),srctemp,bbp<<1);
|
||||
memcpy(desttemp+(2<<bbp),srctemp,bbp<<1);
|
||||
memcpy(desttemp+(3<<bbp),srctemp,bbp<<1);
|
||||
}
|
||||
srctemp = dest+(((i<<2)*Width)<<bbp);
|
||||
desttemp = dest+((((i<<2)+1)*Width)<<bbp);
|
||||
size = GAME_STD_WIDTH*(bbp<<1<<2);
|
||||
|
||||
memcpy(desttemp,srctemp,size);
|
||||
memcpy(desttemp+(Width<<bbp),srctemp,size);
|
||||
memcpy(desttemp+((Width<<bbp)<<1),srctemp,size);
|
||||
}
|
||||
}
|
||||
|
||||
// functions to directly set and retrieve pixels from the VGA display
|
||||
void CVideoDriver::setpixel(unsigned int x, unsigned int y, unsigned char c)
|
||||
{
|
||||
if( x > Width || y > Height )
|
||||
return;
|
||||
|
||||
|
||||
if(BlitSurface->format->BitsPerPixel == 16)
|
||||
{
|
||||
Uint16 *ubuff16;
|
||||
ubuff16 = (Uint16*) FGLayerSurface->pixels;
|
||||
ubuff16 += (y * 320) + x;
|
||||
*ubuff16 = convert4to16BPPcolor(c, BlitSurface);
|
||||
}
|
||||
else if(BlitSurface->format->BitsPerPixel == 32)
|
||||
{
|
||||
Uint32 *ubuff32;
|
||||
ubuff32 = (Uint32*) FGLayerSurface->pixels;
|
||||
ubuff32 += (y * 320) + x;
|
||||
*ubuff32 = convert4to32BPPcolor(c, BlitSurface);
|
||||
}
|
||||
else
|
||||
{
|
||||
Uint8 *ubuff8;
|
||||
ubuff8 = (Uint8*) FGLayerSurface->pixels;
|
||||
ubuff8 += (y * 320) + x;
|
||||
*ubuff8 = (Uint8) c;
|
||||
}
|
||||
}
|
||||
unsigned char CVideoDriver::getpixel(int x, int y)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// "Console" here refers to the capability to pop up in-game messages
|
||||
// in the upper-left corner during game play ala Doom.
|
||||
void CVideoDriver::drawConsoleMessages(void)
|
||||
{
|
||||
int i;
|
||||
int y;
|
||||
|
||||
if (!NumConsoleMessages) return;
|
||||
if (!ConsoleExpireTimer)
|
||||
{
|
||||
NumConsoleMessages--;
|
||||
if (!NumConsoleMessages) return;
|
||||
ConsoleExpireTimer = CONSOLE_EXPIRE_RATE;
|
||||
}
|
||||
else ConsoleExpireTimer--;
|
||||
|
||||
y = CONSOLE_MESSAGE_Y;
|
||||
for(i=0;i<NumConsoleMessages;i++)
|
||||
{
|
||||
g_pGraphics->drawFont( (unsigned char *) cmsg[i].msg, CONSOLE_MESSAGE_X, y, 1);
|
||||
y += CONSOLE_MESSAGE_SPACING;
|
||||
}
|
||||
}
|
||||
|
||||
// removes all console messages
|
||||
void CVideoDriver::DeleteConsoleMsgs(void)
|
||||
{
|
||||
NumConsoleMessages = 0;
|
||||
}
|
||||
|
||||
// adds a console msg to the top of the screen and scrolls any
|
||||
// other existing messages downwards
|
||||
void CVideoDriver::AddConsoleMsg(const char *the_msg)
|
||||
{
|
||||
int i;
|
||||
for(i=MAX_CONSOLE_MESSAGES-2;i>=0;i--)
|
||||
{
|
||||
strcpy(cmsg[i+1].msg, cmsg[i].msg);
|
||||
}
|
||||
strcpy(cmsg[0].msg, the_msg);
|
||||
|
||||
if (NumConsoleMessages < MAX_CONSOLE_MESSAGES) NumConsoleMessages++;
|
||||
ConsoleExpireTimer = CONSOLE_EXPIRE_RATE;
|
||||
}
|
||||
|
||||
short CVideoDriver::getZoomValue(void){ return Zoom; }
|
||||
|
||||
void CVideoDriver::showFPS(bool value){ showfps = value; }
|
||||
|
||||
void CVideoDriver::isFullscreen(bool value)
|
||||
{
|
||||
Fullscreen = value;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned short CVideoDriver::getFrameskip(void)
|
||||
{
|
||||
return FrameSkip;
|
||||
}
|
||||
bool CVideoDriver::getShowFPS(void)
|
||||
{
|
||||
return showfps;
|
||||
}
|
||||
short CVideoDriver::getFiltermode(void)
|
||||
{
|
||||
if(Filtermode < 0)
|
||||
Filtermode = 0;
|
||||
return Filtermode;
|
||||
}
|
||||
bool CVideoDriver::getFullscreen(void)
|
||||
{ return Fullscreen; }
|
||||
unsigned int CVideoDriver::getWidth(void)
|
||||
{ return Width; }
|
||||
unsigned int CVideoDriver::getHeight(void)
|
||||
{ return Height; }
|
||||
unsigned short CVideoDriver::getDepth(void)
|
||||
{ return Depth; }
|
||||
SDL_Surface *CVideoDriver::getScrollSurface(void)
|
||||
{ return ScrollSurface; }
|
||||
SDL_Surface *CVideoDriver::getBGLayerSurface(void)
|
||||
{ return BGLayerSurface; }
|
||||
|
||||
|
||||
@@ -11,11 +11,17 @@
|
||||
#include "../CSingleton.h"
|
||||
#define g_pVideoDriver CVideoDriver::Get()
|
||||
|
||||
struct st_resolution
|
||||
{ short width,height,depth; };
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
#include "COpenGL.h"
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
inline bool LockSurface(SDL_Surface * bmp) {
|
||||
if (SDL_MUSTLOCK(bmp))
|
||||
@@ -38,11 +44,9 @@ public:
|
||||
bool createSurfaces(void);
|
||||
void stop(void);
|
||||
bool start(void);
|
||||
void setMode(unsigned int srcW, unsigned int srcH,
|
||||
unsigned short srcD);
|
||||
void isFullscreen(bool value);
|
||||
//void reset(void);
|
||||
void drawConsoleMessages(void);
|
||||
void initResolutionList();
|
||||
|
||||
void pal_set(short colour, char red, char green, char blue);
|
||||
void pal_apply(void);
|
||||
@@ -78,6 +82,7 @@ public:
|
||||
SDL_Surface *getScrollSurface(void);
|
||||
SDL_Surface *getBGLayerSurface(void);
|
||||
|
||||
void setMode(int width, int height,int depth);
|
||||
void setFrameskip(unsigned short value);
|
||||
void setFilter(short value);
|
||||
void setZoom(short vale);
|
||||
@@ -91,6 +96,7 @@ public:
|
||||
#endif
|
||||
void setTargetFPS(unsigned int targetfps){ if( targetfps >= 0 && targetfps <= 70 ) m_targetfps = targetfps; }
|
||||
unsigned char getTargetFPS(void){ return m_targetfps; }
|
||||
st_resolution setNextResolution();
|
||||
|
||||
void showFPS(bool value);
|
||||
|
||||
@@ -102,33 +108,37 @@ private:
|
||||
COpenGL *mp_OpenGL;
|
||||
#endif
|
||||
|
||||
unsigned int Width;
|
||||
unsigned int Height;
|
||||
unsigned short Depth;
|
||||
unsigned int Mode;
|
||||
bool Fullscreen;
|
||||
short Filtermode;
|
||||
unsigned short Zoom;
|
||||
unsigned short FrameSkip;
|
||||
unsigned int m_targetfps; // Used for automatic frame skipping
|
||||
bool showfps;
|
||||
bool m_opengl;
|
||||
int m_opengl_filter;
|
||||
bool m_aspect_correction;
|
||||
st_resolution m_Resolution;
|
||||
|
||||
SDL_Rect screenrect;
|
||||
SDL_Rect blitrect;
|
||||
list<st_resolution> m_Resolutionlist;
|
||||
list<st_resolution> :: iterator m_Resolution_pos;
|
||||
|
||||
SDL_Color MyPalette[256];
|
||||
unsigned int Mode;
|
||||
bool Fullscreen;
|
||||
short Filtermode;
|
||||
unsigned short Zoom;
|
||||
unsigned short FrameSkip;
|
||||
unsigned int m_targetfps; // Used for automatic frame skipping
|
||||
bool showfps;
|
||||
bool m_opengl;
|
||||
int m_opengl_filter;
|
||||
bool m_aspect_correction;
|
||||
|
||||
SDL_Surface *screen; // the actual video memory/window
|
||||
SDL_Surface *BGLayerSurface; // Special surface which support more colors than the scrollsurface
|
||||
SDL_Rect screenrect;
|
||||
SDL_Rect blitrect;
|
||||
|
||||
SDL_Color MyPalette[256];
|
||||
|
||||
SDL_Surface *FGLayerSurface; // Scroll buffer for Messages
|
||||
// This one is not allowed here! Used only for tests!
|
||||
SDL_Surface *screen; // the actual video memory/window
|
||||
SDL_Surface *BGLayerSurface; // Special surface which support more colors than the scrollsurface
|
||||
//for (Ex. HQ-Images)
|
||||
SDL_Surface *ScrollSurface; // 512x512 scroll buffer
|
||||
SDL_Surface *FGLayerSurface; // Scroll buffer for Messages
|
||||
// pointer to the surface that sb_blit is to assemble the scroll buffer into.
|
||||
// if zoom=1 this is the same as "screen", else it's allocated as it's own
|
||||
// buffer of 320x200.
|
||||
SDL_Surface *BlitSurface;
|
||||
SDL_Surface *ScrollSurface; // 512x512 scroll buffer
|
||||
// pointer to the surface that sb_blit is to assemble the scroll buffer into.
|
||||
// if zoom=1 this is the same as "screen", else it's allocated as it's own
|
||||
// buffer of 320x200.
|
||||
SDL_Surface *BlitSurface;
|
||||
|
||||
};
|
||||
#endif /* CVIDEODRIVER_H_ */
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
*/
|
||||
|
||||
#include "../../keen.h"
|
||||
#include "../../include/fileio/lzexe.h"
|
||||
#include "CSound.h"
|
||||
#include "../../include/fileio.h"
|
||||
#include "../../CLogFile.h"
|
||||
#include "../../hqp/CMusic.h"
|
||||
#include "../../vorticon/sounds.h"
|
||||
#include "../../fileio/CExeFile.h"
|
||||
|
||||
#define SAFE_DELETE_ARRAY(x) if(x) delete[] x; x=NULL
|
||||
|
||||
@@ -398,34 +398,22 @@ char CSound::loadSoundData(unsigned short Episode, char *DataDirectory)
|
||||
Utility to extract the embedded sounds from Commander Keen
|
||||
Episode 2 (keen2.exe) and Episode 3 (keen3.exe)
|
||||
|
||||
Implemented by Gerhard Stein <gerstrong@gmail.com> (2008)
|
||||
Implemented by Gerhard Stein <gerstrong@gmail.com> (2008,2009)
|
||||
Copyright (C) 2007 Hans de Goede <j.w.r.degoede@hhs.nl>
|
||||
|
||||
Many thanks to Mitugu(Kou) Kurizono for the decompression algorithm.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Modification by Gerstrong 2009
|
||||
The new version uses a class named CExeFile which is able to manage compressed or
|
||||
uncompressed files. The function simply let the class do its job and then copy
|
||||
the sound data.
|
||||
*/
|
||||
|
||||
char CSound::extractOfExeFile(char *inputpath, int episode)
|
||||
{
|
||||
const char *outputfname;
|
||||
int bit_count;
|
||||
FILE *fin, *fout;
|
||||
unsigned char buf[131072];
|
||||
short offset;
|
||||
int pos, repeat, sounds_start, sounds_end, ret = 0;
|
||||
int pos, sounds_start, sounds_end, ret = 0;
|
||||
char buffer[MAX_STRING_LENGTH];
|
||||
char inputfname[MAX_STRING_LENGTH];
|
||||
|
||||
@@ -434,6 +422,7 @@ char CSound::extractOfExeFile(char *inputpath, int episode)
|
||||
memset(buffer,0, MAX_STRING_LENGTH*sizeof(char));
|
||||
memset(inputfname,0, MAX_STRING_LENGTH*sizeof(char));
|
||||
|
||||
// Set Offsets. Episode 1 already provides this
|
||||
if (episode == 2)
|
||||
{
|
||||
outputfname = "sounds.ck2";
|
||||
@@ -452,112 +441,21 @@ char CSound::extractOfExeFile(char *inputpath, int episode)
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(buffer,inputpath);
|
||||
sprintf(inputfname,"%skeen%d.exe", inputpath, episode);
|
||||
|
||||
fin = fopen(inputfname, "rb");
|
||||
|
||||
if (!fin)
|
||||
{
|
||||
g_pLogFile->ftextOut( "Error opening input file %s: ", inputfname);
|
||||
perror(NULL);
|
||||
return 2;
|
||||
}
|
||||
CExeFile *ExeFile = new CExeFile(episode, inputfname);
|
||||
if(!ExeFile->readData()) ret = 1;
|
||||
else
|
||||
{
|
||||
sprintf(buffer,"%s%s", inputpath, outputfname);
|
||||
|
||||
fout = fopen(buffer, "wb");
|
||||
if (!fout)
|
||||
FILE *fout;
|
||||
if(!(fout = fopen(outputfname,"wb"))) ret = 1;
|
||||
else
|
||||
{
|
||||
g_pLogFile->ftextOut( "Error opening output file %s: ", outputfname);
|
||||
perror(NULL);
|
||||
fclose(fin);
|
||||
fwrite( ExeFile->getData()+sounds_start, 1, (sounds_end-sounds_start), fout);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
/* skip header */
|
||||
fseek(fin, 32, SEEK_SET);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (ferror(fin))
|
||||
{
|
||||
g_pLogFile->ftextOut( "Error reading from input file %s:", inputfname);
|
||||
perror(NULL);
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (get_bit(&bit_count, &fin))
|
||||
{
|
||||
buf[pos++] = getc(fin);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_bit(&bit_count, &fin))
|
||||
{
|
||||
unsigned char tmp[2];
|
||||
if(!fread(tmp, 1, 2, fin))
|
||||
{
|
||||
g_pLogFile->ftextOut(RED,"Read-Error!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
repeat = (tmp[1] & 0x07);
|
||||
|
||||
offset = ((tmp[1] & ~0x07) << 5) | tmp[0] | 0xE000;
|
||||
|
||||
if (repeat == 0)
|
||||
{
|
||||
repeat = getc (fin);
|
||||
|
||||
|
||||
if (repeat == 0)
|
||||
break;
|
||||
else if (repeat == 1)
|
||||
continue;
|
||||
else
|
||||
repeat++;
|
||||
}
|
||||
else
|
||||
repeat += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
repeat = ((get_bit(&bit_count, &fin) << 1) | get_bit(&bit_count, &fin)) + 2;
|
||||
offset = getc(fin) | 0xFF00;
|
||||
}
|
||||
|
||||
while (repeat > 0)
|
||||
{
|
||||
buf[pos] = buf[pos + offset];
|
||||
pos++;
|
||||
repeat--;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_pLogFile->ftextOut("Decompression (unlzexe) of %s done<br>", inputfname);
|
||||
|
||||
if (strcmp((char *)(&buf[sounds_start]), "SND"))
|
||||
{
|
||||
g_pLogFile->ftextOut( "Error: Beginning of sound data not found at expected offset<br>");
|
||||
ret = 1;
|
||||
}
|
||||
else if ((int)fwrite(&buf[sounds_start], 1, sounds_end - sounds_start, fout) !=
|
||||
(sounds_end - sounds_start))
|
||||
{
|
||||
g_pLogFile->ftextOut( "error writing to output file %s: ", outputfname);
|
||||
perror(NULL);
|
||||
ret = 1;
|
||||
}
|
||||
g_pLogFile->ftextOut("%s has been successfully written<br>", outputfname);
|
||||
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
|
||||
}
|
||||
|
||||
delete ExeFile;
|
||||
|
||||
return ret;
|
||||
}
|
||||
void CSound::setSoundmode(int freq, bool stereo)
|
||||
|
||||
@@ -9,89 +9,68 @@
|
||||
|
||||
#include <vorbis/codec.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#define MAX_LEVELS 100 // Stupid! But you need it!
|
||||
#define BUFFER_SIZE 32768 // 32 KB buffers
|
||||
|
||||
#include "../include/declarations.h"
|
||||
#include "../hqp/hq_sound.h"
|
||||
#include "../sdl/CVideoDriver.h"
|
||||
#include "../CLogFile.h"
|
||||
|
||||
short openOGGSound(FILE *fp, SDL_AudioSpec *pspec, stHQSound *psound)
|
||||
short openOGGSound(FILE *fp, SDL_AudioSpec *pspec, Uint16 format, stHQSound *psound)
|
||||
{
|
||||
// it is an ogg file
|
||||
// If Ogg detected, decode it into the stream psound->sound_buffer. It must fit to Audio_cvt structure, so that
|
||||
// it can be converted
|
||||
// If Ogg detected, decode it into the stream psound->sound_buffer.
|
||||
// It must fit into the Audio_cvt structure, so that it can be converted
|
||||
|
||||
int result;
|
||||
OggVorbis_File oggStream; // stream handle
|
||||
vorbis_info* vorbisInfo; // some formatting data
|
||||
vorbis_comment* vorbisComment; // user comments
|
||||
|
||||
if((result = ov_open(fp, &oggStream, NULL, 0)) < 0)
|
||||
if((result = ov_open_callbacks(fp, &oggStream, NULL, 0, OV_CALLBACKS_DEFAULT)) < 0)
|
||||
{
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
long bytes;
|
||||
char array[BUFFER_SIZE];
|
||||
vector<char> buffer;
|
||||
vorbis_info* vorbisInfo; // some formatting data
|
||||
vorbis_comment* vorbisComment; // user comments
|
||||
|
||||
int bitStream;
|
||||
vorbisInfo = ov_info(&oggStream, -1);
|
||||
vorbisComment = ov_comment(&oggStream, -1);
|
||||
|
||||
pspec->format = 32784; // Not sure, if this works with any ogg file
|
||||
pspec->format = AUDIO_S16LSB; // Ogg Audio seems to always use this format
|
||||
//pspec->format = (AUDIO_S16LSB*147)/160; // Ogg Audio seems to always use this format
|
||||
|
||||
pspec->channels = vorbisInfo->channels;
|
||||
pspec->freq = vorbisInfo->rate;
|
||||
|
||||
psound->sound_len = 0;
|
||||
do {
|
||||
// Read up to a buffer's worth of decoded sound data
|
||||
bytes = ov_read(&oggStream, array, BUFFER_SIZE, 0, 2, 1, &bitStream);
|
||||
// Append to end of buffer
|
||||
buffer.insert(buffer.end(), array, array + bytes);
|
||||
} while (bytes > 0);
|
||||
|
||||
ov_clear(&oggStream);
|
||||
|
||||
psound->sound_len = buffer.size();
|
||||
|
||||
psound->sound_buffer = new Uint8[psound->sound_len];
|
||||
for(Uint32 i=0; i<psound->sound_len ; i++ )
|
||||
{
|
||||
memcpy( &(psound->sound_buffer[i]), &(buffer[i]), 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long length;
|
||||
int section;
|
||||
long pos=0;
|
||||
long ret;
|
||||
char *stream;
|
||||
|
||||
length = 4 * (long)ov_pcm_total(&oggStream,-1);
|
||||
|
||||
stream = (char*) malloc(length*sizeof(char));
|
||||
|
||||
if(stream == NULL)
|
||||
{
|
||||
g_pLogFile->textOut(RED,"Error! Out of memory! in Loading the Ogg file<br>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eof=0;
|
||||
|
||||
while(!eof){
|
||||
ret=ov_read(&oggStream,stream + pos,sizeof(stream),0,2,1,§ion);
|
||||
if (ret == 0) {
|
||||
/* EOF */
|
||||
eof=1;
|
||||
} else if (ret < 0) {
|
||||
/* error in the stream. Not a problem, just reporting it in
|
||||
case we (the app) cares. In this case, we don't. */
|
||||
} else {
|
||||
/* we don't bother dealing with sample rate changes, etc, but
|
||||
you'll have to*/
|
||||
if(pos > length)
|
||||
{
|
||||
// Something went wrong here! Stream is already full!
|
||||
g_pLogFile->ftextOut("WARNING: Stream overflow while reading the ogg-file!<br>");
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
pos += ret;
|
||||
}
|
||||
}
|
||||
|
||||
psound->sound_buffer = (Uint8*) malloc(length);
|
||||
psound->sound_len = pos;
|
||||
|
||||
memcpy( psound->sound_buffer, stream, psound->sound_len);
|
||||
|
||||
free(stream);
|
||||
|
||||
ov_clear(&oggStream); // This also closes fp
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "../include/gamedo.h"
|
||||
|
||||
CCredits::CCredits() {
|
||||
// TODO Auto-generated constructor stub
|
||||
|
||||
}
|
||||
|
||||
CCredits::~CCredits() {
|
||||
@@ -94,7 +92,7 @@ void CCredits::Render(stCloneKeenPlus *pCKP)
|
||||
strcpy(scrolltext[25]," Pickle");
|
||||
strcpy(scrolltext[26],"Resources:");
|
||||
strcpy(scrolltext[27]," Tulip");
|
||||
strcpy(scrolltext[28],"");
|
||||
strcpy(scrolltext[28]," DaVince");
|
||||
strcpy(scrolltext[29],"");
|
||||
strcpy(scrolltext[30],"");
|
||||
strcpy(scrolltext[31],"");
|
||||
|
||||
137
src/vorticon/CEGAGraphics.cpp
Normal file
137
src/vorticon/CEGAGraphics.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* CEGAGraphics.cpp
|
||||
*
|
||||
* Created on: 11.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CEGAGraphics.h"
|
||||
|
||||
#ifdef TARGET_WIN32
|
||||
#include <dir.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
CEGAGraphics::CEGAGraphics(short episode, const char *path) {
|
||||
m_episode = episode;
|
||||
strcpy(m_path, path);
|
||||
|
||||
// EGAHEAD Structure
|
||||
LatchPlaneSize = 0;
|
||||
SpritePlaneSize = 0;
|
||||
BitmapTableStart = 0;
|
||||
SpriteStart = 0;
|
||||
|
||||
FontTiles = 0;
|
||||
FontLocation = 0;
|
||||
ScreenTiles = 0;
|
||||
ScreenLocation = 0;
|
||||
Num16Tiles = 0;
|
||||
Tiles16Location = 0;
|
||||
NumBitmaps = 0;
|
||||
BitmapLocation = 0;
|
||||
NumSprites = 0;
|
||||
SpriteLocation = 0;
|
||||
compressed = 0;
|
||||
|
||||
m_Latch = NULL;
|
||||
m_Sprit = NULL;
|
||||
m_FontSurface = NULL;
|
||||
m_BigTileSurface = NULL;
|
||||
m_TileSurface = NULL;
|
||||
m_BitmapsSurface = NULL;
|
||||
}
|
||||
|
||||
CEGAGraphics::~CEGAGraphics() {
|
||||
if(m_Latch) delete m_Latch;
|
||||
if(m_Sprit) delete m_Sprit;
|
||||
}
|
||||
|
||||
bool CEGAGraphics::loadData()
|
||||
{
|
||||
char buf[256];
|
||||
vector<char> databuf;
|
||||
|
||||
chdir("data"); // TODO: You must be able to use another directory
|
||||
if(m_path[0] == 0)
|
||||
sprintf(buf,"egahead.ck%hd",m_episode);
|
||||
else
|
||||
sprintf(buf,"%s/egahead.ck%hd",m_path,m_episode);
|
||||
ifstream HeadFile(buf,ios::binary);
|
||||
|
||||
if(!HeadFile)
|
||||
return false;
|
||||
|
||||
char byte;
|
||||
while(!HeadFile.eof())
|
||||
{
|
||||
HeadFile.read(&byte,1);
|
||||
databuf.push_back(byte);
|
||||
}
|
||||
HeadFile.close();
|
||||
|
||||
char *data;
|
||||
data = new char[databuf.size()];
|
||||
|
||||
memcpy(data, databuf.data(), databuf.size());
|
||||
|
||||
// Now copy the data to the EGAHEAD Structure
|
||||
memcpy(&LatchPlaneSize,data,4);
|
||||
memcpy(&SpritePlaneSize,data+4,4);
|
||||
memcpy(&BitmapTableStart,data+8,4);
|
||||
memcpy(&SpriteStart,data+12,4);
|
||||
|
||||
memcpy(&FontTiles,data+16,2);
|
||||
memcpy(&FontLocation,data+18,4);
|
||||
memcpy(&ScreenTiles,data+22,2);
|
||||
memcpy(&ScreenLocation,data+24,4);
|
||||
memcpy(&Num16Tiles,data+28,2);
|
||||
memcpy(&Tiles16Location,data+30,4);
|
||||
memcpy(&NumBitmaps,data+34,4);
|
||||
memcpy(&BitmapLocation,data+36,4);
|
||||
memcpy(&NumSprites,data+40,4);
|
||||
memcpy(&SpriteLocation,data+42,4);
|
||||
memcpy(&compressed,data+46,4);
|
||||
|
||||
m_Latch = new CEGALatch(LatchPlaneSize,
|
||||
BitmapTableStart,
|
||||
FontTiles,
|
||||
FontLocation,
|
||||
ScreenTiles,
|
||||
ScreenLocation,
|
||||
Num16Tiles,
|
||||
Tiles16Location,
|
||||
NumBitmaps,
|
||||
BitmapLocation);
|
||||
|
||||
m_Latch->loadHead(data);
|
||||
|
||||
if(m_path[0] == 0)
|
||||
sprintf(buf,"egalatch.ck%hd",m_episode);
|
||||
else
|
||||
sprintf(buf,"%s/egalatch.ck%hd",m_path,m_episode);
|
||||
m_Latch->loadData(buf,(compressed>>1)); // The second bit tells, if latch is compressed.
|
||||
|
||||
|
||||
m_Sprit = new CEGASprit(SpritePlaneSize,
|
||||
SpriteStart,
|
||||
NumSprites,
|
||||
SpriteLocation);
|
||||
m_Sprit->loadHead(data);
|
||||
|
||||
if(m_path[0] == 0)
|
||||
sprintf(buf,"egasprit.ck%hd",m_episode);
|
||||
else
|
||||
sprintf(buf,"%s/egasprit.ck%hd",m_path,m_episode);
|
||||
m_Sprit->loadData(buf,(compressed>>1));
|
||||
|
||||
chdir("../");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CEGAGraphics::getNumSprites() { return NumSprites; }
|
||||
|
||||
|
||||
63
src/vorticon/CEGAGraphics.h
Normal file
63
src/vorticon/CEGAGraphics.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* CEGAGraphics.h
|
||||
*
|
||||
* Created on: 11.07.2009
|
||||
* Author: gerstrong
|
||||
*
|
||||
* This Class carries the head of graphics
|
||||
* which are generally read from EGAHEAD.CK?
|
||||
* It also has uses two other clases, which
|
||||
* have the individual task to read its stuff
|
||||
* (EGASPRIT and EGALATCH)
|
||||
*/
|
||||
|
||||
#ifndef CEGAGRAPHICS_H_
|
||||
#define CEGAGRAPHICS_H_
|
||||
|
||||
#include "CEGALatch.h"
|
||||
#include "CEGASprit.h"
|
||||
|
||||
class CEGAGraphics {
|
||||
public:
|
||||
CEGAGraphics(short episode, const char *path);
|
||||
virtual ~CEGAGraphics();
|
||||
|
||||
bool loadData();
|
||||
|
||||
int getNumSprites();
|
||||
|
||||
private:
|
||||
short m_episode;
|
||||
char m_path[256];
|
||||
|
||||
// Part of the EGAHEAD Data Structure
|
||||
// Section 1:
|
||||
long LatchPlaneSize; //Size of one plane of latch data
|
||||
long SpritePlaneSize; //Size of one plane of sprite data
|
||||
long BitmapTableStart; //Start locations of the EGAHEAD entries for unmasked graphics (Excluding font and tiles.)
|
||||
long SpriteStart; //Where in the EGAHEAD the entries for masked graphics (Sprites) start
|
||||
|
||||
short FontTiles; //Number of 8x8 tiles. Meant for fonts
|
||||
long FontLocation; //Font start location (relative to plane data, but normally 0)
|
||||
long ScreenTiles; //Number of Screengraphics 32x32 tiles (always 0, because they were removed)
|
||||
long ScreenLocation; //Offset of 32x32 tiles (relative to plane data)
|
||||
short Num16Tiles; //Number of 16x16 tiles
|
||||
long Tiles16Location; //Offset of 16x16 tiles (relative to plane data)
|
||||
short NumBitmaps; //Number of bitmaps in table
|
||||
long BitmapLocation; //Offset of bitmaps (relative to plane data)
|
||||
short NumSprites; //Number of sprites
|
||||
long SpriteLocation; //Offset of sprites (relative to plane data)
|
||||
short compressed; // LZ compressed data
|
||||
|
||||
// Section 2 is in CEGALatch and section 3 is in EGASprit where also are the to be used graphics
|
||||
// Here are which will be created, when object of class initialized
|
||||
CEGALatch *m_Latch;
|
||||
CEGASprit *m_Sprit;
|
||||
|
||||
SDL_Surface *m_FontSurface; // 8x8 Tiles
|
||||
SDL_Surface *m_BigTileSurface; // May be 32x32. Never used in the original games
|
||||
SDL_Surface *m_TileSurface; // 16x16 Tiles
|
||||
SDL_Surface *m_BitmapsSurface; // Bitmaps of the games, like title screen
|
||||
};
|
||||
|
||||
#endif /* CEGAGRAPHICS_H_ */
|
||||
266
src/vorticon/CEGALatch.cpp
Normal file
266
src/vorticon/CEGALatch.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* CEGALatch.cpp
|
||||
*
|
||||
* Created on: 11.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CEGALatch.h"
|
||||
#include "../sdl/CVideoDriver.h"
|
||||
#include "CPlanes.h"
|
||||
#include "../funcdefs.h"
|
||||
#include "../keen.h"
|
||||
#include "../keenext.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char *BitmapData; // TODO: Partial solution. This BitmapData must become member of this class!
|
||||
|
||||
CEGALatch::CEGALatch( int planesize,
|
||||
long bitmaptablelocation,
|
||||
short fonttiles,
|
||||
long fontlocation,
|
||||
long screentiles,
|
||||
long screenlocation,
|
||||
short num16tiles,
|
||||
long tiles16location,
|
||||
short bitmaps,
|
||||
long bitmaplocation)
|
||||
{
|
||||
m_latchplanesize = planesize;
|
||||
m_bitmaptablelocation = bitmaptablelocation;
|
||||
m_fonttiles = fonttiles;
|
||||
m_fontlocation = fontlocation;
|
||||
m_screentiles = screentiles;
|
||||
m_screenlocation = screenlocation;
|
||||
m_num16tiles = num16tiles;
|
||||
m_tiles16location = tiles16location;
|
||||
m_bitmaps = bitmaps;
|
||||
m_bitmaplocation = bitmaplocation;
|
||||
|
||||
Bitmap = NULL;
|
||||
|
||||
RawData = NULL;
|
||||
}
|
||||
|
||||
CEGALatch::~CEGALatch() {
|
||||
if(Bitmap) delete [] Bitmap, Bitmap = NULL;
|
||||
if(RawData) delete [] RawData, RawData = NULL;
|
||||
}
|
||||
|
||||
bool CEGALatch::loadHead( char *data )
|
||||
{
|
||||
data += m_bitmaptablelocation;
|
||||
Bitmap = new st_Bitmap[m_bitmaps];
|
||||
|
||||
for(int i=0 ; i<m_bitmaps ; i++)
|
||||
{
|
||||
memcpy(&(Bitmap[i].width),data+16*i,2);
|
||||
memcpy(&(Bitmap[i].height),data+16*i+2,2);
|
||||
memcpy(&(Bitmap[i].location),data+16*i+4,4);
|
||||
memcpy(Bitmap[i].name,data+16*i+8,8);
|
||||
Bitmap[i].width *= 8; // The width is always divided by eight
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEGALatch::loadData(const char *filename, bool compresseddata)
|
||||
{
|
||||
FILE* latchfile;
|
||||
char *RawData;
|
||||
|
||||
latchfile = fopen(filename,"rb");
|
||||
|
||||
if(!latchfile)
|
||||
return false;
|
||||
|
||||
RawData = new char[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);
|
||||
|
||||
// TODO: Try to blit the Font map here!
|
||||
// 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 **
|
||||
//g_pLogFile->ftextOut("latch_loadlatch(): Decoding 8x8 tiles...<br>", fname);
|
||||
|
||||
// set up the getbit() function of CPlanes class
|
||||
CPlanes *Planes = new CPlanes(plane1 + m_fontlocation,
|
||||
plane2 + m_fontlocation,
|
||||
plane3 + m_fontlocation,
|
||||
plane4 + m_fontlocation,
|
||||
0);
|
||||
|
||||
// TODO: Create surfaces which can be blitted directly to the blit surface or maybe screen.
|
||||
|
||||
// Load 8x8 Tiles
|
||||
char c=0;
|
||||
for(int p=0;p<4;p++)
|
||||
{
|
||||
for(int t=0;t<m_fonttiles;t++)
|
||||
{
|
||||
for(int y=0;y<8;y++)
|
||||
{
|
||||
for(int x=0;x<8;x++)
|
||||
{
|
||||
// if we're on the first plane start with black,
|
||||
// else merge with the previously accumulated data
|
||||
if (p==0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = font[t][y][x];
|
||||
}
|
||||
// read a bit out of the current plane, shift it into the
|
||||
// correct position and merge it
|
||||
c |= (Planes->getbit(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;
|
||||
|
||||
// Load 32x32 Tiles
|
||||
|
||||
// TODO: Add a read function for 32x32 Tiles
|
||||
|
||||
// Load 16x16 Tiles
|
||||
Planes = new CPlanes(plane1 + m_tiles16location,
|
||||
plane2 + m_tiles16location,
|
||||
plane3 + m_tiles16location,
|
||||
plane4 + m_tiles16location,
|
||||
0);
|
||||
|
||||
for(int p=0;p<4;p++)
|
||||
{
|
||||
for(int t=0;t<m_num16tiles;t++)
|
||||
{
|
||||
for(int y=0;y<16;y++)
|
||||
{
|
||||
for(int x=0;x<16;x++)
|
||||
{
|
||||
if (p==0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = tiledata[t][y][x];
|
||||
}
|
||||
c |= (Planes->getbit(RawData, p) << p);
|
||||
if (p==3 && c==0) c = 16;
|
||||
|
||||
tiledata[t][y][x] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete Planes;
|
||||
|
||||
|
||||
// Load Bitmaps
|
||||
// figure out how much RAM we'll need to read all 4 planes of
|
||||
// latch data into memory.
|
||||
BitmapBufferRAMSize = 0;
|
||||
for(int i=0;i<m_bitmaps;i++)
|
||||
{
|
||||
// keep a tally of the bitmap sizes so we'll know how much RAM we have
|
||||
// to allocate for all of the bitmaps once they're decoded
|
||||
BitmapBufferRAMSize += (Bitmap[i].width *
|
||||
Bitmap[i].height);
|
||||
}
|
||||
BitmapBufferRAMSize++;
|
||||
|
||||
BitmapData = new char[BitmapBufferRAMSize];
|
||||
|
||||
// set up the getbit() function
|
||||
Planes = new CPlanes(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 continous stream of image data, with the bitmaps[]
|
||||
// array giving pointers to where each bitmap starts within the stream.
|
||||
|
||||
|
||||
const char defbitmapname[][9] = { "TITLE", "IDLOGO", "F1HELP", "HIGHSCOR",
|
||||
"NAME", "SCORE", "PARTS", "GAMEOVER", "AN", "PRESENT", "APOGEE", "KEENSHIP", "WINDON",
|
||||
"WINDOFF", "ONEMOMEN", "OFAN", "PRODUCT", "IDSOFT"};
|
||||
|
||||
// In case there is a strange mod or defect episode, put some names to it!
|
||||
|
||||
char *bmdataptr;
|
||||
|
||||
for(int p=0 ; p<4 ; p++)
|
||||
{
|
||||
// this points to the location that we're currently
|
||||
// decoding bitmap data to
|
||||
bmdataptr = &BitmapData[0];
|
||||
|
||||
for(int b=0 ; b<m_bitmaps ; b++)
|
||||
{
|
||||
bitmaps[b].xsize = Bitmap[b].width;
|
||||
bitmaps[b].ysize = Bitmap[b].height;
|
||||
if( Bitmap[b].name[0] == 0 && b<18 )
|
||||
strcpy(bitmaps[b].name,defbitmapname[b]);
|
||||
else
|
||||
memcpy(bitmaps[b].name, Bitmap[b].name, 8);
|
||||
bitmaps[b].name[8] = 0; //ensure null-terminated
|
||||
|
||||
bitmaps[b].bmptr = (unsigned char*) bmdataptr;
|
||||
|
||||
for(int y=0 ; y<bitmaps[b].ysize ; y++)
|
||||
{
|
||||
for(int x=0 ; x<bitmaps[b].xsize ; x++)
|
||||
{
|
||||
if (p==0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = *bmdataptr;
|
||||
}
|
||||
c |= (Planes->getbit(RawData, p) << p);
|
||||
if (p==3 && c==0) c = 16;
|
||||
*bmdataptr = c;
|
||||
bmdataptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete Planes;
|
||||
|
||||
if(RawData){ delete[] RawData; RawData = NULL;}
|
||||
|
||||
return true;
|
||||
}
|
||||
57
src/vorticon/CEGALatch.h
Normal file
57
src/vorticon/CEGALatch.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* CEGALatch.h
|
||||
*
|
||||
* Created on: 11.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CEGALATCH_H_
|
||||
#define CEGALATCH_H_
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
class CEGALatch {
|
||||
public:
|
||||
CEGALatch( int planesize,
|
||||
long bitmaptablelocation,
|
||||
short fonttiles,
|
||||
long fontlocation,
|
||||
long screentiles,
|
||||
long screenlocation,
|
||||
short num16tiles,
|
||||
long tiles16location,
|
||||
short bitmaps,
|
||||
long bitmaplocation);
|
||||
virtual ~CEGALatch();
|
||||
|
||||
bool loadHead(char *data );
|
||||
bool loadData(const char *filename, bool compresseddata);
|
||||
|
||||
char *RawData;
|
||||
|
||||
private:
|
||||
int m_num_Latches;
|
||||
int m_latchplanesize;
|
||||
long m_bitmaptablelocation;
|
||||
|
||||
struct st_Bitmap{
|
||||
short height;
|
||||
short width;
|
||||
long location;
|
||||
char name[8];
|
||||
}*Bitmap;
|
||||
|
||||
long m_latchstart;
|
||||
short m_fonttiles;
|
||||
long m_fontlocation;
|
||||
long m_screentiles;
|
||||
long m_screenlocation;
|
||||
short m_num16tiles;
|
||||
long m_tiles16location;
|
||||
short m_bitmaps;
|
||||
long m_bitmaplocation;
|
||||
|
||||
unsigned long BitmapBufferRAMSize;
|
||||
};
|
||||
|
||||
#endif /* CEGALATCH_H_ */
|
||||
172
src/vorticon/CEGASprit.cpp
Normal file
172
src/vorticon/CEGASprit.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* CEGASprit.cpp
|
||||
*
|
||||
* Created on: 11.07.2009
|
||||
* Author: gerstrong
|
||||
*
|
||||
* Yes, it should be CEGASprite, bute since the file name
|
||||
* is called EGASPRIT.CK? it is left that way,
|
||||
* to make the understanding clearer
|
||||
*/
|
||||
|
||||
#include "CEGASprit.h"
|
||||
#include "CPlanes.h"
|
||||
#include "../keen.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
////////////////////////
|
||||
// section of defines //
|
||||
////////////////////////
|
||||
|
||||
#define CSF 5
|
||||
|
||||
extern stSprite *sprites;
|
||||
|
||||
CEGASprit::CEGASprit(int planesize,
|
||||
long spritestartloc,
|
||||
int numsprites,
|
||||
long spriteloc)
|
||||
{
|
||||
m_planesize = planesize;
|
||||
m_spritestartloc = spritestartloc;
|
||||
m_numsprites = numsprites;
|
||||
m_spriteloc = spriteloc;
|
||||
Sprite = NULL;
|
||||
sprites = NULL;
|
||||
}
|
||||
|
||||
CEGASprit::~CEGASprit() {
|
||||
if(Sprite) delete [] Sprite, Sprite = NULL;
|
||||
if(sprites) delete [] sprites, sprites = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool CEGASprit::loadHead(char *data)
|
||||
{
|
||||
data += m_spritestartloc;
|
||||
|
||||
Sprite = new st_sprite[m_numsprites];
|
||||
|
||||
for(int i=0 ; i<m_numsprites ; i++ )
|
||||
{
|
||||
memcpy(&(Sprite[i].width),data+128*i,2);
|
||||
memcpy(&(Sprite[i].height),data+128*i+2,2);
|
||||
memcpy(&(Sprite[i].location_offset),data+128*i+4,2);
|
||||
memcpy(&(Sprite[i].location),data+128*i+6,2);
|
||||
memcpy(&(Sprite[i].hitbox_l),data+128*i+8,2);
|
||||
memcpy(&(Sprite[i].hitbox_u),data+128*i+10,2);
|
||||
memcpy(&(Sprite[i].hitbox_r),data+128*i+12,2);
|
||||
memcpy(&(Sprite[i].hitbox_b),data+128*i+14,2);
|
||||
memcpy(Sprite[i].name,data+128*i+16,12);
|
||||
memcpy(&(Sprite[i].hv_offset),data+128*i+28,4);
|
||||
|
||||
Sprite[i].width *= 8; // Another case where the width is divided by 8
|
||||
Sprite[i].hitbox_l >>= 8;
|
||||
Sprite[i].hitbox_u >>= 8;
|
||||
Sprite[i].hitbox_r >>= 8;
|
||||
Sprite[i].hitbox_b >>= 8;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEGASprit::loadData(const char *filename, bool compresseddata)
|
||||
{
|
||||
FILE* latchfile;
|
||||
char *RawData;
|
||||
|
||||
latchfile = fopen(filename,"rb");
|
||||
|
||||
if(!latchfile)
|
||||
return false;
|
||||
|
||||
RawData = new char[m_planesize * 5];
|
||||
// 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_planesize*5) ; i++)
|
||||
RawData[i] = fgetc(latchfile);
|
||||
}
|
||||
|
||||
fclose(latchfile);
|
||||
|
||||
// TODO: Try to blit the Font map here!
|
||||
// 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, plane5;
|
||||
|
||||
plane1 = 0;
|
||||
plane2 = (m_planesize * 1);
|
||||
plane3 = (m_planesize * 2);
|
||||
plane4 = (m_planesize * 3);
|
||||
plane5 = (m_planesize * 4);
|
||||
|
||||
CPlanes *Planes = new CPlanes(plane1 + m_spriteloc,
|
||||
plane2 + m_spriteloc,
|
||||
plane3 + m_spriteloc,
|
||||
plane4 + m_spriteloc,
|
||||
plane5 + m_spriteloc);
|
||||
|
||||
// TODO: Create surfaces which can be blitted directly to the blit surface or maybe screen.
|
||||
// load the image data
|
||||
sprites = new stSprite[301];
|
||||
char c;
|
||||
for(int p=0 ; p<4 ; p++)
|
||||
{
|
||||
for(int s=0 ; s<m_numsprites ; s++)
|
||||
{
|
||||
sprites[s].xsize = Sprite[s].width;
|
||||
sprites[s].ysize = Sprite[s].height;
|
||||
sprites[s].bboxX1 = (Sprite[s].hitbox_l << CSF);
|
||||
sprites[s].bboxY1 = (Sprite[s].hitbox_u << CSF);
|
||||
sprites[s].bboxX2 = (Sprite[s].hitbox_r << CSF);
|
||||
sprites[s].bboxY2 = (Sprite[s].hitbox_b << CSF);
|
||||
|
||||
for(int y=0 ; y<sprites[s].ysize ; y++)
|
||||
{
|
||||
for(int x=0 ; x<sprites[s].xsize ; x++)
|
||||
{
|
||||
if (p==0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = sprites[s].imgdata[y][x];
|
||||
}
|
||||
c |= (Planes->getbit(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(int s=0 ; s<m_numsprites ; s++)
|
||||
{
|
||||
for(int y=0 ; y<sprites[s].ysize ; y++)
|
||||
{
|
||||
for(int x=0 ; x<sprites[s].xsize ; x++)
|
||||
{
|
||||
sprites[s].maskdata[y][x] = (1 - Planes->getbit(RawData, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete Planes;
|
||||
|
||||
if(RawData){ delete[] RawData; RawData = NULL;}
|
||||
|
||||
return true;
|
||||
}
|
||||
44
src/vorticon/CEGASprit.h
Normal file
44
src/vorticon/CEGASprit.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* CEGASprit.h
|
||||
*
|
||||
* Created on: 11.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CEGASPRIT_H_
|
||||
#define CEGASPRIT_H_
|
||||
|
||||
class CEGASprit {
|
||||
public:
|
||||
CEGASprit(int planesize,
|
||||
long spritestartloc,
|
||||
int numsprites,
|
||||
long spriteloc);
|
||||
virtual ~CEGASprit();
|
||||
|
||||
bool loadHead(char *data);
|
||||
bool loadData(const char *filename, bool compresseddata);
|
||||
|
||||
private:
|
||||
int m_numsprites;
|
||||
int m_planesize;
|
||||
long m_spritestartloc;
|
||||
long m_spriteloc;
|
||||
|
||||
struct st_sprite{
|
||||
short width;
|
||||
short height;
|
||||
short location_offset; // usually. See shikadi.net for more info
|
||||
short location;
|
||||
short hitbox_u;
|
||||
short hitbox_l;
|
||||
short hitbox_b;
|
||||
short hitbox_r;
|
||||
char name[12];
|
||||
long hv_offset; // Unused in Keen games. Used in later games such as Shadow Knights
|
||||
// There are 3 copies of the same Elements in the file. There were used for performance
|
||||
// in DOS but are ignored here.
|
||||
}*Sprite;
|
||||
};
|
||||
|
||||
#endif /* CEGASPRIT_H_ */
|
||||
@@ -38,8 +38,8 @@ CHighScores::CHighScores(stCloneKeenPlus *poutsideCKP) {
|
||||
for(i=0 ; i<7 ; i++)
|
||||
sprintf(Score[i],"100");
|
||||
|
||||
memset(Extra, false, 7*4*sizeof(unsigned char));
|
||||
memset(Cities, false, 7*sizeof(unsigned int));
|
||||
memset(Extra, 0, 7*4*sizeof(unsigned char));
|
||||
memset(Cities, 0, 7*sizeof(unsigned int));
|
||||
|
||||
pCKP = poutsideCKP;
|
||||
|
||||
|
||||
@@ -14,12 +14,9 @@
|
||||
#include "../include/gamedo.h"
|
||||
|
||||
CIntro::CIntro() {
|
||||
// TODO Auto-generated constructor stub
|
||||
|
||||
}
|
||||
|
||||
CIntro::~CIntro() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
void CIntro::Render(stCloneKeenPlus *pCKP)
|
||||
@@ -65,13 +62,7 @@ void CIntro::Render(stCloneKeenPlus *pCKP)
|
||||
// blit the scrollbuffer to the display
|
||||
gamedo_frameskipping_blitonly();
|
||||
|
||||
g_pGraphics->drawBitmap2FG(mid[0], scrolly, bmnum[0]);
|
||||
g_pGraphics->drawBitmap2FG(mid[1], scrolly+9, bmnum[1]);
|
||||
g_pGraphics->drawBitmap2FG(mid[2], scrolly+43, bmnum[2]);
|
||||
g_pGraphics->drawBitmap2FG(mid[3], scrolly+56, bmnum[3]);
|
||||
g_pGraphics->drawBitmap2FG(mid[4], scrolly+77, bmnum[4]);
|
||||
g_pGraphics->drawBitmap2FG(mid[5], scrolly+87, bmnum[5]);
|
||||
g_pGraphics->drawBitmap2FG(mid[6], scrolly+120, bmnum[6]);
|
||||
|
||||
gamedo_AnimatedTiles();
|
||||
|
||||
@@ -83,6 +74,16 @@ void CIntro::Render(stCloneKeenPlus *pCKP)
|
||||
{
|
||||
timer=0;
|
||||
if(scrolly>35) scrolly--;
|
||||
else
|
||||
{
|
||||
g_pGraphics->drawBitmap2FG(mid[0], scrolly, bmnum[0]);
|
||||
g_pGraphics->drawBitmap2FG(mid[1], scrolly+9, bmnum[1]);
|
||||
g_pGraphics->drawBitmap2FG(mid[2], scrolly+43, bmnum[2]);
|
||||
g_pGraphics->drawBitmap2FG(mid[3], scrolly+56, bmnum[3]);
|
||||
g_pGraphics->drawBitmap2FG(mid[4], scrolly+77, bmnum[4]);
|
||||
g_pGraphics->drawBitmap2FG(mid[5], scrolly+87, bmnum[5]);
|
||||
g_pGraphics->drawBitmap2FG(mid[6], scrolly+120, bmnum[6]);
|
||||
}
|
||||
}
|
||||
|
||||
if( g_pInput->getPressedAnyKey() || g_pInput->getPressedAnyCommand() )
|
||||
|
||||
84
src/vorticon/CMessages.cpp
Normal file
84
src/vorticon/CMessages.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* CMessages.cpp
|
||||
*
|
||||
* Created on: 16.07.2009
|
||||
* Author: gerstrong
|
||||
*
|
||||
* This special class reads all the strings
|
||||
* out of an exe-file. It also can identify
|
||||
* what string the program needs.
|
||||
*/
|
||||
|
||||
#include "CMessages.h"
|
||||
#include "../CLogFile.h"
|
||||
|
||||
CMessages::CMessages() {
|
||||
|
||||
}
|
||||
|
||||
CMessages::~CMessages() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
// buf - is the uncompressed buffer of the exe-file (keen1.exe for example)
|
||||
// episode - the game's episode
|
||||
// version - version of the exe-file
|
||||
bool CMessages::readData(char *buf, int episode, int version)
|
||||
{
|
||||
long offset_start;
|
||||
long offset_end;
|
||||
|
||||
// TODO: This function still has bugs when reading the text. Check this closer!
|
||||
// This part of switches is used to get the proper addresses of the message text.
|
||||
switch(episode)
|
||||
{
|
||||
case 1:
|
||||
switch(version)
|
||||
{
|
||||
case 131:
|
||||
offset_start = 0x14FAB;
|
||||
offset_end = 0x16801;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
g_pLogFile->textOut(RED,"This version of the game is not supported!");
|
||||
break;
|
||||
case 3:
|
||||
g_pLogFile->textOut(RED,"This version of the game is not supported!");
|
||||
break;
|
||||
default:
|
||||
g_pLogFile->textOut(RED,"This version of the game is not supported!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now read the stuff and store it to a list
|
||||
for(int pos=offset_start ; pos<offset_end ; pos++)
|
||||
{
|
||||
string Text;
|
||||
|
||||
while(buf[pos] != 0)
|
||||
{
|
||||
Text += buf[pos];
|
||||
pos++;
|
||||
}
|
||||
pos++;
|
||||
|
||||
if(!Text.empty()) // not empty
|
||||
StringList.push_back(Text);
|
||||
}
|
||||
|
||||
list<string> :: iterator i;
|
||||
|
||||
#include <iostream>
|
||||
for(i=StringList.begin() ; i!=StringList.end() ; i++)
|
||||
{
|
||||
std::cout << *i << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *CMessages::getString(const char *IDtext)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
32
src/vorticon/CMessages.h
Normal file
32
src/vorticon/CMessages.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* CMessages.h
|
||||
*
|
||||
* Created on: 16.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CMESSAGES_H_
|
||||
#define CMESSAGES_H_
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// TODO: Make the strings a class, but it must read from the exe-files basing on uncompressed buffer
|
||||
|
||||
class CMessages {
|
||||
public:
|
||||
CMessages();
|
||||
virtual ~CMessages();
|
||||
|
||||
bool readData(char *buf, int episode, int version);
|
||||
char *getString(const char *IDtext);
|
||||
|
||||
private:
|
||||
list<string> StringList;
|
||||
list<string> StringIDList;
|
||||
};
|
||||
|
||||
#endif /* CMESSAGES_H_ */
|
||||
53
src/vorticon/CPlanes.cpp
Normal file
53
src/vorticon/CPlanes.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* CPlanes.cpp
|
||||
*
|
||||
* Created on: 12.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#include "CPlanes.h"
|
||||
|
||||
|
||||
// Constructor initializes the positions,getbit will retrieve data from
|
||||
CPlanes::CPlanes(unsigned long p1, unsigned long p2, unsigned long p3,\
|
||||
unsigned long p4, unsigned long p5) {
|
||||
int i;
|
||||
getbit_bytepos[0] = p1;
|
||||
getbit_bytepos[1] = p2;
|
||||
getbit_bytepos[2] = p3;
|
||||
getbit_bytepos[3] = p4;
|
||||
getbit_bytepos[4] = p5;
|
||||
|
||||
for(i=0;i<=4;i++)
|
||||
{
|
||||
getbit_bitmask[i] = 128;
|
||||
}
|
||||
}
|
||||
|
||||
// retrieves a bit from plane "plane". the positions of the planes
|
||||
// should have been previously initilized with setplanepositions()
|
||||
unsigned char CPlanes::getbit(char *buf, unsigned char plane)
|
||||
{
|
||||
int retval;
|
||||
int byt;
|
||||
if (!getbit_bitmask[plane])
|
||||
{
|
||||
getbit_bitmask[plane] = 128;
|
||||
getbit_bytepos[plane]++;
|
||||
}
|
||||
|
||||
byt = buf[getbit_bytepos[plane]];
|
||||
|
||||
if (byt & getbit_bitmask[plane])
|
||||
{
|
||||
retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
getbit_bitmask[plane] >>= 1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
24
src/vorticon/CPlanes.h
Normal file
24
src/vorticon/CPlanes.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* CPlanes.h
|
||||
*
|
||||
* Created on: 12.07.2009
|
||||
* Author: gerstrong
|
||||
*/
|
||||
|
||||
#ifndef CPLANES_H_
|
||||
#define CPLANES_H_
|
||||
|
||||
class CPlanes {
|
||||
public:
|
||||
CPlanes(unsigned long p1, unsigned long p2, unsigned long p3,\
|
||||
unsigned long p4, unsigned long p5);
|
||||
|
||||
unsigned char getbit(char *buf, unsigned char plane);
|
||||
|
||||
private:
|
||||
unsigned long getbit_bytepos[5];
|
||||
unsigned char getbit_bitmask[5];
|
||||
|
||||
};
|
||||
|
||||
#endif /* CPLANES_H_ */
|
||||
Reference in New Issue
Block a user