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
This commit is contained in:
terminx 2013-04-25 17:49:10 +00:00
parent 3af951db1b
commit a002290853
5 changed files with 279 additions and 58 deletions

View File

@ -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; i<NUMGRPFILES; i++) if (crc == grpfiles[i].crcval) break;
if (i != NUMGRPFILES && grpfiles[i].scriptname)
for (grp = listgrps; grp; grp=grp->next)
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; i<NUMGRPFILES; i++) if (fg->crcval == 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);

View File

@ -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; i<NUMGRPFILES; i++)
{
fg = (struct grpfile *)Bcalloc(1, sizeof(struct grpfile));
fg->name = 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; i<NUMGRPFILES; i++) if (grp->crcval == 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();
}

View File

@ -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);

View File

@ -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; i<NUMGRPFILES; i++)
if (fg->crcval == 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; i<NUMGRPFILES; i++) if (settings.crcval == grpfiles[i].crcval) break;
if (i != NUMGRPFILES)
{
g_gameNamePtr = grpfiles[i].name;
g_dependencyCRC = grpfiles[i].dependency;
if (grpfiles[i].scriptname && g_scriptNamePtr == NULL)
g_scriptNamePtr = dup_filename(grpfiles[i].scriptname);
struct grpfile *grp;
for (grp = listgrps; grp; grp=grp->next)
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);
}
}
}

View File

@ -261,9 +261,14 @@ static void PopulateForm(int32_t pgs)
for (fg = foundgrps; fg; fg=fg->next)
{
for (i = 0; i<NUMGRPFILES; i++) if (fg->crcval == 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; i<NUMGRPFILES; i++) if (settings.crcval == grpfiles[i].crcval) break;
if (i != NUMGRPFILES)
{
g_gameNamePtr = grpfiles[i].name;
g_dependencyCRC = grpfiles[i].dependency;
if (grpfiles[i].scriptname && g_scriptNamePtr == NULL)
g_scriptNamePtr = dup_filename(grpfiles[i].scriptname);
struct grpfile *grp;
for (grp = listgrps; grp; grp=grp->next)
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);
}
}
}