Added Uq-Ruan Masters game - it compiles but does not work (renders too slowly? Another problem?)

This commit is contained in:
pelya
2010-08-21 18:57:13 +03:00
parent ffec83a679
commit 629f5b51f1
882 changed files with 230562 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
uqm_CFILES="direct.c filecntl.c getres.c loadres.c stringbank.c
propfile.c resinit.c"

View File

@@ -0,0 +1,101 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "libs/strings/strintrn.h"
#include "libs/memlib.h"
#include "port.h"
#include "libs/uio.h"
#include <sys/stat.h>
DIRENTRY_REF
LoadDirEntryTable (uio_DirHandle *dirHandle, const char *path,
const char *pattern, match_MatchType matchType)
{
uio_DirList *dirList;
COUNT num_entries;
COUNT i;
uio_DirHandle *dir;
STRING_TABLE StringTable;
STRING_TABLE_DESC *lpST;
STRING lpLastString;
dir = uio_openDirRelative (dirHandle, path, 0);
assert(dir != NULL);
dirList = uio_getDirList (dir, "", pattern, matchType);
assert(dirList != NULL);
num_entries = 0;
// First, count the amount of space needed
for (i = 0; i < dirList->numNames; i++)
{
struct stat sb;
if (dirList->names[i][0] == '.')
{
dirList->names[i] = NULL;
continue;
}
if (uio_stat (dir, dirList->names[i], &sb) == -1)
{
dirList->names[i] = NULL;
continue;
}
if (!S_ISREG (sb.st_mode))
{
dirList->names[i] = NULL;
continue;
}
num_entries++;
}
uio_closeDir (dir);
if (num_entries == 0) {
uio_DirList_free(dirList);
return ((DIRENTRY_REF) 0);
}
StringTable = AllocStringTable (num_entries, 0);
lpST = StringTable;
if (lpST == 0)
{
FreeStringTable (StringTable);
uio_DirList_free(dirList);
return ((DIRENTRY_REF) 0);
}
lpST->size = num_entries;
lpLastString = lpST->strings;
for (i = 0; i < dirList->numNames; i++)
{
int size;
STRINGPTR target;
if (dirList->names[i] == NULL)
continue;
size = strlen (dirList->names[i]) + 1;
target = HMalloc (size);
memcpy (target, dirList->names[i], size);
lpLastString->data = target;
lpLastString->length = size;
lpLastString++;
}
uio_DirList_free(dirList);
return StringTable;
}

View File

@@ -0,0 +1,146 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef WIN32
#include <io.h>
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "port.h"
#include "resintrn.h"
#include "libs/uio.h"
uio_Stream *
res_OpenResFile (uio_DirHandle *dir, const char *filename, const char *mode)
{
uio_Stream *fp;
struct stat sb;
if (uio_stat (dir, filename, &sb) == 0 && S_ISDIR(sb.st_mode))
return ((uio_Stream *) ~0);
fp = uio_fopen (dir, filename, mode);
return (fp);
}
BOOLEAN
res_CloseResFile (uio_Stream *fp)
{
if (fp)
{
if (fp != (uio_Stream *)~0)
uio_fclose (fp);
return (TRUE);
}
return (FALSE);
}
BOOLEAN
DeleteResFile (uio_DirHandle *dir, const char *filename)
{
return (uio_unlink (dir, filename) == 0);
}
int
ReadResFile (void *lpBuf, COUNT size, COUNT count, uio_Stream *fp)
{
int retval;
retval = uio_fread (lpBuf, size, count, fp);
return (retval);
}
int
WriteResFile (const void *lpBuf, COUNT size, COUNT count, uio_Stream *fp)
{
int retval;
retval = uio_fwrite (lpBuf, size, count, fp);
return (retval);
}
int
GetResFileChar (uio_Stream *fp)
{
int retval;
retval = uio_getc (fp);
return (retval);
}
int
PutResFileChar (char ch, uio_Stream *fp)
{
int retval;
retval = uio_putc (ch, fp);
return (retval);
}
int
PutResFileNewline (uio_Stream *fp)
{
int retval;
#ifdef WIN32
PutResFileChar ('\r', fp);
#endif
retval = PutResFileChar ('\n', fp);
return (retval);
}
long
SeekResFile (uio_Stream *fp, long offset, int whence)
{
long retval;
retval = uio_fseek (fp, offset, whence);
return (retval);
}
long
TellResFile (uio_Stream *fp)
{
long retval;
retval = uio_ftell (fp);
return (retval);
}
long
LengthResFile (uio_Stream *fp)
{
struct stat sb;
if (fp == (uio_Stream *)~0)
return (1);
if (uio_fstat(uio_streamHandle(fp), &sb) == -1)
return 1;
return sb.st_size;
}

View File

