From: DeaDDooMER Date: Mon, 1 Feb 2021 23:56:44 +0000 (+0300) Subject: kos32: initial port for KolibriOS X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=6ab88bc4b9612cfb165981b3087bd0dea7ff24c4;p=flatwaifu.git kos32: initial port for KolibriOS --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d91997e..65b4196 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ option(SOUND_DRIVER "Build with selected sound driver" "OpenAL") 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) @@ -24,6 +25,7 @@ string(COMPARE EQUAL "${SOUND_DRIVER}" "STUB" WITH_STUBSOUND) 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) @@ -36,6 +38,7 @@ set(D2D_LIBCP866_ROOT ${D2D_GAME_ROOT}/libs/cp866) 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) @@ -78,8 +81,13 @@ elseif(WITH_SDL2) 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 new file mode 100755 index 0000000..92a8594 --- /dev/null +++ b/src/cmake/kos32-tcc.cmake @@ -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 new file mode 100644 index 0000000..9686f12 --- /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 new file mode 100644 index 0000000..3ccbb5b --- /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 . + */ + +#include "kos32.h" + +#include +#include +#include // srand exit +#include +#include +#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; +}