summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLudovic Pouzenc <lpouzenc@gmail.com>2013-07-14 20:00:29 +0200
committerLudovic Pouzenc <lpouzenc@gmail.com>2013-07-14 20:00:29 +0200
commitaebfa9ac4b9eea848ec40f62819ecf743a807b73 (patch)
tree9d3b74ce189ff13b99c19489ec73d44529fae840 /src
parent893b33145439f68990b29a3aad3f628aede78711 (diff)
downloadmplemmings-aebfa9ac4b9eea848ec40f62819ecf743a807b73.tar.gz
mplemmings-aebfa9ac4b9eea848ec40f62819ecf743a807b73.tar.bz2
mplemmings-aebfa9ac4b9eea848ec40f62819ecf743a807b73.zip
Ajout de macros pour reduire la redondance.Parsing des fichiers level*.ini commencé.
Diffstat (limited to 'src')
-rw-r--r--src/include/data_ini.h13
-rw-r--r--src/include/parser.h5
-rw-r--r--src/parser.c172
3 files changed, 147 insertions, 43 deletions
diff --git a/src/include/data_ini.h b/src/include/data_ini.h
index 590f68e..ae6cda0 100644
--- a/src/include/data_ini.h
+++ b/src/include/data_ini.h
@@ -8,12 +8,10 @@
#define LEVEL_HEIGHT 160*2
#define MAX_PARTICLE_COLORS 16
+#define MAX_MUSIC_COUNT 32
+#define MAX_DIFFICULTY_COUNT 8
//////////////////////// LEVEL INI FILES ////////////////////////
-struct skills {
- int releaseRate, numLemmings, numToRescue, timeLimit;
- int numClimbers, numFloaters, numBlockers, numBombers, numBuilders, numBashers, numMiners, numDiggers;
-};
// Item should be an object, terrain or steel
struct levelItem {
@@ -24,7 +22,8 @@ struct levelItem {
};
struct levelIni {
- struct skills initSkills;
+ int releaseRate, numLemmings, numToRescue, timeLimit;
+ int numClimbers, numFloaters, numBlockers, numBombers, numBuilders, numBashers, numMiners, numDiggers;
int xPos;
char *style, *name;
int superLemming;
@@ -35,8 +34,12 @@ struct levelIni {
//////////////////////// LEVELPACK INI FILES ////////////////////////
struct levelPackIni {
+ char *name;
int maxFallDistance;
char *codeSeed;
+ int musicCount, levelDifficultyCount;
+ char *musics[MAX_MUSIC_COUNT];
+ char *levelDifficulty[MAX_DIFFICULTY_COUNT];
};
//////////////////////// STYLE INI FILES ////////////////////////
diff --git a/src/include/parser.h b/src/include/parser.h
index 513ec07..6127628 100644
--- a/src/include/parser.h
+++ b/src/include/parser.h
@@ -8,7 +8,6 @@ enum ini_type { ini_style, ini_levelpack, ini_level };
//#define CANNOT_BE_NEGATIVE "cannot be negative"
//#define BAD_VALUE "bad value"
-//#define MAX_OBJECT_TYPES 32
#define MAX_OBJECT_FRAMES 64
#define MAX_OBJECTS_COUNT 256
#define MAX_TERRAINS_COUNT 1024
@@ -16,8 +15,8 @@ enum ini_type { ini_style, ini_levelpack, ini_level };
#define MAX_LEMMTYPES_COUNT 256
#define MAX_SOUNDS_COUNT 32
#define MAX_NUMLEMMINGS 100
-#define STEEL_MAX_WIDTH 256
-#define STEEL_MAX_HEIGHT 256
+//#define STEEL_MAX_WIDTH 256
+//#define STEEL_MAX_HEIGHT 256
int loadIni(enum ini_type type, const char *filepath, gameIni_t *ini);
diff --git a/src/parser.c b/src/parser.c
index 18924b6..d139436 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,29 +1,65 @@
#include "parser.h"
-
#include "minIni.h"
-/*
-long ini_getl(const mTCHAR *Section, const mTCHAR *Key, long DefValue, const mTCHAR *Filename);
-int ini_gets(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *DefValue, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
-
-int ini_getsection(int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
-int ini_getkey(const mTCHAR *Section, int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
+#define MATCH_INT(keysymbol) \
+ do { \
+ if (SDL_strcasecmp(key,#keysymbol)==0) { \
+ data->keysymbol = SDL_atoi(value); \
+ return 1; \
+ } \
+ } while(0)
+
+#define MATCH_HEXCOLOR(keysymbol) \
+ do { \
+ if (SDL_strcasecmp(key,#keysymbol)==0) { \
+ data->keysymbol = hextext2rgb(value); \
+ return 1; \
+ } \
+ } while(0)
+
+
+#define MATCH_STRING(keysymbol) \
+ do { \
+ if (SDL_strcasecmp(key,#keysymbol)==0) { \
+ data->keysymbol = SDL_strdup(value); \
+ return 1; \
+ } \
+ } while(0)
+
+#define MATCH_STRING_ARRAY(keysymbol,keysymlen,keyidxmax,outofrangeerrnum) \
+ do { \
+ if (SDL_strncasecmp(key,#keysymbol,keysymlen)==0 && key[keysymlen]=='_') { \
+ int k = atoi(value+keysymlen+1); \
+ if (k<0 || k>keyidxmax) { *err=outofrangeerrnum; return 0; } \
+ if (data->keysymbol##Count < k) data->keysymbol##Count = k+1; \
+ data->keysymbol##s[k] = SDL_strdup(value); \
+ return 0; \
+ } \
+ } while(0)
+
+#define MATCH_INT_ARRAY_MALLOC(keysymbol,keysymlen,outofrangeerrnum,minval,maxval,valoutofrangeerrnum) \
+ do { \
+ if (SDL_strncasecmp(key,#keysymbol,keysymlen)==0 && key[keysymlen]=='_') { \
+ int k = atoi(value+keysymlen+1); \
+ if ( k<0 || k > data->objectCount) { *err=outofrangeerrnum; return 0; } \
+ int v = atoi(value); \
+ if ( v<minval || v>maxval) { *err=valoutofrangeerrnum; return 0; } \
+ data->objects[k].keysymbol = v; \
+ } \
+ return 0; \
+ } while(0)
-typedef int (*INI_CALLBACK)(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const void *UserData);
-int ini_browse(INI_CALLBACK Callback, const void *UserData, const mTCHAR *Filename);
-*/
+int callback_ini_style (const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData);
+int callback_ini_levelpack (const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData);
+int callback_ini_level_pass1(const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData);
+int callback_ini_level_pass2(const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData);
+// struct for void *UserData pointer (app context passed to each callback func)
typedef struct {
int error_code;
gameIni_t *ini;
} parserState_t;
-int callback_ini_style (const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData);
-int callback_ini_levelpack (const mTCHAR *Section, const mTCHAR *key, const mTCHAR *value, const void *userData);
-int callback_ini_level_pass1(const mTCHAR *Section, const mTCHAR *key, const mTCHAR *value, const void *userData);
-int callback_ini_level_pass2(const mTCHAR *Section, const mTCHAR *key, const mTCHAR *value, const void *userData);
-
-
int loadIni(enum ini_type type, const char *filepath, gameIni_t *ini) {
int res;
parserState_t state;
@@ -46,33 +82,37 @@ int loadIni(enum ini_type type, const char *filepath, gameIni_t *ini) {
res=ini_browse(callback_ini_level_pass2, UserData, filepath);
return state.error_code;
}
- return -1; // Unreachable
+ return -1; // should be unreachable
}
uint32_t hextext2rgb(const char str[]) {
int res;
unsigned int val;
res=SDL_sscanf(str,"0x%x",&val);
- // Default value to opaque white. Should be visible on screen if problem here
+ // Default value to opaque white. Should be visible on screen if problem with that
return (res!=1)?0xffffffff:(uint32_t)val;
}
int callback_ini_style(const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData) {
gameIni_t *ini = ((parserState_t*) userData)->ini;
+ struct styleIni *data = &( ((parserState_t*) userData)->ini->style );
int *err= &(((parserState_t*) userData)->error_code);
- // styles/*.ini
+ MATCH_HEXCOLOR(bgColor);
+ MATCH_HEXCOLOR(debrisColor);
+/*
if (SDL_strcasecmp(key,"bgColor")==0)
{ini->style.bgColor = hextext2rgb(value); return 1;}
if (SDL_strcasecmp(key,"debrisColor")==0)
{ini->style.debrisColor = hextext2rgb(value); return 1;}
+*/
if (SDL_strcasecmp(key,"particleColor")==0)
{
char *wordBoundary;
int i=0;
//((parserState_t*) userData)->need_2pass=1;
- while ( strlen(value)>0 && (wordBoundary=strchr(value,',')) != NULL && (i<MAX_PARTICLE_COLORS) ) {
+ while ( SDL_strlen(value)>0 && (wordBoundary=SDL_strchr(value,','))!=NULL && i<MAX_PARTICLE_COLORS ) {
*wordBoundary='\0';
ini->style.particleColor[i++]=hextext2rgb(value);
value = wordBoundary+1;
@@ -90,6 +130,8 @@ int callback_ini_style(const mTCHAR *section, const mTCHAR *key, const mTCHAR *v
return 0;
}
+ MATCH_INT_ARRAY_MALLOC(frames,6,4,0,MAX_OBJECT_FRAMES,5);
+/*
if (SDL_strncasecmp(key,"frames_", 7) == 0) {
int i = atoi(value+7);
if ( i<0 || i>=ini->style.objectCount) { *err=4; return 0; }
@@ -100,7 +142,9 @@ int callback_ini_style(const mTCHAR *section, const mTCHAR *key, const mTCHAR *v
ini->style.objects[i].frames = v;
return 0;
}
-
+*/
+ MATCH_INT_ARRAY_MALLOC(anim,5,6,0,3,7);
+/*
if (SDL_strncasecmp(key,"anim_", 5) == 0) {
int i = atoi(value+5);
if ( i<0 || i>=ini->style.objectCount) { *err=6; return 0; }
@@ -111,7 +155,10 @@ int callback_ini_style(const mTCHAR *section, const mTCHAR *key, const mTCHAR *v
ini->style.objects[i].anim = v;
return 0;
}
-
+*/
+ MATCH_INT_ARRAY_MALLOC(type,4,8,0,32,9);
+ // TODO : TEST outof range : if (! (v==0 || v==32 || (v>=3 && v<=8)))
+/*
if (SDL_strncasecmp(key,"type_", 5) == 0) {
int i = atoi(value+5);
if ( i<0 || i>=ini->style.objectCount) { *err=8; return 0; }
@@ -122,7 +169,10 @@ int callback_ini_style(const mTCHAR *section, const mTCHAR *key, const mTCHAR *v
ini->style.objects[i].type = v;
return 0;
}
+*/
+ MATCH_INT_ARRAY_MALLOC(sound,5,10,0,MAX_SOUNDS_COUNT,11);
+ /*
if (SDL_strncasecmp(key,"sound_", 6) == 0) {
int i = atoi(value+6);
if ( i<0 || i>=ini->style.objectCount) { *err=10; return 0; }
@@ -132,34 +182,86 @@ int callback_ini_style(const mTCHAR *section, const mTCHAR *key, const mTCHAR *v
ini->style.objects[i].frames = v;
return 0;
- }
-
- if (SDL_strncasecmp(key,"frames_", 7) == 0) {
- int i = atoi(value+7);
- if ( i<0 || i>=ini->style.objectCount) { *err=12; return 0; }
-
- int v = atoi(value);
- if ( v<0 || v>MAX_OBJECT_FRAMES) { *err=13; return 0; }
-
- ini->style.objects[i].frames = v;
- return 0;
- }
+ }
+ */
// No match is an error (unkown key)
*err=1; return -1;
}
int callback_ini_levelpack(const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData) {
- //gameIni_t *ini = ((parserState_t*) userData)->ini;
+ struct levelPackIni *data = &(((parserState_t*) userData)->ini->levelPack);
+
int *err= &(((parserState_t*) userData)->error_code);
+ int i;
+
+ MATCH_STRING(name);
+ MATCH_INT(maxFallDistance);
+ MATCH_STRING(codeSeed);
+
+ /*
+ if (SDL_strcasecmp(key,"name")==0)
+ { ini->levelPack.name = SDL_strdup(value); return 1;}
+ if (SDL_strcasecmp(key,"maxFallDistance")==0)
+ { ini->levelPack.maxFallDistance = SDL_atoi(value); return 1;}
+ if (SDL_strcasecmp(key,"codeSeed")==0)
+ { ini->levelPack.codeSeed = SDL_strdup(value); return 1;}
+ */
+
+ MATCH_STRING_ARRAY(music,5,MAX_MUSIC_COUNT,22);
+/*
+ if (SDL_strncasecmp(key,"music_", 6) == 0) {
+ int k = atoi(value+6);
+ if (k<0 || k>MAX_MUSIC_COUNT) { *err=22; return 0; }
+ if (ini->levelPack.musicCount < k) ini->levelPack.musicCount=k+1;
+ ini->levelPack.musics[k] = SDL_strdup(value);
+ return 0;
+ }
+*/
+ if (SDL_strncasecmp(key,"level_", 6) == 0) {
+ int k = atoi(value+6);
+ if (k<0 || k>MAX_DIFFICULTY_COUNT) { *err=23; return 0; }
+ if (data->levelDifficultyCount < k) data->levelDifficultyCount=k+1;
+ data->levelDifficulty[k] = SDL_strdup(value);
+ return 0;
+ }
+
+ // Parse all entries like <difficultyname>_<levelnumber> (ex: tame_0, havoc_5)
+ for (i=0;i < data->levelDifficultyCount; i++ ) {
+ char *diffname = data->levelDifficulty[i];
+ int len=SDL_strlen(diffname);
+ if ( (len > 0) && (SDL_strncasecmp(key,diffname,len) == 0) && (key[len] == '_') ) {
+ //FIXME : checher position de .ini : copier la chaine avant + 4
+ //FIXME : chercher , et sscandf de la suite
+ *err=1; return -1;
+ }
+ }
// No match is an error (unkown key)
*err=1; return -1;
}
int callback_ini_level_pass1(const mTCHAR *section, const mTCHAR *key, const mTCHAR *value, const void *userData) {
//gameIni_t *ini = ((parserState_t*) userData)->ini;
+ struct levelIni *data = &(((parserState_t*) userData)->ini->level);
+
int *err= &(((parserState_t*) userData)->error_code);
+ MATCH_INT(releaseRate);
+ MATCH_INT(numLemmings);
+ MATCH_INT(numToRescue);
+ MATCH_INT(timeLimit);
+ MATCH_INT(numClimbers);
+ MATCH_INT(numFloaters);
+ MATCH_INT(numBombers);
+ MATCH_INT(numBlockers);
+ MATCH_INT(numBuilders);
+ MATCH_INT(numBashers);
+ MATCH_INT(numMiners);
+ MATCH_INT(numDiggers);
+ MATCH_INT(xPos);
+ MATCH_STRING(style);
+ MATCH_STRING(name);
+ // TODO : object/terrain/steel à la main (car struct, et complications)
// No match is an error (unkown key)
*err=1; return -1;