├── SRC ├── .clang-format ├── ID_VW_A.ASM ├── LZEXE │ └── LZEXE.EXE ├── DATA │ ├── BM1INTRO.OBJ │ └── INTROSCN.BM1 ├── MAKEFILE ├── GRAPHBM1.EQU ├── ID_ASM.EQU ├── ID_HEADS.H ├── AUDIOBM1.H ├── ID_MM.H ├── ID_US_A.ASM ├── ID_CA.H ├── ID_US.H ├── ID_RF.H ├── ID_SD.H ├── ID_IN.H ├── BM_DEMO.C ├── ID_VW.H ├── BM_MAIN.C ├── BM_DEF.H ├── BM_ACT.H ├── ID_RF_A.ASM ├── BM_GAME1.C ├── GRAPHBM1.H └── BM_TEXT.C ├── .gitignore ├── README.md └── COPYING /SRC/.clang-format: -------------------------------------------------------------------------------- 1 | DisableFormat: true 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.OBJ 2 | *.MAP 3 | *.EXE 4 | !SRC/DATA/*.OBJ 5 | !SRC/LZEXE/LZEXE.EXE 6 | -------------------------------------------------------------------------------- /SRC/ID_VW_A.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lethal-guitar/BioMenaceDecomp/HEAD/SRC/ID_VW_A.ASM -------------------------------------------------------------------------------- /SRC/LZEXE/LZEXE.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lethal-guitar/BioMenaceDecomp/HEAD/SRC/LZEXE/LZEXE.EXE -------------------------------------------------------------------------------- /SRC/DATA/BM1INTRO.OBJ: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lethal-guitar/BioMenaceDecomp/HEAD/SRC/DATA/BM1INTRO.OBJ -------------------------------------------------------------------------------- /SRC/DATA/INTROSCN.BM1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lethal-guitar/BioMenaceDecomp/HEAD/SRC/DATA/INTROSCN.BM1 -------------------------------------------------------------------------------- /SRC/MAKEFILE: -------------------------------------------------------------------------------- 1 | .autodepend 2 | 3 | !if !$d(BCROOT) 4 | BCROOT=C:\BCC_20 5 | !endif 6 | 7 | CC=$(BCROOT)\BIN\bcc 8 | TLINK=$(BCROOT)\BIN\tlink 9 | TASM=$(BCROOT)\BIN\tasm 10 | 11 | INCLUDEDIR=$(BCROOT)\INCLUDE 12 | LIBDIR=$(BCROOT)\LIB 13 | 14 | CFLAGS=-I$(INCLUDEDIR) -L$(LIBDIR) -1- -G -Z -k -mm -a- -f- -b 15 | LDFLAGS=/c /s /m /i /L$(BCROOT)\LIB 16 | 17 | OBJS=BM_MAIN.OBJ BM_TEXT.OBJ BM_DEMO.OBJ BM_GAME1.OBJ BM_GAME2.OBJ BM_GAME3.OBJ BM_STATE.OBJ BM_PLAY1.OBJ BM_PLAY2.OBJ BM_SPEC.OBJ BM_ACT1.OBJ BM_ACT2.OBJ BM_ACT3.OBJ ID_CA.OBJ ID_IN.OBJ ID_MM.OBJ ID_RF.OBJ ID_SD.OBJ ID_US_1.OBJ ID_US_2.OBJ ID_VW.OBJ ID_RF_A.OBJ ID_US_A.OBJ ID_VW_A.OBJ DATA\BM1INTRO.OBJ 18 | TARGET=BMENACE1.EXE 19 | 20 | 21 | all: $(TARGET) 22 | 23 | clean: 24 | @del *.exe 25 | @del *.map 26 | @del *.obj 27 | 28 | .asm.obj: 29 | $(TASM) /MX /ZI /O $. 30 | 31 | .c.obj: 32 | $(CC) $(CFLAGS) -c $. 33 | 34 | $(TARGET): $(OBJS) 35 | $(TLINK) $(LDFLAGS) C0M.OBJ @&&! 36 | $(OBJS), $(TARGET), , CM.LIB 37 | ! 38 | -------------------------------------------------------------------------------- /SRC/GRAPHBM1.EQU: -------------------------------------------------------------------------------- 1 | ;===================================== 2 | ; 3 | ; Graphics .EQU file for .BM1 4 | ; not IGRAB-ed :) 5 | ; 6 | ;===================================== 7 | 8 | ;INCLUDE "VERSION.EQU" 9 | 10 | ; 11 | ; Amount of each data item 12 | ; 13 | NUMFONT = 2 14 | NUMFONTM = 0 15 | NUMPICS = 50 16 | NUMPICM = 1 17 | NUMSPRITES = 355 18 | NUMTILE8 = 144 19 | NUMTILE8M = 36 20 | NUMTILE16 = 1512 21 | NUMTILE16M = 2682 22 | NUMTILE32 = 0 23 | NUMTILE32M = 0 24 | NUMEXTERN = 14 25 | 26 | 27 | ; 28 | ; File offsets for data items 29 | ; 30 | STRUCTPIC = 0 31 | STRUCTPICM = 1 32 | STRUCTSPRITE = 2 33 | 34 | STARTFONT = 3 35 | STARTFONTM = (STARTFONT+NUMFONT) 36 | STARTPICS = (STARTFONTM+NUMFONTM) 37 | STARTPICM = (STARTPICS+NUMPICS) 38 | STARTSPRITES = (STARTPICM+NUMPICM) 39 | STARTTILE8 = (STARTSPRITES+NUMSPRITES) 40 | STARTTILE8M = (STARTTILE8+1) 41 | STARTTILE16 = (STARTTILE8M+1) 42 | STARTTILE16M = (STARTTILE16+NUMTILE16) 43 | STARTTILE32 = (STARTTILE16M+NUMTILE16M) 44 | STARTTILE32M = (STARTTILE32+NUMTILE32) 45 | STARTEXTERN = (STARTTILE32M+NUMTILE32M) 46 | 47 | NUMCHUNKS = (STARTEXTERN+NUMEXTERN) 48 | 49 | ; 50 | ; Thank you for using IGRAB! 51 | ; 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BioMenace decompilation (WIP) 2 | 3 | This is a work in progress decompilation/source code reconstruction of the game BioMenace, 4 | released by Apogee Software in 1993 for MS-DOS. 5 | 6 | Based on [K1n9_Duk3's reconstruction of Commander Keen 4 source code](https://github.com/sparky4/keen4-6). 7 | BioMenace is based on the same engine and thus shares a lot of code with the 2nd Keen trilogy. 8 | It's far from identical though - almost all of the game logic is completely unique to this game, 9 | and many other parts of the code have also been modified. 10 | 11 | To my knowledge, this is the first publicly released code reconstruction of the game's first episode. In the meantime, K1n9_Duk3 has also released a code reconstruction which covers all 3 episodes and some extra versions: 12 | * [Announcement post](https://pckf.com/viewtopic.php?t=18039) 13 | * [Download](https://k1n9duk3.shikadi.net/files/modding/bmsource.zip) 14 | 15 | 16 | ## Current state 17 | 18 | This code produces a 100% identical binary to `BMENACE1.EXE` from the freeware release of the game (SHA-256 `b91ed9c1e8a7a47cff209401f50aa7bc2eca9b42738d7f6aa5e6b55ed35fae7a`). The shareware version v1.1 (SHA-256 `c47d1114263b8cf3f27b776c8a858b4f89dc59d1a2cccfdddffc194277adc008`) can also be perfectly reproduced. Episodes 2 and 3 are not currently covered. 19 | 20 | 21 | ## Compiling the code 22 | 23 | A copy of Borland C++ 2.0 is required, and a DOS environment to run it in (real or emulated). 24 | The compiler is expected to be installed at `C:\BCC_20` by default. 25 | The `BIN` subdirectory of the installation should be in the `PATH`. 26 | 27 | Within the DOS environment, `cd` into the directory containing the code and run `make`. 28 | This creates a file called `BMENACE1.EXE`, but it still needs to be compressed before it matches the original version. 29 | Run `LZEXE\LZEXE.EXE BMENACE1.EXE` to do so, and a perfectly matching file should be produced. 30 | 31 | To build the shareware version, uncomment the corresponding `#define` near the top of `ID_HEADS.H`, and comment out the `FREEWARE` `#define`. 32 | 33 | In order to play the game using an `EXE` built from this code, the game data from the original release is required - 34 | this repository doesn't contain any data files. 35 | -------------------------------------------------------------------------------- /SRC/ID_ASM.EQU: -------------------------------------------------------------------------------- 1 | ; 2 | ; Equates for all .ASM files 3 | ; 4 | 5 | ;---------------------------------------------------------------------------- 6 | 7 | INCLUDE "GRAPHBM1.EQU" 8 | 9 | ;---------------------------------------------------------------------------- 10 | 11 | CGAGR = 1 12 | EGAGR = 2 13 | VGAGR = 3 14 | 15 | GRMODE = EGAGR 16 | PROFILE = 0 ; 1=keep stats on tile drawing 17 | 18 | SC_INDEX = 03C4h 19 | SC_RESET = 0 20 | SC_CLOCK = 1 21 | SC_MAPMASK = 2 22 | SC_CHARMAP = 3 23 | SC_MEMMODE = 4 24 | 25 | CRTC_INDEX = 03D4h 26 | CRTC_H_TOTAL = 0 27 | CRTC_H_DISPEND = 1 28 | CRTC_H_BLANK = 2 29 | CRTC_H_ENDBLANK = 3 30 | CRTC_H_RETRACE = 4 31 | CRTC_H_ENDRETRACE = 5 32 | CRTC_V_TOTAL = 6 33 | CRTC_OVERFLOW = 7 34 | CRTC_ROWSCAN = 8 35 | CRTC_MAXSCANLINE = 9 36 | CRTC_CURSORSTART = 10 37 | CRTC_CURSOREND = 11 38 | CRTC_STARTHIGH = 12 39 | CRTC_STARTLOW = 13 40 | CRTC_CURSORHIGH = 14 41 | CRTC_CURSORLOW = 15 42 | CRTC_V_RETRACE = 16 43 | CRTC_V_ENDRETRACE = 17 44 | CRTC_V_DISPEND = 18 45 | CRTC_OFFSET = 19 46 | CRTC_UNDERLINE = 20 47 | CRTC_V_BLANK = 21 48 | CRTC_V_ENDBLANK = 22 49 | CRTC_MODE = 23 50 | CRTC_LINECOMPARE = 24 51 | 52 | 53 | GC_INDEX = 03CEh 54 | GC_SETRESET = 0 55 | GC_ENABLESETRESET = 1 56 | GC_COLORCOMPARE = 2 57 | GC_DATAROTATE = 3 58 | GC_READMAP = 4 59 | GC_MODE = 5 60 | GC_MISCELLANEOUS = 6 61 | GC_COLORDONTCARE = 7 62 | GC_BITMASK = 8 63 | 64 | ATR_INDEX = 03c0h 65 | ATR_MODE = 16 66 | ATR_OVERSCAN = 17 67 | ATR_COLORPLANEENABLE = 18 68 | ATR_PELPAN = 19 69 | ATR_COLORSELECT = 20 70 | 71 | STATUS_REGISTER_1 = 03dah 72 | 73 | 74 | MACRO WORDOUT 75 | out dx,ax 76 | ENDM 77 | 78 | if 0 79 | 80 | MACRO WORDOUT 81 | out dx,al 82 | inc dx 83 | xchg al,ah 84 | out dx,al 85 | dec dx 86 | xchg al,ah 87 | ENDM 88 | 89 | endif 90 | 91 | UPDATEWIDE = 22 92 | UPDATEHIGH = 14 93 | 94 | ; 95 | ; tile info offsets from segment tinf 96 | ; 97 | 98 | ANIM = 402 99 | SPEED = (ANIM+NUMTILE16) 100 | 101 | NORTHWALL = (SPEED+NUMTILE16) 102 | EASTWALL = (NORTHWALL+NUMTILE16M) 103 | SOUTHWALL = (EASTWALL+NUMTILE16M) 104 | WESTWALL = (SOUTHWALL+NUMTILE16M) 105 | MANIM = (WESTWALL+NUMTILE16M) 106 | INTILE = (MANIM+NUMTILE16M) 107 | MSPEED = (INTILE+NUMTILE16M) 108 | 109 | 110 | IFE GRMODE-EGAGR 111 | SCREENWIDTH = 64 112 | ENDIF 113 | IFE GRMODE-CGAGR 114 | SCREENWIDTH = 128 115 | ENDIF 116 | -------------------------------------------------------------------------------- /SRC/ID_HEADS.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // ID_GLOB.H 26 | 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #define __ID_GLOB__ 42 | 43 | //-------------------------------------------------------------------------- 44 | 45 | #define EXTENSION "BM1" 46 | 47 | #define FREEWARE 48 | //#define SHAREWARE 49 | 50 | extern char far introscn; 51 | 52 | #include "AUDIOBM1.H" 53 | #include "GRAPHBM1.H" 54 | 55 | //-------------------------------------------------------------------------- 56 | 57 | #define TEXTGR 0 58 | #define CGAGR 1 59 | #define EGAGR 2 60 | #define VGAGR 3 61 | 62 | #define GRMODE EGAGR 63 | 64 | #if GRMODE == EGAGR 65 | #define GREXT "EGA" 66 | #endif 67 | #if GRMODE == CGAGR 68 | #define GREXT "CGA" 69 | #endif 70 | 71 | //#define PROFILE 72 | 73 | // 74 | // ID Engine 75 | // Types.h - Generic types, #defines, etc. 76 | // v1.0d1 77 | // 78 | 79 | #ifndef __TYPES__ 80 | #define __TYPES__ 81 | 82 | typedef enum {false,true} boolean; 83 | typedef unsigned char byte; 84 | typedef unsigned int word; 85 | typedef unsigned long longword; 86 | typedef byte * Ptr; 87 | 88 | typedef struct 89 | { 90 | int x,y; 91 | } Point; 92 | typedef struct 93 | { 94 | Point ul,lr; 95 | } Rect; 96 | 97 | #define nil ((void *)0) 98 | 99 | #endif 100 | 101 | #include "ID_CA.H" 102 | #include "ID_IN.H" 103 | #include "ID_MM.H" 104 | #include "ID_RF.H" 105 | #include "ID_SD.H" 106 | #include "ID_US.H" 107 | #include "ID_VW.H" 108 | 109 | 110 | void Quit (char *error); // defined in user program 111 | 112 | -------------------------------------------------------------------------------- /SRC/AUDIOBM1.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef __AUDIO_H__ 22 | #define __AUDIO_H__ 23 | 24 | //#include "VERSION.H" 25 | 26 | ///////////////////////////////////////////////// 27 | // 28 | // MUSE Header for .BM1 29 | // 30 | ///////////////////////////////////////////////// 31 | 32 | #define NUMSOUNDS LASTSOUND 33 | #define NUMSNDCHUNKS ((3*LASTSOUND)+LASTMUSIC) 34 | 35 | // 36 | // Sound names & indexes 37 | // 38 | typedef enum { 39 | SND_ROBOTBOUNCE, 40 | SND_TAKEDAMAGE, 41 | SND_PLAYERSLUGJUMP, 42 | SND_CEILWALKERFALL, 43 | SND_CEILWALKERLAND, 44 | SND_PLAYERDIE, 45 | SND_TURRETSHOOT, 46 | SND_EXPLOSION, 47 | SND_SQUISH, 48 | SND_SNAKESPIT, 49 | SND_SLUGATTACK, 50 | SND_PLAYERJUMP, 51 | SND_PLAYERGUN, 52 | SND_RICOCHET, 53 | SND_COLLECTAMMO, 54 | SND_COLLECTKEY, 55 | SND_COLLECTONEUP, 56 | SND_USEKEYCARD, 57 | SND_NOKEY, 58 | SND_OPENDOOR, 59 | SND_USESWITCH, 60 | SND_LASERSHOT, 61 | SND_USESHARD, 62 | SND_ROAR, 63 | SND_DANGER, 64 | SND_BLEEPBLOOP, 65 | SND_SPECIALMOVE, 66 | SND_COLLECTBONUS, 67 | SND_COLLECTHEALTH, 68 | SND_ZING, 69 | SND_BOOM, 70 | SND_COLLECTPOTION, 71 | SND_32, 72 | SND_COLLECTVALUABLEITEM, 73 | SND_34, 74 | SND_CRUSHERMOVE, 75 | SND_FALLINGBLOCK, 76 | SND_BLOCKPUSHED, 77 | SND_SEWERMUTANTTHROW, 78 | SND_DROPSLIME, 79 | SND_BEACONACTIVE, 80 | SND_NAGTIMERTICK, 81 | LASTSOUND 82 | } soundnames; 83 | 84 | #if LASTSOUND != 42 85 | #error bad sound enum! 86 | #endif 87 | 88 | #define NOWAYSND SND_NOKEY 89 | 90 | // 91 | // Base offsets 92 | // 93 | #define STARTPCSOUNDS 0 94 | #define STARTADLIBSOUNDS (STARTPCSOUNDS+NUMSOUNDS) 95 | #define STARTDIGISOUNDS (STARTADLIBSOUNDS+NUMSOUNDS) 96 | #define STARTMUSIC (STARTDIGISOUNDS+NUMSOUNDS) 97 | 98 | // 99 | // Music names & indexes 100 | // 101 | typedef enum { 102 | CRUISING_MUS, 103 | WEASEL_MUS, 104 | BIOTHEME1_MUS, 105 | SNAKESAVE_MUS, 106 | DIRTYWATER_MUS, 107 | ROCKINIT_MUS, 108 | BAYOU_MUS, 109 | ROBOTY_MUS, 110 | PRISONER_MUS, 111 | DRSHOCK_MUS, 112 | CHASING_MUS, 113 | LIKEITWAS_MUS, 114 | FANFARE_MUS, 115 | SAVED_MUS, 116 | RESTING_MUS, 117 | CANTGET_MUS, 118 | NONVINCE_MUS, 119 | THECITY_MUS, 120 | LASTMUSIC = 18 121 | } musicnames; 122 | 123 | ///////////////////////////////////////////////// 124 | // 125 | // Thanks for playing with MUSE! 126 | // 127 | ///////////////////////////////////////////////// 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /SRC/ID_MM.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // ID_MM.H 26 | 27 | #ifndef __ID_CA__ 28 | 29 | #define __ID_CA__ 30 | 31 | #define SAVENEARHEAP 0x400 // space to leave in data segment 32 | #define SAVEFARHEAP 0 // space to leave in far heap 33 | 34 | #define BUFFERSIZE 0x1000 // miscelanious, allways available buffer 35 | 36 | #define MAXBLOCKS 1200 37 | 38 | 39 | //-------- 40 | 41 | #define EMS_INT 0x67 42 | 43 | #define EMS_STATUS 0x40 44 | #define EMS_GETFRAME 0x41 45 | #define EMS_GETPAGES 0x42 46 | #define EMS_ALLOCPAGES 0x43 47 | #define EMS_MAPPAGE 0x44 48 | #define EMS_FREEPAGES 0x45 49 | #define EMS_VERSION 0x46 50 | 51 | //-------- 52 | 53 | #define XMS_VERSION 0x00 54 | 55 | #define XMS_ALLOCHMA 0x01 56 | #define XMS_FREEHMA 0x02 57 | 58 | #define XMS_GENABLEA20 0x03 59 | #define XMS_GDISABLEA20 0x04 60 | #define XMS_LENABLEA20 0x05 61 | #define XMS_LDISABLEA20 0x06 62 | #define XMS_QUERYA20 0x07 63 | 64 | #define XMS_QUERYREE 0x08 65 | #define XMS_ALLOC 0x09 66 | #define XMS_FREE 0x0A 67 | #define XMS_MOVE 0x0B 68 | #define XMS_LOCK 0x0C 69 | #define XMS_UNLOCK 0x0D 70 | #define XMS_GETINFO 0x0E 71 | #define XMS_RESIZE 0x0F 72 | 73 | #define XMS_ALLOCUMB 0x10 74 | #define XMS_FREEUMB 0x11 75 | 76 | //========================================================================== 77 | 78 | typedef void _seg * memptr; 79 | 80 | typedef struct 81 | { 82 | long nearheap,farheap,EMSmem,XMSmem,mainmem; 83 | } mminfotype; 84 | 85 | //========================================================================== 86 | 87 | extern mminfotype mminfo; 88 | extern memptr bufferseg; 89 | extern boolean mmerror; 90 | 91 | extern void (* beforesort) (void); 92 | extern void (* aftersort) (void); 93 | 94 | //========================================================================== 95 | 96 | void MM_Startup (void); 97 | void MM_Shutdown (void); 98 | void MM_MapEMS (void); 99 | 100 | void MM_GetPtr (memptr *baseptr,unsigned long size); 101 | void MM_FreePtr (memptr *baseptr); 102 | 103 | void MM_SetPurge (memptr *baseptr, int purge); 104 | void MM_SetLock (memptr *baseptr, boolean locked); 105 | void MM_SortMem (void); 106 | 107 | void MM_ShowMemory (void); 108 | 109 | long MM_UnusedMemory (void); 110 | long MM_TotalFree (void); 111 | 112 | void MM_BombOnError (boolean bomb); 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /SRC/ID_US_A.ASM: -------------------------------------------------------------------------------- 1 | ; Catacomb 3-D Source Code 2 | ; Copyright (C) 1993-2014 Flat Rock Software 3 | ; 4 | ; This program is free software; you can redistribute it and/or modify 5 | ; it under the terms of the GNU General Public License as published by 6 | ; the Free Software Foundation; either version 2 of the License, or 7 | ; (at your option) any later version. 8 | ; 9 | ; This program is distributed in the hope that it will be useful, 10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ; GNU General Public License for more details. 13 | ; 14 | ; You should have received a copy of the GNU General Public License along 15 | ; with this program; if not, write to the Free Software Foundation, Inc., 16 | ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | 18 | IDEAL 19 | MODEL MEDIUM,C 20 | 21 | ; Assembly portion of the User Mgr. This is just John Carmack's table 22 | ; driven pseudo-random number generator, and we put it in the User Mgr 23 | ; because we couldn't figure out where it should go 24 | 25 | 26 | ;============================================================================ 27 | ; 28 | ; RANDOM ROUTINES 29 | ; 30 | ;============================================================================ 31 | 32 | FARDATA 33 | 34 | rndindex dw ? 35 | 36 | rndtable db 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 37 | db 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 38 | db 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 39 | db 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 40 | db 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 41 | db 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 42 | db 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 43 | db 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 44 | db 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 45 | db 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 46 | db 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 47 | db 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 48 | db 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 49 | db 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 50 | db 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 51 | db 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 52 | db 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 53 | db 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 54 | db 120, 163, 236, 249 55 | 56 | 57 | CODESEG 58 | 59 | LastRnd dw ? 60 | 61 | ;================================================= 62 | ; 63 | ; void US_InitRndT (boolean randomize) 64 | ; Init table based RND generator 65 | ; if randomize is false, the counter is set to 0 66 | ; 67 | ;================================================= 68 | 69 | PROC US_InitRndT randomize:word 70 | uses si,di 71 | public US_InitRndT 72 | 73 | mov ax,SEG rndtable 74 | mov es,ax 75 | mov ax,[randomize] 76 | or ax,ax 77 | jne @@timeit ;if randomize is true, really random 78 | 79 | mov dx,0 ;set to a definite value 80 | jmp @@setit 81 | 82 | @@timeit: 83 | mov ah,2ch 84 | int 21h ;GetSystemTime 85 | and dx,0ffh 86 | 87 | @@setit: 88 | mov [es:rndindex],dx 89 | ret 90 | 91 | ENDP 92 | 93 | ;================================================= 94 | ; 95 | ; int US_RndT (void) 96 | ; Return a random # between 0-255 97 | ; Exit : AX = value 98 | ; 99 | ;================================================= 100 | PROC US_RndT 101 | public US_RndT 102 | 103 | mov ax,SEG rndtable 104 | mov es,ax 105 | mov bx,[es:rndindex] 106 | inc bx 107 | and bx,0ffh 108 | mov [es:rndindex],bx 109 | mov al,[es:rndtable+BX] 110 | xor ah,ah 111 | 112 | ret 113 | 114 | ENDP 115 | 116 | END 117 | 118 | -------------------------------------------------------------------------------- /SRC/ID_CA.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // ID_CA.H 26 | 27 | #ifndef __TYPES__ 28 | #include "ID_TYPES.H" 29 | #endif 30 | 31 | #ifndef __ID_MM__ 32 | #include "ID_MM.H" 33 | #endif 34 | 35 | #ifndef __ID_GLOB__ 36 | #include "ID_GLOB.H" 37 | #endif 38 | 39 | #define __ID_CA__ 40 | 41 | //=========================================================================== 42 | 43 | //#define NOMAPS 44 | //#define NOGRAPHICS 45 | //#define NOAUDIO 46 | 47 | //#define MAPHEADERLINKED 48 | //#define GRHEADERLINKED 49 | //#define AUDIOHEADERLINKED 50 | 51 | #define NUMMAPS 30 52 | #define MAPPLANES 3 53 | 54 | // 55 | // tile info defines, as bytes after tinf the table starts 56 | // 57 | 58 | 59 | // 60 | // TILEINFO offsets 61 | // 62 | #define ANIM 402 63 | #define SPEED (ANIM+NUMTILE16) 64 | 65 | // 66 | // TILEINFOM offsets 67 | // 68 | #define NORTHWALL (SPEED+NUMTILE16) 69 | #define EASTWALL (NORTHWALL+NUMTILE16M) 70 | #define SOUTHWALL (EASTWALL+NUMTILE16M) 71 | #define WESTWALL (SOUTHWALL+NUMTILE16M) 72 | #define MANIM (WESTWALL+NUMTILE16M) 73 | #define INTILE (MANIM+NUMTILE16M) 74 | #define MSPEED (INTILE+NUMTILE16M) 75 | 76 | //=========================================================================== 77 | 78 | typedef struct 79 | { 80 | long planestart[3]; 81 | unsigned planelength[3]; 82 | unsigned width,height; 83 | char name[16]; 84 | } maptype; 85 | 86 | //=========================================================================== 87 | 88 | extern byte _seg *tinf; 89 | extern int mapon; 90 | 91 | extern unsigned _seg *mapsegs[3]; 92 | extern maptype _seg *mapheaderseg[NUMMAPS]; 93 | extern byte _seg *audiosegs[NUMSNDCHUNKS]; 94 | extern void _seg *grsegs[]; 95 | 96 | extern byte far grneeded[]; 97 | extern byte ca_levelbit,ca_levelnum; 98 | 99 | extern char *titleptr[8]; 100 | 101 | extern int profilehandle,debughandle; 102 | 103 | // 104 | // hooks for custom cache dialogs 105 | // 106 | extern void (*drawcachebox) (char *title, unsigned numcache); 107 | extern void (*updatecachebox) (void); 108 | extern void (*finishcachebox) (void); 109 | 110 | //=========================================================================== 111 | 112 | // just for the score box reshifting 113 | 114 | void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest, 115 | unsigned width, unsigned height, unsigned pixshift); 116 | 117 | //=========================================================================== 118 | 119 | void CA_OpenDebug (void); 120 | void CA_CloseDebug (void); 121 | boolean CA_FarRead (int handle, byte far *dest, long length); 122 | boolean CA_FarWrite (int handle, byte far *source, long length); 123 | boolean CA_ReadFile (char *filename, memptr *ptr); 124 | boolean CA_LoadFile (char *filename, memptr *ptr); 125 | 126 | long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest, 127 | unsigned rlewtag); 128 | 129 | void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length, 130 | unsigned rlewtag); 131 | 132 | void CA_Startup (void); 133 | void CA_Shutdown (void); 134 | 135 | void CA_CacheAudioChunk (int chunk); 136 | void CA_LoadAllSounds (void); 137 | 138 | void CA_UpLevel (void); 139 | void CA_DownLevel (void); 140 | 141 | void CA_SetAllPurge (void); 142 | 143 | void CA_ClearMarks (void); 144 | void CA_ClearAllMarks (void); 145 | 146 | #define CA_MarkGrChunk(chunk) grneeded[chunk]|=ca_levelbit 147 | 148 | void CA_CacheGrChunk (int chunk); 149 | void CA_CacheMap (int mapnum); 150 | 151 | void CA_CacheMarks (char *title); 152 | 153 | -------------------------------------------------------------------------------- /SRC/ID_US.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // 26 | // ID Engine 27 | // ID_US.h - Header file for the User Manager 28 | // v1.0d1 29 | // By Jason Blochowiak 30 | // 31 | 32 | #ifndef __TYPES__ 33 | #include "ID_Types.h" 34 | #endif 35 | 36 | #ifndef __ID_US__ 37 | #define __ID_US__ 38 | 39 | #ifdef __DEBUG__ 40 | #define __DEBUG_UserMgr__ 41 | #endif 42 | 43 | //#define HELPTEXTLINKED 44 | 45 | #define MaxX 320 46 | #define MaxY 200 47 | 48 | #define MaxHelpLines 500 49 | 50 | #define MaxHighName 57 51 | #define MaxScores 8 52 | 53 | typedef struct 54 | { 55 | char name[MaxHighName + 1]; 56 | long score; 57 | word completed; 58 | } HighScore; 59 | 60 | #define MaxGameName 32 61 | #define MaxSaveGames 6 62 | typedef struct 63 | { 64 | char signature[4]; 65 | word *oldtest; 66 | boolean present; 67 | char name[MaxGameName + 1]; 68 | } SaveGame; 69 | 70 | #define MaxString 128 // Maximum input string size 71 | 72 | typedef struct 73 | { 74 | int x,y, 75 | w,h, 76 | px,py; 77 | } WindowRec; // Record used to save & restore screen windows 78 | 79 | typedef enum 80 | { 81 | gd_Continue, 82 | gd_Easy, 83 | gd_Normal, 84 | gd_Hard 85 | } GameDiff; 86 | 87 | // Hack import for TED launch support 88 | extern boolean tedlevel; 89 | extern word tedlevelnum; 90 | extern void TEDDeath(void); 91 | 92 | extern boolean ingame, // Set by game code if a game is in progress 93 | abortgame, // Set if a game load failed 94 | loadedgame, // Set if the current game was loaded 95 | NoWait, 96 | HighScoresDirty; 97 | extern char *abortprogram; // Set to error msg if program is dying 98 | extern boolean wantspractice; 99 | extern GameDiff restartgame; // Normally gd_Continue, else starts game 100 | extern word PrintX,PrintY; // Current printing location in the window 101 | extern word WindowX,WindowY,// Current location of window 102 | WindowW,WindowH;// Current size of window 103 | 104 | extern boolean Button0,Button1, 105 | CursorBad; 106 | extern ScanCode firescan; 107 | extern int CursorX,CursorY; 108 | 109 | extern void (*USL_MeasureString)(char far *,word *,word *), 110 | (*USL_DrawString)(char far *); 111 | 112 | extern boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int); 113 | extern void (*USL_ResetGame)(void); 114 | extern SaveGame Games[MaxSaveGames]; 115 | extern HighScore Scores[]; 116 | 117 | #define US_HomeWindow() {PrintX = WindowX; PrintY = WindowY;} 118 | 119 | extern void US_Startup(void), 120 | US_Setup(void), 121 | US_Shutdown(void), 122 | US_InitRndT(boolean randomize), 123 | US_SetLoadSaveHooks(boolean (*load)(int), 124 | boolean (*save)(int), 125 | void (*reset)(void)), 126 | US_TextScreen(void), 127 | US_UpdateTextScreen(void), 128 | US_FinishTextScreen(void), 129 | US_ControlPanel(int unkown), 130 | US_DrawWindow(word x,word y,word w,word h), 131 | US_CenterWindow(word,word), 132 | US_SaveWindow(WindowRec *win), 133 | US_RestoreWindow(WindowRec *win), 134 | US_ClearWindow(void), 135 | US_SetPrintRoutines(void (*measure)(char far *,word *,word *), 136 | void (*print)(char far *)), 137 | US_PrintCentered(char *s), 138 | US_CPrint(char far *s), 139 | US_CPrintLine(char *s), 140 | US_Print(char *s), 141 | US_PrintUnsigned(longword n), 142 | US_PrintSigned(long n), 143 | US_StartCursor(void), 144 | US_ShutCursor(void), 145 | US_CheckHighScore(long score,word other), 146 | US_DisplayHighScores(int which); 147 | extern boolean US_UpdateCursor(void), 148 | US_LineInput(int x,int y,char *buf,char *def,boolean escok, 149 | int maxchars,int maxwidth); 150 | extern int US_CheckParm(char *parm,char **strings), 151 | US_RndT(void); 152 | 153 | extern boolean US_ParmPresent(char *arg); 154 | 155 | void USL_PrintInCenter(char *s,Rect r); 156 | char *USL_GiveSaveName(word game); 157 | #endif 158 | -------------------------------------------------------------------------------- /SRC/ID_RF.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // ID_RF.H 26 | 27 | #define __ID_RF__ 28 | 29 | #ifndef __ID_MM__ 30 | #include "ID_MM.H" 31 | #endif 32 | 33 | /* 34 | ============================================================================= 35 | 36 | CONSTANTS 37 | 38 | ============================================================================= 39 | */ 40 | 41 | #define MINTICS 2 42 | #define MAXTICS 5 43 | #define DEMOTICS 3 44 | 45 | #define MAPBORDER 2 // map border must be at least 1 46 | 47 | #define MAXSPRITES 60 // max tracked sprites 48 | #define MAXANIMTILES 90 // max animating tiles on screen 49 | #define MAXANIMTYPES 62 // max different unique anim tiles on map 50 | 51 | #define MAXMAPHEIGHT 250 52 | 53 | #define PRIORITIES 4 54 | #define MASKEDTILEPRIORITY 3 // planes go: 0,1,2,MTILES,3 55 | 56 | #define TILEGLOBAL 256 57 | #define PIXGLOBAL 16 58 | 59 | #define G_T_SHIFT 8 // global >> ?? = tile 60 | #define G_P_SHIFT 4 // global >> ?? = pixels 61 | #define P_T_SHIFT 4 // pixels >> ?? = tile 62 | 63 | #define PORTTILESWIDE 21 // all drawing takes place inside a 64 | #define PORTTILESHIGH 14 // non displayed port of this size 65 | 66 | //#define PORTGLOBALWIDE (21*TILEGLOBAL) 67 | //#define PORTGLOBALHIGH (14*TILEGLOBAL) 68 | 69 | #define UPDATEWIDE (PORTTILESWIDE+1) 70 | #define UPDATEHIGH PORTTILESHIGH 71 | 72 | 73 | //=========================================================================== 74 | 75 | typedef enum {spritedraw,maskdraw} drawtype; 76 | 77 | /* 78 | ============================================================================= 79 | 80 | PUBLIC VARIABLES 81 | 82 | ============================================================================= 83 | */ 84 | 85 | 86 | extern boolean compatability; // crippled refresh for wierdo SVGAs 87 | 88 | extern unsigned tics; 89 | extern long lasttimecount; 90 | 91 | extern unsigned originxglobal,originyglobal; 92 | extern unsigned originxtile,originytile; 93 | extern unsigned originxscreen,originyscreen; 94 | 95 | extern unsigned mapwidth,mapheight,mapbyteswide,mapwordswide 96 | ,mapbytesextra,mapwordsextra; 97 | extern unsigned mapbwidthtable[MAXMAPHEIGHT]; 98 | 99 | extern unsigned originxmin,originxmax,originymin,originymax; 100 | 101 | extern unsigned masterofs; 102 | 103 | // 104 | // the floating update window is also used by the view manager for 105 | // double buffer tracking 106 | // 107 | 108 | extern byte *updateptr; // current start of update window 109 | 110 | #if GRMODE == CGAGR 111 | extern byte *baseupdateptr; 112 | #endif 113 | 114 | extern unsigned blockstarts[UPDATEWIDE*UPDATEHIGH]; 115 | extern unsigned updatemapofs[UPDATEWIDE*UPDATEHIGH]; 116 | extern unsigned uwidthtable[UPDATEHIGH]; // lookup instead of multiple 117 | 118 | #define UPDATETERMINATE 0x0301 119 | 120 | /* 121 | ============================================================================= 122 | 123 | PUBLIC FUNCTIONS 124 | 125 | ============================================================================= 126 | */ 127 | 128 | void RF_Startup (void); 129 | void RF_Shutdown (void); 130 | 131 | void RF_FixOfs (void); 132 | void RF_NewMap (void); 133 | void RF_MarkTileGraphics (void); 134 | void RF_SetScrollBlock (int x, int y, boolean horizontal); 135 | void RF_NewPosition (unsigned x, unsigned y); 136 | void RF_Scroll (int x, int y); 137 | 138 | void RF_MapToMap (unsigned srcx, unsigned srcy, 139 | unsigned destx, unsigned desty, 140 | unsigned width, unsigned height); 141 | void RF_MemToMap (unsigned far *source, unsigned plane, 142 | unsigned destx, unsigned desty, 143 | unsigned width, unsigned height); 144 | 145 | void RF_ClearBlock (int x, int y, int width, int height); 146 | void RF_RedrawBlock (int x, int y, int width, int height); 147 | 148 | void RF_PlaceSprite (void **user,unsigned globalx,unsigned globaly, 149 | unsigned spritenumber, drawtype draw, int priority); 150 | void RF_RemoveSprite (void **user); 151 | 152 | void RF_CalcTics (void); 153 | 154 | void RF_Refresh (void); 155 | void RF_ForceRefresh (void); 156 | void RF_SetRefreshHook (void (*func) (void) ); 157 | 158 | unsigned RF_FindFreeBuffer (void); 159 | 160 | -------------------------------------------------------------------------------- /SRC/ID_SD.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // 26 | // ID Engine 27 | // ID_SD.h - Sound Manager Header 28 | // v1.0d1 29 | // By Jason Blochowiak 30 | // 31 | 32 | #ifndef __TYPES__ 33 | #include "ID_Types.h" 34 | #endif 35 | 36 | #ifndef __ID_SD__ 37 | #define __ID_SD__ 38 | 39 | #ifdef __DEBUG__ 40 | #define __DEBUG_SoundMgr__ 41 | #endif 42 | 43 | #define TickBase 70 // 70Hz per tick - used as a base for timer 0 44 | 45 | typedef enum { 46 | sdm_Off, 47 | sdm_PC,sdm_AdLib, 48 | } SDMode; 49 | typedef enum { 50 | smm_Off,smm_AdLib 51 | } SMMode; 52 | 53 | typedef struct 54 | { 55 | longword length; 56 | word priority; 57 | } SoundCommon; 58 | 59 | // PC Sound stuff 60 | #define pcTimer 0x42 61 | #define pcTAccess 0x43 62 | #define pcSpeaker 0x61 63 | 64 | #define pcSpkBits 3 65 | 66 | typedef struct 67 | { 68 | SoundCommon common; 69 | byte data[1]; 70 | } PCSound; 71 | 72 | // Registers for the Sound Blaster card - needs to be offset by n0 73 | #define sbReset 0x206 74 | #define sbReadData 0x20a 75 | #define sbWriteCmd 0x20c 76 | #define sbWriteData 0x20c 77 | #define sbWriteStat 0x20c 78 | #define sbDataAvail 0x20e 79 | 80 | typedef struct 81 | { 82 | SoundCommon common; 83 | word hertz; 84 | byte bits, 85 | reference, 86 | data[1]; 87 | } SampledSound; 88 | 89 | // Registers for the AdLib card 90 | // Operator stuff 91 | #define alChar 0x20 92 | #define alScale 0x40 93 | #define alAttack 0x60 94 | #define alSus 0x80 95 | #define alWave 0xe0 96 | // Channel stuff 97 | #define alFreqL 0xa0 98 | #define alFreqH 0xb0 99 | #define alFeedCon 0xc0 100 | // Global stuff 101 | #define alEffects 0xbd 102 | 103 | typedef struct 104 | { 105 | byte mChar,cChar, 106 | mScale,cScale, 107 | mAttack,cAttack, 108 | mSus,cSus, 109 | mWave,cWave, 110 | nConn, 111 | 112 | // These are only for Muse - these bytes are really unused 113 | voice, 114 | mode, 115 | unused[3]; 116 | } Instrument; 117 | 118 | typedef struct 119 | { 120 | SoundCommon common; 121 | Instrument inst; 122 | byte block, 123 | data[1]; 124 | } AdLibSound; 125 | 126 | // 127 | // Sequencing stuff 128 | // 129 | #define sqMaxTracks 10 130 | #define sqMaxMoods 1 // DEBUG 131 | 132 | #define sev_Null 0 // Does nothing 133 | #define sev_NoteOff 1 // Turns a note off 134 | #define sev_NoteOn 2 // Turns a note on 135 | #define sev_NotePitch 3 // Sets the pitch of a currently playing note 136 | #define sev_NewInst 4 // Installs a new instrument 137 | #define sev_NewPerc 5 // Installs a new percussive instrument 138 | #define sev_PercOn 6 // Turns a percussive note on 139 | #define sev_PercOff 7 // Turns a percussive note off 140 | #define sev_SeqEnd -1 // Terminates a sequence 141 | 142 | // Flags for MusicGroup.flags 143 | #define sf_Melodic 0 144 | #define sf_Percussive 1 145 | 146 | #if 1 147 | typedef struct 148 | { 149 | word length, 150 | values[1]; 151 | } MusicGroup; 152 | #else 153 | typedef struct 154 | { 155 | word flags, 156 | count, 157 | offsets[1]; 158 | } MusicGroup; 159 | #endif 160 | 161 | typedef struct 162 | { 163 | /* This part needs to be set up by the user */ 164 | word mood,far *moods[sqMaxMoods]; 165 | 166 | /* The rest is set up by the code */ 167 | Instrument inst; 168 | boolean percussive; 169 | word far *seq; 170 | longword nextevent; 171 | } ActiveTrack; 172 | 173 | #define sqmode_Normal 0 174 | #define sqmode_FadeIn 1 175 | #define sqmode_FadeOut 2 176 | 177 | #define sqMaxFade 64 // DEBUG 178 | 179 | 180 | // Global variables 181 | extern boolean AdLibPresent, 182 | NeedsMusic, // For Caching Mgr 183 | QuietFX; 184 | extern SDMode SoundMode; 185 | extern SMMode MusicMode; 186 | extern longword TimeCount; // Global time in ticks 187 | 188 | // Function prototypes 189 | extern void SD_Startup(void), 190 | SD_Shutdown(void), 191 | SD_Default(boolean gotit,SDMode sd,SMMode sm), 192 | SD_PlaySound(soundnames sound), 193 | SD_StopSound(void), 194 | SD_WaitSoundDone(void), 195 | SD_StartMusic(MusicGroup far *music), 196 | SD_MusicOn(void), 197 | SD_MusicOff(void), 198 | SD_FadeOutMusic(void), 199 | SD_SetUserHook(void (*hook)(void)); 200 | extern boolean SD_MusicPlaying(void), 201 | SD_SetSoundMode(SDMode mode), 202 | SD_SetMusicMode(SMMode mode); 203 | extern word SD_SoundPlaying(void); 204 | 205 | #ifdef _MUSE_ // MUSE Goes directly to the lower level routines 206 | extern void SDL_PCPlaySound(PCSound far *sound), 207 | SDL_PCStopSound(void), 208 | SDL_ALPlaySound(AdLibSound far *sound), 209 | SDL_ALStopSound(void); 210 | #endif 211 | 212 | #endif 213 | -------------------------------------------------------------------------------- /SRC/ID_IN.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // 26 | // ID Engine 27 | // ID_IN.h - Header file for Input Manager 28 | // v1.0d1 29 | // By Jason Blochowiak 30 | // 31 | 32 | #ifndef __TYPES__ 33 | #include "ID_Types.h" 34 | #endif 35 | 36 | #ifndef __ID_IN__ 37 | #define __ID_IN__ 38 | 39 | #ifdef __DEBUG__ 40 | #define __DEBUG_InputMgr__ 41 | #endif 42 | 43 | #define MaxPlayers 4 44 | #define MaxKbds 2 45 | #define MaxJoys 2 46 | #define NumCodes 128 47 | 48 | typedef byte ScanCode; 49 | #define sc_None 0 50 | #define sc_Bad 0xff 51 | #define sc_Return 0x1c 52 | #define sc_Enter sc_Return 53 | #define sc_Escape 0x01 54 | #define sc_Space 0x39 55 | #define sc_BackSpace 0x0e 56 | #define sc_Tab 0x0f 57 | #define sc_Alt 0x38 58 | #define sc_Control 0x1d 59 | #define sc_CapsLock 0x3a 60 | #define sc_ 61 | #define sc_LShift 0x2a 62 | #define sc_RShift 0x36 63 | #define sc_UpArrow 0x48 64 | #define sc_DownArrow 0x50 65 | #define sc_LeftArrow 0x4b 66 | #define sc_RightArrow 0x4d 67 | #define sc_Insert 0x52 68 | #define sc_Delete 0x53 69 | #define sc_Home 0x47 70 | #define sc_End 0x4f 71 | #define sc_PgUp 0x49 72 | #define sc_PgDn 0x51 73 | #define sc_F1 0x3b 74 | #define sc_F2 0x3c 75 | #define sc_F3 0x3d 76 | #define sc_F4 0x3e 77 | #define sc_F5 0x3f 78 | #define sc_F6 0x40 79 | #define sc_F7 0x41 80 | #define sc_F8 0x42 81 | #define sc_F9 0x43 82 | #define sc_F10 0x44 83 | #define sc_F11 0x57 84 | #define sc_F12 0x59 // BUG: F12 uses scan code 0x58! 85 | 86 | #define sc_A 0x1e 87 | #define sc_B 0x30 88 | #define sc_C 0x2e 89 | #define sc_D 0x20 90 | #define sc_E 0x12 91 | #define sc_F 0x21 92 | #define sc_G 0x22 93 | #define sc_H 0x23 94 | #define sc_I 0x17 95 | #define sc_J 0x24 96 | #define sc_K 0x25 97 | #define sc_L 0x26 98 | #define sc_M 0x32 99 | #define sc_N 0x31 100 | #define sc_O 0x18 101 | #define sc_P 0x19 102 | #define sc_Q 0x10 103 | #define sc_R 0x13 104 | #define sc_S 0x1f 105 | #define sc_T 0x14 106 | #define sc_U 0x16 107 | #define sc_V 0x2f 108 | #define sc_W 0x11 109 | #define sc_X 0x2d 110 | #define sc_Y 0x15 111 | #define sc_Z 0x2c 112 | 113 | #define sc_1 0x02 114 | #define sc_2 0x03 115 | #define sc_3 0x04 116 | #define sc_4 0x05 117 | #define sc_5 0x06 118 | #define sc_6 0x07 119 | #define sc_7 0x08 120 | #define sc_8 0x09 121 | #define sc_9 0x0a 122 | #define sc_0 0x0b 123 | 124 | #define key_None 0 125 | #define key_Return 0x0d 126 | #define key_Enter key_Return 127 | #define key_Escape 0x1b 128 | #define key_Space 0x20 129 | #define key_BackSpace 0x08 130 | #define key_Tab 0x09 131 | #define key_Delete 0x7f 132 | 133 | // Stuff for the mouse 134 | #define MReset 0 135 | #define MButtons 3 136 | #define MDelta 11 137 | 138 | #define MouseInt 0x33 139 | #define Mouse(x) _AX = x,geninterrupt(MouseInt) 140 | 141 | typedef enum { 142 | demo_Off,demo_Record,demo_Playback,demo_PlayDone 143 | } Demo; 144 | typedef enum { 145 | ctrl_Keyboard, 146 | ctrl_Keyboard1 = ctrl_Keyboard,ctrl_Keyboard2, 147 | ctrl_Joystick, 148 | ctrl_Joystick1 = ctrl_Joystick,ctrl_Joystick2, 149 | ctrl_Mouse 150 | } ControlType; 151 | typedef enum { 152 | motion_Left = -1,motion_Up = -1, 153 | motion_None = 0, 154 | motion_Right = 1,motion_Down = 1 155 | } Motion; 156 | typedef enum { 157 | dir_North,dir_NorthEast, 158 | dir_East,dir_SouthEast, 159 | dir_South,dir_SouthWest, 160 | dir_West,dir_NorthWest, 161 | dir_None 162 | } Direction; 163 | typedef enum { 164 | ga_Jump, 165 | ga_Pogo, 166 | ga_Fire, 167 | ga_Status 168 | } GravisAType; 169 | typedef struct { 170 | boolean button0,button1; 171 | int x,y; 172 | Motion xaxis,yaxis; 173 | Direction dir; 174 | } CursorInfo; 175 | typedef CursorInfo ControlInfo; 176 | typedef struct { 177 | ScanCode button0,button1, 178 | upleft, up, upright, 179 | left, right, 180 | downleft, down, downright; 181 | } KeyboardDef; 182 | typedef struct { 183 | word joyMinX,joyMinY, 184 | threshMinX,threshMinY, 185 | threshMaxX,threshMaxY, 186 | joyMaxX,joyMaxY, 187 | joyMultXL,joyMultYL, 188 | joyMultXH,joyMultYH; 189 | } JoystickDef; 190 | // Global variables 191 | extern boolean Keyboard[], 192 | MousePresent, 193 | JoysPresent[]; 194 | extern boolean Paused; 195 | extern char LastASCII; 196 | extern ScanCode LastScan; 197 | extern KeyboardDef KbdDefs[]; 198 | extern JoystickDef JoyDefs[]; 199 | extern ControlType Controls[MaxPlayers]; 200 | 201 | extern Demo DemoMode; 202 | extern byte _seg *DemoBuffer; 203 | extern word DemoOffset,DemoSize; 204 | 205 | // Function prototypes 206 | #define IN_KeyDown(code) (Keyboard[(code)]) 207 | #define IN_ClearKey(code) {Keyboard[code] = false;\ 208 | if (code == LastScan) LastScan = sc_None;} 209 | 210 | // DEBUG - put names in prototypes 211 | extern void IN_Startup(void),IN_Shutdown(void), 212 | IN_Default(boolean gotit,ControlType in), 213 | IN_SetKeyHook(void (*)()), 214 | IN_ClearKeysDown(void), 215 | IN_ReadCursor(CursorInfo *), 216 | IN_ReadControl(int,ControlInfo *), 217 | IN_SetControlType(int,ControlType), 218 | IN_GetJoyAbs(word joy,word *xp,word *yp), 219 | IN_SetupJoy(word joy,word minx,word maxx, 220 | word miny,word maxy), 221 | IN_StartDemoPlayback(byte _seg *buffer,word bufsize), 222 | IN_StopDemo(void),IN_FreeDemoBuffer(void), 223 | IN_Ack(void),IN_AckBack(void); 224 | extern boolean IN_UserInput(longword delay,boolean clear), 225 | IN_IsUserInput(void), 226 | IN_StartDemoRecord(word bufsize); 227 | extern byte *IN_GetScanName(ScanCode); 228 | extern char IN_WaitForASCII(void); 229 | extern ScanCode IN_WaitForKey(void); 230 | extern word IN_GetJoyButtonsDB(word joy); 231 | 232 | #endif 233 | -------------------------------------------------------------------------------- /SRC/BM_DEMO.C: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is loosely based on: 7 | * Keen Dreams Source Code 8 | * Copyright (C) 2014 Javier M. Chavez 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | #include "BM_DEF.H" 26 | 27 | /* 28 | ============================================================================= 29 | 30 | GLOBAL VARIABLES 31 | 32 | ============================================================================= 33 | */ 34 | 35 | boolean scorescreenkludge; 36 | 37 | /* 38 | ============================================================================= 39 | 40 | LOCAL VARIABLES 41 | 42 | ============================================================================= 43 | */ 44 | 45 | //=========================================================================== 46 | 47 | /* 48 | ============================ 49 | = 50 | = CheckLastScan 51 | = 52 | ============================ 53 | */ 54 | 55 | void CheckLastScan(void) 56 | { 57 | if (LastScan) 58 | { 59 | if (storedemo) 60 | { 61 | playstate = ex_resetgame; 62 | restartgame = gd_Normal; 63 | IN_ClearKeysDown(); 64 | NewGame(); 65 | return; 66 | } 67 | 68 | US_ControlPanel(0); 69 | ResetScoreBox(); 70 | } 71 | } 72 | 73 | 74 | //=========================================================================== 75 | 76 | /* 77 | ============================ 78 | = 79 | = ShowTitle 80 | = 81 | ============================ 82 | */ 83 | 84 | void ShowTitle(Uint16 timeout) 85 | { 86 | VW_FadeOut(); 87 | RF_FixOfs(); 88 | 89 | panadjust = 0; 90 | 91 | #ifdef SHAREWARE 92 | CA_CacheGrChunk(TITLESHAREWARE_PIC); 93 | VWB_DrawPic(0, 0, TITLESHAREWARE_PIC); 94 | #else 95 | CA_CacheGrChunk(TITLE_PIC); 96 | VWB_DrawPic(0, 0, TITLE_PIC); 97 | #endif 98 | 99 | VW_SetScreen(displayofs, 0); 100 | VW_ScreenToScreen(bufferofs, displayofs, 42, 224); 101 | VW_FadeIn(); 102 | 103 | IN_UserInput(timeout*TickBase, false); 104 | 105 | CA_ClearMarks(); 106 | CheckLastScan(); 107 | } 108 | 109 | //=========================================================================== 110 | 111 | /* 112 | ============================ 113 | = 114 | = ShowScreen 115 | = 116 | ============================ 117 | */ 118 | 119 | void ShowScreen(Sint16 num) 120 | { 121 | VW_FadeOut(); 122 | RF_FixOfs(); 123 | 124 | panadjust = 0; 125 | 126 | if (num == 0) 127 | { 128 | CA_CacheGrChunk(PREVIEW_PIC); 129 | VWB_DrawPic(0, 0, PREVIEW_PIC); 130 | } 131 | else if (num == 1) 132 | { 133 | CA_CacheGrChunk(CREDITS_PIC); 134 | VWB_DrawPic(0, 0, CREDITS_PIC); 135 | } 136 | else if (num == 2) 137 | { 138 | CA_CacheGrChunk(NOTSHAREWARE_PIC); 139 | VWB_DrawPic(0, 0, NOTSHAREWARE_PIC); 140 | } 141 | else if (num == 3) 142 | { 143 | CA_CacheGrChunk(TECHHELP_PIC); 144 | VWB_DrawPic(0, 0, TECHHELP_PIC); 145 | } 146 | 147 | VW_SetScreen(displayofs, 0); 148 | VW_ScreenToScreen(bufferofs, displayofs, 42, 224); 149 | VW_FadeIn(); 150 | 151 | if (num < 3) 152 | { 153 | IN_UserInput(6*TickBase, false); 154 | } 155 | else 156 | { 157 | IN_ClearKeysDown(); 158 | IN_Ack(); 159 | } 160 | 161 | CA_ClearMarks(); 162 | CheckLastScan(); 163 | } 164 | 165 | //=========================================================================== 166 | 167 | /* 168 | ============================ 169 | = 170 | = RunDemo 171 | = 172 | ============================ 173 | */ 174 | 175 | void RunDemo(Sint16 num) 176 | { 177 | Sint16 basenum; 178 | Uint16 far *demodata; 179 | gametype statecopy; 180 | 181 | basenum = num; 182 | 183 | if (basenum != 4) 184 | { 185 | NewGame(); 186 | } 187 | else 188 | { 189 | memcpy(&statecopy, &gamestate, sizeof(gamestate)); 190 | } 191 | 192 | num += DEMO0; 193 | CA_CacheGrChunk(num); 194 | demodata = grsegs[num]; 195 | gamestate.mapon = demodata[0]; 196 | DemoSize = demodata[1]; 197 | MM_GetPtr(&(memptr)DemoBuffer, DemoSize); 198 | MM_SetLock(&(memptr)DemoBuffer, true); 199 | _fmemcpy(DemoBuffer, ((char _seg *)grsegs[num])+4, DemoSize); 200 | MM_FreePtr(&grsegs[num]); 201 | IN_StartDemoPlayback(DemoBuffer, DemoSize); 202 | SetupGameLevel(true); 203 | if (scorescreenkludge) 204 | { 205 | DrawHighScores(); 206 | } 207 | PlayLoop(); 208 | IN_StopDemo(); 209 | MM_FreePtr(&(memptr)DemoBuffer); 210 | VW_FixRefreshBuffer(); 211 | CA_ClearMarks(); 212 | 213 | if (basenum != 1 && basenum != 4) 214 | { 215 | CheckLastScan(); 216 | } 217 | 218 | if (basenum == 4) 219 | { 220 | memcpy(&gamestate, &statecopy, sizeof(gamestate)); 221 | } 222 | } 223 | 224 | //=========================================================================== 225 | 226 | /* 227 | ============================ 228 | = 229 | = DrawHighScores 230 | = 231 | ============================ 232 | */ 233 | 234 | void DrawHighScores(void) 235 | { 236 | Uint16 i, n; 237 | Uint16 width, height; 238 | HighScore *entry; 239 | Uint16 oldbufferofs; 240 | char buf[16], *bufptr; 241 | 242 | RF_NewPosition(0, 0); 243 | oldbufferofs = bufferofs; 244 | bufferofs = masterofs; 245 | 246 | for (i=0, entry=&Scores[0]; iname); 251 | ultoa(entry->score, buf, 10); 252 | for (bufptr=buf; *bufptr; bufptr++) 253 | { 254 | *bufptr = *bufptr + 81; 255 | } 256 | USL_MeasureString(buf, &width, &height); 257 | PrintX = HIGHSCORE_RIGHT - width; 258 | US_Print(buf); 259 | } 260 | 261 | fontcolor = WHITE; // back to default color 262 | bufferofs = oldbufferofs; 263 | } 264 | 265 | //=========================================================================== 266 | 267 | /* 268 | ============================ 269 | = 270 | = CheckHighScore 271 | = 272 | ============================ 273 | */ 274 | 275 | void CheckHighScore(Sint32 score, Sint16 completed) 276 | { 277 | Uint16 i; 278 | Sint16 index; 279 | HighScore entry; 280 | 281 | strcpy(entry.name, ""); //Note: 'entry.name[0] = 0;' would be more efficient 282 | entry.score = score; 283 | entry.completed = completed; 284 | for (i=0, index=-1; i i) 293 | { 294 | Scores[n] = Scores[n-1]; 295 | } 296 | Scores[i] = entry; 297 | index = i; 298 | HighScoresDirty = true; 299 | break; 300 | } 301 | } 302 | 303 | if (index != -1) 304 | { 305 | scorescreenkludge = true; 306 | gamestate.mapon = HIGHSCORE_MAP; 307 | SetupGameLevel(true); 308 | DrawHighScores(); 309 | RF_Refresh(); 310 | RF_Refresh(); 311 | PrintY = i*16 + HIGHSCORE_TOP; 312 | PrintX = HIGHSCORE_LEFT; 313 | US_LineInput(PrintX, PrintY, Scores[index].name, NULL, true, MaxHighName, 112); 314 | scorescreenkludge = false; 315 | } 316 | } 317 | 318 | //=========================================================================== 319 | 320 | /* 321 | ============================ 322 | = 323 | = ShowHighScores 324 | = 325 | ============================ 326 | */ 327 | 328 | void ShowHighScores(void) 329 | { 330 | scorescreenkludge = true; 331 | IN_ClearKeysDown(); 332 | RunDemo(0); 333 | scorescreenkludge = false; 334 | } 335 | -------------------------------------------------------------------------------- /SRC/ID_VW.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Catacomb 3-D Source Code 8 | * Copyright (C) 1993-2014 Flat Rock Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // ID_VW.H 26 | 27 | #ifndef __TYPES__ 28 | #include "ID_TYPES.H" 29 | #endif 30 | 31 | #ifndef __ID_MM__ 32 | #include "ID_MM.H" 33 | #endif 34 | 35 | #ifndef __ID_GLOB__ 36 | #include "ID_GLOB.H" 37 | #endif 38 | 39 | #define __ID_VW__ 40 | 41 | //=========================================================================== 42 | 43 | #define G_P_SHIFT 4 // global >> ?? = pixels 44 | 45 | #if GRMODE == EGAGR 46 | #define SCREENWIDTH 64 47 | #define CHARWIDTH 1 48 | #define TILEWIDTH 2 49 | #define GRPLANES 4 50 | #define BYTEPIXELS 8 51 | #endif 52 | 53 | #if GRMODE == CGAGR 54 | #define SCREENWIDTH 128 55 | #define CHARWIDTH 2 56 | #define TILEWIDTH 4 57 | #define GRPLANES 1 58 | #define BYTEPIXELS 4 59 | #endif 60 | 61 | #define VIRTUALHEIGHT 300 62 | #define VIRTUALWIDTH 512 63 | 64 | 65 | #if GRMODE == CGAGR 66 | 67 | #define MAXSHIFTS 1 68 | 69 | #define WHITE 3 // graphics mode independant colors 70 | #define BLACK 0 71 | #define FIRSTCOLOR 1 72 | #define SECONDCOLOR 2 73 | #define F_WHITE 0 // for XOR font drawing 74 | #define F_BLACK 3 75 | #define F_FIRSTCOLOR 2 76 | #define F_SECONDCOLOR 1 77 | 78 | #endif 79 | 80 | #if GRMODE == EGAGR 81 | 82 | #define MAXSHIFTS 4 83 | 84 | #define WHITE 15 // graphics mode independant colors 85 | #define BLACK 0 86 | #define FIRSTCOLOR 1 87 | #define SECONDCOLOR 12 88 | #define F_WHITE 0 // for XOR font drawing 89 | #define F_BLACK 15 90 | #define F_FIRSTCOLOR 14 91 | #define F_SECONDCOLOR 3 92 | 93 | #endif 94 | 95 | #if GRMODE == EGAGR 96 | #define SCREENXMASK (~7) 97 | #define SCREENXPLUS (7) 98 | #define SCREENXDIV (8) 99 | #endif 100 | 101 | #if GRMODE == CGAGR 102 | #define SCREENXMASK (~3) 103 | #define SCREENXDIV (4) 104 | #endif 105 | 106 | //=========================================================================== 107 | 108 | 109 | #define SC_INDEX 0x3C4 110 | #define SC_RESET 0 111 | #define SC_CLOCK 1 112 | #define SC_MAPMASK 2 113 | #define SC_CHARMAP 3 114 | #define SC_MEMMODE 4 115 | 116 | #define CRTC_INDEX 0x3D4 117 | #define CRTC_H_TOTAL 0 118 | #define CRTC_H_DISPEND 1 119 | #define CRTC_H_BLANK 2 120 | #define CRTC_H_ENDBLANK 3 121 | #define CRTC_H_RETRACE 4 122 | #define CRTC_H_ENDRETRACE 5 123 | #define CRTC_V_TOTAL 6 124 | #define CRTC_OVERFLOW 7 125 | #define CRTC_ROWSCAN 8 126 | #define CRTC_MAXSCANLINE 9 127 | #define CRTC_CURSORSTART 10 128 | #define CRTC_CURSOREND 11 129 | #define CRTC_STARTHIGH 12 130 | #define CRTC_STARTLOW 13 131 | #define CRTC_CURSORHIGH 14 132 | #define CRTC_CURSORLOW 15 133 | #define CRTC_V_RETRACE 16 134 | #define CRTC_V_ENDRETRACE 17 135 | #define CRTC_V_DISPEND 18 136 | #define CRTC_OFFSET 19 137 | #define CRTC_UNDERLINE 20 138 | #define CRTC_V_BLANK 21 139 | #define CRTC_V_ENDBLANK 22 140 | #define CRTC_MODE 23 141 | #define CRTC_LINECOMPARE 24 142 | 143 | 144 | #define GC_INDEX 0x3CE 145 | #define GC_SETRESET 0 146 | #define GC_ENABLESETRESET 1 147 | #define GC_COLORCOMPARE 2 148 | #define GC_DATAROTATE 3 149 | #define GC_READMAP 4 150 | #define GC_MODE 5 151 | #define GC_MISCELLANEOUS 6 152 | #define GC_COLORDONTCARE 7 153 | #define GC_BITMASK 8 154 | 155 | #define ATR_INDEX 0x3c0 156 | #define ATR_MODE 16 157 | #define ATR_OVERSCAN 17 158 | #define ATR_COLORPLANEENABLE 18 159 | #define ATR_PELPAN 19 160 | #define ATR_COLORSELECT 20 161 | 162 | #define STATUS_REGISTER_1 0x3da 163 | 164 | //=========================================================================== 165 | 166 | typedef enum {NOcard,MDAcard,CGAcard,EGAcard,MCGAcard,VGAcard, 167 | HGCcard=0x80,HGCPcard,HICcard} cardtype; 168 | 169 | typedef struct 170 | { 171 | int width, 172 | height, 173 | orgx,orgy, 174 | xl,yl,xh,yh, 175 | shifts; 176 | } spritetabletype; 177 | 178 | typedef struct 179 | { 180 | unsigned sourceoffset[MAXSHIFTS]; 181 | unsigned planesize[MAXSHIFTS]; 182 | unsigned width[MAXSHIFTS]; 183 | byte data[]; 184 | } spritetype; // the memptr for each sprite points to this 185 | 186 | typedef struct 187 | { 188 | int width,height; 189 | } pictabletype; 190 | 191 | 192 | typedef struct 193 | { 194 | int height; 195 | int location[256]; 196 | char width[256]; 197 | } fontstruct; 198 | 199 | 200 | typedef enum {CGAgr,EGAgr,VGAgr} grtype; 201 | 202 | //=========================================================================== 203 | 204 | extern cardtype videocard; // set by VW_Startup 205 | extern grtype grmode; // CGAgr, EGAgr, VGAgr 206 | 207 | extern unsigned bufferofs; // hidden port to draw to before displaying 208 | extern unsigned displayofs; // origin of port on visable screen 209 | extern unsigned panx,pany; // panning adjustments inside port in pixels 210 | extern unsigned pansx,pansy; 211 | extern unsigned panadjust; // panx/pany adjusted by screen resolution 212 | 213 | extern unsigned screenseg; // normally 0xa000 or buffer segment 214 | 215 | extern unsigned linewidth; 216 | extern unsigned ylookup[VIRTUALHEIGHT]; 217 | 218 | extern boolean screenfaded; 219 | extern char colors[7][17]; // pallets for fades 220 | 221 | extern pictabletype _seg *pictable; 222 | extern pictabletype _seg *picmtable; 223 | extern spritetabletype _seg *spritetable; 224 | 225 | extern unsigned fontnumber; // 0 based font number for drawing 226 | extern int px,py; 227 | extern byte pdrawmode,fontcolor; 228 | 229 | extern int bordercolor; 230 | extern boolean latchpel; 231 | 232 | // 233 | // asm globals 234 | // 235 | 236 | extern unsigned *shifttabletable[8]; 237 | extern unsigned bufferwidth,bufferheight,screenspot; // used by font drawing stuff 238 | 239 | 240 | 241 | //=========================================================================== 242 | 243 | 244 | void VW_Startup (void); 245 | void VW_Shutdown (void); 246 | 247 | cardtype VW_VideoID (void); 248 | 249 | // 250 | // EGA hardware routines 251 | // 252 | 253 | #define EGAWRITEMODE(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_MODE+256*x;out dx,ax;sti;} 254 | #define EGABITMASK(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_BITMASK+256*x;out dx,ax;sti;} 255 | #define EGAMAPMASK(x) asm{cli;mov dx,SC_INDEX;mov ax,SC_MAPMASK+x*256;out dx,ax;sti;} 256 | #define EGAREADMAP(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_READMAP+x*256;out dx,ax;sti;} 257 | 258 | void VW_SetLineWidth(int width); 259 | void VW_SetSplitScreen(int width); 260 | void VW_SetScreen (unsigned CRTC, unsigned pelpan); 261 | 262 | void VW_SetScreenMode (int grmode); 263 | void VW_ClearVideo (int color); 264 | void VW_WaitVBL (int number); 265 | 266 | void VW_ColorBorder (int color); 267 | void VW_SetPalette(byte *palette); 268 | void VW_SetDefaultColors(void); 269 | void VW_FadeOut(void); 270 | void VW_FadeIn(void); 271 | void VW_FadeUp(void); 272 | void VW_FadeDown(void); 273 | 274 | void VW_SetAtrReg (int reg, int value); 275 | 276 | // 277 | // block primitives 278 | // 279 | 280 | void VW_MaskBlock(memptr segm,unsigned ofs,unsigned dest, 281 | unsigned wide,unsigned height,unsigned planesize); 282 | void VW_InverseMask(memptr segm,unsigned ofs,unsigned dest, 283 | unsigned wide,unsigned height); 284 | void VW_MemToScreen(memptr source,unsigned dest,unsigned width,unsigned height); 285 | void VW_ScreenToMem(unsigned source,memptr dest,unsigned width,unsigned height); 286 | void VW_ScreenToScreen(unsigned source,unsigned dest,unsigned width,unsigned height); 287 | 288 | 289 | // 290 | // block addressable routines 291 | // 292 | 293 | void VW_DrawTile8(unsigned x, unsigned y, unsigned tile); 294 | 295 | #if GRMODE == EGAGR 296 | 297 | #define VW_DrawTile8M(x,y,t) \ 298 | VW_MaskBlock(grsegs[STARTTILE8M],(t)*40,bufferofs+ylookup[y]+(x),1,8,8) 299 | #define VW_DrawTile16(x,y,t) \ 300 | VW_MemToScreen(grsegs[STARTTILE16+t],bufferofs+ylookup[y]+(x),2,16) 301 | #define VW_DrawTile16M(x,y,t) \ 302 | VW_MaskBlock(grsegs[STARTTILE16M],(t)*160,bufferofs+ylookup[y]+(x),2,16,32) 303 | 304 | #endif 305 | 306 | #if GRMODE == CGAGR 307 | 308 | #define VW_DrawTile8M(x,y,t) \ 309 | VW_MaskBlock(grsegs[STARTTILE8M],(t)*32,bufferofs+ylookup[y]+(x),2,8,16) 310 | #define VW_DrawTile16(x,y,t) \ 311 | VW_MemToScreen(grsegs[STARTTILE16+t],bufferofs+ylookup[y]+(x),4,16) 312 | #define VW_DrawTile16M(x,y,t) \ 313 | VW_MaskBlock(grsegs[STARTTILE16M],(t)*128,bufferofs+ylookup[y]+(x),4,16,64) 314 | 315 | #endif 316 | 317 | void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum); 318 | void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum); 319 | void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum); 320 | 321 | // 322 | // pixel addressable routines 323 | // 324 | void VW_MeasurePropString (char far *string, word *width, word *height); 325 | void VW_MeasureMPropString (char far *string, word *width, word *height); 326 | 327 | void VW_DrawPropString (char far *string); 328 | void VW_DrawMPropString (char far *string); 329 | void VW_DrawSprite(int x, int y, unsigned sprite); 330 | void VW_Plot(unsigned x, unsigned y, unsigned color); 331 | void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color); 332 | void VW_Vlin(unsigned yl, unsigned yh, unsigned x, unsigned color); 333 | void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height, 334 | unsigned color); 335 | 336 | //=========================================================================== 337 | 338 | // 339 | // Double buffer management routines 340 | // 341 | 342 | void VW_InitDoubleBuffer (void); 343 | void VW_FixRefreshBuffer (void); 344 | int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2); 345 | void VW_UpdateScreen (void); 346 | void VW_CGAFullUpdate (void); 347 | 348 | // 349 | // cursor 350 | // 351 | 352 | void VW_ShowCursor (void); 353 | void VW_HideCursor (void); 354 | void VW_MoveCursor (int x, int y); 355 | void VW_SetCursor (int spritenum); 356 | void VW_FreeCursor (void); 357 | 358 | // 359 | // mode independant routines 360 | // coordinates in pixels, rounded to best screen res 361 | // regions marked in double buffer 362 | // 363 | 364 | void VWB_DrawTile8 (int x, int y, int tile); 365 | void VWB_DrawTile8M (int x, int y, int tile); 366 | void VWB_DrawTile16 (int x, int y, int tile); 367 | void VWB_DrawTile16M (int x, int y, int tile); 368 | void VWB_DrawPic (int x, int y, int chunknum); 369 | void VWB_DrawMPic(int x, int y, int chunknum); 370 | void VWB_Bar (int x, int y, int width, int height, int color); 371 | 372 | void VWB_DrawPropString (char far *string); 373 | void VWB_DrawMPropString (char far *string); 374 | void VWB_DrawSprite (int x, int y, int chunknum); 375 | void VWB_Plot (int x, int y, int color); 376 | void VWB_Hlin (int x1, int x2, int y, int color); 377 | void VWB_Vlin (int y1, int y2, int x, int color); 378 | 379 | //=========================================================================== 380 | -------------------------------------------------------------------------------- /SRC/BM_MAIN.C: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is loosely based on: 7 | * Keen Dreams Source Code 8 | * Copyright (C) 2014 Javier M. Chavez 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | // BM_MAIN.C 26 | /* 27 | ============================================================================= 28 | 29 | BIOMENACE 30 | 31 | An Apogee Software production 32 | 33 | ============================================================================= 34 | */ 35 | 36 | #include "BM_DEF.H" 37 | 38 | /* 39 | ============================================================================= 40 | 41 | GLOBAL VARIABLES 42 | 43 | ============================================================================= 44 | */ 45 | 46 | boolean tedlevel; 47 | Uint16 tedlevelnum; 48 | 49 | char str[80], str2[20]; 50 | boolean storedemo; 51 | 52 | // Boss health divisor - see UpdateScoreBox() in BM_PLAY2.C 53 | Sint16 hbardivisor; 54 | 55 | Uint16 curmusic; 56 | 57 | boolean debugcodeentered = false; 58 | boolean showmenuhighscores = false; 59 | Uint16 unused1 = 0; 60 | boolean practicerestoremap = 0; 61 | Sint16 practicetimer = -1; 62 | Uint16 playerrestorex = 0; 63 | Uint16 playerrestorey = 0; 64 | Sint16 bosshealth = -1; 65 | Sint16 lastbosshealth = -1; 66 | Sint16 nagtimer = -1; 67 | boolean copyprotectionfailed = false; 68 | 69 | 70 | /* 71 | ============================================================================= 72 | 73 | LOCAL VARIABLES 74 | 75 | ============================================================================= 76 | */ 77 | 78 | //=========================================================================== 79 | 80 | /* 81 | ===================== 82 | = 83 | = SizeText 84 | = 85 | = Calculates width and height of a string that contains line breaks 86 | = (Note: only the height is ever used, width is NOT calculated correctly) 87 | = 88 | ===================== 89 | */ 90 | 91 | void SizeText(char *text, Uint16 *width, Uint16 *height) 92 | { 93 | register char *ptr; 94 | char c; 95 | Uint16 w, h; 96 | char strbuf[80]; 97 | 98 | *width = *height = 0; 99 | ptr = &strbuf[0]; 100 | while ((c=*(text++)) != '\0') 101 | { 102 | *(ptr++) = c; 103 | if (c == '\n' || !*text) 104 | { 105 | USL_MeasureString(strbuf, &w, &h); // BUG: strbuf may not have a terminating '\0' at the end! 106 | *height += h; 107 | if (*width < w) 108 | { 109 | *width = w; 110 | } 111 | ptr = &strbuf[0]; 112 | } 113 | } 114 | } 115 | 116 | //=========================================================================== 117 | 118 | /* 119 | ========================== 120 | = 121 | = ShutdownId 122 | = 123 | = Shuts down all ID_?? managers 124 | = 125 | ========================== 126 | */ 127 | 128 | void ShutdownId(void) 129 | { 130 | US_Shutdown(); 131 | SD_Shutdown(); 132 | IN_Shutdown(); 133 | RF_Shutdown(); 134 | VW_Shutdown(); 135 | CA_Shutdown(); 136 | MM_Shutdown(); 137 | } 138 | 139 | 140 | //=========================================================================== 141 | 142 | /* 143 | ========================== 144 | = 145 | = InitGame 146 | = 147 | = Load a few things right away 148 | = 149 | ========================== 150 | */ 151 | 152 | void InitGame(void) 153 | { 154 | void MML_UseSpace (Uint16 segstart, Uint16 seglength); 155 | 156 | Uint16 segstart,seglength; 157 | Sint16 i; 158 | 159 | US_TextScreen(); 160 | _setcursortype(_NOCURSOR); 161 | 162 | MM_Startup(); 163 | VW_Startup(); 164 | RF_Startup(); 165 | IN_Startup(); 166 | SD_Startup(); 167 | US_Startup(); 168 | 169 | US_UpdateTextScreen(); 170 | 171 | CA_Startup(); 172 | US_Setup(); 173 | 174 | US_SetLoadSaveHooks(&LoadTheGame, &SaveTheGame, &ResetGame); 175 | 176 | CA_ClearMarks(); 177 | 178 | CA_MarkGrChunk(STARTFONT); 179 | CA_MarkGrChunk(STARTTILE8); 180 | CA_MarkGrChunk(STARTTILE8M); 181 | 182 | CA_CacheMarks(NULL); 183 | 184 | MM_SetLock(&grsegs[STARTFONT], true); 185 | MM_SetLock(&grsegs[STARTTILE8], true); 186 | MM_SetLock(&grsegs[STARTTILE8M], true); 187 | 188 | fontcolor = WHITE; 189 | 190 | US_FinishTextScreen(); 191 | 192 | // 193 | // reclaim the memory from the linked in text screen 194 | // 195 | segstart = FP_SEG(&introscn); 196 | seglength = 4000/16; 197 | if (FP_OFF(&introscn)) 198 | { 199 | segstart++; 200 | seglength--; 201 | } 202 | MML_UseSpace (segstart,seglength); 203 | 204 | VW_SetScreenMode(GRMODE); 205 | VW_ColorBorder(BLACK); 206 | VW_ClearVideo(BLACK); 207 | } 208 | 209 | //=========================================================================== 210 | 211 | /* 212 | ========================== 213 | = 214 | = Quit 215 | = 216 | ========================== 217 | */ 218 | 219 | void Quit(char *error) 220 | { 221 | Uint16 finscreen; 222 | 223 | if (!error) 224 | { 225 | CA_SetAllPurge(); 226 | CA_CacheGrChunk(ORDERSCREEN); 227 | finscreen = (Uint16)grsegs[ORDERSCREEN]; 228 | } 229 | 230 | // BUG: VW_ClearVideo may brick the system if screenseg is 0 231 | // (i.e. VW_SetScreenMode has not been executed) - this may 232 | // happen if the code runs into an error during InitGame 233 | // (EMS/XMS errors, files not found etc.) 234 | VW_ClearVideo(BLACK); 235 | VW_SetLineWidth(40); 236 | 237 | ShutdownId(); 238 | if (error && *error) 239 | { 240 | puts(error); 241 | if (tedlevel) 242 | { 243 | getch(); 244 | execlp("TED5.EXE", "TED5.EXE", "/LAUNCH", NULL); 245 | } 246 | exit(1); 247 | } 248 | 249 | if (!NoWait) 250 | { 251 | movedata(finscreen, 0, 0xB800, 0, 3780); 252 | textmode(C80); 253 | textcolor(WHITE); 254 | textbackground(BLACK); 255 | gotoxy(1, 24); 256 | } 257 | 258 | exit(0); 259 | } 260 | 261 | //=========================================================================== 262 | 263 | /* 264 | ================== 265 | = 266 | = TEDDeath 267 | = 268 | ================== 269 | */ 270 | 271 | void TEDDeath(void) 272 | { 273 | ShutdownId(); 274 | execlp("TED5.EXE", "TED5.EXE", "/LAUNCH", NULL); 275 | // BUG: should call exit(1); here in case starting TED5 fails 276 | } 277 | 278 | //=========================================================================== 279 | 280 | /* 281 | ================== 282 | = 283 | = CheckMemory 284 | = 285 | ================== 286 | */ 287 | 288 | void CheckMemory(void) 289 | { 290 | Uint16 finscreen; 291 | 292 | if (mminfo.nearheap+mminfo.farheap+mminfo.EMSmem+mminfo.XMSmem >= MINMEMORY) 293 | return; 294 | 295 | CA_CacheGrChunk (OUTOFMEM); 296 | finscreen = (Uint16)grsegs[OUTOFMEM]; 297 | ShutdownId(); 298 | 299 | movedata(finscreen,7,0xb800,0,3780); 300 | textmode(C80); 301 | textcolor(WHITE); 302 | textbackground(BLACK); 303 | gotoxy(1,24); 304 | 305 | exit(1); 306 | } 307 | 308 | //=========================================================================== 309 | 310 | /* 311 | ===================== 312 | = 313 | = DemoLoop 314 | = 315 | ===================== 316 | */ 317 | 318 | void DemoLoop(void) 319 | { 320 | static char *ParmStrings[] = {"easy", "normal", "hard", ""}; 321 | 322 | register Sint16 i, state; 323 | Sint16 level; 324 | boolean unusedvar = true; 325 | boolean donefirstrun = false; 326 | 327 | // 328 | // check for launch from ted 329 | // 330 | if (tedlevel) 331 | { 332 | NewGame(); 333 | CA_LoadAllSounds(); 334 | gamestate.mapon = tedlevelnum; 335 | restartgame = gd_Normal; 336 | for (i = 1;i < _argc;i++) 337 | { 338 | if ( (level = US_CheckParm(_argv[i],ParmStrings)) == -1) 339 | continue; 340 | 341 | restartgame = level+gd_Easy; 342 | break; 343 | } 344 | GameLoop(); 345 | TEDDeath(); 346 | } 347 | 348 | // 349 | // demo loop 350 | // 351 | state = 0; 352 | playstate = ex_stillplaying; 353 | while (1) 354 | { 355 | switch (state++) 356 | { 357 | case 0: 358 | RunDemo(1); 359 | IN_ClearKeysDown(); 360 | LastScan = 0; 361 | 362 | if (!donefirstrun) 363 | { 364 | StartMusic(TECHHELPMUSIC); 365 | donefirstrun = true; 366 | ShowScreen(SCR_TECHHELP); 367 | } 368 | 369 | #ifndef SHAREWARE 370 | StartMusic(TECHHELPMUSIC); 371 | ShowScreen(SCR_NOTSHAREWARE); 372 | #endif 373 | break; 374 | 375 | case 1: 376 | IN_ClearKeysDown(); 377 | LastScan = 0; 378 | StartMusic(DEMOLOOPMUSIC); 379 | ShowTitle(40); 380 | break; 381 | 382 | case 2: 383 | if (curmusic != DEMOLOOPMUSIC) 384 | { 385 | StartMusic(DEMOLOOPMUSIC); 386 | } 387 | 388 | ShowScreen(SCR_CREDITS); 389 | break; 390 | 391 | case 3: 392 | if (curmusic != DEMOLOOPMUSIC) 393 | { 394 | StartMusic(DEMOLOOPMUSIC); 395 | } 396 | ShowScreen(SCR_PREVIEW); 397 | break; 398 | 399 | case 4: 400 | ShowHighScores(); 401 | break; 402 | 403 | case 5: 404 | RunDemo(2); 405 | break; 406 | 407 | case 6: 408 | RunDemo(3); 409 | state = 0; 410 | break; 411 | } 412 | 413 | CheckLastScan(); 414 | 415 | while (playstate == ex_resetgame || playstate == ex_loadedgame) 416 | { 417 | GameLoop(); 418 | 419 | if (playstate == ex_resetgame || playstate == ex_loadedgame) 420 | { 421 | continue; // don't show title screen, go directly to GameLoop(); 422 | } 423 | /////////////// 424 | // this is completely useless: 425 | if (playstate == ex_resetgame || playstate == ex_loadedgame) 426 | { 427 | continue; 428 | } 429 | /////////////// 430 | } 431 | } 432 | } 433 | 434 | //=========================================================================== 435 | 436 | #if (GRMODE == EGAGR) 437 | /* 438 | ===================== 439 | = 440 | = CheckCutFile 441 | = 442 | ===================== 443 | */ 444 | 445 | #define FILE_GR1 GREXT"1."EXTENSION 446 | #define FILE_GR2 GREXT"2."EXTENSION 447 | #define FILE_GRAPH GREXT"GRAPH."EXTENSION 448 | 449 | static void CheckCutFile(void) 450 | { 451 | register Sint16 ohandle, ihandle; 452 | Sint16 handle; 453 | Sint32 size; 454 | void far *buffer; 455 | 456 | if ( (handle = open(FILE_GRAPH, O_BINARY|O_RDONLY)) != -1) 457 | { 458 | close(handle); 459 | return; 460 | } 461 | puts("Combining "FILE_GR1" and "FILE_GR2" into "FILE_GRAPH"..."); 462 | if (rename(FILE_GR1, FILE_GRAPH) == -1) 463 | { 464 | puts("Can't rename "FILE_GR1"!"); 465 | exit(1); 466 | } 467 | if ( (ohandle = open(FILE_GRAPH, O_BINARY|O_APPEND|O_WRONLY)) == -1) 468 | { 469 | puts("Can't open "FILE_GRAPH"!"); 470 | exit(1); 471 | } 472 | lseek(ohandle, 0, SEEK_END); 473 | if ( (ihandle = open(FILE_GR2, O_BINARY|O_RDONLY)) == -1) 474 | { 475 | puts("Can't find "FILE_GR2"!"); 476 | exit(1); 477 | } 478 | size = filelength(ihandle); 479 | buffer = farmalloc(32000); 480 | while (size) 481 | { 482 | if (size > 32000) 483 | { 484 | CA_FarRead(ihandle, buffer, 32000); 485 | CA_FarWrite(ohandle, buffer, 32000); 486 | size -= 32000; 487 | } 488 | else 489 | { 490 | CA_FarRead(ihandle, buffer, size); 491 | CA_FarWrite(ohandle, buffer, size); 492 | size = 0; 493 | } 494 | } 495 | farfree(buffer); 496 | close(ohandle); 497 | close(ihandle); 498 | unlink(FILE_GR2); 499 | } 500 | #endif 501 | 502 | //=========================================================================== 503 | 504 | /* 505 | ===================== 506 | = 507 | = CheckCopyProtection 508 | = 509 | ===================== 510 | */ 511 | 512 | static boolean CheckCopyProtection(void) 513 | { 514 | int i; 515 | Sint16 handle; 516 | char c1, c2; 517 | 518 | const char EXPECTED_FILE_ID_DIZ[443] = 519 | "\xdb\xdb\xdb\xdb\xb2\xb1\xb0 THIS IS PIRATED SOFTWARE! \xb0\xb1\xb2\xdb\xdb\xdb\xdb " 520 | "\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb " 521 | "THIS FILE IS NOT SHAREWARE -- it is ILLEGAL " 522 | "and forbidden to upload this copyrighted " 523 | "software on bulletin boards. If you see " 524 | "this message on a BBS, please request that " 525 | "the Sysop remove this software IMMEDIATELY. " 526 | "\xdb\xb2\xb1\xb0 OR CONTACT APOGEE: (214) 278-5655 \xb0\xb1\xb2\xdb " 527 | "IT IS ILLEGAL TO GET THIS FILE FROM A BBS! " 528 | "\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb "; 529 | char actualtext[sizeof(EXPECTED_FILE_ID_DIZ)]; 530 | 531 | 532 | if ((handle = open("file_id.diz", O_BINARY | O_RDONLY)) == -1) 533 | { 534 | close(handle); 535 | return true; 536 | } 537 | 538 | if (filelength(handle) != sizeof(EXPECTED_FILE_ID_DIZ) - 1) 539 | { 540 | close(handle); 541 | return true; 542 | } 543 | 544 | if (read(handle, actualtext, sizeof(EXPECTED_FILE_ID_DIZ) - 1) == -1) 545 | { 546 | close(handle); 547 | return true; 548 | } 549 | else 550 | { 551 | close(handle); 552 | } 553 | 554 | for (i = 0; i < sizeof(EXPECTED_FILE_ID_DIZ) - 1; i++) 555 | { 556 | c1 = EXPECTED_FILE_ID_DIZ[i]; 557 | c2 = actualtext[i]; 558 | 559 | if (c2 != '\xD' && c2 != '\xA' && c1 != c2) 560 | { 561 | return true; 562 | } 563 | } 564 | 565 | return false; 566 | } 567 | 568 | //=========================================================================== 569 | 570 | 571 | /* 572 | ========================== 573 | = 574 | = main 575 | = 576 | ========================== 577 | */ 578 | 579 | void main(void) 580 | { 581 | static char *ParmStrings[] = {"sewerman", ""}; 582 | 583 | #ifndef SHAREWARE 584 | copyprotectionfailed = CheckCopyProtection(); 585 | #endif 586 | 587 | CheckCutFile(); 588 | 589 | storedemo = false; 590 | 591 | InitGame(); 592 | CheckMemory(); 593 | 594 | gamestate.var44 = 0; 595 | 596 | _setcursortype(_NORMALCURSOR); 597 | 598 | DemoLoop(); 599 | Quit("Demo loop exited???"); 600 | } 601 | -------------------------------------------------------------------------------- /SRC/BM_DEF.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is loosely based on: 7 | * Keen Dreams Source Code 8 | * Copyright (C) 2014 Javier M. Chavez 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | #ifndef __BM_DEF__ 26 | #define __BM_DEF__ 27 | 28 | #include 29 | #include 30 | 31 | #include "ID_HEADS.H" 32 | 33 | /* 34 | ============================================================================= 35 | 36 | GLOBAL CONSTANTS & MACROS 37 | 38 | ============================================================================= 39 | */ 40 | 41 | #define MINMEMORY 250000l 42 | 43 | #define HIGHSCORE_LEFT 40 44 | #define HIGHSCORE_TOP 35 45 | #define HIGHSCORE_RIGHT 280 46 | #define HIGHSCORE_MAP 12 47 | 48 | #define TECHHELPMUSIC 18 49 | #define DEMOLOOPMUSIC 11 50 | #define HELPSCREENSMUSIC 0 51 | #define DIALOGMUSIC 15 52 | #define INVINCIBLEMUSIC 17 53 | #define ENDINGMUSIC 12 54 | #define VICTORYMUSIC 14 55 | 56 | #define INACTIVATEDIST 6 57 | 58 | #define MAXACTORS 125 59 | 60 | #define GAMELEVELS 25 61 | 62 | #define CONVERT_GLOBAL_TO_TILE(x) ((x)>>(G_T_SHIFT)) 63 | #define CONVERT_TILE_TO_GLOBAL(x) ((x)<<(G_T_SHIFT)) 64 | #define CONVERT_GLOBAL_TO_PIXEL(x) ((x)>>(G_P_SHIFT)) 65 | #define CONVERT_PIXEL_TO_GLOBAL(x) ((x)<<(G_P_SHIFT)) 66 | #define CONVERT_PIXEL_TO_TILE(x) ((x)>>(P_T_SHIFT)) 67 | #define CONVERT_TILE_TO_PIXEL(x) ((x)<<(P_T_SHIFT)) 68 | 69 | #define SPAWN_ADJUST_Y(y, h) (CONVERT_TILE_TO_GLOBAL(y) + (CONVERT_PIXEL_TO_GLOBAL(16-(h)))) 70 | 71 | #define ARRAYLENGTH(x) (sizeof(x)/sizeof(*(x))) 72 | 73 | #define CA_UnmarkGrChunk(num) (grneeded[num] &= ~ca_levelbit) 74 | 75 | #define SetPalette(pal) {_ES=FP_SEG(pal); _DX=FP_OFF(pal); _AX=0x1002; geninterrupt(0x10);} 76 | #define SetPaletteEx(pal) {(pal)[16] = bordercolor; SetPalette(pal);} 77 | 78 | //HACK IMPORTS: 79 | void RFL_InitAnimList(void); 80 | void CA_FreeGraphics(void); 81 | void CA_SetGrPurge(void); 82 | 83 | /* 84 | Note: 85 | 86 | The ID software memory manager doesn't care about the different purge levels. 87 | Using PURGE_FIRST is identical to using PURGE_LAST. 88 | */ 89 | #define PURGE_FIRST 3 90 | #define PURGE_LAST 1 91 | 92 | #define PLATFORMBLOCK 71 93 | #define DIRARROWSTART 58 94 | #define DIRARROWEND (DIRARROWSTART+arrow_None) 95 | 96 | /* 97 | ============================================================================= 98 | 99 | GLOBAL TYPES 100 | 101 | ============================================================================= 102 | */ 103 | 104 | //SDL-style integer types - just to make future SDL ports easier 105 | typedef unsigned int Uint16; 106 | typedef signed int Sint16; 107 | typedef unsigned char Uint8; 108 | typedef signed char Sint8; 109 | typedef unsigned long Uint32; 110 | typedef signed long Sint32; 111 | //Note: only the game code (BM_*.C) uses these! 112 | 113 | //some compile-time checks to make sure the ints have the correct size 114 | #if (sizeof(Uint16) != 2) 115 | #error 'Uint16' has wrong size 116 | #elif (sizeof(Sint16) != 2) 117 | #error 'Sint16' has wrong size 118 | #elif (sizeof(Uint8) != 1) 119 | #error 'Uint8' has wrong size 120 | #elif (sizeof(Sint8) != 1) 121 | #error 'Sint8' has wrong size 122 | #elif (sizeof(Uint32) != 4) 123 | #error 'Uint32' has wrong size 124 | #elif (sizeof(Sint32) != 4) 125 | #error 'Sint32' has wrong size 126 | #endif 127 | 128 | typedef enum { 129 | arrow_North, // 0 130 | arrow_East, // 1 131 | arrow_South, // 2 132 | arrow_West, // 3 133 | arrow_NorthEast, // 4 134 | arrow_SouthEast, // 5 135 | arrow_SouthWest, // 6 136 | arrow_NorthWest, // 7 137 | arrow_None // 8 138 | } arrowdirtype; 139 | 140 | typedef enum { 141 | ex_stillplaying, // 0 142 | ex_died, // 1 143 | ex_completed, // 2 144 | ex_warped, // 3 145 | ex_resetgame, // 4 146 | ex_loadedgame, // 5 147 | ex_abortgame, // 6 148 | NUMEXITTYPES 149 | } exittype; 150 | 151 | typedef enum 152 | { 153 | INTILE_NOTHING = 0, 154 | INTILE_LADDER = 1, 155 | INTILE_DAMAGING = 2, 156 | INTILE_KEYCARD_SLOT = 3, 157 | INTILE_DOORLOCK_TRIANGLE = 4, 158 | INTILE_DOORLOCK1 = 5, 159 | INTILE_DOORLOCK2 = 6, 160 | INTILE_DOOR = 7, 161 | INTILE_DOORLOCK_SPECIAL = 8, 162 | INTILE_SHARD_SLOT_BLUE = 9, 163 | INTILE_SHARD_SLOT_GREEN = 10, 164 | INTILE_SHARD_SLOT_RED = 11, 165 | INTILE_SHARD_SLOT_CYAN = 12, 166 | INTILE_RADIATION = 13, 167 | INTILE_NUKE_SLOT = 14, 168 | INTILE_EXITKEY_SLOT = 15, 169 | INTILE_FORCEFIELD = 16, 170 | INTILE_BRIDGE_SWITCH = 18, 171 | INTILE_PLATFORM_SWITCH = 19, 172 | INTILE_UNKNOWN = 20, 173 | INTILE_TRIGGER_DRMANGLE = 21, 174 | INTILE_TRIGGER_UNKNOWN = 22, 175 | INTILE_COLOR_SEQ_SWITCH = 23, 176 | INTILE_TRIGGER_CRUSHER = 25, 177 | INTILE_FOREGROUND = 0x80 178 | } intiletype; 179 | 180 | #define INTILE_TYPEMASK (INTILE_FOREGROUND-1) 181 | 182 | typedef enum 183 | { 184 | nothing = 0, 185 | playerobj = 1, 186 | inertobj = 2, 187 | grenadeobj = 3, 188 | fireballobj = 5, 189 | pickupobj = 6, 190 | slugobj = 7, 191 | obclass_8 = 8, 192 | brawlerobj = 9, 193 | ceilingwalkerobj = 10, 194 | spittersnakeobj = 11, 195 | hostageobj = 12, 196 | drmangleobj = 13, 197 | platformobj = 14, 198 | robopalobj = 16, 199 | shotobj = 17, 200 | lasergunnerobj = 19, 201 | tankbotobj = 20, 202 | pushblockobj = 21, 203 | bounderobj = 22, 204 | bouncebotobj = 23, 205 | slimedropperobj = 24, 206 | enemyprojectileobj = 25, 207 | obclass_26 = 26, 208 | crushblockobj = 27, 209 | laserturretobj = 28, 210 | obclass_29 = 29, 211 | obclass_30 = 30, 212 | sewermutantobj = 31, 213 | hedgehogobj = 32, 214 | skullmanobj = 33, 215 | skullmanhandobj = 34, 216 | bombobj = 36, 217 | crawlingslimeobj = 39, 218 | fireimpobj = 40, 219 | helicopterobj = 41, 220 | parachutebotobj = 42, 221 | NUMCLASSTYPES 222 | } classtype; 223 | 224 | typedef struct statestruct 225 | { 226 | Sint16 leftshapenum, rightshapenum; 227 | enum {step,slide,think,stepthink,slidethink} progress; 228 | boolean skippable; 229 | enum { ps_none, ps_tofloor, ps_toceiling } pushstyle; 230 | Sint16 tictime; 231 | Sint16 xmove; 232 | Sint16 ymove; 233 | void (*think) (struct objstruct*); 234 | void (*contact) (struct objstruct*, struct objstruct*); 235 | void (*react) (struct objstruct*); 236 | struct statestruct far *nextstate; 237 | } statetype; 238 | 239 | typedef struct objstruct 240 | { 241 | classtype obclass; 242 | enum {ac_no, ac_yes, ac_allways, ac_removable} active; 243 | boolean needtoreact; 244 | enum {cl_noclip, cl_midclip, cl_fullclip} needtoclip; 245 | Uint16 nothink; 246 | Uint16 x, y; 247 | Sint16 xdir, ydir; 248 | Sint16 xmove, ymove; 249 | Sint16 xspeed, yspeed; 250 | Sint16 ticcount; 251 | statetype far *state; 252 | Uint16 shapenum; 253 | Uint16 priority; 254 | Uint16 left, top, right, bottom, midx; 255 | Uint16 tileleft, tiletop, tileright, tilebottom, tilemidx; 256 | Sint16 hitnorth, hiteast, hitsouth, hitwest; 257 | boolean shootable; 258 | enum {sb_any, sb_player} spawnedby; 259 | Sint16 health; 260 | Sint16 dmgflash; 261 | Sint16 temp1; 262 | Sint16 temp2; 263 | Sint16 temp3; 264 | Sint16 temp4; 265 | Sint16 temp5; 266 | Sint16 temp6; 267 | Sint16 temp7; 268 | void *sprite; 269 | struct objstruct *next, *prev; 270 | } objtype; 271 | 272 | #define AMMO_REGULAR 0 273 | #define AMMO_SUPERBULLET 3 274 | #define AMMO_PLASMABOLT 4 275 | 276 | 277 | typedef struct 278 | { 279 | Sint32 score; 280 | Sint32 nextextra; 281 | Sint16 mapon; 282 | struct { 283 | Sint8 landmines; 284 | Sint8 grenades; 285 | Sint8 redgrenades; 286 | } explosives; 287 | struct { 288 | Sint16 keycards; 289 | Sint16 keys; 290 | } keyitems; 291 | boolean blueshard; 292 | boolean greenshard; 293 | boolean redshard; 294 | boolean cyanshard; 295 | boolean specialkey; 296 | enum { ns_none, ns_collected, ns_placed } nukestate; 297 | boolean radpill; 298 | boolean exitkey; 299 | boolean trianglekeys; 300 | boolean hasrobopal; 301 | Sint8 potions; 302 | Sint8 lives; 303 | Sint8 gems; 304 | Sint8 maxhealth; 305 | Sint8 difficulty; 306 | Sint8 rapidfire; 307 | Sint8 ammoinclip; 308 | Sint8 clips; 309 | Sint8 ammotype; 310 | boolean hostagerescued; 311 | boolean secretlevelgem; 312 | boolean helpmsggrenades; 313 | boolean helpmsgclips; 314 | boolean helpmsgkeycards; 315 | boolean helpmsgdoors; 316 | boolean helpmsgshards; 317 | boolean helpmsgsupergun; 318 | boolean helpmsglandmines; 319 | boolean helpmsggems; 320 | boolean helpmsghealth; 321 | boolean helpmsginvincible; 322 | boolean helpmsgrobopal; 323 | boolean helpmsgbridgeswitch; 324 | boolean helpmsgplatformswitch; 325 | boolean helpmsgcolorseq; 326 | boolean helpmsgenterdoor; 327 | boolean helpmsgplasmabolts; 328 | boolean helpmsgsecretlevelgem; 329 | boolean helpmsgbeacon; 330 | boolean var44; 331 | objtype *riding; 332 | } gametype; 333 | 334 | /* 335 | ============================================================================= 336 | 337 | BM_MAIN DEFINITIONS 338 | 339 | ============================================================================= 340 | */ 341 | 342 | extern char str[80], str2[20]; 343 | extern boolean storedemo; 344 | extern Sint16 hbardivisor; 345 | extern Uint16 curmusic; 346 | extern boolean debugcodeentered; 347 | extern boolean showmenuhighscores; 348 | extern boolean practicerestoremap; 349 | extern Sint16 practicetimer; 350 | extern Uint16 playerrestorex; 351 | extern Uint16 playerrestorey; 352 | extern Sint16 bosshealth; 353 | extern Sint16 lastbosshealth; 354 | extern Sint16 nagtimer; 355 | extern boolean copyprotectionfailed; 356 | 357 | void SizeText(char *text, Uint16 *width, Uint16 *height); 358 | 359 | /* 360 | ============================================================================= 361 | 362 | BM_DEMO DEFINITIONS 363 | 364 | ============================================================================= 365 | */ 366 | 367 | extern boolean scorescreenkludge; 368 | 369 | #define SCR_PREVIEW 0 370 | #define SCR_CREDITS 1 371 | #define SCR_NOTSHAREWARE 2 372 | #define SCR_TECHHELP 3 373 | 374 | void CheckLastScan(void); 375 | void ShowTitle(Uint16 timeout); 376 | void ShowScreen(Sint16 num); 377 | void RunDemo(Sint16 num); 378 | void DrawHighScores(void); 379 | void CheckHighScore(Sint32 score, Sint16 completed); 380 | void ShowHighScores(void); 381 | 382 | /* 383 | ============================================================================= 384 | 385 | BM_GAME DEFINITIONS 386 | 387 | ============================================================================= 388 | */ 389 | 390 | void FreeGraphics(void); 391 | void NewGame(void); 392 | boolean SaveTheGame(Sint16 handle); 393 | boolean LoadTheGame(Sint16 handle); 394 | void ResetGame(void); 395 | void SetupGameLevel(boolean loadnow); 396 | void StartDemoRecord(void); 397 | void EndDemoRecord(void); 398 | void GameLoop(void); 399 | 400 | extern boolean singlestep, godmode; 401 | extern exittype playstate; 402 | extern gametype gamestate; 403 | extern objtype *new, *player, *scoreobj; 404 | extern Uint16 originxtilemax, originytilemax; 405 | extern ControlInfo c; 406 | extern objtype dummyobj; 407 | extern boolean helpmessages, showscorebox; 408 | extern boolean debugok; 409 | extern boolean firebutton, fireheld, upheld; 410 | 411 | 412 | void CheckKeys(void); 413 | void StatusWindow(void); 414 | void CenterActor(objtype *ob); 415 | void ScrollScreen(objtype *ob); 416 | void InitObjArray(void); 417 | Sint16 GetNewObj(boolean usedummy); 418 | void RemoveObj(objtype *ob); 419 | void GivePoints(Uint16 points); 420 | void StopMusic(void); 421 | void StartMusic(Uint16 num); 422 | void PlayLoop(void); 423 | 424 | /* 425 | ============================================================================= 426 | 427 | BM_TEXT DEFINITIONS 428 | 429 | ============================================================================= 430 | */ 431 | 432 | void ShowHelpMessage(char far* msg); 433 | void HelpScreens(void); 434 | void EpisodeEndScreens(void); 435 | 436 | /* 437 | ============================================================================= 438 | 439 | BM_STATE DEFINITIONS 440 | 441 | ============================================================================= 442 | */ 443 | 444 | extern Sint16 wallclip[8][16]; 445 | 446 | extern Sint16 xtry; 447 | extern Sint16 ytry; 448 | extern boolean playerkludgeclipcancel; 449 | 450 | void MoveObjVert(objtype *ob, Sint16 ymove); 451 | void MoveObjHoriz(objtype *ob, Sint16 xmove); 452 | void PlayerBottomKludge(objtype *ob); 453 | void PlayerTopKludge(objtype *ob); 454 | void ClipToEnds(objtype *ob); 455 | void ClipToSides(objtype *ob); 456 | boolean CheckPosition(objtype *ob); 457 | boolean StatePositionOk(objtype *ob, statetype far *state); 458 | 459 | void ClipToWalls(objtype *ob); 460 | void FullClipToWalls(objtype *ob); 461 | void PushObj(objtype *ob); 462 | void ClipToSpriteSide(objtype *push, objtype *solid); 463 | void ClipToSpriteTop(objtype *push, objtype *solid); 464 | void ClipToSprite(objtype *push, objtype *solid, boolean squish); 465 | void ClipToPushBlock(objtype *push, objtype *solid, boolean squish); 466 | Sint16 DoActor(objtype *ob, Sint16 numtics); 467 | void StateMachine(objtype *ob); 468 | void NewState(objtype *ob, statetype far *state); 469 | void ChangeState(objtype *ob, statetype far *state); 470 | boolean OnScreen(objtype *ob); 471 | void DoGravity(objtype *ob); 472 | void DoWeakGravity(objtype *ob); 473 | void DoTinyGravity(objtype *ob); 474 | void AccelerateX(objtype *ob, Sint16 dir, Sint16 maxspeed); 475 | void AccelerateXv(objtype *ob, Sint16 dir, Sint16 maxspeed); 476 | void AccelerateY(objtype *ob, Sint16 dir, Sint16 maxspeed); 477 | void FrictionX(objtype *ob); 478 | void FrictionY(objtype *ob); 479 | void T_Projectile(objtype *ob); 480 | void T_WeakProjectile(objtype *ob); 481 | void ProjectileThink1(objtype *ob); 482 | void T_Velocity(objtype *ob); 483 | void SetReactThink(objtype *ob); 484 | void C_Lethal(objtype *ob, objtype *hit); 485 | void R_Draw(objtype *ob); 486 | void R_Walk(objtype *ob); 487 | void R_WalkNormal(objtype *ob); 488 | void BadState(void); 489 | 490 | extern statetype far sc_deadstate; 491 | extern statetype far sc_badstate; 492 | 493 | /* 494 | ============================================================================= 495 | 496 | BM_PLAY DEFINITIONS 497 | 498 | ============================================================================= 499 | */ 500 | 501 | void DamagePlayer(objtype* ob, Sint16 amount); 502 | void KillPlayer(void); 503 | void SnakeContact2(objtype* o1, objtype* o2); 504 | void HandleRiding(objtype *ob); 505 | void CheckInTiles(objtype *ob); 506 | void PollControls(void); 507 | 508 | extern char *levelnames[GAMELEVELS]; 509 | 510 | void ScanInfoPlane(void); 511 | 512 | void ResetScoreBox(void); 513 | void UpdateScoreBox(objtype *ob); 514 | 515 | extern statetype far s_player_standing; 516 | 517 | extern boolean playerdied; 518 | 519 | #endif 520 | -------------------------------------------------------------------------------- /SRC/BM_ACT.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef BM_ACT_H 22 | #define BM_ACT_H 23 | 24 | #include "BM_DEF.H" 25 | 26 | 27 | #define PLACESPRITE \ 28 | RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, \ 29 | ob->dmgflash ? maskdraw : spritedraw, ob->priority); 30 | 31 | 32 | void SpawnScoreBox(void); 33 | void FireBullet(Uint16 x, Uint16 y, Sint16 xdir, Sint16 damage); 34 | void DealDamage(objtype* ob, Sint16 amount); 35 | void SpawnSuperPlasmaBolt(Uint16 x, Uint16 y, Sint16 dir); 36 | void HostageDialog(void); 37 | void ShowCompatibilityInfoMessage(void); 38 | void BossDialog(void); 39 | 40 | void C_GrenadeExplosion(objtype* ob, objtype* hit); 41 | void ChunkBloom(objtype* ob, Uint16 x, Uint16 y, Direction dir); 42 | void FragBloom(Uint16 x, Uint16 y, Direction dir); 43 | void SpawnPlayer(Sint16 x, Sint16 y, Sint16 xdir); 44 | void ThrowGrenade(Uint16 x, Uint16 y, Direction dir); 45 | void SpawnBulletImpact(Uint16 x, Uint16 y); 46 | void SpawnShot(Uint16 x, Uint16 y, Sint16 dir); 47 | void SpawnLaserShot(Uint16 x, Uint16 y, Sint16 dir); 48 | void SpawnSuperPlasmaBolt(Uint16 x, Uint16 y, Sint16 dir); 49 | 50 | void SpawnNapalmBomb(objtype* ob); 51 | Sint16 SpawnEnemyShot(Sint16 x, Sint16 y, statetype far* state); 52 | void SpawnParachuteBot(objtype* ob); 53 | void SpawnElevator(Sint16 x, Sint16 y, arrowdirtype dir); 54 | void SpawnApogeeLogo(Sint16 x, Sint16 y, arrowdirtype dir); 55 | void SpawnHelicopter(Sint16 x, Sint16 y, arrowdirtype dir); 56 | void SpawnParachuteBot(objtype* ob); 57 | void SpawnSpitterSnake(Sint16 x, Sint16 y); 58 | void SpawnSewerMutant(Sint16 x, Sint16 y); 59 | void SpawnHostage(Sint16 x, Sint16 y, Sint16 type); 60 | void SpawnDrMangleHologram(Sint16 x, Sint16 y); 61 | void SpawnDrMangle(Sint16 x, Sint16 y); 62 | void SpawnPickup(Sint16 x, Sint16 y, Sint16 type); 63 | void SpawnRobopal(Sint16 x, Sint16 y); 64 | void SpawnSlug(Sint16 x, Sint16 y); 65 | void SpawnGhostlySlug(Sint16 x, Sint16 y); 66 | void SpawnBomb(Sint16 x, Sint16 y); 67 | void SpawnFireImp(Sint16 x, Sint16 y); 68 | void SpawnHedgehog(Sint16 x, Sint16 y); 69 | void SpawnBrawler(Sint16 x, Sint16 y); 70 | void SpawnCeilingWalker(Sint16 x, Sint16 y); 71 | void SpawnCrawlingSlime(Sint16 x, Sint16 y); 72 | void SpawnBigExplosion(Sint16 x, Sint16 y); 73 | void SpawnTankBot(Sint16 x, Sint16 y); 74 | void SpawnLaserGunner(Sint16 x, Sint16 y); 75 | void SpawnPushBlock(Sint16 x, Sint16 y); 76 | void SpawnFallingBlock(Sint16 x, Sint16 y); 77 | void SpawnCrusher(Sint16 x, Sint16 y); 78 | void SpawnBounceBot(Sint16 x, Sint16 y); 79 | void SpawnSlimeDropper(Sint16 x, Sint16 y); 80 | void SpawnLaserTurret(Sint16 x, Sint16 y); 81 | void SpawnAsteroid(Sint16 x, Sint16 y); 82 | void SpawnLandMine(Sint16 x, Sint16 y); 83 | void SpawnSkullmanHand(Sint16 x, Sint16 y, Sint16 t); 84 | void SpawnSkullman(Sint16 x, Sint16 y); 85 | void SpawnSparkShooter(Sint16 x, Sint16 y); 86 | void SpawnRespawnBeacon(Sint16 x, Sint16 y); 87 | 88 | 89 | extern Uint16 bounceangle[8][8]; 90 | extern boolean firerobopal; 91 | extern boolean drmangleactive; 92 | extern Sint16 hbardivisor; 93 | extern Uint16 invincible; 94 | extern Uint16 colorstep; 95 | extern Sint16 doordestx; 96 | extern Sint16 doordesty; 97 | extern Uint16 jumptime; 98 | extern Uint8 unktime; 99 | 100 | extern boolean jumpcheat; 101 | extern boolean godmode; 102 | extern boolean button0held, button1held, fireheld; 103 | 104 | extern Sint16 skullmanactivestate; 105 | extern Sint16 crusheractive; 106 | 107 | 108 | extern statetype far s_player_dying; 109 | extern statetype far s_player_dead; 110 | extern statetype far s_player_fireball; 111 | extern statetype far s_player_shielded1; 112 | extern statetype far s_player_shielded2; 113 | extern statetype far s_player_unused; 114 | extern statetype far s_player_standing; 115 | extern statetype far s_player_activated_trigger; 116 | extern statetype far s_player_unused2; 117 | extern statetype far s_player_lineup; 118 | extern statetype far s_player_enter_door1; 119 | extern statetype far s_player_enter_door2; 120 | extern statetype far s_player_interact1; 121 | extern statetype far s_player_interact2; 122 | extern statetype far s_player_opendoor1; 123 | extern statetype far s_player_opendoor2; 124 | extern statetype far s_player_crouching; 125 | extern statetype far s_player_place_mine; 126 | extern statetype far s_player_climbing_idle; 127 | extern statetype far s_player_climbing1; 128 | extern statetype far s_player_climbing2; 129 | extern statetype far s_player_walking1; 130 | extern statetype far s_player_walking2; 131 | extern statetype far s_player_walking3; 132 | extern statetype far s_player_walking4; 133 | extern statetype far s_player_throwing_grenade1; 134 | extern statetype far s_player_throwing_grenade2; 135 | extern statetype far s_player_throwing_grenade3; 136 | extern statetype far s_player_throwing_grenade_air1; 137 | extern statetype far s_player_throwing_grenade_air2; 138 | extern statetype far s_player_throwing_grenade_air3; 139 | extern statetype far s_player_in_air1; 140 | extern statetype far s_player_in_air2; 141 | extern statetype far s_player_in_air3; 142 | extern statetype far s_player_shoot_single1; 143 | extern statetype far s_player_shoot_single2; 144 | extern statetype far s_player_shoot_single3; 145 | extern statetype far s_player_shoot_single_air1; 146 | extern statetype far s_player_shoot_single_air2; 147 | extern statetype far s_player_shoot_single_air3; 148 | extern statetype far s_player_shoot_single_crouch1; 149 | extern statetype far s_player_shoot_single_crouch2; 150 | extern statetype far s_player_shoot_single_crouch3; 151 | extern statetype far s_player_shoot1; 152 | extern statetype far s_player_shoot2; 153 | extern statetype far s_player_shoot_crouch1; 154 | extern statetype far s_player_shoot_crouch2; 155 | extern statetype far s_player_shoot_air1; 156 | extern statetype far s_player_shoot_air2; 157 | 158 | extern statetype far s_score; 159 | extern statetype far s_bulletimpact1; 160 | extern statetype far s_bulletimpact2; 161 | extern statetype far s_bulletimpact3; 162 | extern statetype far s_gib_bone1; 163 | extern statetype far s_gib_bone2; 164 | extern statetype far s_gib_eyeball1; 165 | extern statetype far s_gib_eyeball2; 166 | extern statetype far s_gib_flesh1; 167 | extern statetype far s_gib_flesh2; 168 | extern statetype far s_gibs_on_floor; 169 | extern statetype far s_metal_debris1; 170 | extern statetype far s_metal_debris2; 171 | extern statetype far s_metal_debris3; 172 | extern statetype far s_metal_debris4; 173 | extern statetype far s_metal_debris_on_floor; 174 | extern statetype far s_fireball1; 175 | extern statetype far s_fireball2; 176 | extern statetype far s_fireball3; 177 | extern statetype far s_fireball4; 178 | extern statetype far s_grenade1; 179 | extern statetype far s_grenade2; 180 | extern statetype far s_grenade3; 181 | extern statetype far s_grenade4; 182 | extern statetype far s_redgrenade1; 183 | extern statetype far s_redgrenade2; 184 | extern statetype far s_redgrenade3; 185 | extern statetype far s_redgrenade4; 186 | extern statetype far s_grenadeexplosion1; 187 | extern statetype far s_grenadeexplosion2; 188 | extern statetype far s_grenadeexplosion3; 189 | extern statetype far s_grenadeexplosion4; 190 | extern statetype far s_grenadeexplosion5; 191 | extern statetype far s_grenadeexplosion6; 192 | extern statetype far s_robopalrocket1; 193 | extern statetype far s_robopalrocket2; 194 | extern statetype far s_lasershot; 195 | extern statetype far s_superplasmabolt; 196 | extern statetype far s_rocketimpact1; 197 | extern statetype far s_rocketimpact2; 198 | extern statetype far s_plasmaboltimpact1; 199 | extern statetype far s_plasmaboltimpact2; 200 | 201 | extern statetype far s_platform; 202 | extern statetype far s_apogeelogo; 203 | extern statetype far s_helicopter1; 204 | extern statetype far s_helicopter2; 205 | extern statetype far s_helicopter_spawnbot; 206 | extern statetype far s_parachutebot_walk1; 207 | extern statetype far s_parachutebot_walk2; 208 | extern statetype far s_parachutebot_attack; 209 | extern statetype far s_parachutebot_falling; 210 | extern statetype far s_spitsnake_walk1; 211 | extern statetype far s_spitsnake_walk2; 212 | extern statetype far s_spitsnake_wait1; 213 | extern statetype far s_spitsnake_wait2; 214 | extern statetype far s_spitsnake_attack1; 215 | extern statetype far s_spitsnake_attack2; 216 | extern statetype far s_spitsnake_projectile1; 217 | extern statetype far s_spitsnake_projectile2; 218 | extern statetype far s_sewermutant1; 219 | extern statetype far s_sewermutant2; 220 | extern statetype far s_sewermutant_attack; 221 | extern statetype far s_sewermutant_projectile1; 222 | extern statetype far s_sewermutant_projectile2; 223 | extern statetype far s_hostage1_1; 224 | extern statetype far s_hostage1_2; 225 | extern statetype far s_hostage2_1; 226 | extern statetype far s_hostage2_2; 227 | extern statetype far s_hostage3_1; 228 | extern statetype far s_hostage3_2; 229 | extern statetype far s_drmangle_hologram1; 230 | extern statetype far s_drmangle_hologram2; 231 | extern statetype far s_drmangle_hologram3; 232 | extern statetype far s_drmangle_hologram1_faded; 233 | extern statetype far s_drmangle_hologram2_faded; 234 | extern statetype far s_drmangle_hologram3_faded; 235 | extern statetype far s_drmangle_hologram_attacking; 236 | extern statetype far s_drmangle_typing1; 237 | extern statetype far s_drmangle_typing2; 238 | extern statetype far s_drmangle_monster1; 239 | extern statetype far s_drmangle_monster2; 240 | extern statetype far s_drmangle_monster_jumping; 241 | extern statetype far s_drmangle_dying; 242 | extern statetype far s_drmangle_dead; 243 | extern statetype far s_drmangle_dead2; 244 | 245 | extern statetype far s_pickup1; 246 | extern statetype far s_pickup2; 247 | extern statetype far s_pickuprise; 248 | extern statetype far s_robopalwait1; 249 | extern statetype far s_robopalwait2; 250 | extern statetype far s_robopalactive1; 251 | extern statetype far s_robopalactive2; 252 | extern statetype far s_robopal_teleport1; 253 | extern statetype far s_robopal_teleport2; 254 | extern statetype far s_robopal_teleport3; 255 | extern statetype far s_robopal_teleport4; 256 | extern statetype far s_robopal_teleport5; 257 | extern statetype far s_slug_walk1; 258 | extern statetype far s_slug_walk2; 259 | extern statetype far s_slug_attack; 260 | extern statetype far s_running_fire1; 261 | extern statetype far s_running_fire2; 262 | extern statetype far s_ghostlyslug1; 263 | extern statetype far s_ghostlyslug2; 264 | extern statetype far s_ghostlyslug_attack; 265 | extern statetype far s_bomb_idle; 266 | extern statetype far s_bomb_attack1; 267 | extern statetype far s_bomb_attack2; 268 | extern statetype far s_bomb_attack3; 269 | extern statetype far s_fireimp_walk1; 270 | extern statetype far s_fireimp_walk2; 271 | extern statetype far s_fireimp_walk3; 272 | extern statetype far s_fireimp_walk4; 273 | extern statetype far s_fireimp_fireform1; 274 | extern statetype far s_fireimp_fireform2; 275 | extern statetype far s_fireimp_stand; 276 | extern statetype far s_fireimp_jumping; 277 | extern statetype far s_hedgehog_roll1; 278 | extern statetype far s_hedgehog_roll2; 279 | extern statetype far s_hedgehog_roll3; 280 | extern statetype far s_hedgehog_roll4; 281 | extern statetype far s_hedgehog_wait1; 282 | extern statetype far s_hedgehog_wait2; 283 | extern statetype far s_hedgehog_jumping; 284 | extern statetype far s_brawler_stand; 285 | extern statetype far s_brawler_walk1; 286 | extern statetype far s_brawler_walk2; 287 | extern statetype far s_brawler_walk3; 288 | extern statetype far s_brawler_walk4; 289 | extern statetype far s_brawler_attack1; 290 | extern statetype far s_brawler_attack2; 291 | extern statetype far s_ceilwalker_walkceil1; 292 | extern statetype far s_ceilwalker_walkceil2; 293 | extern statetype far s_ceilwalker_walkceil3; 294 | extern statetype far s_ceilwalker_walkceil4; 295 | extern statetype far s_ceilwalker_walkfloor1; 296 | extern statetype far s_ceilwalker_walkfloor2; 297 | extern statetype far s_ceilwalker_walkfloor3; 298 | extern statetype far s_ceilwalker_walkfloor4; 299 | extern statetype far s_ceilwalker_falling; 300 | extern statetype far s_crawlslime1; 301 | extern statetype far s_crawlslime2; 302 | extern statetype far s_crawlslime3; 303 | extern statetype far s_crawlslime_steppedon; 304 | 305 | extern statetype far s_bigexplosion1; 306 | extern statetype far s_bigexplosion2; 307 | extern statetype far s_bigexplosion3; 308 | extern statetype far s_tankbot_dying; 309 | extern statetype far s_tankbot_waiting; 310 | extern statetype far s_tankbot_moving1; 311 | extern statetype far s_tankbot_moving2; 312 | extern statetype far s_tankbot_shooting; 313 | extern statetype far s_tankbot_launchbomb; 314 | extern statetype far s_tankbot_bomb_flying; 315 | extern statetype far s_tankbot_bomb_landing; 316 | extern statetype far s_tankbot_shot; 317 | extern statetype far s_tankbot_shot_explode1; 318 | extern statetype far s_tankbot_shot_explode2; 319 | extern statetype far s_napalmfire1; 320 | extern statetype far s_napalmfire2; 321 | extern statetype far s_napalmfire3; 322 | extern statetype far s_lasergunner_idle; 323 | extern statetype far s_lasergunner_attack1; 324 | extern statetype far s_lasergunner_attack2; 325 | extern statetype far s_lasergunner_attack3; 326 | extern statetype far s_lasergunner_attack4; 327 | extern statetype far s_enemy_laser_shot; 328 | extern statetype far s_bigshotimpact1; 329 | extern statetype far s_bigshotimpact2; 330 | extern statetype far s_drmangleshot1; 331 | extern statetype far s_drmangleshot2; 332 | extern statetype far s_pushblock; 333 | extern statetype far s_pushblock_falling; 334 | extern statetype far s_fallingblock_idle; 335 | extern statetype far s_fallingblock_falling; 336 | extern statetype far s_crusher_idle; 337 | extern statetype far s_crusher_moving; 338 | extern statetype far s_bouncebot1; 339 | extern statetype far s_bouncebot2; 340 | extern statetype far s_bouncebot3; 341 | extern statetype far s_bouncebot4; 342 | extern statetype far s_bouncebot5; 343 | extern statetype far s_slimedropper1; 344 | extern statetype far s_slimedropper2; 345 | extern statetype far s_slimedropper3; 346 | extern statetype far s_slime_drop1; 347 | extern statetype far s_slime_drop2; 348 | extern statetype far s_slime_drop3; 349 | extern statetype far s_slimedrop_splat1; 350 | extern statetype far s_slimedrop_splat2; 351 | extern statetype far s_slimedrop_splat3; 352 | extern statetype far s_slimedrop_splat4; 353 | extern statetype far s_turret_idle; 354 | extern statetype far s_turret_attack1; 355 | extern statetype far s_turret_attack2; 356 | extern statetype far s_turret_attack3; 357 | extern statetype far s_asteroid1; 358 | extern statetype far s_asteroid2; 359 | extern statetype far s_asteroid3; 360 | extern statetype far s_asteroid4; 361 | extern statetype far s_landmine1; 362 | extern statetype far s_landmine2; 363 | extern statetype far s_skullman1; 364 | extern statetype far s_skullman2; 365 | extern statetype far s_skullmanhand_r1; 366 | extern statetype far s_skullmanhand_l1; 367 | extern statetype far s_skullmanhand_r2; 368 | extern statetype far s_skullmanhand_l2; 369 | extern statetype far s_skullmanhand_attack_r1; 370 | extern statetype far s_skullmanhand_attack_r2; 371 | extern statetype far s_skullmanhand_attack_l1; 372 | extern statetype far s_skullmanhand_attack_l2; 373 | extern statetype far s_sparkshooter1; 374 | extern statetype far s_sparkshooter2; 375 | extern statetype far s_sparkshot1; 376 | extern statetype far s_sparkshot2; 377 | extern statetype far s_sparkshot_explode1; 378 | extern statetype far s_sparkshot_explode2; 379 | extern statetype far s_respawn_beacon_idle; 380 | extern statetype far s_respawn_beacon1; 381 | extern statetype far s_respawn_beacon2; 382 | extern statetype far s_respawn_beacon3; 383 | extern statetype far s_respawn_beacon4; 384 | 385 | #endif 386 | -------------------------------------------------------------------------------- /SRC/ID_RF_A.ASM: -------------------------------------------------------------------------------- 1 | ; Catacomb 3-D Source Code 2 | ; Copyright (C) 1993-2014 Flat Rock Software 3 | ; 4 | ; This program is free software; you can redistribute it and/or modify 5 | ; it under the terms of the GNU General Public License as published by 6 | ; the Free Software Foundation; either version 2 of the License, or 7 | ; (at your option) any later version. 8 | ; 9 | ; This program is distributed in the hope that it will be useful, 10 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ; GNU General Public License for more details. 13 | ; 14 | ; You should have received a copy of the GNU General Public License along 15 | ; with this program; if not, write to the Free Software Foundation, Inc., 16 | ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 17 | 18 | ; ID_RF_A.ASM 19 | 20 | IDEAL 21 | MODEL MEDIUM,C 22 | 23 | INCLUDE "ID_ASM.EQU" 24 | 25 | ;============================================================================ 26 | 27 | TILESWIDE = 21 28 | TILESHIGH = 14 29 | 30 | UPDATESIZE = (TILESWIDE+1)*TILESHIGH+1 31 | 32 | DATASEG 33 | 34 | EXTRN screenseg:WORD 35 | EXTRN updateptr:WORD 36 | EXTRN updatestart:WORD 37 | EXTRN masterofs:WORD ;start of master tile port 38 | EXTRN bufferofs:WORD ;start of current buffer port 39 | EXTRN screenstart:WORD ;starts of three screens (0/1/master) in EGA mem 40 | EXTRN grsegs:WORD 41 | EXTRN mapsegs:WORD 42 | EXTRN originmap:WORD 43 | EXTRN updatemapofs:WORD 44 | EXTRN tinf:WORD ;seg pointer to map header and tile info 45 | EXTRN blockstarts:WORD ;offsets from bufferofs for each update block 46 | 47 | planemask db ? 48 | planenum db ? 49 | 50 | CODESEG 51 | 52 | screenstartcs dw ? ;in code segment for accesability 53 | 54 | 55 | 56 | 57 | IFE GRMODE-CGAGR 58 | ;============================================================================ 59 | ; 60 | ; CGA refresh routines 61 | ; 62 | ;============================================================================ 63 | 64 | TILEWIDTH = 4 65 | 66 | ;================= 67 | ; 68 | ; RFL_NewTile 69 | ; 70 | ; Draws a composit two plane tile to the master screen and sets the update 71 | ; spot to 1 in both update pages, forcing the tile to be copied to the 72 | ; view pages the next two refreshes 73 | ; 74 | ; Called to draw newlly scrolled on strips and animating tiles 75 | ; 76 | ;================= 77 | 78 | PROC RFL_NewTile updateoffset:WORD 79 | PUBLIC RFL_NewTile 80 | USES SI,DI 81 | 82 | ; 83 | ; mark both update lists at this spot 84 | ; 85 | mov di,[updateoffset] 86 | 87 | mov bx,[updateptr] ;start of update matrix 88 | mov [BYTE bx+di],1 89 | 90 | mov dx,SCREENWIDTH-TILEWIDTH ;add to get to start of next line 91 | 92 | ; 93 | ; set di to the location in screenseg to draw the tile 94 | ; 95 | shl di,1 96 | mov si,[updatemapofs+di] ;offset in map from origin 97 | add si,[originmap] 98 | mov di,[blockstarts+di] ;screen location for tile 99 | add di,[masterofs] 100 | 101 | ; 102 | ; set BX to the foreground tile number and SI to the background number 103 | ; If either BX or SI = 0xFFFF, the tile does not need to be masked together 104 | ; as one of the planes totally eclipses the other 105 | ; 106 | mov es,[mapsegs+2] ;foreground plane 107 | mov bx,[es:si] 108 | mov es,[mapsegs] ;background plane 109 | mov si,[es:si] 110 | 111 | mov es,[screenseg] 112 | 113 | or bx,bx 114 | jz @@singletile 115 | jmp @@maskeddraw ;draw both together 116 | 117 | ;============= 118 | ; 119 | ; Draw single background tile from main memory 120 | ; 121 | ;============= 122 | 123 | @@singletile: 124 | shl si,1 125 | mov ds,[grsegs+STARTTILE16*2+si] 126 | 127 | xor si,si ;block is segment aligned 128 | 129 | REPT 15 130 | movsw 131 | movsw 132 | add di,dx 133 | ENDM 134 | movsw 135 | movsw 136 | 137 | mov ax,ss 138 | mov ds,ax ;restore turbo's data segment 139 | ret 140 | 141 | 142 | ;========= 143 | ; 144 | ; Draw a masked tile combo 145 | ; Interupts are disabled and the stack segment is reassigned 146 | ; 147 | ;========= 148 | @@maskeddraw: 149 | cli ; don't allow ints when SS is set 150 | shl bx,1 151 | mov ss,[grsegs+STARTTILE16M*2+bx] 152 | shl si,1 153 | mov ds,[grsegs+STARTTILE16*2+si] 154 | 155 | xor si,si ;first word of tile data 156 | 157 | REPT 16 158 | mov ax,[si] ;background tile 159 | and ax,[ss:si] ;mask 160 | or ax,[ss:si+64] ;masked data 161 | stosw 162 | mov ax,[si+2] ;background tile 163 | and ax,[ss:si+2] ;mask 164 | or ax,[ss:si+66] ;masked data 165 | stosw 166 | add si,4 167 | add di,dx 168 | ENDM 169 | 170 | mov ax,@DATA 171 | mov ss,ax 172 | sti 173 | mov ds,ax 174 | ret 175 | ENDP 176 | 177 | ENDIF 178 | 179 | 180 | 181 | IFE GRMODE-EGAGR 182 | ;=========================================================================== 183 | ; 184 | ; EGA refresh routines 185 | ; 186 | ;=========================================================================== 187 | 188 | TILEWIDTH = 2 189 | 190 | ;================= 191 | ; 192 | ; RFL_NewTile 193 | ; 194 | ; Draws a composit two plane tile to the master screen and sets the update 195 | ; spot to 1 in both update pages, forcing the tile to be copied to the 196 | ; view pages the next two refreshes 197 | ; 198 | ; Called to draw newlly scrolled on strips and animating tiles 199 | ; 200 | ; Assumes write mode 0 201 | ; 202 | ;================= 203 | 204 | PROC RFL_NewTile updateoffset:WORD 205 | PUBLIC RFL_NewTile 206 | USES SI,DI 207 | 208 | ; 209 | ; mark both update lists at this spot 210 | ; 211 | mov di,[updateoffset] 212 | 213 | mov bx,[updatestart] ;page 0 pointer 214 | mov [BYTE bx+di],1 215 | mov bx,[updatestart+2] ;page 1 pointer 216 | mov [BYTE bx+di],1 217 | 218 | ; 219 | ; set screenstartcs to the location in screenseg to draw the tile 220 | ; 221 | shl di,1 222 | mov si,[updatemapofs+di] ;offset in map from origin 223 | add si,[originmap] 224 | mov di,[blockstarts+di] ;screen location for tile 225 | add di,[masterofs] 226 | mov [cs:screenstartcs],di 227 | 228 | ; 229 | ; set BX to the foreground tile number and SI to the background number 230 | ; If either BX or SI = 0xFFFF, the tile does not need to be masked together 231 | ; as one of the planes totally eclipses the other 232 | ; 233 | mov es,[mapsegs+2] ;foreground plane 234 | mov bx,[es:si] 235 | mov es,[mapsegs] ;background plane 236 | mov si,[es:si] 237 | 238 | mov es,[screenseg] 239 | mov dx,SC_INDEX ;for stepping through map mask planes 240 | 241 | or bx,bx 242 | jz @@singletile 243 | jmp @@maskeddraw ;draw both together 244 | 245 | ;========= 246 | ; 247 | ; No foreground tile, so draw a single background tile. 248 | ; 249 | ;========= 250 | @@singletile: 251 | 252 | mov bx,SCREENWIDTH-2 ;add to get to start of next line 253 | shl si,1 254 | 255 | mov ax,[cs:screenstartcs] 256 | mov ds,[grsegs+STARTTILE16*2+si] 257 | 258 | xor si,si ;block is segment aligned 259 | 260 | mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0 261 | 262 | mov cx,4 ;draw four planes 263 | @@planeloop: 264 | mov dx,SC_INDEX 265 | WORDOUT 266 | 267 | mov di,[cs:screenstartcs] ;start at same place in all planes 268 | 269 | REPT 15 270 | movsw 271 | add di,bx 272 | ENDM 273 | movsw 274 | 275 | shl ah,1 ;shift plane mask over for next plane 276 | loop @@planeloop 277 | 278 | mov ax,ss 279 | mov ds,ax ;restore turbo's data segment 280 | ret 281 | 282 | 283 | ;========= 284 | ; 285 | ; Draw a masked tile combo 286 | ; Interupts are disabled and the stack segment is reassigned 287 | ; 288 | ;========= 289 | @@maskeddraw: 290 | cli ; don't allow ints when SS is set 291 | shl bx,1 292 | mov ss,[grsegs+STARTTILE16M*2+bx] 293 | shl si,1 294 | mov ds,[grsegs+STARTTILE16*2+si] 295 | 296 | xor si,si ;first word of tile data 297 | 298 | mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0 299 | 300 | mov di,[cs:screenstartcs] 301 | @@planeloopm: 302 | WORDOUT 303 | tileofs = 0 304 | lineoffset = 0 305 | REPT 16 306 | mov bx,[si+tileofs] ;background tile 307 | and bx,[ss:tileofs] ;mask 308 | or bx,[ss:si+tileofs+32] ;masked data 309 | mov [es:di+lineoffset],bx 310 | tileofs = tileofs + 2 311 | lineoffset = lineoffset + SCREENWIDTH 312 | ENDM 313 | add si,32 314 | shl ah,1 ;shift plane mask over for next plane 315 | cmp ah,10000b 316 | je @@done ;drawn all four planes 317 | jmp @@planeloopm 318 | 319 | @@done: 320 | mov ax,@DATA 321 | mov ss,ax 322 | sti 323 | mov ds,ax 324 | ret 325 | ENDP 326 | 327 | ENDIF 328 | 329 | IFE GRMODE-VGAGR 330 | ;============================================================================ 331 | ; 332 | ; VGA refresh routines 333 | ; 334 | ;============================================================================ 335 | 336 | 337 | ENDIF 338 | 339 | 340 | ;============================================================================ 341 | ; 342 | ; reasonably common refresh routines 343 | ; 344 | ;============================================================================ 345 | 346 | 347 | ;================= 348 | ; 349 | ; RFL_UpdateTiles 350 | ; 351 | ; Scans through the update matrix pointed to by updateptr, looking for 1s. 352 | ; A 1 represents a tile that needs to be copied from the master screen to the 353 | ; current screen (a new row or an animated tiled). If more than one adjacent 354 | ; tile in a horizontal row needs to be copied, they will be copied as a group. 355 | ; 356 | ; Assumes write mode 1 357 | ; 358 | ;================= 359 | 360 | 361 | ; AX 0/1 for scasb, temp for segment register transfers 362 | ; BX width for block copies 363 | ; CX REP counter 364 | ; DX line width deltas 365 | ; SI source for copies 366 | ; DI scas dest / movsb dest 367 | ; BP pointer to UPDATETERMINATE 368 | ; 369 | ; DS 370 | ; ES 371 | ; SS 372 | 373 | PROC RFL_UpdateTiles 374 | PUBLIC RFL_UpdateTiles 375 | USES SI,DI,BP 376 | 377 | jmp SHORT @@realstart 378 | @@done: 379 | ; 380 | ; all tiles have been scanned 381 | ; 382 | ret 383 | 384 | @@realstart: 385 | mov di,[updateptr] 386 | mov bp,(TILESWIDE+1)*TILESHIGH+1 387 | add bp,di ; when di = bx, all tiles have been scanned 388 | push di 389 | mov cx,-1 ; definately scan the entire thing 390 | 391 | ; 392 | ; scan for a 1 in the update list, meaning a tile needs to be copied 393 | ; from the master screen to the current screen 394 | ; 395 | @@findtile: 396 | pop di ; place to continue scaning from 397 | mov ax,ss 398 | mov es,ax ; search in the data segment 399 | mov ds,ax 400 | mov al,1 401 | repne scasb 402 | cmp di,bp 403 | je @@done 404 | 405 | cmp [BYTE di],al 406 | jne @@singletile 407 | jmp @@tileblock 408 | 409 | ;============ 410 | ; 411 | ; copy a single tile 412 | ; 413 | ;============ 414 | EVEN 415 | @@singletile: 416 | inc di ; we know the next tile is nothing 417 | push di ; save off the spot being scanned 418 | sub di,[updateptr] 419 | shl di,1 420 | mov di,[blockstarts-4+di] ; start of tile location on screen 421 | mov si,di 422 | add di,[bufferofs] ; dest in current screen 423 | add si,[masterofs] ; source in master screen 424 | 425 | mov dx,SCREENWIDTH-TILEWIDTH 426 | mov ax,[screenseg] 427 | mov ds,ax 428 | mov es,ax 429 | 430 | ;-------------------------- 431 | 432 | IFE GRMODE-CGAGR 433 | 434 | REPT 15 435 | movsw 436 | movsw 437 | add si,dx 438 | add di,dx 439 | ENDM 440 | movsw 441 | movsw 442 | 443 | ENDIF 444 | 445 | ;-------------------------- 446 | 447 | IFE GRMODE-EGAGR 448 | 449 | REPT 15 450 | movsb 451 | movsb 452 | add si,dx 453 | add di,dx 454 | ENDM 455 | movsb 456 | movsb 457 | 458 | ENDIF 459 | 460 | ;-------------------------- 461 | 462 | jmp @@findtile 463 | 464 | ;============ 465 | ; 466 | ; more than one tile in a row needs to be updated, so do it as a group 467 | ; 468 | ;============ 469 | EVEN 470 | @@tileblock: 471 | mov dx,di ; hold starting position + 1 in dx 472 | inc di ; we know the next tile also gets updated 473 | repe scasb ; see how many more in a row 474 | push di ; save off the spot being scanned 475 | 476 | mov bx,di 477 | sub bx,dx ; number of tiles in a row 478 | shl bx,1 ; number of bytes / row 479 | 480 | mov di,dx ; lookup position of start tile 481 | sub di,[updateptr] 482 | shl di,1 483 | mov di,[blockstarts-2+di] ; start of tile location 484 | mov si,di 485 | add di,[bufferofs] ; dest in current screen 486 | add si,[masterofs] ; source in master screen 487 | 488 | mov dx,SCREENWIDTH 489 | sub dx,bx ; offset to next line on screen 490 | IFE GRMODE-CGAGR 491 | sub dx,bx ; bx is words wide in CGA tiles 492 | ENDIF 493 | 494 | mov ax,[screenseg] 495 | mov ds,ax 496 | mov es,ax 497 | 498 | REPT 15 499 | mov cx,bx 500 | IFE GRMODE-CGAGR 501 | rep movsw 502 | ENDIF 503 | IFE GRMODE-EGAGR 504 | rep movsb 505 | ENDIF 506 | add si,dx 507 | add di,dx 508 | ENDM 509 | mov cx,bx 510 | IFE GRMODE-CGAGR 511 | rep movsw 512 | ENDIF 513 | IFE GRMODE-EGAGR 514 | rep movsb 515 | ENDIF 516 | 517 | dec cx ; was 0 from last rep movsb, now $ffff for scasb 518 | jmp @@findtile 519 | 520 | ENDP 521 | 522 | 523 | ;============================================================================ 524 | 525 | 526 | ;================= 527 | ; 528 | ; RFL_MaskForegroundTiles 529 | ; 530 | ; Scan through update looking for 3's. If the foreground tile there is a 531 | ; masked foreground tile, draw it to the screen 532 | ; 533 | ;================= 534 | 535 | PROC RFL_MaskForegroundTiles 536 | PUBLIC RFL_MaskForegroundTiles 537 | USES SI,DI,BP 538 | jmp SHORT @@realstart 539 | @@done: 540 | ; 541 | ; all tiles have been scanned 542 | ; 543 | ret 544 | 545 | @@realstart: 546 | mov di,[updateptr] 547 | mov bp,(TILESWIDE+1)*TILESHIGH+2 548 | add bp,di ; when di = bx, all tiles have been scanned 549 | push di 550 | mov cx,-1 ; definately scan the entire thing 551 | ; 552 | ; scan for a 3 in the update list 553 | ; 554 | @@findtile: 555 | mov ax,ss 556 | mov es,ax ; scan in the data segment 557 | mov al,3 558 | pop di ; place to continue scaning from 559 | repne scasb 560 | cmp di,bp 561 | je @@done 562 | 563 | ;============ 564 | ; 565 | ; found a tile, see if it needs to be masked on 566 | ; 567 | ;============ 568 | 569 | push di 570 | 571 | sub di,[updateptr] 572 | shl di,1 573 | mov si,[updatemapofs-2+di] ; offset from originmap 574 | add si,[originmap] 575 | 576 | mov es,[mapsegs+2] ; foreground map plane segment 577 | mov si,[es:si] ; foreground tile number 578 | 579 | or si,si 580 | jz @@findtile ; 0 = no foreground tile 581 | 582 | mov bx,si 583 | add bx,INTILE ;INTILE tile info table 584 | mov es,[tinf] 585 | test [BYTE PTR es:bx],80h ;high bit = masked tile 586 | jz @@findtile 587 | 588 | ;------------------- 589 | 590 | IFE GRMODE-CGAGR 591 | ;================= 592 | ; 593 | ; mask the tile CGA 594 | ; 595 | ;================= 596 | 597 | mov di,[blockstarts-2+di] 598 | add di,[bufferofs] 599 | mov es,[screenseg] 600 | shl si,1 601 | mov ds,[grsegs+STARTTILE16M*2+si] 602 | 603 | mov bx,64 ;data starts 64 bytes after mask 604 | 605 | xor si,si 606 | 607 | lineoffset = 0 608 | REPT 16 609 | mov ax,[es:di+lineoffset] ;background 610 | and ax,[si] ;mask 611 | or ax,[si+bx] ;masked data 612 | mov [es:di+lineoffset],ax ;background 613 | inc si 614 | inc si 615 | mov ax,[es:di+lineoffset+2] ;background 616 | and ax,[si] ;mask 617 | or ax,[si+bx] ;masked data 618 | mov [es:di+lineoffset+2],ax ;background 619 | inc si 620 | inc si 621 | lineoffset = lineoffset + SCREENWIDTH 622 | ENDM 623 | ENDIF 624 | 625 | ;------------------- 626 | 627 | IFE GRMODE-EGAGR 628 | ;================= 629 | ; 630 | ; mask the tile 631 | ; 632 | ;================= 633 | 634 | mov [BYTE planemask],1 635 | mov [BYTE planenum],0 636 | 637 | mov di,[blockstarts-2+di] 638 | add di,[bufferofs] 639 | mov [cs:screenstartcs],di 640 | mov es,[screenseg] 641 | shl si,1 642 | mov ds,[grsegs+STARTTILE16M*2+si] 643 | 644 | mov bx,32 ;data starts 32 bytes after mask 645 | 646 | @@planeloopm: 647 | mov dx,SC_INDEX 648 | mov al,SC_MAPMASK 649 | mov ah,[ss:planemask] 650 | WORDOUT 651 | mov dx,GC_INDEX 652 | mov al,GC_READMAP 653 | mov ah,[ss:planenum] 654 | WORDOUT 655 | 656 | xor si,si 657 | mov di,[cs:screenstartcs] 658 | lineoffset = 0 659 | REPT 16 660 | mov cx,[es:di+lineoffset] ;background 661 | and cx,[si] ;mask 662 | or cx,[si+bx] ;masked data 663 | inc si 664 | inc si 665 | mov [es:di+lineoffset],cx 666 | lineoffset = lineoffset + SCREENWIDTH 667 | ENDM 668 | add bx,32 ;the mask is now further away 669 | inc [ss:planenum] 670 | shl [ss:planemask],1 ;shift plane mask over for next plane 671 | cmp [ss:planemask],10000b ;done all four planes? 672 | je @@drawn ;drawn all four planes 673 | jmp @@planeloopm 674 | 675 | @@drawn: 676 | ENDIF 677 | 678 | ;------------------- 679 | 680 | mov ax,ss 681 | mov ds,ax 682 | mov cx,-1 ;definately scan the entire thing 683 | 684 | jmp @@findtile 685 | 686 | ENDP 687 | 688 | 689 | END 690 | 691 | -------------------------------------------------------------------------------- /SRC/BM_GAME1.C: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is loosely based on: 7 | * Keen Dreams Source Code 8 | * Copyright (C) 2014 Javier M. Chavez 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | #include "BM_DEF.H" 26 | 27 | /* 28 | ============================================================================= 29 | 30 | GLOBAL VARIABLES 31 | 32 | ============================================================================= 33 | */ 34 | 35 | extern Uint16 unknown; 36 | extern Sint16 crusheractive; 37 | extern Uint16 invincible; 38 | extern Uint16 colorstep; 39 | extern Uint8 unktime; 40 | 41 | Uint16 fadecount; 42 | Sint16 mapon; 43 | 44 | /* 45 | ============================================================================= 46 | 47 | LOCAL VARIABLES 48 | 49 | ============================================================================= 50 | */ 51 | 52 | const char FILE_ID_MISSING[] = 53 | "Critical file FILE_ID.DIZ missing\n" 54 | "or modified. If you purchased the\n" 55 | "game from Apogee simply reinstall\n" 56 | "the game. You can call Apogee at\n" 57 | "(214) 278-5655 or refer to\n" 58 | "Ordering Info for more details.\n"; 59 | 60 | char far EASY[] = "easy"; 61 | char far NORMAL[] = "normal"; 62 | char far HARD[] = "hard"; 63 | char far GAME_OVER[] = "Game Over!"; 64 | char far NOT_ENOUGH_MEM[] = "Not enough memory\nto load game!"; 65 | char far DIDNT_MAKE_IT_PAST[] = "You didn't make it past"; 66 | char far TRY_AGAIN[] = "Try Again"; 67 | char far INSUFFICIENT_MEM[] = "Insufficient memory\nto load level!"; 68 | char far ONE_MOMENT[] = "One moment"; 69 | char far GOD_MODE_ON[] = "God mode ON"; 70 | char far GOD_MODE_OFF[] = "God mode OFF"; 71 | char far FREE_ITEMS[] = "Free items!"; 72 | char far JUMP_CHEAT_ON[] = "Jump cheat ON"; 73 | char far JUMP_CHEAT_OFF[] = "Jump cheat OFF"; 74 | char far WARP_LEVEL_PROMPT[] = " Warp to which level(1-17): "; 75 | char far PRACTICE_LEVEL_PROMPT[] = " Practice which level (1-11): "; 76 | 77 | void FadeAndUnhook(void); 78 | 79 | //=========================================================================== 80 | 81 | /* 82 | ============================ 83 | = 84 | = FreeGraphics 85 | = 86 | ============================ 87 | */ 88 | 89 | void FreeGraphics(void) 90 | { 91 | Sint16 i; 92 | for (i=STARTSPRITES; i>= 1; 189 | CA_ClearMarks(); 190 | ca_levelbit <<= 1; 191 | ca_levelnum++; 192 | 193 | if (restartgame != gd_Continue) 194 | { 195 | if (wantspractice == true) 196 | { 197 | practicerestoremap = gamestate.mapon; 198 | 199 | VW_FixRefreshBuffer(); 200 | US_CenterWindow(26, 3); 201 | PrintY += 6; 202 | 203 | _fstrcpy(str, PRACTICE_LEVEL_PROMPT); 204 | US_Print(str); 205 | VW_UpdateScreen(); 206 | inputfailed = !US_LineInput(px, py, str, NULL, true, 2, 0); 207 | 208 | if (!inputfailed) 209 | { 210 | practicelevel = atoi(str); 211 | 212 | if (practicelevel > 0 && practicelevel <= 11) 213 | { 214 | gamestate.mapon = practicelevel - 1; 215 | } 216 | } 217 | 218 | wantspractice = false; 219 | practicetimer = 500; 220 | } 221 | else 222 | { 223 | if (practicetimer >= 0) 224 | { 225 | practicetimer = -1; 226 | } 227 | } 228 | 229 | playstate = ex_resetgame; 230 | } 231 | else if (loadedgame) 232 | { 233 | playstate = ex_loadedgame; 234 | practicetimer = -1; 235 | } 236 | 237 | VW_FadeOut(); 238 | } 239 | 240 | //=========================================================================== 241 | 242 | /* 243 | ============================ 244 | = 245 | = SaveTheGame 246 | = 247 | ============================ 248 | */ 249 | 250 | boolean SaveTheGame(Sint16 handle) 251 | { 252 | gametype state; 253 | 254 | gamestate.riding = NULL; 255 | practicetimer = -1; 256 | wantspractice = 0; 257 | 258 | memcpy(&state, &gamestate, sizeof(gamestate)); 259 | memset(&state.keyitems, 0, sizeof(state.keyitems)); 260 | state.blueshard = false; 261 | state.greenshard = false; 262 | state.redshard = false; 263 | state.cyanshard = false; 264 | state.exitkey = false; 265 | state.trianglekeys = 0; 266 | state.specialkey = false; 267 | state.radpill = false; 268 | state.hasrobopal = false; 269 | state.hostagerescued = false; 270 | state.clips = 0; 271 | state.ammoinclip = 0; 272 | state.ammotype = AMMO_REGULAR; 273 | memset(&state.explosives, 0, sizeof(state.explosives)); 274 | 275 | switch (state.difficulty) 276 | { 277 | case gd_Easy: 278 | state.maxhealth = 8; 279 | break; 280 | 281 | case gd_Normal: 282 | state.maxhealth = 4; 283 | break; 284 | 285 | case gd_Hard: 286 | state.maxhealth = 4; 287 | break; 288 | 289 | default: 290 | state.maxhealth = 4; 291 | break; 292 | } 293 | 294 | colorstep = 0; 295 | if (!CA_FarWrite(handle, (byte far *)&state, sizeof(state))) 296 | return false; 297 | 298 | return true; 299 | } 300 | 301 | //=========================================================================== 302 | 303 | /* 304 | ============================ 305 | = 306 | = LoadTheGame 307 | = 308 | ============================ 309 | */ 310 | 311 | boolean LoadTheGame(Sint16 handle) 312 | { 313 | if (!CA_FarRead(handle, (byte far *)&gamestate, sizeof(gamestate))) 314 | return false; 315 | 316 | playstate = ex_loadedgame; 317 | player->health = gamestate.maxhealth; 318 | practicetimer = -1; 319 | wantspractice = 0; 320 | return true; 321 | } 322 | 323 | //=========================================================================== 324 | 325 | /* 326 | ========================== 327 | = 328 | = DelayedFade 329 | = 330 | = Fades out and latches FadeAndUnhook onto the refresh 331 | = 332 | ========================== 333 | */ 334 | 335 | void DelayedFade(void) 336 | { 337 | VW_FadeOut(); 338 | fadecount = 0; 339 | RF_SetRefreshHook(&FadeAndUnhook); 340 | } 341 | 342 | /* 343 | ========================== 344 | = 345 | = FadeAndUnhook 346 | = 347 | = Latch this onto the refresh so the screen only gets faded in after two 348 | = refreshes. This lets all actors draw themselves to both pages before 349 | = fading the screen in. 350 | = 351 | ========================== 352 | */ 353 | 354 | void FadeAndUnhook(void) 355 | { 356 | if (++fadecount == 2) 357 | { 358 | VW_FadeIn(); 359 | RF_SetRefreshHook(NULL); 360 | TimeCount = lasttimecount; // don't adaptively time the fade 361 | } 362 | } 363 | 364 | //=========================================================================== 365 | 366 | 367 | /* 368 | ========================== 369 | = 370 | = SetupGameLevel 371 | = 372 | = Load in map mapon and cache everything needed for it 373 | = 374 | ========================== 375 | */ 376 | 377 | void SetupGameLevel(boolean loadnow) 378 | { 379 | playerrestorex = 0; 380 | playerrestorey = 0; 381 | 382 | SD_FadeOutMusic(); 383 | CA_SetAllPurge(); 384 | 385 | // 386 | // randomize if not a demo 387 | // 388 | if (DemoMode) 389 | { 390 | US_InitRndT(false); 391 | gamestate.difficulty = gd_Normal; 392 | } 393 | else 394 | { 395 | US_InitRndT(true); 396 | } 397 | 398 | // 399 | // load the level header and three map planes 400 | // 401 | CA_CacheMap(gamestate.mapon); 402 | 403 | // 404 | // let the refresh manager set up some variables 405 | // 406 | RF_NewMap(); 407 | 408 | // 409 | // decide which graphics are needed and spawn actors 410 | // 411 | CA_ClearMarks(); 412 | ScanInfoPlane(); 413 | RF_MarkTileGraphics(); 414 | 415 | // 416 | // have the caching manager load and purge stuff to make sure all marks 417 | // are in memory 418 | // 419 | CA_LoadAllSounds(); 420 | if (loadnow) 421 | { 422 | if (scorescreenkludge || gamestate.mapon == 13) 423 | { 424 | CA_CacheMarks(NULL); 425 | } 426 | else if (gamestate.mapon >= 20) 427 | { 428 | CA_CacheMarks("Secret Level"); 429 | } 430 | else if (DemoMode) 431 | { 432 | CA_CacheMarks("DEMO"); 433 | } 434 | else 435 | { 436 | CA_CacheMarks(levelnames[mapon]); 437 | } 438 | } 439 | 440 | if (loadnow) 441 | { 442 | DelayedFade(); 443 | } 444 | } 445 | 446 | //=========================================================================== 447 | 448 | boolean RespawnPlayer(void) 449 | { 450 | if (playerrestorex > 0 && playerrestorey > 0) 451 | { 452 | player->y = playerrestorey; 453 | player->x = playerrestorex; 454 | player->priority = 1; 455 | 456 | player->needtoclip = cl_noclip; 457 | ChangeState(player, &s_player_standing); 458 | 459 | player->needtoclip = cl_midclip; 460 | CenterActor(player); 461 | 462 | ytry = 15; 463 | player->obclass = playerobj; 464 | player->active = ac_yes; 465 | player->needtoclip = cl_midclip; 466 | 467 | switch (gamestate.difficulty) 468 | { 469 | case gd_Easy: 470 | player->health = 8; 471 | break; 472 | 473 | case gd_Normal: 474 | player->health = 4; 475 | break; 476 | 477 | case gd_Hard: 478 | player->health = 2; 479 | break; 480 | 481 | default: 482 | player->health = 4; 483 | break; 484 | } 485 | 486 | gamestate.maxhealth = player->health; 487 | invincible = 50; 488 | unktime = 0; 489 | return true; 490 | } 491 | 492 | return false; 493 | } 494 | 495 | //========================================================================== 496 | 497 | /* 498 | ============================ 499 | = 500 | = GameLoop 501 | = 502 | = A game has just started (after the cinematic or load game) 503 | = 504 | ============================ 505 | */ 506 | 507 | void GameLoop(void) 508 | { 509 | register Uint16 oldbufferofs; 510 | 511 | #define ENTER_SECRET_LEVEL(n) \ 512 | playstate = ex_stillplaying; \ 513 | RunDemo(4); \ 514 | gamestate.mapon = (n - 1); \ 515 | gamestate.secretlevelgem = false; 516 | 517 | 518 | start: 519 | if (playstate != ex_loadedgame) 520 | { 521 | gamestate.difficulty = restartgame; 522 | } 523 | 524 | restartgame = gd_Continue; 525 | 526 | restart: 527 | SetupGameLevel(true); 528 | 529 | loaded: 530 | colorstep = 0; 531 | crusheractive = 0; 532 | unknown = 0; 533 | bosshealth = 999; 534 | SD_WaitSoundDone(); 535 | 536 | 537 | PlayLoop(); 538 | 539 | 540 | if (playstate == ex_died && gamestate.lives >= 0 && RespawnPlayer()) 541 | { 542 | playstate = ex_stillplaying; 543 | goto loaded; 544 | } 545 | 546 | gamestate.maxhealth = player->health; 547 | memset(&gamestate.keyitems, 0, sizeof(gamestate.keyitems)); 548 | gamestate.blueshard = false; 549 | gamestate.greenshard = false; 550 | gamestate.redshard = false; 551 | gamestate.cyanshard = false; 552 | gamestate.exitkey = false; 553 | gamestate.trianglekeys = 0; 554 | gamestate.specialkey = false; 555 | gamestate.radpill = false; 556 | gamestate.hasrobopal = false; 557 | gamestate.hostagerescued = false; 558 | gamestate.clips = 0; 559 | gamestate.ammoinclip = 0; 560 | gamestate.ammotype = AMMO_REGULAR; 561 | memset(&gamestate.explosives, 0, sizeof(gamestate.explosives)); 562 | 563 | colorstep = 0; 564 | 565 | VW_FixRefreshBuffer(); 566 | 567 | if (tedlevel) 568 | { 569 | if (playstate == ex_loadedgame) 570 | { 571 | goto loaded; 572 | } 573 | else if (playstate == ex_died) 574 | { 575 | goto restart; 576 | } 577 | else 578 | { 579 | TEDDeath(); 580 | } 581 | } 582 | 583 | switch (playstate) 584 | { 585 | case ex_resetgame: 586 | goto start; 587 | 588 | case ex_loadedgame: 589 | goto start; 590 | 591 | case ex_completed: 592 | #ifdef SHAREWARE 593 | // Shareware nag timer 594 | if (gamestate.mapon >= 4 && gamestate.mapon < 11 && !debugok) 595 | { 596 | nagtimer = (gamestate.mapon - 4) * 5 + 30; 597 | 598 | if (nagtimer > 60) 599 | { 600 | nagtimer = 60; 601 | } 602 | 603 | HelpScreens(); 604 | } 605 | #else 606 | if (copyprotectionfailed) 607 | { 608 | VW_FixRefreshBuffer(); 609 | US_CenterWindow(35, 8); 610 | PrintY += 2; 611 | 612 | US_CPrint(FILE_ID_MISSING); 613 | VW_UpdateScreen(); 614 | VW_WaitVBL(50); 615 | IN_ClearKeysDown(); 616 | IN_Ack(); 617 | RF_ForceRefresh(); 618 | 619 | goto abortGame; 620 | } 621 | #endif 622 | 623 | // Return from secret bonus level 624 | if (gamestate.mapon > 13) 625 | { 626 | switch (gamestate.mapon) 627 | { 628 | case 20: 629 | gamestate.mapon = 2; 630 | break; 631 | 632 | case 21: 633 | gamestate.mapon = 5; 634 | break; 635 | 636 | case 22: 637 | gamestate.mapon = 8; 638 | break; 639 | 640 | case 23: 641 | gamestate.mapon = 10; 642 | break; 643 | } 644 | } 645 | 646 | // Enter secret bonus level 647 | if (gamestate.secretlevelgem == true) 648 | { 649 | switch (gamestate.mapon) 650 | { 651 | case 2: 652 | ENTER_SECRET_LEVEL(20); 653 | break; 654 | 655 | case 5: 656 | ENTER_SECRET_LEVEL(21); 657 | break; 658 | 659 | case 8: 660 | ENTER_SECRET_LEVEL(22); 661 | break; 662 | 663 | case 10: 664 | ENTER_SECRET_LEVEL(23); 665 | break; 666 | } 667 | } 668 | 669 | // Advance to next level 670 | gamestate.mapon++; 671 | 672 | if (gamestate.mapon == 12) 673 | { 674 | // Game beaten! 675 | FreeGraphics(); 676 | RF_FixOfs(); 677 | VW_FixRefreshBuffer(); 678 | EpisodeEndScreens(); 679 | CheckHighScore(gamestate.score, 0); 680 | return; 681 | } 682 | 683 | if (storedemo && mapon == 2) 684 | { 685 | // Demo recording finished 686 | IN_ClearKeysDown(); 687 | return; 688 | } 689 | 690 | oldbufferofs = bufferofs; 691 | bufferofs = displayofs; 692 | US_CenterWindow(15, 2); 693 | PrintY += 2; 694 | US_CPrint("One moment...\n\n"); 695 | bufferofs = oldbufferofs; 696 | break; 697 | 698 | case ex_abortgame: 699 | abortGame: 700 | IN_ClearKeysDown(); 701 | StopMusic(); 702 | CA_SetAllPurge(); 703 | return; 704 | } 705 | 706 | if (gamestate.lives >= 0) 707 | { 708 | goto restart; 709 | } 710 | 711 | StopMusic(); 712 | CA_SetAllPurge(); 713 | GameOver(); 714 | CheckHighScore(gamestate.score, mapon); 715 | 716 | #undef ENTER_SECRET_LEVEL 717 | } 718 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /SRC/GRAPHBM1.H: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef __GFX_H__ 22 | #define __GFX_H__ 23 | 24 | //#include "VERSION.H" 25 | 26 | ////////////////////////////////////// 27 | // 28 | // Graphics .H file for .BM1 29 | // not IGRAB-ed :) 30 | // 31 | ////////////////////////////////////// 32 | 33 | // 34 | // Lump creation macros 35 | // 36 | 37 | #define START_LUMP(actualname, dummyname) actualname, dummyname=actualname-1, 38 | #define END_LUMP(actualname, dummyname) dummyname, actualname=dummyname-1, 39 | 40 | // 41 | // Amount of each data item 42 | // 43 | 44 | #define NUMCHUNKS NUMGRCHUNKS 45 | #define NUMFONT 2 46 | #define NUMFONTM 0 47 | #define NUMPICS 50 48 | #define NUMPICM 1 49 | #define NUMSPRITES 355 50 | #define NUMTILE8 144 51 | #define NUMTILE8M 36 52 | #define NUMTILE16 1512 53 | #define NUMTILE16M 2682 54 | #define NUMTILE32 0 55 | #define NUMTILE32M 0 56 | #define NUMEXTERNS 14 57 | 58 | // 59 | // File offsets for data items 60 | // 61 | #define STRUCTPIC 0 62 | #define STRUCTPICM 1 63 | #define STRUCTSPRITE 2 64 | 65 | #define STARTFONT 3 66 | #define STARTFONTM (STARTFONT+NUMFONT) 67 | #define STARTPICS (STARTFONTM+NUMFONTM) 68 | #define STARTPICM (STARTPICS+NUMPICS) 69 | #define STARTSPRITES (STARTPICM+NUMPICM) 70 | #define STARTTILE8 (STARTSPRITES+NUMSPRITES) 71 | #define STARTTILE8M (STARTTILE8+1) 72 | #define STARTTILE16 (STARTTILE8M+1) 73 | #define STARTTILE16M (STARTTILE16+NUMTILE16) 74 | #define STARTTILE32 (STARTTILE16M+NUMTILE16M) 75 | #define STARTTILE32M (STARTTILE32+NUMTILE32) 76 | #define STARTEXTERNS (STARTTILE32M+NUMTILE32M) 77 | 78 | typedef enum { 79 | LASTFONT=STARTPICS-1, 80 | 81 | // 82 | // PICS 83 | // 84 | 85 | START_LUMP(CONTROLS_LUMP_START, __CONTROLSSTART) 86 | CP_MAINMENU_PIC, // 5 87 | CP_NEWGAMEMENU_PIC, // 6 88 | CP_LOADMENU_PIC, // 7 89 | CP_SAVEMENU_PIC, // 8 90 | CP_CONFIGMENU_PIC, // 9 91 | CP_SOUNDMENU_PIC, // 10 92 | CP_MUSICMENU_PIC, // 11 93 | CP_KEYBOARDMENU_PIC, // 12 94 | CP_KEYMOVEMENT_PIC, // 13 95 | CP_KEYBUTTON_PIC, // 14 96 | CP_JOYSTICKMENU_PIC, // 15 97 | CP_OPTIONSMENU_PIC, // 16 98 | CP_QUIT_PIC, // 17 99 | CP_JOYSTICK_PIC, // 18 100 | CP_MENUSCREEN_PIC, // 19 101 | END_LUMP(CONTROLS_LUMP_END, __CONTROLSEND) 102 | 103 | TITLESHAREWARE_PIC, // 20 104 | H_HELP_PIC, // 21 105 | H_HAND_PIC, // 22 106 | H_FLASHARROW1_PIC, // 23 107 | H_FLASHARROW2_PIC, // 24 108 | H_TOPWINDOW_PIC, // 25 109 | H_LEFTWINDOW_PIC, // 26 110 | H_RIGHTWINDOW_PIC, // 27 111 | H_BOTTOMINFO_PIC, // 28 112 | H_ESC_PIC, // 29 113 | H_LARROW_PIC, // 30 114 | H_RARROW_PIC, // 31 115 | H_ENTER_PIC, // 32 116 | ENDOFTEXT_PIC, // 33 117 | H_VISA_PIC, // 34 118 | H_MC_PIC, // 35 119 | HOSTAGE1_PIC, // 36 120 | HOSTAGE2_PIC, // 37 121 | HOSTAGE3_PIC, // 38 122 | SNAKETALK_PIC, // 39 123 | H_ITEMS_PIC, // 40 124 | STORY1_PIC, // 41 125 | STORY2_PIC, // 42 126 | STORY3_PIC, // 43 127 | STORY4_PIC, // 44 128 | STORY5_PIC, // 45 129 | STORY6_PIC, // 46 130 | STORY7_PIC, // 47 131 | STORY8_PIC, // 48 132 | STORY9_PIC, // 49 133 | CREDITS_PIC, // 50 134 | PREVIEW_PIC, // 51 135 | TITLE_PIC, // 52 136 | NOTSHAREWARE_PIC, // 53 137 | TECHHELP_PIC, // 54 138 | 139 | CP_MENUMASK_PICM, // 55 140 | 141 | // 142 | // SPRITES 143 | // 144 | 145 | HANDCURSOR_SPR, // 56 146 | 147 | START_LUMP(PLAYER_LUMP_START, __PLAYERSTART) 148 | SHOT_EXPLODE1_SPR, // 57 149 | SHOT_EXPLODE2_SPR, // 58 150 | SMALL_FIRE1_SPR, // 59 151 | SMALL_FIRE2_SPR, // 60 152 | SMALL_FIRE3_SPR, // 61 153 | LASER_BLAST_BLUE_SPR, // 62 154 | LASER_BLAST_RED_SPR, // 63 155 | SUPER_BLAST_R_SPR, // 64 156 | SUPER_BLAST_L_SPR, // 65 157 | PLAYER_STANDING_R_SPR, // 66 158 | PLAYER_WALKING1_R_SPR, // 67 159 | PLAYER_WALKING2_R_SPR, // 68 160 | PLAYER_WALKING3_R_SPR, // 69 161 | PLAYER_WALKING4_R_SPR, // 70 162 | PLAYER_STANDING_L_SPR, // 71 163 | PLAYER_WALKING1_L_SPR, // 72 164 | PLAYER_WALKING2_L_SPR, // 73 165 | PLAYER_WALKING3_L_SPR, // 74 166 | PLAYER_WALKING4_L_SPR, // 75 167 | PLAYER_SHIELDED1_R_SPR, // 76 168 | PLAYER_SHIELDED2_R_SPR, // 77 169 | PLAYER_SHIELDED1_L_SPR, // 78 170 | PLAYER_SHIELDED2_L_SPR, // 79 171 | PLAYER_INTERACTING_SPR, // 80 172 | PLAYER_CLIMBING1_SPR, // 81 173 | PLAYER_CLIMBING2_SPR, // 82 174 | PLAYER_DYING1_SPR, // 83 175 | PLAYER_DYING2_SPR, // 84 176 | PLAYER_THROW1_R_SPR, // 85 177 | PLAYER_THROW2_R_SPR, // 86 178 | PLAYER_THROW1_L_SPR, // 87 179 | PLAYER_THROW2_L_SPR, // 88 180 | PLAYER_IN_AIR_THROW1_R_SPR, // 89 181 | PLAYER_IN_AIR_THROW2_R_SPR, // 90 182 | PLAYER_IN_AIR_THROW1_L_SPR, // 91 183 | PLAYER_IN_AIR_THROW2_L_SPR, // 92 184 | PLAYER_SHOOT1_R_SPR, // 93 185 | PLAYER_SHOOT2_R_SPR, // 94 186 | PLAYER_SHOOT1_L_SPR, // 95 187 | PLAYER_SHOOT2_L_SPR, // 96 188 | PLAYER_CROUCH_R_SPR, // 97 189 | PLAYER_CROUCH_SHOOT_R_SPR, // 98 190 | PLAYER_CROUCH_L_SPR, // 99 191 | PLAYER_CROUCH_SHOOT_L_SPR, // 100 192 | PLAYER_IN_AIR_R_SPR, // 101 193 | PLAYER_IN_AIR_SHOOT_R_SPR, // 102 194 | PLAYER_IN_AIR_L_SPR, // 103 195 | PLAYER_IN_AIR_SHOOT_L_SPR, // 104 196 | GRENADE_GREEN1_SPR, // 105 197 | GRENADE_GREEN2_SPR, // 106 198 | GRENADE_GREEN3_SPR, // 107 199 | GRENADE_GREEN4_SPR, // 108 200 | GRENADE_RED1_SPR, // 109 201 | GRENADE_RED2_SPR, // 110 202 | GRENADE_RED3_SPR, // 111 203 | GRENADE_RED4_SPR, // 112 204 | RUNNING_FIRE1_SPR, // 113 205 | RUNNING_FIRE2_SPR, // 114 206 | GRENADE_EXPLOSION1_SPR, // 115 207 | GRENADE_EXPLOSION2_SPR, // 116 208 | GRENADE_EXPLOSION3_SPR, // 117 209 | GRENADE_EXPLOSION4_SPR, // 118 210 | GRENADE_EXPLOSION5_SPR, // 119 211 | GRENADE_EXPLOSION6_SPR, // 120 212 | FIREBALL1_SPR, // 121 213 | FIREBALL2_SPR, // 122 214 | FIREBALL3_SPR, // 123 215 | FIREBALL4_SPR, // 124 216 | FIREBALL5_SPR, // 125 217 | FIREBALL6_SPR, // 126 218 | FIREBALL7_SPR, // 127 219 | FIREBALL8_SPR, // 128 220 | BULLET_IMPACT1_SPR, // 129 221 | BULLET_IMPACT2_SPR, // 130 222 | BULLET_IMPACT3_SPR, // 131 223 | GIBS1_SPR, // 132 224 | GIBS2_SPR, // 133 225 | GIBS_BONE1_SPR, // 134 226 | GIBS_BONE2_SPR, // 135 227 | GIBS_EYEBALL1_SPR, // 136 228 | GIBS_EYEBALL2_SPR, // 137 229 | GIBS_FLESH1_SPR, // 138 230 | GIBS_FLESH2_SPR, // 139 231 | PICKUP_GRENADE1_SPR, // 140 232 | PICKUP_GRENADE2_SPR, // 141 233 | PICKUP_GRENADE_RED1_SPR, // 142 234 | PICKUP_GRENADE_RED2_SPR, // 143 235 | PICKUP_GUN1_SPR, // 144 236 | PICKUP_GUN2_SPR, // 145 237 | METAL_DEBRIS1_SPR, // 146 238 | METAL_DEBRIS2_SPR, // 147 239 | METAL_DEBRIS3_SPR, // 148 240 | METAL_DEBRIS4_SPR, // 149 241 | METAL_DEBRIS5_SPR, // 150 242 | METAL_DEBRIS6_SPR, // 151 243 | METAL_DEBRIS7_SPR, // 152 244 | METAL_DEBRIS8_SPR, // 153 245 | PICKUP_KEYCARD1_SPR, // 154 246 | PICKUP_KEYCARD2_SPR, // 155 247 | PICKUP_KEY1_SPR, // 156 248 | PICKUP_KEY2_SPR, // 157 249 | BONUS_CHEMICALS1_1_SPR, // 158 250 | BONUS_CHEMICALS1_2_SPR, // 159 251 | BONUS_CHEMICALS2_1_SPR, // 160 252 | BONUS_CHEMICALS2_2_SPR, // 161 253 | BONUS_DEVICE1_SPR, // 162 254 | BONUS_DEVICE2_SPR, // 163 255 | BONUS_BOOK1_SPR, // 164 256 | BONUS_BOOK2_SPR, // 165 257 | PICKUP_LIFEGEM1_SPR, // 166 258 | PICKUP_LIFEGEM2_SPR, // 167 259 | PICKUP_HEALTH1_SPR, // 168 260 | PICKUP_HEALTH2_SPR, // 169 261 | PICKUP_NUKE1_SPR, // 170 262 | PICKUP_NUKE2_SPR, // 171 263 | PICKUP_RADPILL1_SPR, // 172 264 | PICKUP_RADPILL2_SPR, // 173 265 | PICKUP_INVINCIBILITY1_SPR, // 174 266 | PICKUP_INVINCIBILITY2_SPR, // 175 267 | BONUS_GEM1_1_SPR, // 176 268 | BONUS_GEM1_2_SPR, // 177 269 | BONUS_GEM2_1_SPR, // 178 270 | BONUS_GEM2_2_SPR, // 179 271 | PICKUP_SECRETLEVELGEM1_SPR, // 180 272 | PICKUP_SECRETLEVELGEM2_SPR, // 181 273 | BIG_EXPLOSION1_SPR, // 182 274 | BIG_EXPLOSION2_SPR, // 183 275 | BIG_EXPLOSION3_SPR, // 184 276 | PICKUP_SHARD_BLUE1_SPR, // 185 277 | PICKUP_SHARD_BLUE2_SPR, // 186 278 | PICKUP_SHARD_GREEN1_SPR, // 187 279 | PICKUP_SHARD_GREEN2_SPR, // 188 280 | PICKUP_SHARD_RED1_SPR, // 189 281 | PICKUP_SHARD_RED2_SPR, // 190 282 | PICKUP_SHARD_CYAN1_SPR, // 191 283 | PICKUP_SHARD_CYAN2_SPR, // 192 284 | PICKUP_EXTRALIFE1_SPR, // 193 285 | PICKUP_EXTRALIFE2_SPR, // 194 286 | BONUS_TAPE1_SPR, // 195 287 | BONUS_TAPE2_SPR, // 196 288 | BONUS_CALCULATOR1_SPR, // 197 289 | BONUS_CALCULATOR2_SPR, // 198 290 | ONE_UP_SPR, // 199 291 | POINTS_100_SPR, // 200 292 | POINTS_200_SPR, // 201 293 | POINTS_500_SPR, // 202 294 | POINTS_800_SPR, // 203 295 | POINTS_1000_SPR, // 204 296 | POINTS_1500_SPR, // 205 297 | POINTS_2000_SPR, // 206 298 | POINTS_5000_SPR, // 207 299 | POINTS_50000_SPR, // 208 300 | PICKUP_SPECIALKEY1_SPR, // 209 301 | PICKUP_SPECIALKEY2_SPR, // 210 302 | PICKUP_EXITKEY1_SPR, // 211 303 | PICKUP_EXITKEY2_SPR, // 212 304 | PICKUP_TRIANGLE1_SPR, // 213 305 | PICKUP_TRIANGLE2_SPR, // 214 306 | PICKUP_AMMO_PLASMA1_SPR, // 215 307 | PICKUP_AMMO_PLASMA2_SPR, // 216 308 | PICKUP_AMMO_SUPER1_SPR, // 217 309 | PICKUP_AMMO_SUPER2_SPR, // 218 310 | PICKUP_LANDMINES1_SPR, // 219 311 | PICKUP_LANDMINES2_SPR, // 220 312 | LANDMINE1_SPR, // 221 313 | LANDMINE2_SPR, // 222 314 | END_LUMP(PLAYER_LUMP_END, __PLAYEREND) 315 | 316 | START_LUMP(HOSTAGE_LUMP_START, __HOSTAGESTART) 317 | HOSTAGE1_1_SPR, // 223 318 | HOSTAGE1_2_SPR, // 224 319 | HOSTAGE2_1_SPR, // 225 320 | HOSTAGE2_2_SPR, // 226 321 | HOSTAGE3_1_SPR, // 227 322 | HOSTAGE3_2_SPR, // 228 323 | END_LUMP(HOSTAGE_LUMP_END, __HOSTAGEEND) 324 | 325 | START_LUMP(SLUG_LUMP_START, __SLUGSTART) 326 | SLUG_WALK1_L_SPR, // 229 327 | SLUG_WALK2_L_SPR, // 230 328 | SLUG_ATTACK_L_SPR, // 231 329 | SLUG_WALK1_R_SPR, // 232 330 | SLUG_WALK2_R_SPR, // 233 331 | SLUG_ATTACK_R_SPR, // 234 332 | END_LUMP(SLUG_LUMP_END, __SLUGEND) 333 | 334 | START_LUMP(UNUSED1_LUMP_START, __UNUSED1START) 335 | END_LUMP(UNUSED1_LUMP_END, __UNUSED1END) 336 | 337 | START_LUMP(BRAWLER_LUMP_START, __BRAWLERSTART) 338 | BRAWLER_STAND_L_SPR, // 235 339 | BRAWLER_STAND_R_SPR, // 236 340 | BRAWLER_WALK1_L_SPR, // 237 341 | BRAWLER_WALK2_L_SPR, // 238 342 | BRAWLER_WALK3_L_SPR, // 239 343 | BRAWLER_WALK4_L_SPR, // 240 344 | BRAWLER_ATTACK1_L_SPR, // 241 345 | BRAWLER_ATTACK2_L_SPR, // 242 346 | BRAWLER_WALK1_R_SPR, // 243 347 | BRAWLER_WALK2_R_SPR, // 244 348 | BRAWLER_WALK3_R_SPR, // 245 349 | BRAWLER_WALK4_R_SPR, // 246 350 | BRAWLER_ATTACK1_R_SPR, // 247 351 | BRAWLER_ATTACK2_R_SPR, // 248 352 | END_LUMP(BRAWLER_LUMP_END, __BRAWLEREND) 353 | 354 | START_LUMP(CEILWALKER_LUMP_START, __CEILWALKERSTART) 355 | CEILWALKER_WALK_CEIL1_L_SPR, // 249 356 | CEILWALKER_WALK_CEIL2_L_SPR, // 250 357 | CEILWALKER_WALK_CEIL3_L_SPR, // 251 358 | CEILWALKER_WALK_CEIL4_L_SPR, // 252 359 | CEILWALKER_FALL_L_SPR, // 253 360 | CEILWALKER_WALK_CEIL1_R_SPR, // 254 361 | CEILWALKER_WALK_CEIL2_R_SPR, // 255 362 | CEILWALKER_WALK_CEIL3_R_SPR, // 256 363 | CEILWALKER_WALK_CEIL4_R_SPR, // 257 364 | CEILWALKER_FALL_R_SPR, // 258 365 | CEILWALKER_WALK1_L_SPR, // 259 366 | CEILWALKER_WALK2_L_SPR, // 260 367 | CEILWALKER_WALK3_L_SPR, // 261 368 | CEILWALKER_WALK4_L_SPR, // 262 369 | CEILWALKER_WALK1_R_SPR, // 263 370 | CEILWALKER_WALK2_R_SPR, // 264 371 | CEILWALKER_WALK3_R_SPR, // 265 372 | CEILWALKER_WALK4_R_SPR, // 266 373 | END_LUMP(CEILWALKER_LUMP_END, __CEILWALKEREND) 374 | 375 | START_LUMP(BOMB_LUMP_START, __BOMBSTART) 376 | BOMB_WAIT_L_SPR, // 267 377 | BOMB_JUMP1_L_SPR, // 268 378 | BOMB_JUMP2_L_SPR, // 269 379 | BOMB_JUMP3_L_SPR, // 270 380 | BOMB_WAIT_R_SPR, // 271 381 | BOMB_JUMP1_R_SPR, // 272 382 | BOMB_JUMP2_R_SPR, // 273 383 | BOMB_JUMP3_R_SPR, // 274 384 | END_LUMP(BOMB_LUMP_END, __BOMBEND) 385 | 386 | START_LUMP(SPITSNAKE_LUMP_START, __SPITSNAKESTART) 387 | SPITSNAKE_WALK1_L_SPR, // 275 388 | SPITSNAKE_WALK2_L_SPR, // 276 389 | SPITSNAKE_WALK1_R_SPR, // 277 390 | SPITSNAKE_WALK2_R_SPR, // 278 391 | SPITSNAKE_ATTACK_L_SPR, // 279 392 | SPITSNAKE_ATTACK_R_SPR, // 280 393 | SPITSNAKE_SPIT1_L_SPR, // 281 394 | SPITSNAKE_SPIT2_L_SPR, // 282 395 | SPITSNAKE_SPIT1_R_SPR, // 283 396 | SPITSNAKE_SPIT2_R_SPR, // 284 397 | END_LUMP(SPITSNAKE_LUMP_END, __SPITSNAKEEND) 398 | 399 | START_LUMP(FIREIMP_LUMP_START, __FIREIMPSTART) 400 | FIREIMP_WALK1_L_SPR, // 285 401 | FIREIMP_WALK2_L_SPR, // 286 402 | FIREIMP_WALK3_L_SPR, // 287 403 | FIREIMP_WALK4_L_SPR, // 288 404 | FIREIMP_WALK1_R_SPR, // 289 405 | FIREIMP_WALK2_R_SPR, // 290 406 | FIREIMP_WALK3_R_SPR, // 291 407 | FIREIMP_WALK4_R_SPR, // 292 408 | FIREIMP_STAND_SPR, // 293 409 | END_LUMP(FIREIMP_LUMP_END, __FIREIMPEND) 410 | 411 | START_LUMP(GHOSTSLUG_LUMP_START, __GHOSTSLUGSTART) 412 | GHOSTSLUG1_L_SPR, // 294 413 | GHOSTSLUG2_L_SPR, // 295 414 | GHOSTSLUG1_R_SPR, // 296 415 | GHOSTSLUG2_R_SPR, // 297 416 | END_LUMP(GHOSTSLUG_LUMP_END, __GHOSTSLUGEND) 417 | 418 | START_LUMP(SEWERMUTANT_LUMP_START, __SEWERMUTANTSTART) 419 | SEWERMUTANT_WALK1_L_SPR, // 298 420 | SEWERMUTANT_WALK2_L_SPR, // 299 421 | SEWERMUTANT_ATTACK_L_SPR, // 300 422 | SEWERMUTANT_WALK1_R_SPR, // 301 423 | SEWERMUTANT_WALK2_R_SPR, // 302 424 | SEWERMUTANT_ATTACK_R_SPR, // 303 425 | SEWERMUTANT_SPIT1_SPR, // 304 426 | SEWERMUTANT_SPIT2_SPR, // 305 427 | END_LUMP(SEWERMUTANT_LUMP_END, __SEWERMUTANTEND) 428 | 429 | START_LUMP(SLIME_DROPPER_LUMP_START, __SLIME_DROPPERSTART) 430 | SLIME_DROPPER1_SPR, // 306 431 | SLIME_DROPPER2_SPR, // 307 432 | SLIME_DROPPER3_SPR, // 308 433 | SLIME_DROP1_SPR, // 309 434 | SLIME_DROP2_SPR, // 310 435 | SLIME_DROP3_SPR, // 311 436 | SLIME_DROP_SPLAT1_SPR, // 312 437 | SLIME_DROP_SPLAT2_SPR, // 313 438 | SLIME_DROP_SPLAT3_SPR, // 314 439 | SLIME_DROP_SPLAT4_SPR, // 315 440 | END_LUMP(SLIME_DROPPER_LUMP_END, __SLIME_DROPPEREND) 441 | 442 | START_LUMP(CRAWLSLIME_LUMP_START, __CRAWLSLIMESTART) 443 | CRAWLSLIME1_L_SPR, // 316 444 | CRAWLSLIME2_L_SPR, // 317 445 | CRAWLSLIME1_R_SPR, // 318 446 | CRAWLSLIME2_R_SPR, // 319 447 | CRAWLSLIME_STEPON_SPR, // 320 448 | END_LUMP(CRAWLSLIME_LUMP_END, __CRAWLSLIMEEND) 449 | 450 | START_LUMP(HEDGEHOG_LUMP_START, __HEDGEHOGSTART) 451 | HEDGEHOG_STAND_R_SPR, // 321 452 | HEDGEHOG_STAND_L_SPR, // 322 453 | HEDGEHOG_ROLL1_L_SPR, // 323 454 | HEDGEHOG_ROLL2_L_SPR, // 324 455 | HEDGEHOG_ROLL3_L_SPR, // 325 456 | HEDGEHOG_ROLL4_L_SPR, // 326 457 | HEDGEHOG_ROLL1_R_SPR, // 327 458 | HEDGEHOG_ROLL2_R_SPR, // 328 459 | HEDGEHOG_ROLL3_R_SPR, // 329 460 | HEDGEHOG_ROLL4_R_SPR, // 330 461 | END_LUMP(HEDGEHOG_LUMP_END, __HEDGEHOGEND) 462 | 463 | START_LUMP(UNUSED2_LUMP_START, __UNUSED2START) 464 | END_LUMP(UNUSED2_LUMP_END, __UNUSED2END) 465 | 466 | START_LUMP(SKULLMAN_LUMP_START, __SKULLMANSTART) 467 | SKULLMAN1_SPR, // 331 468 | SKULLMAN2_SPR, // 332 469 | SKULLMAN_HAND_L_SPR, // 333 470 | SKULLMAN_HAND_R_SPR, // 334 471 | SKULLMAN_HAND_ATTACK1_SPR, // 335 472 | SKULLMAN_HAND_ATTACK2_SPR, // 336 473 | END_LUMP(SKULLMAN_LUMP_END, __SKULLMANEND) 474 | 475 | START_LUMP(MANGLE_LUMP_START, __MANGLESTART) 476 | MANGLE_HOLOGRAM1_SPR, // 337 477 | MANGLE_HOLOGRAM2_SPR, // 338 478 | MANGLE_HOLOGRAM3_SPR, // 339 479 | MANGLE_HOLOGRAM_FADE1_SPR, // 340 480 | MANGLE_HOLOGRAM_FADE2_SPR, // 341 481 | MANGLE_HOLOGRAM_FADE3_SPR, // 342 482 | MANGLE_HOLOGRAM_ATTACK_SPR, // 343 483 | MANGLE_TYPING1_SPR, // 344 484 | MANGLE_TYPING2_SPR, // 345 485 | MANGLE_DEFEATED_SPR, // 346 486 | MANGLE_MONSTER1_L_SPR, // 347 487 | MANGLE_MONSTER2_L_SPR, // 348 488 | MANGLE_MONSTER1_R_SPR, // 349 489 | MANGLE_MONSTER2_R_SPR, // 350 490 | END_LUMP(MANGLE_LUMP_END, __MANGLEEND) 491 | 492 | START_LUMP(HELICOPTER_LUMP_START, __HELICOPTERSTART) 493 | HELICOPTER1_SPR, // 351 494 | HELICOPTER2_SPR, // 352 495 | PARACHUTEBOT_FALLING_L_SPR, // 353 496 | PARACHUTEBOT_FALLING_R_SPR, // 354 497 | PARACHUTEBOT_WALK1_L_SPR, // 355 498 | PARACHUTEBOT_WALK2_L_SPR, // 356 499 | PARACHUTEBOT_WALK1_R_SPR, // 357 500 | PARACHUTEBOT_WALK2_R_SPR, // 358 501 | END_LUMP(HELICOPTER_LUMP_END, __HELICOPTEREND) 502 | 503 | START_LUMP(RESPAWN_BEACON_LUMP_START, __RESPAWN_BEACONSTART) 504 | RESPAWN_BEACON_INACTIVE_SPR, // 359 505 | RESPAWN_BEACON_ACTIVE1_SPR, // 360 506 | RESPAWN_BEACON_ACTIVE2_SPR, // 361 507 | RESPAWN_BEACON_ACTIVE3_SPR, // 362 508 | RESPAWN_BEACON_ACTIVE4_SPR, // 363 509 | END_LUMP(RESPAWN_BEACON_LUMP_END, __RESPAWN_BEACONEND) 510 | 511 | START_LUMP(BOUNCEBOT_LUMP_START, __BOUNCEBOTSTART) 512 | BOUNCEBOT1_SPR, // 364 513 | BOUNCEBOT2_SPR, // 365 514 | BOUNCEBOT3_SPR, // 366 515 | BOUNCEBOT4_SPR, // 367 516 | BOUNCEBOT5_SPR, // 368 517 | END_LUMP(BOUNCEBOT_LUMP_END, __BOUNCEBOTEND) 518 | 519 | START_LUMP(PLATFORM_LUMP_START, __PLATFORMSTART) 520 | PLATFORM_SPR, // 369 521 | END_LUMP(PLATFORM_LUMP_END, __PLATFORMEND) 522 | 523 | START_LUMP(UNUSED3_LUMP_START, __UNUSED3START) 524 | END_LUMP(UNUSED3_LUMP_END, __UNUSED3END) 525 | 526 | START_LUMP(TURRET_LUMP_START, __TURRETSTART) 527 | TURRET_IDLE_L_SPR, // 370 528 | TURRET_READY_L_SPR, // 371 529 | TURRET_SHOOT_L_SPR, // 372 530 | TURRET_IDLE_R_SPR, // 373 531 | TURRET_READY_R_SPR, // 374 532 | TURRET_SHOOT_R_SPR, // 375 533 | END_LUMP(TURRET_LUMP_END, __TURRETEND) 534 | 535 | START_LUMP(LASERGUNNER_LUMP_START, __LASERGUNNERSTART) 536 | LASERGUNNER_IDLE_L_SPR, // 376 537 | LASERGUNNER_SHOOT_L_SPR, // 377 538 | LASERGUNNER_IDLE_R_SPR, // 378 539 | LASERGUNNER_SHOOT_R_SPR, // 379 540 | END_LUMP(LASERGUNNER_LUMP_END, __LASERGUNNEREND) 541 | 542 | START_LUMP(FORCEFIELD_BOT_LUMP_START, __FORCEFIELD_BOTSTART) 543 | FORCEFIELD_BOT1_SPR, // 380 544 | FORCEFIELD_BOT2_SPR, // 381 545 | FORCEFIELD_BOT3_SPR, // 382 546 | FORCEFIELD_BOT4_SPR, // 383 547 | END_LUMP(FORCEFIELD_BOT_LUMP_END, __FORCEFIELD_BOTEND) 548 | 549 | START_LUMP(SPARKSHOT_LUMP_START, __SPARKSHOTSTART) 550 | SPARKSHOT1_SPR, // 384 551 | SPARKSHOT2_SPR, // 385 552 | END_LUMP(SPARKSHOT_LUMP_END, __SPARKSHOTEND) 553 | 554 | START_LUMP(PUSHBLOCK_LUMP_START, __PUSHBLOCKSTART) 555 | PUSHBLOCK_SPR, // 386 556 | END_LUMP(PUSHBLOCK_LUMP_END, __PUSHBLOCKEND) 557 | 558 | START_LUMP(ROBOPAL_LUMP_START, __ROBOPALSTART) 559 | ROBOPAL1_SPR, // 387 560 | ROBOPAL2_SPR, // 388 561 | ROBOPAL_TELEPORT1_SPR, // 389 562 | ROBOPAL_TELEPORT2_SPR, // 390 563 | ROBOPAL_SHOT1_R_SPR, // 391 564 | ROBOPAL_SHOT2_R_SPR, // 392 565 | ROBOPAL_SHOT1_L_SPR, // 393 566 | ROBOPAL_SHOT2_L_SPR, // 394 567 | ROCKET_IMPACT1_SPR, // 395 568 | ROCKET_IMPACT2_SPR, // 396 569 | END_LUMP(ROBOPAL_LUMP_END, __ROBOPALEND) 570 | 571 | START_LUMP(CRUSHERBLOCK_LUMP_START, __CRUSHERBLOCKSTART) 572 | CRUSHERBLOCK_SPR, // 397 573 | END_LUMP(CRUSHERBLOCK_LUMP_END, __CRUSHERBLOCKEND) 574 | 575 | START_LUMP(FALLINGBLOCK_LUMP_START, __FALLINGBLOCKSTART) 576 | FALLINGBLOCK_SPR, // 398 577 | END_LUMP(FALLINGBLOCK_LUMP_END, __FALLINGBLOCKEND) 578 | 579 | START_LUMP(TANKBOT_LUMP_START, __TANKBOTSTART) 580 | TANKBOT1_SPR, // 399 581 | TANKBOT2_SPR, // 400 582 | TANKBOT_SHOOT_SPR, // 401 583 | TANKBOT_BIG_SHOT_SPR, // 402 584 | TANKBOT_SHOT_FLYING_SPR, // 403 585 | TANKBOT_SHOT_LANDING_SPR, // 404 586 | END_LUMP(TANKBOT_LUMP_END, __TANKBOTEND) 587 | 588 | SCOREBOX_SPR, // 405 589 | 590 | START_LUMP(INTRO_LUMP_START, __INTROSTART) 591 | APOGEELOGO_SPR, // 406 592 | ASTEROID1_SPR, // 407 593 | ASTEROID2_SPR, // 408 594 | ASTEROID3_SPR, // 409 595 | ASTEROID4_SPR, // 410 596 | END_LUMP(INTRO_LUMP_END, __INTROEND) 597 | 598 | // 599 | // TILES (these don't need names) 600 | // 601 | 602 | LASTTILE=STARTEXTERNS-1, 603 | 604 | // 605 | // EXTERNS 606 | // 607 | 608 | //texts 609 | T_SCORESART, // 4607 610 | T_CONTRART, // 4608 611 | T_ENDART, // 4609 612 | T_HELPART, // 4610 613 | T_STORYART, // 4611 614 | T_ORDERART, // 4612 615 | T_NAGSCREENART, // 4613 616 | 617 | //demos 618 | DEMO0, // 4614 619 | DEMO1, // 4615 620 | DEMO2, // 4616 621 | DEMO3, // 4617 622 | DEMO4, // 4618 623 | 624 | ORDERSCREEN, // 4619 625 | OUTOFMEM, // 4620 626 | 627 | NUMGRCHUNKS 628 | } graphicnums; 629 | 630 | #undef START_LUMP 631 | #undef END_LUMP 632 | 633 | #endif //__GFX_H__ 634 | 635 | -------------------------------------------------------------------------------- /SRC/BM_TEXT.C: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2024 Nikolai Wuttke-Hohendorf 2 | * 3 | * Based on reconstructed Commander Keen 4-6 Source Code 4 | * Copyright (C) 2021 K1n9_Duk3 5 | * 6 | * This file is primarily based on: 7 | * Wolfenstein 3-D Source Code 8 | * Copyright (C) 1992 id Software 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License along 21 | * with this program; if not, write to the Free Software Foundation, Inc., 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 | */ 24 | 25 | #include "BM_DEF.H" 26 | 27 | /* 28 | ============================================================================= 29 | 30 | TEXT FORMATTING COMMANDS 31 | ------------------------ 32 | ^C Change text color 33 | ^E[enter] End of layout (all pages) 34 | ^G,,[enter] Draw a graphic and push margins 35 | ^P[enter] start new page, must be the first chars in a layout 36 | ^L,[ENTER] Locate to a specific spot, x in pixels, y in lines 37 | 38 | ============================================================================= 39 | */ 40 | 41 | /* 42 | ============================================================================= 43 | 44 | LOCAL CONSTANTS 45 | 46 | ============================================================================= 47 | */ 48 | 49 | #define BACKCOLOR BLUE 50 | 51 | #define WORDLIMIT 80 52 | #define FONTHEIGHT 10 53 | #define TOPMARGIN 10 54 | #define BOTTOMMARGIN 10 55 | #define LEFTMARGIN 10 56 | #define RIGHTMARGIN 10 57 | #define PICMARGIN 8 58 | #define SPACEWIDTH 7 59 | #define TEXTROWS ((200-TOPMARGIN-BOTTOMMARGIN)/FONTHEIGHT) 60 | #define SCREENPIXWIDTH 320 61 | #define SCREENMID (SCREENPIXWIDTH/2) 62 | 63 | /* 64 | ============================================================================= 65 | 66 | LOCAL VARIABLES 67 | 68 | ============================================================================= 69 | */ 70 | 71 | boolean nagscreenshown = false; 72 | 73 | Sint16 pagenum,numpages; 74 | Uint16 leftmargin[TEXTROWS],rightmargin[TEXTROWS]; 75 | char far *text; 76 | Uint16 rowon; 77 | Sint16 picx,picy,picnum,picdelay; 78 | boolean layoutdone; 79 | 80 | Sint16 myhelpmenupos; 81 | 82 | 83 | //=========================================================================== 84 | 85 | void ShowHelpMessage(char far* msg) 86 | { 87 | if (!helpmessages || DemoMode) { return; } 88 | 89 | VW_FixRefreshBuffer(); 90 | 91 | US_CenterWindow(35, 2); 92 | PrintY += 2; 93 | US_CPrint(msg); 94 | 95 | VW_UpdateScreen(); 96 | VW_WaitVBL(50); 97 | IN_ClearKeysDown(); 98 | IN_Ack(); 99 | RF_ForceRefresh(); 100 | } 101 | 102 | 103 | /* 104 | ===================== 105 | = 106 | = RipToEOL 107 | = 108 | ===================== 109 | */ 110 | 111 | void RipToEOL(void) 112 | { 113 | while (*text++ != '\n'); 114 | } 115 | 116 | 117 | /* 118 | ===================== 119 | = 120 | = ParseNumber 121 | = 122 | ===================== 123 | */ 124 | 125 | Sint16 ParseNumber(void) 126 | { 127 | char c, buffer[80]; 128 | char *bufptr; 129 | 130 | // 131 | // scan until a number is found 132 | // 133 | c = *text; 134 | while (c < '0' || c > '9') 135 | c = *++text; 136 | 137 | // 138 | // copy the number out 139 | // 140 | bufptr = buffer; 141 | do 142 | { 143 | *bufptr = c; 144 | bufptr++; 145 | text++; 146 | c = *text; 147 | } while (c >= '0' && c <= '9'); 148 | *bufptr = 0; 149 | 150 | return atoi(buffer); 151 | } 152 | 153 | 154 | /* 155 | ===================== 156 | = 157 | = ParsePicCommand 158 | = 159 | = Call with text pointing just after a ^P 160 | = Upon exit text points to the start of next line 161 | = 162 | ===================== 163 | */ 164 | 165 | void ParsePicCommand(void) 166 | { 167 | picy = ParseNumber(); 168 | picx = ParseNumber(); 169 | picnum = ParseNumber(); 170 | RipToEOL(); 171 | } 172 | 173 | void ParseTimedCommand(void) 174 | { 175 | picy = ParseNumber(); 176 | picx = ParseNumber(); 177 | picnum = ParseNumber(); 178 | picdelay = ParseNumber(); 179 | RipToEOL(); 180 | } 181 | 182 | /* 183 | ===================== 184 | = 185 | = TimedPicCommand 186 | = 187 | = Call with text pointing just after a ^P 188 | = Upon exit text points to the start of next line 189 | = 190 | ===================== 191 | */ 192 | 193 | void TimedPicCommand(void) 194 | { 195 | ParseTimedCommand(); 196 | 197 | // 198 | // update the screen, and wait for time delay 199 | // 200 | VW_WaitVBL(1); 201 | VW_ScreenToScreen(bufferofs, displayofs, 40, 200); 202 | 203 | // 204 | // wait for time 205 | // 206 | TimeCount = 0; 207 | while (picdelay > TimeCount) 208 | ; 209 | 210 | // 211 | // draw pic 212 | // 213 | VWB_DrawPic(picx & ~7, picy, picnum); 214 | } 215 | 216 | 217 | /* 218 | ===================== 219 | = 220 | = HandleCommand 221 | = 222 | ===================== 223 | */ 224 | 225 | void HandleCommand(void) 226 | { 227 | Sint16 i,margin,top,bottom; 228 | Sint16 picwidth,picheight,picmid; 229 | 230 | switch (toupper(*(++text))) 231 | { 232 | case 'B': 233 | picy = ParseNumber(); 234 | picx = ParseNumber(); 235 | picwidth = ParseNumber(); 236 | picheight = ParseNumber(); 237 | VWB_Bar(picx, picy, picwidth, picheight, BACKCOLOR); 238 | RipToEOL(); 239 | break; 240 | 241 | case 'P': // ^P is start of next page, ^E is end of file 242 | case 'E': 243 | layoutdone = true; 244 | text--; 245 | break; 246 | 247 | case 'C': // ^c changes text color 248 | i = toupper(*(++text)); 249 | if (i >= '0' && i <= '9') 250 | { 251 | fontcolor = i + 0 - '0'; 252 | } 253 | else if (i >= 'A' && i <= 'F') 254 | { 255 | fontcolor = i + 10 - 'A'; 256 | } 257 | fontcolor ^= BACKCOLOR; 258 | text++; 259 | break; 260 | 261 | case 'L': 262 | py = ParseNumber(); 263 | rowon = (py - FONTHEIGHT)/FONTHEIGHT; 264 | py = rowon * FONTHEIGHT + FONTHEIGHT; 265 | px = ParseNumber(); 266 | while (*(text++) != '\n') // scan to end of line 267 | ; 268 | break; 269 | 270 | case 'T': // ^Tyyy,xxx,ppp,ttt waits ttt tics, then draws pic 271 | TimedPicCommand(); 272 | break; 273 | 274 | case 'G': // ^Gyyy,xxx,ppp draws graphic 275 | ParsePicCommand(); 276 | VWB_DrawPic(picx & ~7, picy, picnum); 277 | picwidth = pictable[picnum-STARTPICS].width * BYTEPIXELS; 278 | picheight = pictable[picnum-STARTPICS].height; 279 | picmid = picx + picwidth/2; 280 | // 281 | // adjust margins 282 | // 283 | if (picmid > SCREENMID) 284 | { 285 | margin = picx-PICMARGIN; // new right margin 286 | } 287 | else 288 | { 289 | margin = picx+picwidth+PICMARGIN; // new left margin 290 | } 291 | top = (picy-TOPMARGIN)/FONTHEIGHT; 292 | if (top < 0) 293 | { 294 | top = 0; 295 | } 296 | bottom = (picy+picheight-TOPMARGIN)/FONTHEIGHT; 297 | if (bottom >= TEXTROWS) 298 | { 299 | bottom = TEXTROWS-1; 300 | } 301 | 302 | for (i=top; i<=bottom; i++) 303 | { 304 | if (picmid > SCREENMID) 305 | { 306 | rightmargin[i] = margin; 307 | } 308 | else 309 | { 310 | leftmargin[i] = margin; 311 | } 312 | } 313 | 314 | // 315 | // adjust this line if needed 316 | // 317 | if (leftmargin[rowon] > px) 318 | { 319 | px = leftmargin[rowon]; 320 | } 321 | break; 322 | } 323 | } 324 | 325 | 326 | /* 327 | ===================== 328 | = 329 | = NewLine 330 | = 331 | ===================== 332 | */ 333 | 334 | void NewLine(void) 335 | { 336 | char c; 337 | 338 | if (++rowon == TEXTROWS) 339 | { 340 | // 341 | // overflowed the page, so skip until next page break 342 | // 343 | layoutdone = true; 344 | do 345 | { 346 | if (*text == '^') 347 | { 348 | c = toupper(text[1]); 349 | if (c == 'E' || c == 'P') 350 | { 351 | layoutdone = true; 352 | return; 353 | } 354 | } 355 | text++; 356 | } while (1); 357 | } 358 | px = leftmargin[rowon]; 359 | py += FONTHEIGHT; 360 | } 361 | 362 | 363 | /* 364 | ===================== 365 | = 366 | = HandleCtrls 367 | = 368 | ===================== 369 | */ 370 | 371 | void HandleCtrls(void) 372 | { 373 | char c; 374 | 375 | c = *(text++); // get the character and advance 376 | 377 | if (c == '\n') 378 | { 379 | NewLine(); 380 | return; 381 | } 382 | } 383 | 384 | /* 385 | ===================== 386 | = 387 | = HandleWord 388 | = 389 | ===================== 390 | */ 391 | 392 | void HandleWord(void) 393 | { 394 | Uint16 wwidth, wheight, newpos, wordindex; 395 | char word[WORDLIMIT]; 396 | 397 | // 398 | // copy the next word into [word] 399 | // 400 | word[0] = *(text++); 401 | wordindex = 1; 402 | while (*text > ' ') 403 | { 404 | word[wordindex] = *(text++); 405 | if (++wordindex == WORDLIMIT) 406 | { 407 | Quit("PageLayout: Word limit exceeded"); 408 | } 409 | } 410 | word[wordindex] = 0; // stick a null at end for C 411 | 412 | // 413 | // see if it fits on this line 414 | // 415 | VW_MeasurePropString(word, &wwidth, &wheight); 416 | 417 | while (rightmargin[rowon] < px+wwidth) 418 | { 419 | NewLine(); 420 | if (layoutdone) 421 | { 422 | return; // overflowed page 423 | } 424 | } 425 | 426 | // 427 | // print it 428 | // 429 | newpos = px+wwidth; 430 | VWB_DrawPropString(word); 431 | px = newpos; 432 | 433 | // 434 | // suck up any extra spaces 435 | // 436 | while (*text == ' ') 437 | { 438 | px += SPACEWIDTH; 439 | text++; 440 | } 441 | } 442 | 443 | 444 | static void DrawHighScores_HelpMenu(void) 445 | { 446 | HighScore *entry; 447 | char* bufptr; 448 | 449 | Sint16 oldcolor; 450 | Uint16 i; 451 | Uint16 width, height; 452 | char buf[16]; 453 | 454 | oldcolor = fontcolor; 455 | fontcolor = WHITE; 456 | 457 | for (i=0, entry=&Scores[0]; iname); 462 | 463 | ultoa(entry->score, buf, 10); 464 | 465 | for (bufptr=buf; *bufptr; bufptr++) 466 | { 467 | *bufptr = *bufptr + 81; 468 | } 469 | 470 | USL_MeasureString(buf, &width, &height); 471 | PrintX = HIGHSCORE_RIGHT - width; 472 | US_Print(buf); 473 | } 474 | 475 | fontcolor = oldcolor; 476 | } 477 | 478 | 479 | static void DrawNagScreenTimer(void) 480 | { 481 | Sint16 oldcolor; 482 | oldcolor = fontcolor; 483 | 484 | VWB_DrawPic(16, 176, H_BOTTOMINFO_PIC); 485 | 486 | strcpy(str, "Timer= "); 487 | 488 | if (nagtimer <= 0) 489 | { 490 | nagtimer = -1; 491 | strcat(str, "GO!"); 492 | nagscreenshown = true; 493 | SD_PlaySound(SND_BEACONACTIVE); 494 | } 495 | else 496 | { 497 | itoa(nagtimer, str2, 10); 498 | strcat(str, str2); 499 | SD_PlaySound(SND_NAGTIMERTICK); 500 | } 501 | 502 | fontcolor = LIGHTMAGENTA; 503 | py = 186; 504 | px = 218; 505 | 506 | VWB_DrawPropString(str); 507 | 508 | fontcolor = oldcolor; 509 | } 510 | 511 | /* 512 | ===================== 513 | = 514 | = PageLayout 515 | = 516 | = Clears the screen, draws the pics on the page, and word wraps the text. 517 | = Returns a pointer to the terminating command 518 | = 519 | ===================== 520 | */ 521 | 522 | void PageLayout(boolean shownumber) 523 | { 524 | Sint16 oldcolor, i; 525 | char c; 526 | 527 | oldcolor = fontcolor; 528 | 529 | fontcolor = YELLOW^BACKCOLOR; 530 | 531 | // 532 | // clear the screen 533 | // 534 | VWB_Bar(0, 0, 320, 200, BACKCOLOR); 535 | VWB_DrawPic( 16, 0, H_TOPWINDOW_PIC); 536 | VWB_DrawPic( 0, 0, H_LEFTWINDOW_PIC); 537 | VWB_DrawPic(304, 0, H_RIGHTWINDOW_PIC); 538 | if (shownumber) 539 | { 540 | VWB_DrawPic(16, 176, H_BOTTOMINFO_PIC); 541 | } 542 | else 543 | { 544 | VWB_DrawPic(16, 192, H_TOPWINDOW_PIC); 545 | } 546 | 547 | for (i=0; i 4) 738 | { 739 | myhelpmenupos = 4; 740 | } 741 | VWB_DrawPic(56, 24*myhelpmenupos+56, H_HAND_PIC); 742 | VW_UpdateScreen(); 743 | VWB_Bar(56, 24*myhelpmenupos+56, 31, 24, BACKCOLOR); 744 | IN_ReadControl(0, &control); 745 | IN_ReadCursor(&cursor); 746 | if (LastScan) 747 | { 748 | key = LastScan; 749 | IN_ClearKeysDown(); 750 | switch (key) 751 | { 752 | case sc_UpArrow: 753 | myhelpmenupos--; 754 | break; 755 | case sc_DownArrow: 756 | myhelpmenupos++; 757 | break; 758 | case sc_Enter: 759 | VW_ClearVideo(BACKCOLOR); 760 | return myhelpmenupos; 761 | case sc_Escape: 762 | VW_ClearVideo(BACKCOLOR); 763 | return -1; 764 | } 765 | } 766 | ydelta += cursor.y; 767 | if (cursor.button0 || cursor.button1 || control.button0 || control.button1) 768 | { 769 | VW_ClearVideo(BACKCOLOR); 770 | return myhelpmenupos; 771 | } 772 | if (ydelta < -40) 773 | { 774 | ydelta += 40; 775 | myhelpmenupos--; 776 | } 777 | else if (ydelta > 40) 778 | { 779 | ydelta -= 40; 780 | myhelpmenupos++; 781 | } 782 | } while (1); 783 | } 784 | 785 | /* 786 | ================= 787 | = 788 | = HelpScreens 789 | = 790 | ================= 791 | */ 792 | void HelpScreens(void) 793 | { 794 | static Uint16 layouttable[] = 795 | { 796 | T_ORDERART, 797 | T_HELPART, 798 | T_STORYART, 799 | T_CONTRART, 800 | T_SCORESART, 801 | T_NAGSCREENART 802 | }; 803 | 804 | Uint16 olddisplayofs, oldbufferofs, oldfontnumber; 805 | Sint16 pos; 806 | Uint16 oldmusic; 807 | boolean newpage; 808 | register Uint16 temp; 809 | 810 | oldfontnumber = fontnumber; 811 | olddisplayofs = displayofs; 812 | oldbufferofs = bufferofs; 813 | fontnumber = 0; 814 | oldmusic = curmusic; 815 | 816 | EGAMAPMASK(15); 817 | 818 | CA_UpLevel(); 819 | CA_SetGrPurge(); 820 | VW_ClearVideo(BACKCOLOR); 821 | 822 | RF_FixOfs(); 823 | bufferofs = 0; 824 | displayofs = 0x8000; 825 | VW_SetScreen(displayofs, 0); 826 | 827 | StartMusic(HELPSCREENSMUSIC); 828 | TimeCount = 0; 829 | nagscreenshown = false; 830 | 831 | do 832 | { 833 | if (nagtimer == -1) 834 | { 835 | pos = HelpMenu(); 836 | } 837 | else 838 | { 839 | pos = 5; 840 | } 841 | 842 | if (pos == 4) 843 | { 844 | showmenuhighscores = true; 845 | } 846 | 847 | VW_ClearVideo(BACKCOLOR); 848 | 849 | if (pos == -1) 850 | { 851 | CA_DownLevel(); 852 | IN_ClearKeysDown(); 853 | bufferofs = oldbufferofs; 854 | displayofs = olddisplayofs; 855 | fontnumber = oldfontnumber; 856 | VW_ClearVideo(BACKCOLOR); 857 | RF_FixOfs(); 858 | 859 | SD_FadeOutMusic(); 860 | while (SD_MusicPlaying()); 861 | 862 | StopMusic(); 863 | StartMusic(oldmusic); 864 | return; 865 | } 866 | 867 | pos = layouttable[pos]; 868 | CA_CacheGrChunk(pos); 869 | text = grsegs[pos]; 870 | CacheLayoutGraphics(); 871 | 872 | newpage = true; 873 | while (true) 874 | { 875 | if (newpage) 876 | { 877 | newpage = false; 878 | PageLayout(true); 879 | 880 | if (showmenuhighscores == true) 881 | { 882 | DrawHighScores_HelpMenu(); 883 | showmenuhighscores = false; 884 | } 885 | 886 | VW_SetScreen(bufferofs, 0); 887 | temp = displayofs; 888 | displayofs = bufferofs; 889 | bufferofs = temp; 890 | } 891 | 892 | LastScan = 0; 893 | 894 | // 895 | // Shareware episode nag timer 896 | // 897 | while (!LastScan) 898 | { 899 | if (TimeCount >= 70 && nagtimer != -1) 900 | { 901 | LastScan = sc_Bad - 1; 902 | } 903 | } 904 | 905 | if (TimeCount >= 70 && nagtimer > -1) 906 | { 907 | temp = displayofs; 908 | displayofs = bufferofs; 909 | bufferofs = temp; 910 | 911 | TimeCount = 0; 912 | DrawNagScreenTimer(); 913 | 914 | VW_SetScreen(bufferofs, 0); 915 | 916 | temp = displayofs; 917 | displayofs = bufferofs; 918 | bufferofs = temp; 919 | 920 | if (nagtimer >= 0) 921 | { 922 | nagtimer--; 923 | } 924 | } 925 | 926 | switch (LastScan) 927 | { 928 | case sc_UpArrow: 929 | case sc_LeftArrow: 930 | case sc_PgUp: 931 | if (pagenum > 1) 932 | { 933 | BackPage(); 934 | BackPage(); 935 | newpage = true; 936 | } 937 | break; 938 | 939 | case sc_DownArrow: 940 | case sc_RightArrow: 941 | case sc_PgDn: 942 | if (pagenum < numpages) 943 | { 944 | newpage = true; 945 | } 946 | break; 947 | 948 | case sc_Escape: 949 | if (nagtimer == -1) 950 | goto stopLoop; 951 | break; 952 | } 953 | } 954 | 955 | stopLoop: 956 | MM_FreePtr(&grsegs[pos]); 957 | IN_ClearKeysDown(); 958 | 959 | if (nagscreenshown == true) 960 | { 961 | nagscreenshown = false; 962 | 963 | CA_DownLevel(); 964 | IN_ClearKeysDown(); 965 | bufferofs = oldbufferofs; 966 | displayofs = olddisplayofs; 967 | fontnumber = oldfontnumber; 968 | VW_ClearVideo(BACKCOLOR); 969 | RF_FixOfs(); 970 | 971 | SD_FadeOutMusic(); 972 | while (SD_MusicPlaying()); 973 | 974 | StopMusic(); 975 | break; 976 | } 977 | } while (true); 978 | 979 | while (false); 980 | } 981 | 982 | 983 | //=========================================================================== 984 | 985 | /* 986 | ================= 987 | = 988 | = EpisodeEndScreens 989 | = 990 | ================= 991 | */ 992 | void EpisodeEndScreens(void) 993 | { 994 | char _seg *textseg; 995 | Sint16 i; 996 | 997 | VW_ClearVideo(BACKCOLOR); 998 | RF_FixOfs(); 999 | CA_UpLevel(); 1000 | CA_SetGrPurge(); 1001 | CA_CacheGrChunk(H_FLASHARROW2_PIC); 1002 | CA_CacheGrChunk(H_FLASHARROW1_PIC); 1003 | 1004 | CA_CacheGrChunk(T_ENDART); 1005 | textseg = grsegs[T_ENDART]; 1006 | 1007 | text = textseg; 1008 | CacheLayoutGraphics(); 1009 | 1010 | StartMusic(ENDINGMUSIC); 1011 | 1012 | while (pagenum < numpages) 1013 | { 1014 | PageLayout(false); 1015 | IN_ClearKeysDown(); 1016 | VW_SetScreen(bufferofs, 0); 1017 | 1018 | do 1019 | { 1020 | VWB_DrawPic(298, 184, H_FLASHARROW1_PIC); 1021 | for (i=0; i