summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 990d4b2)
raw | patch | inline | side by side (parent: 990d4b2)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 1 Feb 2021 23:56:44 +0000 (02:56 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 1 Feb 2021 23:56:44 +0000 (02:56 +0300) |
src/CMakeLists.txt | patch | blob | history | |
src/cmake/kos32-tcc.cmake | [new file with mode: 0755] | patch | blob |
src/kos32/kos32.h | [new file with mode: 0644] | patch | blob |
src/kos32/main.c | [new file with mode: 0644] | patch | blob |
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d91997eb8fa0612fc4d61e2ab1b36ab55fcf6b70..65b419637e68be42f584ccf462518461fa424bbd 100644 (file)
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
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(TOUPPER "${RENDER_DRIVER}" RENDER_DRIVER)
string(COMPARE EQUAL "${RENDER_DRIVER}" "OPENGL" WITH_OPENGL)
string(COMPARE EQUAL "${RENDER_DRIVER}" "SOFTWARE" WITH_SOFTWARE)
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_OPENGL_ROOT ${D2D_GAME_ROOT}/gl)
set(D2D_SOFTWARE_ROOT ${D2D_GAME_ROOT}/soft)
set(D2D_STUBRENDER_ROOT ${D2D_GAME_ROOT}/stubren)
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_OPENGL_ROOT} D2D_OPENGL_SRC)
aux_source_directory(${D2D_SOFTWARE_ROOT} D2D_SOFTWARE_SRC)
aux_source_directory(${D2D_STUBRENDER_ROOT} D2D_STUBRENDER_SRC)
set(D2D_SYSTEM_INCLUDE_DIR "${SDL2_INCLUDE_DIRS}")
set(D2D_SYSTEM_LIBRARY "${SDL2_LIBRARIES}")
endif()
+elseif(WITH_KOS32)
+ set(D2D_SYSTEM_SRC "${D2D_KOS32_SRC}")
+ set(D2D_SYSTEM_INCLUDE_DIR "")
+ set(D2D_SYSTEM_LIBRARY "-lck")
+ set(D2D_SYSTEM_LINKFLAGS "")
else()
- message(FATAL_ERROR "Select SYSTEM_DRIVER as 'SDL' or 'SDL2'")
+ message(FATAL_ERROR "Select SYSTEM_DRIVER as 'SDL' or 'SDL2' or 'KOS32'")
endif()
if(WITH_STUBRENDER)
diff --git a/src/cmake/kos32-tcc.cmake b/src/cmake/kos32-tcc.cmake
--- /dev/null
@@ -0,0 +1,17 @@
+# Usage:
+# cmake -DCMAKE_TOOLCHAIN_FILE=path/to/kos32-tcc.cmake ..
+
+set(CMAKE_SYSTEM_NAME KolibriOS)
+set(TOOLCHAIN_PREFIX kos32)
+
+# cross compilers to use for C, C++ and Fortran
+set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-tcc)
+
+# target environment on the build host system
+#set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}/sys-root/kos32)
+
+# modify default behavior of FIND_XXX() commands
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
diff --git a/src/kos32/kos32.h b/src/kos32/kos32.h
--- /dev/null
+++ b/src/kos32/kos32.h
@@ -0,0 +1,380 @@
+#ifndef KOS32_H
+#define KOS32_H
+
+/* --- fn 0 (styles) --- */
+#define KOS32_WIN_STYLE_EMPTY 0
+#define KOS32_WIN_STYLE_SKIN 3
+#define KOS32_WIN_STYLE_FIXED 4
+
+/* --- fn 0 (flags) --- */
+#define KOS32_WIN_FLAG_CAPTION 1
+#define KOS32_WIN_FLAG_RELATIVE 2
+#define KOS32_WIN_FLAG_NOFILL 4
+#define KOS32_WIN_FLAG_GRADIENT 8
+#define KOS32_WIN_FLAG_UNMOVABLE 256
+
+/* --- fn 0 --- */
+static inline void CreateWindow (int x, int y, int w, int h, int style, int flags, int color, int hcolor, const char *title) {
+ int f = (title ? KOS32_WIN_FLAG_CAPTION : 0) | (flags & ~KOS32_WIN_FLAG_CAPTION);
+ __asm__ __volatile__ (
+ "int $0x40"
+ :
+ : "a" (0),
+ "b" (x << 16 | ((w - 1) & 0xffff)),
+ "c" (y << 16 | ((h - 1) & 0xffff)),
+ "d" ((f << 28) | ((style & 0xf) << 24) | (color & 0xffffff)),
+ "S" (((f >> 8) << 24) | (hcolor & 0xffffff)),
+ "D" (title)
+ : "memory"
+ );
+}
+
+/* --- fn 12.1 --- */
+static inline void BeginDraw (void) {
+ __asm__ __volatile__ (
+ "int $0x40"
+ :
+ : "a" (12),
+ "b" (1)
+ );
+}
+
+/* --- fn 12.2 --- */
+static inline void EndDraw (void) {
+ __asm__ __volatile__ (
+ "int $0x40"
+ :
+ : "a" (12),
+ "b" (2)
+ );
+}
+
+/* --- fn 65 --- */
+static inline void PutImageExt (const void *image, int w, int h, int x, int y, int bpp, const void *pal, int offset) {
+ __asm__ __volatile__ (
+ "push %%ebp; movl %6, %%ebp; int $0x40; pop %%ebp"
+ :
+ : "a" (65),
+ "b" (image),
+ "c" (w << 16 | (h & 0xffff)),
+ "d" (x << 16 | (y & 0xffff)),
+ "S" (bpp),
+ "D" (pal),
+ "m" (offset)
+ : "memory", "ebp"
+ );
+}
+
+/* --- fn 18.4 --- */
+static inline int GetIdleCount (void) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (18),
+ "b" (4)
+ );
+ return ret;
+}
+
+/* --- fn 26.9 --- */
+/* result is 1/100 sec */
+static inline int GetTimeCount (void) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (26),
+ "b" (9)
+ );
+ return ret;
+}
+
+/* --- fn 26.10 --- */
+/* result is 1/1000000 sec (nanosec) */
+static inline long GetTimeCountPro (void) {
+ union {
+ struct { int lo, hi; };
+ long pair;
+ } ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret.lo),
+ "=b" (ret.hi)
+ : "a" (26),
+ "b" (10)
+ );
+ return ret.pair;
+}
+
+/* --- fn 40 (flags) --- */
+#define KOS32_EVENT_FLAG_REDRAW (1 << 0)
+#define KOS32_EVENT_FLAG_KEYBOARD (1 << 1)
+#define KOS32_EVENT_FLAG_BUTTON (1 << 2)
+#define KOS32_EVENT_FLAG_RESERVED (1 << 3)
+#define KOS32_EVENT_FLAG_REDRAW_BG (1 << 4)
+#define KOS32_EVENT_FLAG_MOUSE (1 << 5)
+#define KOS32_EVENT_FLAG_IPC (1 << 6)
+#define KOS32_EVENT_FLAG_NETWORK (1 << 7)
+#define KOS32_EVENT_FLAG_DEBUG (1 << 8)
+#define KOS32_EVENT_FLAG_IRQ0 (1 << 15)
+#define KOS32_EVENT_FLAG_IRQ1 (1 << 16)
+#define KOS32_EVENT_FLAG_IRQ2 (1 << 17)
+#define KOS32_EVENT_FLAG_IRQ3 (1 << 18)
+#define KOS32_EVENT_FLAG_IRQ4 (1 << 19)
+#define KOS32_EVENT_FLAG_IRQ5 (1 << 20)
+#define KOS32_EVENT_FLAG_IRQ6 (1 << 21)
+#define KOS32_EVENT_FLAG_IRQ7 (1 << 22)
+#define KOS32_EVENT_FLAG_IRQ8 (1 << 23)
+#define KOS32_EVENT_FLAG_IRQ9 (1 << 24)
+#define KOS32_EVENT_FLAG_IRQ10 (1 << 25)
+#define KOS32_EVENT_FLAG_IRQ11 (1 << 26)
+#define KOS32_EVENT_FLAG_IRQ12 (1 << 27)
+#define KOS32_EVENT_FLAG_IRQ13 (1 << 28)
+#define KOS32_EVENT_FLAG_IRQ14 (1 << 29)
+#define KOS32_EVENT_FLAG_IRQ15 (1 << 30) /* ??? */
+#define KOS32_EVENT_FLAG_MOUSE_NOFOCUS (1 << 30)
+#define KOS32_EVENT_FLAG_MOUSE_NOACTIVE (1 << 31)
+
+/* --- fn 40 (events) --- */
+#define KOS32_EVENT_NONE 0
+#define KOS32_EVENT_REDRAW 1
+#define KOS32_EVENT_KEYBOARD 2
+#define KOS32_EVENT_BUTTON 3
+#define KOS32_EVENT_RESERVED 4
+#define KOS32_EVENT_REDRAW_BG 5
+#define KOS32_EVENT_MOUSE 6
+#define KOS32_EVENT_IPC 7
+#define KOS32_EVENT_NETWORK 8
+#define KOS32_EVENT_DEBUG 9
+#define KOS32_EVENT_IRQ0 16
+#define KOS32_EVENT_IRQ1 17
+#define KOS32_EVENT_IRQ2 18
+#define KOS32_EVENT_IRQ3 19
+#define KOS32_EVENT_IRQ4 20
+#define KOS32_EVENT_IRQ5 21
+#define KOS32_EVENT_IRQ6 22
+#define KOS32_EVENT_IRQ7 23
+#define KOS32_EVENT_IRQ8 24
+#define KOS32_EVENT_IRQ9 25
+#define KOS32_EVENT_IRQ10 26
+#define KOS32_EVENT_IRQ11 27
+#define KOS32_EVENT_IRQ12 28
+#define KOS32_EVENT_IRQ13 29
+#define KOS32_EVENT_IRQ14 30
+#define KOS32_EVENT_IRQ15 31
+
+/* --- fn 40 --- */
+static inline int SetEventsMask (int mask) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (mask)
+ );
+ return ret;
+}
+
+/* --- fn 11 --- */
+static inline int CheckEvent (void) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (11)
+ );
+ return ret;
+}
+
+/* --- fn 2 --- */
+static inline int GetKey (void) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (2)
+ );
+ return ret;
+}
+
+/* --- fn 17 --- */
+static inline int GetButton (void) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (17)
+ );
+ return ret;
+}
+
+#define KOS32_INPUT_MODE_ASCII 0
+#define KOS32_INPUT_MODE_SCANCODE 1
+
+/* --- fn 66.1 --- */
+static inline void SetInputMode (int mode) {
+ __asm__ __volatile__ (
+ "int $0x40"
+ :
+ : "a" (66),
+ "b" (1),
+ "c" (mode)
+ );
+}
+
+/* --- fn 66.2 --- */
+static inline int GetInputMode (void) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (66),
+ "b" (2)
+ );
+ return ret;
+}
+
+/* --- fn 48.4 --- */
+static inline int GetSkinHeight (void) {
+ int ret;
+ __asm__ __volatile__ (
+ "int $0x40"
+ : "=a" (ret)
+ : "a" (48),
+ "b" (4)
+ );
+ return ret;
+}
+
+#define KOS32_SC_UNKNOWN 0x00
+#define KOS32_SC_ESCAPE 0x01
+#define KOS32_SC_1 0x02
+#define KOS32_SC_2 0x03
+#define KOS32_SC_3 0x04
+#define KOS32_SC_4 0x05
+#define KOS32_SC_5 0x06
+#define KOS32_SC_6 0x07
+#define KOS32_SC_7 0x08
+#define KOS32_SC_8 0x09
+#define KOS32_SC_9 0x0A
+#define KOS32_SC_0 0x0B
+#define KOS32_SC_MINUS 0x0C
+#define KOS32_SC_EQUALS 0x0D
+#define KOS32_SC_BACKSPACE 0x0E
+#define KOS32_SC_TAB 0x0F
+#define KOS32_SC_Q 0x10
+#define KOS32_SC_W 0x11
+#define KOS32_SC_E 0x12
+#define KOS32_SC_R 0x13
+#define KOS32_SC_T 0x14
+#define KOS32_SC_Y 0x15
+#define KOS32_SC_U 0x16
+#define KOS32_SC_I 0x17
+#define KOS32_SC_O 0x18
+#define KOS32_SC_P 0x19
+#define KOS32_SC_LEFTBRACKET 0x1A
+#define KOS32_SC_RIGHTBRACKET 0x1B
+#define KOS32_SC_RETURN 0x1C
+#define KOS32_SC_LCTRL 0x1D
+#define KOS32_SC_A 0x1E
+#define KOS32_SC_S 0x1F
+#define KOS32_SC_D 0x20
+#define KOS32_SC_F 0x21
+#define KOS32_SC_G 0x22
+#define KOS32_SC_H 0x23
+#define KOS32_SC_J 0x24
+#define KOS32_SC_K 0x25
+#define KOS32_SC_L 0x26
+#define KOS32_SC_SEMICOLON 0x27
+#define KOS32_SC_APOSTROPHE 0x28
+#define KOS32_SC_GRAVE 0x29
+#define KOS32_SC_LSHIFT 0x2A
+#define KOS32_SC_BACKSLASH 0x2B
+#define KOS32_SC_Z 0x2C
+#define KOS32_SC_X 0x2D
+#define KOS32_SC_C 0x2E
+#define KOS32_SC_V 0x2F
+#define KOS32_SC_B 0x30
+#define KOS32_SC_N 0x31
+#define KOS32_SC_M 0x32
+#define KOS32_SC_COMMA 0x33
+#define KOS32_SC_PERIOD 0x34
+#define KOS32_SC_SLASH 0x35
+#define KOS32_SC_RSHIFT 0x36
+#define KOS32_SC_KP_MULTIPLY 0x37
+#define KOS32_SC_LALT 0x38
+#define KOS32_SC_SPACE 0x39
+#define KOS32_SC_CAPSLOCK 0x3A
+#define KOS32_SC_F1 0x3B
+#define KOS32_SC_F2 0x3C
+#define KOS32_SC_F3 0x3D
+#define KOS32_SC_F4 0x3E
+#define KOS32_SC_F5 0x3F
+#define KOS32_SC_F6 0x40
+#define KOS32_SC_F7 0x41
+#define KOS32_SC_F8 0x42
+#define KOS32_SC_F9 0x43
+#define KOS32_SC_F10 0x44
+#define KOS32_SC_NUMLOCK 0x45
+#define KOS32_SC_SCROLLLOCK 0x46
+#define KOS32_SC_KP_7 0x47
+#define KOS32_SC_KP_8 0x48
+#define KOS32_SC_KP_9 0x49
+#define KOS32_SC_KP_MINUS 0x4A
+#define KOS32_SC_KP_4 0x4B
+#define KOS32_SC_KP_5 0x4C
+#define KOS32_SC_KP_6 0x4D
+#define KOS32_SC_KP_PLUS 0x4E
+#define KOS32_SC_KP_1 0x4F
+#define KOS32_SC_KP_2 0x50
+#define KOS32_SC_KP_3 0x51
+#define KOS32_SC_KP_0 0x52
+#define KOS32_SC_KP_PERIOD 0x53
+/* ... */
+#define KOS32_SC_F11 0x57
+#define KOS32_SC_F12 0x58
+
+/* extended scancodes */
+#define KOS32_SC_EXTENDED 0xE0 /* starts with this */
+#define KOS32_SC_PREV_TRACK 0x10
+#define KOS32_SC_NEXT_TRACK 0x19
+#define KOS32_SC_KP_ENTER 0x1C
+#define KOS32_SC_RCTRL 0x1D
+#define KOS32_SC_MUTE 0x20
+#define KOS32_SC_CALC 0x21
+#define KOS32_SC_PLAY 0x22
+#define KOS32_SC_STOP 0x24
+#define KOS32_SC_VOLUME_DOWN 0x2E
+#define KOS32_SC_VOLUME_UP 0x30
+#define KOS32_SC_WWW 0x32
+#define KOS32_SC_KP_DIVIDE 0x35
+#define KOS32_SC_RALT 0x38
+#define KOS32_SC_HOME 0x47
+#define KOS32_SC_UP 0x48
+#define KOS32_SC_PAGEUP 0x49
+#define KOS32_SC_LEFT 0x4B
+#define KOS32_SC_RIGHT 0x4D
+#define KOS32_SC_END 0x4F
+#define KOS32_SC_DOWN 0x50
+#define KOS32_SC_PAGEDOWN 0x51
+#define KOS32_SC_INSERT 0x52
+#define KOS32_SC_DELETE 0x53
+#define KOS32_SC_LSUPER 0x5B
+#define KOS32_SC_RSUPER 0x5C
+#define KOS32_SC_APP 0x5D
+#define KOS32_SC_POWER 0x5E
+#define KOS32_SC_SLEEP 0x5F
+#define KOS32_SC_WAKE 0x63
+#define KOS32_SC_WWW_SEARCH 0x65
+#define KOS32_SC_WWW_FAVORITE 0x66
+#define KOS32_SC_WWW_REFRESH 0x67
+#define KOS32_SC_WWW_STOP 0x68
+#define KOS32_SC_WWW_FORWARD 0x69
+#define KOS32_SC_WWW_BACK 0x6A
+#define KOS32_SC_MY_COMPUTER 0x6B
+#define KOS32_SC_EMAIL 0x6C
+#define KOS32_SC_SELECT 0x6D
+
+#define KOS32_SC_EXTENDED_PAUSE 0xE1 /* pause key seq */
+
+#endif /* KOS32_H */
diff --git a/src/kos32/main.c b/src/kos32/main.c
--- /dev/null
+++ b/src/kos32/main.c
@@ -0,0 +1,590 @@
+/* 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 "kos32.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h> // srand exit
+#include <string.h>
+#include <assert.h>
+#include "system.h"
+#include "input.h"
+
+#include "my.h" // fexists
+#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
+
+static int ticks = 0;
+static int quit = 0;
+static videomode_size_t wlist[3] = {
+ { 320, 200, 0 },
+ { 640, 400, 0 },
+ { 800, 600, 0 },
+};
+static videomode_t vlist = {
+ 3,
+ wlist
+};
+
+static byte *buf = NULL;
+static int buf_w = 0;
+static int buf_h = 0;
+static struct rgb_pal {
+ byte b, g, r, a;
+} rgbpal[256];
+
+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("");
+ while (1) ;
+// exit(1);
+}
+
+void ERR_fatal (char *s, ...) {
+ va_list ap;
+ R_done();
+ MUS_done();
+ S_done();
+ M_shutdown();
+ puts("\nCRITICAL ERROR:");
+ va_start(ap, s);
+ vprintf(s, ap);
+ va_end(ap);
+ puts("");
+ while (1) ;
+// exit(1);
+}
+
+void ERR_quit (void) {
+ quit = 1;
+}
+
+/* --- system.h --- */
+
+static int Y_resize_window (int w, int h, int fullscreen) {
+ assert(w > 0);
+ assert(h > 0);
+ if (buf != NULL) {
+ return Y_set_videomode_software(w, h, fullscreen);
+ }
+ return 0;
+}
+
+int Y_set_videomode_opengl (int w, int h, int fullscreen) {
+ assert(w > 0);
+ assert(h > 0);
+ // TODO
+ return 0;
+}
+
+static void SetupWindow (int w, int h, const char *title) {
+ int flags = KOS32_WIN_FLAG_CAPTION | KOS32_WIN_FLAG_RELATIVE | KOS32_WIN_FLAG_NOFILL;
+ int skin_h = GetSkinHeight();
+ CreateWindow(0, 0, w + 5*2, h + 5 + skin_h, KOS32_WIN_STYLE_FIXED, flags, 0x000000, 0x000000, title);
+}
+
+int Y_set_videomode_software (int w, int h, int fullscreen) {
+ assert(w > 0);
+ assert(h > 0);
+ int size = w * h;
+ byte *new_buf = malloc(size);
+ if (new_buf != NULL) {
+ Y_unset_videomode();
+ memset(new_buf, 0, size);
+ buf = new_buf;
+ buf_w = w;
+ buf_h = h;
+ BeginDraw();
+ SetupWindow(w, h, "Doom2D (software render)");
+ EndDraw();
+ }
+ return buf != NULL;
+}
+
+void Y_get_videomode (int *w, int *h) {
+ *w = buf_w;
+ *h = buf_h;
+}
+
+int Y_videomode_setted (void) {
+ return buf != NULL;
+}
+
+void Y_unset_videomode (void) {
+ if (buf != NULL) {
+ free(buf);
+ buf = NULL;
+ buf_w = 0;
+ buf_h = 0;
+ }
+}
+
+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_set_fullscreen (int yes) {
+ // TODO
+}
+
+int Y_get_fullscreen (void) {
+ // TODO
+ return 0;
+}
+
+void Y_swap_buffers (void) {
+ // TODO
+}
+
+void Y_get_buffer (byte **buf_ref, int *w, int *h, int *pitch) {
+ assert(buf_ref != NULL);
+ assert(w != NULL);
+ assert(h != NULL);
+ assert(pitch != NULL);
+ *buf_ref = buf;
+ *w = buf_w;
+ *h = buf_h;
+ *pitch = buf_w;
+}
+
+void Y_set_vga_palette (byte *vgapal) {
+ int i;
+ byte *p = vgapal;
+ assert(buf != NULL);
+ assert(vgapal != NULL);
+ for (i = 0; i < 256; i++) {
+ rgbpal[i].r = p[0] * 255 / 63;
+ rgbpal[i].g = p[1] * 255 / 63;
+ rgbpal[i].b = p[2] * 255 / 63;
+ p += 3;
+ }
+}
+
+void Y_repaint_rect (int x, int y, int w, int h) {
+ Y_repaint();
+}
+
+void Y_repaint (void) {
+ assert(buf != NULL);
+ BeginDraw();
+ SetupWindow(buf_w, buf_h, NULL);
+ PutImageExt(buf, buf_w, buf_h, 0, 0, 8, rgbpal, 0);
+ EndDraw();
+}
+
+void Y_enable_text_input (void) {
+ SetInputMode(KOS32_INPUT_MODE_ASCII);
+}
+
+void Y_disable_text_input (void) {
+ SetInputMode(KOS32_INPUT_MODE_SCANCODE);
+}
+
+/* --- main --- */
+
+static int scancode_to_key (int scancode) {
+ switch (scancode) {
+ case KOS32_SC_0: return KEY_0;
+ case KOS32_SC_1: return KEY_1;
+ case KOS32_SC_2: return KEY_2;
+ case KOS32_SC_3: return KEY_3;
+ case KOS32_SC_4: return KEY_4;
+ case KOS32_SC_5: return KEY_5;
+ case KOS32_SC_6: return KEY_6;
+ case KOS32_SC_7: return KEY_7;
+ case KOS32_SC_8: return KEY_8;
+ case KOS32_SC_9: return KEY_9;
+ case KOS32_SC_A: return KEY_A;
+ case KOS32_SC_B: return KEY_B;
+ case KOS32_SC_C: return KEY_C;
+ case KOS32_SC_D: return KEY_D;
+ case KOS32_SC_E: return KEY_E;
+ case KOS32_SC_F: return KEY_F;
+ case KOS32_SC_G: return KEY_G;
+ case KOS32_SC_H: return KEY_H;
+ case KOS32_SC_I: return KEY_I;
+ case KOS32_SC_J: return KEY_J;
+ case KOS32_SC_K: return KEY_K;
+ case KOS32_SC_L: return KEY_L;
+ case KOS32_SC_M: return KEY_M;
+ case KOS32_SC_N: return KEY_N;
+ case KOS32_SC_O: return KEY_O;
+ case KOS32_SC_P: return KEY_P;
+ case KOS32_SC_Q: return KEY_Q;
+ case KOS32_SC_R: return KEY_R;
+ case KOS32_SC_S: return KEY_S;
+ case KOS32_SC_T: return KEY_T;
+ case KOS32_SC_U: return KEY_U;
+ case KOS32_SC_V: return KEY_V;
+ case KOS32_SC_W: return KEY_W;
+ case KOS32_SC_X: return KEY_X;
+ case KOS32_SC_Y: return KEY_Y;
+ case KOS32_SC_Z: return KEY_Z;
+ case KOS32_SC_RETURN: return KEY_RETURN;
+ case KOS32_SC_ESCAPE: return KEY_ESCAPE;
+ case KOS32_SC_BACKSPACE: return KEY_BACKSPACE;
+ case KOS32_SC_TAB: return KEY_TAB;
+ case KOS32_SC_SPACE: return KEY_SPACE;
+ case KOS32_SC_MINUS: return KEY_MINUS;
+ case KOS32_SC_EQUALS: return KEY_EQUALS;
+ case KOS32_SC_LEFTBRACKET: return KEY_LEFTBRACKET;
+ case KOS32_SC_RIGHTBRACKET: return KEY_RIGHTBRACKET;
+ case KOS32_SC_BACKSLASH: return KEY_BACKSLASH;
+ case KOS32_SC_SEMICOLON: return KEY_SEMICOLON;
+ case KOS32_SC_APOSTROPHE: return KEY_APOSTROPHE;
+ case KOS32_SC_GRAVE: return KEY_GRAVE;
+ case KOS32_SC_COMMA: return KEY_COMMA;
+ case KOS32_SC_PERIOD: return KEY_PERIOD;
+ case KOS32_SC_SLASH: return KEY_SLASH;
+ case KOS32_SC_CAPSLOCK: return KEY_CAPSLOCK;
+ case KOS32_SC_F1: return KEY_F1;
+ case KOS32_SC_F2: return KEY_F2;
+ case KOS32_SC_F3: return KEY_F3;
+ case KOS32_SC_F4: return KEY_F4;
+ case KOS32_SC_F5: return KEY_F5;
+ case KOS32_SC_F6: return KEY_F6;
+ case KOS32_SC_F7: return KEY_F7;
+ case KOS32_SC_F8: return KEY_F8;
+ case KOS32_SC_F9: return KEY_F9;
+ case KOS32_SC_F10: return KEY_F10;
+ case KOS32_SC_F11: return KEY_F11;
+ case KOS32_SC_F12: return KEY_F12;
+ case KOS32_SC_SCROLLLOCK: return KEY_SCROLLLOCK;
+ case KOS32_SC_NUMLOCK: return KEY_NUMLOCK;
+ case KOS32_SC_KP_MULTIPLY: return KEY_KP_MULTIPLY;
+ case KOS32_SC_KP_MINUS: return KEY_KP_MINUS;
+ case KOS32_SC_KP_PLUS: return KEY_KP_PLUS;
+ case KOS32_SC_KP_0: return KEY_KP_0;
+ case KOS32_SC_KP_1: return KEY_KP_1;
+ case KOS32_SC_KP_2: return KEY_KP_2;
+ case KOS32_SC_KP_3: return KEY_KP_3;
+ case KOS32_SC_KP_4: return KEY_KP_4;
+ case KOS32_SC_KP_5: return KEY_KP_5;
+ case KOS32_SC_KP_6: return KEY_KP_6;
+ case KOS32_SC_KP_7: return KEY_KP_7;
+ case KOS32_SC_KP_8: return KEY_KP_8;
+ case KOS32_SC_KP_9: return KEY_KP_9;
+ case KOS32_SC_KP_PERIOD: return KEY_KP_PERIOD;
+ case KOS32_SC_LCTRL: return KEY_LCTRL;
+ case KOS32_SC_LSHIFT: return KEY_LSHIFT;
+ case KOS32_SC_LALT: return KEY_LALT;
+ default: return KEY_UNKNOWN;
+ }
+}
+
+static int ext_scancode_to_key (int scancode) {
+ switch (scancode) {
+ case KOS32_SC_INSERT: return KEY_INSERT;
+ case KOS32_SC_HOME: return KEY_HOME;
+ case KOS32_SC_PAGEUP: return KEY_PAGEUP;
+ case KOS32_SC_DELETE: return KEY_DELETE;
+ case KOS32_SC_END: return KEY_END;
+ case KOS32_SC_PAGEDOWN: return KEY_PAGEDOWN;
+ case KOS32_SC_RIGHT: return KEY_RIGHT;
+ case KOS32_SC_LEFT: return KEY_LEFT;
+ case KOS32_SC_DOWN: return KEY_DOWN;
+ case KOS32_SC_UP: return KEY_UP;
+ case KOS32_SC_KP_DIVIDE: return KEY_KP_DIVIDE;
+ case KOS32_SC_KP_ENTER: return KEY_KP_ENTER;
+ case KOS32_SC_LSUPER: return KEY_LSUPER;
+ case KOS32_SC_RCTRL: return KEY_RCTRL;
+ case KOS32_SC_RSHIFT: return KEY_RSHIFT;
+ case KOS32_SC_RALT: return KEY_RALT;
+ case KOS32_SC_RSUPER: return KEY_RSUPER;
+ default: return KEY_UNKNOWN;
+ }
+}
+
+static void handle_scancode (int code) {
+ static enum {
+ ST_std, ST_ext,
+ ST_print_down_1, ST_print_down_2,
+ ST_print_up_1, ST_print_up_2,
+ ST_pause_1, ST_pause_2, ST_pause_3, ST_pause_4, ST_pause_5,
+ ST_ok
+ } state = ST_std;
+ int k, down;
+ // logo("scancode >> 0x%x\n", code);
+ switch (state) {
+ case ST_std:
+ if (code == KOS32_SC_EXTENDED) {
+ state = ST_ext;
+ } else if (code == KOS32_SC_EXTENDED_PAUSE) {
+ state = ST_pause_1;
+ } else {
+ state = ST_ok;
+ k = scancode_to_key(code & 0x7f);
+ down = !((code >> 7) & 1);
+ }
+ break;
+ case ST_ext:
+ if (code == 0x2A) {
+ state = ST_print_down_1;
+ } else if (code == 0xB7) {
+ state = ST_print_up_1;
+ } else {
+ state = ST_ok;
+ k = ext_scancode_to_key(code & 0x7f);
+ down = !((code >> 7) & 1);
+ }
+ break;
+ case ST_print_down_1:
+ assert(code == 0xE0);
+ state = ST_print_down_2;
+ break;
+ case ST_print_down_2:
+ assert(code == 0x37);
+ state = ST_ok;
+ k = KEY_PRINTSCREEN;
+ down = 1;
+ break;
+ case ST_print_up_1:
+ assert(code == 0xE0);
+ state = ST_print_up_2;
+ break;
+ case ST_print_up_2:
+ assert(code == 0xAA);
+ state = ST_ok;
+ k = KEY_PRINTSCREEN;
+ down = 0;
+ break;
+ case ST_pause_1:
+ assert(code == 0x1D);
+ state = ST_pause_2;
+ break;
+ case ST_pause_2:
+ assert(code == 0x45);
+ state = ST_pause_3;
+ break;
+ case ST_pause_3:
+ assert(code == 0xE1);
+ state = ST_pause_4;
+ break;
+ case ST_pause_4:
+ assert(code == 0x9D);
+ state = ST_pause_5;
+ break;
+ case ST_pause_5:
+ assert(code == 0xC5);
+ state = ST_ok;
+ k = KEY_PAUSE;
+ down = 1;
+ break;
+ default:
+ ERR_fatal("handle_scancode: invalid state: %i\n", state);
+ }
+ if (state == ST_ok) {
+ state = ST_std;
+ // logo("key: %s (%i, %s)\n", I_key_to_string(k), k, down ? "down" : "up");
+ I_press(k, down);
+ GM_key(k, down);
+ if (k = KEY_PAUSE) {
+ I_press(k, 0);
+ GM_key(k, 0);
+ }
+ }
+}
+
+static void poll_events (void) {
+ int ev, key, button, code, ch, k;
+ while(!!(ev = CheckEvent())) {
+ switch (ev) {
+ case KOS32_EVENT_REDRAW:
+ return; /* force redraw */
+ case KOS32_EVENT_KEYBOARD:
+ key = GetKey();
+ if ((key & 0xff) == 0) {
+ switch (GetInputMode()) {
+ case KOS32_INPUT_MODE_ASCII:
+ ch = (key >> 8) & 0xff;
+ code = (key >> 16) & 0x7f;
+ k = scancode_to_key(code);
+ I_press(k, 1);
+ GM_key(k, 1);
+ GM_input(ch);
+ I_press(k, 0);
+ GM_key(k, 0);
+ break;
+ case KOS32_INPUT_MODE_SCANCODE:
+ code = key >> 8;
+ handle_scancode(code);
+ break;
+ }
+ }
+ break;
+ case KOS32_EVENT_BUTTON:
+ button = GetButton();
+ quit = button == 256; /* close button + left click */
+ break;
+ default:
+ ERR_fatal("poll_events: unhandled event: %i\n", ev);
+ }
+ }
+}
+
+static void step (void) {
+ poll_events();
+ MUS_update();
+ long t = GetTimeCountPro(); /* ns */
+ if (t - ticks > DELAY * 1000000) {
+ ticks = t;
+ G_act();
+ }
+ R_draw();
+}
+
+int main (int argc, char **argv) {
+ char *pw;
+ CFG_args(argc, argv);
+ logo("system: initialize engine\n");
+ SetEventsMask(KOS32_EVENT_FLAG_REDRAW | KOS32_EVENT_FLAG_KEYBOARD | KOS32_EVENT_FLAG_BUTTON);
+ Y_disable_text_input();
+ // 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(GetIdleCount());
+ F_startup();
+ CFG_load();
+ pw = "doom2d.wad";
+ if (fexists(pw)) {
+ F_addwad(pw);
+ } else {
+ F_addwad("doom2d.wad");
+ }
+ F_initwads();
+ M_startup();
+ F_allocres();
+ S_init();
+ MUS_init();
+ R_init();
+ G_init();
+ ticks = GetTimeCountPro();
+ logo("system: game loop\n");
+ while (!quit) {
+ step();
+ }
+ logo("system: finalize engine\n");
+ CFG_save();
+ R_done();
+ MUS_done();
+ S_done();
+ M_shutdown();
+ logo("system: halt\n");
+ return 0;
+}