Implement a FitzQuake like SDL build: [90/10 Non-Tutorial]

Post tutorials on how to do certain tasks within game or engine code here.
Post Reply
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Implement a FitzQuake like SDL build: [90/10 Non-Tutorial]

Post by Baker »

Image

This is a 90/10 non-tutorial: it doesn't tell you what to do, but tells you where to look. It operates on the idea you have some sort of diff application like WinMerge.

Image Image

SDL

SDL stands for Simple DirectMedia Layer (wikipedia) and is a multiplatform library that makes it rather easy to have operating system neutral builds for the traditional desktop platforms --- Windows, OS X, Linux.

SDL supports OpenGL and in the FitzQuake 0.80 implementation virtually all the OpenGL code stayed the same and FitzQuake is an OpenGL only engine.

In addition to FitzQuake 0.80 SDL, the engine Quakespasm is SDL, DarkPlaces comes with an SDL build and FTEQW might have an SDL version buildable (I've always seen SDL stuffs in the FTEQW source). The first SDL Quake was SDL Quake.

For a list of SDL games see this list ... http://en.wikipedia.org/wiki/List_of_games_using_SDL and lists games like the Linux versions of Quake 4, Unreal Tournament and Sid Meier's Alpha Centauri.

SDL is kind of a quick and easy way to make multiplatform quick.

The Changes

This reviews the changes in FitzQuake 0.80 (source link) and FitzQuake 0.80 SDL (source link)

First, anything WIN32 specific is going to need to be stripped or rewritten to be multiplatform. Assembly language references of course are going to have to go.

An example in FitzQuake 0.80:

This had to be rewritten ... you obviously can't use a Windows API-based file find on OS X or Linux and instead need to use readdir().

Code: Select all

void Modlist_Init (void) //TODO: move win32 specific stuff to sys_win.c
{
#ifdef _WIN32
	WIN32_FIND_DATA	FindFileData, FindChildData;
	HANDLE			Find, FindProgs, FindPak;
	char			filestring[MAX_OSPATH], childstring[MAX_OSPATH];
	int				count, temp;

	sprintf (filestring,"%s/*", host_parms.basedir);
	Find = FindFirstFile(filestring, &FindFileData);
	if (Find == INVALID_HANDLE_VALUE)
	{
		FindClose (Find);
		return;
	}

	do
	{
		sprintf (childstring,"%s/%s/progs.dat", host_parms.basedir, FindFileData.cFileName);
		FindProgs = FindFirstFile(childstring, &FindChildData);

		sprintf (childstring,"%s/%s/*.pak", host_parms.basedir, FindFileData.cFileName);
		FindPak = FindFirstFile(childstring, &FindChildData);

		if (FindProgs == INVALID_HANDLE_VALUE && FindPak == INVALID_HANDLE_VALUE)
			continue;

		Modlist_Add (FindFileData.cFileName);

		FindClose (FindProgs);
		FindClose (FindPak);
		count++;
	} while (FindNextFile(Find, &FindFileData));
	FindClose (Find);

	//make sure these get closed too
	FindClose (FindProgs);
	FindClose (FindPak);
#endif
}
And ended up being rewritten as such ...

Code: Select all

void Modlist_Init (void)
{
    DIR             *dir_p, *mod_dir_p;
    struct dirent   *dir_t, *mod_dir_t;
    qboolean        progs_found, pak_found;
	char			dir_string[MAX_OSPATH], mod_dir_string[MAX_OSPATH];
    int             i;

	i = COM_CheckParm ("-basedir");
	if (i && i < com_argc-1)
        sprintf (dir_string, "%s/", com_argv[i+1]);
    else
        sprintf (dir_string, "%s/", host_parms.basedir);

    dir_p = opendir(dir_string);
    if (dir_p == NULL)
        return;

    while ((dir_t = readdir(dir_p)) != NULL)
    {
        if ((strcmp(dir_t->d_name, ".") == 0) || (strcmp(dir_t->d_name, "..") == 0))
            continue;

        sprintf(mod_dir_string, "%s%s/", dir_string, dir_t->d_name);
        mod_dir_p = opendir(mod_dir_string);

        if (mod_dir_p == NULL)
            continue;

        progs_found = false;
        pak_found = false;

        // find progs.dat and pak file(s)
        while ((mod_dir_t = readdir(mod_dir_p)) != NULL)
        {
            if ((strcmp(mod_dir_t->d_name, ".") == 0) || (strcmp(mod_dir_t->d_name, "..") == 0))
                continue;

            if (Q_strcasecmp(mod_dir_t->d_name, "progs.dat") != -1)
                progs_found = true;

            if (strstr(mod_dir_t->d_name, ".pak") || strstr(mod_dir_t->d_name, ".PAK"))
               pak_found = true;

            if (progs_found || pak_found)
                break;
        }
        closedir(mod_dir_p);

        if (!progs_found && !pak_found)
            continue;

        Modlist_Add(dir_t->d_name);
    }

    closedir(dir_p);
}

Some variables and functions have to be moved out of an operating system specific file like in_win.c or gl_vidnet.c into a general source file.

So ... the kind of things affected are going to sound, input ...

Files Which Are Changed

The changes are quite mild and in FitzQuake 0.80 mostly occurred in ...

1. console.c (mouse capture difference)
2. gl_texmgr.c (stricmp is windows-specific ---> Q_strcasecmp)
3. glquake.h (inclusion of headers, removal of WIN 32 stuff)
4. host.c (input flow is altered, not using the WIN32 way)
5. host_cmd.c (rewrite of Fitz maps and mods commands)
6. input.h
7. keys.c
8. mathlib.c (enabled non-assembly C function)
9. menu.c
10. net_dgrm.c
11. quakedef.h
12. snd_dma.c (removal of WIN32 specific stuff)
13. snd_mix.c (removal of WIN32 specific stuff)
14. vid.h

To compile, I'm going to defer to the QuakeSpasm source:

http://quakespasm.sourceforge.net/download.htm

Or on OSX you can read this:

http://forums.inside3d.com/viewtopic.php?t=1221

End Result of an SDL Build

You can have one engine with essentially one single code-base and same features on all desktop platforms (Windows, OSX, Linux). Quakespasm has a few special #ifdefs left to support 64-bit it appears like #ifdef WIN64.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
Post Reply