@@ -0,0 +1,257 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "options.h"
#include "port.h"
#include "resintrn.h"
#include "libs/memlib.h"
#include "libs/log.h"
#include "libs/uio/charhashtable.h"
const char *_cur_resfile_name;
// When a file is being loaded, _cur_resfile_name is set to its name.
// At other times, it is NULL.
ResourceDesc *
lookupResourceDesc (RESOURCE_INDEX idx, RESOURCE res)
{
return (ResourceDesc *) CharHashTable_find (idx->map, res);
}
void
loadResourceDesc (ResourceDesc *desc)
{
desc->vtable->loadFun (desc->fname, &desc->resdata);
}
void *
LoadResourceFromPath (const char *path, ResourceLoadFileFun *loadFun)
{
uio_Stream *stream;
long dataLen;
void *resdata;
stream = res_OpenResFile (contentDir, path, "rb");
if (stream == NULL)
{
log_add (log_Warning, "Warning: Can't open '%s'", path);
return NULL;
}
dataLen = LengthResFile (stream);
log_add (log_Info, "\t'%s' -- %lu bytes", path, dataLen);
if (dataLen == 0)
{
log_add (log_Warning, "Warning: Trying to load empty file '%s'.", path);
goto err;
}
_cur_resfile_name = path;
resdata = (*loadFun) (stream, dataLen);
_cur_resfile_name = NULL;
res_CloseResFile (stream);
return resdata;
err:
res_CloseResFile (stream);
return NULL;
}
const char *
res_GetResourceType (RESOURCE res)
{
RESOURCE_INDEX resourceIndex;
ResourceDesc *desc;
if (res == NULL_RESOURCE)
{
log_add (log_Warning, "Trying to get type of null resource");
return NULL;
}
resourceIndex = _get_current_index_header ();
desc = lookupResourceDesc (resourceIndex, res);
if (desc == NULL)
{
log_add (log_Warning, "Trying to get type of undefined resource '%s'",
res);
return NULL;
}
return desc->vtable->resType;
}
// Get a resource by its resource ID.
void *
res_GetResource (RESOURCE res)
{
RESOURCE_INDEX resourceIndex;
ResourceDesc *desc;
if (res == NULL_RESOURCE)
{
log_add (log_Warning, "Trying to get null resource");
return NULL;
}
resourceIndex = _get_current_index_header ();
desc = lookupResourceDesc (resourceIndex, res);
if (desc == NULL)
{
log_add (log_Warning, "Trying to get undefined resource '%s'",
res);
return NULL;
}
if (desc->resdata.ptr == NULL)
loadResourceDesc (desc);
if (desc->resdata.ptr != NULL)
++desc->refcount;
return desc->resdata.ptr;
// May still be NULL, if the load failed.
}
DWORD
res_GetIntResource (RESOURCE res)
{
RESOURCE_INDEX resourceIndex;
ResourceDesc *desc;
if (res == NULL_RESOURCE)
{
log_add (log_Warning, "Trying to get null resource");
return 0;
}
resourceIndex = _get_current_index_header ();
desc = lookupResourceDesc (resourceIndex, res);
if (desc == NULL)
{
log_add (log_Warning, "Trying to get undefined resource '%s'",
res);
return 0;
}
return desc->resdata.num;
}
BOOLEAN
res_GetBooleanResource (RESOURCE res)
{
return (res_GetIntResource (res) != 0);
}
// NB: this function appears to be never called!
void
res_FreeResource (RESOURCE res)
{
ResourceDesc *desc;
ResourceFreeFun *freeFun;
desc = lookupResourceDesc (_get_current_index_header(), res);
if (desc == NULL)
{
log_add (log_Debug, "Warning: trying to free an unrecognised "
"resource.");
return;
}
if (desc->refcount > 0)
--desc->refcount;
else
log_add (log_Debug, "Warning: freeing an unreferenced resource.");
if (desc->refcount > 0)
return; // Still references left
freeFun = desc->vtable->freeFun;
if (freeFun == NULL)
{
log_add (log_Debug, "Warning: trying to free a non-heap resource.");
return;
}
if (desc->resdata.ptr == NULL)
{
log_add (log_Debug, "Warning: trying to free not loaded "
"resource.");
return;
}
(*freeFun) (desc->resdata.ptr);
desc->resdata.ptr = NULL;
}
// By calling this function the caller will be responsible of unloading
// the resource. If res_GetResource() get called again for this
// resource, a NEW copy will be loaded, regardless of whether a detached
// copy still exists.
void *
res_DetachResource (RESOURCE res)
{
ResourceDesc *desc;
ResourceFreeFun *freeFun;
void *result;
desc = lookupResourceDesc (_get_current_index_header(), res);
if (desc == NULL)
{
log_add (log_Debug, "Warning: trying to detach from an unrecognised "
"resource.");
return NULL;
}
freeFun = desc->vtable->freeFun;
if (freeFun == NULL)
{
log_add (log_Debug, "Warning: trying to detach from a non-heap resource.");
return NULL;
}
if (desc->resdata.ptr == NULL)
{
log_add (log_Debug, "Warning: trying to detach from a not loaded "
"resource.");
return NULL;
}
if (desc->refcount > 1)
{
log_add (log_Debug, "Warning: trying to detach a resource referenced "
"%u times", desc->refcount);
return NULL;
}
result = desc->resdata.ptr;
desc->resdata.ptr = NULL;
desc->refcount = 0;
return result;
}
BOOLEAN
FreeResourceData (void *data)
{
HFree (data);
return TRUE;
}

