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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
168
src/CVec.h
Normal 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
133
src/Color.h
Normal 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
540
src/CrashHandler.cpp
Normal 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
25
src/CrashHandler.h
Normal 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
584
src/Debug.cpp
Normal 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
76
src/Debug.h
Normal 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
143
src/Event.h
Normal 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
101
src/EventQueue.h
Normal 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
496
src/FindFile.h
Normal 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
43
src/Functors.h
Normal 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
128
src/Iterator.h
Normal 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
266
src/MathLib.h
Normal 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
51
src/Mutex.h
Normal 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
43
src/Ref.h
Normal 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
54
src/RefCounter.h
Normal 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
263
src/SmartPointer.h
Normal 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
199
src/StringBuf.cpp
Normal 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
74
src/StringBuf.h
Normal 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
1050
src/StringUtils.cpp
Normal file
File diff suppressed because it is too large
Load Diff
370
src/StringUtils.h
Normal file
370
src/StringUtils.h
Normal 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
93
src/ThreadPool.h
Normal 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
171
src/Unicode.h
Normal 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
66
src/Utils.h
Normal 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
|
||||
|
||||
885
src/eseq_ep1.cpp
885
src/eseq_ep1.cpp
@@ -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);
|
||||
}
|
||||
|
||||
1430
src/eseq_ep2.cpp
1430
src/eseq_ep2.cpp
File diff suppressed because it is too large
Load Diff
1585
src/fileio.cpp
1585
src/fileio.cpp
File diff suppressed because it is too large
Load Diff
12
src/fileio.h
12
src/fileio.h
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
268
src/finale.cpp
268
src/finale.cpp
@@ -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);
|
||||
}
|
||||
|
||||
325
src/funcdefs.h
325
src/funcdefs.h
@@ -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
|
||||
|
||||
|
||||
1497
src/gamedo.cpp
1497
src/gamedo.cpp
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
1728
src/keen.h
File diff suppressed because it is too large
Load Diff
@@ -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];
|
||||
|
||||
|
||||
|
||||
2896
src/menu.cpp
2896
src/menu.cpp
File diff suppressed because it is too large
Load Diff
2739
src/misc.cpp
2739
src/misc.cpp
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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() )
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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("../");
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
Reference in New Issue
Block a user