From a002290853b7b936418e5f03c0299887e61795be Mon Sep 17 00:00:00 2001 From: terminx Date: Thu, 25 Apr 2013 17:49:10 +0000 Subject: [PATCH] Support adding custom grps to the selector in the startup window. To use this feature, create a file with a ".grpinfo" extension in your EDuke32 directory, following this template: grpinfo { name "YourGameName" scriptname "yourgame.con" defname "yourgame.def" size yourgrpsize dependency DUKE15_CRC flags GAMEFLAG_ADDON crc yourgrpcrc } The "flags" field can also take the value "GAMEFLAG_DUKE" to define a new base game. Since this is the first commit of a new feature, certain semantics of the implementation and syntax are liable to change as necessary. git-svn-id: https://svn.eduke32.com/eduke32@3708 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/game.c | 37 ++-- polymer/eduke32/source/grpscan.c | 223 ++++++++++++++++++++++--- polymer/eduke32/source/grpscan.h | 10 +- polymer/eduke32/source/startgtk.game.c | 33 ++-- polymer/eduke32/source/startwin.game.c | 34 ++-- 5 files changed, 279 insertions(+), 58 deletions(-) diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index fa861d10c..7d1b25f9d 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -9666,6 +9666,7 @@ void G_Shutdown(void) KB_Shutdown(); uninitengine(); G_Cleanup(); + FreeGroups(); Bfflush(NULL); } @@ -10170,17 +10171,26 @@ void G_LoadAddon(void) if (grp && FindGroup(DUKE15_CRC)) { int32_t i; + struct grpfile *grp; clearGrpNamePtr(); g_grpNamePtr = dup_filename(FindGroup(DUKE15_CRC)->name); G_AddGroup(grp->name); - for (i = 0; inext) + if (crc == grp->crcval) break; + + if (grp != NULL && grp->scriptname) { clearScriptNamePtr(); - g_scriptNamePtr = dup_filename(grpfiles[i].scriptname); + g_scriptNamePtr = dup_filename(grp->scriptname); + } + + if (grp != NULL && grp->defname) + { + clearDefNamePtr(); + g_defNamePtr = dup_filename(grp->defname); } } } @@ -10453,17 +10463,22 @@ int32_t app_main(int32_t argc, const char **argv) // if it is found, set up the environment accordingly for the game it represents. // if it is not found, choose the first GRP from the list struct grpfile *fg, *first = NULL; - int32_t i; + for (fg = foundgrps; fg; fg=fg->next) { - for (i = 0; icrcval == grpfiles[i].crcval) break; - if (i == NUMGRPFILES) continue; // unrecognised grp file - fg->game = grpfiles[i].game; + struct grpfile *grp; + for (grp = listgrps; grp; grp=grp->next) + if (fg->crcval == grp->crcval) break; + + if (grp == NULL) + continue; + + fg->game = grp->game; if (!first) first = fg; if (!Bstrcasecmp(fg->name, G_DefaultGrpFile())) { - g_gameType = grpfiles[i].game; - g_gameNamePtr = grpfiles[i].name; + g_gameType = grp->game; + g_gameNamePtr = grp->name; break; } } @@ -10475,7 +10490,7 @@ int32_t app_main(int32_t argc, const char **argv) g_grpNamePtr = dup_filename(first->name); } g_gameType = first->game; - g_gameNamePtr = grpfiles[0].name; + g_gameNamePtr = listgrps->name; } else if (!fg) g_gameNamePtr = "Unknown GRP"; } @@ -10553,8 +10568,6 @@ int32_t app_main(int32_t argc, const char **argv) } } - FreeGroups(); - if (g_modDir[0] != '/') G_LoadGroupsInDir(g_modDir); diff --git a/polymer/eduke32/source/grpscan.c b/polymer/eduke32/source/grpscan.c index ac0dffd65..5add451c0 100644 --- a/polymer/eduke32/source/grpscan.c +++ b/polymer/eduke32/source/grpscan.c @@ -31,22 +31,197 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "common_game.h" #include "grpscan.h" -struct grpfile grpfiles[NUMGRPFILES] = +// custom GRP support for the startup window, file format reflects the structure below +#define GAMELISTFILE "games.list" +// name crc size flags dependency scriptname defname +struct grpfile internalgrpfiles[NUMGRPFILES] = { - { "Duke Nukem 3D", DUKE13_CRC, 26524524, GAMEFLAG_DUKE, 0, NULL, NULL }, - { "Duke Nukem 3D (South Korean Censored)", DUKEKR_CRC, 26385383, GAMEFLAG_DUKE, 0, NULL, NULL }, - { "Duke Nukem 3D: Atomic Edition", DUKE15_CRC, 44356548, GAMEFLAG_DUKE, 0, NULL, NULL }, - { "Duke Nukem 3D: Plutonium Pak", DUKEPP_CRC, 44348015, GAMEFLAG_DUKE, 0, NULL, NULL }, - { "Duke Nukem 3D Shareware", DUKESW_CRC, 11035779, GAMEFLAG_DUKE, 0, NULL, NULL }, - { "Duke Nukem 3D Mac Demo", DUKEMD_CRC, 10444391, GAMEFLAG_DUKE, 0, NULL, NULL }, - { "Duke it out in D.C.", DUKEDC_CRC, 8410183 , GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL, NULL }, - { "Duke Caribbean: Life's a Beach", DUKECB_CRC, 22213819, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL, NULL }, - { "Duke: Nuclear Winter", DUKENW_CRC, 16169365, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, "nwinter.con", NULL }, - { "NAM", NAM_CRC, 43448927, GAMEFLAG_NAM, 0, NULL, NULL }, - { "NAPALM", NAPALM_CRC, 44365728, GAMEFLAG_NAM|GAMEFLAG_NAPALM, 0, NULL, NULL }, - { "WWII GI", WW2GI_CRC, 77939508, GAMEFLAG_WW2GI|GAMEFLAG_NAM, 0, NULL, NULL }, + { "Duke Nukem 3D", DUKE13_CRC, 26524524, GAMEFLAG_DUKE, 0, NULL, NULL, NULL }, + { "Duke Nukem 3D (South Korean Censored)", DUKEKR_CRC, 26385383, GAMEFLAG_DUKE, 0, NULL, NULL, NULL }, + { "Duke Nukem 3D: Atomic Edition", DUKE15_CRC, 44356548, GAMEFLAG_DUKE, 0, NULL, NULL, NULL }, + { "Duke Nukem 3D: Plutonium Pak", DUKEPP_CRC, 44348015, GAMEFLAG_DUKE, 0, NULL, NULL, NULL }, + { "Duke Nukem 3D Shareware", DUKESW_CRC, 11035779, GAMEFLAG_DUKE, 0, NULL, NULL, NULL }, + { "Duke Nukem 3D Mac Demo", DUKEMD_CRC, 10444391, GAMEFLAG_DUKE, 0, NULL, NULL, NULL }, + { "Duke it out in D.C.", DUKEDC_CRC, 8410183 , GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL, NULL, NULL }, + { "Duke Caribbean: Life's a Beach", DUKECB_CRC, 22213819, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL, NULL, NULL }, + { "Duke: Nuclear Winter", DUKENW_CRC, 16169365, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, "nwinter.con", NULL, NULL }, + { "NAM", NAM_CRC, 43448927, GAMEFLAG_NAM, 0, "nam.con", "nam.def", NULL }, + { "NAPALM", NAPALM_CRC, 44365728, GAMEFLAG_NAM|GAMEFLAG_NAPALM, 0, "napalm.con", "nam.def", NULL }, + { "WWII GI", WW2GI_CRC, 77939508, GAMEFLAG_WW2GI|GAMEFLAG_NAM, 0, "ww2gi.con", "ww2gi.def", NULL }, }; struct grpfile *foundgrps = NULL; +struct grpfile *listgrps = NULL; + +static void LoadList(const char * filename) +{ + struct grpfile *fg; + + char *grpend = NULL; + + scriptfile *script = scriptfile_fromfile(filename); + + if (!script) + return; + + scriptfile_addsymbolvalue("GAMEFLAG_DUKE", GAMEFLAG_DUKE); + scriptfile_addsymbolvalue("GAMEFLAG_ADDON", GAMEFLAG_DUKE|GAMEFLAG_ADDON); + scriptfile_addsymbolvalue("DUKE15_CRC", DUKE15_CRC); + scriptfile_addsymbolvalue("DUKE13_CRC", DUKE13_CRC); + scriptfile_addsymbolvalue("DUKEDC_CRC", DUKEDC_CRC); + scriptfile_addsymbolvalue("DUKECB_CRC", DUKECB_CRC); + scriptfile_addsymbolvalue("DUKENW_CRC", DUKENW_CRC); + + enum + { + T_GRPINFO, + T_GAMENAME, + T_CRC, + T_SIZE, + T_DEPCRC, + T_SCRIPTNAME, + T_DEFNAME, + T_FLAGS, + }; + + static const tokenlist profiletokens[] = + { + { "grpinfo", T_GRPINFO }, + }; + + while (!scriptfile_eof(script)) + { + int32_t token = getatoken(script,profiletokens,sizeof(profiletokens)/sizeof(tokenlist)); + switch (token) + { + case T_GRPINFO: + { + int32_t gsize = 0, gcrcval = 0, gflags = GAMEFLAG_DUKE, gdepcrc = DUKE15_CRC; + char *gname = NULL, *gscript = NULL, *gdef = NULL; + + static const tokenlist grpinfotokens[] = + { + { "name", T_GAMENAME }, + { "scriptname", T_SCRIPTNAME }, + { "defname", T_DEFNAME }, + { "crc", T_CRC }, + { "dependency", T_DEPCRC }, + { "size", T_SIZE }, + { "flags", T_FLAGS }, + + }; + + if (scriptfile_getbraces(script,&grpend)) break; + + while (script->textptr < grpend) + { + int32_t token = getatoken(script,grpinfotokens,sizeof(grpinfotokens)/sizeof(tokenlist)); + + switch (token) + { + case T_GAMENAME: + scriptfile_getstring(script,&gname); break; + case T_SCRIPTNAME: + scriptfile_getstring(script,&gscript); break; + case T_DEFNAME: + scriptfile_getstring(script,&gdef); break; + + case T_FLAGS: + scriptfile_getsymbol(script,&gflags); break; + case T_DEPCRC: + scriptfile_getsymbol(script,&gdepcrc); break; + case T_CRC: + scriptfile_getsymbol(script,&gcrcval); break; + case T_SIZE: + scriptfile_getnumber(script,&gsize); break; + default: + break; + } + + fg = (struct grpfile *)Bcalloc(1, sizeof(struct grpfile)); + fg->next = listgrps; + listgrps = fg; + + if (gname) + fg->name = Bstrdup(gname); + + fg->size = gsize; + fg->crcval = gcrcval; + fg->dependency = gdepcrc; + fg->game = gflags; + + if (gscript) + fg->scriptname = dup_filename(gscript); + + if (gdef) + fg->defname = dup_filename(gdef); + } + } + + break; + default: + break; + } + } + + scriptfile_close(script); + scriptfile_clearsymbols(); +} + +static void LoadGameList(void) +{ + struct grpfile *fg; + CACHE1D_FIND_REC *srch, *sidx; + + int32_t i; + + for (i = 0; iname = Bstrdup(internalgrpfiles[i].name); + fg->crcval = internalgrpfiles[i].crcval; + fg->size = internalgrpfiles[i].size; + fg->game = internalgrpfiles[i].game; + fg->dependency = internalgrpfiles[i].dependency; + + if (internalgrpfiles[i].scriptname) + fg->scriptname = dup_filename(internalgrpfiles[i].scriptname); + + if (internalgrpfiles[i].defname) + fg->defname = dup_filename(internalgrpfiles[i].defname); + + fg->next = listgrps; + listgrps = fg; + } + + srch = klistpath("/", "*.grpinfo", CACHE1D_FIND_FILE); + + for (sidx = srch; sidx; sidx = sidx->next) + LoadList(srch->name); + + klistfree(srch); +} + +static void FreeGameList(void) +{ + struct grpfile *fg; + + while (listgrps) + { + fg = listgrps->next; + Bfree(listgrps->name); + + if (listgrps->scriptname) + Bfree(listgrps->scriptname); + + if (listgrps->defname) + Bfree(listgrps->defname); + + Bfree(listgrps); + listgrps = fg; + } +} + #define GRPCACHEFILE "grpfiles.cache" static struct grpcache @@ -169,6 +344,7 @@ int32_t ScanGroups(void) initprintf("Searching for game data...\n"); + LoadGameList(); LoadGroupsCache(); srch = klistpath("/", "*.grp", CACHE1D_FIND_FILE); @@ -251,21 +427,26 @@ int32_t ScanGroups(void) for (grp = foundgrps; grp; /*grp=grp->next*/) { - int32_t i; + struct grpfile *igrp; + for (igrp = listgrps; igrp; igrp=igrp->next) + if (grp->crcval == igrp->crcval) break; - for (i = 0; icrcval == grpfiles[i].crcval) break; - if (i == NUMGRPFILES) { grp=grp->next; continue; } // unrecognised grp file + if (igrp == NULL) + { + grp = grp->next; + continue; + } - if (grpfiles[i].dependency) + if (igrp->dependency) { //initprintf("found grp with dep\n"); for (grp = foundgrps; grp; grp=grp->next) - if (grp->crcval == grpfiles[i].dependency) break; + if (grp->crcval == igrp->dependency) break; - if (grp == NULL || grp->crcval != grpfiles[i].dependency) // couldn't find dependency + if (grp == NULL || grp->crcval != igrp->dependency) // couldn't find dependency { //initprintf("removing %s\n", grp->name); - RemoveGroup(grpfiles[i].crcval); + RemoveGroup(igrp->crcval); grp = foundgrps; continue; } @@ -314,5 +495,7 @@ void FreeGroups(void) Bfree(foundgrps); foundgrps = fg; } + + FreeGameList(); } diff --git a/polymer/eduke32/source/grpscan.h b/polymer/eduke32/source/grpscan.h index e3e1a42a8..a48c4d08f 100644 --- a/polymer/eduke32/source/grpscan.h +++ b/polymer/eduke32/source/grpscan.h @@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __grpscan_h__ #define __grpscan_h__ +#define MAXLISTNAMELEN 32 + // List of internally-known GRP files #define NUMGRPFILES 12 @@ -48,17 +50,19 @@ enum addon_t { }; typedef struct grpfile { - const char *name; + char *name; int32_t crcval; int32_t size; int32_t game; int32_t dependency; - const char *scriptname; + char *scriptname; + char *defname; struct grpfile *next; } grpfile_type; -extern struct grpfile grpfiles[NUMGRPFILES]; +// extern struct grpfile grpfiles[NUMGRPFILES]; extern struct grpfile *foundgrps; +extern struct grpfile *listgrps; extern struct grpfile * FindGroup(int32_t crcval); int32_t ScanGroups(void); diff --git a/polymer/eduke32/source/startgtk.game.c b/polymer/eduke32/source/startgtk.game.c index 4778ece25..fd53677bf 100644 --- a/polymer/eduke32/source/startgtk.game.c +++ b/polymer/eduke32/source/startgtk.game.c @@ -441,7 +441,6 @@ static void PopulateForm(unsigned char pgs) if ((pgs == ALL) || (pgs == POPULATE_GAME)) { struct grpfile *fg; - int32_t i; GtkListStore *list; GtkTreeIter iter; GtkTreeView *gamelist; @@ -452,9 +451,12 @@ static void PopulateForm(unsigned char pgs) for (fg = foundgrps; fg; fg=fg->next) { - for (i = 0; icrcval == grpfiles[i].crcval) break; - if (i == NUMGRPFILES) continue; // unrecognised grp file + struct grpfile *grp; + for (grp = listgrps; grp; grp=grp->next) + if (fg->crcval == grp->crcval) break; + + if (grp == NULL) + continue; gtk_list_store_append(list, &iter); gtk_list_store_set(list, &iter, 0, grpfiles[i].name, 1, fg->name, 2, (gpointer)fg, -1); @@ -909,8 +911,6 @@ int32_t startwin_run(void) SetPage(TAB_MESSAGES); if (retval) // launch the game with these parameters { - int32_t i; - ud.config.ScreenWidth = settings.xdim3d; ud.config.ScreenHeight = settings.ydim3d; ud.config.ScreenBPP = settings.bpp3d; @@ -930,13 +930,22 @@ int32_t startwin_run(void) if (settings.autoload) ud.config.NoAutoLoad = FALSE; else ud.config.NoAutoLoad = TRUE; - for (i = 0; inext) + if (settings.crcval == grp->crcval) break; + + if (grp) + { + g_gameNamePtr = grp->name; + g_dependencyCRC = grp->dependency; + + if (grp->scriptname && g_scriptNamePtr == NULL) + g_scriptNamePtr = dup_filename(grp->scriptname); + + if (grp->defname && g_defNamePtr == NULL) + g_defNamePtr = dup_filename(grp->defname); + } } } diff --git a/polymer/eduke32/source/startwin.game.c b/polymer/eduke32/source/startwin.game.c index ba45a146d..46bf85a81 100644 --- a/polymer/eduke32/source/startwin.game.c +++ b/polymer/eduke32/source/startwin.game.c @@ -261,9 +261,14 @@ static void PopulateForm(int32_t pgs) for (fg = foundgrps; fg; fg=fg->next) { - for (i = 0; icrcval == grpfiles[i].crcval) break; - if (i == NUMGRPFILES) continue; // unrecognised grp file - Bsprintf(buf, "%s\t%s", grpfiles[i].name, fg->name); + struct grpfile *grp; + for (grp = listgrps; grp; grp=grp->next) + if (fg->crcval == grp->crcval) break; + + if (grp == NULL) + continue; + + Bsprintf(buf, "%s\t%s", grp->name, fg->name); j = ListBox_AddString(hwnd, buf); (void)ListBox_SetItemData(hwnd, j, (LPARAM)fg); if (!Bstrcasecmp(fg->name, settings.selectedgrp)) @@ -772,8 +777,6 @@ int32_t startwin_run(void) EnableConfig(0); if (done) { - int32_t i; - ud.config.ScreenMode = (settings.flags&1); #ifdef POLYMER if (settings.flags & 2) glrendmode = 4; @@ -797,13 +800,22 @@ int32_t startwin_run(void) Bstrcpy(g_modDir,settings.gamedir); else Bsprintf(g_modDir,"/"); - for (i = 0; inext) + if (settings.crcval == grp->crcval) break; + + if (grp) + { + g_gameNamePtr = grp->name; + g_dependencyCRC = grp->dependency; + + if (grp->scriptname && g_scriptNamePtr == NULL) + g_scriptNamePtr = dup_filename(grp->scriptname); + + if (grp->defname && g_defNamePtr == NULL) + g_defNamePtr = dup_filename(grp->defname); + } } }