View File

@@ -0,0 +1,51 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _INDEX_H
#define _INDEX_H
#include <stdio.h>
#include "libs/reslib.h"
#include "libs/uio/charhashtable.h"
typedef struct resource_handlers
{
const char *resType;
ResourceLoadFun *loadFun;
ResourceFreeFun *freeFun;
ResourceStringFun *toString;
} ResourceHandlers;
typedef struct resource_desc
{
RESOURCE res_id;
char *fname;
ResourceHandlers *vtable;
RESOURCE_DATA resdata;
// refcount is rudimentary as nothing really frees the descriptors
unsigned refcount;
} ResourceDesc;
struct resource_index_desc
{
CharHashTable_HashTable *map;
size_t numRes;
};
#endif /* _INDEX_H */

View File

@@ -0,0 +1,72 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "resintrn.h"
#include "libs/declib.h"
#include "libs/memlib.h"
void *
GetResourceData (uio_Stream *fp, DWORD length)
{
BYTE *RDPtr;
void *result;
DECODE_REF fh = 0;
if (length == ~(DWORD)0)
length = LengthResFile (fp);
else if ((fh = copen (fp, FILE_STREAM, STREAM_READ)))
cfilelength (fh, &length);
else
length -= sizeof (DWORD);
result = AllocResourceData (length);
RDPtr = result;
if (RDPtr)
{
COUNT num_read;
do
{
#define READ_LENGTH 0x00007FFFL
num_read = length >= READ_LENGTH ?
(COUNT)READ_LENGTH : (COUNT)length;
if (fh)
{
if (cread (RDPtr, 1, num_read, fh) != num_read)
break;
}
else
{
if ((int)(ReadResFile (RDPtr, 1, num_read, fp)) != (int)num_read)
break;
}
RDPtr += num_read;
} while (length -= num_read);
if (length > 0)
{
FreeResourceData (result);
result = NULL;
}
}
cclose (fh);
return result;
}

View File

@@ -0,0 +1,127 @@
/* propfile.c, Copyright (c) 2008 Michael C. Martin */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope thta it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "libs/log.h"
#include "propfile.h"
#include "libs/reslib.h"
void
PropFile_from_string (char *d, PROPERTY_HANDLER handler, const char *prefix)
{
int len, i;
len = strlen(d);
i = 0;
while (i < len) {
int key_start, key_end, value_start, value_end;
/* Starting a line: search for non-whitespace */
while ((i < len) && isspace (d[i])) i++;
if (i >= len) break; /* Done parsing! */
/* If it was a comment, skip to end of comment/file */
if (d[i] == '#') {
while ((i < len) && (d[i] != '\n')) i++;
if (i >= len) break;
continue; /* Back to keyword search */
}
key_start = i;
/* Find the = on this line */
while ((i < len) && (d[i] != '=') &&
(d[i] != '\n') && (d[i] != '#')) i++;
if (i >= len) { /* Bare key at EOF */
log_add (log_Warning, "Warning: Bare keyword at EOF");
break;
}
/* Comments here mean incomplete line too */
if (d[i] != '=') {
log_add (log_Warning, "Warning: Key without value");
while ((i < len) && (d[i] != '\n')) i++;
if (i >= len) break;
continue; /* Back to keyword search */
}
/* Key ends at first whitespace before = , or at key_start*/
key_end = i;
while ((key_end > key_start) && isspace (d[key_end-1]))
key_end--;
/* Consume the = */
i++;
/* Value starts at first non-whitespace after = on line... */
while ((i < len) && (d[i] != '#') && (d[i] != '\n') &&
isspace (d[i]))
i++;
value_start = i;
/* Until first non-whitespace before terminator */
while ((i < len) && (d[i] != '#') && (d[i] != '\n'))
i++;
value_end = i;
while ((value_end > value_start) && isspace (d[value_end-1]))
value_end--;
/* Skip past EOL or EOF */
while ((i < len) && (d[i] != '\n'))
i++;
i++;
/* We now have start and end values for key and value.
We terminate the strings for both by writing \0s, then
make a new map entry. */
d[key_end] = '\0';
d[value_end] = '\0';
if (prefix) {
char buf[256];
snprintf(buf, 255, "%s%s", prefix, d+key_start);
buf[255]=0;
handler(buf, d+value_start);
} else {
handler (d+key_start, d+value_start);
}
}
}
void
PropFile_from_file (uio_Stream *f, PROPERTY_HANDLER handler, const char *prefix)
{
long flen;
char *data;
flen = LengthResFile (f);
data = malloc (flen + 1);
if (!data) {
return;
}
flen = ReadResFile (data, 1, flen, f);
data[flen] = '\0';
PropFile_from_string (data, handler, prefix);
free (data);
}
void
PropFile_from_filename (uio_DirHandle *path, const char *fname, PROPERTY_HANDLER handler, const char *prefix)
{
uio_Stream *f = res_OpenResFile (path, fname, "rt");
if (!f) {
return;
}
PropFile_from_file (f, handler, prefix);
res_CloseResFile(f);
}

