/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+* Artsoft Retro-Game Library *
*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
+* (c) 1994-2001 Artsoft Entertainment *
+* Holger Schemel *
+* Detmolder Strasse 189 *
+* 33604 Bielefeld *
+* Germany *
+* e-mail: info@artsoft.org *
*----------------------------------------------------------*
-* misc.c *
+* misc.c *
***********************************************************/
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
+/*
#include <sys/stat.h>
+*/
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <sys/param.h>
#endif
-#include "libgame.h"
-
#include "misc.h"
+#include "setup.h"
+#include "random.h"
-#if 0
-#include "joystick_TMP.h"
-#endif
#if defined(PLATFORM_MSDOS)
volatile unsigned long counter = 0;
{
unsigned long actual_frame_counter = FrameCounter;
- if (actual_frame_counter < *frame_counter_var+frame_delay &&
+ if (actual_frame_counter < *frame_counter_var + frame_delay &&
actual_frame_counter >= *frame_counter_var)
- return(FALSE);
+ return FALSE;
*frame_counter_var = actual_frame_counter;
- return(TRUE);
+
+ return TRUE;
}
boolean DelayReached(unsigned long *counter_var,
if (actual_counter < *counter_var + delay &&
actual_counter >= *counter_var)
- return(FALSE);
+ return FALSE;
*counter_var = actual_counter;
- return(TRUE);
+
+ return TRUE;
}
void WaitUntilDelayReached(unsigned long *counter_var, unsigned long delay)
options.ro_base_directory = RO_BASE_PATH;
options.rw_base_directory = RW_BASE_PATH;
options.level_directory = RO_BASE_PATH "/" LEVELS_DIRECTORY;
+ options.graphics_directory = RO_BASE_PATH "/" GRAPHICS_DIRECTORY;
+ options.sounds_directory = RO_BASE_PATH "/" SOUNDS_DIRECTORY;
+ options.music_directory = RO_BASE_PATH "/" MUSIC_DIRECTORY;
options.serveronly = FALSE;
options.network = FALSE;
options.verbose = FALSE;
{
printf("Usage: %s [options] [server.name [port]]\n"
"Options:\n"
- " -d, --display machine:0 X server display\n"
- " -b, --basepath directory alternative base directory\n"
- " -l, --level directory alternative level directory\n"
- " -s, --serveronly only start network server\n"
+ " -d, --display <host>[:<scr>] X server display\n"
+ " -b, --basepath <directory> alternative base directory\n"
+ " -l, --level <directory> alternative level directory\n"
+ " -g, --graphics <directory> alternative graphics directory\n"
+ " -s, --sounds <directory> alternative graphics directory\n"
+ " -m, --music <directory> alternative graphics directory\n"
" -n, --network network multiplayer game\n"
- " -v, --verbose verbose mode\n",
+ " --serveronly only start network server\n"
+ " -v, --verbose verbose mode\n"
+ " --debug display debugging information\n",
program.command_basename);
exit(0);
}
if (option_arg == next_option)
options_left++;
}
+ else if (strncmp(option, "-graphics", option_len) == 0)
+ {
+ if (option_arg == NULL)
+ Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
+
+ options.graphics_directory = option_arg;
+ if (option_arg == next_option)
+ options_left++;
+ }
+ else if (strncmp(option, "-sounds", option_len) == 0)
+ {
+ if (option_arg == NULL)
+ Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
+
+ options.sounds_directory = option_arg;
+ if (option_arg == next_option)
+ options_left++;
+ }
+ else if (strncmp(option, "-music", option_len) == 0)
+ {
+ if (option_arg == NULL)
+ Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str);
+
+ options.music_directory = option_arg;
+ if (option_arg == next_option)
+ options_left++;
+ }
else if (strncmp(option, "-network", option_len) == 0)
{
options.network = TRUE;
}
}
+/* used by SetError() and GetError() to store internal error messages */
+static char internal_error[1024]; /* this is bad */
+
+void SetError(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vsprintf(internal_error, format, ap);
+ va_end(ap);
+}
+
+char *GetError()
+{
+ return internal_error;
+}
+
void Error(int mode, char *format, ...)
{
char *process_name = "";
FILE *error = stderr;
+ char *newline = "\n";
/* display warnings only when running in verbose mode */
if (mode & ERR_WARN && !options.verbose)
return;
#if !defined(PLATFORM_UNIX)
+ newline = "\r\n";
+
if ((error = openErrorFile()) == NULL)
{
- printf("Cannot write to error output file!\n");
+ printf("Cannot write to error output file!%s", newline);
program.exit_function(1);
}
#endif
vfprintf(error, format, ap);
va_end(ap);
- fprintf(error, "\n");
+ fprintf(error, "%s", newline);
}
if (mode & ERR_HELP)
- fprintf(error, "%s: Try option '--help' for more information.\n",
- program.command_basename);
+ fprintf(error, "%s: Try option '--help' for more information.%s",
+ program.command_basename, newline);
if (mode & ERR_EXIT)
- fprintf(error, "%s%s: aborting\n", program.command_basename, process_name);
+ fprintf(error, "%s%s: aborting%s",
+ program.command_basename, process_name, newline);
if (error != stderr)
fclose(error);
return ptr;
}
+void *checked_realloc(void *ptr, unsigned long size)
+{
+ ptr = realloc(ptr, size);
+
+ if (ptr == NULL)
+ Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size);
+
+ return ptr;
+}
+
+inline void swap_numbers(int *i1, int *i2)
+{
+ int help = *i1;
+
+ *i1 = *i2;
+ *i2 = help;
+}
+
+inline void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
+{
+ int help_x = *x1;
+ int help_y = *y1;
+
+ *x1 = *x2;
+ *x2 = help_x;
+
+ *y1 = *y2;
+ *y2 = help_y;
+}
+
short getFile16BitInteger(FILE *file, int byte_order)
{
if (byte_order == BYTE_ORDER_BIG_ENDIAN)
}
}
-void getFileChunk(FILE *file, char *chunk_buffer, int *chunk_length,
- int byte_order)
+boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
+ int byte_order)
{
- const int chunk_identifier_length = 4;
+ const int chunk_name_length = 4;
- /* read chunk identifier */
- fgets(chunk_buffer, chunk_identifier_length + 1, file);
+ /* read chunk name */
+ fgets(chunk_name, chunk_name_length + 1, file);
- /* read chunk length */
- *chunk_length = getFile32BitInteger(file, byte_order);
+ if (chunk_size != NULL)
+ {
+ /* read chunk size */
+ *chunk_size = getFile32BitInteger(file, byte_order);
+ }
+
+ return (feof(file) || ferror(file) ? FALSE : TRUE);
}
-void putFileChunk(FILE *file, char *chunk_name, int chunk_length,
+void putFileChunk(FILE *file, char *chunk_name, int chunk_size,
int byte_order)
{
- /* write chunk identifier */
+ /* write chunk name */
fputs(chunk_name, file);
- /* write chunk length */
- putFile32BitInteger(file, chunk_length, byte_order);
+ if (chunk_size >= 0)
+ {
+ /* write chunk size */
+ putFile32BitInteger(file, chunk_size, byte_order);
+ }
+}
+
+void ReadUnusedBytesFromFile(FILE *file, unsigned long bytes)
+{
+ while (bytes-- && !feof(file))
+ fgetc(file);
+}
+
+void WriteUnusedBytesToFile(FILE *file, unsigned long bytes)
+{
+ while (bytes--)
+ fputc(0, file);
}
#define TRANSLATE_KEYSYM_TO_KEYNAME 0
#define TRANSLATE_KEYSYM_TO_X11KEYNAME 1
-#define TRANSLATE_X11KEYNAME_TO_KEYSYM 2
+#define TRANSLATE_KEYNAME_TO_KEYSYM 2
+#define TRANSLATE_X11KEYNAME_TO_KEYSYM 3
void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
{
*x11name = name_buffer;
}
+ else if (mode == TRANSLATE_KEYNAME_TO_KEYSYM)
+ {
+ Key key = KSYM_UNDEFINED;
+
+ i = 0;
+ do
+ {
+ if (strcmp(translate_key[i].name, *name) == 0)
+ {
+ key = translate_key[i].key;
+ break;
+ }
+ }
+ while (translate_key[++i].x11name);
+
+ if (key == KSYM_UNDEFINED)
+ Error(ERR_WARN, "getKeyFromKeyName(): not completely implemented");
+
+ *keysym = key;
+ }
else if (mode == TRANSLATE_X11KEYNAME_TO_KEYSYM)
{
Key key = KSYM_UNDEFINED;
return x11name;
}
+Key getKeyFromKeyName(char *name)
+{
+ Key key;
+
+ translate_keyname(&key, NULL, &name, TRANSLATE_KEYNAME_TO_KEYSYM);
+ return key;
+}
+
Key getKeyFromX11KeyName(char *x11name)
{
Key key;
return letter;
}
-/* ------------------------------------------------------------------------- */
-/* some functions to handle lists of level directories */
-/* ------------------------------------------------------------------------- */
-
-struct LevelDirInfo *newLevelDirInfo()
-{
- return checked_calloc(sizeof(struct LevelDirInfo));
-}
-
-void pushLevelDirInfo(struct LevelDirInfo **node_first,
- struct LevelDirInfo *node_new)
-{
- node_new->next = *node_first;
- *node_first = node_new;
-}
-
-int numLevelDirInfo(struct LevelDirInfo *node)
-{
- int num = 0;
-
- while (node)
- {
- num++;
- node = node->next;
- }
-
- return num;
-}
-
-boolean validLevelSeries(struct LevelDirInfo *node)
-{
- return (node != NULL && !node->node_group && !node->parent_link);
-}
-
-struct LevelDirInfo *getFirstValidLevelSeries(struct LevelDirInfo *node)
-{
- if (node == NULL)
- {
- if (leveldir_first) /* start with first level directory entry */
- return getFirstValidLevelSeries(leveldir_first);
- else
- return NULL;
- }
- else if (node->node_group) /* enter level group (step down into tree) */
- return getFirstValidLevelSeries(node->node_group);
- else if (node->parent_link) /* skip start entry of level group */
- {
- if (node->next) /* get first real level series entry */
- return getFirstValidLevelSeries(node->next);
- else /* leave empty level group and go on */
- return getFirstValidLevelSeries(node->node_parent->next);
- }
- else /* this seems to be a regular level series */
- return node;
-}
-
-struct LevelDirInfo *getLevelDirInfoFirstGroupEntry(struct LevelDirInfo *node)
-{
- if (node == NULL)
- return NULL;
-
- if (node->node_parent == NULL) /* top level group */
- return leveldir_first;
- else /* sub level group */
- return node->node_parent->node_group;
-}
-
-int numLevelDirInfoInGroup(struct LevelDirInfo *node)
-{
- return numLevelDirInfo(getLevelDirInfoFirstGroupEntry(node));
-}
-
-int posLevelDirInfo(struct LevelDirInfo *node)
-{
- struct LevelDirInfo *node_cmp = getLevelDirInfoFirstGroupEntry(node);
- int pos = 0;
-
- while (node_cmp)
- {
- if (node_cmp == node)
- return pos;
-
- pos++;
- node_cmp = node_cmp->next;
- }
-
- return 0;
-}
-
-struct LevelDirInfo *getLevelDirInfoFromPos(struct LevelDirInfo *node, int pos)
-{
- struct LevelDirInfo *node_default = node;
- int pos_cmp = 0;
-
- while (node)
- {
- if (pos_cmp == pos)
- return node;
-
- pos_cmp++;
- node = node->next;
- }
-
- return node_default;
-}
-
-struct LevelDirInfo *getLevelDirInfoFromFilenameExt(struct LevelDirInfo *node,
- char *filename)
-{
- if (filename == NULL)
- return NULL;
-
- while (node)
- {
- if (node->node_group)
- {
- struct LevelDirInfo *node_group;
-
- node_group = getLevelDirInfoFromFilenameExt(node->node_group, filename);
-
- if (node_group)
- return node_group;
- }
- else if (!node->parent_link)
- {
- if (strcmp(filename, node->filename) == 0)
- return node;
- }
-
- node = node->next;
- }
-
- return NULL;
-}
-
-struct LevelDirInfo *getLevelDirInfoFromFilename(char *filename)
-{
- return getLevelDirInfoFromFilenameExt(leveldir_first, filename);
-}
-
-void dumpLevelDirInfo(struct LevelDirInfo *node, int depth)
-{
- int i;
-
- while (node)
- {
- for (i=0; i<depth * 3; i++)
- printf(" ");
-
- printf("filename == '%s'\n", node->filename);
-
- if (node->node_group != NULL)
- dumpLevelDirInfo(node->node_group, depth + 1);
-
- node = node->next;
- }
-}
-
-void sortLevelDirInfo(struct LevelDirInfo **node_first,
- int (*compare_function)(const void *, const void *))
-{
- int num_nodes = numLevelDirInfo(*node_first);
- struct LevelDirInfo **sort_array;
- struct LevelDirInfo *node = *node_first;
- int i = 0;
-
- if (num_nodes == 0)
- return;
-
- /* allocate array for sorting structure pointers */
- sort_array = checked_calloc(num_nodes * sizeof(struct LevelDirInfo *));
-
- /* writing structure pointers to sorting array */
- while (i < num_nodes && node) /* double boundary check... */
- {
- sort_array[i] = node;
-
- i++;
- node = node->next;
- }
-
- /* sorting the structure pointers in the sorting array */
- qsort(sort_array, num_nodes, sizeof(struct LevelDirInfo *),
- compare_function);
-
- /* update the linkage of list elements with the sorted node array */
- for (i=0; i<num_nodes - 1; i++)
- sort_array[i]->next = sort_array[i + 1];
- sort_array[num_nodes - 1]->next = NULL;
-
- /* update the linkage of the main list anchor pointer */
- *node_first = sort_array[0];
-
- free(sort_array);
-
- /* now recursively sort the level group structures */
- node = *node_first;
- while (node)
- {
- if (node->node_group != NULL)
- sortLevelDirInfo(&node->node_group, compare_function);
-
- node = node->next;
- }
-}
-
-inline void swap_numbers(int *i1, int *i2)
-{
- int help = *i1;
-
- *i1 = *i2;
- *i2 = help;
-}
-
-inline void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
-{
- int help_x = *x1;
- int help_y = *y1;
-
- *x1 = *x2;
- *x2 = help_x;
-
- *y1 = *y2;
- *y2 = help_y;
-}
-
/* ========================================================================= */
-/* some stuff from "files.c" */
+/* functions for checking filenames */
/* ========================================================================= */
-#define MODE_R_ALL (S_IRUSR | S_IRGRP | S_IROTH)
-#define MODE_W_ALL (S_IWUSR | S_IWGRP | S_IWOTH)
-#define MODE_X_ALL (S_IXUSR | S_IXGRP | S_IXOTH)
-#define USERDATA_DIR_MODE (MODE_R_ALL | MODE_X_ALL | S_IWUSR)
-
-char *getUserDataDir(void)
+boolean FileIsGraphic(char *filename)
{
- static char *userdata_dir = NULL;
+ if (strlen(filename) > 4 &&
+ strcmp(&filename[strlen(filename) - 4], ".pcx") == 0)
+ return TRUE;
- if (!userdata_dir)
- {
- char *home_dir = getHomeDir();
- char *data_dir = program.userdata_directory;
-
- userdata_dir = getPath2(home_dir, data_dir);
- }
-
- return userdata_dir;
+ return FALSE;
}
-void createDirectory(char *dir, char *text)
+boolean FileIsSound(char *filename)
{
- if (access(dir, F_OK) != 0)
-#if defined(PLATFORM_WIN32)
- if (mkdir(dir) != 0)
-#else
- if (mkdir(dir, USERDATA_DIR_MODE) != 0)
-#endif
- Error(ERR_WARN, "cannot create %s directory '%s'", text, dir);
+ if (strlen(filename) > 4 &&
+ strcmp(&filename[strlen(filename) - 4], ".wav") == 0)
+ return TRUE;
+
+ return FALSE;
}
-void InitUserDataDirectory()
+boolean FileIsMusic(char *filename)
{
- createDirectory(getUserDataDir(), "user data");
+ if (strlen(filename) > 4 &&
+ (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 ||
+ strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 ||
+ strncmp(filename, "mod.", 4) == 0 ||
+ strncmp(filename, "MOD.", 4) == 0))
+ return TRUE;
+
+ return FALSE;
}
-
/* ========================================================================= */
/* functions only needed for non-Unix (non-command-line) systems */
/* ========================================================================= */
FILE *error_file;
filename = getPath2(getUserDataDir(), ERROR_FILENAME);
- error_file = fopen(filename, "a");
+ error_file = fopen(filename, MODE_APPEND);
free(filename);
return error_file;
FILE *error_file;
filename = getPath2(getUserDataDir(), ERROR_FILENAME);
- error_file = fopen(filename, "r");
+ error_file = fopen(filename, MODE_READ);
free(filename);
if (error_file != NULL)