many C-string -> std::string replacements and some additional code taken from OpenLieroX

git-svn-id: https://clonekeenplus.svn.sourceforge.net/svnroot/clonekeenplus/cgenius/trunk@87 4df4b0f3-56ce-47cb-b001-ed939b7d65a6
This commit is contained in:
albertzeyer
2009-07-22 15:17:41 +00:00
parent cb3c2e2502
commit 5fcc021293
73 changed files with 12091 additions and 6988 deletions

View File

@@ -27,7 +27,6 @@
CGame::CGame() {
m_Episode = 0;
memset(m_DataDirectory,0,256);
TileLoader = NULL;
EGAGraphics = NULL;
@@ -218,13 +217,13 @@ short CGame::runCycle(stCloneKeenPlus *pCKP)
return 0;
}
int CGame::loadResources(unsigned short Episode, char *DataDirectory)
int CGame::loadResources(unsigned short Episode, const std::string& DataDirectory)
{
m_Episode = Episode;
memcpy(m_DataDirectory, DataDirectory, 256);
m_DataDirectory = DataDirectory;
if( ( *(DataDirectory+strlen(DataDirectory)-1) != '/' ) && strlen(DataDirectory) > 0)
strcat(DataDirectory,"/");
if( m_DataDirectory.size() > 0 && m_DataDirectory[m_DataDirectory.size()-1] != '/' )
m_DataDirectory += "/";
// Decode the entire graphics for the game (EGALATCH, EGASPRIT)
EGAGraphics = new CEGAGraphics(Episode, DataDirectory); // Path is relative to the data dir
@@ -277,8 +276,6 @@ void CGame::preallocateCKP(stCloneKeenPlus *pCKP)
pCKP->GameData = NULL;
pCKP->GameData = new stGameData[1];
memset(pCKP->GameData, 0, sizeof(stGameData));
framebyframe = 0;
demomode = DEMO_NODEMO;

View File

@@ -8,7 +8,7 @@
#ifndef CGAME_H_
#define CGAME_H_
#include <string.h>
#include <string>
#include "vorticon/CEGAGraphics.h"
#include "vorticon/CMessages.h"
@@ -17,15 +17,14 @@ public:
CGame();
virtual ~CGame();
int loadResources(unsigned short Episode, char *DataDirectory);
int loadResources(unsigned short Episode, const std::string& DataDirectory);
void freeResources(void);
short runCycle(stCloneKeenPlus *pCKP);
void preallocateCKP(stCloneKeenPlus *pCKP);
private:
static const unsigned short MAX_TEXT_LENGTH = 256;
unsigned short m_Episode;
char m_DataDirectory[MAX_TEXT_LENGTH];
std::string m_DataDirectory;
int current_demo;
CEGAGraphics *EGAGraphics;

View File

@@ -10,12 +10,14 @@
* not platform-specific).
*/
#include "CGraphics.h"
#include "keen.h"
#include "keenext.h"
#include "CGraphics.h"
#include "sdl/CVideoDriver.h"
#include "sdl/video/colourtable.h"
#include "sdl/CVideoDriver.h"
#include "CLogFile.h"
#include "StringUtils.h"
CGraphics::CGraphics() {
HQBitmap = NULL;
@@ -591,13 +593,13 @@ int c;
}
// font drawing functions
void CGraphics::drawFont(unsigned char *text, int xoff, int yoff, int highlight)
void CGraphics::drawFont(const std::string& text, int xoff, int yoff, int highlight)
{
unsigned int i,x=xoff,y;
int c;
y = yoff;
for(i=0;i<strlen( (char*) text);i++)
for(i=0;i<text.size();i++)
{
c = text[i];
if (!c) break;
@@ -614,15 +616,14 @@ int c;
}
}
}
void CGraphics::sb_font_draw(const unsigned char *text, int xoff, int yoff)
void CGraphics::sb_font_draw(const std::string& text, int xoff, int yoff)
{
unsigned int i,x,y;
x=xoff;
y=yoff;
for(i=0;i<strlen( (char*) text);i++)
for(i=0;i<text.size();i++)
{
if (!text[i]) break;
if (text[i]!=13)
{
sb_drawCharacter(x, y, text[i]);
@@ -636,13 +637,13 @@ void CGraphics::sb_font_draw(const unsigned char *text, int xoff, int yoff)
}
}
void CGraphics::sb_mask_font_draw(unsigned char *text, int xoff, int yoff, char mask)
void CGraphics::sb_mask_font_draw(const std::string& text, int xoff, int yoff, char mask)
{
unsigned int i,x,y;
x=xoff;
y=yoff;
for(i=0;i<strlen( (char*) text);i++)
for(i=0;i<text.size();i++)
{
if (!text[i]) break;
if (text[i]!=13)
@@ -659,15 +660,14 @@ unsigned int i,x,y;
}
void CGraphics::sb_color_font_draw(unsigned char *text, int xoff, int yoff, unsigned int colour, unsigned short bgcolour)
void CGraphics::sb_color_font_draw(const std::string& text, int xoff, int yoff, unsigned int colour, unsigned short bgcolour)
{
unsigned int i,x,y;
x=xoff;
y=yoff;
for(i=0;i<strlen( (char*) text);i++)
for(i=0;i< text.size(); i++)
{
if (!text[i]) break;
if (text[i]!=13)
{
sb_drawColorcharacter(x, y, text[i], colour, bgcolour);
@@ -681,14 +681,13 @@ unsigned int i,x,y;
}
}
void CGraphics::sb_font_draw_inverse(unsigned char *text, int xoff, int yoff)
void CGraphics::sb_font_draw_inverse(const std::string& text, int xoff, int yoff)
{
unsigned int i,x=xoff,y;
y=yoff;
for(i=0;i<strlen( (char*) text);i++)
for(i=0;i< text.size();i++)
{
if (!text[i]) break;
if (text[i]!=13)
{
sb_drawCharacterinverse(x, y, text[i]);
@@ -725,18 +724,12 @@ void CGraphics::renderHQBitmap()
}
}
void CGraphics::loadHQGraphics(unsigned char episode, unsigned char level, char *datadir)
void CGraphics::loadHQGraphics(unsigned char episode, unsigned char level, const std::string& datadir)
{
char buf[256];
char buf2[256];
SDL_Rect screen_rect;
memset(buf,0,256);
memset(buf2,0,256);
formatPathString(buf,datadir);
sprintf(buf2,"%slevel%dep%d.bmp",buf,level,episode);
std::string buf = formatPathString(datadir);
std::string buf2 = buf + "level" + itoa(level) + "ep" + itoa(episode) + ".bmp";
screen_rect.x = 0;
screen_rect.y = 0;

View File

@@ -11,6 +11,7 @@
#include "CSingleton.h"
#define g_pGraphics CGraphics::Get()
#include <string>
#include <SDL.h>
#include "hqp/CHQBitmap.h"
@@ -44,18 +45,18 @@ public:
void drawBitmap2FG(int xa, int ya, int b);
int getBitmapNumberFromName(const char *bmname);
void sb_drawCharacterinverse(int x, int y, int f);
void drawFont(unsigned char *text, int xoff, int yoff, int highlight);
void sb_font_draw(const unsigned char *text, int xoff, int yoff);
void sb_mask_font_draw(unsigned char *text, int xoff, int yoff, char mask);
void sb_color_font_draw(unsigned char *text, int xoff, int yoff, unsigned int colour, unsigned short bgcolour);
void sb_font_draw_inverse(unsigned char *text, int xoff, int yoff);
void drawFont(const std::string& text, int xoff, int yoff, int highlight);
void sb_font_draw(const std::string& text, int xoff, int yoff);
void sb_mask_font_draw(const std::string& text, int xoff, int yoff, char mask);
void sb_color_font_draw(const std::string& text, int xoff, int yoff, unsigned int colour, unsigned short bgcolour);
void sb_font_draw_inverse(const std::string& text, int xoff, int yoff);
void drawTile_direct(int x, int y, unsigned int t);
void setFadeBlack(bool value);
Uint8 *getScrollbuffer(void);
void renderHQBitmap();
void loadHQGraphics(unsigned char episode, unsigned char level, char *datadir);
void loadHQGraphics(unsigned char episode, unsigned char level, const std::string& datadir);
void unloadHQGraphics();
private:

View File

@@ -13,6 +13,7 @@
#include "fileio.h"
#include "keen.h"
#include "keenext.h"
#include "StringUtils.h"
#include "CLogFile.h"
//#include "vorticon/CEGAGraphics.h"
@@ -58,19 +59,15 @@ char CLatch::loadHeader(int episode, const char *path)
FILE *headfile;
unsigned long SpriteTableRAMSize;
unsigned long BitmapTableRAMSize;
char buf[12];
std::string buf;
int i,j,k;
char fname[80];
char buffer[256];
std::string fname;
std::string buffer;
memset(buffer,0,256);
memset(fname,0,80);
buffer = formatPathString(path);
buffer += "egahead.ck";
formatPathString(buffer,path);
strcat(buffer,"egahead.ck");
sprintf(fname, "%s%d", buffer,episode);
fname = buffer + itoa(episode);
/*CEGAGraphics *EGAGraphics;
@@ -80,14 +77,14 @@ char CLatch::loadHeader(int episode, const char *path)
delete EGAGraphics;*/
headfile = fopen(fname, "rb");
headfile = fopen(fname.c_str(), "rb");
if (!headfile)
{
g_pLogFile->ftextOut("latch_loadheader(): unable to open '%s'.<br>", fname);
g_pLogFile->ftextOut("latch_loadheader(): unable to open '%s'.<br>", fname.c_str());
return 1;
}
g_pLogFile->ftextOut("latch_loadheader(): reading main header from '%s'...<br>", fname);
g_pLogFile->ftextOut("latch_loadheader(): reading main header from '%s'...<br>", fname.c_str());
// read the main header data from EGAHEAD
LatchHeader.LatchPlaneSize = fgetl(headfile);
@@ -135,7 +132,7 @@ char CLatch::loadHeader(int episode, const char *path)
return 1;
}
g_pLogFile->ftextOut("latch_loadheader(): Reading sprite table from '%s'...<br>", fname);
g_pLogFile->ftextOut("latch_loadheader(): Reading sprite table from '%s'...<br>", fname.c_str());
fseek(headfile, LatchHeader.OffSpriteTable, SEEK_SET);
for(i=0;i<LatchHeader.NumSprites;i++)
@@ -172,7 +169,7 @@ char CLatch::loadHeader(int episode, const char *path)
return 1;
}
g_pLogFile->ftextOut("latch_loadheader(): reading bitmap table from '%s'...<br>", fname);
g_pLogFile->ftextOut("latch_loadheader(): reading bitmap table from '%s'...<br>", fname.c_str());
fseek(headfile, LatchHeader.OffBitmapTable, SEEK_SET);
@@ -191,7 +188,7 @@ char CLatch::loadHeader(int episode, const char *path)
// print the bitmap info to the console for debug
for(j=0;j<8;j++) buf[j] = BitmapTable[i].Name[j];
buf[j] = 0;
g_pLogFile->ftextOut(" Bitmap '%s': %dx%d at offset %04x. RAMAllocSize=0x%04x<br>", buf,BitmapTable[i].Width,BitmapTable[i].Height,BitmapTable[i].Offset,BitmapBufferRAMSize);
g_pLogFile->ftextOut(" Bitmap '%s': %dx%d at offset %04x. RAMAllocSize=0x%04x<br>", buf.c_str(),BitmapTable[i].Width,BitmapTable[i].Height,BitmapTable[i].Offset,BitmapBufferRAMSize);
}
BitmapBufferRAMSize++;
@@ -206,26 +203,24 @@ char CLatch::load(int episode, const char *path)
{
FILE *latchfile;
unsigned long plane1, plane2, plane3, plane4;
char fname[80];
std::string fname;
int x,y,t,b,c,p;
char *bmdataptr;
unsigned long RawDataSize;
//unsigned char ch;
char buffer[256];
std::string buffer;
formatPathString(buffer,path);
buffer = formatPathString(path);
buffer += "egalatch.ck";
fname = buffer + itoa(episode);
strcat(buffer,"egalatch.ck");
g_pLogFile->ftextOut("latch_loadlatch(): Opening file '%s'.<br>", fname.c_str());
sprintf(fname, "%s%c", buffer,episode + '0');
g_pLogFile->ftextOut("latch_loadlatch(): Opening file '%s'.<br>", fname);
latchfile = fopen(fname, "rb");
latchfile = fopen(fname.c_str(), "rb");
if (!latchfile)
{
g_pLogFile->ftextOut("latch_loadlatch(): Unable to open '%s'!<br>", fname);
g_pLogFile->ftextOut("latch_loadlatch(): Unable to open '%s'!<br>", fname.c_str());
return 1;
}
@@ -266,7 +261,7 @@ char buffer[256];
plane4 = (LatchHeader.LatchPlaneSize * 3);
// ** read the 8x8 tiles **
g_pLogFile->ftextOut("latch_loadlatch(): Decoding 8x8 tiles...<br>", fname);
g_pLogFile->ftextOut("latch_loadlatch(): Decoding 8x8 tiles...<br>", fname.c_str());
// set up the getbit() function
@@ -309,7 +304,7 @@ char buffer[256];
delete Planes;
// ** read the 16x16 tiles **
g_pLogFile->ftextOut("latch_loadlatch(): Decoding 16x16 tiles...<br>", fname);
g_pLogFile->ftextOut("latch_loadlatch(): Decoding 16x16 tiles...<br>", fname.c_str());
// set up the getbit() function
Planes = new CPlanes(plane1 + LatchHeader.Off16Tiles, \
@@ -354,7 +349,7 @@ char buffer[256];
return 1;
}
g_pLogFile->ftextOut("latch_loadlatch(): Decoding bitmaps...<br>", fname);
g_pLogFile->ftextOut("latch_loadlatch(): Decoding bitmaps...<br>", fname.c_str());
// set up the getbit() function
Planes = new CPlanes(plane1 + LatchHeader.OffBitmaps, \
@@ -419,24 +414,22 @@ char CLatch::loadSprites(int episode, const char *path)
{
FILE *spritfile;
unsigned long plane1, plane2, plane3, plane4, plane5;
char fname[80];
std::string fname;
int x,y,s,c,p;
unsigned long RawDataSize;
char buffer[256];
std::string buffer;
CPlanes *Planes;
formatPathString(buffer,path);
buffer = formatPathString(path);
buffer += "egasprit.ck";
fname = buffer + itoa(episode);
strcat(buffer,"egasprit.ck");
g_pLogFile->ftextOut("latch_loadsprites(): Opening file '%s'.<br>", fname.c_str());
sprintf(fname, "%s%c", buffer,episode + '0');
g_pLogFile->ftextOut("latch_loadsprites(): Opening file '%s'.<br>", fname);
spritfile = fopen(fname, "rb");
spritfile = fopen(fname.c_str(), "rb");
if (!spritfile)
{
g_pLogFile->ftextOut("latch_loadsprites(): Unable to open '%s'!<br>", fname);
g_pLogFile->ftextOut("latch_loadsprites(): Unable to open '%s'!<br>", fname.c_str());
return 1;
}
@@ -475,7 +468,7 @@ CPlanes *Planes;
plane5 = (LatchHeader.SpritePlaneSize * 4);
// ** read the sprites **
g_pLogFile->ftextOut("latch_loadsprites(): Decoding sprites...<br>", fname);
g_pLogFile->ftextOut("latch_loadsprites(): Decoding sprites...<br>", fname.c_str());
// set up the getbit() function
Planes = new CPlanes(plane1 + LatchHeader.OffSprites, \

168
src/CVec.h Normal file
View File

@@ -0,0 +1,168 @@
/////////////////////////////////////////
//
// OpenLieroX
//
// Auxiliary Software class library
//
// based on the work of JasonB
// enhanced by Dark Charlie and Albert Zeyer
//
// code under LGPL
//
/////////////////////////////////////////
// 2D Vector / Matrix class
// Created 20/11/01
// By Jason Boettcher
// enhanced by Albert Zeyer
#ifndef __CVEC_H__
#define __CVEC_H__
#include <cmath>
template<typename _T>
struct VectorD2 {
// Constructor
VectorD2() : x(0), y(0) {}
VectorD2(_T _x, _T _y) : x(_x), y(_y) {}
// Attributes
_T x, y;
// Methods
template<typename _T2>
VectorD2(const _T2& cp) {
x = (_T)cp.x; y = (_T)cp.y;
}
float GetLength() const { return sqrtf((float)x*x + (float)y*y); }
_T GetLength2() const { return x*x + y*y; };
float GetAngle() const { return (float)atan2((float)y,(float)x); }
VectorD2 Normalize() { return *this/GetLength(); }
_T Scalar(const VectorD2& vec) const { return x*vec.x + y*vec.y; }
VectorD2 orthogonal() const { return VectorD2(y, -x); }
_T Cross(const VectorD2& oth) const { return x * oth.y - y * oth.x; }
// Overloads
VectorD2 operator*(const float scalar) const {
return VectorD2(x*scalar,y*scalar);
}
VectorD2 operator*(const int scalar) const {
return VectorD2(x*scalar,y*scalar);
}
/*
VectorD2 operator*(const VectorD2& vec) const {
// WARNING: this doesn't make any sense (in most 'mathematical' cases)
// TODO: why is it here? I would expect dot product or cross product...
return VectorD2(x*vec.x,y*vec.y);
}
*/
VectorD2 operator/(const float scalar) const {
return VectorD2(x/scalar,y/scalar);
}
VectorD2 operator/(const int scalar) const {
return VectorD2(x/scalar,y/scalar);
}
VectorD2 operator+(const VectorD2& vec) const {
return VectorD2(x+vec.x,y+vec.y);
}
VectorD2 operator-(const VectorD2& vec) const {
return VectorD2(x-vec.x,y-vec.y);
}
VectorD2 operator-() const {
return VectorD2(-x,-y);
}
VectorD2& operator+=(const VectorD2& vec) {
x+=vec.x; y+=vec.y;
return *this;
}
VectorD2& operator-=(const VectorD2& vec) {
x-=vec.x; y-=vec.y;
return *this;
}
VectorD2& operator*=(const float scalar) {
x*=scalar; y*=scalar;
return *this;
}
VectorD2& operator*=(const int scalar) {
x*=scalar; y*=scalar;
return *this;
}
template<typename _T2>
bool operator<(const VectorD2<_T2> & op) const {
return ((y == op.y && (x < op.x))
|| y < op.y);
}
template<typename _T2>
bool operator==(const VectorD2<_T2> & op) const {
return (x==op.x && y==op.y);
}
template<typename _T2>
bool operator!=(const VectorD2<_T2> & op) const {
return (x!=op.x || y!=op.y);
}
template<typename _T2>
bool operator<=(const VectorD2<_T2> & op) const {
return ((*this < op) || (*this == op));
}
};
template<typename _T>
struct VectorD2__absolute_less {
VectorD2<_T> zero;
VectorD2__absolute_less(VectorD2<_T> z = VectorD2<_T>(0,0)) : zero(z) {}
bool operator()(const VectorD2<_T> v1, const VectorD2<_T> v2) const {
return (v1-zero).GetLength2() < (v2-zero).GetLength2();
}
};
typedef VectorD2<float> CVec;
template<typename _T>
struct MatrixD2 {
VectorD2<_T> v1;
VectorD2<_T> v2;
MatrixD2() {}
MatrixD2(_T f) { v1.x = f; v2.y = f; }
MatrixD2(_T x1, _T y1, _T x2, _T y2) : v1(x1,y1), v2(x2,y2) {}
MatrixD2(const VectorD2<_T>& _v1, const VectorD2<_T>& _v2) : v1(_v1), v2(_v2) {}
static MatrixD2 Rotation(_T x, _T y) { return MatrixD2(x,y,-y,x); }
template<typename _T2> bool operator==(const MatrixD2<_T2>& m) const { return v1 == m.v1 && v2 == m.v2; }
template<typename _T2> bool operator!=(const MatrixD2<_T2>& m) const { return !(*this == m); }
VectorD2<_T> operator*(const VectorD2<_T>& v) const {
return VectorD2<_T>( v1.x * v.x + v2.x * v.y, v1.y * v.x + v2.y * v.y );
}
MatrixD2<_T> operator*(const MatrixD2<_T>& m) const {
return MatrixD2<_T>( *this * m.v1, *this * m.v2 );
}
MatrixD2<_T>& operator*=(const MatrixD2<_T>& m) {
return *this = *this * m;
}
};
#endif // __CVEC_H__

133
src/Color.h Normal file
View File

@@ -0,0 +1,133 @@
/*
OpenLieroX
color type and related functions
code under LGPL
created 10-01-2007
*/
#ifndef __COLOR_H__
#define __COLOR_H__
#include <SDL.h>
#include <cassert>
#include "MathLib.h"
///////////////////
// If you want to use the adress of some Uint32 directly with memcpy or similar, use this
inline Uint32 SDLColourToNativeColour(Uint32 pixel, short bpp) {
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
return (pixel << (32 - 8 * bpp));
#else
return pixel;
#endif
}
/////////////////
// If you copied some data directly with memcpy into an Uint32, use this
inline Uint32 NativeColourToSDLColour(Uint32 pixel, short bpp) {
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
return (pixel >> (32 - 8 * bpp));
#else
return pixel;
#endif
}
///////////////
// Get the specified component from the pixel (grabbed from SDL)
inline Uint8 GetR(Uint32 pixel, SDL_PixelFormat *fmt) {
return (Uint8)((((pixel & fmt->Rmask) >> fmt->Rshift) << fmt->Rloss) +
(((pixel & fmt->Rmask) >> fmt->Rshift) >> (8 - (fmt->Rloss << 1))));
}
inline Uint8 GetG(Uint32 pixel, SDL_PixelFormat *fmt) {
return (Uint8)((((pixel & fmt->Gmask) >> fmt->Gshift) << fmt->Gloss) +
(((pixel & fmt->Gmask) >> fmt->Gshift) >> (8 - (fmt->Gloss << 1))));
}
inline Uint8 GetB(Uint32 pixel, SDL_PixelFormat *fmt) {
return (Uint8)((((pixel & fmt->Bmask) >> fmt->Bshift) << fmt->Bloss) +
(((pixel & fmt->Bmask) >> fmt->Bshift) >> (8 - (fmt->Bloss << 1))));
}
inline Uint8 GetA(Uint32 pixel, SDL_PixelFormat *fmt) {
return (Uint8)((((pixel & fmt->Amask) >> fmt->Ashift) << fmt->Aloss) +
(((pixel & fmt->Amask) >> fmt->Ashift) >> (8 - (fmt->Aloss << 1))));
}
extern SDL_PixelFormat* mainPixelFormat;
inline SDL_PixelFormat* getMainPixelFormat() {
return mainPixelFormat;
}
///////////////
// Returns true if the two colors are the same, ignoring the alpha
// HINT: both colors have to be in the same pixelformat
inline bool EqualRGB(Uint32 p1, Uint32 p2, SDL_PixelFormat* fmt) {
return ((p1|fmt->Amask) == (p2|fmt->Amask));
}
///////////////
// Creates a int colour based on the 3 components
// HINT: format is that one from videosurface!
inline Uint32 MakeColour(Uint8 r, Uint8 g, Uint8 b) {
return SDL_MapRGB(getMainPixelFormat(), r, g, b);
}
///////////////
// Creates a int colour based on the 4 components
// HINT: format is that one from videosurface!
inline Uint32 MakeColour(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
return SDL_MapRGBA(getMainPixelFormat(), r, g, b, a);
}
// Device-independent color
struct Color {
Color() : r(0), g(0), b(0), a(SDL_ALPHA_OPAQUE) {}
Color(Uint8 _r, Uint8 _g, Uint8 _b) : r(_r), g(_g), b(_b), a(SDL_ALPHA_OPAQUE) {}
Color(Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a) : r(_r), g(_g), b(_b), a(_a) {}
Color(SDL_PixelFormat *f, Uint32 cl) { SDL_GetRGBA(cl, f, &r, &g, &b, &a); }
explicit Color(Uint32 cl) { set(getMainPixelFormat(), cl); }
Color(const SDL_Color& cl) : r(cl.r), g(cl.g), b(cl.b), a(SDL_ALPHA_OPAQUE) {}
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;
Uint32 get() const { return get(getMainPixelFormat()); }
Uint32 get(SDL_PixelFormat *f) const { return SDL_MapRGBA(f, r, g, b, a); }
Uint32 getDefault() const { return (Uint32(r) << 24) | (Uint32(g) << 16) | (Uint32(b) << 8) | Uint32(a); }
Color derived(Sint16 _r, Sint16 _g, Sint16 _b, Sint16 _a) const {
return Color(
Uint8(CLAMP(_r + r, 0, 255)),
Uint8(CLAMP(_g + g, 0, 255)),
Uint8(CLAMP(_b + b, 0, 255)),
Uint8(CLAMP(_a + a, 0, 255)));
}
void set(SDL_PixelFormat *f, Uint32 cl) { SDL_GetRGBA(cl, f, &r, &g, &b, &a); }
bool operator == ( const Color & c ) const { return r == c.r && g == c.g && b == c.b && a == c.a; };
bool operator != ( const Color & c ) const { return ! ( *this == c ); };
Color operator * ( float f ) const { return Color( Uint8(CLAMP(r*f,0.0f,255.0f)), Uint8(CLAMP(g*f,0.0f,255.0f)), Uint8(CLAMP(b*f,0.0f,255.0f)), a ); };
Color operator + ( const Color & c ) const { return Color( (Uint8)CLAMP(Uint16(r)+c.r,0,255), (Uint8)CLAMP(Uint16(g)+c.g,0,255), (Uint8)CLAMP(Uint16(b)+c.b,0,255), (Uint8)(Uint16(a)+c.a)/2 ); };
bool operator<(const Color& c) const {
if(r != c.r) return r < c.r;
if(g != c.g) return g < c.g;
if(b != c.b) return b < c.b;
return a < c.a;
}
Uint8& operator[](int i) { switch(i) { case 0: return r; case 1: return g; case 2: return b; case 3: return a; default: assert(false); } return *((Uint8*)NULL); }
Uint8 operator[](int i) const { switch(i) { case 0: return r; case 1: return g; case 2: return b; case 3: return a; default: assert(false); } return 0; }
};
#endif

540
src/CrashHandler.cpp Normal file
View File

@@ -0,0 +1,540 @@
/*
OpenLieroX CrashHandler
registers a crash handler in the OS and handles the crashes
code under LGPL
created 09-07-2008 by Albert Zeyer
*/
#include "CrashHandler.h"
#include "StringUtils.h"
#include "Debug.h"
#ifndef WIN32
#include <setjmp.h>
sigjmp_buf longJumpBuffer;
#endif
// note: important to have const char* here because std::string is too dynamic, could be screwed up when returning
void SetCrashHandlerReturnPoint(const char* name) {
#ifndef WIN32
if(sigsetjmp(longJumpBuffer, true) != 0) {
hints << "returned from sigsetjmp in " << name << endl;
if(/*tLXOptions->bFullscreen*/ false) {
notes << "we are in fullscreen, going to window mode now" << endl;
// tLXOptions->bFullscreen = false;
// doSetVideoModeInMainThread();
notes << "back in window mode" << endl;
}
}
#endif
}
//
// WIN 32
//
#if defined(_MSC_VER)
#define itoa _itoa
#include <DbgHelp.h>
#include <ShlObj.h>
#include "FindFile.h" // for IsFileAvailable and mkdir
LONG WINAPI CustomUnhandledExceptionFilter(PEXCEPTION_POINTERS pExInfo);
// Crash handling
class CrashHandlerImpl : public CrashHandler {
public:
CrashHandlerImpl() {
#ifdef _DEBUG
#ifdef USE_DEFAULT_MSC_DELEAKER
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
#endif // _DEBUG
SetUnhandledExceptionFilter(CustomUnhandledExceptionFilter);
notes << "Win32 Exception Filter installed" << endl;
}
};
extern void OlxWriteCoreDump_Win32(const char* fileName, PEXCEPTION_POINTERS pExInfo);
///////////////////
// This callback function is called whenever an unhandled exception occurs
LONG WINAPI CustomUnhandledExceptionFilter(PEXCEPTION_POINTERS pExInfo)
{
// Get the path
char buf[1024];
if (!SHGetSpecialFolderPath(NULL, buf, CSIDL_PERSONAL, false)) {
buf[0] = '\0';
strcpy(buf, "bug_reports");
} else {
size_t len = strnlen(buf, sizeof(buf));
if (buf[len - 1] != '\\' && buf[len - 1] != '/')
strncat(buf, "\\OpenLieroX", sizeof(buf));
else
strncat(buf, "OpenLieroX", sizeof(buf));
CreateDirectory(buf, NULL); // If the crash occurs at first startup, the OpenLieroX dir doesn't have to exist
strncat(buf, "\\bug_reports", sizeof(buf));
fix_markend(buf);
}
CreateDirectory(buf, NULL);
strncat(buf, "\\", sizeof(buf));
// Get the file name
char checkname[1024];
char tmp[32];
FILE *f = NULL;
for (int i=1;1;i++) {
itoa(i, tmp, 10);
fix_markend(tmp);
strncpy(checkname, buf, sizeof(checkname));
strncat(checkname, "report", sizeof(checkname));
strncat(checkname, tmp, sizeof(checkname));
strncat(checkname, ".dmp", sizeof(checkname));
f = fopen(checkname, "rb");
if (!f)
break;
fclose(f);
}
OlxWriteCoreDump_Win32(checkname, pExInfo);
// Try to free the cache, it eats a lot of memory
__try {
cCache.Clear();
}
__except(EXCEPTION_EXECUTE_HANDLER) {}
// Quit SDL
__try {
SDL_Quit();
}
__except(EXCEPTION_EXECUTE_HANDLER) {}
// End conversation logging (to make the XML valid)
__try {
if (convoLogger)
delete convoLogger;
}
__except(EXCEPTION_EXECUTE_HANDLER) {}
// Close all opened files
fcloseall();
strncpy(&buf[1], checkname, sizeof(buf) - 1);
buf[0] = '\"';
strncat(buf, "\"", sizeof(buf));
fix_markend(buf);
// If ded server is running as service user won't see any dialog anyway
if (!bDedicated)
ShellExecute(NULL,"open","BugReport.exe",buf,NULL,SW_SHOWNORMAL);
// If running as a dedicated server, restart the application (there usually isn't any person sitting
// at the computer to fix this problem)
// If ded server is running as service it's restarted automatically
#ifdef DEDICATED_ONLY
//ShellExecute(NULL, "open", GetAppPath(), "-dedicated", NULL, SW_SHOWNORMAL);
#else
if (bDedicated) {
//ShellExecute(NULL, "open", GetAppPath(), "-dedicated", NULL, SW_SHOWNORMAL);
}
#endif
return EXCEPTION_EXECUTE_HANDLER;
}
#elif !defined(WIN32) // MacOSX, Linux, Unix
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <unistd.h>
#if defined(__linux__) || defined(__APPLE__)
// TODO: why is execinfo needed here? at least on MacOSX, it's not needed here
//#include <execinfo.h>
/* get REG_EIP / REG_RIP from ucontext.h */
#include <ucontext.h>
#endif
#ifndef EIP
#define EIP 14
#endif
#if (defined (__x86_64__))
#ifndef REG_RIP
#define REG_RIP REG_INDEX(rip) /* seems to be 16 */
#endif
#endif
struct signal_def { char name[10]; int id; char description[40]; } ;
static signal_def signal_data[] =
{
{ "SIGHUP", SIGHUP, "Hangup (POSIX)" },
{ "SIGINT", SIGINT, "Interrupt (ANSI)" },
{ "SIGQUIT", SIGQUIT, "Quit (POSIX)" },
{ "SIGILL", SIGILL, "Illegal instruction (ANSI)" },
{ "SIGTRAP", SIGTRAP, "Trace trap (POSIX)" },
{ "SIGABRT", SIGABRT, "Abort (ANSI)" },
{ "SIGIOT", SIGIOT, "IOT trap (4.2 BSD)" },
{ "SIGBUS", SIGBUS, "BUS error (4.2 BSD)" },
{ "SIGFPE", SIGFPE, "Floating-point exception (ANSI)" },
{ "SIGKILL", SIGKILL, "Kill, unblockable (POSIX)" },
{ "SIGUSR1", SIGUSR1, "User-defined signal 1 (POSIX)" },
{ "SIGSEGV", SIGSEGV, "Segmentation violation (ANSI)" },
{ "SIGUSR2", SIGUSR2, "User-defined signal 2 (POSIX)" },
{ "SIGPIPE", SIGPIPE, "Broken pipe (POSIX)" },
{ "SIGALRM", SIGALRM, "Alarm clock (POSIX)" },
{ "SIGTERM", SIGTERM, "Termination (ANSI)" },
//{ "SIGSTKFLT", SIGSTKFLT, "Stack fault" },
{ "SIGCHLD", SIGCHLD, "Child status has changed (POSIX)" },
//{ "SIGCLD", SIGCLD, "Same as SIGCHLD (System V)" },
{ "SIGCONT", SIGCONT, "Continue (POSIX)" },
{ "SIGSTOP", SIGSTOP, "Stop, unblockable (POSIX)" },
{ "SIGTSTP", SIGTSTP, "Keyboard stop (POSIX)" },
{ "SIGTTIN", SIGTTIN, "Background read from tty (POSIX)" },
{ "SIGTTOU", SIGTTOU, "Background write to tty (POSIX)" },
{ "SIGURG", SIGURG, "Urgent condition on socket (4.2 BSD)" },
{ "SIGXCPU", SIGXCPU, "CPU limit exceeded (4.2 BSD)" },
{ "SIGXFSZ", SIGXFSZ, "File size limit exceeded (4.2 BSD)" },
{ "SIGVTALRM", SIGVTALRM, "Virtual alarm clock (4.2 BSD)" },
{ "SIGPROF", SIGPROF, "Profiling alarm clock (4.2 BSD)" },
{ "SIGWINCH", SIGWINCH, "Window size change (4.3 BSD, Sun)" },
{ "SIGIO", SIGIO, "I/O now possible (4.2 BSD)" },
//{ "SIGPOLL", SIGPOLL, "Pollable event occurred (System V)" },
//{ "SIGPWR", SIGPWR, "Power failure restart (System V)" },
{ "SIGSYS", SIGSYS, "Bad system call" },
};
static int handlerSignalList[] = {
SIGSEGV, SIGTRAP, SIGABRT, SIGHUP, SIGBUS, SIGILL, SIGFPE, SIGSYS, SIGUSR1, SIGUSR2
};
typedef const char * cchar;
bool CrashHandler_RecoverAfterCrash = false;
class CrashHandlerImpl : public CrashHandler {
public:
CrashHandlerImpl() {
if(CrashHandler_RecoverAfterCrash) {
setSignalHandlers();
DumpCallstack(NullOut); // dummy call to force loading dynamic lib at this point (with sane heap) for backtrace and friends
notes << "registered simple resuming signal handler" << endl;
}
else
notes << "no signal handler with these settings" << endl;
}
static void setSignalHandlers() {
struct sigaction sa;
sa.sa_sigaction = SimpleSignalHandler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
for (unsigned int i = 0; i < sizeof(handlerSignalList) / sizeof(int); i++)
sigaction(handlerSignalList[i], &sa, NULL);
}
static void unsetSignalHandlers() {
for (unsigned int i = 0; i < sizeof(handlerSignalList) / sizeof(int); i++)
signal(handlerSignalList[i], SIG_DFL);
}
void enable() { if(CrashHandler_RecoverAfterCrash) setSignalHandlers(); }
void disable() { unsetSignalHandlers(); }
static void SimpleSignalHandler(int signr, siginfo_t *info, void *secret) {
signal(signr, SIG_IGN); // discard all remaining signals
signal_def *d = NULL;
for (unsigned int i = 0; i < sizeof(signal_data) / sizeof(signal_def); i++)
if (signr == signal_data[i].id)
{ d = &signal_data[i]; break; }
if (d)
printf("Got signal 0x%02X (%s): %s\n", signr, d->name, d->description);
else
printf("Got signal 0x%02X\n", signr);
/*
see this article for further details: (thanks also for some code snippets)
http://www.linuxjournal.com/article/6391 */
void *pnt = NULL;
#if defined(__APPLE__)
# if defined(__x86_64__)
ucontext_t* uc = (ucontext_t*) secret;
pnt = (void*) uc->uc_mcontext->__ss.__rip ;
# elif defined(__hppa__)
ucontext_t* uc = (ucontext_t*) secret;
pnt = (void*) uc->uc_mcontext.sc_iaoq[0] & ~0x3UL ;
# elif (defined (__ppc__)) || (defined (__powerpc__))
ucontext_t* uc = (ucontext_t*) secret;
# if __DARWIN_UNIX03
pnt = (void*) uc->uc_mcontext->__ss.__srr0 ;
# else
pnt = (void*) uc->uc_mcontext->ss.srr0 ;
# endif
# elif defined(__sparc__)
struct sigcontext* sc = (struct sigcontext*) secret;
# if __WORDSIZE == 64
pnt = (void*) scp->sigc_regs.tpc ;
# else
pnt = (void*) scp->si_regs.pc ;
# endif
# elif defined(__i386__)
ucontext_t* uc = (ucontext_t*) secret;
# if __DARWIN_UNIX03
pnt = (void*) uc->uc_mcontext->__ss.__eip ;
# else
pnt = (void*) uc->uc_mcontext->ss.eip ;
# endif
# else
# warning mcontext is not defined for this arch, thus a dumped backtrace could be crippled
# endif
#elif defined(__linux__)
# if defined(__x86_64__)
ucontext_t* uc = (ucontext_t*) secret;
pnt = (void*) uc->uc_mcontext.gregs[REG_RIP] ;
# elif defined(__hppa__)
ucontext_t* uc = (ucontext_t*) secret;
pnt = (void*) uc->uc_mcontext.sc_iaoq[0] & ~0x3UL ;
# elif (defined (__ppc__)) || (defined (__powerpc__))
ucontext_t* uc = (ucontext_t*) secret;
pnt = (void*) uc->uc_mcontext.regs->nip ;
# elif defined(__sparc__)
struct sigcontext* sc = (struct sigcontext*) secret;
# if __WORDSIZE == 64
pnt = (void*) scp->sigc_regs.tpc ;
# else
pnt = (void*) scp->si_regs.pc ;
# endif
# elif defined(__i386__)
ucontext_t* uc = (ucontext_t*) secret;
pnt = (void*) uc->uc_mcontext.gregs[REG_EIP] ;
# else
# warning mcontext is not defined for this arch, thus a dumped backtrace could be crippled
# endif
#else
# warning mcontest is not defined for this system, thus a dumped backtraced could be crippled
#endif
/* potentially correct for other archs:
* alpha: ucp->m_context.sc_pc
* arm: ucp->m_context.ctx.arm_pc
* ia64: ucp->m_context.sc_ip & ~0x3UL
* mips: ucp->m_context.sc_pc
* s390: ucp->m_context.sregs->regs.psw.addr
*/
if (signr == SIGSEGV || signr == SIGBUS)
printf("Faulty address is %p, called from %p\n", info->si_addr, pnt);
/* The first two entries in the stack frame chain when you
* get into the signal handler contain, respectively, a
* return address inside your signal handler and one inside
* sigaction() in libc. The stack frame of the last function
* called before the signal (which, in case of fault signals,
* also is the one that supposedly caused the problem) is lost.
*/
/* the third parameter to the signal handler points to an
* ucontext_t structure that contains the values of the CPU
* registers when the signal was raised.
*/
// WARNING: dont use cout here in this function, it sometimes screws the cout up
// look at signal(2) for a list of safe functions
DumpCallstackPrintf(pnt);
#ifdef DEBUG
// commented out for now because it still doesn't work that good
//OlxWriteCoreDump(d ? d->name : NULL);
#endif
if(!CrashHandler_RecoverAfterCrash)
{
fflush(stdout);
abort();
#ifdef DEBUG
// raise(SIGQUIT);
#else
// exit(-1);
#endif
return;
}
setSignalHandlers(); // reset handler
printf("resuming ...\n");
fflush(stdout);
setSignalHandlers();
siglongjmp(longJumpBuffer, 1); // jump back to main loop, maybe we'll be able to continue somehow
}
/////////////////////////////////////////////////////////////////////////////
//
// Attempts to cleanup and call drkonqi to process the crash
// (code taken from Lgi (LGPL) and modified)
//
static void DrKonqiSignalHandler(int Sig) {
// Don't get into an infinite loop
signal(SIGSEGV, SIG_DFL);
// Our pid
int MyPid = getpid();
printf("CrashHandler trigger MyPid=%i\n", MyPid);
// Fork to run the crash handler
pid_t Pid = fork();
if (Pid <= 0)
{
// Pass our state down to the crash handler...
int Args = 0;
cchar Arg[32];
memset(Arg, 0, sizeof(Arg));
char SigName[16], PidName[16], Version[32];
// TODO: sprintf allocates memory on the heap internally, is it safe to do it here?
sprintf(SigName, "%i", Sig);
sprintf(PidName, "%i", MyPid);
// strcpy( Version, GetFullGameName() );
Arg[Args++] = "drkonqi";
//Arg[Args++] = "--display";
//Arg[Args++] = XDisplayString(o.XDisplay());
Arg[Args++] = "--appname";
// Arg[Args++] = GetFullGameName();
Arg[Args++] = "--programname";
// Arg[Args++] = GetFullGameName();
Arg[Args++] = "--appversion";
Arg[Args++] = Version;
Arg[Args++] = "--apppath";
// Arg[Args++] = GetAppPath(); // should be save to call
Arg[Args++] = "--signal";
Arg[Args++] = SigName;
Arg[Args++] = "--pid";
Arg[Args++] = PidName;
Arg[Args++] = "--bugaddress";
Arg[Args++] = "openlierox@az2000.de";
setgid(getgid());
setuid(getuid());
execvp("drkonqi", (char* const*)Arg);
}
else
{
// Wait for child to exit
waitpid(Pid, NULL, 0);
_exit(253);
}
}
// Attempts to cleanup and call bug-buddy to process the crash
static void BugBuddySignalHandler(int Sig) {
// Don't get into an infinite loop
signal(SIGSEGV, SIG_DFL);
// Our pid
int MyPid = getpid();
printf("CrashHandler trigger MyPid=%i\n", MyPid);
// Fork to run the crash handler
pid_t Pid = fork();
if (Pid <= 0)
{
// Pass our state down to the crash handler...
int Args = 0;
cchar Arg[32];
memset(Arg, 0, sizeof(Arg));
char SigName[16], PidName[16], Version[40];
sprintf(SigName, "%i", Sig);
sprintf(PidName, "%i", MyPid);
// strcpy( Version, GetFullGameName() );
Arg[Args++] = "bug-buddy";
//Arg[Args++] = "--display";
//Arg[Args++] = XDisplayString(o.XDisplay());
Arg[Args++] = "--appname";
Arg[Args++] = Version;
Arg[Args++] = "--pid";
Arg[Args++] = PidName;
Arg[Args++] = "--name";
Arg[Args++] = "Albert Zeyer";
Arg[Args++] = "--email";
Arg[Args++] = "openlierox@az2000.de";
setgid(getgid());
setuid(getuid());
execvp("bug-buddy", (char* const*)Arg);
}
else
{
// Wait for child to exit
waitpid(Pid, NULL, 0);
_exit(253);
}
}
};
#else
class CrashHandlerImpl : public CrashHandler {
public:
CrashHandlerImpl() {
notes << "Dummy CrashHandler implementation" << endl;
}
};
#endif
CrashHandlerImpl* crashHandlerInstance = NULL;
void CrashHandler::init() {
if(crashHandlerInstance) {
warnings << "CrashHandler tried to init twice" << endl;
return;
}
notes << "Installing CrashHandler .. ";
crashHandlerInstance = new CrashHandlerImpl();
}
void CrashHandler::uninit() {
if(crashHandlerInstance) {
delete crashHandlerInstance;
crashHandlerInstance = NULL;
}
}
CrashHandler* CrashHandler::get() {
return crashHandlerInstance;
}

25
src/CrashHandler.h Normal file
View File

@@ -0,0 +1,25 @@
/*
OpenLieroX CrashHandler
registers a crash handler in the OS and handles the crashes
code under LGPL
created 09-07-2008 by Albert Zeyer
*/
#ifndef __CRASHHANDLER_H__
#define __CRASHHANDLER_H__
class CrashHandler {
public:
virtual ~CrashHandler() {}
static void init();
static void uninit();
static CrashHandler* get();
// you can temporarly disable it (and then enable it again)
virtual void disable() {}
virtual void enable() {}
};
#endif

584
src/Debug.cpp Normal file
View File

@@ -0,0 +1,584 @@
/*
* Debug.cpp
* OpenLieroX
*
* Created by Albert Zeyer on 01.01.09.
* code under LGPL
*
*/
#include "Debug.h"
#include "StringUtils.h"
#include "CrashHandler.h"
#include <time.h>
#ifdef WIN32
void RaiseDebugger() {
#ifdef DEBUG
// HINT: ignored when not in debugger
// If it just does nothing then, remove the surrounding #ifdef DEBUG
// I read about a Win32's IsDebuggerPresent() function, perhaps you should use that one here.
__asm { int 3 };
#endif
}
#else
#if defined(__APPLE__)
#include <cassert>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
// Based on Apple's recommended method as described in
// http://developer.apple.com/qa/qa2004/qa1361.html
static bool AmIBeingDebugged()
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
{
// Initialize mib, which tells sysctl what info we want. In this case,
// we're looking for information about a specific process ID.
int mib[] =
{
CTL_KERN,
KERN_PROC,
KERN_PROC_PID,
getpid()
};
// Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE. The source and
// binary interfaces may change.
struct kinfo_proc info;
size_t info_size = sizeof ( info );
int sysctl_result = sysctl ( mib, sizeof(mib) / sizeof(*mib), &info, &info_size, NULL, 0 );
if ( sysctl_result != 0 )
return false;
// This process is being debugged if the P_TRACED flag is set.
return ( info.kp_proc.p_flag & P_TRACED ) != 0;
}
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstring>
#include <unistd.h>
static bool AmIBeingDebugged() {
// We can look in /proc/self/status for TracerPid. We are likely used in crash
// handling, so we are careful not to use the heap or have side effects.
int status_fd = open("/proc/self/status", O_RDONLY);
if (status_fd == -1)
return false;
// We assume our line will be in the first 1024 characters and that we can
// read this much all at once. In practice this will generally be true.
// This simplifies and speeds up things considerably.
char buf[1024];
ssize_t num_read = read(status_fd, buf, sizeof(buf));
fix_markend(buf);
close(status_fd);
if (num_read <= 0) return false;
const char* searchStr = "TracerPid:\t";
const char* f = strstr(buf, searchStr);
if(f == NULL) return false;
// Our pid is 0 without a debugger, assume this for any pid starting with 0.
f += strlen(searchStr);
return f < &buf[num_read] && *f != '0';
}
#endif // OSX/LINUX
#include <signal.h>
void RaiseDebugger() {
if(AmIBeingDebugged()) {
printf("I am being debugged, raising debugger ...\n");
CrashHandler::get()->disable();
// TODO: We need a way to set another ucontext here. (And that should be specified via a parameter
// to RaiseDebugger().) E.g. when we use this function in the debugger thread, we want to set the
// ucontext of the main loop thread.
raise(SIGABRT);
CrashHandler::get()->enable();
} else
printf("I am not being debugged, ignoring debugger raise.\n");
}
#endif
#ifdef WIN32
#include "AuxLib.h" // for Windows.h
#include <DbgHelp.h>
#include <ShlObj.h>
#include "LieroX.h"
#include "CClient.h"
#include "CServer.h"
#include "DedicatedControl.h"
#include "StringUtils.h"
#include "ConversationLogger.h"
#include "CGameMode.h"
#define itoa _itoa
void *ReadGameStateForReport(char *buffer, size_t bufsize)
{
memset(buffer, 0, bufsize);
__try {
if (cClient) {
strncat(buffer, "Game state:\n", bufsize);
if (cClient->getStatus() == NET_CONNECTED) {
if (cClient->getGameReady())
strncat(buffer, "In game, selecting weapons.", bufsize);
else
strncat(buffer, "In lobby.", bufsize);
} else if (cClient->getStatus() == NET_PLAYING) {
strncat(buffer, "In game, playing.", bufsize);
} else if (cClient->getStatus() == NET_CONNECTING) {
strncat(buffer, "Connecting to a server.", bufsize);
} else if (cClient->getStatus() == NET_DISCONNECTED) {
strncat(buffer, "Disconnected.\n", bufsize);
} else {
strncat(buffer, "Unknown state.\n", bufsize);
}
}
buffer[bufsize - 1] = '\0';
} __except (EXCEPTION_EXECUTE_HANDLER)
{ return buffer; }
return buffer;
}
void *ReadGameInfoForReport(char *buffer, size_t bufsize)
{
memset(buffer, 0, bufsize);
if (!tLXOptions || !tLX)
return buffer;
char tmp[32];
__try {
// Game type
strncat(buffer, "iGameType = ", bufsize);
switch (tLX->iGameType) {
case GME_LOCAL:
strncat(buffer, "GME_LOCAL", bufsize);
break;
case GME_HOST:
strncat(buffer, "GME_HOST", bufsize);
break;
case GME_JOIN:
strncat(buffer, "GME_JOIN", bufsize);
break;
default:
itoa(tLX->iGameType, tmp, 10);
fix_markend(tmp);
strncat(buffer, "UNKNOWN ", bufsize); strncat(buffer, tmp, bufsize);
}
strncat(buffer, "\n", bufsize);
// Game mode
strncat(buffer, "GameMode = ", bufsize);
char tmp[16];
itoa(tLXOptions->tGameInfo.gameMode->GeneralGameType(), tmp, 10);
fix_markend(tmp);
strncat(buffer, tmp, bufsize);
strncat(buffer, "\n", bufsize);
// Mod name
strncat(buffer, "sModName = ", bufsize);
if (tLXOptions->tGameInfo.sModName.size())
strncat(buffer, tLXOptions->tGameInfo.sModName.c_str(), bufsize);
strncat(buffer, "\n", bufsize);
// Map file
strncat(buffer, "sMapFile = ", bufsize);
if (tLXOptions->tGameInfo.sMapFile.size())
strncat(buffer, tLXOptions->tGameInfo.sMapFile.c_str(), bufsize);
strncat(buffer, "\n", bufsize);
// Map name
strncat(buffer, "sMapName = ", bufsize);
if (tLXOptions->tGameInfo.sMapName.size())
strncat(buffer, tLXOptions->tGameInfo.sMapName.c_str(), bufsize);
strncat(buffer, "\n", bufsize);
// Mod dir
strncat(buffer, "sModDir = ", bufsize);
if (tLXOptions->tGameInfo.sModDir.size())
strncat(buffer, tLXOptions->tGameInfo.sModDir.c_str(), bufsize);
strncat(buffer, "\n", bufsize);
// Loading time
itoa(tLXOptions->tGameInfo.iLoadingTime, tmp, 10);
fix_markend(tmp);
strncat(buffer, "iLoadingTimes = ", bufsize);
strncat(buffer, tmp, bufsize);
strncat(buffer, "\n", bufsize);
// Server name
strncat(buffer, "sServerName = ", bufsize);
if (tLXOptions->sServerName.size())
strncat(buffer, tLXOptions->sServerName.c_str(), bufsize);
strncat(buffer, "\n", bufsize);
// Welcome message
strncat(buffer, "sWelcomeMessage = ", bufsize);
if (tLXOptions->sWelcomeMessage.size())
strncat(buffer, tLXOptions->sWelcomeMessage.c_str(), bufsize);
strncat(buffer, "\n", bufsize);
// Lives
itoa(tLXOptions->tGameInfo.iLives, tmp, 10);
fix_markend(tmp);
strncat(buffer, "iLives = ", bufsize);
strncat(buffer, tmp, bufsize);
strncat(buffer, "\n", bufsize);
// Max kills
itoa(tLXOptions->tGameInfo.iKillLimit, tmp, 10);
fix_markend(tmp);
strncat(buffer, "iKillLimit = ", bufsize);
strncat(buffer, tmp, bufsize);
strncat(buffer, "\n", bufsize);
// Time limit
itoa((int)(tLXOptions->tGameInfo.fTimeLimit * 10), tmp, 10);
fix_markend(tmp);
strncat(buffer, "fTimeLimit = ", bufsize);
strncat(buffer, tmp, bufsize);
strncat(buffer, "\n", bufsize);
// Bonuses on
strncat(buffer, "bBonusesOn = ", bufsize);
strncat(buffer, tLXOptions->tGameInfo.bBonusesOn ? "true" : "false", bufsize);
strncat(buffer, "\n", bufsize);
// Bonus names
strncat(buffer, "bShowBonusName = ", bufsize);
strncat(buffer, tLXOptions->tGameInfo.bShowBonusName ? "true" : "false", bufsize);
strncat(buffer, "\n", bufsize);
// Number of players
if (cServer) {
itoa(cServer->getNumPlayers(), tmp, 10);
fix_markend(tmp);
strncat(buffer, "iNumPlayers = ", bufsize);
strncat(buffer, tmp, bufsize);
strncat(buffer, "\n", bufsize);
}
buffer[bufsize - 1] = '\0';
} __except (EXCEPTION_EXECUTE_HANDLER) {
return buffer;
}
return buffer;
}
// This function also used in CrashHandler.cpp
void OlxWriteCoreDump_Win32(const char* fileName, PEXCEPTION_POINTERS pExInfo )
{
// MSVC-compatible core dump, GDB cannot read it :(
// Set the exception info for the minidump
MINIDUMP_EXCEPTION_INFORMATION eInfo;
eInfo.ThreadId = GetCurrentThreadId();
eInfo.ExceptionPointers = pExInfo;
eInfo.ClientPointers = FALSE;
// Set the minidump info
MINIDUMP_CALLBACK_INFORMATION cbMiniDump;
cbMiniDump.CallbackRoutine = NULL;
cbMiniDump.CallbackParam = 0;
// Additional data
MINIDUMP_USER_STREAM pExtraInfo[3];
// Version info
char version[64];
strcpy(version, GetFullGameName());
pExtraInfo[0].Type = LastReservedStream + 1;
pExtraInfo[0].BufferSize = sizeof(version);
pExtraInfo[0].Buffer = (void *)&version[0];
// Current game info
char game_info[1024];
pExtraInfo[1].Type = LastReservedStream + 2;
pExtraInfo[1].BufferSize = sizeof(game_info);
pExtraInfo[1].Buffer = ReadGameInfoForReport(game_info, sizeof(game_info));
// Current game state
char game_state[1024];
pExtraInfo[2].Type = LastReservedStream + 3;
pExtraInfo[2].BufferSize = sizeof(game_state);
pExtraInfo[2].Buffer = ReadGameStateForReport(game_state, sizeof(game_state));
MINIDUMP_USER_STREAM_INFORMATION iStreams;
iStreams.UserStreamCount = sizeof(pExtraInfo)/sizeof(MINIDUMP_USER_STREAM);
iStreams.UserStreamArray = pExtraInfo;
// Open the file
HANDLE hFile = CreateFile((LPCSTR)fileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
// Write the minidump
if (hFile) {
MINIDUMP_TYPE type = (MINIDUMP_TYPE)(MiniDumpScanMemory | MiniDumpWithIndirectlyReferencedMemory);
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, type, &eInfo,&iStreams,&cbMiniDump);
}
// Close the file
CloseHandle(hFile);
}
void OlxWriteCoreDump(const char* fileName)
{
OlxWriteCoreDump_Win32(fileName, NULL);
}
#else
#ifdef GCOREDUMPER
#include <google/coredumper.h>
#endif
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
#include <cstdio>
#ifndef GCOREDUMPER
static void GdbWriteCoreDump(const char* fname) {
// WARNING: this is terribly slow like this
char gdbparam[1000];
sprintf(gdbparam,
"attach %i \n"
"gcore %s \n"
"detach \n"
"quit \n",
getpid(), fname);
FILE* p = popen("gdb -q", "w");
if(p) {
fprintf(p, "%s", gdbparam);
fflush(p);
int status = 0; wait(&status);
pclose(p);
}
}
#endif
void OlxWriteCoreDump(const char* file_postfix) {
char corefile[PATH_MAX + 100];
if(getcwd(corefile, PATH_MAX) == NULL) strcpy(corefile, "");
strcat(corefile, "/core.OpenLieroX");
if(file_postfix) { strcat(corefile, "."); strcat(corefile, file_postfix); }
printf("writing coredump to %s\n", corefile);
printf("dumping core ... "); fflush(0);
#ifdef GCOREDUMPER
WriteCoreDump(corefile);
#else
GdbWriteCoreDump(corefile);
#endif
printf("ready\n");
}
#endif
// ----------------- core dump code end -------------
// --------------- backtrace stuff start --------------
#ifndef HAVE_EXECINFO
# if defined(__linux__)
# define HAVE_EXECINFO 1
# elif defined(__DARWIN_VERS_1050)
# define HAVE_EXECINFO 1
# else
# define HAVE_EXECINFO 0
# endif
#endif
#if HAVE_EXECINFO
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
void DumpCallstackPrintf(void* callpnt) {
void *callstack[128];
int framesC = backtrace(callstack, sizeof(callstack));
printf("backtrace() returned %d addresses\n", framesC);
if(callpnt != NULL && framesC > 3) callstack[3] = callpnt; // expected to be called from signal handler
char** strs = backtrace_symbols(callstack, framesC);
for(int i = 0; i < framesC; ++i) {
if(strs[i])
printf("%s\n", strs[i]);
else
break;
}
free(strs);
}
void DumpCallstack(void (*PrintOutFct) (const std::string&)) {
void *callstack[128];
int framesC = backtrace(callstack, sizeof(callstack));
(*PrintOutFct) ("DumpCallstack: " + itoa(framesC) + " addresses:");
char** strs = backtrace_symbols(callstack, framesC);
for(int i = 0; i < framesC; ++i) {
if(strs[i])
(*PrintOutFct) (std::string(" ") + strs[i] + "\n");
else
break;
}
free(strs);
}
#elif defined(WIN32)
#include "StackWalker.h" // Call Luke Stackwalker for help
typedef void (*PrintOutFct) (const std::string&);
// Override the default stackwalker with our own print functions
class PrintStackWalker : public StackWalker {
private:
PrintOutFct m_print;
public:
PrintStackWalker(PrintOutFct fct = NULL) : StackWalker(RetrieveVerbose) { m_print = fct; }
void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
{
}
void OnOutput(LPCSTR szText)
{
if (m_print == NULL)
printf(szText);
else
m_print(std::string(szText));
StackWalker::OnOutput(szText);
}
};
void DumpCallstackPrintf(void* callpnt)
{
PrintStackWalker sw;
sw.ShowCallstack();
}
void DumpCallstack(void (*LineOutFct) (const std::string&))
{
PrintStackWalker sw(LineOutFct);
sw.ShowCallstack();
}
#else
#warning No DumpCallstack implementation for this arch/sys
void DumpCallstackPrintf(void* callpnt) {
printf("DumpCallstackPrintf not implemented\n");
}
void DumpCallstack(void (*PrintOutFct) (const std::string&)) {
printf("DumpCallstack not implemented\n");
}
#endif
std::string GetLogTimeStamp()
{
// TODO: please recode this, don't use C-strings!
char buf[64];
const time_t unif_time = time(NULL);
struct tm *t = localtime(&unif_time);
if (t == NULL)
return "";
strftime(buf, sizeof(buf), "[%H:%M:%S] ", t);
fix_markend(buf);
return std::string(buf);
}
Logger notes(0,2,1000, "n: ");
Logger hints(0,1,100, "H: ");
Logger warnings(0,0,10, "W: ");
Logger errors(-1,-1,1, "E: ");
#include <iostream>
#include <sstream>
#include "ThreadPool.h"
#include "StringUtils.h"
static SDL_mutex* globalCoutMutex = NULL;
Logger::Logger(int o, int ingame, int callst, const std::string& p)
: minCoutVerb(o), minIngameConVerb(ingame), minCallstackVerb(callst), prefix(p), lastWasNewline(true), mutex(NULL) {
mutex = SDL_CreateMutex();
if(!globalCoutMutex)
globalCoutMutex = SDL_CreateMutex();
}
Logger::~Logger() {
SDL_DestroyMutex(mutex); mutex = NULL;
if(globalCoutMutex) {
SDL_DestroyMutex(globalCoutMutex);
globalCoutMutex = NULL;
}
}
void Logger::lock() {
SDL_mutexP(mutex);
}
void Logger::unlock() {
SDL_mutexV(mutex);
}
static void CoutPrint(const std::string& str) {
// TODO: We have used std::cout here before but it doesn't seem to work after a while for some reason.
printf("%s", str.c_str());
}
int Logger_Verbosity = 0;
// true if last was newline
static bool logger_output(Logger& log, const std::string& buf) {
bool ret = true;
std::string prefix = log.prefix;
if(Logger_Verbosity >= log.minCoutVerb) {
SDL_mutexP(globalCoutMutex);
ret = PrettyPrint(prefix, buf, CoutPrint, log.lastWasNewline);
//std::cout.flush();
SDL_mutexV(globalCoutMutex);
}
if(Logger_Verbosity >= log.minCallstackVerb) {
DumpCallstackPrintf();
}
return ret;
}
Logger& Logger::flush() {
lock();
lastWasNewline = logger_output(*this, buffer);
buffer = "";
unlock();
return *this;
}

76
src/Debug.h Normal file
View File

@@ -0,0 +1,76 @@
/*
* Debug.h
* OpenLieroX
*
* Created by Albert Zeyer on 01.01.09.
* code under LGPL
*
*/
#ifndef __OLXDEBUG_H__
#define __OLXDEBUG_H__
#include <string>
#include <cassert>
#include "StringUtils.h"
// { these function should be safe to be called from everywhere, also from signalhandlers
void RaiseDebugger(); // if run in a debugger, it should raise it; if not, it should do nothing
void OlxWriteCoreDump(const char* file_postfix = NULL);
void DumpCallstackPrintf(void* callpnt = NULL);
// }
void DumpCallstack(void (*PrintOutFct) (const std::string&));
struct SDL_mutex;
struct Logger {
int minCoutVerb;
int minIngameConVerb;
int minCallstackVerb;
std::string prefix;
std::string buffer;
bool lastWasNewline;
SDL_mutex* mutex;
Logger(int o, int ingame, int callst, const std::string& p);
~Logger();
void lock(); void unlock();
struct LockedStreamWrapper {
Logger* logger;
LockedStreamWrapper(Logger* l) : logger(l) {}
LockedStreamWrapper(const LockedStreamWrapper& l) : logger(l.logger) { ((LockedStreamWrapper&)l).logger = NULL; }
~LockedStreamWrapper() { if(logger) logger->unlock(); }
Logger* push_back() { Logger* tmp = logger; logger = NULL; return tmp; }
Logger* push_back_and_unlock() { Logger* tmp = push_back(); tmp->unlock(); return tmp; }
LockedStreamWrapper& operator<<(const std::string& msg) { logger->buffer += msg; return *this; }
template<typename _T> LockedStreamWrapper& operator<<(_T v) { return operator<<(to_string(v)); }
Logger& operator<<(Logger& (*__pf)(Logger&)) { return (*__pf)(*push_back_and_unlock()); }
Logger& flush() { return push_back_and_unlock()->flush(); }
};
LockedStreamWrapper operator<<(const std::string& msg) { lock(); buffer += msg; return LockedStreamWrapper(this); }
Logger& operator<<(Logger& (*__pf)(Logger&)) { return (*__pf)(*this); }
template<typename _T> LockedStreamWrapper operator<<(_T v) { return operator<<(to_string(v)); }
Logger& flush();
// deprecated, only for easier find/replace with printf
void operator()(const std::string& str) { (*this) << str; flush(); }
};
inline Logger& endl(Logger& __os) { return (__os << "\n").flush(); }
inline Logger& flush(Logger& __os) { return __os.flush(); }
template< Logger& l >
void printOnLogger(const std::string& str) { l << str; }
extern Logger notes;
extern Logger hints;
extern Logger warnings;
extern Logger errors;
#endif

143
src/Event.h Normal file
View File

@@ -0,0 +1,143 @@
/*
OpenLieroX
event class
created on 27-05-2008 by Albert Zeyer
code under LGPL
*/
#ifndef __EVENT_H__
#define __EVENT_H__
#include <list>
#include <SDL.h>
#include "Ref.h"
#include "SmartPointer.h"
#include "EventQueue.h"
#include "Utils.h" // for isSameType
struct EventData {
EventData(void* own = NULL) : owner(own) {}
void* owner;
};
class _Event {};
/*
This is an Event class, which represents a possible event.
It handles all the event handlers.
_Data should provide at least an owner field like EventData
*/
template< typename _Data = EventData >
class Event : public _Event {
public:
class Handler {
public:
typedef _Data Data;
virtual ~Handler() {}
virtual void operator()(_Data data) = 0;
virtual bool operator==(const Handler& hndl) = 0;
virtual Handler* copy() const = 0;
};
typedef std::list< Ref<Handler> > HandlerList;
protected:
class HandlerAccessor {
private:
Event* base;
public:
HandlerAccessor(Event* b) : base(b) {}
HandlerAccessor& operator=(const Ref<Handler>& h) { base->m_handlers.clear(); if(h.isSet()) base->m_handlers.push_back(h); return *this; }
HandlerAccessor& operator+=(const Ref<Handler>& h) { if(h.isSet()) base->m_handlers.push_back(h); return *this; }
HandlerAccessor& operator-=(const Ref<Handler>& h) {
for(typename Event::HandlerList::iterator i = base->m_handlers.begin(); i != base->m_handlers.end(); ++i)
if(i->get() == h.get()) {
base->m_handlers.erase(i);
break;
}
return *this;
}
const typename Event::HandlerList& get() { return base->m_handlers; }
};
private:
friend class HandlerAccessor;
HandlerList m_handlers;
public:
Event() {}
~Event() { if (mainQueue) mainQueue->removeCustomEvents(this); }
Event(const Event& e) { (*this) = e; }
Event& operator=(const Event& e) { m_handlers = e.m_handlers; return *this; }
HandlerAccessor handler() { return HandlerAccessor(this); }
void pushToMainQueue(_Data data) { if(mainQueue) mainQueue->push(new EventThrower<_Data>(this, data)); }
void occurred(_Data data) {
callHandlers(m_handlers, data);
}
static void callHandlers(HandlerList& handlers, _Data data) {
for(typename HandlerList::iterator i = handlers.begin(); i != handlers.end(); ++i)
i->get()(data);
}
};
template< typename _Base, typename _Data = EventData >
class MemberFunction : public Event<_Data>::Handler {
public:
typedef void (_Base::*Function) (_Data data);
private:
_Base* m_obj;
Function m_fct;
public:
MemberFunction(_Base* obj, Function fct) : m_obj(obj), m_fct(fct) {}
MemberFunction(const MemberFunction& other) : m_obj(other.m_obj), m_fct(other.m_fct) {}
virtual void operator()(_Data data) { (*m_obj.*m_fct)(data); }
virtual bool operator==(const typename Event<_Data>::Handler& hndl) {
const MemberFunction* hPtr = dynamic_cast<const MemberFunction*>(&hndl);
if(hPtr == NULL) return false;
return hPtr->m_obj == m_obj && hPtr->m_fct == m_fct;
}
virtual typename Event<_Data>::Handler* copy() const { return new MemberFunction(m_obj, m_fct); }
};
template< typename _Data = EventData >
class StaticFunction : public Event<_Data>::Handler {
public:
typedef void (*Function) (_Data data);
private:
Function m_fct;
public:
StaticFunction(Function fct) : m_fct(fct) {}
StaticFunction(const StaticFunction& other) : m_fct(other.m_fct) {}
virtual void operator()(_Data data) { (m_fct)(data); }
virtual bool operator==(const typename Event<_Data>::Handler& hndl) {
const StaticFunction* hPtr = dynamic_cast<const StaticFunction*>(&hndl);
if(hPtr == NULL) return false;
return hPtr->m_fct == m_fct;
}
virtual typename Event<_Data>::Handler* copy() const { return new StaticFunction(m_fct); }
};
template< typename _Base, typename _Data >
Ref<class Event<_Data>::Handler> getEventHandler( _Base* obj, void (_Base::*fct) (_Data data) ) {
return new MemberFunction<_Base,_Data>( obj, fct );
}
template< typename _Data >
Ref<class Event<_Data>::Handler> getEventHandler( void (*fct) (_Data data) ) {
return new StaticFunction<_Data>( fct );
}
#endif

101
src/EventQueue.h Normal file
View File

@@ -0,0 +1,101 @@
/////////////////////////////////////////
//
// OpenLieroX
//
// event queue
//
// based on the work of JasonB
// enhanced by Dark Charlie and Albert Zeyer
//
// code under LGPL
//
/////////////////////////////////////////
#ifndef __EVENTQUEUE_H__
#define __EVENTQUEUE_H__
#include <cassert>
#include "ThreadPool.h" // for Action
enum SDLUserEvent {
UE_CustomEventHandler = 0,
UE_QuitEventThread = 1,
UE_DoVideoFrame = 2,
UE_DoSetVideoMode = 3,
UE_DoActionInMainThread = 4
};
// bDedicated must be set before we can call this
void InitEventQueue();
void ShutdownEventQueue();
union SDL_Event;
typedef SDL_Event EventItem; // for now, we can change that later
class _Event;
template< typename _Data > class Event;
class CustomEventHandler : public Action {
public:
virtual int handle() = 0;
virtual const _Event* owner() const = 0;
virtual CustomEventHandler* copy(_Event* newOwner = NULL) const = 0;
virtual ~CustomEventHandler() {}
};
template< typename _Data >
class EventThrower : public CustomEventHandler {
public:
Event<_Data>* m_event;
_Data m_data;
EventThrower(Event<_Data>* e, _Data d) : m_event(e), m_data(d) {}
virtual int handle() {
m_event->occurred( m_data );
return 0;
}
virtual const _Event* owner() const { return m_event; }
virtual CustomEventHandler* copy(_Event* newOwner) const {
EventThrower* th = new EventThrower(*this);
if(newOwner) th->m_event = (Event<_Data>*) newOwner;
return th;
}
};
struct EventQueueIntern;
class EventQueue {
private:
EventQueueIntern* data;
public:
EventQueue();
~EventQueue();
// Polls for currently pending events.
bool poll(EventItem& e);
// Waits indefinitely for the next available event.
bool wait(EventItem& e);
/* Add an event to the event queue.
* This function returns true on success
* or false if there was some error.
*/
bool push(const EventItem& e);
bool push(Action* eh);
// goes through all CustomEventHandler and copies them if oldOwner is matching
void copyCustomEvents(const _Event* oldOwner, _Event* newOwner);
// removes all CustomEventHandler with owner
void removeCustomEvents(const _Event* owner);
};
extern EventQueue* mainQueue;
#endif // __EVENTQUEUE_H__

496
src/FindFile.h Normal file
View File

@@ -0,0 +1,496 @@
/////////////////////////////////////////
//
// OpenLieroX
//
// Auxiliary Software class library
//
// work by JasonB
// code under LGPL
// enhanced by Dark Charlie and Albert Zeyer
//
/////////////////////////////////////////
// File finding routines
// Created 30/9/01
// By Jason Boettcher
// TODO: rename this file
#ifndef __FINDFILE_H__
#define __FINDFILE_H__
#include <fstream>
#include <string>
#include <list>
#include <vector>
#include <set>
#include "Unicode.h"
#include "Debug.h"
#include "Mutex.h"
#include "Iterator.h"
#include "RefCounter.h"
#include "Event.h"
#include "StringUtils.h"
#ifndef WIN32
# include <dirent.h>
# include <unistd.h>
#endif
// file input/output
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
# include <windows.h>
# include <io.h>
# include <direct.h>
// wrappers to provide the standards
inline int mkdir(const char *path, int mode) { return _mkdir(Utf8ToSystemNative(path).c_str()); }
# define stat _stat
#ifndef S_ISREG
# define S_IFLNK 0120000
inline bool S_ISREG(unsigned short s) { return (s & S_IFREG) != 0; }
inline bool S_ISDIR(unsigned short d) { return (d & S_IFDIR) != 0; }
inline bool S_ISLNK(unsigned short d) { return (d & S_IFLNK) != 0; }
#endif
#endif
#ifndef SYSTEM_DATA_DIR
# define SYSTEM_DATA_DIR "/usr/share"
#endif
extern std::string binary_dir;
//
// Drive types
//
// Windows
#ifdef WIN32
# define DRV_UNKNOWN DRIVE_UNKNOWN // The drive is unknown
# define DRV_NO_ROOT_DIR DRIVE_NO_ROOT_DIR // The root path is invalid; for example, there is no volume is mounted at the path.
# define DRV_REMOVABLE DRIVE_REMOVABLE // The drive has removable media; for example, a floppy drive or flash card reader.
# define DRV_FIXED DRIVE_FIXED // The drive has fixed media; for example, a hard drive, flash drive, or thumb drive.
# define DRV_REMOTE DRIVE_REMOTE // The drive is a remote (network) drive.
# define DRV_CDROM DRIVE_CDROM // The drive is a CD-ROM drive.
# define DRV_RAMDISK DRIVE_RAMDISK // The drive is a RAM disk.
#endif
class drive_t { public:
std::string name;
unsigned int type;
};
typedef std::vector<drive_t> drive_list;
// Define intptr_t if not defined
#ifdef _MSC_VER
#ifndef _INTPTR_T_DEFINED
typedef long intptr_t;
#endif
#endif
typedef std::vector<std::string> searchpathlist;
extern searchpathlist tSearchPaths;
void AddToFileList(searchpathlist* l, const std::string& f);
bool FileListIncludesExact(const searchpathlist* l, const std::string& f);
void initSpecialSearchPathForTheme();
const std::string* getSpecialSearchPathForTheme();
// this replaces ${var} in filename with concrete values
// currently, the following variables are handled:
// ${HOME} - the home-dir, that means under unix ~ and under windows the 'my-documents'
// ${BIN} - the dir of the executable-binary
// ${SYSTEM_DATA} - data-dir of the system, that means usually /usr/share
void ReplaceFileVariables(std::string& filename);
drive_list GetDrives();
// This function converts relative paths to absolute paths
std::string GetAbsolutePath(const std::string& path);
#ifndef WIN32
// mostly all system but Windows use case sensitive file systems
// this game uses also filenames ignoring the case sensitivity
// this function gives the case sensitive right name of a file
// also, it replaces ${var} in the searchname
// returns false if no success, true else
bool GetExactFileName(const std::string& abs_searchname, std::string& filename);
#else // WIN32
// we don't have case sensitive file systems under windows
// but we still need to replace ${var} in the searchname
// returns true, if file/dir is existing and accessable, false else
inline bool GetExactFileName(const std::string& abs_searchname, std::string& filename) {
filename = abs_searchname;
if(abs_searchname.size() == 0) {
return true;
}
ReplaceFileVariables(filename);
// Remove the ending slash, else stat will fail
if (filename[filename.length()-1]== '/' || filename[filename.length()-1]== '\\')
// Don't remove, if this is a root directory, else stat will fail (really crazy)
#ifdef WIN32
if (filename[filename.length()-2] != ':')
#endif
filename.erase(filename.length()-1);
struct stat finfo;
if(stat(Utf8ToSystemNative(filename).c_str(), &finfo) != 0) {
// problems stating file
return false;
}
// we got some info, so there is something ...
return true;
}
#endif
extern searchpathlist basesearchpaths;
void InitBaseSearchPaths();
// this does a search on all searchpaths for the file and returns the first one found
// if none was found, NULL will be returned
// if searchpath!=NULL, it will place there the searchpath
std::string GetFullFileName(const std::string& path, std::string* searchpath = NULL);
// this give always a dir like searchpath[0]/path, but it ensures:
// - the filename is correct, if the file exists
// - it replaces ${var} with ReplaceFileVariables
// if create_nes_dirs is set, the nessecary dirs will be created
std::string GetWriteFullFileName(const std::string& path, bool create_nes_dirs = false);
// replacement for the simple fopen
// this does a search on all searchpaths for the file and opens the first one; if none was found, NULL will be returned
// related to tSearchPaths
FILE* OpenGameFile(const std::string& path, const char *mode);
FILE* OpenAbsFile(const std::string& path, const char *mode);
std::ifstream* OpenGameFileR(const std::string& path);
std::string GetFileContents(const std::string& path, bool absolute = false);
std::string ExtractDirectory(const std::string& path);
std::string JoinPaths(const std::string& path1, const std::string& path2);
std::string GetScriptInterpreterCommandForFile(const std::string& filename);
bool IsFileAvailable(const std::string& f, bool absolute = false);
// the dir will be created recursivly
// IMPORTANT: filename is absolute; no game-path!
void CreateRecDir(const std::string& abs_filename, bool last_is_dir = true);
bool EqualPaths(const std::string& path1, const std::string& path2);
// Returns true if the path is absolute
bool IsAbsolutePath(const std::string& path);
// copy the src-file to the dest
// it will simply fopen(src, "r"), fopen(dest, "w") and write all the stuff
// IMPORTANT: filenames are absolute; no game-path!
bool FileCopy(const std::string& src, const std::string& dest);
// returns true, if we can write to the dir
bool CanWriteToDir(const std::string& dir);
size_t FileSize(const std::string& path);
// returns the home-directory (used by ReplaceFileVariables)
std::string GetHomeDir();
// returns the system-data-dir (under Linux, usually /usr/share)
std::string GetSystemDataDir();
// returns the dir of the executable-binary
std::string GetBinaryDir();
// returns the temp-dir of the system
std::string GetTempDir();
typedef char filemodes_t;
enum {
FM_DIR = 1,
FM_REG = 2,
FM_LNK = 4,
};
bool PathListIncludes(const std::list<std::string>& list, const std::string& path);
// _handler has to be a functor with
// bool op() ( const std::string& path )
// ending pathsep is ensured if needed
// if return is false, it will break
// HINT: it does no GetExactFileName with the paths
template<typename _handler>
void ForEachSearchpath(_handler& handler) {
std::list<std::string> handled_dirs;
std::string path;
searchpathlist::const_iterator i;
{
const std::string* themeDir = getSpecialSearchPathForTheme();
if(themeDir) {
if(!handler(*themeDir + "/")) return;
handled_dirs.push_back(*themeDir);
}
}
for(
i = tSearchPaths.begin();
i != tSearchPaths.end(); i++) {
path = *i;
if(!PathListIncludes(handled_dirs, path)) {
if(!handler(path + "/")) return;
handled_dirs.push_back(path);
}
}
for(
i = basesearchpaths.begin();
i != basesearchpaths.end(); i++) {
if(!FileListIncludesExact(&tSearchPaths, *i)) {
path = *i;
if(!PathListIncludes(handled_dirs, path)) {
if(!handler(path + "/")) return;
handled_dirs.push_back(path);
}
}
}
}
// functor for ForEachSearchpath, used by FindFiles
// it will search a subdir of a given searchpath for files
template<typename _filehandler>
class FindFilesHandler {
public:
const std::string& dir;
const std::string& namefilter;
const filemodes_t modefilter;
_filehandler& filehandler;
FindFilesHandler(
const std::string& dir_,
const std::string& namefilter_,
const filemodes_t modefilter_,
_filehandler& filehandler_) :
dir(dir_),
namefilter(namefilter_),
modefilter(modefilter_),
filehandler(filehandler_) {}
bool operator() (const std::string& path) {
std::string abs_path = path;
if(!GetExactFileName(path + dir, abs_path)) return true;
bool ret = true;
#ifdef WIN32 // uses UTF16
struct _finddata_t fileinfo;
abs_path.append("/");
intptr_t handle = _findfirst(Utf8ToSystemNative(abs_path + "*").c_str(), &fileinfo);
while(handle > 0) {
//If file is not self-directory or parent-directory
if(fileinfo.name[0] != '.' || (fileinfo.name[1] != '\0' && (fileinfo.name[1] != '.' || fileinfo.name[2] != '\0'))) {
if((!(fileinfo.attrib&_A_SUBDIR) && modefilter&FM_REG)
|| fileinfo.attrib&_A_SUBDIR && modefilter&FM_DIR)
if(!filehandler(abs_path + SystemNativeToUtf8(fileinfo.name))) {
ret = false;
break;
}
}
if(_findnext(handle,&fileinfo))
break;
}
_findclose(handle);
#else /* not WIN32 */
std::string filename;
dirent* entry;
struct stat s;
DIR* handle = opendir(abs_path.c_str());
if(!handle) return ret;
while((entry = readdir(handle)) != 0) {
//If file is not self-directory or parent-directory
if(entry->d_name[0] != '.' || (entry->d_name[1] != '\0' && (entry->d_name[1] != '.' || entry->d_name[2] != '\0'))) {
filename = abs_path + "/" + entry->d_name;
if(stat(filename.c_str(), &s) == 0)
if((S_ISREG(s.st_mode) && modefilter&FM_REG)
|| (S_ISDIR(s.st_mode) && modefilter&FM_DIR)
|| (S_ISLNK(s.st_mode) && modefilter&FM_LNK))
if(!filehandler(filename)) {
ret = false;
break;
}
}
}
closedir(handle);
#endif /* WIN32 */
return ret;
}
};
// FindFiles searches for files
// _handler has to be a functor with
// bool op()( const std::string& abs_filename )
// if it returns false, it will break
template<typename _handler>
void FindFiles(
_handler& handler,
const std::string& dir,
bool absolutePath = false,
const filemodes_t modefilter = -1,
const std::string& namefilter = ""
) {
if(namefilter != "*" && namefilter != "")
warnings << "FindFiles: filter " << namefilter <<" isn't handled yet" << endl;
if(absolutePath)
FindFilesHandler<_handler>(dir, namefilter, modefilter, handler) ("");
else {
FindFilesHandler<_handler> searchpathHandler(dir, namefilter, modefilter, handler);
ForEachSearchpath(searchpathHandler);
}
}
template <typename _List, typename _CheckFct>
struct GetFileList_FileListAdder {
_CheckFct& checkFct;
_List& filelist;
GetFileList_FileListAdder(_CheckFct& f, _List& l) : checkFct(f), filelist(l) {}
bool operator() (const std::string& path) {
checkFct(filelist, path);
return true;
}
};
template <typename _List, typename _CheckFct>
void GetFileList(
_List& filelist,
_CheckFct& checkFct,
const std::string& dir,
bool absolutePath = false,
const filemodes_t modefilter = -1,
const std::string& namefilter = "")
{
GetFileList_FileListAdder<_List,_CheckFct> adder(checkFct, filelist);
FindFiles(adder, dir, absolutePath, modefilter, namefilter);
}
class Command;
struct AutocompleteRequest;
class FileListCacheIntf {
public:
typedef std::string Filename;
typedef std::string ObjectName;
typedef std::map<Filename,ObjectName,stringcaseless> FileList;
protected:
Mutex mutex;
FileList filelist;
bool isReady; // will be set true after an update and stays always true then
public:
const std::string name;
Event<> OnUpdateFinished;
FileListCacheIntf(const std::string& n) : isReady(false), name(n) {}
virtual ~FileListCacheIntf() {}
// this iterator locks the filelist as long as it exists
class Iterator : public ::Iterator<FileList::value_type>, public RefCounter {
private:
FileList::iterator it;
FileListCacheIntf& filelist;
public:
Iterator(FileList::iterator _it, FileListCacheIntf& f) : it(_it), filelist(f) {
filelist.mutex.lock();
}
~Iterator() { RefCounter::uninit(); }
virtual void onLastRefRemoved() {
filelist.mutex.unlock();
}
Iterator(const Iterator& it) : RefCounter(it), it(it.it), filelist(it.filelist) {}
virtual ::Iterator<FileList::value_type>* copy() const { return new Iterator(*this); }
virtual bool isValid() { return it != filelist.filelist.end(); }
virtual void next() { ++it; }
virtual bool operator==(const ::Iterator<FileList::value_type>& other) const {
const Iterator* o = dynamic_cast<const Iterator*> (&other);
return o && it == o->it;
}
virtual FileList::value_type get() { return *it; }
typedef ::Iterator<FileList::value_type>::Ref Ref;
};
Iterator::Ref begin() { return new Iterator(filelist.begin(), *this); }
void add(const FileList::value_type& o) { Mutex::ScopedLock lock(mutex); filelist.insert(o); }
bool includes(const Filename& fn) { Mutex::ScopedLock lock(mutex); return filelist.find(fn) != filelist.end(); }
bool autoComplete(AutocompleteRequest& request);
bool ready() { Mutex::ScopedLock lock(mutex); return isReady; }
virtual void update() = 0; // will be run in an own thread and should lock as short as possible (in best case only for the swap of the old/new list)
};
template <typename _CheckFct> // asume that _CheckFct will be static anyway - makes it a bit simpler - just change if needed
class FileListCache : public FileListCacheIntf {
protected:
const std::string dir;
const bool absolutePath;
const filemodes_t modefilter;
const std::string namefilter;
public:
// Note: slightly different default values from FindFiles (modefilter is FM_REG here)
FileListCache(const std::string& _name,
const std::string& _dir,
bool _absPath = false,
const filemodes_t _modefilter = FM_REG,
const std::string& _namefilter = "")
: FileListCacheIntf(_name), dir(_dir), absolutePath(_absPath), modefilter(_modefilter), namefilter(_namefilter) {}
virtual void update() {
static _CheckFct fct;
FileList newList;
GetFileList(newList, fct, dir, absolutePath, modefilter, namefilter);
{
Mutex::ScopedLock lock(mutex);
filelist.swap(newList);
isReady = true;
}
OnUpdateFinished.pushToMainQueue(EventData(this));
}
};
// File pointer to SDL RWops conversion
SDL_RWops *RWopsFromFP(FILE *fp, bool autoclose);
// Platform-independent stat() - use S_ISREG( st.st_mode ) and S_ISDIR( st.st_mode ) on stat struct
inline bool StatFile( const std::string & file, struct stat * st )
{
std::string fname = GetFullFileName( file );
std::string exactfname;
if( ! GetExactFileName( fname, exactfname ) )
return false;
if( stat( Utf8ToSystemNative(fname).c_str(), st ) != 0 )
return false;
return true;
}
#endif // __FINDFILE_H__

43
src/Functors.h Normal file
View File

@@ -0,0 +1,43 @@
/*
OpenLieroX
various functors
code under LGPL
created 01-05-2007
by Albert Zeyer and Dark Charlie
*/
#ifndef __FUNCTORS_H__
#define __FUNCTORS_H__
// joins 2 functors
template<typename _F1, typename _F2>
class JoinedFunctors : _F1, _F2 {
private:
_F1& f1; _F2& f2;
public:
JoinedFunctors(_F1& f1_, _F2& f2_) : f1(f1_), f2(f2_) {}
template<typename Targ1>
bool operator()(Targ1 arg1) {
return f1(arg1) && f2(arg1);
}
template<typename Targ1, typename Targ2>
bool operator()(Targ1 arg1, Targ2 arg2) {
return f1(arg1, arg2) && f2(arg1, arg2);
}
};
template <typename _ParamType>
class NopFunctor {
public:
void operator()(_ParamType param) {}
};
#endif

128
src/Iterator.h Normal file
View File

@@ -0,0 +1,128 @@
/*
OpenLieroX
general iterator interface
created by Albert Zeyer on 27-05-2008
code under LGPL
*/
#ifndef __OLX_ITERATOR_H__
#define __OLX_ITERATOR_H__
#include <set>
#include <map>
#include <vector>
#include <list>
#include <string>
#include "Ref.h"
template < typename _Obj >
class Iterator {
public:
virtual ~Iterator() {}
virtual Iterator* copy() const = 0;
virtual bool isValid() = 0;
virtual void next() = 0;
virtual bool operator==(const Iterator& other) const = 0;
bool operator!=(const Iterator& other) const { return ! ((*this) == other); }
virtual _Obj get() = 0; // this has to return a valid obj if valid == true
//_Obj* operator->() { return &get(); }
typedef ::Ref< Iterator > Ref;
};
template<typename _STLT, typename _T>
class STLIteratorBase : public Iterator<_T> {
protected:
typename _STLT::iterator i;
_STLT& obj;
public:
STLIteratorBase(_STLT& o) : i(o.begin()), obj(o) {}
STLIteratorBase(const STLIteratorBase& it) : i(it.i), obj(it.obj) {}
virtual bool isValid() { return i != obj.end(); }
virtual void next() { ++i; }
virtual bool operator==(const Iterator<_T>& other) const { const STLIteratorBase* ot = dynamic_cast< const STLIteratorBase* > (&other); return ot && &ot->obj == &obj && ot->i == i; }
};
template<typename _STLT, typename _T>
class STLIterator : public STLIteratorBase<_STLT, _T> {
public:
STLIterator(_STLT& o) : STLIteratorBase<_STLT, _T>(o) {}
STLIterator(const STLIterator& it) : STLIteratorBase<_STLT, _T>(it) {}
virtual Iterator<_T>* copy() const { return new STLIterator(*this); }
virtual bool operator==(const Iterator<_T>& other) const { const STLIterator* ot = dynamic_cast< const STLIterator* > (&other); return ot != NULL && STLIteratorBase<_STLT, _T> :: operator == ( other ); }
virtual _T get() { return * STLIteratorBase<_STLT, _T> :: i; }
};
template<typename _STLT, typename _T>
class STL_MapIterator : public STLIteratorBase<_STLT, _T> {
public:
STL_MapIterator(_STLT& o) : STLIteratorBase<_STLT, _T> (o) {}
STL_MapIterator(const STL_MapIterator& it) : STLIteratorBase<_STLT, _T> (it) {}
virtual Iterator<_T>* copy() const { return new STL_MapIterator(*this); }
virtual bool operator==(const Iterator<_T>& other) const { const STL_MapIterator* ot = dynamic_cast< const STL_MapIterator* > (&other); return ot != NULL && STLIteratorBase<_STLT, _T> :: operator == ( other ); }
virtual _T get() { return STLIteratorBase<_STLT, _T> :: i -> second; }
};
template<typename _T>
struct CArray {
_T* array;
unsigned long len;
CArray(_T* a, unsigned long l) : array(a), len(l) {}
};
template<typename _T>
CArray<_T> Array(_T* a, unsigned long l) { return CArray<_T>(a,l); }
template<typename _T>
class CArrayIterator : public Iterator<_T*> {
private:
unsigned long i, len;
_T* array;
public:
CArrayIterator(const CArray<_T>& a) : i(0), len(a.len), array(a.array) {}
CArrayIterator(const CArrayIterator& it) : i(it.i), array(it.array) {}
virtual Iterator<_T*>* copy() const { return new CArrayIterator(*this); }
virtual bool isValid() { return i < len; }
virtual void next() { ++i; }
virtual bool operator==(const Iterator<_T*>& other) const { const CArrayIterator* ot = dynamic_cast< const CArrayIterator* > (&other); return ot && ot->array == array && ot->i == i; }
virtual _T* get() { return &array[i]; }
};
template< typename __T, typename __C >
typename Iterator<__T>::Ref GetIterator(__C& s) { return s.iterator(); }
template< typename _T >
typename Iterator<_T>::Ref GetIterator(std::set<_T>& s) { return new STLIterator<std::set<_T>,_T>(s); }
template< typename _T >
typename Iterator<_T&>::Ref GetIterator(std::list<_T>& s) { return new STLIterator<std::list<_T>,_T&>(s); }
template< typename _T >
typename Iterator<_T&>::Ref GetIterator(std::vector<_T>& s) { return new STLIterator<std::vector<_T>,_T&>(s); }
template< typename _T, typename _KT >
typename Iterator<_T&>::Ref GetIterator(std::map<_KT, _T>& s) { return new STL_MapIterator<std::map< _KT, _T >, _T& >(s); }
inline
Iterator<char&>::Ref GetIterator(std::string& s) { return new STLIterator<std::string,char&>(s); }
inline
Iterator<char>::Ref GetConstIterator(std::string& s) { return new STLIterator<std::string,char>(s); }
template< typename _T >
typename Iterator<_T const&>::Ref GetConstIterator(std::vector<_T>& s) { return new STLIterator<std::vector<_T>,_T const&>(s); }
//template< typename _I, typename _T >
//typename Iterator< std::pair<_I,_T> >::Ref GetIterator(std::map<_I,_T>& s) { return s.begin(); }
template< typename _T >
typename Iterator<_T*>::Ref GetIterator(const CArray<_T>& s) { return new CArrayIterator<_T>(s); }
#define foreach( t, el, s ) for( Iterator<t>::Ref el = GetIterator(s); el->isValid(); el->next() )
#endif

266
src/MathLib.h Normal file
View File

@@ -0,0 +1,266 @@
/////////////////////////////////////////
//
// OpenLieroX
//
// Auxiliary Software class library
//
// based on the work of JasonB
// enhanced by Dark Charlie and Albert Zeyer
//
// code under LGPL
//
/////////////////////////////////////////
// Mathematics Library
// Created 20/12/01
// Jason Boettcher
// Albert Zeyer
#ifndef __MATHLIB_H__
#define __MATHLIB_H__
#include <cmath>
#include "CVec.h"
// Constants
#define PI 3.14159265358979323846
// Routines
float GetRandomNum(); // get a random float from [-1,1]
float GetRandomPosNum(); // get a random float from [0,1]
int GetRandomInt(int max); // get a random int from [0,max]
int Round(float x);
/*#ifdef _MSC_VER
float cos(float _v) {return cosf(_v); }
float sin(float _v) {return sinf(_v); }
float tan(float _v) {return tanf(_v); }
float atan(float _v) {return atanf(_v); }
float sqrt(float _v) {return sqrtf(_v); }
#endif*/
float CalculateDistance(CVec p1, CVec p2);
float NormalizeVector(CVec *vec);
CVec GetRandomVec();
void GetVecsFromAngle(int yaw,CVec *forward, CVec *right);
float VectorAngle(CVec vec1, CVec vec2);
float VectorLength(CVec vec);
float fastSQRT(float x);
#define SIGN(x) (((x) > 0)?1:(((x) < 0)?-1:0))
#define SQR(x) ((x)*(x))
#undef MIN
#undef MAX
template <typename T> T MIN(T a, T b) { return a < b ? a : b; }
template <typename T> T MAX(T a, T b) { return a > b ? a : b; }
inline unsigned long MIN(unsigned long a, unsigned int b) { return a < b ? a : b; }
template <typename T> T CLAMP(const T& num, const T& lower_bound, const T& upper_bound) {
return num < lower_bound ? lower_bound : (num > upper_bound ? upper_bound : num); }
template <typename T> int CLAMP_DIRECT(T& num, const T& lower_bound, const T& upper_bound) {
if(num < lower_bound) {
num = lower_bound;
return -1;
} else if(num > upper_bound) {
num = upper_bound;
return 1;
} else return 0;
}
template <typename T> void REDUCE_CONST(T& v, const T& red_const) {
if(v > 0) v = MAX((T)0, v - red_const); else if(v < 0) v = MIN((T)0, v + red_const); }
template <typename T> void RESET_SMALL(T& v, const T& limit) {
if((v > 0 && v < limit) || (v < 0 && v > -limit)) v = 0; }
template <typename T> void MOD(T& a, const T& b) { a %= b; if(a < 0) a += b; }
template <typename T> void FMOD(T& a, const T& b) { a -= b * floor(a / b); if(a < 0) a += b; }
template<typename _T>
class SquareMatrix {
public:
VectorD2<_T> v1, v2;
SquareMatrix(VectorD2<_T> _v1 = VectorD2<_T>(0,0), VectorD2<_T> _v2 = VectorD2<_T>(0,0)) {
v1 = _v1; v2 = _v2;
}
static SquareMatrix Identity() {
return SquareMatrix(VectorD2<_T>(1,0), VectorD2<_T>(0,1));
}
static SquareMatrix RotateMatrix(float angle) {
SquareMatrix m;
m.v1.x = cos(angle);
m.v1.y = sin(angle);
m.v2.x = -m.v1.y;
m.v2.y = m.v1.x;
return m;
}
CVec operator()(const VectorD2<_T>& v) const {
return CVec(v.x*v1.x + v.y*v2.x, v.x*v1.y + v.y*v2.y);
}
SquareMatrix operator*(const SquareMatrix& m) const {
return SquareMatrix((*this)(m.v1), (*this)(m.v2));
}
SquareMatrix operator*(const float m) const {
return SquareMatrix(v1*m, v2*m);
}
SquareMatrix operator*(const int m) const {
return SquareMatrix(v1*m, v2*m);
}
SquareMatrix operator/(const float m) const {
return SquareMatrix(v1/m, v2/m);
}
SquareMatrix operator/(const int m) const {
return SquareMatrix(v1/m, v2/m);
}
_T det() const {
return v1.x*v2.y - v1.y*v2.x;
}
SquareMatrix inverse() const {
_T tdet = det();
if(tdet == 0)
return SquareMatrix();
else
return SquareMatrix(VectorD2<_T>(v2.y,-v1.y),VectorD2<_T>(-v2.x,v1.x))/tdet;
}
// v1 is the upper-left, v2 the right-bottom
bool isInDefinedArea(const VectorD2<_T>& p) const {
return v1.x <= p.x && p.x <= v2.x && v1.y <= p.y && p.y <= v2.y;
}
VectorD2<_T> getCenter() const {
return (v1 + v2) / 2;
}
SquareMatrix getInsersectionWithArea(const SquareMatrix& a) const {
return SquareMatrix(
VectorD2<_T>( MAX(a.v1.x, v1.x), MAX(a.v1.y, v1.y) ),
VectorD2<_T>( MIN(a.v2.x, v2.x), MIN(a.v2.y, v2.y) )
);
}
};
class Parabola {
public:
float a, b, c; // a*x^2 + b*x + c
public:
Parabola() : a(0), b(0), c(0) {}
Parabola(float pa, float pb, float pc) : a(pa), b(pb), c(pc) {}
Parabola(const Parabola& p) { a = p.a; b = p.b; c = p.c; }
Parabola(CVec p1, CVec p2, CVec p3);
Parabola(CVec p1, float angleP1, CVec p2);
inline bool operator==(const Parabola& p) const {
return (a == p.a && b == p.b && c == p.c);
}
float getLength(CVec p1, CVec p2);
float getLength(float pa, float pb);
bool isPointAtParabola(CVec p1) {
return (p1.y == (a * p1.x * p1.x ) + (b * p1.x) + c);
}
};
// Random number generator with save()/restore() methods that will save and restore generator's state
// This generator should produce the same numbers on any CPU architecture, if initialized with the same seed.
// Ripped from Gnu Math library
// I don't want to use Mersenne Twister 'cuz it has a state of 624 ints which should be copied with Save()/Restore()
class SyncedRandom
{
public:
SyncedRandom( unsigned long s = getRandomSeed() )
{
if (!s)
s = 1UL; /* default seed is 1 */
z1 = LCG (s);
if (z1 < 2UL)
z1 += 2UL;
z2 = LCG (z1);
if (z2 < 8UL)
z2 += 8UL;
z3 = LCG (z2);
if (z3 < 16UL)
z3 += 16UL;
z4 = LCG (z3);
if (z4 < 128UL)
z4 += 128UL;
/* Calling RNG ten times to satify recurrence condition */
getInt(); getInt(); getInt(); getInt(); getInt();
getInt(); getInt(); getInt(); getInt(); getInt();
};
// Returns unsigned int in a range 0 : UINT_MAX
unsigned long getInt()
{
unsigned long b1, b2, b3, b4;
b1 = ((((z1 << 6UL) & MASK) ^ z1) >> 13UL);
z1 = ((((z1 & 4294967294UL) << 18UL) & MASK) ^ b1);
b2 = ((((z2 << 2UL) & MASK) ^ z2) >> 27UL);
z2 = ((((z2 & 4294967288UL) << 2UL) & MASK) ^ b2);
b3 = ((((z3 << 13UL) & MASK) ^ z3) >> 21UL);
z3 = ((((z3 & 4294967280UL) << 7UL) & MASK) ^ b3);
b4 = ((((z4 << 3UL) & MASK) ^ z4) >> 12UL);
z4 = ((((z4 & 4294967168UL) << 13UL) & MASK) ^ b4);
return (z1 ^ z2 ^ z3 ^ z4);
};
// Returns float in range 0 : 1 (1 non-inclusive)
float getFloat()
{
return getInt() / 4294967296.0f;
};
void save()
{
save_z1 = z1;
save_z2 = z2;
save_z3 = z3;
save_z4 = z4;
};
void restore()
{
z1 = save_z1;
z2 = save_z2;
z3 = save_z3;
z4 = save_z4;
};
// Returns random seed based on time() and SDL_GetTicks() functions
static unsigned long getRandomSeed();
private:
static const unsigned long MASK = 0xffffffffUL;
unsigned long LCG(unsigned long n) { return ((69069UL * n) & MASK); };
unsigned long z1, z2, z3, z4;
unsigned long save_z1, save_z2, save_z3, save_z4;
};
#endif // __MATHLIB_H__

51
src/Mutex.h Normal file
View File

@@ -0,0 +1,51 @@
/*
OpenLieroX
Mutex wrapper
created 10-02-2009 by Karel Petranek
code under LGPL
*/
#ifndef __MUTEX_H__
#define __MUTEX_H__
#include <SDL_mutex.h>
#define INVALID_THREAD_ID (Uint32)-1
class Condition;
// Mutex wrapper class with some extra debugging checks
class Mutex {
friend class Condition;
private:
SDL_mutex *m_mutex;
#ifdef DEBUG
volatile Uint32 m_lockedThread; // Thread that keeps the lock
#endif
public:
/*#ifdef DEBUG
Mutex();
~Mutex();
void lock();
void unlock();
static void test();
#else */
Mutex() { m_mutex = SDL_CreateMutex(); }
~Mutex() { SDL_DestroyMutex(m_mutex); }
void lock() { SDL_LockMutex(m_mutex); }
void unlock() { SDL_UnlockMutex(m_mutex); }
//#endif
struct ScopedLock {
Mutex& mutex;
ScopedLock(Mutex& m) : mutex(m) { mutex.lock(); }
~ScopedLock() { mutex.unlock(); }
};
};
#endif // __MUTEX_H__

43
src/Ref.h Normal file
View File

@@ -0,0 +1,43 @@
/*
OpenLieroX
various utilities
code under LGPL
created 01-05-2007
by Albert Zeyer and Dark Charlie
*/
#ifndef __OLX__REF_H__
#define __OLX__REF_H__
/*
intended to hold an object of an abstract class (interface)
Ref< Iterator<int> > is a typical example, because you normally
don't want to know about the specific implementation of Iterator
*/
template < typename _Obj >
class Ref {
private:
_Obj* m_obj;
void clear() { if(m_obj) delete m_obj; m_obj = NULL; }
public:
Ref(_Obj* obj = NULL) : m_obj(obj) {}
Ref(const Ref& ref) { m_obj = ref->copy(); }
~Ref() { clear(); }
Ref& operator=(_Obj* obj) { if(obj != m_obj) { clear(); m_obj = obj; } return *this; }
Ref& operator=(const Ref& ref) { if(ref.m_obj != m_obj) { clear(); m_obj = ref->copy(); } return *this; }
_Obj* operator->() { return m_obj; }
const _Obj* operator->() const { return m_obj; }
_Obj& get() { return *m_obj; }
const _Obj& get() const { return *m_obj; }
bool isSet() const { return m_obj != NULL; }
_Obj* overtake() { _Obj* r = m_obj; m_obj = NULL; return r; } // this resets the Ref and returns the old pointer without deleting it
};
#endif

54
src/RefCounter.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* RefCounter.h
* OpenLieroX
*
* Created by Albert Zeyer on 01.06.09.
* code under LGPL
*
*/
#ifndef __OLX__REFCOUNTER_H__
#define __OLX__REFCOUNTER_H__
#include <cstring> // for size_t
/*
* This class is to be added as an additional baseclass and overload the onLastRefRemoved method.
*/
class RefCounter {
private:
size_t* m_refCount;
// asumes that already cleared
void copy(const RefCounter& r) {
m_refCount = r.m_refCount;
(*m_refCount)++;
}
protected:
// call this manually if you aren't sure if your virtual function is already unset
void uninit() {
if(m_refCount) {
(*m_refCount)--;
size_t* ref = m_refCount;
m_refCount = NULL;
if(*ref == 0) {
delete ref;
onLastRefRemoved();
}
}
}
public:
RefCounter() : m_refCount(NULL) { m_refCount = new size_t(1); }
RefCounter(const RefCounter& r) : m_refCount(NULL) { copy(r); }
RefCounter& operator=(const RefCounter& r) { uninit(); copy(r); return *this; }
virtual ~RefCounter() { uninit(); }
size_t refCount() const { return *m_refCount; }
virtual void onLastRefRemoved() = 0;
};
#endif

263
src/SmartPointer.h Normal file
View File

@@ -0,0 +1,263 @@
/*
OpenLieroX
code under LGPL
27-12-2007 Albert Zeyer
*/
#ifndef __SMARTPOINTER_H__
#define __SMARTPOINTER_H__
#include <limits.h>
#include <cassert>
#include <SDL_mutex.h>
#ifdef DEBUG
#include <map>
#include "Debug.h"
#endif
#include "Functors.h"
#include "ThreadPool.h"
template < typename _Type, typename _SpecificInitFunctor >
class SmartPointer;
// Default de-initialization action is to call operator delete, for each object type.
template < typename _Type >
void SmartPointer_ObjectDeinit( _Type * obj )
{
delete obj;
}
// these forward-declaration are needed here
struct SDL_Surface;
struct SoundSample;
class CMap;
class CGameScript;
// Specialized de-init functions, for each simple struct-like type that has no destructor
template <> void SmartPointer_ObjectDeinit<SDL_Surface> ( SDL_Surface * obj ); // Calls gfxFreeSurface(obj);
template <> void SmartPointer_ObjectDeinit<SoundSample> ( SoundSample * obj ); // Calls FreeSoundSample(obj);
template <> void SmartPointer_ObjectDeinit<CMap> ( CMap * obj ); // Requires to be defined elsewhere
template <> void SmartPointer_ObjectDeinit<CGameScript> ( CGameScript * obj ); // Requires to be defined elsewhere
#ifdef DEBUG
extern SDL_mutex *SmartPointer_CollMutex;
extern std::map< void *, SDL_mutex * > * SmartPointer_CollisionDetector;
#endif
/*
standard smartpointer based on simple refcounting
The refcounting is multithreading safe in this class,
you can have copies of this object in different threads.
Though it's not designed to operate with the same
object in different threads. Also there is absolutly no
thread safty on the pointer itself, you have to care
about this yourself.
*/
/*template < typename _Obj >
class SmartObject;*/
template < typename _Type, typename _SpecificInitFunctor = NopFunctor<void*> >
class SmartPointer { //friend class SmartObject<_Type>;
private:
_Type* obj;
int* refCount;
SDL_mutex* mutex;
void init(_Type* newObj) {
#ifdef DEBUG
if (SmartPointer_CollMutex == NULL)
SmartPointer_CollMutex = SDL_CreateMutex();
#endif
if( newObj == NULL )
return;
if(!mutex) {
mutex = SDL_CreateMutex();
obj = newObj;
refCount = new int;
*refCount = 1;
#ifdef DEBUG
SDL_LockMutex(SmartPointer_CollMutex);
if( SmartPointer_CollisionDetector == NULL )
{
hints << "SmartPointer collision detector initialized" << endl;
SmartPointer_CollisionDetector = new std::map< void *, SDL_mutex * > ();
}
if( SmartPointer_CollisionDetector->count(obj) != 0 ) // Should be faster than find() I think
{
errors << "ERROR! SmartPointer collision detected, old mutex " << (*SmartPointer_CollisionDetector)[obj]
<< ", new ptr (" << this << " " << obj << " " << refCount << " " << mutex << " " << (refCount?*refCount:-99) << ") new " << newObj << endl;
SDL_UnlockMutex(SmartPointer_CollMutex);
assert(false); // TODO: maybe do smth like *(int *)NULL = 1; to generate coredump? Simple assert(false) won't help us a lot
}
else
SmartPointer_CollisionDetector->insert( std::make_pair( obj, mutex ) );
SDL_UnlockMutex(SmartPointer_CollMutex);
#endif
}
}
void reset() {
if(mutex) {
lock();
(*refCount)--;
if(*refCount == 0) {
#ifdef DEBUG
SDL_LockMutex(SmartPointer_CollMutex);
if( !SmartPointer_CollisionDetector || SmartPointer_CollisionDetector->count(obj) == 0 )
{
errors << "ERROR! SmartPointer already deleted reference ("
<< this << " " << obj << " " << refCount << " " << mutex << " " << (refCount?*refCount:-99) << ")" << endl;
if(!SmartPointer_CollisionDetector)
errors << "SmartPointer_CollisionDetector is already uninitialised" << endl;
SDL_UnlockMutex(SmartPointer_CollMutex);
assert(false);
}
else
{
SmartPointer_CollisionDetector->erase(obj);
if( SmartPointer_CollisionDetector->empty() )
{
delete SmartPointer_CollisionDetector;
SmartPointer_CollisionDetector = NULL;
if (SmartPointer_CollMutex)
{
SDL_DestroyMutex(SmartPointer_CollMutex);
SmartPointer_CollMutex = NULL;
}
// WARNING: this is called at a very end for global objects and most other objects are already uninitialised.
// For me, even the internal string structure doesn't work anymore (I get a std::length_error) and thus we cannot use the logging system.
// TODO: Remove any global objects! We should not have any globals, at least not such complex globals.
#ifdef DEBUG
printf("SmartPointer collision detector de-initialized, everything is freed now\n");
#endif
}
}
if( SmartPointer_CollMutex )
SDL_UnlockMutex(SmartPointer_CollMutex);
#endif
SmartPointer_ObjectDeinit( obj );
delete refCount; // safe, because there is no other ref anymore
obj = NULL;
refCount = NULL;
unlock();
SDL_DestroyMutex(mutex); // safe because there is no other ref anymore
mutex = NULL;
} else
unlock();
}
obj = NULL;
refCount = NULL;
mutex = NULL;
}
void incCounter() {
assert(*refCount > 0 && *refCount < INT_MAX);
(*refCount)++;
}
void lock() {
//printf("SmartPointer::lock (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
SDL_mutexP(mutex);
}
void unlock() {
//printf("SmartPointer::unlock (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
SDL_mutexV(mutex);
}
public:
SmartPointer() : obj(NULL), refCount(NULL), mutex(NULL) {
//printf("SmartPointer::construc(%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
_SpecificInitFunctor()(this);
}
~SmartPointer() {
//printf("SmartPointer::destruct(%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
reset();
}
// Default copy constructor and operator=
// If you specify any template<> params here these funcs will be silently ignored by compiler
SmartPointer(const SmartPointer& pt) : obj(NULL), refCount(NULL), mutex(NULL) { operator=(pt); }
SmartPointer& operator=(const SmartPointer& pt) {
if(mutex == pt.mutex) return *this; // ignore this case
reset();
mutex = pt.mutex;
if(mutex) {
lock();
obj = pt.obj; refCount = pt.refCount;
incCounter();
unlock();
} else { obj = NULL; refCount = NULL; }
return *this;
}
// WARNING: Be carefull, don't assing a pointer to different SmartPointer objects,
// else they will get freed twice in the end. Always copy the SmartPointer itself.
// In short: SmartPointer ptr(SomeObj); SmartPointer ptr1( ptr.get() ); // It's wrong, don't do that.
SmartPointer(_Type* pt): obj(NULL), refCount(NULL), mutex(NULL) { operator=(pt); }
SmartPointer& operator=(_Type* pt) {
//printf("SmartPointer::op=Type (%10p %10p %10p %10p %3i)\n", this, obj, refCount, mutex, refCount?*refCount:-99);
if(obj == pt) return *this; // ignore this case
reset();
init(pt);
return *this;
}
_Type* get() const { return obj; } // The smartpointer itself won't change when returning address of obj, so it's const.
// HINT: no convenient cast functions in this class to avoid error-prone automatic casts
// (which would lead to collisions!)
// This operator is safe though.
_Type * operator -> () const { return obj; };
// refcount may be changed from another thread, though if refcount==1 or 0 it won't change
int getRefCount() {
int ret = 0;
if(mutex) {
lock();
ret = *refCount;
unlock(); // Here the other thread may change refcount, that's why it's approximate
}
return ret;
}
// Returns true only if the data is deleted (no other smartpointer used it), sets pointer to NULL then
bool tryDeleteData() {
if(mutex) {
lock();
if( *refCount == 1 )
{
unlock(); // Locks mutex again inside reset(), since we're only ones using data refcount cannot change from other thread
reset();
return true; // Data deleted
}
unlock();
return false; // Data not deleted
}
return true; // Data was already deleted
}
};
/*
template< typename _Obj>
class SmartObject : public SmartPointer< SmartObject<_Obj> > {
public:
typedef SmartPointer< SmartObject<_Obj> > SmartPtrType;
SmartObject() { SmartPtrType :: operator =( this ); }
virtual ~SmartObject() { }
private:
// overwrite to disable this op=
SmartPtrType& operator=(const SmartPtrType& pt) { assert(false); }
};
*/
#endif

199
src/StringBuf.cpp Normal file
View File

@@ -0,0 +1,199 @@
/////////////////////////////////////////
//
// OpenLieroX
//
// code under LGPL, based on JasonBs work,
// enhanced by Dark Charlie and Albert Zeyer
//
//
/////////////////////////////////////////
// String Buffer
// Created 11/8/08
// Karel Petranek
#include "StringBuf.h"
#include "StringUtils.h"
#include "Debug.h"
#include "Utils.h"
// Helper functions
std::string strlwr(const std::string& s)
{
std::string res = s;
stringlwr(res);
return res;
}
/////////////////////
// Adjusts the blank characters so that there are no repeated blank characters and the blank characters are all
// turned to spaces
void StringBuf::adjustBlank()
{
// Check
if (sStr.size() < 3)
return;
// Initialize iterators
std::string::const_iterator it = sStr.begin();
std::string::const_iterator prev = it;
it++;
// Get the adjusted string
std::string res;
res += *sStr.begin(); // First character, sStr != "" here
for (; it != sStr.end(); it++, prev++) {
if (isspace((unsigned char)*it)) { // Blank
if (isspace((unsigned char)*prev)) // Previous also blank, ignroe
continue;
else { // Previous not blank, convert to space and add
res += ' ';
continue;
}
}
res += *it; // Normal character
}
sStr = res;
tPos = sStr.begin();
}
/////////////////////
// Trims all blank characters from both sides of the string
void StringBuf::trimBlank()
{
// Start
while (sStr.size() && isspace((unsigned char)(*(sStr.begin()))))
sStr.erase(sStr.begin());
// End
while (sStr.size() && isspace((unsigned char)(*(sStr.rbegin()))))
sStr.erase(sStr.size() - 1, 1);
tPos = sStr.begin();
}
////////////////////
// Tokenizes the string buffer by blank characters, multiple blank characters are taken as one
std::vector<std::string> StringBuf::splitByBlank()
{
std::vector<std::string> res;
std::string token;
bool was_space = false;
for (std::string::iterator it = sStr.begin(); it != sStr.end(); it++) {
if (isspace((unsigned char)(*it))) {
if (was_space) // Multiple spaces get ignored
continue;
else {
res.push_back(token); // Add the token
token = "";
}
was_space = true;
continue;
}
was_space = false;
token += *it;
}
// Last token
res.push_back(token);
return res;
}
////////////////////
// Tokenizes the string buffer by blank the specified character
std::vector<std::string> StringBuf::splitBy(char c)
{
std::vector<std::string> res;
std::string token;
for (std::string::iterator it = sStr.begin(); it != sStr.end(); it++) {
if (*it == c) {
res.push_back(token); // Add the token
token = "";
continue;
}
token += *it;
}
// Last token
res.push_back(token);
return res;
}
////////////////////////
// Reads until the specified character and skips it
std::string StringBuf::readUntil(char c)
{
std::string res;
while (!atEnd() && *tPos != c) {
res += *tPos;
incPos();
}
// Skip the breaking character
if (!atEnd())
incPos();
return res;
}
////////////////////////
// Reads until one of the characters specified in char_array, NOT until the string in char_array
std::string StringBuf::readUntil(const std::string& char_array)
{
std::string res;
while (!atEnd() && char_array.find(*tPos) == std::string::npos) {
res += *tPos;
incPos();
}
// Skip the breaking character
if (!atEnd())
incPos();
return res;
}
/////////////////////////
// Reads the specified number of bytes from the buf
std::string StringBuf::read(size_t num)
{
std::string::iterator oth = tPos;
SafeAdvance(tPos, num, sStr.end());
return std::string(tPos, oth);
}
///////////////////////
// Skips any blank characters
size_t StringBuf::skipBlank()
{
size_t res = 0;
while (!atEnd() && isspace((unsigned char)(*tPos))) {
++res;
incPos();
}
return res;
}
/////////////////////
// Converts the buffer to lower case
void StringBuf::toLower()
{
stringlwr(sStr);
}
/////////////////////
// Prints the contents to stdout
void StringBuf::debugPrint()
{
notes << sStr << endl << endl;
}

74
src/StringBuf.h Normal file
View File

@@ -0,0 +1,74 @@
/////////////////////////////////////////
//
// OpenLieroX
//
// code under LGPL, based on JasonBs work,
// enhanced by Dark Charlie and Albert Zeyer
//
//
/////////////////////////////////////////
#ifndef __OLX__STRINGBUF_H__
#define __OLX__STRINGBUF_H__
// String Buffer
// Created 11/8/08
// Karel Petranek
#include <string>
#include <vector>
// String buffer class
class StringBuf {
public:
StringBuf() : sStr("") { tPos = sStr.begin(); }
StringBuf(const std::string& str) : sStr(str) { tPos = sStr.begin(); }
private:
std::string::iterator tPos;
std::string sStr;
public:
StringBuf& operator=(const StringBuf& b2) {
if (&b2 != this) {
tPos = b2.tPos;
sStr = b2.sStr;
}
return *this;
}
StringBuf& operator=(const std::string& s) {
sStr = s;
tPos = sStr.begin();
return *this;
}
StringBuf& operator=(const char *s) {
sStr = s;
tPos = sStr.begin();
return *this;
}
char getC() { return tPos == sStr.end() ? 0 : *tPos; }
void setC(char c) { if (!atEnd()) *tPos = c; }
void incPos() { tPos++; }
void decPos() { tPos--; }
void resetPos() { tPos = sStr.begin(); }
bool atEnd() { return tPos == sStr.end(); }
void erase(size_t start, size_t count) { sStr.erase(start, count); tPos = sStr.begin(); }
void toLower();
std::string readUntil(char c);
std::string readUntil(const std::string& char_array);
std::string read(size_t num);
std::string getRestStr() { return std::string(tPos, sStr.end()); }
void trimBlank();
void adjustBlank();
size_t skipBlank();
size_t size() { return sStr.size(); }
bool empty() { return sStr.size() == 0; }
const std::string& str() { return sStr; }
std::vector<std::string> splitByBlank();
std::vector<std::string> splitBy(char c);
void debugPrint();
};
#endif

1050
src/StringUtils.cpp Normal file

File diff suppressed because it is too large Load Diff

370
src/StringUtils.h Normal file
View File

@@ -0,0 +1,370 @@
/*
OpenLieroX
string utilities
code under LGPL
created 01-05-2007
by Albert Zeyer and Dark Charlie
*/
#ifndef __STRINGUTILS_H__
#define __STRINGUTILS_H__
#include <SDL.h> // for Uint32
#include <cstdio> // for FILE
#include <string>
#include <sstream>
#include <vector>
#include <cassert>
#include <list>
#include <limits.h>
#include "Color.h" // for StrToCol
#include "Iterator.h"
//
// C-string handling routines
//
// HINT: these are obsolete, use std::string where possible!!!
// Secure c-string handling macros
// WARNING: don't use expressions like buf[i++] with the macros, because the "i" variable will be incremented twice in some macros!
#define fix_markend(chrarray) \
chrarray[sizeof(chrarray)-1] = '\0';
#define fix_strnlen(chrarray) \
strnlen(chrarray,sizeof(chrarray))
#define fix_strncpy(chrarray, src) \
{ strncpy(chrarray, src, sizeof(chrarray)); \
chrarray[sizeof(chrarray)-1] = '\0'; }
#define fix_strncat(chrarray, src) \
{ size_t destlen = strnlen(chrarray, sizeof(chrarray)); \
strncpy(&chrarray[destlen], src, sizeof(chrarray)-destlen); \
chrarray[sizeof(chrarray)-1] = '\0'; }
#define dyn_markend(dest, len) \
dest[len-1] = '\0';
#define dyn_strncpy(dest, src, len) \
{ strncpy(dest, src, len); \
dest[len-1] = '\0'; }
#define dyn_strncat(dest, src, len) \
{ size_t destlen = strnlen(dest, len); \
strncpy(&dest[destlen], src, len-destlen); \
dest[len-1] = '\0'; }
// Strnlen definition for compilers that don't have it
#if !defined(__USE_GNU) && _MSC_VER <= 1200
inline size_t strnlen(const char *str, size_t maxlen) {
register size_t i;
for(i = 0; (i < maxlen) && str[i]; ++i) {}
return i;
}
#endif
// Misc cross-compiler compatibility problem solutions
#ifdef WIN32
#if (defined(_MSC_VER) && (_MSC_VER <= 1200))
inline int strncasecmp(const char *str1, const char *str2, size_t l) {
return _strnicmp(str1, str2, l);
}
#endif
# define vsnprintf _vsnprintf
# define snprintf _snprintf
# define stricmp _stricmp
# define fcloseall _fcloseall
# define strcasecmp stricmp
#else
inline void strlwr(char* string) {
if(string)
while( *string ) {
*string = (char)tolower( *string );
string++;
}
}
#endif
/////////////
// Case-insensitive comparison of two chars, behaves like stringcasecmp
int chrcasecmp(const char c1, const char c2);
/////////////
// C-string itoa for non-windows compilers (on Windows it's defined in windows.h)
#ifndef WIN32
// TODOL remove this
inline char* itoa(int val, char* buf, int base) {
int i = 29; // TODO: bad style
buf[i+1] = '\0';
do {
buf = "0123456789abcdefghijklmnopqrstuvwxyz"[val % base] + buf;
--i, val /= base;
} while(val && i);
return &buf[i+1];
}
// Cross-compiler compatibility
# define stricmp strcasecmp
#endif
//
// C++ string (std::string) routines
//
// HINT: use these where possible
void TrimSpaces(std::string& szLine);
bool replace(const std::string& text, const std::string& what, const std::string& with, std::string& result);
bool replace(std::string& text, const std::string& what, const std::string& with);
std::string replacemax(const std::string& text, const std::string& what, const std::string& with, std::string& result, int max);
std::string replacemax(const std::string& text, const std::string& what, const std::string& with, int max);
std::string strip(const std::string& text, int width);
bool stripdot(std::string& text, int width);
void ucfirst(std::string& text);
std::string ReadUntil(const std::string& text, char until_character = '\n'); // will return whole text if not found
std::string ReadUntil(const std::string& text, std::string::const_iterator& start, char until_character, const std::string& alternative = "");
std::string ReadUntil(FILE* fp, char until_character = '\n');
Color StrToCol(const std::string& str);
Color StrToCol(const std::string& str, bool& fail);
std::vector<std::string> explode(const std::string& str, const std::string& delim);
void freadstr(std::string& result, size_t maxlen, FILE *fp);
size_t fwrite(const std::string& txt, size_t len, FILE* fp);
size_t findLastPathSep(const std::string& path);
void stringlwr(std::string& txt);
std::string stringtolower(const std::string& txt);
bool strincludes(const std::string& str, const std::string& what);
short stringcasecmp(const std::string& s1, const std::string& s2);
bool stringcaseequal(const std::string& s1, const std::string& s2);
bool subStrEqual(const std::string& s1, const std::string s2, size_t p);
bool subStrCaseEqual(const std::string& s1, const std::string s2, size_t p);
inline bool strStartsWith(const std::string& str, const std::string& start) { if(start.size() > str.size()) return false; return str.substr(0,start.size()) == start; }
inline bool strCaseStartsWith(const std::string& str, const std::string& start) { if(start.size() > str.size()) return false; return subStrCaseEqual(str,start,start.size()); }
size_t maxStartingEqualStr(const std::list<std::string>& strs);
size_t maxStartingCaseEqualStr(const std::list<std::string>& strs);
std::vector<std::string> splitstring(const std::string& str, size_t maxlen, size_t maxwidth, class CFont& font);
std::string splitStringWithNewLine(const std::string& str, size_t maxlen, size_t maxwidth, class CFont& font);
std::string GetFileExtension(const std::string& filename);
std::string GetBaseFilename(const std::string& filename);
std::string GetBaseFilenameWithoutExt(const std::string& filename);
std::list<std::string> SplitFilename(const std::string& filename, size_t numPartsFromRight = (size_t)-1); // splits fn by PathSep
std::string GetDirName(const std::string& filename);
size_t stringcasefind(const std::string& text, const std::string& search_for);
size_t stringcaserfind(const std::string& text, const std::string& search_for);
std::string GetNextWord(std::string::const_iterator it, const std::string& str);
std::string Base64Encode(const std::string &data);
std::string UrlEncode(const std::string &data); // Substitute space with + and all non-alphanum symbols with %XX
std::string AutoDetectLinks(const std::string& text);
std::string HtmlEntityUnpairedBrackets(const std::string &txt);
size_t GetPosByTextWidth(const std::string& text, int width, CFont *fnt);
std::string ColToHex(Color col);
std::string EscapeHtmlTags( const std::string & src ); // Escape all "<" and ">" and "&"
bool strSeemsLikeChatCommand(const std::string& str);
inline size_t subStrCount(const std::string& str, const std::string& substr) {
size_t c = 0, p = 0;
while((p = str.find(substr, p)) != std::string::npos) { c++; p++; }
return c;
}
typedef void (*PrintOutFct) (const std::string&);
inline void NullOut(const std::string&) {}
// returns true if last char was a newline
bool PrettyPrint(const std::string& prefix, const std::string& buf, PrintOutFct printOutFct, bool firstLineWithPrefix = true);
Iterator<char>::Ref HexDump(Iterator<char>::Ref start, PrintOutFct printOutFct, size_t mark = (size_t)-1, size_t count = (size_t)-1);
inline std::string FixedWidthStr_RightFill(const std::string& str, size_t w, char c) {
assert(str.size() <= w);
return str + std::string(str.size() - w, c);
}
inline std::string FixedWidthStr_LeftFill(const std::string& str, size_t w, char c) {
assert(str.size() <= w);
return std::string(w - str.size(), c) + str;
}
inline void StripQuotes(std::string& value) {
if( value.size() >= 2 )
if( value[0] == '"' && value[value.size()-1] == '"' )
value = value.substr( 1, value.size()-2 );
}
////////////////////
// Read a fixed-length C-string from a file
inline std::string freadfixedcstr(FILE *fp, size_t maxlen) {
std::string fileData;
freadstr(fileData, maxlen, fp);
return ReadUntil(fileData, '\0');
}
///////////////////
// Convert a numerical position to iterator
inline std::string::iterator PositionToIterator(std::string& str, size_t pos) {
std::string::iterator res = str.begin();
for (size_t i=0; i < pos && res != str.end(); ++i, res++) {}
return res;
}
// Conversion functions from string to numbers
template<typename T>
T from_string(const std::string& s, std::ios_base& (*f)(std::ios_base&), bool& failed) {
std::istringstream iss(s); T t = T();
failed = (iss >> f >> t).fail();
return t;
}
template<typename T>
T from_string(const std::string& s, std::ios_base& (*f)(std::ios_base&)) {
std::istringstream iss(s); T t = T();
iss >> f >> t;
return t;
}
template<typename T>
T from_string(const std::string& s, bool& failed) {
std::istringstream iss(s); T t = T();
failed = (iss >> t).fail();
return t;
}
// Conversion functions from numbers to string
template<typename T>
std::string to_string(T val) {
std::ostringstream oss;
oss << val;
return oss.str();
}
template<>
inline std::string to_string<bool>(bool val) {
if(val) return "true"; else return "false";
}
template<>
inline std::string to_string<const char*>(const char* val) {
if(val) return val; else return "";
}
template<>
inline bool from_string<bool>(const std::string& s, bool& fail) {
std::string s1(stringtolower(s));
TrimSpaces(s1);
if( s1 == "true" || s1 == "yes" || s1 == "on" ) return true;
else if( s1 == "false" || s1 == "no" || s1 == "off" ) return false;
return from_string<int>(s, fail) != 0;
}
template<> VectorD2<int> from_string< VectorD2<int> >(const std::string& s, bool& fail);
template<> inline std::string to_string< VectorD2<int> >(VectorD2<int> v) { return "(" + to_string(v.x) + "," + to_string(v.y) + ")"; }
template<typename T>
T from_string(const std::string& s) {
bool fail; return from_string<T>(s, fail);
}
inline int atoi(const std::string& str) { return from_string<int>(str); }
inline float atof(const std::string& str) { return from_string<float>(str); }
inline std::string ftoa(float val, int precision = -1)
{
std::string res = to_string<float>(val);
if (precision != -1) {
size_t dotpos = res.find_last_of('.');
if (dotpos == std::string::npos) {
res += '.';
for (int i = 0; i < precision; i++)
res += '0';
} else {
res = res.substr(0, dotpos + precision);
}
}
return res;
}
inline std::string itoa(unsigned long num, short base=10) {
std::string buf;
do {
buf = "0123456789abcdefghijklmnopqrstuvwxyz"[num % base] + buf;
num /= base;
} while(num);
return buf;
}
// std::string itoa
inline std::string itoa(long num, short base=10) {
if(num >= 0)
return itoa((unsigned long)num, base);
else
return "-" + itoa((unsigned long)-num, base);
}
inline std::string itoa(int num, short base=10) { return itoa((long)num,base); }
inline std::string itoa(unsigned int num, short base=10) { return itoa((unsigned long)num,base); }
// If 64-bit long available?
#ifdef ULLONG_MAX
inline std::string itoa(unsigned long long num, short base=10) {
std::string buf;
do {
buf = "0123456789abcdefghijklmnopqrstuvwxyz"[num % base] + buf;
num /= base;
} while(num);
return buf;
}
#endif
template<typename _T> std::string hex(_T num) { return itoa(num,16); }
struct simple_reversestring_hasher {
size_t operator() (const std::string& str) const {
std::string::const_reverse_iterator pos = str.rbegin();
unsigned short nibble = 0;
size_t result = 0;
for(; pos != str.rend() && nibble < sizeof(size_t)*2; pos++, nibble++)
result += ((size_t)*pos % 16) << nibble*4;
return result;
}
};
struct stringcaseless {
bool operator()(const std::string& s1, const std::string& s2) const {
return stringcasecmp(s1,s2) < 0;
}
};
struct const_string_iterator {
const std::string& str;
size_t pos;
const_string_iterator(const std::string& s, size_t p = 0) : str(s), pos(p) {}
const_string_iterator& operator++() { pos++; return *this; }
const_string_iterator& operator--() { assert(pos > 0); pos--; return *this; }
bool operator==(const const_string_iterator& i) const {
return &str == &i.str && (pos == i.pos || (pos > str.size() && i.pos > str.size()));
}
bool operator!=(const const_string_iterator& i) const { return !(*this == i); }
char operator*() const { return str[pos]; }
};
#endif

93
src/ThreadPool.h Normal file
View File

@@ -0,0 +1,93 @@
/*
* ThreadPool.h
* OpenLieroX
*
* Created by Albert Zeyer on 08.02.09.
* code under LGPL
*
*/
#ifndef __OLX__THREADPOOL_H__
#define __OLX__THREADPOOL_H__
#include <set>
#include <string>
struct SDL_mutex;
struct SDL_cond;
struct SDL_Thread;
class ThreadPool;
typedef int (*ThreadFunc) (void*);
struct CmdLineIntf;
struct Action {
virtual ~Action() {}
virtual int handle() = 0;
};
struct ThreadPoolItem {
ThreadPool* pool;
SDL_Thread* thread;
std::string name;
bool working;
bool finished;
bool headless;
SDL_cond* finishedSignal;
SDL_cond* readyForNewWork;
int ret;
};
class ThreadPool {
private:
SDL_mutex* mutex;
SDL_cond* awakeThread;
SDL_cond* threadStartedWork;
SDL_cond* threadStatusChanged;
Action* nextAction; bool nextIsHeadless; std::string nextName;
ThreadPoolItem* nextData;
bool quitting;
std::set<ThreadPoolItem*> availableThreads;
std::set<ThreadPoolItem*> usedThreads;
void prepareNewThread();
static int threadWrapper(void* param);
SDL_mutex* startMutex;
public:
ThreadPool();
~ThreadPool();
ThreadPoolItem* start(ThreadFunc fct, void* param = NULL, const std::string& name = "unknown worker");
// WARNING: if you set headless, you cannot use wait() and you should not save the returned ThreadPoolItem*
ThreadPoolItem* start(Action* act, const std::string& name = "unknown worker", bool headless = false); // ThreadPool will own and free the Action
bool wait(ThreadPoolItem* thread, int* status = NULL);
bool waitAll();
void dumpState(CmdLineIntf& cli) const;
};
extern ThreadPool* threadPool;
void InitThreadPool();
void UnInitThreadPool();
template<typename _T>
struct _ThreadFuncWrapper {
typedef int (_T::* FuncPointer)();
template< FuncPointer _func >
struct Wrapper {
static int wrapper(void* obj) {
return (((_T*)obj) ->* _func)();
}
static ThreadPoolItem* startThread(_T* const obj, const std::string& name) {
return threadPool->start((ThreadFunc)&wrapper, (void*)obj, name);
}
};
};
#define StartMemberFuncInThread(T, memberfunc, name) \
_ThreadFuncWrapper<T>::Wrapper<&memberfunc>::startThread(this, name)
#endif

171
src/Unicode.h Normal file
View File

@@ -0,0 +1,171 @@
/*
OpenLieroX
UTF8/Unicode conversions
code under LGPL
created 01-05-2007
by Albert Zeyer and Dark Charlie
*/
#ifndef __UNICODE_H__
#define __UNICODE_H__
#include <SDL.h> // for Uint32
#include <string>
typedef Uint32 UnicodeChar;
typedef std::basic_string<UnicodeChar> UnicodeString;
typedef Uint16 Utf16Char;
typedef std::basic_string<Utf16Char> Utf16String;
struct ConversionItem {
UnicodeChar Unicode;
unsigned char Utf8[4];
char Ascii;
};
#define UNKNOWN_CHARACTER ' ' // Characters not in conversion table
extern ConversionItem tConversionTable[];
///////////////////////
// Moves the iterator to next unicode character in the string, returns number of bytes skipped
template<typename _Iterator1, typename _Iterator2>
inline size_t IncUtf8StringIterator(_Iterator1& it, const _Iterator2& last) {
if(it == last) return 0;
unsigned char c;
size_t res = 1;
for(++it; last != it; ++it, ++res) {
c = *it;
if(!(c&0x80) || ((c&0xC0) == 0xC0)) break;
}
return res;
}
template<typename _Iterator>
inline size_t MultIncUtf8StringIterator(_Iterator& it, const _Iterator& last, size_t count) {
size_t res = 0;
for(size_t i = 0; i < count; i++) {
if(it == last) break;
res += IncUtf8StringIterator(it, last);
}
return res;
}
///////////////////
// The iterator points at first byte of the UTF8 encoded character, returns number of bytes skipped
template<typename _Iterator1, typename _Iterator2>
inline size_t DecUtf8StringIterator(_Iterator1& it, const _Iterator2& first) {
if(it == first) return 0;
size_t res = 1;
unsigned char c;
--it;
for(; first != it; --it, ++res) {
c = *it;
if(!(c&0x80) || ((c&0xC0) == 0xC0)) break;
}
return res;
}
template<typename _Iterator>
inline _Iterator GetMultIncUtf8StringIterator(_Iterator it, const _Iterator& last, size_t count) {
MultIncUtf8StringIterator(it, last, count);
return it;
}
inline std::string::const_iterator Utf8PositionToIterator(const std::string& str, size_t pos) {
std::string::const_iterator res = str.begin();
MultIncUtf8StringIterator(res, str.end(), pos);
return res;
}
inline std::string::iterator Utf8PositionToIterator(std::string& str, size_t pos) {
std::string::iterator res = str.begin();
MultIncUtf8StringIterator(res, str.end(), pos);
return res;
}
////////////////////////
// Reads next unicode character from a UTF8 encoded string
// the iterator shows at the next character after this operation
UnicodeChar GetNextUnicodeFromUtf8(std::string::const_iterator &it, const std::string::const_iterator& last, size_t& num_skipped);
inline UnicodeChar GetNextUnicodeFromUtf8(std::string::const_iterator& it, const std::string::const_iterator& last) {
size_t tmp; return GetNextUnicodeFromUtf8(it, last, tmp); }
inline UnicodeChar GetUnicodeFromUtf8(const std::string& str, size_t pos) {
std::string::const_iterator it = Utf8PositionToIterator(str, pos);
return GetNextUnicodeFromUtf8(it, str.end());
}
////////////////////
// Gets the UTF8 representation of the unicode character (can be more bytes)
std::string GetUtf8FromUnicode(UnicodeChar ch);
inline size_t Utf8StringSize(const std::string& str) {
size_t res = 0;
std::string::const_iterator it = str.begin();
for(; it != str.end(); IncUtf8StringIterator(it, str.end()))
res++;
return res;
}
inline std::string Utf8SubStr(const std::string& str, size_t start, size_t n = (size_t)-1) {
if (n == (size_t)-1)
return std::string(Utf8PositionToIterator(str, start), str.end());
else
return std::string(
Utf8PositionToIterator(str, start),
Utf8PositionToIterator(str, start + n));
}
inline void Utf8Erase(std::string& str, size_t start, size_t n = (size_t)-1) {
std::string::iterator it = Utf8PositionToIterator(str, start);
str.erase(it, GetMultIncUtf8StringIterator(it, str.end(), n));
}
inline void Utf8Insert(std::string& str, size_t start, const std::string& s) {
str.insert(Utf8PositionToIterator(str, start), s.begin(), s.end());
}
inline void InsertUnicodeChar(std::string& str, size_t pos, UnicodeChar ch) {
std::string tmp = GetUtf8FromUnicode(ch);
Utf8Insert(str, pos, tmp);
}
// Uppercase/lowercase handling
UnicodeChar UnicodeToLower(UnicodeChar c);
UnicodeChar UnicodeToUpper(UnicodeChar c);
// Conversion functions
int FindTableIndex(UnicodeChar c);
char UnicodeCharToAsciiChar(UnicodeChar c);
std::string RemoveSpecialChars(const std::string &Utf8String);
std::string Utf16ToUtf8(const Utf16String& str);
Utf16String Utf8ToUtf16(const std::string& str);
std::string UnicodeToUtf8(const UnicodeString& str);
UnicodeString Utf8ToUnicode(const std::string& str);
#ifdef WIN32
std::string Utf8ToSystemNative(const std::string& utf8str);
std::string SystemNativeToUtf8(const std::string& natstr);
#else // Other platforms use natively utf8 (at least we suppose so)
inline std::string Utf8ToSystemNative(const std::string& utf8str) { return utf8str; }
inline std::string SystemNativeToUtf8(const std::string& natstr) { return natstr; }
#endif
size_t TransformRawToUtf8Pos(const std::string& text, size_t pos);
size_t TransformUtf8PosToRaw(const std::string& text, size_t pos);
inline size_t TransformRawToUtf8ToRaw(const std::string& src, size_t srcpos, const std::string& dest) {
return TransformUtf8PosToRaw(dest, TransformRawToUtf8Pos(src, srcpos));
}
#endif

66
src/Utils.h Normal file
View File

@@ -0,0 +1,66 @@
/*
OpenLieroX
various utilities
code under LGPL
created 01-05-2007
by Albert Zeyer and Dark Charlie
*/
#ifndef __UTILS_H__
#define __UTILS_H__
#include <stddef.h> // for size_t
#include <vector>
#include <list>
#include <cassert>
#include "MathLib.h"
template <typename _dst, typename _src>
bool isSameType(const _src& obj1, const _dst& obj2) {
if(sizeof(_dst) < sizeof(_src)) return isSameType(obj2, obj1);
return dynamic_cast<const _dst*>(&obj1) != NULL;
}
/*
some very basic math functions
*/
template <class Iter> void SafeAdvance(Iter& it, size_t count, const Iter& end) {
for (size_t i=0; i < count && it != end; i++, it++) {}
}
template <typename T>
T& randomChoiceFrom(std::vector<T>& data) {
assert(data.size() > 0);
size_t i = (size_t)GetRandomInt(data.size() - 1);
return data[i];
}
template <typename T>
int highestBit(T d) {
for(int i = sizeof(T) * 8 - 1; i >= 0; --i)
if((1 << i) <= d) return i + 1;
return 0;
}
class DontCopyTag {
public:
DontCopyTag() {}
private:
DontCopyTag(const DontCopyTag&) { assert(false); }
DontCopyTag& operator=(const DontCopyTag&) { assert(false); }
};
template<typename T>
std::vector<T> ListAsVector(const std::list<T>& l) {
return std::vector<T>(l.begin(), l.end());
}
#endif

View File

@@ -1,442 +1,443 @@
/* ESEQ_EP1.C
Ending sequence for Episode 1.
*/
#include "keen.h"
#include "include/game.h"
#include "include/gamedo.h"
#include "include/gamepdo.h"
#include "sdl/CInput.h"
#include "sdl/CTimer.h"
#include "include/eseq_ep1.h"
#include "include/eseq_ep2.h"
#include "include/menu.h"
#include "CGraphics.h"
#define CMD_MOVE 0
#define CMD_WAIT 1
#define CMD_SPAWNSPR 2
#define CMD_REMOVESPR 3
#define CMD_FADEOUT 4
#define CMD_ENDOFQUEUE 5
#define CMD_ENABLESCROLLING 6
#define CMD_DISABLESCROLLING 7
// start x,y map scroll position for eseq1_ShipFlys()
#define SHIPFLY_X 32
#define SHIPFLY_Y 0
// worldmap scroll position for eseq1_ReturnsToShip()
#define WM_X 40
#define WM_Y 540
#define LETTER_SHOW_SPD 30
#define RETURNTOSHIP_WAIT_TIME 600
#define SPR_SHIP_RIGHT 115
#define SPR_SHIP_LEFT 116
#define SPR_EXCLAMATION 117
#define SPR_QUESTION 118
#define SHIPSPD 4
#define BACKHOME_SHORT_WAIT_TIME 250
int eseq1_ReturnsToShip(stCloneKeenPlus *pCKP)
{
int i;
for(i=0;i<MAX_LEVELS;i++)
pCKP->Control.levelcontrol.levels_completed[i] = 0;
showmapatpos(80, WM_X, WM_Y, 0, pCKP);
// draw keen next to his ship
g_pGraphics->drawSprite(168, 85, PMAPLEFTFRAME, 0);
// do not show player when we render the screen
numplayers = 1;
player[0].x = 0;
player[0].y = 0;
player[0].playframe = BlankSprite;
// all objects -> nonexistant
for(i=0;i<MAX_OBJECTS;i++) objects[i].exists = 0;
fade.mode = FADE_GO;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
eseq_showmsg(getstring("EP1_ESEQ_PART1"),1,18,37,6,1, pCKP);
// fade out
fade.mode = FADE_GO;
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
do
{
gamedo_fades();
gamedo_AnimatedTiles();
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(fade.mode != FADE_COMPLETE && !g_pInput->getPressedKey(KQUIT));
return 0;
}
void addshipqueue(int cmd, int time, int flag1)
{
shipqueue[ShipQueuePtr].cmd = cmd;
shipqueue[ShipQueuePtr].time = time;
shipqueue[ShipQueuePtr].flag1 = flag1;
ShipQueuePtr++;
}
int eseq1_ShipFlys(stCloneKeenPlus *pCKP)
{
char enter,lastenterstate;
int x, y;
int scrollingon;
scrollingon = 1;
#define MARK_SPR_NUM 5
initgame(pCKP);
// set up the ship's route
ShipQueuePtr = 0;
addshipqueue(CMD_MOVE, 230, DUP);
addshipqueue(CMD_WAIT, 50, 0);
addshipqueue(CMD_MOVE, 2690, DDOWNRIGHT);
addshipqueue(CMD_WAIT, 100, 0);
addshipqueue(CMD_MOVE, 480, DDOWN);
addshipqueue(CMD_WAIT, 150, 0);
addshipqueue(CMD_SPAWNSPR, 0, SPR_QUESTION);
addshipqueue(CMD_DISABLESCROLLING, 0, 0);
addshipqueue(CMD_WAIT, 350, 0);
addshipqueue(CMD_REMOVESPR, 0, 0);
addshipqueue(CMD_WAIT, 50, 0);
addshipqueue(CMD_MOVE, 700, DLEFT);
addshipqueue(CMD_WAIT, 150, 0);
addshipqueue(CMD_SPAWNSPR, 0, SPR_EXCLAMATION);
addshipqueue(CMD_WAIT, 500, 0);
addshipqueue(CMD_REMOVESPR, 0, 0);
addshipqueue(CMD_WAIT, 50, 0);
addshipqueue(CMD_MOVE, 700, DRIGHT);
addshipqueue(CMD_WAIT, 25, 0);
addshipqueue(CMD_ENABLESCROLLING, 0, 0);
addshipqueue(CMD_MOVE, 465, DDOWN);
addshipqueue(CMD_FADEOUT, 0, 0);
addshipqueue(CMD_MOVE, 100, DDOWN);
addshipqueue(CMD_ENDOFQUEUE, 0, 0);
showmapatpos(81, SHIPFLY_X, SHIPFLY_Y, 0, pCKP);
objects[MARK_SPR_NUM].type = OBJ_YORP; // doesn't matter
objects[MARK_SPR_NUM].exists = 0;
objects[MARK_SPR_NUM].sprite = SPR_QUESTION;
numplayers = 1;
// place the player at the center of mars
if (map_findtile(593, &x, &y))
{ // found the tile at the center of mars
player[0].x = ((x<<4)+1)<<CSF;
player[0].y = ((y<<4)-3)<<CSF;
}
else
{
crashflag = 1;
why_term_ptr = "eseq1_shipflys(): unable to find center of Mars.";
return 1;
}
player[0].playframe = SPR_SHIP_RIGHT;
// player[0].pbgprioritycorners = 0;
fade.mode = FADE_GO;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
ShipQueuePtr = 0;
max_scroll_x = max_scroll_y = 20000;
do
{
// keep the question or exclamation mark sprite next to the player
objects[MARK_SPR_NUM].x = player[0].x + (20<<CSF);
objects[MARK_SPR_NUM].y = player[0].y - (10<<CSF);
objects[MARK_SPR_NUM].onscreen = 1;
// objects[MARK_SPR_NUM].priorityptsfound = 0;
// objects[MARK_SPR_NUM].priorityptschecked = 4;
objects[MARK_SPR_NUM].scrx = (objects[MARK_SPR_NUM].x>>CSF)-scroll_x;
objects[MARK_SPR_NUM].scry = (objects[MARK_SPR_NUM].y>>CSF)-scroll_y;
// execute the current command in the queue
if (fade.dir != FADE_OUT)
{
switch(shipqueue[ShipQueuePtr].cmd)
{
case CMD_MOVE:
switch(shipqueue[ShipQueuePtr].flag1)
{
case DUP:
player[0].y-=SHIPSPD;
player[0].playframe = SPR_SHIP_RIGHT;
break;
case DDOWN:
player[0].y+=SHIPSPD/2;
player[0].playframe = SPR_SHIP_RIGHT;
break;
case DLEFT:
player[0].x-=SHIPSPD;
player[0].playframe = SPR_SHIP_LEFT;
break;
case DRIGHT:
player[0].x+=SHIPSPD;
player[0].playframe = SPR_SHIP_RIGHT;
break;
case DDOWNRIGHT:
player[0].x+=SHIPSPD*2;
player[0].y+=SHIPSPD*0.8;
player[0].playframe = SPR_SHIP_RIGHT;
break;
}
break;
case CMD_SPAWNSPR:
objects[MARK_SPR_NUM].sprite = shipqueue[ShipQueuePtr].flag1;
objects[MARK_SPR_NUM].exists = 1;
break;
case CMD_REMOVESPR:
objects[MARK_SPR_NUM].sprite = shipqueue[ShipQueuePtr].flag1;
objects[MARK_SPR_NUM].exists = 0;
break;
case CMD_ENABLESCROLLING:
scrollingon = 1;
break;
case CMD_DISABLESCROLLING:
scrollingon = 0;
break;
case CMD_WAIT:
break;
case CMD_FADEOUT:
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
}
break;
default: break;
}
// decrease the time remaining
if (shipqueue[ShipQueuePtr].time)
{
shipqueue[ShipQueuePtr].time--;
}
else
{ // no time left on this command, go to next cmd
ShipQueuePtr++;
}
}
if (fade.dir==FADE_OUT && fade.mode==FADE_COMPLETE)
{ // we're done
return 0;
}
enter = ( g_pInput->getPressedKey(KENTER) || g_pInput->getPressedKey(KCTRL) || g_pInput->getPressedKey(KALT) );
if (enter)
{
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
}
}
lastenterstate = enter;
gamedo_fades();
gamedo_AnimatedTiles();
gamedo_frameskipping(pCKP);
if (scrollingon) gamedo_ScrollTriggers(0);
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(!g_pInput->getPressedKey(KQUIT));
return 1;
}
int eseq1_BackAtHome(stCloneKeenPlus *pCKP)
{
/*int draw;*/
int i;
char *text[10];
char strname[40];
char tempbuf[200];
short textline, showtimer;
unsigned short amountshown;
signed int waittimer;
int state;
int enter, lastenterstate;
int dlgX, dlgY, dlgW, dlgH;
#define STATE_TEXTAPPEARING 0
#define STATE_WAITASEC 1
#define STATE_FADING 2
// get pointers to all the strings we're going to be using
for(i=0;i<8;i++)
{
sprintf(strname, "EP1_ESEQ_PART2_PAGE%d", i+1);
text[i] = getstring(strname);
}
textline = 0;
amountshown = 0;
showtimer = 0;
state = STATE_TEXTAPPEARING;
lastenterstate = 1;
waittimer = 0;
finale_draw("finale.ck1", pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory);
scrollx_buf = scroll_x = 0;
scrolly_buf = scroll_y = 0;
numplayers = 1;
player[0].x = 16;
player[0].y = 16;
player[0].playframe = BlankSprite;
dlgX = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "LEFT");
dlgY = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "TOP");
dlgW = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "WIDTH");
dlgH = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "HEIGHT");
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
do
{
enter = ( g_pInput->getPressedKey(KENTER) || g_pInput->getPressedKey(KCTRL) || g_pInput->getPressedKey(KALT) );
sb_dialogbox(dlgX, dlgY, dlgW, dlgH);
// draw the current text line up to the amount currently shown
strcpy(tempbuf, text[textline]);
tempbuf[amountshown] = 0;
g_pGraphics->sb_font_draw( (unsigned char*) tempbuf, (dlgX+1)*8, (dlgY+1)*8);
if (state==STATE_TEXTAPPEARING)
{
if (enter) goto fullshow;
if (showtimer > LETTER_SHOW_SPD)
{ // it's time to show a new letter
amountshown++;
if (amountshown > strlen(text[textline]))
{ // reached end of line
state = STATE_WAITASEC;
// if (textline==8)
// waittimer = -BACKHOME_SHORT_WAIT_TIME*3;
// else
waittimer = -BACKHOME_SHORT_WAIT_TIME*2;
}
// if the last letter shown is a dash/cr ('Billy...are you a-'),
// show the rest of the text immediately
// (for when the mom shouts "WHAT IS THIS ONE-EYED GREEN THING..."
if (text[textline][amountshown]==13 && \
text[textline][amountshown-1]=='-')
{
fullshow: ;
amountshown = strlen(text[textline]);
state = STATE_WAITASEC;
waittimer = -BACKHOME_SHORT_WAIT_TIME*3;
}
showtimer = 0;
} else showtimer++;
// user pressed enter
if (enter)
{ // show all text immediately
}
}
else if (state==STATE_WAITASEC)
{
if (enter) goto nextline;
if (waittimer<BACKHOME_SHORT_WAIT_TIME)
{
waittimer++;
if (waittimer==BACKHOME_SHORT_WAIT_TIME)
{
nextline: ;
textline++;
state = STATE_TEXTAPPEARING;
amountshown = 0;
if (textline>7)
{ // end of text
break;
}
}
}
}
if (fade.dir==FADE_OUT && fade.mode==FADE_COMPLETE)
return 0;
gamedo_fades();
gamedo_frameskipping_blitonly();
lastenterstate = enter;
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
if (g_pInput->getPressedKey(KQUIT)) return 1;
} while(1);
finale_draw("finale.ck1", pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory);
eseq_ToBeContinued(pCKP);
return 1;
}
void eseq_ToBeContinued(stCloneKeenPlus *pCKP)
{
int i;
char *text;
int dlgX, dlgY, dlgW, dlgH;
// remove all objects because eseq_showmsg will call drawobjects
for(i=0;i<MAX_OBJECTS;i++)
objects[i].exists = 0;
text = getstring("TO_BE_CONTINUED");
dlgX = GetStringAttribute("TO_BE_CONTINUED", "LEFT");
dlgY = GetStringAttribute("TO_BE_CONTINUED", "TOP");
dlgW = GetStringAttribute("TO_BE_CONTINUED", "WIDTH");
dlgH = GetStringAttribute("TO_BE_CONTINUED", "HEIGHT");
eseq_showmsg(text, dlgX, dlgY, dlgW, dlgH, 0, pCKP);
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
fade.mode = FADE_GO;
do
{
gamedo_fades();
if (g_pInput->getPressedKey(KQUIT)) return;
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(fade.mode == FADE_GO);
}
/* ESEQ_EP1.C
Ending sequence for Episode 1.
*/
#include "keen.h"
#include "include/game.h"
#include "include/gamedo.h"
#include "include/gamepdo.h"
#include "sdl/CInput.h"
#include "sdl/CTimer.h"
#include "include/eseq_ep1.h"
#include "include/eseq_ep2.h"
#include "include/menu.h"
#include "CGraphics.h"
#include "StringUtils.h"
#define CMD_MOVE 0
#define CMD_WAIT 1
#define CMD_SPAWNSPR 2
#define CMD_REMOVESPR 3
#define CMD_FADEOUT 4
#define CMD_ENDOFQUEUE 5
#define CMD_ENABLESCROLLING 6
#define CMD_DISABLESCROLLING 7
// start x,y map scroll position for eseq1_ShipFlys()
#define SHIPFLY_X 32
#define SHIPFLY_Y 0
// worldmap scroll position for eseq1_ReturnsToShip()
#define WM_X 40
#define WM_Y 540
#define LETTER_SHOW_SPD 30
#define RETURNTOSHIP_WAIT_TIME 600
#define SPR_SHIP_RIGHT 115
#define SPR_SHIP_LEFT 116
#define SPR_EXCLAMATION 117
#define SPR_QUESTION 118
#define SHIPSPD 4
#define BACKHOME_SHORT_WAIT_TIME 250
int eseq1_ReturnsToShip(stCloneKeenPlus *pCKP)
{
int i;
for(i=0;i<MAX_LEVELS;i++)
pCKP->Control.levelcontrol.levels_completed[i] = 0;
showmapatpos(80, WM_X, WM_Y, 0, pCKP);
// draw keen next to his ship
g_pGraphics->drawSprite(168, 85, PMAPLEFTFRAME, 0);
// do not show player when we render the screen
numplayers = 1;
player[0].x = 0;
player[0].y = 0;
player[0].playframe = BlankSprite;
// all objects -> nonexistant
for(i=0;i<MAX_OBJECTS;i++) objects[i].exists = 0;
fade.mode = FADE_GO;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
eseq_showmsg(getstring("EP1_ESEQ_PART1"),1,18,37,6,1, pCKP);
// fade out
fade.mode = FADE_GO;
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
do
{
gamedo_fades();
gamedo_AnimatedTiles();
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(fade.mode != FADE_COMPLETE && !g_pInput->getPressedKey(KQUIT));
return 0;
}
void addshipqueue(int cmd, int time, int flag1)
{
shipqueue[ShipQueuePtr].cmd = cmd;
shipqueue[ShipQueuePtr].time = time;
shipqueue[ShipQueuePtr].flag1 = flag1;
ShipQueuePtr++;
}
int eseq1_ShipFlys(stCloneKeenPlus *pCKP)
{
char enter,lastenterstate;
int x, y;
int scrollingon;
scrollingon = 1;
#define MARK_SPR_NUM 5
initgame(pCKP);
// set up the ship's route
ShipQueuePtr = 0;
addshipqueue(CMD_MOVE, 230, DUP);
addshipqueue(CMD_WAIT, 50, 0);
addshipqueue(CMD_MOVE, 2690, DDOWNRIGHT);
addshipqueue(CMD_WAIT, 100, 0);
addshipqueue(CMD_MOVE, 480, DDOWN);
addshipqueue(CMD_WAIT, 150, 0);
addshipqueue(CMD_SPAWNSPR, 0, SPR_QUESTION);
addshipqueue(CMD_DISABLESCROLLING, 0, 0);
addshipqueue(CMD_WAIT, 350, 0);
addshipqueue(CMD_REMOVESPR, 0, 0);
addshipqueue(CMD_WAIT, 50, 0);
addshipqueue(CMD_MOVE, 700, DLEFT);
addshipqueue(CMD_WAIT, 150, 0);
addshipqueue(CMD_SPAWNSPR, 0, SPR_EXCLAMATION);
addshipqueue(CMD_WAIT, 500, 0);
addshipqueue(CMD_REMOVESPR, 0, 0);
addshipqueue(CMD_WAIT, 50, 0);
addshipqueue(CMD_MOVE, 700, DRIGHT);
addshipqueue(CMD_WAIT, 25, 0);
addshipqueue(CMD_ENABLESCROLLING, 0, 0);
addshipqueue(CMD_MOVE, 465, DDOWN);
addshipqueue(CMD_FADEOUT, 0, 0);
addshipqueue(CMD_MOVE, 100, DDOWN);
addshipqueue(CMD_ENDOFQUEUE, 0, 0);
showmapatpos(81, SHIPFLY_X, SHIPFLY_Y, 0, pCKP);
objects[MARK_SPR_NUM].type = OBJ_YORP; // doesn't matter
objects[MARK_SPR_NUM].exists = 0;
objects[MARK_SPR_NUM].sprite = SPR_QUESTION;
numplayers = 1;
// place the player at the center of mars
if (map_findtile(593, &x, &y))
{ // found the tile at the center of mars
player[0].x = ((x<<4)+1)<<CSF;
player[0].y = ((y<<4)-3)<<CSF;
}
else
{
crashflag = 1;
why_term_ptr = "eseq1_shipflys(): unable to find center of Mars.";
return 1;
}
player[0].playframe = SPR_SHIP_RIGHT;
// player[0].pbgprioritycorners = 0;
fade.mode = FADE_GO;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
ShipQueuePtr = 0;
max_scroll_x = max_scroll_y = 20000;
do
{
// keep the question or exclamation mark sprite next to the player
objects[MARK_SPR_NUM].x = player[0].x + (20<<CSF);
objects[MARK_SPR_NUM].y = player[0].y - (10<<CSF);
objects[MARK_SPR_NUM].onscreen = 1;
// objects[MARK_SPR_NUM].priorityptsfound = 0;
// objects[MARK_SPR_NUM].priorityptschecked = 4;
objects[MARK_SPR_NUM].scrx = (objects[MARK_SPR_NUM].x>>CSF)-scroll_x;
objects[MARK_SPR_NUM].scry = (objects[MARK_SPR_NUM].y>>CSF)-scroll_y;
// execute the current command in the queue
if (fade.dir != FADE_OUT)
{
switch(shipqueue[ShipQueuePtr].cmd)
{
case CMD_MOVE:
switch(shipqueue[ShipQueuePtr].flag1)
{
case DUP:
player[0].y-=SHIPSPD;
player[0].playframe = SPR_SHIP_RIGHT;
break;
case DDOWN:
player[0].y+=SHIPSPD/2;
player[0].playframe = SPR_SHIP_RIGHT;
break;
case DLEFT:
player[0].x-=SHIPSPD;
player[0].playframe = SPR_SHIP_LEFT;
break;
case DRIGHT:
player[0].x+=SHIPSPD;
player[0].playframe = SPR_SHIP_RIGHT;
break;
case DDOWNRIGHT:
player[0].x+=SHIPSPD*2;
player[0].y+=SHIPSPD*0.8;
player[0].playframe = SPR_SHIP_RIGHT;
break;
}
break;
case CMD_SPAWNSPR:
objects[MARK_SPR_NUM].sprite = shipqueue[ShipQueuePtr].flag1;
objects[MARK_SPR_NUM].exists = 1;
break;
case CMD_REMOVESPR:
objects[MARK_SPR_NUM].sprite = shipqueue[ShipQueuePtr].flag1;
objects[MARK_SPR_NUM].exists = 0;
break;
case CMD_ENABLESCROLLING:
scrollingon = 1;
break;
case CMD_DISABLESCROLLING:
scrollingon = 0;
break;
case CMD_WAIT:
break;
case CMD_FADEOUT:
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
}
break;
default: break;
}
// decrease the time remaining
if (shipqueue[ShipQueuePtr].time)
{
shipqueue[ShipQueuePtr].time--;
}
else
{ // no time left on this command, go to next cmd
ShipQueuePtr++;
}
}
if (fade.dir==FADE_OUT && fade.mode==FADE_COMPLETE)
{ // we're done
return 0;
}
enter = ( g_pInput->getPressedKey(KENTER) || g_pInput->getPressedKey(KCTRL) || g_pInput->getPressedKey(KALT) );
if (enter)
{
if (fade.dir!=FADE_OUT)
{
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
}
}
lastenterstate = enter;
gamedo_fades();
gamedo_AnimatedTiles();
gamedo_frameskipping(pCKP);
if (scrollingon) gamedo_ScrollTriggers(0);
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(!g_pInput->getPressedKey(KQUIT));
return 1;
}
int eseq1_BackAtHome(stCloneKeenPlus *pCKP)
{
/*int draw;*/
int i;
std::string text[10];
std::string strname;
std::string tempbuf;
short textline, showtimer;
unsigned short amountshown;
signed int waittimer;
int state;
int enter, lastenterstate;
int dlgX, dlgY, dlgW, dlgH;
#define STATE_TEXTAPPEARING 0
#define STATE_WAITASEC 1
#define STATE_FADING 2
// get pointers to all the strings we're going to be using
for(i=0;i<8;i++)
{
strname = "EP1_ESEQ_PART2_PAGE" + itoa(i+1);
text[i] = getstring(strname);
}
textline = 0;
amountshown = 0;
showtimer = 0;
state = STATE_TEXTAPPEARING;
lastenterstate = 1;
waittimer = 0;
finale_draw("finale.ck1", pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory);
scrollx_buf = scroll_x = 0;
scrolly_buf = scroll_y = 0;
numplayers = 1;
player[0].x = 16;
player[0].y = 16;
player[0].playframe = BlankSprite;
dlgX = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "LEFT");
dlgY = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "TOP");
dlgW = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "WIDTH");
dlgH = GetStringAttribute("EP1_ESEQ_PART2_PAGE1", "HEIGHT");
fade.mode = FADE_GO;
fade.rate = FADE_NORM;
fade.dir = FADE_IN;
fade.curamt = 0;
fade.fadetimer = 0;
do
{
enter = ( g_pInput->getPressedKey(KENTER) || g_pInput->getPressedKey(KCTRL) || g_pInput->getPressedKey(KALT) );
sb_dialogbox(dlgX, dlgY, dlgW, dlgH);
// draw the current text line up to the amount currently shown
tempbuf = text[textline];
tempbuf.erase(amountshown);
g_pGraphics->sb_font_draw( tempbuf, (dlgX+1)*8, (dlgY+1)*8);
if (state==STATE_TEXTAPPEARING)
{
if (enter) goto fullshow;
if (showtimer > LETTER_SHOW_SPD)
{ // it's time to show a new letter
amountshown++;
if (amountshown > text[textline].size())
{ // reached end of line
state = STATE_WAITASEC;
// if (textline==8)
// waittimer = -BACKHOME_SHORT_WAIT_TIME*3;
// else
waittimer = -BACKHOME_SHORT_WAIT_TIME*2;
}
// if the last letter shown is a dash/cr ('Billy...are you a-'),
// show the rest of the text immediately
// (for when the mom shouts "WHAT IS THIS ONE-EYED GREEN THING..."
if (text[textline][amountshown]==13 && \
text[textline][amountshown-1]=='-')
{
fullshow: ;
amountshown = text[textline].size();
state = STATE_WAITASEC;
waittimer = -BACKHOME_SHORT_WAIT_TIME*3;
}
showtimer = 0;
} else showtimer++;
// user pressed enter
if (enter)
{ // show all text immediately
}
}
else if (state==STATE_WAITASEC)
{
if (enter) goto nextline;
if (waittimer<BACKHOME_SHORT_WAIT_TIME)
{
waittimer++;
if (waittimer==BACKHOME_SHORT_WAIT_TIME)
{
nextline: ;
textline++;
state = STATE_TEXTAPPEARING;
amountshown = 0;
if (textline>7)
{ // end of text
break;
}
}
}
}
if (fade.dir==FADE_OUT && fade.mode==FADE_COMPLETE)
return 0;
gamedo_fades();
gamedo_frameskipping_blitonly();
lastenterstate = enter;
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
if (g_pInput->getPressedKey(KQUIT)) return 1;
} while(1);
finale_draw("finale.ck1", pCKP->GameData[pCKP->Resources.GameSelected-1].DataDirectory);
eseq_ToBeContinued(pCKP);
return 1;
}
void eseq_ToBeContinued(stCloneKeenPlus *pCKP)
{
int i;
std::string text;
int dlgX, dlgY, dlgW, dlgH;
// remove all objects because eseq_showmsg will call drawobjects
for(i=0;i<MAX_OBJECTS;i++)
objects[i].exists = 0;
text = getstring("TO_BE_CONTINUED");
dlgX = GetStringAttribute("TO_BE_CONTINUED", "LEFT");
dlgY = GetStringAttribute("TO_BE_CONTINUED", "TOP");
dlgW = GetStringAttribute("TO_BE_CONTINUED", "WIDTH");
dlgH = GetStringAttribute("TO_BE_CONTINUED", "HEIGHT");
eseq_showmsg(text, dlgX, dlgY, dlgW, dlgH, 0, pCKP);
fade.dir = FADE_OUT;
fade.curamt = PAL_FADE_SHADES;
fade.fadetimer = 0;
fade.rate = FADE_NORM;
fade.mode = FADE_GO;
do
{
gamedo_fades();
if (g_pInput->getPressedKey(KQUIT)) return;
g_pInput->pollEvents();
g_pTimer->SpeedThrottle();
} while(fade.mode == FADE_GO);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,12 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __CG_FILEIO2_H__
#define __CG_FILEIO2_H__
#include <stdio.h>
#include <string>
#include <cstdio>
char loadstrings(const char *fname);
unsigned int fgeti(FILE *fp);
unsigned long fgetl(FILE *fp);
void formatPathString(char *output, const char *path);
std::string formatPathString(const std::string& path);
#ifdef __cplusplus
}
#endif

View File

@@ -6,12 +6,15 @@
*/
#include "CExeFile.h"
#include <string.h>
#include <cstring>
#include <iostream>
#include <fstream>
#include "../StringUtils.h"
using namespace std;
CExeFile::CExeFile(int episode, char *datadirectory) {
CExeFile::CExeFile(int episode, const std::string& datadirectory) {
m_episode = episode;
m_datadirectory = datadirectory;
m_data = NULL;
@@ -23,12 +26,11 @@ CExeFile::~CExeFile() {
bool CExeFile::readData()
{
char filename[256];
unsigned char *m_data_temp;
sprintf(filename, "data/%skeen%d.exe", m_datadirectory, m_episode);
std::string filename = "data/" + m_datadirectory + "keen" + itoa(m_episode) + ".exe";
ifstream File(filename,ios::binary);
std::ifstream File(filename.c_str(),ios::binary);
if(!File) return false;

View File

@@ -12,11 +12,11 @@
#define CEXEFILE_H_
#include <vector>
using namespace std;
#include <string>
class CExeFile {
public:
CExeFile(int episode, char *datadirectory);
CExeFile(int episode, const std::string& datadirectory);
virtual ~CExeFile();
bool readData();
@@ -27,10 +27,10 @@ private:
int m_datasize;
int m_episode;
unsigned char *m_data;
char *m_datadirectory;
std::string m_datadirectory;
int get_bit(int *p_bit_count, unsigned char *fin, int *posin);
int unlzexe(unsigned char *fin, vector<unsigned char> *outbuffer);
int unlzexe(unsigned char *fin, std::vector<unsigned char> *outbuffer);
};
#endif /* CEXEFILE_H_ */

View File

@@ -83,7 +83,7 @@ bool CParser::saveParseFile(void) // open, write on the file and close
if((fp=fopen(CONFIGFILENAME,"wt")))
{
list<char*>::iterator i;
std::list<char*>::iterator i;
for(i=m_filebuffer.begin() ; i != m_filebuffer.end() ; ++i )
fprintf(fp,"%s",*i);
@@ -104,7 +104,7 @@ bool CParser::saveParseFile(void) // open, write on the file and close
int CParser::getIntValue(const char *keyword, const char *category)
{
// The getter will search for category and than for keyword. After that, read the value and return it!
list<char*>::iterator i;
std::list<char*>::iterator i;
char *line;
@@ -152,7 +152,7 @@ void CParser::saveIntValue(const char *keyword, const char *category,int value)
// 2.- category exists, but keyword not
// 3.- category and keyword exist, only the value must be changed
list<char*>::iterator i;
std::list<char*>::iterator i;
char *line;

View File

@@ -10,7 +10,6 @@
#include <iostream>
#include <list>
using namespace std;
class CParser {
@@ -43,7 +42,7 @@ public:
private:
bool m_isOpen;
list<char*> m_filebuffer;
std::list<char*> m_filebuffer;
};

View File

@@ -10,11 +10,11 @@
#include <string.h>
#include <fstream>
CPatcher::CPatcher(int episode, int version,unsigned char *data, char *datadir) {
CPatcher::CPatcher(int episode, int version,unsigned char *data, const std::string& datadir) {
m_episode = episode;
m_version = version;
m_data = data;
strcpy(m_datadirectory, datadir);
m_datadirectory = datadir;
}
CPatcher::~CPatcher() {
@@ -35,7 +35,7 @@ void CPatcher::patchMemory()
// change to the proper directory
chdir("data");
chdir(m_datadirectory);
chdir(m_datadirectory.c_str());
// TODO: Extend this part further with more commands
while(!m_TextList.empty())
@@ -108,7 +108,7 @@ bool CPatcher::loadPatchfile()
{
bool ret = false;
chdir("data");
chdir(m_datadirectory);
chdir(m_datadirectory.c_str());
// Detect the patchfile
DIR *dir = opendir(".");
struct dirent *dp;
@@ -122,7 +122,7 @@ bool CPatcher::loadPatchfile()
// The file was found! now read it into the memory!
char* buf;
ifstream Patchfile(dp->d_name);
std::ifstream Patchfile(dp->d_name);
while(!Patchfile.eof())
{
@@ -157,12 +157,12 @@ bool CPatcher::loadPatchfile()
return ret;
}
void CPatcher::patchMemfromFile(const char *patch_file_name, int offset)
void CPatcher::patchMemfromFile(const std::string& patch_file_name, int offset)
{
unsigned char *buf_to_patch;
unsigned char byte;
ifstream Patchfile(patch_file_name, ios::binary);
std::ifstream Patchfile(patch_file_name.c_str(), std::ios::binary);
if(!Patchfile) return;

View File

@@ -9,15 +9,15 @@
#define CPATCHER_H_
#include <list>
using namespace std;
#include <string>
class CPatcher {
public:
CPatcher(int episode, int version,unsigned char *data, char *datadir);
CPatcher(int episode, int version,unsigned char *data, const std::string& datadir);
virtual ~CPatcher();
void patchMemory();
void patchMemfromFile(const char *patch_file_name, int offset);
void patchMemfromFile(const std::string& patch_file_name, int offset);
private:
@@ -26,9 +26,9 @@ private:
int m_episode;
int m_version;
unsigned char *m_data;
char m_datadirectory[256];
list<char*> m_TextList;
std::string m_datadirectory;
std::list<char*> m_TextList;
};

View File

@@ -12,24 +12,19 @@
#include "../include/fileio.h"
#include "../fileio/CExeFile.h"
#include "../CLogFile.h"
#include "../StringUtils.h"
int readStoryText(char **ptext, int episode, char *path)
int readStoryText(char **ptext, int episode, const std::string& path)
{
std::string buf2 = formatPathString(path);
std::string buf = buf2 + "storytxt.ck" + itoa(episode);
FILE *fp;
char buf[256];
char buf2[256];
memset(buf,0,256*sizeof(char));
formatPathString(buf2,path);
sprintf(buf,"%sstorytxt.ck%d",buf2,episode);
if((fp=fopen(buf,"rt"))==NULL)
if((fp=fopen(buf.c_str(),"rt"))==NULL)
{
sprintf(buf,"%skeen%d.exe",buf2,episode);
buf = buf2 + "keen" + itoa(episode) + ".exe";
if((fp=fopen(buf,"rb"))!=NULL)
if((fp=fopen(buf.c_str(),"rb"))!=NULL)
{
unsigned char *filebuf;
int startflag=0, endflag=0; // where story begins and ends!

View File

@@ -1,135 +1,133 @@
/* FINALE.C
Code for displaying the FINALE.CK? files.
Thanks to Andrew Durdin for FIN2BMP, from which I got
the decompression algorithm.
*/
#include "keen.h"
#include "include/fileio.h"
#include "CGraphics.h"
int finale_x;
int finale_y;
int finale_count;
int finale_planecol;
int finale_plane_length;
int finale_done;
// used internally by finale_draw()
void finale_plot(int pix)
{
int mask;
mask = 128;
do
{
if (pix & mask)
{
if (finale_planecol==1)
{
g_pGraphics->sb_setpixel(finale_x, finale_y, finale_planecol);
}
else
{ // merge with previous planes
g_pGraphics->sb_setpixel(finale_x, finale_y, g_pGraphics->sb_getpixel(finale_x, finale_y) | finale_planecol);
}
}
else if (finale_planecol==1)
{
g_pGraphics->sb_setpixel(finale_x, finale_y, 0);
}
finale_x++;
if (finale_x > 319)
{
finale_x = 0;
finale_y++;
}
finale_count++;
if (finale_count >= finale_plane_length)
{
finale_x = finale_y = 0;
finale_count = 0;
finale_planecol <<= 1;
if (finale_planecol > 8) finale_done = 1;
}
if (mask==1)
{
return;
}
else
{
mask >>= 1;
}
} while(1);
}
// draws a finale.ck? file into the upper-left corner of the scrollbuffer
void finale_draw(const char *filename, const char *path)
{
char fname[256];
FILE *fp;
int cmdbyte;
int bytecount;
int repeatbyte;
int i;
char buffer[256];
formatPathString(buffer,path);
map_unregister_all_animtiles();
sprintf(fname, "%s%s", buffer,filename);
fp = fopen(fname, "rb");
if (!fp)
{
crashflag = 1;
why_term_ptr = "finale_draw(): cannot open finake.ck? file.";
return;
}
finale_plane_length = fgetl(fp)*2; //length of a plane when decompressed
finale_planecol = 1;
finale_x = finale_y = 0;
finale_count = 0;
finale_done = 0;
/* decompress/draw the image */
do
{
cmdbyte = fgetc(fp);
if (cmdbyte<0)
{ // EOF
return;
}
if (cmdbyte & 0x80)
{
//N + 1 bytes of data follows
bytecount = (cmdbyte & 0x7F) + 1;
for(i=0;i<bytecount;i++)
{
finale_plot(fgetc(fp));
}
}
else
{
//Repeat N + 3 of following byte
bytecount = (cmdbyte + 3);
repeatbyte = fgetc(fp);
for(i=0;i<bytecount;i++)
{
finale_plot(repeatbyte);
}
}
} while(!finale_done);
fclose(fp);
}
/* FINALE.C
Code for displaying the FINALE.CK? files.
Thanks to Andrew Durdin for FIN2BMP, from which I got
the decompression algorithm.
*/
#include "keen.h"
#include "include/fileio.h"
#include "CGraphics.h"
int finale_x;
int finale_y;
int finale_count;
int finale_planecol;
int finale_plane_length;
int finale_done;
// used internally by finale_draw()
void finale_plot(int pix)
{
int mask;
mask = 128;
do
{
if (pix & mask)
{
if (finale_planecol==1)
{
g_pGraphics->sb_setpixel(finale_x, finale_y, finale_planecol);
}
else
{ // merge with previous planes
g_pGraphics->sb_setpixel(finale_x, finale_y, g_pGraphics->sb_getpixel(finale_x, finale_y) | finale_planecol);
}
}
else if (finale_planecol==1)
{
g_pGraphics->sb_setpixel(finale_x, finale_y, 0);
}
finale_x++;
if (finale_x > 319)
{
finale_x = 0;
finale_y++;
}
finale_count++;
if (finale_count >= finale_plane_length)
{
finale_x = finale_y = 0;
finale_count = 0;
finale_planecol <<= 1;
if (finale_planecol > 8) finale_done = 1;
}
if (mask==1)
{
return;
}
else
{
mask >>= 1;
}
} while(1);
}
// draws a finale.ck? file into the upper-left corner of the scrollbuffer
void finale_draw(const std::string& filename, const std::string& path)
{
FILE *fp;
int cmdbyte;
int bytecount;
int repeatbyte;
int i;
std::string buffer = formatPathString(path);
map_unregister_all_animtiles();
std::string fname = buffer + filename;
fp = fopen(fname.c_str(), "rb");
if (!fp)
{
crashflag = 1;
why_term_ptr = "finale_draw(): cannot open finake.ck? file.";
return;
}
finale_plane_length = fgetl(fp)*2; //length of a plane when decompressed
finale_planecol = 1;
finale_x = finale_y = 0;
finale_count = 0;
finale_done = 0;
/* decompress/draw the image */
do
{
cmdbyte = fgetc(fp);
if (cmdbyte<0)
{ // EOF
return;
}
if (cmdbyte & 0x80)
{
//N + 1 bytes of data follows
bytecount = (cmdbyte & 0x7F) + 1;
for(i=0;i<bytecount;i++)
{
finale_plot(fgetc(fp));
}
}
else
{
//Repeat N + 3 of following byte
bytecount = (cmdbyte + 3);
repeatbyte = fgetc(fp);
for(i=0;i<bytecount;i++)
{
finale_plot(repeatbyte);
}
}
} while(!finale_done);
fclose(fp);
}

View File

@@ -1,163 +1,162 @@
/*check if the compiler is of C++*/
#ifdef __cplusplus
extern "C" {
#endif
// gamedo.c
int gamedo_ScrollTriggers(int theplayer);
void gamedo_AnimatedTiles(void);
void gamedo_render_eraseobjects(void);
void gamedo_render_drawdebug(void);
void gamedo_render_erasedebug(void);
void gamedo_fades(void);
// gamepdo.c
// gamepdowm.c
//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, int *levels_completed);
// game.c
//void SetGameOver(void);
void overrun_detect(void);
void scrolltest(void);
//void gameloop_initialize(void);
void give_keycard(int doortile, int p);
void take_keycard(int doortile, int p);
//void open_door(int doortile, int doorsprite, int mpx, int mpy, int cp, stCloneKeenPlus *pCKP)
void extralifeat(int p);
char spawn_object(int x, int y, int otype);
void common_enemy_ai(int o);
char hitdetect(int object1, int object2);
void freezeplayer(int theplayer);
void unregister_animtiles(int tile);
//void endlevel(int success, stCloneKeenPlus *pCKP)
char checkobjsolid(unsigned int x, unsigned int y, unsigned int cp);
//void initsprites(stCloneKeenPlus *pCKP)
void CopyTileToSprite(int t, int s, int ntilestocopy, int transparent);
void GiveAnkh(int cp);
// map.c
void map_scroll_right(void);
void map_scroll_left(void);
void map_scroll_down(void);
void map_scroll_up(void);
void map_draw_vstripe(unsigned int x, unsigned int mpx);
void map_draw_hstripe(unsigned int y, unsigned int mpy);
void nosb_map_draw_vstripe(unsigned int x, unsigned int mapx);
unsigned int getmaptileat(unsigned int x, unsigned int y);
unsigned int getlevelat(unsigned int x, unsigned int y);
void drawmap(void);
void map_unregister_all_animtiles(void);
void map_deanimate(int x, int y);
int map_isanimated(int x, int y);
void map_animate(int x, int y);
char map_findobject(unsigned int obj, int *xout, int *yout);
char map_findtile(unsigned int tile, int *xout, int *yout);
void map_redraw(void);
void map_chgtile(unsigned int x,unsigned int y, int newtile);
// dos\snddrv.c
void SoundDrv_Stop(void);
void sound_do(void);
void sound_play_stereo(int snd, char mode, short balance);
void sound_play_stereo_from_coord(int snd, char mode, unsigned int xcoordinate);
void sound_play(int snd, char mode);
char sound_is_playing(int snd);
void sound_stop(int snd);
void sound_stop_all(void);
void sound_pause(void);
void sound_resume(void);
char sound_extraction_of_exe_files(char *inputpath, int episode);
// graphics.c
void DrawBitmap(int xa, int ya, int b);
void freemem(void);
void Graphics_Stop(void);
void /*inline*/ sb_setpixel(int x, int y, unsigned char c);
unsigned char sb_getpixel(int x, int y);
void drawtile(int x, int y, unsigned int t);
void drawtile_direct(int x, int y, unsigned int t);
void drawtilewithmask(int x, int y, unsigned int til, unsigned int tmask);
void drawprioritytile(int x, int y, unsigned int til);
void drawsprite_direct(int x, int y, unsigned int t);
void drawsprite(int x, int y, unsigned int s, int objectnum);
void erasesprite(int x, int y, unsigned int s, int objectnum);
void drawcharacter(int x, int y, int f);
void sb_drawcharacter(int x, int y, int f);
void sb_drawcharacterwithmask(int x, int y, int f, char mask);
void sb_drawcolorcharacter(int x, int y, int f, unsigned short colour, unsigned short bgcolour);
void sb_drawcharacterinverse(int x, int y, int f);
void save_area(int x1, int y1, int x2, int y2);
void restore_area(int x1, int y1, int x2, int y2);
void setvideomode(unsigned char mode);
void addpal(int c, int r, int g, int b);
void pal_init(int dark);
void pal_fade(int fadeamt);
void pal_apply(void);
void font_draw(unsigned char *text, int xoff, int yoff, int highlight);
void sb_font_draw(const unsigned char *text, int xoff, int yoff);
void sb_mask_font_draw(unsigned char *text, int xoff, int yoff, char mask);
void sb_color_font_draw(unsigned char *text, int xoff, int yoff, unsigned int colour, unsigned short bgcolour);
void sb_font_draw_inverse(unsigned char *text, int xoff, int yoff);
// viddrv.c
// fileio.c
//void addmaptile(unsigned int t, stCloneKeenPlus *pCKP);
//void addenemytile(unsigned int t, stCloneKeenPlus *pCKP);
//unsigned int fgeti(FILE *fp);
//unsigned long fgetl(FILE *fp);
//unsigned int loadmap(char *filename, char *path, int lvlnum, int isworldmap);
#include "fileio.h"
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);
// keydrv.c
char KeyDrv_Start(void);
void KeyDrv_Stop(void);
// misc.c
void banner(void);
void dialogbox(int x1, int y1, int w, int h);
void sb_dialogbox(int x1, int y1, int w, int h);
void statusbox(void);
int savegameiswm(char *fname);
void usage(void);
void radar(void);
void SetAllCanSupportPlayer(int o, int state);
void AllPlayersInvisible(void);
// menu.c
int GetBitmapNumberFromName(const char *bmname);
// eseq_ep1.c
void addshipqueue(int cmd, int time, int flag1);
// latch.c
//char latch_loadgraphics(int episode, char *path);
// sglre.c
void sgrle_reset(void);
void sgrle_compress(FILE *fp, unsigned char *ptr, unsigned long nbytes);
void sgrle_decompress(FILE *fp, unsigned char *ptr, unsigned long nbytes);
unsigned char sgrle_get_next_byte(FILE *fp);
// lz.c
char lz_decompress(FILE *lzfile, unsigned char *outbuffer);
// finale.c
void finale_draw(const char *filename, const char *path);
// scalerx.c
//void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height);
/*check if the compiler is of C++*/
#ifdef __cplusplus
}
#endif
#ifndef __CG_FUNCDEFS_H__
#define __CG_FUNCDEFS_H__
#include <string>
// gamedo.c
int gamedo_ScrollTriggers(int theplayer);
void gamedo_AnimatedTiles(void);
void gamedo_render_eraseobjects(void);
void gamedo_render_drawdebug(void);
void gamedo_render_erasedebug(void);
void gamedo_fades(void);
// gamepdo.c
// gamepdowm.c
//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, int *levels_completed);
// game.c
//void SetGameOver(void);
void overrun_detect(void);
void scrolltest(void);
//void gameloop_initialize(void);
void give_keycard(int doortile, int p);
void take_keycard(int doortile, int p);
//void open_door(int doortile, int doorsprite, int mpx, int mpy, int cp, stCloneKeenPlus *pCKP)
void extralifeat(int p);
char spawn_object(int x, int y, int otype);
void common_enemy_ai(int o);
char hitdetect(int object1, int object2);
void freezeplayer(int theplayer);
void unregister_animtiles(int tile);
//void endlevel(int success, stCloneKeenPlus *pCKP)
char checkobjsolid(unsigned int x, unsigned int y, unsigned int cp);
//void initsprites(stCloneKeenPlus *pCKP)
void CopyTileToSprite(int t, int s, int ntilestocopy, int transparent);
void GiveAnkh(int cp);
// map.c
void map_scroll_right(void);
void map_scroll_left(void);
void map_scroll_down(void);
void map_scroll_up(void);
void map_draw_vstripe(unsigned int x, unsigned int mpx);
void map_draw_hstripe(unsigned int y, unsigned int mpy);
void nosb_map_draw_vstripe(unsigned int x, unsigned int mapx);
unsigned int getmaptileat(unsigned int x, unsigned int y);
unsigned int getlevelat(unsigned int x, unsigned int y);
void drawmap(void);
void map_unregister_all_animtiles(void);
void map_deanimate(int x, int y);
int map_isanimated(int x, int y);
void map_animate(int x, int y);
char map_findobject(unsigned int obj, int *xout, int *yout);
char map_findtile(unsigned int tile, int *xout, int *yout);
void map_redraw(void);
void map_chgtile(unsigned int x,unsigned int y, int newtile);
// dos\snddrv.c
void SoundDrv_Stop(void);
void sound_do(void);
void sound_play_stereo(int snd, char mode, short balance);
void sound_play_stereo_from_coord(int snd, char mode, unsigned int xcoordinate);
void sound_play(int snd, char mode);
char sound_is_playing(int snd);
void sound_stop(int snd);
void sound_stop_all(void);
void sound_pause(void);
void sound_resume(void);
char sound_extraction_of_exe_files(char *inputpath, int episode);
// graphics.c
void DrawBitmap(int xa, int ya, int b);
void freemem(void);
void Graphics_Stop(void);
void /*inline*/ sb_setpixel(int x, int y, unsigned char c);
unsigned char sb_getpixel(int x, int y);
void drawtile(int x, int y, unsigned int t);
void drawtile_direct(int x, int y, unsigned int t);
void drawtilewithmask(int x, int y, unsigned int til, unsigned int tmask);
void drawprioritytile(int x, int y, unsigned int til);
void drawsprite_direct(int x, int y, unsigned int t);
void drawsprite(int x, int y, unsigned int s, int objectnum);
void erasesprite(int x, int y, unsigned int s, int objectnum);
void drawcharacter(int x, int y, int f);
void sb_drawcharacter(int x, int y, int f);
void sb_drawcharacterwithmask(int x, int y, int f, char mask);
void sb_drawcolorcharacter(int x, int y, int f, unsigned short colour, unsigned short bgcolour);
void sb_drawcharacterinverse(int x, int y, int f);
void save_area(int x1, int y1, int x2, int y2);
void restore_area(int x1, int y1, int x2, int y2);
void setvideomode(unsigned char mode);
void addpal(int c, int r, int g, int b);
void pal_init(int dark);
void pal_fade(int fadeamt);
void pal_apply(void);
void font_draw(unsigned char *text, int xoff, int yoff, int highlight);
void sb_font_draw(const unsigned char *text, int xoff, int yoff);
void sb_mask_font_draw(unsigned char *text, int xoff, int yoff, char mask);
void sb_color_font_draw(unsigned char *text, int xoff, int yoff, unsigned int colour, unsigned short bgcolour);
void sb_font_draw_inverse(unsigned char *text, int xoff, int yoff);
// viddrv.c
// fileio.c
//void addmaptile(unsigned int t, stCloneKeenPlus *pCKP);
//void addenemytile(unsigned int t, stCloneKeenPlus *pCKP);
//unsigned int fgeti(FILE *fp);
//unsigned long fgetl(FILE *fp);
//unsigned int loadmap(char *filename, char *path, int lvlnum, int isworldmap);
#include "fileio.h"
bool loadtileattributes(int episode, int version, unsigned char *filebuf);
int freestrings(void);
std::string getstring(const std::string& name);
int GetStringAttribute(const std::string& stringName, const char *attrName);
// keydrv.c
char KeyDrv_Start(void);
void KeyDrv_Stop(void);
// misc.c
void banner(void);
void dialogbox(int x1, int y1, int w, int h);
void sb_dialogbox(int x1, int y1, int w, int h);
void statusbox(void);
int savegameiswm(char *fname);
void usage(void);
void radar(void);
void SetAllCanSupportPlayer(int o, int state);
void AllPlayersInvisible(void);
// menu.c
int GetBitmapNumberFromName(const char *bmname);
// eseq_ep1.c
void addshipqueue(int cmd, int time, int flag1);
// latch.c
//char latch_loadgraphics(int episode, char *path);
// sglre.c
void sgrle_reset(void);
void sgrle_compress(FILE *fp, unsigned char *ptr, unsigned long nbytes);
void sgrle_decompress(FILE *fp, unsigned char *ptr, unsigned long nbytes);
unsigned char sgrle_get_next_byte(FILE *fp);
// lz.c
char lz_decompress(FILE *lzfile, unsigned char *outbuffer);
// finale.c
void finale_draw(const std::string& filename, const std::string& path);
// scalerx.c
//void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -22,9 +22,9 @@ CHQBitmap::~CHQBitmap() {
if(m_blackscreen){ SDL_FreeSurface(m_blackscreen); m_blackscreen = NULL;}
}
bool CHQBitmap::loadImage(const char *pFilename, int wsize, int hsize)
bool CHQBitmap::loadImage(const std::string& pFilename, int wsize, int hsize)
{
SDL_Surface *BitmapSurface = SDL_LoadBMP(pFilename);
SDL_Surface *BitmapSurface = SDL_LoadBMP(pFilename.c_str());
m_active = false;

View File

@@ -9,6 +9,7 @@
#define CHQBITMAP_H_
#include <SDL.h>
#include <string>
class CHQBitmap {
public:
@@ -17,7 +18,7 @@ public:
void setScrollposition(unsigned int xpos, unsigned int ypos);
void updateHQBitmap(SDL_Surface *m_surface, SDL_Rect *p_srcrect, SDL_Rect *p_dstrect);
bool loadImage(const char *pFilename, int wsize, int hsize);
bool loadImage(const std::string& pFilename, int wsize, int hsize);
void setAlphaBlend(Uint8 alpha);
void offsetAlphaBlend(Uint8 alpha);

View File

@@ -11,17 +11,17 @@
#include "../include/vorbis/oggsupport.h"
#include "../CLogFile.h"
short HQSndDrv_Load(SDL_AudioSpec *AudioSpec, stHQSound *psound, const char *soundfile)
short HQSndDrv_Load(SDL_AudioSpec *AudioSpec, stHQSound *psound, const std::string& soundfile)
{
SDL_AudioSpec AudioFileSpec;
SDL_AudioCVT Audio_cvt;
psound->sound_buffer = NULL;
char buf[80];
std::string buf;
FILE *fp;
sprintf(buf,"data/hqp/snd/%s.OGG",soundfile); // Start with OGG
if((fp = fopen(buf,"rb")) != NULL)
buf = "data/hqp/snd/" + soundfile + ".OGG"; // Start with OGG
if((fp = fopen(buf.c_str(),"rb")) != NULL)
{
#ifdef BUILD_WITH_OGG
if(openOGGSound(fp, &AudioFileSpec, AudioSpec->format, psound) != 0)
@@ -35,12 +35,12 @@ short HQSndDrv_Load(SDL_AudioSpec *AudioSpec, stHQSound *psound, const char *sou
#ifndef BUILD_WITH_OGG
g_pLogFile->textOut(PURPLE,"Sorry, OGG-Support is disabled!<br>");
sprintf(buf,"data/hqp/snd/%s.WAV",soundfile);
buf = "data/hqp/snd/"+ soundfile + ".WAV";
// Check, if it is a wav file or go back to classic sounds
if (SDL_LoadWAV (buf, &AudioFileSpec, &(psound->sound_buffer), &(psound->sound_len)) == NULL)
if (SDL_LoadWAV (buf.c_str(), &AudioFileSpec, &(psound->sound_buffer), &(psound->sound_len)) == NULL)
{
g_pLogFile->textOut(PURPLE,"Wave file could not be opened: \"%s\". Trying to load the classical sound<br>", buf);
g_pLogFile->textOut(PURPLE,"Wave file could not be opened: \"%s\". Trying to load the classical sound<br>", buf.c_str());
return 1;
}
@@ -48,18 +48,18 @@ short HQSndDrv_Load(SDL_AudioSpec *AudioSpec, stHQSound *psound, const char *sou
}
else
{
sprintf(buf,"data/hqp/snd/%s.WAV",soundfile);
buf = "data/hqp/snd/" + soundfile + ".WAV";
// Check, if it is a wav file or go back to classic sounds
if (SDL_LoadWAV (buf, &AudioFileSpec, &(psound->sound_buffer), &(psound->sound_len)) == NULL)
if (SDL_LoadWAV (buf.c_str(), &AudioFileSpec, &(psound->sound_buffer), &(psound->sound_len)) == NULL)
{
g_pLogFile->textOut(PURPLE,"Wave file could not be opened: \"%s\". Trying to load the classical sounds<br>", buf);
g_pLogFile->textOut(PURPLE,"Wave file could not be opened: \"%s\". Trying to load the classical sounds<br>", buf.c_str());
return 1;
}
}
psound->sound_pos = 0;
g_pLogFile->textOut(PURPLE,"File \"%s\" opened successfully!<br>", buf);
g_pLogFile->textOut(PURPLE,"File \"%s\" opened successfully!<br>", buf.c_str());
int ret;
/* Build AudioCVT (This is needed for the conversion from one format to the one used in the game)*/

View File

@@ -5,15 +5,21 @@
* Author: gerstrong
*/
#include <SDL.h>
#ifndef __CG_HQ_SOUND_H__
#define __CG_HQ_SOUND_H__
typedef struct stHQSound
#include <SDL.h>
#include <string>
struct stHQSound
{
Uint8 *sound_buffer;
Uint32 sound_len;
int sound_pos;
bool enabled;
} stHQSound;
};
short HQSndDrv_Load(SDL_AudioSpec *AudioSpec, stHQSound *psound, const char *soundfile);
short HQSndDrv_Load(SDL_AudioSpec *AudioSpec, stHQSound *psound, const std::string& soundfile);
void HQSndDrv_Unload(stHQSound *psound);
#endif

View File

@@ -1,8 +1,12 @@
#ifndef __CG_DECLARATIONS_H__
#define __CG_DECLARATIONS_H__
#include <string>
#include <SDL.h>
#define MAX_COMMANDS 8
#define MAX_SOUND_LENGTH 1024
#define MAX_SOUNDS 50
#define MAX_STRING_LENGTH 256
#define MAX_NUMBER_OF_FILES 100
@@ -68,10 +72,11 @@ typedef struct stControl
typedef struct stGameData
{
char DataDirectory[MAX_STRING_LENGTH];
short Episode;
char Name[MAX_STRING_LENGTH];
char FileList[MAX_NUMBER_OF_FILES][MAX_STRING_LENGTH];
std::string DataDirectory;
short Episode;
std::string Name;
std::string FileList[MAX_NUMBER_OF_FILES];
stGameData() : Episode(0) {}
} stGameData;
@@ -106,3 +111,5 @@ typedef struct stNewPlayer
{
stCommand Command;
} stNewPlayer;
#endif

View File

@@ -5,10 +5,17 @@
* Author: gerstrong
*/
#ifndef __CG_ESEQ_EP2_H__
#define __CG_ESEQ_EP2_H__
#include <string>
struct stCloneKeenPlus;
int eseq2_LimpsHome(stCloneKeenPlus *pCKP);
int eseq2_TantalusRay(stCloneKeenPlus *pCKP);
void eseq2_vibrate(stCloneKeenPlus *pCKP);
int eseq2_HeadsForEarth(stCloneKeenPlus *pCKP);
int eseq2_SnowedOutside(stCloneKeenPlus *pCKP);
void eseq_showmsg(char *text, int boxleft, int boxtop, int boxwidth, int boxheight, char autodismiss, stCloneKeenPlus *pCKP);
void eseq_showmsg(const std::string& text, int boxleft, int boxtop, int boxwidth, int boxheight, char autodismiss, stCloneKeenPlus *pCKP);
#endif

View File

@@ -5,10 +5,17 @@
* Author: gerstrong
*/
unsigned int loadmap(char filename[MAX_STRING_LENGTH], char *path, int lvlnum, int isworldmap, stCloneKeenPlus *pCKP);
#ifndef __CG_FILEIO_H__
#define __CG_FILEIO_H__
#include <string>
unsigned int loadmap(const std::string& filename, const std::string& path, int lvlnum, int isworldmap, stCloneKeenPlus *pCKP);
void addmaptile(unsigned int t);
void addenemytile(unsigned int t, stCloneKeenPlus *pCKP);
short checkConsistencyofGameData(stGameData *p_GameData);
void formatPathString(char *output, const char *path);
std::string formatPathString(const std::string& path);
bool renameFilenamesLowerCase(const char *dir_name);
void assignChangeTileAttribute(stTile *tile, int episode);
#endif

View File

@@ -5,4 +5,11 @@
* Author: gerstrong
*/
int readStoryText(char **ptext, int episode, char *path);
#ifndef __CG_STORY_H__
#define __CG_STORY_H__
#include <string>
int readStoryText(char **ptext, int episode, const std::string& path);
#endif

1728
src/keen.h

File diff suppressed because it is too large Load Diff

View File

@@ -572,6 +572,7 @@ demoHeaderCorrupt: ;
short readCommandLine(int argc, char *argv[], stCloneKeenPlus *pCKP)
{
int i;
static const int MAX_STRING_LENGTH = 256;
char tempbuf[MAX_STRING_LENGTH];

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -480,7 +480,7 @@ char tempbuf[80];
#else
sprintf(tempbuf, "FPS: %03d", fps);
#endif
g_pGraphics->drawFont( (unsigned char *) tempbuf, 320-3-(strlen( (char *) tempbuf)<<3), 3, 1);
g_pGraphics->drawFont( tempbuf, 320-3-(strlen( (char *) tempbuf)<<3), 3, 1);
}
update_screen();
@@ -765,7 +765,7 @@ int y;
y = CONSOLE_MESSAGE_Y;
for(i=0;i<NumConsoleMessages;i++)
{
g_pGraphics->drawFont( (unsigned char *) cmsg[i].msg, CONSOLE_MESSAGE_X, y, 1);
g_pGraphics->drawFont( cmsg[i].msg, CONSOLE_MESSAGE_X, y, 1);
y += CONSOLE_MESSAGE_SPACING;
}
}

View File

@@ -21,7 +21,6 @@ struct st_resolution
#include <SDL.h>
#include <iostream>
#include <list>
using namespace std;
inline bool LockSurface(SDL_Surface * bmp) {
if (SDL_MUSTLOCK(bmp))
@@ -110,8 +109,8 @@ private:
st_resolution m_Resolution;
list<st_resolution> m_Resolutionlist;
list<st_resolution> :: iterator m_Resolution_pos;
std::list<st_resolution> m_Resolutionlist;
std::list<st_resolution> :: iterator m_Resolution_pos;
unsigned int Mode;
bool Fullscreen;

View File

@@ -12,6 +12,7 @@
#include "../../hqp/CMusic.h"
#include "../../vorticon/sounds.h"
#include "../../fileio/CExeFile.h"
#include "../../StringUtils.h"
#define SAFE_DELETE_ARRAY(x) if(x) delete[] x; x=NULL
@@ -44,7 +45,7 @@ CSound::~CSound() {
bool CSound::init(void)
{
char name[MAX_STRING_LENGTH];
char name[256];
SDL_AudioSpec *desired, *obtained;
desired = &AudioSpec;
@@ -297,14 +298,14 @@ playsound: ;
m_soundchannel[chnl].setupSound((unsigned short)snd, 0, true, WAVE_IN, 0, (mode==PLAY_FORCE) ? true : false );
}
char CSound::loadSoundData(unsigned short Episode, char *DataDirectory)
char CSound::loadSoundData(unsigned short Episode, const std::string& DataDirectory)
{
if(!m_active) return false;
char *path;
std::string path;
int ok;
char soundfile[80];
char buf[256];
std::string soundfile;
std::string buf;
if(m_soundslot) delete[] m_soundslot;
m_soundslot = new CSoundSlot[MAX_SOUNDS];
@@ -318,21 +319,16 @@ char CSound::loadSoundData(unsigned short Episode, char *DataDirectory)
g_pLogFile->ftextOut("sound_load_all(): loading all sounds...<br>");
char buffer[256];
formatPathString(buffer,path);
sprintf(soundfile, "%ssounds.ck%d", buffer,Episode);
soundfile = formatPathString(path) + "sounds.ck" + itoa(Episode);
FILE *p_file;
if( ( p_file = fopen(soundfile,"rb") ) == NULL )
if( ( p_file = fopen(soundfile.c_str(),"rb") ) == NULL )
{
formatPathString(buffer,path);
sprintf(buf,"keen%d.exe",Episode);
g_pLogFile->ftextOut("sound_load_all(): \"%s\" was not found in the data directory. Looking for \"%s\" in \"%s\" and trying to extract this file<br>", soundfile, buf, buffer);
extractOfExeFile(buffer, Episode);
buf = "keen" + itoa(Episode) + ".exe";
g_pLogFile->ftextOut("sound_load_all(): \"%s\" was not found in the data directory. Looking for \"%s\" in \"%s\" and trying to extract this file<br>", soundfile.c_str(), buf.c_str(), formatPathString(path).c_str());
extractOfExeFile(formatPathString(path), Episode);
}
else
fclose(p_file);
@@ -409,18 +405,16 @@ char CSound::loadSoundData(unsigned short Episode, char *DataDirectory)
the sound data.
*/
char CSound::extractOfExeFile(char *inputpath, int episode)
char CSound::extractOfExeFile(const std::string& inputpath, int episode)
{
const char *outputfname;
std::string outputfname;
int bit_count;
int pos, sounds_start, sounds_end, ret = 0;
char buffer[MAX_STRING_LENGTH];
char inputfname[MAX_STRING_LENGTH];
std::string buffer;
std::string inputfname;
pos = 0;
bit_count = 0;
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)
@@ -437,7 +431,7 @@ char CSound::extractOfExeFile(char *inputpath, int episode)
}
else
{
g_pLogFile->ftextOut("Error: Unknown keen executable name: %s<br>", inputfname);
g_pLogFile->ftextOut("Error: Unknown keen executable name: %s<br>", inputfname.c_str());
return 1;
}
@@ -446,7 +440,7 @@ char CSound::extractOfExeFile(char *inputpath, int episode)
else
{
FILE *fout;
if(!(fout = fopen(outputfname,"wb"))) ret = 1;
if(!(fout = fopen(outputfname.c_str(),"wb"))) ret = 1;
else
{
fwrite( ExeFile->getData()+sounds_start, 1, (sounds_end-sounds_start), fout);

View File

@@ -11,10 +11,12 @@
#include "../../CSingleton.h"
#define g_pSound CSound::Get()
#include <string>
#include <SDL.h>
#include "CSoundChannel.h"
#include "CSoundSlot.h"
class CSound : public CSingleton<CSound>
{
public:
@@ -23,11 +25,11 @@ public:
bool init(void);
void stop(void);
char loadSoundData(unsigned short Episode, char *DataDirectory);
char loadSoundData(unsigned short Episode, const std::string& DataDirectory);
void stopAllSounds(void);
bool forcedisPlaying(void);
char sound_load_all(const char *path);
char sound_load_all(const std::string& path);
void transform_into_logaritmic_sound(int *pcmstream, int len);
void callback(void *unused, Uint8 *stream, int len);
void pauseSound(void);
@@ -44,7 +46,7 @@ public:
void setSoundmode(int freq, bool stereo);
char extractOfExeFile(char *inputpath, int episode); // This is a special funktion. It doesn't belong here!
char extractOfExeFile(const std::string& inputpath, int episode); // This is a special funktion. It doesn't belong here!
private:
CSoundChannel *m_soundchannel;

View File

@@ -34,7 +34,7 @@ CSoundSlot::~CSoundSlot() {
// loads sound searchname from file fname, into sounds[] entry loadnum
// return value is nonzero on failure
bool CSoundSlot::loadSound(const char *fname, const char *searchname, unsigned int loadnum)
bool CSoundSlot::loadSound(const std::string& fname, const std::string& searchname, unsigned int loadnum)
{
// Unload the sound if any was previously loaded
if(m_sounddata){ delete[] m_sounddata; m_sounddata = NULL; }
@@ -57,10 +57,10 @@ bool CSoundSlot::loadSound(const char *fname, const char *searchname, unsigned i
for(i=0;i<12;i++)
name[i] = 0;
fp = fopen(fname, "rb");
fp = fopen(fname.c_str(), "rb");
if (!fp)
{
g_pLogFile->ftextOut("loadSound : Sounds file '%s' unopenable attempting load of '%s'<br>", fname, searchname);
g_pLogFile->ftextOut("loadSound : Sounds file '%s' unopenable attempting load of '%s'<br>", fname.c_str(), searchname.c_str());
return false;
}
@@ -75,12 +75,12 @@ bool CSoundSlot::loadSound(const char *fname, const char *searchname, unsigned i
priority = fgetc(fp);
garbage = fgetc(fp);
for(i=0;i<12;i++) name[i] = fgetc(fp);
if (!strcmp(name, searchname)) goto sound_found;
if (name == searchname) goto sound_found;
curheader += 0x10;
}
// sound could not be found
g_pLogFile->ftextOut("loadSound : sound %s could not be found in %s.<br>", searchname, fname);
g_pLogFile->ftextOut("loadSound : sound %s could not be found in %s.<br>", searchname.c_str(), fname.c_str());
fclose(fp);
return false;
@@ -115,7 +115,7 @@ bool CSoundSlot::loadSound(const char *fname, const char *searchname, unsigned i
memcpy(m_sounddata, tempstack, m_soundlength*sizeof(unsigned int));
g_pLogFile->ftextOut("loadSound : loaded sound %s of %d bytes.<br>", searchname, m_soundlength);
g_pLogFile->ftextOut("loadSound : loaded sound %s of %d bytes.<br>", searchname.c_str(), m_soundlength);
m_hqsound.enabled = false;
fclose(fp);

View File

@@ -15,7 +15,7 @@ public:
CSoundSlot();
virtual ~CSoundSlot();
bool loadSound(const char *fname, const char *searchname, unsigned int loadnum);
bool loadSound(const std::string& fname, const std::string& searchname, unsigned int loadnum);
void setpAudioSpec(SDL_AudioSpec *pAudioSpec){ m_pAudioSpec = pAudioSpec; }

View File

@@ -128,7 +128,7 @@ void CCredits::Render(stCloneKeenPlus *pCKP)
for(int j=0 ; j<51 ; j++)
if(scrolly+(j<<3) > -8 && scrolly+(j<<3) < 200)
g_pGraphics->sb_font_draw_inverse( (unsigned char*) scrolltext[j], mid[j], scrolly+(j<<3));
g_pGraphics->sb_font_draw_inverse( scrolltext[j], mid[j], scrolly+(j<<3));
if( g_pInput->getPressedAnyCommand() )
{

View File

@@ -77,10 +77,9 @@ void CDialog::addSeparator(void)
addOptionText("");
}
void CDialog::addOptionText(const char *text)
void CDialog::addOptionText(const std::string& text)
{
char buf[TEXT_LENGTH];
memset(buf,0,TEXT_LENGTH);
std::string buf;
// This algorithm is similar to one pointer session and
// list implementation. TextList is the head.
if(OptionTextList == NULL)
@@ -88,22 +87,21 @@ void CDialog::addOptionText(const char *text)
OptionTextList = new stTextList;
OptionTextList->nextElement = NULL;
memset(OptionTextList->text,0,TEXT_LENGTH);
OptionTextList->text = "";
strcpy(buf,text);
buf = text;
unsigned int length;
length = strlen(buf);
size_t length = buf.length();
// before the text is copied, check if that string is too long.
if(length > w-4)
{
copy(text,text+w-7,OptionTextList->text);
strcat(OptionTextList->text,"...");
OptionTextList->text = text.substr(0, w-7);
OptionTextList->text += "...";
}
else
{
strcpy(OptionTextList->text,text);
OptionTextList->text = text;
}
number_of_options = 1;
@@ -124,41 +122,41 @@ void CDialog::addOptionText(const char *text)
curTextList = (stTextList*) curTextList->nextElement;
memset(curTextList->text,0, TEXT_LENGTH);
curTextList->text = "";
number_of_options++;
strcpy(buf,text);
buf = text;
unsigned int length;
length = strlen(buf);
size_t length = buf.length();
// before the text is copied, check if that string is too long.
if(length > w-4)
{
copy(text,text+w-7,curTextList->text);
strcat(curTextList->text,"...");
curTextList->text = text.substr(0, w-7);
curTextList->text += "...";
}
else
{
strcpy(curTextList->text,text);
curTextList->text = text;
}
curTextList->nextElement = NULL;
}
}
void CDialog::setOptionText(unsigned int pos, const char *text)
void CDialog::setOptionText(unsigned int pos, const std::string& text)
{
unsigned int i;
stTextList *curTextList;
stTextList *curTextList = OptionTextList;
curTextList = OptionTextList;
for(i=0 ; i<pos ; i++)
curTextList = (stTextList*) curTextList->nextElement;
memset(curTextList->text,0,TEXT_LENGTH);
strcpy(curTextList->text,text);
for(i=0 ; i<pos ; i++) {
if(!curTextList)
// TODO: print error
return;
curTextList = curTextList->nextElement;
}
curTextList->text = text;
}
void CDialog::setDimensions(int rectx, int recty, int rectw, int recth)
@@ -197,7 +195,7 @@ void CDialog::renderDialog()
while(curTextList != NULL)
{
g_pGraphics->sb_font_draw((unsigned char*)(curTextList->text), (x+3)<<3, (y+i+1)<<3);
g_pGraphics->sb_font_draw(curTextList->text, (x+3)<<3, (y+i+1)<<3);
curTextList = (stTextList*) curTextList->nextElement;
i++;
if(i >= h-2)
@@ -287,7 +285,7 @@ void CDialog::renderOpenDialogAnimation(int x,int y, int w, int h)
isanimated = false;
}
char *CDialog::getOptionString(unsigned int pos)
std::string CDialog::getOptionString(unsigned int pos)
{
unsigned int i;
stTextList *curTextList;
@@ -327,7 +325,7 @@ bool CDialog::setNextSelection()
int i=0;
if(selection+1 < number_of_options)
{
while(strcmp(getOptionString(selection+i+1),"") == 0)
while(getOptionString(selection+i+1) == "")
i++;
selection += i;
@@ -343,7 +341,7 @@ bool CDialog::setPrevSelection()
int i=0;
if(selection-1 > 0)
{
while(strcmp(getOptionString(selection-i-1),"") == 0)
while(getOptionString(selection-i-1) == "")
i++;
selection -= i;

View File

@@ -8,13 +8,13 @@
#ifndef CDIALOG_H_
#define CDIALOG_H_
#define TEXT_LENGTH 256
#include <string>
typedef struct stTextList
struct stTextList
{
char text[TEXT_LENGTH];
void *nextElement;
}stTextList;
std::string text;
stTextList *nextElement;
};
class CDialog {
public:
@@ -25,8 +25,8 @@ public:
void drawDialogbox(int x1, int y1, int w, int h);
void setDimensions(int rectx, int recty, int rectw, int recth);
void addOptionText(const char *text);
void setOptionText(unsigned int pos, const char *text);
void addOptionText(const std::string& text);
void setOptionText(unsigned int pos, const std::string& text);
void addSeparator(void);
bool setSelection(int value);
@@ -34,7 +34,7 @@ public:
bool setPrevSelection();
int getSelection(void);
char *getOptionString(unsigned int pos);
std::string getOptionString(unsigned int pos);
void renderOpenDialogAnimation(int x,int y, int w, int h);
void animateDialogBox(bool value);

View File

@@ -12,11 +12,14 @@
#endif
#include <fstream>
#include <vector>
#include "../StringUtils.h"
using namespace std;
CEGAGraphics::CEGAGraphics(short episode, const char *path) {
CEGAGraphics::CEGAGraphics(short episode, const std::string& path) {
m_episode = episode;
strcpy(m_path, path);
m_path = path;
// EGAHEAD Structure
LatchPlaneSize = 0;
@@ -51,15 +54,15 @@ CEGAGraphics::~CEGAGraphics() {
bool CEGAGraphics::loadData()
{
char buf[256];
std::string buf;
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);
if(m_path == "")
buf = "egahead.ck" + itoa(m_episode);
else
sprintf(buf,"%s/egahead.ck%hd",m_path,m_episode);
ifstream HeadFile(buf,ios::binary);
buf = m_path + "/egahead.ck" + itoa(m_episode);
std::ifstream HeadFile(buf.c_str(),ios::binary);
if(!HeadFile)
return false;
@@ -106,10 +109,10 @@ bool CEGAGraphics::loadData()
m_Latch->loadHead(data);
if(m_path[0] == 0)
sprintf(buf,"egalatch.ck%hd",m_episode);
if(m_path == "")
buf = "egalatch.ck" + itoa(m_episode);
else
sprintf(buf,"%s/egalatch.ck%hd",m_path,m_episode);
buf = m_path + "/egalatch.ck" + itoa(m_episode);
m_Latch->loadData(buf,(compressed>>1)); // The second bit tells, if latch is compressed.
@@ -119,10 +122,10 @@ bool CEGAGraphics::loadData()
SpriteLocation);
m_Sprit->loadHead(data);
if(m_path[0] == 0)
sprintf(buf,"egasprit.ck%hd",m_episode);
if(m_path == "")
buf = "egasprit.ck" + itoa(m_episode);
else
sprintf(buf,"%s/egasprit.ck%hd",m_path,m_episode);
buf = m_path + "/egasprit.ck" + itoa(m_episode);
m_Sprit->loadData(buf,(compressed>>1));
chdir("../");

View File

@@ -14,12 +14,13 @@
#ifndef CEGAGRAPHICS_H_
#define CEGAGRAPHICS_H_
#include <string>
#include "CEGALatch.h"
#include "CEGASprit.h"
class CEGAGraphics {
public:
CEGAGraphics(short episode, const char *path);
CEGAGraphics(short episode, const std::string& path);
virtual ~CEGAGraphics();
bool loadData();
@@ -28,7 +29,7 @@ public:
private:
short m_episode;
char m_path[256];
std::string m_path;
// Part of the EGAHEAD Data Structure
// Section 1:

View File

@@ -65,12 +65,11 @@ bool CEGALatch::loadHead( char *data )
return true;
}
bool CEGALatch::loadData(const char *filename, bool compresseddata)
bool CEGALatch::loadData(const std::string& filename, bool compresseddata)
{
FILE* latchfile;
char *RawData;
latchfile = fopen(filename,"rb");
FILE* latchfile = fopen(filename.c_str(),"rb");
if(!latchfile)
return false;

View File

@@ -8,7 +8,8 @@
#ifndef CEGALATCH_H_
#define CEGALATCH_H_
#include <SDL/SDL.h>
#include <SDL.h>
#include <string>
class CEGALatch {
public:
@@ -25,7 +26,7 @@ public:
virtual ~CEGALatch();
bool loadHead(char *data );
bool loadData(const char *filename, bool compresseddata);
bool loadData(const std::string& filename, bool compresseddata);
char *RawData;

View File

@@ -71,12 +71,11 @@ bool CEGASprit::loadHead(char *data)
return true;
}
bool CEGASprit::loadData(const char *filename, bool compresseddata)
bool CEGASprit::loadData(const std::string& filename, bool compresseddata)
{
FILE* latchfile;
char *RawData;
latchfile = fopen(filename,"rb");
FILE* latchfile = fopen(filename.c_str(),"rb");
if(!latchfile)
return false;

View File

@@ -8,6 +8,8 @@
#ifndef CEGASPRIT_H_
#define CEGASPRIT_H_
#include <string>
class CEGASprit {
public:
CEGASprit(int planesize,
@@ -17,7 +19,7 @@ public:
virtual ~CEGASprit();
bool loadHead(char *data);
bool loadData(const char *filename, bool compresseddata);
bool loadData(const std::string& filename, bool compresseddata);
private:
int m_numsprites;

View File

@@ -9,9 +9,7 @@
#include <fstream>
#include <string>
using namespace std;
#include <string.h>
#include <cstring>
#include "../keen.h"
#include "../include/menu.h"
@@ -20,10 +18,14 @@ using namespace std;
#include "../sdl/CInput.h"
#include "../sdl/CTimer.h"
#include "../CGraphics.h"
#include "../StringUtils.h"
#define HIGHSCORETABLE_X 1344
#define HIGHSCORETABLE_Y 32
using namespace std;
CHighScores::CHighScores(stCloneKeenPlus *poutsideCKP) {
// Set default Scores
strcpy(Name[0],"Gerstrong");
@@ -124,8 +126,8 @@ char CHighScores::showHighScore(void)
for( i=0 ; i<7 ; i++ )
{
g_pGraphics->sb_color_font_draw((unsigned char*) Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw((unsigned char*) Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
if(Extra[i][0] == true)
g_pGraphics->drawTile(32,90+(i<<4),ItemTiles[0]);
if(Extra[i][1] == true)
@@ -140,19 +142,19 @@ char CHighScores::showHighScore(void)
{
for( i=0 ; i<7 ; i++ )
{
char buf[2];
g_pGraphics->sb_color_font_draw((unsigned char*) Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw((unsigned char*) Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
sprintf(buf,"%d",Cities[i]);
g_pGraphics->sb_color_font_draw((unsigned char*) buf,250,64+(i<<4),4,7);
std::string buf;
g_pGraphics->sb_color_font_draw(Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
buf = itoa(Cities[i]);
g_pGraphics->sb_color_font_draw(buf,250,64+(i<<4),4,7);
}
}
else
{
for( i=0 ; i<7 ; i++ )
{
g_pGraphics->sb_color_font_draw((unsigned char*) Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw((unsigned char*) Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
}
}
@@ -245,19 +247,19 @@ char CHighScores::writeHighScore(int points, bool *extras, int cities)
{
for( i=0 ; i<7 ; i++ )
{
char buf[2];
g_pGraphics->sb_color_font_draw((unsigned char*) Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw((unsigned char*) Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
sprintf(buf,"%d",Cities[i]);
g_pGraphics->sb_color_font_draw((unsigned char*) buf,250,64+(i<<4),4,7);
std::string buf;
g_pGraphics->sb_color_font_draw(Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
buf = itoa(Cities[i]);
g_pGraphics->sb_color_font_draw(buf,250,64+(i<<4),4,7);
}
}
else
{
for( i=0 ; i<7 ; i++ )
{
g_pGraphics->sb_color_font_draw((unsigned char*) Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw((unsigned char*) Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
}
}
@@ -311,7 +313,7 @@ char CHighScores::writeHighScore(int points, bool *extras, int cities)
if(g_pInput->getPressedKey(KBCKSPCE) && (WrittenName.length() > 0))
{
memset(buf,0,256);
g_pGraphics->sb_color_font_draw((unsigned char*) " ",40,64+(place<<4),4,7);
g_pGraphics->sb_color_font_draw(" ",40,64+(place<<4),4,7);
WrittenName.erase(WrittenName.length()-1);
WrittenName.copy(buf,WrittenName.length(),0);
memset(Name[place],0,16);
@@ -329,10 +331,10 @@ char CHighScores::writeHighScore(int points, bool *extras, int cities)
for( i=0 ; i<7 ; i++ )
{
if(i != place)
g_pGraphics->sb_color_font_draw((unsigned char*) Name[i],40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Name[i],40,64+(i<<4),4,7);
else
g_pGraphics->sb_color_font_draw((unsigned char*) buf,40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw((unsigned char*) Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(buf,40,64+(i<<4),4,7);
g_pGraphics->sb_color_font_draw(Score[i],200-(strlen(Score[i])<<3),64+(i<<4),4,7);
if(pCKP->Control.levelcontrol.episode == 1)
{
@@ -364,9 +366,7 @@ char CHighScores::writeHighScore(int points, bool *extras, int cities)
char CHighScores::loadHighScoreTable(void)
{
string sBuf;
char chBuf[256];
sprintf(chBuf,"%d",Episode);
std::string chBuf = itoa(Episode);
sBuf.append("data/");
sBuf.append(DataDirectory);

View File

@@ -8,6 +8,8 @@
#ifndef CHIGHSCORES_H_
#define CHIGHSCORES_H_
#include <string>
class CHighScores {
public:
CHighScores(stCloneKeenPlus *poutsideCKP);
@@ -25,7 +27,7 @@ private:
int ItemTiles[4];
char Episode;
char *DataDirectory;
std::string DataDirectory;
stCloneKeenPlus *pCKP;

View File

@@ -55,7 +55,7 @@ bool CMessages::readData(char *buf, int episode, int version)
// Now read the stuff and store it to a list
for(int pos=offset_start ; pos<offset_end ; pos++)
{
string Text;
std::string Text;
while(buf[pos] != 0)
{
@@ -68,7 +68,7 @@ bool CMessages::readData(char *buf, int episode, int version)
StringList.push_back(Text);
}
list<string> :: iterator i;
std::list<std::string> :: iterator i;
#include <iostream>
for(i=StringList.begin() ; i!=StringList.end() ; i++)

View File

@@ -12,8 +12,6 @@
#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 {
@@ -25,8 +23,8 @@ public:
char *getString(const char *IDtext);
private:
list<string> StringList;
list<string> StringIDList;
std::list<std::string> StringList;
std::list<std::string> StringIDList;
};
#endif /* CMESSAGES_H_ */