View File

@@ -0,0 +1,30 @@
/* propfile.h, Copyright (c) 2008 Michael C. Martin */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope thta it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef PROPFILE_H_
#define PROPFILE_H_
#include "libs/uio.h"
typedef void (*PROPERTY_HANDLER) (const char *, const char *);
void PropFile_from_string (char *d, PROPERTY_HANDLER handler, const char *prefix);
void PropFile_from_file (uio_Stream *f, PROPERTY_HANDLER handler, const char *prefix);
void PropFile_from_filename (uio_DirHandle *path, const char *fname, PROPERTY_HANDLER handler, const char *prefix);
#endif

View File

@@ -0,0 +1,650 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "resintrn.h"
#include "libs/memlib.h"
#include "options.h"
#include "types.h"
#include "libs/log.h"
#include "libs/gfxlib.h"
#include "libs/reslib.h"
#include "libs/sndlib.h"
#include "libs/vidlib.h"
#include "propfile.h"
#include <ctype.h>
#include <stdlib.h>
// XXX: we should not include anything from uqm/ inside libs/
#include "uqm/coderes.h"
static RESOURCE_INDEX
allocResourceIndex (void) {
RESOURCE_INDEX ndx = HMalloc (sizeof (RESOURCE_INDEX_DESC));
ndx->map = CharHashTable_newHashTable (NULL, NULL, NULL, NULL, 0, 0.85, 0.9);
return ndx;
}
static void
freeResourceIndex (RESOURCE_INDEX h) {
if (h != NULL)
{
/* TODO: This leaks the contents of h->map */
CharHashTable_deleteHashTable (h->map);
HFree (h);
}
}
#define TYPESIZ 32
static ResourceDesc *
newResourceDesc (const char *res_id, const char *resval)
{
const char *path;
int pathlen;
ResourceHandlers *vtable;
ResourceDesc *result, *handlerdesc;
RESOURCE_INDEX idx = _get_current_index_header ();
char typestr[TYPESIZ];
path = strchr (resval, ':');
if (path == NULL)
{
log_add (log_Warning, "Could not find type information for resource '%s'", res_id);
strncpy(typestr, "sys.UNKNOWNRES", TYPESIZ);
path = resval;
}
else
{
int n = path - resval;
if (n >= TYPESIZ - 4)
{
n = TYPESIZ - 5;
}
strncpy (typestr, "sys.", TYPESIZ);
strncat (typestr+1, resval, n);
typestr[n+4] = '\0';
path++;
}
pathlen = strlen (path);
handlerdesc = lookupResourceDesc(idx, typestr);
if (handlerdesc == NULL) {
path = resval;
log_add (log_Warning, "Illegal type '%s' for resource '%s'; treating as UNKNOWNRES", typestr, res_id);
handlerdesc = lookupResourceDesc(idx, "sys.UNKNOWNRES");
}
vtable = (ResourceHandlers *)handlerdesc->resdata.ptr;
if (vtable->loadFun == NULL)
{
log_add (log_Warning, "Warning: Unable to load '%s'; no handler "
"for type %s defined.", res_id, typestr);
return NULL;
}
result = HMalloc (sizeof (ResourceDesc));
if (result == NULL)
return NULL;
result->fname = HMalloc (pathlen + 1);
strncpy (result->fname, path, pathlen);
result->fname[pathlen] = '\0';
result->vtable = vtable;
result->refcount = 0;
if (vtable->freeFun == NULL)
{
/* Non-heap resources are raw values. Work those out at load time. */
vtable->loadFun (result->fname, &result->resdata);
}
else
{
result->resdata.ptr = NULL;
}
return result;
}
static void
process_resource_desc (const char *key, const char *value)
{
CharHashTable_HashTable *map = _get_current_index_header ()->map;
ResourceDesc *newDesc = newResourceDesc (key, value);
if (newDesc != NULL)
{
if (!CharHashTable_add (map, key, newDesc))
{
res_Remove (key);
CharHashTable_add (map, key, newDesc);
}
}
}
static void
UseDescriptorAsRes (const char *descriptor, RESOURCE_DATA *resdata)
{
resdata->ptr = (void *)descriptor;
}
static void
DescriptorToInt (const char *descriptor, RESOURCE_DATA *resdata)
{
resdata->num = atoi (descriptor);
}
static void
DescriptorToBoolean (const char *descriptor, RESOURCE_DATA *resdata)
{
if (!strcasecmp (descriptor, "true"))
{
resdata->num = TRUE;
}
else
{
resdata->num = FALSE;
}
}
static inline size_t
skipWhiteSpace (const char *start)
{
const char *ptr = start;
while (isspace (*ptr))
ptr++;
return (ptr - start);
}
// On success, resdata->num will be filled with a 32-bits RGBA value.
static void
DescriptorToColor (const char *descriptor, RESOURCE_DATA *resdata)
{
int bytesParsed;
int componentBits;
int maxComponentValue;
size_t componentCount;
size_t compI;
int comps[4];
// One element for each of r, g, b, a.
descriptor += skipWhiteSpace (descriptor);
#if 0
// Can't use this; '#' starts a comment.
if (*descriptor == '#')
{
// "#rrggbb"
int i;
DWORD value = 0;
descriptor++;
for (i = 0; i < 6; i++)
{
BYTE nibbleValue;
if (*descriptor >= '0' && *descriptor <= '9')
nibbleValue = *descriptor - '0';
else if (*descriptor >= 'a' && *descriptor <= 'f')
nibbleValue = 0xa + *descriptor - 'a';
else if (*descriptor >= 'A' && *descriptor <= 'F')
nibbleValue = 0xa + *descriptor - 'A';
else
goto fail;
value = (value * 16) + nibbleValue;
descriptor++;
}
descriptor += skipWhiteSpace (descriptor);
if (*descriptor != '\0')
log_add (log_Warning, "Junk after color resource string.");
resdata->num = (value << 8) | 0xff;
return;
}
#endif
// Color is of the form "rgb(r, g, b)", "rgba(r, g, b, a)",
// or "rgb15(r, g, b)".
if (sscanf (descriptor, "rgb ( %i , %i , %i ) %n",
&comps[0], &comps[1], &comps[2], &bytesParsed) >= 3)
{
componentBits = 8;
componentCount = 3;
comps[3] = 0xff;
}
else if (sscanf (descriptor, "rgba ( %i , %i , %i , %i ) %n",
&comps[0], &comps[1], &comps[2], &comps[3], &bytesParsed) >= 4)
{
componentBits = 8;
componentCount = 4;
}
else if (sscanf (descriptor, "rgb15 ( %i , %i , %i ) %n",
&comps[0], &comps[1], &comps[2], &bytesParsed) >= 3)
{
componentBits = 5;
componentCount = 3;
comps[3] = 0xff;
}
else
goto fail;
if (descriptor[bytesParsed] != '\0')
log_add (log_Warning, "Junk after color resource string.");
maxComponentValue = (1 << componentBits) - 1;
// Check the range of the components.
for (compI = 0; compI < componentCount; compI++)
{
if (comps[compI] < 0)
{
comps[compI] = 0;
log_add (log_Warning, "Color component value too small; "
"value clipped.");
}
if (comps[compI] > (long) maxComponentValue)
{
comps[compI] = maxComponentValue;
log_add (log_Warning, "Color component value too large; "
"value clipped.");
}
}
if (componentBits == 5)
resdata->num = ((CC5TO8 (comps[0]) << 24) |
(CC5TO8 (comps[1]) << 16) | (CC5TO8 (comps[2]) << 8) |
comps[3]);
else
resdata->num = ((comps[0] << 24) | (comps[1] << 16) |
(comps[2] << 8) | comps[3]);
return;
fail:
log_add (log_Error, "Invalid color description string for resource.\n");
resdata->num = 0x00000000;
}
static void
RawDescriptor (RESOURCE_DATA *resdata, char *buf, unsigned int size)
{
snprintf (buf, size, "%s", (char *)resdata->ptr);
}
static void
IntToString (RESOURCE_DATA *resdata, char *buf, unsigned int size)
{
snprintf (buf, size, "%d", resdata->num);
}
static void
BooleanToString (RESOURCE_DATA *resdata, char *buf, unsigned int size)
{
snprintf (buf, size, "%s", resdata->num ? "true" : "false");
}
static void
ColorToString (RESOURCE_DATA *resdata, char *buf, unsigned int size)
{
if ((resdata->num & 0xff) == 0xff)
{
// Opaque color, save as "rgb".
snprintf (buf, size, "rgb(0x%02x, 0x%02x, 0x%02x)",
(resdata->num >> 24), (resdata->num >> 16) & 0xff,
(resdata->num >> 8) & 0xff);
}
else
{
// (Partially) transparent color, save as "rgba".
snprintf (buf, size, "rgba(0x%02x, 0x%02x, 0x%02x, 0x%02x)",
(resdata->num >> 24), (resdata->num >> 16) & 0xff,
(resdata->num >> 8) & 0xff, resdata->num & 0xff);
}
}
static RESOURCE_INDEX curResourceIndex;
void
_set_current_index_header (RESOURCE_INDEX newResourceIndex)
{
curResourceIndex = newResourceIndex;
}
RESOURCE_INDEX
InitResourceSystem (void)
{
RESOURCE_INDEX ndx;
if (curResourceIndex) {
return curResourceIndex;
}
ndx = allocResourceIndex ();
_set_current_index_header (ndx);
InstallResTypeVectors ("UNKNOWNRES", UseDescriptorAsRes, NULL, NULL);
InstallResTypeVectors ("STRING", UseDescriptorAsRes, NULL, RawDescriptor);
InstallResTypeVectors ("INT32", DescriptorToInt, NULL, IntToString);
InstallResTypeVectors ("BOOLEAN", DescriptorToBoolean, NULL,
BooleanToString);
InstallResTypeVectors ("COLOR", DescriptorToColor, NULL, ColorToString);
InstallGraphicResTypes ();
InstallStringTableResType ();
InstallAudioResTypes ();
InstallVideoResType ();
InstallCodeResType ();
return ndx;
}
RESOURCE_INDEX
_get_current_index_header (void)
{
if (!curResourceIndex) {
InitResourceSystem ();
}
return curResourceIndex;
}
void
LoadResourceIndex (uio_DirHandle *dir, const char *rmpfile, const char *prefix)
{
PropFile_from_filename (dir, rmpfile, process_resource_desc, prefix);
}
void
SaveResourceIndex (uio_DirHandle *dir, const char *rmpfile, const char *root, BOOLEAN strip_root)
{
uio_Stream *f;
CharHashTable_Iterator *it;
unsigned int prefix_len;
f = res_OpenResFile (dir, rmpfile, "wb");
if (!f) {
/* TODO: Warning message */
return;
}
prefix_len = root ? strlen (root) : 0;
for (it = CharHashTable_getIterator (_get_current_index_header ()->map);
!CharHashTable_iteratorDone (it);
it = CharHashTable_iteratorNext (it)) {
char *key = CharHashTable_iteratorKey (it);
if (!root || !strncmp (root, key, prefix_len)) {
ResourceDesc *value = CharHashTable_iteratorValue (it);
if (!value) {
log_add(log_Warning, "Resource %s had no value", key);
} else if (!value->vtable) {
log_add(log_Warning, "Resource %s had no type", key);
} else if (value->vtable->toString) {
char buf[256];
value->vtable->toString (&value->resdata, buf, 256);
buf[255]=0;
if (root && strip_root) {
WriteResFile (key+prefix_len, 1, strlen (key) - prefix_len, f);
} else {
WriteResFile (key, 1, strlen (key), f);
}
PutResFileChar(' ', f);
PutResFileChar('=', f);
PutResFileChar(' ', f);
WriteResFile (value->vtable->resType, 1, strlen (value->vtable->resType), f);
PutResFileChar(':', f);
WriteResFile (buf, 1, strlen (buf), f);
PutResFileNewline(f);
}
}
}
res_CloseResFile (f);
CharHashTable_freeIterator (it);
}
void
UninitResourceSystem (void)
{
freeResourceIndex (_get_current_index_header ());
_set_current_index_header (NULL);
}
BOOLEAN
InstallResTypeVectors (const char *resType, ResourceLoadFun *loadFun,
ResourceFreeFun *freeFun, ResourceStringFun *stringFun)
{
ResourceHandlers *handlers;
ResourceDesc *result;
char key[TYPESIZ];
int typelen;
CharHashTable_HashTable *map;
snprintf(key, TYPESIZ, "sys.%s", resType);
key[TYPESIZ-1] = '\0';
typelen = strlen(resType);
handlers = HMalloc (sizeof (ResourceHandlers));
if (handlers == NULL)
{
return FALSE;
}
handlers->loadFun = loadFun;
handlers->freeFun = freeFun;
handlers->toString = stringFun;
handlers->resType = resType;
result = HMalloc (sizeof (ResourceDesc));
if (result == NULL)
return FALSE;
result->fname = HMalloc (strlen(resType) + 1);
strncpy (result->fname, resType, typelen);
result->fname[typelen] = '\0';
result->vtable = NULL;
result->resdata.ptr = handlers;
map = _get_current_index_header ()->map;
return CharHashTable_add (map, key, result) != 0;
}
/* These replace the mapres.c calls and probably should be split out at some point. */
BOOLEAN
res_IsString (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
return desc && !strcmp(desc->vtable->resType, "STRING");
}
const char *
res_GetString (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
if (!desc || !desc->resdata.ptr || strcmp(desc->vtable->resType, "STRING"))
return "";
/* TODO: Work out exact STRING semantics, specifically, the lifetime of
* the returned value. If caller is allowed to reference the returned
* value forever, STRING has to be ref-counted. */
return (const char *)desc->resdata.ptr;
}
void
res_PutString (const char *key, const char *value)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
int srclen, dstlen;
if (!desc || !desc->resdata.ptr || strcmp(desc->vtable->resType, "STRING"))
{
/* TODO: This is kind of roundabout. We can do better by refactoring newResourceDesc */
process_resource_desc(key, "STRING:undefined");
desc = lookupResourceDesc (idx, key);
}
srclen = strlen (value);
dstlen = strlen (desc->resdata.ptr);
if (srclen > dstlen) {
char *newValue = HMalloc(srclen + 1);
char *oldValue = desc->fname;
log_add(log_Warning, "Reallocating string space for '%s'", key);
strncpy (newValue, value, srclen + 1);
desc->resdata.ptr = newValue;
desc->fname = newValue;
HFree (oldValue);
} else {
strncpy (desc->resdata.ptr, value, srclen + 1);
}
}
BOOLEAN
res_IsInteger (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
return desc && !strcmp(desc->vtable->resType, "INT32");
}
int
res_GetInteger (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
if (!desc || strcmp(desc->vtable->resType, "INT32"))
{
// TODO: Better error handling
return 0;
}
return desc->resdata.num;
}
void
res_PutInteger (const char *key, int value)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
if (!desc || strcmp(desc->vtable->resType, "INT32"))
{
/* TODO: This is kind of roundabout. We can do better by refactoring newResourceDesc */
process_resource_desc(key, "INT32:0");
desc = lookupResourceDesc (idx, key);
}
desc->resdata.num = value;
}
BOOLEAN
res_IsBoolean (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
return desc && !strcmp(desc->vtable->resType, "BOOLEAN");
}
BOOLEAN
res_GetBoolean (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
if (!desc || strcmp(desc->vtable->resType, "BOOLEAN"))
{
// TODO: Better error handling
return FALSE;
}
return desc->resdata.num ? TRUE : FALSE;
}
void
res_PutBoolean (const char *key, BOOLEAN value)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
if (!desc || strcmp(desc->vtable->resType, "BOOLEAN"))
{
/* TODO: This is kind of roundabout. We can do better by refactoring newResourceDesc */
process_resource_desc(key, "BOOLEAN:false");
desc = lookupResourceDesc (idx, key);
}
desc->resdata.num = value;
}
BOOLEAN
res_IsColor (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
return desc && !strcmp(desc->vtable->resType, "COLOR");
}
Color
res_GetColor (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
DWORD num;
if (!desc || strcmp(desc->vtable->resType, "COLOR"))
{
// TODO: Better error handling
return buildColorRgba (0, 0, 0, 0);
}
num = desc->resdata.num;
return buildColorRgba (num >> 24, (num >> 16) & 0xff,
(desc->resdata.num >> 8) & 0xff, num & 0xff);
}
void
res_PutColor (const char *key, Color value)
{
RESOURCE_INDEX idx = _get_current_index_header ();
ResourceDesc *desc = lookupResourceDesc (idx, key);
if (!desc || strcmp(desc->vtable->resType, "COLOR"))
{
/* TODO: This is kind of roundabout. We can do better by refactoring
* newResourceDesc */
process_resource_desc(key, "COLOR:rgb(0, 0, 0)");
desc = lookupResourceDesc (idx, key);
}
desc->resdata.num =
(value.r << 24) | (value.g << 16) | (value.b << 8) | value.a;
}
BOOLEAN
res_HasKey (const char *key)
{
RESOURCE_INDEX idx = _get_current_index_header ();
return (lookupResourceDesc(idx, key) != NULL);
}
BOOLEAN
res_Remove (const char *key)
{
CharHashTable_HashTable *map = _get_current_index_header ()->map;
ResourceDesc *oldDesc = (ResourceDesc *)CharHashTable_find (map, key);
if (oldDesc != NULL)
{
if (oldDesc->resdata.ptr != NULL)
{
if (oldDesc->refcount > 0)
log_add (log_Warning, "WARNING: Replacing '%s' while it is live", key);
if (oldDesc->vtable && oldDesc->vtable->freeFun)
{
oldDesc->vtable->freeFun(oldDesc->resdata.ptr);
}
}
HFree (oldDesc->fname);
HFree (oldDesc);
}
return CharHashTable_remove (map, key);
}

