DEADSOFTWARE

system: add stub system driver
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sat, 6 Nov 2021 10:19:22 +0000 (13:19 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Sat, 6 Nov 2021 10:19:22 +0000 (13:19 +0300)
src/CMakeLists.txt
src/stubsys/files.c [new file with mode: 0644]
src/stubsys/main.c [new file with mode: 0644]

index 096663a786ddbe51bf8820559c879f79dab16d65..aa05b291c939c762a4d438f2e666eeec95b48e41 100644 (file)
@@ -13,6 +13,7 @@ string(TOUPPER "${SYSTEM_DRIVER}" SYSTEM_DRIVER)
 string(COMPARE EQUAL "${SYSTEM_DRIVER}" "SDL" WITH_SDL)
 string(COMPARE EQUAL "${SYSTEM_DRIVER}" "SDL2" WITH_SDL2)
 string(COMPARE EQUAL "${SYSTEM_DRIVER}" "KOS32" WITH_KOS32)
+string(COMPARE EQUAL "${SYSTEM_DRIVER}" "STUB" WITH_STUBSYS)
 string(TOUPPER "${RENDER_DRIVER}" RENDER_DRIVER)
 string(COMPARE EQUAL "${RENDER_DRIVER}" "OPENGL" WITH_OPENGL)
 string(COMPARE EQUAL "${RENDER_DRIVER}" "SOFTWARE" WITH_SOFTWARE)
@@ -26,6 +27,7 @@ set(D2D_GAME_ROOT .)
 set(D2D_SDL_ROOT ${D2D_GAME_ROOT}/sdl)
 set(D2D_SDL2_ROOT ${D2D_GAME_ROOT}/sdl2)
 set(D2D_KOS32_ROOT ${D2D_GAME_ROOT}/kos32)
+set(D2D_STUBSYS_ROOT ${D2D_GAME_ROOT}/stubsys)
 set(D2D_OPENGL_ROOT ${D2D_GAME_ROOT}/gl)
 set(D2D_SOFTWARE_ROOT ${D2D_GAME_ROOT}/soft)
 set(D2D_STUBRENDER_ROOT ${D2D_GAME_ROOT}/stubren)
@@ -39,6 +41,7 @@ aux_source_directory(${D2D_GAME_ROOT} D2D_GAME_SRC)
 aux_source_directory(${D2D_SDL_ROOT} D2D_SDL_SRC)
 aux_source_directory(${D2D_SDL2_ROOT} D2D_SDL2_SRC)
 aux_source_directory(${D2D_KOS32_ROOT} D2D_KOS32_SRC)
+aux_source_directory(${D2D_STUBSYS_ROOT} D2D_STUBSYS_SRC)
 aux_source_directory(${D2D_OPENGL_ROOT} D2D_OPENGL_SRC)
 aux_source_directory(${D2D_SOFTWARE_ROOT} D2D_SOFTWARE_SRC)
 aux_source_directory(${D2D_STUBRENDER_ROOT} D2D_STUBRENDER_SRC)
@@ -86,8 +89,13 @@ elseif(WITH_KOS32)
   set(D2D_SYSTEM_INCLUDE_DIR "")
   set(D2D_SYSTEM_LIBRARY "-lck")
   set(D2D_SYSTEM_LINKFLAGS "")
+elseif(WITH_STUBSYS)
+  set(D2D_SYSTEM_SRC "${D2D_STUBSYS_SRC}")
+  set(D2D_SYSTEM_INCLUDE_DIR "")
+  set(D2D_SYSTEM_LIBRARY "")
+  set(D2D_SYSTEM_LINKFLAGS "")
 else()
-  message(FATAL_ERROR "Select SYSTEM_DRIVER as 'SDL' or 'SDL2' or 'KOS32'")
+  message(FATAL_ERROR "Select SYSTEM_DRIVER as 'SDL' or 'SDL2' or 'KOS32' or 'STUB'")
 endif()
 
 if(WITH_STUBRENDER)
diff --git a/src/stubsys/files.c b/src/stubsys/files.c
new file mode 100644 (file)
index 0000000..7ccfe4e
--- /dev/null
@@ -0,0 +1,202 @@
+/* Copyright (C) 1996-1997 Aleksey Volynskov
+ * Copyright (C) 2011 Rambo
+ * Copyright (C) 2020 SovietPony
+ *
+ * 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, version 3 of the License ONLY.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "glob.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "files.h"
+#include "error.h"
+
+#include "map.h" // MAP_load
+#include "save.h" // SAVE_getname
+
+#ifdef UNIX
+#  include <sys/stat.h>
+#endif
+
+#include "common/streams.h"
+#include "common/files.h"
+#include "common/wadres.h"
+#include "common/cp866.h"
+
+int d_start, d_end;
+
+char savname[SAVE_MAX][SAVE_MAXLEN];
+char savok[SAVE_MAX];
+
+static int m_start, m_end;
+static int s_start, s_end;
+
+void F_addwad (const char *fn) {
+  static int i = 0;
+  static FILE_Stream wadh[MAX_WADS];
+  if (i < MAX_WADS) {
+    if (FILE_Open(&wadh[i], fn, "rb")) {
+      if (WADRES_addwad(&wadh[i].base)) {
+        i += 1;
+      } else {
+        ERR_failinit("Invalid WAD %s", fn);
+      }
+    } else {
+      ERR_failinit("Unable to add WAD %s", fn);
+    }
+  } else {
+    ERR_failinit("Too many wads");
+  }
+}
+
+void F_initwads (void) {
+  if (!WADRES_rehash()) {
+    ERR_failinit("F_initwads: failed rehash");
+  }
+  d_start = F_getresid("D_START");
+  d_end = F_getresid("D_END");
+  m_start = F_getresid("M_START");
+  m_end = F_getresid("M_END");
+  s_start = F_getresid("S_START");
+  s_end = F_getresid("S_END");
+}
+
+int F_findres (const char n[8]) {
+  return WADRES_find(n);
+}
+
+int F_getresid (const char n[8]) {
+  int i = F_findres(n);
+  if (i == -1) {
+    ERR_fatal("F_getresid: resource %.8s not found", n);
+  }
+  return i;
+}
+
+void F_getresname (char n[8], int r) {
+  WADRES_getname(r, n);
+}
+
+int F_getsprid (const char n[4], int s, int d, char *dir) {
+  int i = WADRES_findsprite(n, s, d, dir);
+  if (i == -1) {
+    ERR_fatal("F_getsprid: image %.4s%c%c not found", n, s, d);
+  }
+  return i;
+}
+
+int F_getreslen (int r) {
+  return WADRES_getsize(r);
+}
+
+/*
+void F_nextmus (char *s) {
+  int i = F_findres(s);
+  if (i <= m_start || i >= m_end) {
+    i = m_start;
+  }
+  for (++i; ; ++i) {
+    if (i >= m_end) {
+      i = m_start + 1;
+    }
+    WADRES_getname(i, s);
+    if (cp866_strcasecmp(s, "MENU") == 0 ||
+        cp866_strcasecmp(s, "INTERMUS") == 0 ||
+        cp866_strcasecmp(s, "\x8a\x8e\x8d\x85\x96\x0") == 0) {
+      continue;
+    }
+    if (cp866_strncasecmp(s, "DMI", 3) != 0) {
+      break;
+    }
+  }
+}
+
+void F_randmus (char *s) {
+  int i;
+  int n = myrand(10);
+  for (i = 0; i < n; i++) {
+    F_nextmus(s);
+  }
+}
+*/
+
+void F_loadmap (char n[8]) {
+  int id = F_getresid(n);
+  if (id != -1) {
+    Stream *r = WADRES_getbasereader(id);
+    long offset = WADRES_getoffset(id);
+    stream_setpos(r, offset);
+    if (!MAP_load(r)) {
+      ERR_fatal("Failed to load map");
+    }
+  } else {
+    ERR_fatal("Failed to load map: resource %.8s not found", n);
+  }
+}
+
+static char *getsavfpname (int n, int ro) {
+  static char fn[] = "savgame0.dat";
+  static char p[100];
+  fn[7] = n + '0';
+#ifdef UNIX
+  char *e = getenv("HOME");
+  strncpy(p, e, 60);
+  strcat(p, "/.flatwaifu");
+  if (!ro) {
+    mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+  }
+  strcat(p, "/");
+  strcat(p, fn);
+#else
+  strcpy(p, fn);
+#endif
+  return p;
+}
+
+void F_getsavnames (void) {
+  int i;
+  FILE_Stream rd;
+  for (i = 0; i < SAVE_MAX; ++i) {
+    savok[i] = 0;
+    char *p = getsavfpname(i, 1);
+    if (FILE_Open(&rd, p, "rb")) {
+      savok[i] = SAVE_getname(&rd.base, savname[i]);
+      FILE_Close(&rd);
+    }
+    if (!savok[i]) {
+      memset(savname[i], 0, 24);
+    } else {
+      savname[i][23] = 0;
+    }
+  }
+}
+
+void F_loadgame (int n) {
+  FILE_Stream rd;
+  char *p = getsavfpname(n, 1);
+  if (FILE_Open(&rd, p, "rb")) {
+    SAVE_load(&rd.base);
+    FILE_Close(&rd);
+  }
+}
+
+void F_savegame (int n, char *s) {
+  FILE_Stream wr;
+  char *p = getsavfpname(n, 0);
+  if (FILE_Open(&wr, p, "wb")) {
+    SAVE_save(&wr.base, s);
+    FILE_Close(&wr);
+  }
+}
diff --git a/src/stubsys/main.c b/src/stubsys/main.c
new file mode 100644 (file)
index 0000000..75ddd86
--- /dev/null
@@ -0,0 +1,308 @@
+/* Copyright (C) 2020 SovietPony
+ *
+ * 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, version 3 of the License ONLY.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __EMSCRIPTEN__
+#  include <emscripten.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h> // srand exit
+#include <assert.h>
+#include <time.h>
+#include "system.h"
+#include "input.h"
+
+#include "player.h" // pl1 pl2
+#include "menu.h" // G_keyf
+#include "error.h" // logo
+#include "monster.h" // nomon
+
+#include "files.h" // F_startup F_addwad F_initwads F_allocres
+#include "config.h" // CFG_args CFG_load CFG_save
+#include "args.h" // ARG_parse
+#include "memory.h" // M_startup
+#include "game.h" // G_init G_act
+#include "sound.h" // S_init S_done
+#include "music.h" // S_initmusic S_updatemusic S_donemusic
+#include "render.h" // R_init R_draw R_done
+
+#define MODE_NONE 0
+#define MODE_OPENGL 1
+#define MODE_SOFTWARE 2
+
+static clock_t ticks;
+static int quit = 0;
+static int mode = MODE_NONE;
+static int text_input = 0;
+static int width = 0;
+static int height = 0;
+static int fullscreen = 0;
+static void *softbuffer = NULL;
+static videomode_size_t vsize = { 320, 200, 0 };
+static videomode_t vlist = { 1, &vsize };
+
+static const cfg_t arg[] = {
+  {"file", NULL, Y_FILES},
+  {"cheat", &cheat, Y_SW_ON},
+//  {"vga", &shot_vga, Y_SW_ON},
+//  {"musvol", &mus_vol, Y_WORD},
+  {"mon", &nomon, Y_SW_OFF},
+  {"warp", &_warp, Y_BYTE},
+//  {"config", NULL, cfg_file, Y_STRING},
+  {NULL, NULL, 0} // end
+};
+
+static const cfg_t cfg[] = {
+//  {"screenshot", &shot_vga, Y_SW_ON},
+//  {"music_volume", &mus_vol, Y_WORD},
+//  {"music_random", &music_random, Y_SW_ON},
+//  {"music_time", &music_time, Y_DWORD},
+//  {"music_fade", &music_fade, Y_DWORD},
+  {"pl1_left", &pl1.kl, Y_KEY},
+  {"pl1_right",&pl1.kr, Y_KEY},
+  {"pl1_up", &pl1.ku, Y_KEY},
+  {"pl1_down", &pl1.kd, Y_KEY},
+  {"pl1_jump", &pl1.kj, Y_KEY},
+  {"pl1_fire", &pl1.kf, Y_KEY},
+  {"pl1_next", &pl1.kwr, Y_KEY},
+  {"pl1_prev", &pl1.kwl, Y_KEY},
+  {"pl1_use", &pl1.kp, Y_KEY},
+  {"pl2_left", &pl2.kl, Y_KEY},
+  {"pl2_right", &pl2.kr, Y_KEY},
+  {"pl2_up", &pl2.ku, Y_KEY},
+  {"pl2_down", &pl2.kd, Y_KEY},
+  {"pl2_jump", &pl2.kj, Y_KEY},
+  {"pl2_fire", &pl2.kf, Y_KEY},
+  {"pl2_next", &pl2.kwr, Y_KEY},
+  {"pl2_prev", &pl2.kwl, Y_KEY},
+  {"pl2_use", &pl2.kp, Y_KEY},
+  {NULL, NULL, 0} // end
+};
+
+static void CFG_args (int argc, char **argv) {
+  const cfg_t *list[] = { arg, R_args(), S_args(), MUS_args() };
+  ARG_parse(argc, argv, 4, list);
+}
+
+static void CFG_load (void) {
+  const cfg_t *list[] = { cfg, R_conf(), S_conf(), MUS_conf() };
+  CFG_read_config("default.cfg", 4, list);
+  CFG_read_config("doom2d.cfg", 4, list);
+}
+
+static void CFG_save (void) {
+  const cfg_t *list[] = { cfg, R_conf(), S_conf(), MUS_conf() };
+  CFG_update_config("doom2d.cfg", "doom2d.cfg", 4, list, "generated by doom2d, do not modify");
+}
+
+/* --- error.h --- */
+
+void logo (const char *s, ...) {
+  va_list ap;
+  va_start(ap, s);
+  vprintf(s, ap);
+  va_end(ap);
+  fflush(stdout);
+}
+
+void logo_gas (int cur, int all) {
+  // stub
+}
+
+void ERR_failinit (char *s, ...) {
+  va_list ap;
+  va_start(ap, s);
+  vprintf(s, ap);
+  va_end(ap);
+  puts("");
+  abort();
+}
+
+void ERR_fatal (char *s, ...) {
+  va_list ap;
+  R_done();
+  MUS_done();
+  S_done();
+  puts("\nCRITICAL ERROR:");
+  va_start(ap, s);
+  vprintf(s, ap);
+  va_end(ap);
+  puts("");
+  abort();
+}
+
+void ERR_quit (void) {
+  quit = 1;
+}
+
+/* --- system.h --- */
+
+int Y_set_videomode_opengl (int w, int h, int fullscreen) {
+  assert(w > 0);
+  assert(h > 0);
+  mode = MODE_OPENGL;
+  width = w;
+  height = h;
+  return 1;
+}
+
+int Y_set_videomode_software (int w, int h, int fullscreen) {
+  assert(w > 0);
+  assert(h > 0);
+  void *buf = softbuffer ? realloc(softbuffer, w * h) : malloc(w * h);
+  if (buf) {
+    mode = MODE_SOFTWARE;
+    softbuffer = buf;
+    width = w;
+    height = h;
+  }
+  return buf != NULL;
+}
+
+const videomode_t *Y_get_videomode_list_opengl (int fullscreen) {
+  return &vlist;
+}
+
+const videomode_t *Y_get_videomode_list_software (int fullscreen) {
+  return &vlist;
+}
+
+void Y_get_videomode (int *w, int *h) {
+  if (mode != MODE_NONE) {
+    *w = width;
+    *h = height;
+  } else {
+    *w = 0;
+    *h = 0;
+  }
+}
+
+int Y_videomode_setted (void) {
+  return mode != MODE_NONE;
+}
+
+void Y_unset_videomode (void) {
+  mode = MODE_NONE;
+  free(softbuffer);
+  softbuffer = NULL;
+}
+
+void Y_set_fullscreen (int yes) {
+  fullscreen = yes;
+}
+
+int Y_get_fullscreen (void) {
+  return (mode != MODE_NONE) && fullscreen;
+}
+
+void Y_swap_buffers (void) {
+  assert(mode == MODE_OPENGL);
+}
+
+void Y_get_buffer (byte **buf, int *w, int *h, int *pitch) {
+  assert(mode == MODE_SOFTWARE);
+  // *buf = surf->pixels;
+  *buf = NULL; // fix this
+  *w = width;
+  *h = height;
+  *pitch = width;
+}
+
+void Y_set_vga_palette (byte *vgapal) {
+  int i;
+  byte *p = vgapal;
+  assert(vgapal != NULL);
+  assert(mode == MODE_SOFTWARE);
+}
+
+void Y_repaint_rect (int x, int y, int w, int h) {
+  assert(mode == MODE_SOFTWARE);
+}
+
+void Y_repaint (void) {
+  assert(mode == MODE_SOFTWARE);
+}
+
+void Y_enable_text_input (void) {
+  text_input = 1;
+}
+
+void Y_disable_text_input (void) {
+  text_input = 0;
+}
+
+/* --- main --- */
+
+static void poll_events (void) {
+  // stub
+}
+
+static void step (void) {
+  poll_events();
+  MUS_update();
+  clock_t t = clock();
+  if ((t - ticks) * 1000 / CLOCKS_PER_SEC > DELAY) {
+    ticks = t;
+    G_act();
+  }
+  R_draw();
+}
+
+int main (int argc, char *argv[]) {
+  logo("main: initialize\n");
+  // Player 1 defaults
+  pl1.ku = KEY_KP_8;
+  pl1.kd = KEY_KP_5;
+  pl1.kl = KEY_KP_4;
+  pl1.kr = KEY_KP_6;
+  pl1.kf = KEY_PAGEDOWN;
+  pl1.kj = KEY_DELETE;
+  pl1.kwl = KEY_HOME;
+  pl1.kwr = KEY_END;
+  pl1.kp = KEY_KP_8;
+  // Player 2 defaults
+  pl2.ku = KEY_E;
+  pl2.kd = KEY_D;
+  pl2.kl = KEY_S;
+  pl2.kr = KEY_F;
+  pl2.kf = KEY_A;
+  pl2.kj = KEY_Q;
+  pl2.kwl = KEY_1;
+  pl2.kwr = KEY_2;
+  pl2.kp = KEY_E;
+  //srand(SDL_GetTicks());
+  F_addwad("doom2d.wad");
+  CFG_args(argc, argv);
+  CFG_load();
+  F_initwads();
+  S_init();
+  MUS_init();
+  R_init();
+  G_init();
+  ticks = clock();
+#ifdef __EMSCRIPTEN__
+  emscripten_set_main_loop(step, 0, 1);
+#else
+  while (!quit) {
+    step();
+  }
+#endif
+  CFG_save();
+  R_done();
+  MUS_done();
+  S_done();
+  return 0;
+}