View File

@@ -0,0 +1,34 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _RESINTRN_H
#define _RESINTRN_H
#include <string.h>
#include "libs/reslib.h"
#include "index.h"
ResourceDesc *lookupResourceDesc (RESOURCE_INDEX idx, RESOURCE res);
void loadResourceDesc (ResourceDesc *desc);
void _set_current_index_header (RESOURCE_INDEX newResourceIndex);
RESOURCE_INDEX _get_current_index_header (void);
#endif /* _RESINTRN_H */

View File

@@ -0,0 +1,181 @@
/* stringbank.c, Copyright (c) 2005 Michael C. Martin */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope thta it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stringbank.h"
typedef stringbank chunk;
static stringbank *
add_chunk (stringbank *bank)
{
stringbank *n = malloc (sizeof (stringbank));
n->len = 0;
n->next = NULL;
if (bank)
{
while (bank->next)
bank = bank->next;
bank->next = n;
}
return n;
}
stringbank *
StringBank_Create (void)
{
return add_chunk (NULL);
}
void
StringBank_Free (stringbank *bank)
{
if (bank)
{
StringBank_Free (bank->next);
free (bank);
}
}
const char *
StringBank_AddString (stringbank *bank, const char *str)
{
unsigned int len = strlen (str) + 1;
stringbank *x = bank;
if (len > STRBANK_CHUNK_SIZE)
return NULL;
while (x) {
unsigned int remaining = STRBANK_CHUNK_SIZE - x->len;
if (len < remaining) {
char *result = x->data + x->len;
strcpy (result, str);
x->len += len;
return result;
}
x = x->next;
}
/* No room in any currently existing chunk */
x = add_chunk (bank);
strcpy (x->data, str);
x->len += len;
return x->data;
}
const char *
StringBank_AddOrFindString (stringbank *bank, const char *str)
{
unsigned int len = strlen (str) + 1;
stringbank *x = bank;
if (len > STRBANK_CHUNK_SIZE)
return NULL;
while (x) {
int i = 0;
while (i < x->len) {
if (!strcmp (x->data + i, str))
return x->data + i;
while (x->data[i]) i++;
i++;
}
x = x->next;
}
/* We didn't find it, so add it */
return StringBank_AddString (bank, str);
}
static char buffer[STRBANK_CHUNK_SIZE];
const char *
StringBank_AddSubstring (stringbank *bank, const char *str, unsigned int n)
{
unsigned int len = strlen (str);
if (n > len)
{
return StringBank_AddString (bank, str);
}
if (n >= STRBANK_CHUNK_SIZE)
{
return NULL;
}
strncpy (buffer, str, n);
buffer[n] = '\0';
return StringBank_AddString(bank, buffer);
}
const char *
StringBank_AddOrFindSubstring (stringbank *bank, const char *str, unsigned int n)
{
unsigned int len = strlen (str);
if (n > len)
{
return StringBank_AddOrFindString (bank, str);
}
if (n >= STRBANK_CHUNK_SIZE)
{
return NULL;
}
strncpy (buffer, str, n);
buffer[n] = '\0';
return StringBank_AddOrFindString(bank, buffer);
}
int
SplitString (const char *s, char splitchar, int n, const char **result, stringbank *bank)
{
int i;
const char *index = s;
for (i = 0; i < n-1; i++)
{
const char *next;
int len;
next = strchr (index, splitchar);
if (!next)
{
break;
}
len = next - index;
result[i] = StringBank_AddOrFindSubstring (bank, index, len);
index = next+1;
}
result[i] = StringBank_AddOrFindString (bank, index);
return i+1;
}
#ifdef SB_DEBUG
void
StringBank_Dump (stringbank *bank, FILE *s)
{
stringbank *x = bank;
while (x) {
int i = 0;
while (i < x->len) {
fprintf (s, "\"%s\"\n", x->data + i);
while (x->data[i]) i++;
i++;
}
x = x->next;
}
}
#endif

View File

@@ -0,0 +1,57 @@
/* stringbank.h, Copyright (c) 2005 Michael C. Martin */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope thta it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Se the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _STRINGBANK_H_
#define _STRINGBANK_H_
#ifdef SB_DEBUG
#include <stdio.h>
#endif
#define STRBANK_CHUNK_SIZE (1024 - sizeof (void *) - sizeof (int))
typedef struct _stringbank_chunk {
char data[STRBANK_CHUNK_SIZE];
int len;
struct _stringbank_chunk *next;
} stringbank;
/* Constructors and destructors */
stringbank *StringBank_Create (void);
void StringBank_Free (stringbank *bank);
/* Put str or n chars after str into the string bank. */
const char *StringBank_AddString (stringbank *bank, const char *str);
const char *StringBank_AddSubstring (stringbank *bank, const char *str, unsigned int n);
/* Put str or n chars after str into the string bank if it's not already
there. Much slower. */
const char *StringBank_AddOrFindString (stringbank *bank, const char *str);
const char *StringBank_AddOrFindSubstring (stringbank *bank, const char *str, unsigned int n);
/* Split a string s into at most n substrings, separated by splitchar.
Pointers to these substrings will be stored in result; the
substrings themselves will be filed in the specified stringbank. */
int SplitString (const char *s, char splitchar, int n, const char **result, stringbank *bank);
#ifdef SB_DEBUG
/* Print out a list of the contents of the string bank to the named stream. */
void StringBank_Dump (stringbank *bank, FILE *s);
#endif /* SB_DEBUG */
#endif /* _STRINGBANK_H_ */