[submodule "16/abrashbb"]
path = 16/abrashbb
url = https://github.com/jeffpar/abrash-black-book.git
+[submodule "16/keen4-6"]
+ path = 16/keen4-6
+ url = https://github.com/sparky4/keen4-6.git
--- /dev/null
+Subproject commit 287b78e38f9e8adff78100e0a95227ac926540ed
+++ /dev/null
-; Reconstructed Commander Keen 4-6 Source Code\r
-; Copyright (C) 2021 K1n9_Duk3\r
-;\r
-; This file is primarily based on:\r
-; Catacomb 3-D Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-;=================================\r
-;\r
-; EGA view manager routines\r
-;\r
-;=================================\r
-\r
-;============================================================================\r
-;\r
-; All EGA drawing routines that write out words need to have alternate forms\r
-; for starting on even and odd addresses, because writing a word at segment\r
-; offset 0xffff causes an exception! To work around this, write a single\r
-; byte out to make the address even, so it wraps cleanly at the end.\r
-;\r
-; All of these routines assume read/write mode 0, and will allways return\r
-; in that state.\r
-; The direction flag should be clear\r
-; readmap/writemask is left in an undefined state\r
-;\r
-;============================================================================\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Plot (int x,y,color)\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-plotpixels db 128,64,32,16,8,4,2,1\r
-\r
-CODESEG\r
-\r
-PROC VW_Plot x:WORD, y:WORD, color:WORD\r
-PUBLIC VW_Plot\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[y]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov bl,[BYTE color]\r
- xchg bl,[es:di] ; load latches and write pixel\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Vlin (int yl,yh,x,color)\r
-;\r
-;============================================================================\r
-\r
-PROC VW_Vlin yl:WORD, yh:WORD, x:WORD, color:WORD\r
-PUBLIC VW_Vlin\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[yl]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov cx,[yh]\r
- sub cx,[yl]\r
- inc cx ;number of pixels to plot\r
-\r
- mov bh,[BYTE color]\r
- mov dx,[linewidth]\r
-\r
-@@plot:\r
- mov bl,bh\r
- xchg bl,[es:di] ; load latches and write pixel\r
- add di,dx\r
-\r
- loop @@plot\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;===================\r
-;\r
-; VW_DrawTile8\r
-;\r
-; xcoord in bytes (8 pixels), ycoord in pixels\r
-; All Tile8s are in one grseg, so an offset is calculated inside it\r
-;\r
-;===================\r
-\r
-PROC VW_DrawTile8 xcoord:WORD, ycoord:WORD, tile:WORD\r
-PUBLIC VW_DrawTile8\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- add di,[xcoord]\r
- mov bx,[ycoord]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov [ss:screendest],di ;screen destination\r
-\r
- mov bx,[linewidth]\r
- dec bx\r
-\r
- mov si,[tile]\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
-\r
- mov ds,[grsegs+STARTTILE8*2] ; segment for all tile8s\r
-\r
- mov cx,4 ;planes to draw\r
- mov ah,0001b ;map mask\r
-\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
-\r
-;\r
-; start drawing\r
-;\r
-\r
-@@planeloop:\r
- WORDOUT\r
- shl ah,1 ;shift plane mask over for next plane\r
-\r
- mov di,[ss:screendest] ;start at same place in all planes\r
-\r
-REPT 7\r
- movsb\r
- add di,bx\r
-ENDM\r
- movsb\r
-\r
- loop @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MaskBlock\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then four planes of data.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-UNWOUNDMASKS = 10\r
-\r
-\r
-maskroutines dw mask0,mask0,mask1E,mask1E,mask2E,mask2O,mask3E,mask3O\r
- dw mask4E,mask4O,mask5E,mask5O,mask6E,mask6O\r
- dw mask7E,mask7O,mask8E,mask8O,mask9E,mask9O\r
- dw mask10E,mask10O\r
-\r
-\r
-routinetouse dw ?\r
-\r
-CODESEG\r
-\r
-PROC VW_MaskBlock segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD, planesize:WORD\r
-PUBLIC VW_MaskBlock\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov [BYTE planemask],1\r
- mov [BYTE planenum],0\r
-\r
- mov di,[wide]\r
- mov dx,[linewidth]\r
- sub dx,[wide]\r
- mov [linedelta],dx ;amount to add after drawing each line\r
-\r
- mov bx,[planesize] ; si+bx = data location\r
-\r
- cmp di,UNWOUNDMASKS\r
- jbe @@unwoundroutine\r
- mov [routinetouse],OFFSET generalmask\r
- jmp NEAR @@startloop\r
-\r
-;=================\r
-;\r
-; use the unwound routines\r
-;\r
-;=================\r
-\r
-@@unwoundroutine:\r
- mov cx,[dest]\r
- shr cx,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,[maskroutines+di] ;call the right routine\r
- mov [routinetouse],ax\r
-\r
-@@startloop:\r
- mov ds,[segm]\r
-\r
-@@drawplane:\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[ss:planemask]\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov al,GC_READMAP\r
- mov ah,[ss:planenum]\r
- WORDOUT\r
-\r
- mov si,[ofs] ;start back at the top of the mask\r
- mov di,[dest] ;start at same place in all planes\r
- mov cx,[height] ;scan lines to draw\r
- mov dx,[ss:linedelta]\r
-\r
- jmp [ss:routinetouse] ;draw one plane\r
-planereturn: ;routine jmps back here\r
-\r
- add bx,[ss:planesize] ;start of mask = start of next plane\r
-\r
- inc [ss:planenum]\r
- shl [ss:planemask],1 ;shift plane mask over for next plane\r
- cmp [ss:planemask],10000b ;done all four planes?\r
- jne @@drawplane\r
-\r
-mask0:\r
- mov ax,ss\r
- mov ds,ax\r
- ret ;width of 0 = no drawing\r
-\r
-;==============\r
-;\r
-; General purpose masked block drawing. This could be optimised into\r
-; four routines to use words, but few play loop sprites should be this big!\r
-;\r
-;==============\r
-\r
-generalmask:\r
- mov dx,cx\r
-\r
-@@lineloopgen:\r
- mov cx,[wide]\r
-@@byteloop:\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
- loop @@byteloop\r
-\r
- add di,[ss:linedelta]\r
- dec dx\r
- jnz @@lineloopgen\r
- jmp planereturn\r
-\r
-;=================\r
-;\r
-; Horizontally unwound routines to draw certain masked blocks faster\r
-;\r
-;=================\r
-\r
-MACRO MASKBYTE\r
- lodsb\r
- and al,[es:di]\r
- or al,[bx+si-1]\r
- stosb\r
-ENDM\r
-\r
-MACRO MASKWORD\r
- lodsw\r
- and ax,[es:di]\r
- or ax,[bx+si-2]\r
- stosw\r
-ENDM\r
-\r
-MACRO SPRITELOOP addr\r
- add di,dx\r
- loop addr\r
- jmp planereturn\r
-ENDM\r
-\r
-\r
-EVEN\r
-mask1E:\r
- MASKBYTE\r
- SPRITELOOP mask1E\r
-\r
-EVEN\r
-mask2E:\r
- MASKWORD\r
- SPRITELOOP mask2E\r
-\r
-EVEN\r
-mask2O:\r
- MASKBYTE\r
- MASKBYTE\r
- SPRITELOOP mask2O\r
-\r
-EVEN\r
-mask3E:\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask3E\r
-\r
-EVEN\r
-mask3O:\r
- MASKBYTE\r
- MASKWORD\r
- SPRITELOOP mask3O\r
-\r
-EVEN\r
-mask4E:\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask4E\r
-\r
-EVEN\r
-mask4O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask4O\r
-\r
-EVEN\r
-mask5E:\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask5E\r
-\r
-EVEN\r
-mask5O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask5O\r
-\r
-EVEN\r
-mask6E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask6E\r
-\r
-EVEN\r
-mask6O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask6O\r
-\r
-EVEN\r
-mask7E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask7E\r
-\r
-EVEN\r
-mask7O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask7O\r
-\r
-EVEN\r
-mask8E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask8E\r
-\r
-EVEN\r
-mask8O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask8O\r
-\r
-EVEN\r
-mask9E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask9E\r
-\r
-EVEN\r
-mask9O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask9O\r
-\r
-EVEN\r
-mask10E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask10E\r
-\r
-EVEN\r
-mask10O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask10O\r
-\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_InverseMask\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then four planes of data.\r
-;\r
-;============================================================================\r
-\r
-PROC VW_InverseMask segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_InverseMask\r
-USES SI,DI\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE+16*256 ;set function = OR\r
- WORDOUT\r
-\r
- mov es, [screenseg]\r
- mov ax, [wide]\r
- mov dx, [linewidth]\r
- sub dx, ax;\r
- mov ds, [segm]\r
- mov si, [ofs]\r
- mov di, [dest]\r
- mov bx, [height]\r
-@@yloop:\r
- mov cx, [wide]\r
-@@xloop:\r
- lodsb\r
- not al\r
- xchg al, [es:di]\r
- inc di\r
- loop @@xloop\r
- add di, dx\r
- dec bx\r
- jnz @@yloop\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE+0*256 ;set function = no change\r
- WORDOUT\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-;\r
-; VW_ScreenToScreen\r
-;\r
-; Basic block copy routine. Copies one block of screen memory to another,\r
-; using write mode 1 (sets it and returns with write mode 0). bufferofs is\r
-; NOT accounted for.\r
-;\r
-;============================================================================\r
-\r
-PROC VW_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToScreen\r
-USES SI,DI\r
-\r
- pushf\r
- cli\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- popf\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ax,[screenseg]\r
- mov es,ax\r
- mov ds,ax\r
-\r
- mov si,[source]\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
-\r
-@@lineloop:\r
- mov cx,ax\r
- rep movsb\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MemToScreen\r
-;\r
-; Basic block drawing routine. Takes a block shape at segment pointer source\r
-; with four planes of width by height data, and draws it to dest in the\r
-; virtual screen, based on linewidth. bufferofs is NOT accounted for.\r
-; There are four drawing routines to provide the best optimized code while\r
-; accounting for odd segment wrappings due to the floating screens.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-memtoscreentable dw eventoeven,eventoodd,oddtoeven,oddtoodd\r
-\r
-CODESEG\r
-\r
-\r
-PROC VW_MemToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_MemToScreen\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[source]\r
-\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- xor di,di\r
- shr [wide],1 ;change wide to words, and see if carry is set\r
- rcl di,1 ;1 if wide is odd\r
- mov ax,[dest]\r
- shr ax,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
- jmp [ss:memtoscreentable+di] ;call the right routine\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an even video address\r
-;\r
-;==============\r
-\r
-eventoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEE:\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne eventoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an even video address\r
-;\r
-;==============\r
-\r
-oddtoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOE:\r
- mov cx,[wide]\r
- rep movsw\r
- movsb ;copy the last byte\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an odd video address\r
-;\r
-;==============\r
-\r
-eventoodd:\r
- dec [wide] ;one word has to be handled seperately\r
-EOplaneloop:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
- movsb\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne EOplaneloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an odd video address\r
-;\r
-;==============\r
-\r
-oddtoodd:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoodd\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;===========================================================================\r
-;\r
-; VW_ScreenToMem\r
-;\r
-; Copies a block of video memory to main memory, in order from planes 0-3.\r
-; This could be optimized along the lines of VW_MemToScreen to take advantage\r
-; of word copies, but this is an infrequently called routine.\r
-;\r
-;===========================================================================\r
-\r
-PROC VW_ScreenToMem source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToMem\r
-USES SI,DI\r
-\r
- mov es,[dest]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[screenseg]\r
-\r
- mov ax,GC_READMAP ;read map for plane 0\r
-\r
- xor di,di\r
-\r
-@@planeloop:\r
- mov dx,GC_INDEX\r
- WORDOUT\r
-\r
- mov si,[source] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloop:\r
- mov cx,[wide]\r
- rep movsb\r
-\r
- add si,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- inc ah\r
- cmp ah,4 ;done all four planes?\r
- jne @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VWL_UpdateScreenBlocks\r
-;\r
-; Scans through the update matrix and copies any areas that have changed\r
-; to the visable screen, then zeros the update array\r
-;\r
-;============================================================================\r
-\r
-\r
-\r
-; AX 0/1 for scasb, temp for segment register transfers\r
-; BX width for block copies\r
-; CX REP counter\r
-; DX line width deltas\r
-; SI source for copies\r
-; DI scas dest / movsb dest\r
-; BP pointer to end of bufferblocks\r
-\r
-PROC VWL_UpdateScreenBlocks\r
-PUBLIC VWL_UpdateScreenBlocks\r
-USES SI,DI,BP\r
-\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- mov dx,GC_INDEX ; restore write mode 0\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- xor ax,ax ; clear out the update matrix\r
- mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-\r
- mov di,[updateptr]\r
- rep stosw\r
-\r
- ret\r
-\r
-@@realstart:\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- mov di,[updateptr] ; start of floating update screen\r
- mov bp,di\r
- add bp,UPDATEWIDE*UPDATEHIGH+1 ; when di = bp, all tiles have been scanned\r
-\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-\r
-;\r
-; scan for a 1 in the update list, meaning a tile needs to be copied\r
-; from the master screen to the current screen\r
-;\r
-@@findtile:\r
- pop di ; place to continue scaning from\r
- mov ax,ss\r
- mov es,ax ; search in the data segment\r
- mov ds,ax\r
- mov al,1\r
- repne scasb\r
- cmp di,bp\r
- jae @@done\r
-\r
- cmp [BYTE di],al\r
- jne @@singletile\r
- jmp @@tileblock\r
-\r
-;============\r
-;\r
-; copy a single tile\r
-;\r
-;============\r
-@@singletile:\r
- inc di ; we know the next tile is nothing\r
- push di ; save off the spot being scanned\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-4+di] ; start of tile location on screen\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,2\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- movsb\r
- movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
- jmp @@findtile\r
-\r
-;============\r
-;\r
-; more than one tile in a row needs to be updated, so do it as a group\r
-;\r
-;============\r
-EVEN\r
-@@tileblock:\r
- mov dx,di ; hold starting position + 1 in dx\r
- inc di ; we know the next tile also gets updated\r
- repe scasb ; see how many more in a row\r
- push di ; save off the spot being scanned\r
-\r
- mov bx,di\r
- sub bx,dx ; number of tiles in a row\r
- shl bx,1 ; number of bytes / row\r
-\r
- mov di,dx ; lookup position of start tile\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-2+di] ; start of tile location\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,bx ; offset to next line on screen\r
-\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- mov cx,bx\r
- rep movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- mov cx,bx\r
- rep movsb\r
-\r
- dec cx ; was 0 from last rep movsb, now $ffff for scasb\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-;\r
-; MISC EGA ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-;=================\r
-;\r
-; VWL_WaitRetrace\r
-;\r
-;=================\r
-\r
-DATASEG\r
-\r
-EXTRN TimeCount :DWORD\r
-EXTRN jerk :WORD\r
-EXTRN nopan :WORD\r
-\r
-CODESEG\r
-\r
-PROC VWL_WaitRetrace NEAR\r
- mov dx,STATUS_REGISTER_1\r
- mov bx,[WORD TimeCount]\r
-@@waitloop:\r
- sti\r
- jmp $+2\r
- cli\r
-\r
- in al,dx\r
- test al,8\r
- jnz @@done\r
- mov ax,[WORD TimeCount]\r
- sub ax,bx\r
- cmp ax,1\r
- jbe @@waitloop\r
-\r
-@@done:\r
- ret\r
-ENDP\r
-\r
-\r
-;==============\r
-;\r
-; VW_SetScreen\r
-;\r
-;==============\r
-\r
-PROC VW_SetScreen crtc:WORD, pel:WORD\r
-PUBLIC VW_SetScreen\r
-\r
-if waitforvbl\r
-\r
- mov dx,STATUS_REGISTER_1\r
-\r
-;\r
-; wait util the CRTC just starts scaning a diplayed line to set the CRTC start\r
-;\r
- cli\r
-\r
-@@waitnodisplay:\r
- in al,dx\r
- test al,01b\r
- jz @@waitnodisplay\r
-\r
-@@waitdisplay:\r
- in al,dx\r
- test al,01b\r
- jnz @@waitdisplay\r
-\r
-endif\r
-\r
-;\r
-; set CRTC start\r
-;\r
-; for some reason, my XT's EGA card doesn't like word outs to the CRTC\r
-; index...\r
-;\r
- mov cx,[crtc]\r
- mov dx,CRTC_INDEX\r
- mov al,0ch ;start address high register\r
- out dx,al\r
- inc dx\r
- mov al,ch\r
- out dx,al\r
- dec dx\r
- mov al,0dh ;start address low register\r
- out dx,al\r
- mov al,cl\r
- inc dx\r
- out dx,al\r
-\r
- test [jerk],1\r
- jz @@l3\r
- call VWL_WaitRetrace\r
-\r
-@@l3:\r
- test [nopan],1\r
- jnz @@l4\r
-;\r
-; set horizontal panning\r
-;\r
-\r
- mov dx,ATR_INDEX\r
- mov al,ATR_PELPAN or 20h\r
- out dx,al\r
- jmp $+2\r
- mov al,[BYTE pel] ;pel pan value\r
- out dx,al\r
-\r
-@@l4:\r
- test [jerk],1\r
- jnz @@done\r
- call VWL_WaitRetrace\r
-\r
-@@done:\r
- sti\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-if NUMFONT+NUMFONTM\r
-\r
-;===========================================================================\r
-;\r
-; GENERAL FONT DRAWING ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-DATASEG\r
-\r
-px dw ? ; proportional character drawing coordinates\r
-py dw ?\r
-pdrawmode db 11000b ; 8 = OR, 24 = XOR, put in GC_DATAROTATE\r
-fontcolor db 15 ;0-15 mapmask value\r
-\r
-PUBLIC px,py,pdrawmode,fontcolor\r
-\r
-;\r
-; offsets in font structure\r
-;\r
-pcharheight = 0 ;lines high\r
-charloc = 2 ;pointers to every character\r
-charwidth = 514 ;every character's width in pixels\r
-\r
-\r
-propchar dw ? ; the character number to shift\r
-stringptr dw ?,?\r
-\r
-\r
-BUFFWIDTH = 50\r
-BUFFHEIGHT = 32 ; must be twice as high as font for masked fonts\r
-\r
-databuffer db BUFFWIDTH*BUFFHEIGHT dup (?)\r
-\r
-bufferwidth dw ? ; bytes with valid info / line\r
-bufferheight dw ? ; number of lines currently used\r
-\r
-bufferbyte dw ?\r
-bufferbit dw ?\r
-\r
-screenspot dw ? ; where the buffer is going\r
-\r
-bufferextra dw ? ; add at end of a line copy\r
-screenextra dw ?\r
-\r
-PUBLIC bufferwidth,bufferheight,screenspot\r
-\r
-CODESEG\r
-\r
-;======================\r
-;\r
-; Macros to table shift a byte of font\r
-;\r
-;======================\r
-\r
-MACRO SHIFTNOXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- or [di],al ; or with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-MACRO SHIFTWITHXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- not ax\r
- and [di],al ; and with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-\r
-;=======================\r
-;\r
-; BufferToScreen\r
-;\r
-; Pass buffer start in SI (somewhere in databuffer)\r
-; Draws the buffer to the EGA screen in the current write mode\r
-;\r
-;========================\r
-\r
-PROC BufferToScreen NEAR\r
-\r
- mov es,[screenseg]\r
- mov di,[screenspot]\r
-\r
- mov bx,[bufferwidth] ;calculate offsets for end of each line\r
- or bx,bx\r
- jnz @@isthere\r
- ret ;nothing to draw\r
-\r
-@@isthere:\r
- mov ax,[linewidth]\r
- sub ax,bx\r
- mov [screenextra],ax\r
- mov ax,BUFFWIDTH\r
- sub ax,bx\r
- mov [bufferextra],ax\r
-\r
- mov bx,[bufferheight] ;lines to copy\r
-@@lineloop:\r
- mov cx,[bufferwidth] ;bytes to copy\r
-@@byteloop:\r
- lodsb ;get a byte from the buffer\r
- xchg [es:di],al ;load latches and store back to screen\r
- inc di\r
-\r
- loop @@byteloop\r
-\r
- add si,[bufferextra]\r
- add di,[screenextra]\r
-\r
- dec bx\r
- jnz @@lineloop\r
-\r
- ret\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; NON MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfont\r
-\r
-DATASEG\r
-\r
-shiftdrawtable dw 0,shift1wide,shift2wide,shift3wide,shift4wide\r
- dw shift5wide\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
-;\r
-; advance position by character width\r
-;\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:shiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-shift1wide:\r
- dec dx\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-shift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-shift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
- ret\r
-\r
-;\r
-; four byte character\r
-;\r
-shift4wide:\r
- sub dx,4\r
-EVEN\r
-@@loop4:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop4\r
- ret\r
-\r
-;\r
-; five byte character\r
-;\r
-shift5wide:\r
- sub dx,5\r
-EVEN\r
-@@loop5:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop5\r
- ret\r
-\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-CODESEG\r
-\r
-PROC VW_DrawPropString string:DWORD\r
-PUBLIC VW_DrawPropString\r
-USES SI,DI\r
-\r
-;\r
-; proportional spaceing, which clears the buffer ahead of it, so only\r
-; clear the first collumn\r
-;\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line],al\r
-line = line+1\r
-ENDM\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
-@@shiftchars:\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
-\r
-; set xor/or mode\r
- mov dx,GC_INDEX\r
- mov al,GC_DATAROTATE\r
- mov ah,[pdrawmode]\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ;numfont\r
-\r
-;============================================================================\r
-;\r
-; MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfontm\r
-\r
-DATASEG\r
-\r
-mshiftdrawtable dw 0,mshift1wide,mshift2wide,mshift3wide\r
-\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftMPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftMPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:mshiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-mshift1wide:\r
- dec dx\r
-\r
-EVEN\r
-@@loop1m:\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-mshift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-mshift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawMPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-\r
-\r
-PROC VW_DrawMPropString string:DWORD\r
-PUBLIC VW_DrawMPropString\r
-USES SI,DI\r
-\r
-;\r
-; clear out the first byte of the buffer, the rest will automatically be\r
-; cleared as characters are drawn into it\r
-;\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si]\r
- mov dx,[es:pcharheight]\r
- mov di,OFFSET databuffer\r
- mov ax,ds\r
- mov es,ax\r
- mov bx,BUFFWIDTH-1\r
-\r
- mov cx,dx\r
- mov al,0ffh\r
-@@maskfill:\r
- stosb ; fill the mask part with $ff\r
- add di,bx\r
- loop @@maskfill\r
-\r
- mov cx,dx\r
- xor al,al\r
-@@datafill:\r
- stosb ; fill the data part with $0\r
- add di,bx\r
- loop @@datafill\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftMPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
-; set AND mode to punch out the mask\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 8*256\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set OR mode to fill in the color\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 16*256\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- call BufferToScreen ; SI is still in the right position in buffer\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ; if numfontm\r
-\r
-endif ; if fonts\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __CK_DEF__\r
-#define __CK_DEF__\r
-\r
-#include <BIOS.H>\r
-#include <CONIO.H>\r
-\r
-#include "ID_HEADS.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL CONSTANTS & MACROS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define MAXACTORS 100\r
-\r
-#define GAMELEVELS 25\r
-\r
-#define CONVERT_GLOBAL_TO_TILE(x) ((x)>>(G_T_SHIFT))\r
-#define CONVERT_TILE_TO_GLOBAL(x) ((x)<<(G_T_SHIFT))\r
-#define CONVERT_GLOBAL_TO_PIXEL(x) ((x)>>(G_P_SHIFT))\r
-#define CONVERT_PIXEL_TO_GLOBAL(x) ((x)<<(G_P_SHIFT))\r
-#define CONVERT_PIXEL_TO_TILE(x) ((x)>>(P_T_SHIFT))\r
-#define CONVERT_TILE_TO_PIXEL(x) ((x)<<(P_T_SHIFT))\r
-\r
-#define SPAWN_ADJUST_Y(y, h) (CONVERT_TILE_TO_GLOBAL(y) + (CONVERT_PIXEL_TO_GLOBAL(16-(h))))\r
-\r
-#define ARRAYLENGTH(x) (sizeof(x)/sizeof(*(x)))\r
-\r
-#define CA_UnmarkGrChunk(num) (grneeded[num] &= ~ca_levelbit)\r
-\r
-#define SetPalette(pal) {_ES=FP_SEG(pal); _DX=FP_OFF(pal); _AX=0x1002; geninterrupt(0x10);}\r
-#define SetPaletteEx(pal) {(pal)[16] = bordercolor; SetPalette(pal);}\r
-\r
-//HACK IMPORTS:\r
-void RFL_InitAnimList(void);\r
-void CA_FreeGraphics(void);\r
-void CA_SetGrPurge(void);\r
-\r
-/*\r
-Note:\r
-\r
-The ID software memory manager doesn't care about the different purge levels.\r
-Using PURGE_FIST is identical to using PURGE_LAST.\r
-*/\r
-#define PURGE_FIRST 3\r
-#define PURGE_LAST 1\r
-\r
-#define PLATFORMBLOCK 31\r
-#define DIRARROWSTART 91\r
-#define DIRARROWEND (DIRARROWSTART+arrow_None)\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL TYPES\r
-\r
-=============================================================================\r
-*/\r
-\r
-//SDL-style integer types - just to make future SDL ports easier\r
-typedef unsigned int Uint16;\r
-typedef signed int Sint16;\r
-typedef unsigned char Uint8;\r
-typedef signed char Sint8;\r
-typedef unsigned long Uint32;\r
-typedef signed long Sint32;\r
-//Note: only the game code (CK_*.C, K?_*.C) uses these!\r
-\r
-//some compile-time checks to make sure the ints have the correct size\r
-#if (sizeof(Uint16) != 2)\r
-#error 'Uint16' has wrong size\r
-#elif (sizeof(Sint16) != 2)\r
-#error 'Sint16' has wrong size\r
-#elif (sizeof(Uint8) != 1)\r
-#error 'Uint8' has wrong size\r
-#elif (sizeof(Sint8) != 1)\r
-#error 'Sint8' has wrong size\r
-#elif (sizeof(Uint32) != 4)\r
-#error 'Uint32' has wrong size\r
-#elif (sizeof(Sint32) != 4)\r
-#error 'Sint32' has wrong size\r
-#endif\r
-\r
-typedef enum {\r
- arrow_North, // 0\r
- arrow_East, // 1\r
- arrow_South, // 2\r
- arrow_West, // 3\r
- arrow_NorthEast, // 4\r
- arrow_SouthEast, // 5\r
- arrow_SouthWest, // 6\r
- arrow_NorthWest, // 7\r
- arrow_None // 8\r
-} arrowdirtype;\r
-\r
-typedef enum {\r
- ex_stillplaying, // 0\r
- ex_died, // 1\r
- ex_completed, // 2\r
- ex_rescued, // 3, only in Keen 4\r
- ex_warped, // 4\r
- ex_resetgame, // 5\r
- ex_loadedgame, // 6\r
- ex_foot, // 7, only in Keen 4\r
- ex_abortgame, // 8\r
- ex_sandwich, // 9, only in Keen 6\r
- ex_hook, // 10, only in Keen 6\r
- ex_card, // 11, only in Keen 6\r
- ex_molly, // 12, only in Keen 6\r
- ex_portout, // 13, only in Keen 5\r
- ex_fusebroke, // 14, only in Keen 5\r
- ex_qedbroke, // 15, only in Keen 5\r
- NUMEXITTYPES\r
-} exittype;\r
-\r
-typedef enum\r
-{\r
- INTILE_NOTHING, // 0\r
- INTILE_POLE, // 1\r
- INTILE_DOOR, // 2\r
- INTILE_DEADLY, // 3\r
- INTILE_DROP, // 4\r
- INTILE_SWITCH0, // 5\r
- INTILE_SWITCH1, // 6\r
- INTILE_GEMSOCKET0, // 7\r
- INTILE_GEMSOCKET1, // 8\r
- INTILE_GEMSOCKET2, // 9\r
- INTILE_GEMSOCKET3, // 10\r
- INTILE_SHORESOUTH, // 11\r
- INTILE_SHOREWEST, // 12\r
- INTILE_SHORENORTH, // 13\r
- INTILE_SHOREEAST, // 14\r
- INTILE_BRIDGESWITCH, // 15\r
- INTILE_MOON, // 16\r
- INTILE_DIRARROW, // 17 (not used in the code, but assigned to tiles in Keen 5 & 6)\r
- INTILE_BRIDGE, // 18\r
- INTILE_FORCEFIELD, // 19\r
- INTILE_TELEPORT, // 20\r
- INTILE_BONUS100, // 21\r
- INTILE_BONUS200, // 22\r
- INTILE_BONUS500, // 23\r
- INTILE_BONUS1000, // 24\r
- INTILE_BONUS2000, // 25\r
- INTILE_BONUS5000, // 26\r
- INTILE_EXTRALIFE, // 27\r
- INTILE_AMMO, // 28\r
- INTILE_29, // 29 (never used)\r
- INTILE_FORCEFIELDEND, // 30\r
- INTILE_AMPTONCOMPUTER, // 31\r
- INTILE_KEYCARDDOOR, // 32\r
- INTILE_ELEVATORLEFT, // 33\r
- INTILE_ELEVATORRIGHT, // 34\r
-\r
- INTILE_FOREGROUND = 0x80\r
-} intiletype;\r
-\r
-#define INTILE_TYPEMASK (INTILE_FOREGROUND-1)\r
-\r
-typedef enum\r
-{\r
- nothing, // 0\r
- inertobj, // 1\r
- keenobj, // 2\r
- stunshotobj, // 3\r
-#if defined KEEN4\r
- bonusobj, // 4\r
- slugobj, // 5\r
- oracleobj, // 6\r
- classtype_7, // 7, never used\r
- eggobj, // 8\r
- madmushroomobj, // 9\r
- arachnutobj, // 10\r
- skypestobj, // 11\r
- wormouthobj, // 12\r
- thundercloudobj, // 13\r
- berkeloidobj, // 14\r
- bounderobj, // 15\r
- inchwormobj, // 16\r
- footobj, // 17\r
- lickobj, // 18\r
- mimrockobj, // 19\r
- platformobj, // 20\r
- dopefishobj, // 21\r
- schoolfishobj, // 22\r
- pixieobj, // 23\r
- lindseyobj, // 24\r
- lightningobj, // 25\r
- treasureeaterobj,// 26\r
- eggbirdobj, // 27\r
- classtype_28, // 28, never used\r
- classtype_29, // 29, never used\r
- scubaobj, // 30\r
- mshotobj, // 31\r
- mineobj, // 32\r
- stunnedobj, // 33\r
- flagobj, // 34\r
-#elif defined KEEN5\r
- mshotobj, // 4\r
- bonusobj, // 5\r
- platformobj, // 6\r
- stunnedobj, // 7\r
- flagobj, // 8\r
- sparkyobj, // 9\r
- mineobj, // 10\r
- slicestarobj, // 11\r
- roboredobj, // 12\r
- spirogripobj, // 13\r
- amptonobj, // 14\r
- cannonobj, // 15\r
- volteobj, // 16\r
- shelleyobj, // 17, never used\r
- spindredobj, // 18\r
- shikadimasterobj,// 19\r
- shikadiobj, // 20\r
- petobj, // 21\r
- spherefulobj, // 22\r
- scottieobj, // 23\r
- teleporterobj, // 24\r
- qedobj, // 25\r
-#elif defined KEEN6\r
- mshotobj, // 4\r
- bonusobj, // 5\r
- platformobj, // 6\r
- bloogobj, // 7\r
- bloogletobj, // 8\r
- classtype_9, // 9, never used\r
- fleexobj, // 10\r
- classtype_11, // 11, never used\r
- mollyobj, // 12\r
- babobbaobj, // 13\r
- bobbaobj, // 14\r
- classtype_15, // 15\r
- nospikeobj, // 16\r
- gikobj, // 17\r
- cannonobj, // 18\r
- orbatrixobj, // 19\r
- bipobj, // 20\r
- flectobj, // 21\r
- blorbobj, // 22\r
- ceilickobj, // 23\r
- blooguardobj, // 24\r
- stunnedobj, // 25\r
- bipshipobj, // 26\r
- sandwichobj, // 27\r
- hookobj, // 28\r
- passcardobj, // 29\r
- grabbiterobj, // 30\r
- rocketobj, // 31\r
- grapplespotobj, // 32\r
- satelliteobj, // 33\r
- satellitestopobj,// 34\r
- flagobj, // 35\r
-#endif\r
- NUMCLASSTYPES\r
-} classtype;\r
-\r
-typedef struct statestruct\r
-{\r
- Sint16 leftshapenum, rightshapenum;\r
- enum {step,slide,think,stepthink,slidethink} progress;\r
- boolean skippable;\r
- boolean pushtofloor;\r
- Sint16 tictime;\r
- Sint16 xmove;\r
- Sint16 ymove;\r
- void (*think) (struct objstruct*);\r
- void (*contact) (struct objstruct*, struct objstruct*);\r
- void (*react) (struct objstruct*);\r
- struct statestruct *nextstate;\r
-} statetype;\r
-\r
-typedef struct objstruct\r
-{\r
- classtype obclass;\r
- enum {ac_no, ac_yes, ac_allways, ac_removable} active;\r
- boolean needtoreact;\r
- enum {cl_noclip, cl_midclip, cl_fullclip} needtoclip;\r
- Uint16 nothink;\r
- Uint16 x, y;\r
- Sint16 xdir, ydir;\r
- Sint16 xmove, ymove;\r
- Sint16 xspeed, yspeed;\r
- Sint16 ticcount;\r
- statetype *state;\r
- Uint16 shapenum;\r
- Uint16 priority;\r
- Uint16 left, top, right, bottom, midx;\r
- Uint16 tileleft, tiletop, tileright, tilebottom, tilemidx;\r
- Sint16 hitnorth, hiteast, hitsouth, hitwest;\r
- Sint16 temp1, temp2, temp3, temp4;\r
- void *sprite;\r
- struct objstruct *next, *prev;\r
-} objtype;\r
-\r
-typedef struct\r
-{\r
- Uint16 worldx, worldy;\r
- boolean leveldone[GAMELEVELS];\r
- Sint32 score, nextextra;\r
- Sint16 ammo, drops;\r
-#if defined KEEN4\r
- Sint16 wetsuit;\r
- Sint16 rescued;\r
-#elif defined KEEN5\r
- boolean keycard;\r
- Sint16 destroyed; // never used\r
- Sint16 numfuses;\r
-#elif defined KEEN6\r
- Sint16 sandwichstate, hookstate, passcardstate, rocketstate;\r
-#endif\r
- Sint16 keys[4];\r
- Sint16 mapon;\r
- Sint16 lives;\r
- Sint16 difficulty;\r
- objtype *riding;\r
-} gametype;\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_MAIN DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern char str[80], str2[20];\r
-extern boolean storedemo;\r
-\r
-void SizeText(char *text, Uint16 *width, Uint16 *height);\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_DEMO DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern boolean scorescreenkludge;\r
-\r
-void CheckLastScan(void);\r
-#if GRMODE == EGAGR\r
-void Terminator(void);\r
-void StarWars(void);\r
-#endif\r
-void ShowTitle(void);\r
-#if GRMODE == CGAGR\r
-void ShowCredits(void);\r
-#endif\r
-void RunDemo(Sint16 num);\r
-void DrawHighScores(void);\r
-void CheckHighScore(Sint32 score, Sint16 completed);\r
-void ShowHighScores(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_GAME DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void FreeGraphics(void);\r
-void NewGame(void);\r
-boolean SaveTheGame(Sint16 handle);\r
-boolean LoadTheGame(Sint16 handle);\r
-void ResetGame(void);\r
-void SetupGameLevel(boolean loadnow);\r
-void DialogDraw(char *title, Uint16 numcache);\r
-void DialogUpdate(void);\r
-void DialogFinish(void);\r
-void StartDemoRecord(void);\r
-void EndDemoRecord(void);\r
-void GameLoop(void);\r
-void HandleDeath(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_PLAY DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern boolean singlestep, jumpcheat, godmode, keenkilled;\r
-extern exittype playstate;\r
-extern gametype gamestate;\r
-extern objtype *new, *check, *player, *scoreobj;\r
-extern Uint16 originxtilemax, originytilemax;\r
-extern ControlInfo c;\r
-extern boolean button2, button3; // never used\r
-extern objtype dummyobj;\r
-extern Sint16 invincible;\r
-extern boolean oldshooting, showscorebox, joypad;\r
-extern Sint16 groundslam;\r
-extern boolean debugok;\r
-extern boolean jumpbutton, jumpheld, pogobutton, pogoheld, firebutton, fireheld, upheld;\r
-\r
-\r
-void CheckKeys(void);\r
-void StatusWindow(void);\r
-void CenterActor(objtype *ob);\r
-void WorldScrollScreen(objtype *ob);\r
-void ScrollScreen(objtype *ob);\r
-void InitObjArray(void);\r
-Sint16 GetNewObj(boolean usedummy);\r
-void RemoveObj(objtype *ob);\r
-void GivePoints(Uint16 points);\r
-void StopMusic(void);\r
-void StartMusic(Uint16 num);\r
-void PlayLoop(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_TEXT DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void HelpScreens(void);\r
-void FinaleLayout(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_STATE DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern Sint16 wallclip[8][16];\r
-\r
-extern Sint16 xtry;\r
-extern Sint16 ytry;\r
-extern boolean playerkludgeclipcancel;\r
-\r
-void MoveObjVert(objtype *ob, Sint16 ymove);\r
-void MoveObjHoriz(objtype *ob, Sint16 xmove);\r
-void PlayerBottomKludge(objtype *ob);\r
-void PlayerTopKludge(objtype *ob);\r
-void ClipToEnds(objtype *ob);\r
-void ClipToSides(objtype *ob);\r
-boolean CheckPosition(objtype *ob);\r
-boolean StatePositionOk(objtype *ob, statetype *state);\r
-\r
-#ifdef KEEN5\r
-void CalcBounds(objtype *ob);\r
-#endif\r
-\r
-void ClipToWalls(objtype *ob);\r
-void FullClipToWalls(objtype *ob);\r
-void PushObj(objtype *ob);\r
-void ClipToSpriteSide(objtype *push, objtype *solid);\r
-void ClipToSpriteTop(objtype *push, objtype *solid);\r
-void ClipToSprite(objtype *push, objtype *solid, boolean squish);\r
-Sint16 DoActor(objtype *ob, Sint16 numtics);\r
-void StateMachine(objtype *ob);\r
-void NewState(objtype *ob, statetype *state);\r
-void ChangeState(objtype *ob, statetype *state);\r
-boolean OnScreen(objtype *ob);\r
-void DoGravity(objtype *ob);\r
-void DoWeakGravity(objtype *ob);\r
-void DoTinyGravity(objtype *ob);\r
-void AccelerateX(objtype *ob, Sint16 dir, Sint16 maxspeed);\r
-void AccelerateXv(objtype *ob, Sint16 dir, Sint16 maxspeed);\r
-void AccelerateY(objtype *ob, Sint16 dir, Sint16 maxspeed);\r
-void FrictionX(objtype *ob);\r
-void FrictionY(objtype *ob);\r
-void StunObj(objtype *ob, objtype *shot, statetype *stunstate);\r
-void T_Projectile(objtype *ob);\r
-void T_WeakProjectile(objtype *ob);\r
-void ProjectileThink1(objtype *ob);\r
-void T_Velocity(objtype *ob);\r
-void SetReactThink(objtype *ob);\r
-void T_Stunned(objtype *ob);\r
-void C_Lethal(objtype *ob, objtype *hit);\r
-void R_Draw(objtype *ob);\r
-void R_Walk(objtype *ob);\r
-void R_WalkNormal(objtype *ob);\r
-void BadState(void);\r
-void R_Stunned(objtype *ob);\r
-\r
-extern statetype sc_deadstate;\r
-extern statetype sc_badstate;\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_KEEN DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern Uint16 bounceangle[8][8];\r
-#ifndef KEEN4\r
-extern arrowdirtype arrowflip[];\r
-#endif\r
-\r
-extern statetype s_keenstand;\r
-extern statetype s_keenpauselook;\r
-extern statetype s_keenwait1;\r
-extern statetype s_keenwait2;\r
-extern statetype s_keenwait3;\r
-extern statetype s_keenwait4;\r
-extern statetype s_keenwait5;\r
-extern statetype s_keenwait6;\r
-extern statetype s_keenmoon1;\r
-extern statetype s_keenmoon2;\r
-extern statetype s_keenmoon3;\r
-extern statetype s_keenread;\r
-extern statetype s_keenread2;\r
-extern statetype s_keenread3;\r
-extern statetype s_keenread4;\r
-extern statetype s_keenread5;\r
-extern statetype s_keenread6;\r
-extern statetype s_keenread7;\r
-extern statetype s_keenstopread;\r
-extern statetype s_keenstopread2;\r
-extern statetype s_keenstopread3;\r
-extern statetype s_keenlookup;\r
-extern statetype s_keenlookup2;\r
-extern statetype s_keenlookdown;\r
-extern statetype s_keenlookdown2;\r
-extern statetype s_keenlookdown3;\r
-extern statetype s_keenlookdown4;\r
-extern statetype s_keendrop;\r
-extern statetype s_keendead;\r
-extern statetype s_keendie1;\r
-extern statetype s_keendie2;\r
-#ifdef KEEN4\r
-extern statetype s_keensuitdie1;\r
-extern statetype s_keensuitdie2;\r
-#endif\r
-extern statetype s_keenshoot1;\r
-extern statetype s_keenshoot2;\r
-extern statetype s_keenshootup1;\r
-extern statetype s_keenshootup2;\r
-extern statetype s_keenswitch;\r
-extern statetype s_keenswitch2;\r
-extern statetype s_keenkey;\r
-extern statetype s_keenlineup;\r
-extern statetype s_keenenter1;\r
-extern statetype s_keenenter2;\r
-extern statetype s_keenenter3;\r
-extern statetype s_keenenter4;\r
-extern statetype s_keenenter5;\r
-extern statetype s_keenpole;\r
-extern statetype s_keenclimb1;\r
-extern statetype s_keenclimb2;\r
-extern statetype s_keenclimb3;\r
-extern statetype s_keenslide1;\r
-extern statetype s_keenslide2;\r
-extern statetype s_keenslide3;\r
-extern statetype s_keenslide4;\r
-extern statetype s_keenpoleshoot1;\r
-extern statetype s_keenpoleshoot2;\r
-extern statetype s_keenpoleshootup1;\r
-extern statetype s_keenpoleshootup2;\r
-extern statetype s_keenpoleshootdown1;\r
-extern statetype s_keenpoleshootdown2;\r
-extern statetype s_keenwalk1;\r
-extern statetype s_keenwalk2;\r
-extern statetype s_keenwalk3;\r
-extern statetype s_keenwalk4;\r
-extern statetype s_keenpogodown;\r
-extern statetype s_keenpogo;\r
-extern statetype s_keenpogo2;\r
-extern statetype s_keenjump1;\r
-extern statetype s_keenjump2;\r
-extern statetype s_keenjump3;\r
-extern statetype s_keenjump4;\r
-extern statetype s_keenairshoot1;\r
-extern statetype s_keenairshoot2;\r
-extern statetype s_keenairshoot3;\r
-extern statetype s_keenairshootup1;\r
-extern statetype s_keenairshootup2;\r
-extern statetype s_keenairshootup3;\r
-extern statetype s_keenairshootdown1;\r
-extern statetype s_keenairshootdown2;\r
-extern statetype s_keenairshootdown3;\r
-extern statetype s_keenholdon;\r
-extern statetype s_keenholdon2;\r
-extern statetype s_keenclimbup;\r
-extern statetype s_keenclimbup2;\r
-extern statetype s_keenclimbup3;\r
-extern statetype s_keenclimbup4;\r
-extern statetype s_keenclimbup5;\r
-\r
-extern Sint16 slopespeed[8];\r
-extern Sint16 polexspeed[3];\r
-\r
-extern Sint16 shotsinclip[4];\r
-extern Sint16 bonussound[];\r
-extern Sint16 bonuspoints[];\r
-extern Sint16 bonussprite[];\r
-\r
-extern Uint16 zeromap;\r
-\r
-extern Sint16 singlegravity;\r
-extern Sint16 jumptime;\r
-extern Sint32 leavepoletime;\r
-extern Sint16 moonok;\r
-\r
-void SpawnKeen(Sint16 x, Sint16 y, Sint16 dir);\r
-boolean CheckGrabPole(objtype *ob);\r
-boolean CheckEnterHouse(objtype *ob);\r
-void WalkSound1(objtype *ob);\r
-void WalkSound2(objtype *ob);\r
-void KeenStandThink(objtype *ob);\r
-void KeenPauseThink(objtype *ob);\r
-void KeenReadThink(objtype *ob);\r
-void KeenLookUpThink(objtype *ob);\r
-void KeenLookDownThink(objtype *ob);\r
-void KeenWalkThink(objtype *ob);\r
-void T_LineUp(objtype *ob);\r
-void KeenEnterThink(objtype *ob);\r
-void KeenSwitchThink(objtype *ob);\r
-void KeenKeyThink(objtype *ob);\r
-void KeenAirThink(objtype *ob);\r
-void KeenBounceThink(objtype *ob);\r
-void KeenPogoThink(objtype *ob);\r
-void PoleActions(objtype *ob);\r
-void KeenPoleThink(objtype *ob);\r
-void KeenClimbThink(objtype *ob);\r
-void KeenDropThink(objtype *ob);\r
-void KeenDropDownThink(objtype *ob);\r
-void KeenHoldThink(objtype *ob);\r
-void KeenShootThink(objtype *ob);\r
-void T_PullUp1(objtype *ob);\r
-void T_PullUp2(objtype *ob);\r
-void T_PullUp3(objtype *ob);\r
-void T_PulledUp(objtype *ob);\r
-void KeenDieThink(objtype *ob);\r
-void KillKeen(void);\r
-void KeenContact(objtype *ob, objtype *hit);\r
-void KeenPosContact(objtype *ob, objtype *hit);\r
-void HandleRiding(objtype *ob);\r
-void TileBonus(Uint16 x, Uint16 y, Uint16 bonus);\r
-void GiveDrop(Uint16 x, Uint16 y);\r
-void CheckInTiles(objtype *ob);\r
-void KeenSimpleReact(objtype *ob);\r
-void KeenStandReact(objtype *ob);\r
-void KeenWalkReact(objtype *ob);\r
-void KeenAirReact(objtype *ob);\r
-void KeenPogoReact(objtype *ob);\r
-void KeenPoleReact(objtype *ob);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- CK_KEEN2 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_score;\r
-extern statetype s_demo;\r
-void SpawnScore(void);\r
-void UpdateScore(objtype *ob);\r
-void DrawDemoPlaque(objtype *ob);\r
-\r
-extern statetype s_worldkeen;\r
-extern statetype s_worldkeenwave1;\r
-extern statetype s_worldkeenwave2;\r
-extern statetype s_worldkeenwave3;\r
-extern statetype s_worldkeenwave4;\r
-extern statetype s_worldkeenwave5;\r
-extern statetype s_worldkeenwalk;\r
-void SpawnWorldKeen(Sint16 x, Sint16 y);\r
-#ifdef KEEN5\r
-void SpawnWorldKeenPort(Uint16 tileX, Uint16 tileY);\r
-#endif\r
-void CheckEnterLevel(objtype *ob);\r
-void T_KeenWorld(objtype *ob);\r
-void T_KeenWorldWalk(objtype *ob);\r
-void CheckWorldInTiles(objtype *ob);\r
-\r
-#ifdef KEEN4\r
-extern statetype s_keenonfoot1;\r
-extern statetype s_keenonfoot2;\r
-extern statetype s_worldswim;\r
-void T_FootFly(objtype *ob);\r
-void T_KeenWorldSwim(objtype *ob);\r
-#endif\r
-\r
-#ifdef KEEN5\r
-extern statetype s_worldelevate;\r
-void T_Elevate(objtype *ob);\r
-#endif\r
-\r
-extern statetype s_flagwave1;\r
-extern statetype s_flagwave2;\r
-extern statetype s_flagwave3;\r
-extern statetype s_flagwave4;\r
-void SpawnFlag(Sint16 x, Sint16 y);\r
-\r
-#ifndef KEEN5\r
-extern statetype s_throwflag0;\r
-extern statetype s_throwflag1;\r
-extern statetype s_throwflag2;\r
-extern statetype s_throwflag3;\r
-extern statetype s_throwflag4;\r
-extern statetype s_throwflag5;\r
-extern statetype s_throwflag6;\r
-void SpawnThrowFlag(Sint16 x, Sint16 y);\r
-void TossThink(objtype *ob);\r
-void PathThink(objtype *ob);\r
-void FlagAlign(objtype *ob);\r
-#endif\r
-\r
-extern statetype s_stunray1;\r
-extern statetype s_stunray2;\r
-extern statetype s_stunray3;\r
-extern statetype s_stunray4;\r
-extern statetype s_stunhit;\r
-extern statetype s_stunhit2;\r
-void SpawnShot(Uint16 x, Uint16 y, Direction dir);\r
-void ExplodeShot(objtype *ob);\r
-void T_Shot(objtype *ob);\r
-void R_Shot(objtype *ob);\r
-\r
-extern statetype s_door1;\r
-extern statetype s_door2;\r
-extern statetype s_door3;\r
-void DoorOpen(objtype *ob);\r
-\r
-#ifdef KEEN5\r
-extern statetype s_carddoor;\r
-void CardDoorOpen(objtype *ob);\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- OTHER DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if defined KEEN4\r
-#include "K4_DEF.H"\r
-#elif defined KEEN5\r
-#include "K5_DEF.H"\r
-#elif defined KEEN6\r
-#include "K6_DEF.H"\r
-#endif\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean scorescreenkludge;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == EGAGR\r
-\r
-Uint8 starcolors[17] = STARPALETTE;\r
-Uint16 plaquenum[4] = {IDSOFTPIC, PROGTEAMPIC, ARTISTPIC, DIRECTORPIC};\r
-Uint8 termcolors[17] = INTROPALETTE;\r
-Uint8 termcolors2[17] = SHRINKPALETTE;\r
-\r
-Uint8 ortoend[8] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01};\r
-Uint8 andtoend[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// uninitialized variables:\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-typedef struct {\r
- Uint16 height;\r
- Uint16 width;\r
- Uint16 rowofs[200];\r
-} shapehead;\r
-\r
-typedef shapehead _seg * shapeseg;\r
-\r
-// text crawl variables:\r
-memptr linecode;\r
-void far *linestarts[200];\r
-Uint16 sourceline[200];\r
-Uint16 masterlines;\r
-void far *routine;\r
-memptr sourcepic;\r
-memptr bittables;\r
-\r
-// terminator intro variables:\r
-shapeseg commander;\r
-shapeseg keen;\r
-shapeseg both;\r
-memptr scaletable;\r
-memptr cmdrshifts[8];\r
-Sint16 commanderbwide;\r
-Uint16 lastsource;\r
-Uint16 keenstart;\r
-memptr basepl[5];\r
-Uint16 baseplwidth[5];\r
-Uint16 baseplheight[5];\r
-memptr plaqueseg;\r
-Uint16 plaquewidth;\r
-Uint16 plaquewidthwords;\r
-Uint16 plaqueheight;\r
-Uint16 plaqueplane;\r
-Uint16 plaquedelta;\r
-Uint16 *shiftptr;\r
-Uint16 planeon;\r
-Sint16 drawheight;\r
-Uint16 source2;\r
-static Uint16 t_dest;\r
-static Sint16 plaque;\r
-static Sint16 plaquephase;\r
-static Sint16 plaquey;\r
-static Sint16 lastframe;\r
-static Sint16 pageon;\r
-static Sint16 prevbottom[2];\r
-Uint16 pageofs;\r
-Uint16 byteadjust;\r
-\r
-#endif // if GRMODE == EGAGR\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= CheckLastScan\r
-=\r
-============================\r
-*/\r
-\r
-void CheckLastScan(void)\r
-{\r
- if (LastScan)\r
- {\r
- if (storedemo)\r
- {\r
- playstate = ex_resetgame;\r
- restartgame = gd_Normal;\r
- IN_ClearKeysDown();\r
- NewGame();\r
- }\r
-#ifndef KEEN6\r
- else if (LastScan == sc_F1)\r
- {\r
- HelpScreens();\r
- }\r
-#endif\r
- else\r
- {\r
- US_ControlPanel();\r
- if (restartgame)\r
- {\r
- playstate = ex_resetgame;\r
- }\r
- else if (loadedgame)\r
- {\r
- playstate = ex_loadedgame;\r
- }\r
- }\r
- }\r
-}\r
-\r
-#if GRMODE == EGAGR\r
-/*\r
-=============================================================================\r
-\r
- TERMINATOR INTRO\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-============================\r
-=\r
-= LoadPlaque\r
-=\r
-============================\r
-*/\r
-\r
-void LoadPlaque(Sint16 index)\r
-{\r
- Sint16 LocatePlaque(Sint16 elapsed);\r
-\r
- Uint16 chunk, picnum, width, height, planesize, i;\r
- Uint8 far *source;\r
- Uint16 far *dest;\r
-\r
- //\r
- // cache the pic and get pic size\r
- //\r
- chunk = plaquenum[index];\r
- CA_CacheGrChunk(chunk);\r
- picnum = chunk - STARTPICS;\r
- baseplwidth[index] = width = pictable[picnum].width;\r
- baseplheight[index] = height = pictable[picnum].height;\r
- planesize = width * height * 2;\r
-\r
- //\r
- // allocate buffer and convert pic into to our format\r
- // (convert bytes to word indices for faster shift-drawing)\r
- //\r
- MM_GetPtr(&basepl[index], planesize*2); // 2 planes\r
- source = grsegs[chunk];\r
- dest = basepl[index];\r
- for (i=0; i<planesize; i++)\r
- {\r
- *dest++ = *source++ << 1;\r
- }\r
-\r
- //\r
- // pic in original format is no longer needed\r
- //\r
- MM_FreePtr(&grsegs[chunk]);\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= DrawPlaque\r
-=\r
-============================\r
-*/\r
-\r
-void DrawPlaque(Sint16 elapsed, Uint16 x)\r
-{\r
- Uint16 shift, xb;\r
- Sint16 y, bottom, oldbottom;\r
- Uint16 eraseheight, skip, screenoff;\r
-\r
- shift = x & 7;\r
- xb = (pageofs + (x / 8)) + (20 - (plaquewidth >> 1));\r
-\r
- EGAMAPMASK(12); // write to "red" and "intensity" plane (for erasing old pic)\r
-\r
- //\r
- // update position (and pic number)\r
- //\r
- y = LocatePlaque(elapsed);\r
-\r
- //\r
- // erase leftovers of the previous frame\r
- //\r
- bottom = y + plaqueheight;\r
- if (bottom < 0)\r
- bottom = 0;\r
- oldbottom = prevbottom[pageon];\r
- if (bottom < 200 && oldbottom > bottom)\r
- {\r
- eraseheight = oldbottom - bottom;\r
- screenoff = xb + ylookup[bottom];\r
- asm {\r
- mov es, screenseg;\r
- mov bx, linewidth;\r
- sub bx, plaquewidthwords;\r
- sub bx, plaquewidthwords;\r
- mov di, screenoff;\r
- mov dx, eraseheight;\r
- mov si, plaquewidthwords;\r
- xor ax, ax;\r
- }\r
-eraseloop:\r
- asm {\r
- mov cx, si;\r
- rep stosw;\r
- add di, bx;\r
- dec dx;\r
- jnz eraseloop;\r
- }\r
- }\r
- if (bottom > 200)\r
- bottom = 200;\r
- prevbottom[pageon] = bottom;\r
-\r
- //\r
- // draw the (new) pic at the new position\r
- //\r
- drawheight = plaqueheight;\r
- skip = 0;\r
- if (y < 0)\r
- {\r
- skip = -y * (plaquewidth << 1);\r
- drawheight += y;\r
- y = 0;\r
- }\r
- else if (y + plaqueheight > 200)\r
- {\r
- drawheight = 200 - y;\r
- }\r
- source2 = skip + plaqueplane;\r
- if (drawheight > 0)\r
- {\r
- shiftptr = shifttabletable[shift];\r
- t_dest = xb + ylookup[y];\r
- asm {\r
- mov bx, skip;\r
- push bp;\r
- mov bp, shiftptr;\r
- mov es, screenseg;\r
- mov ds, plaqueseg;\r
- mov ah, 4;\r
- mov BYTE PTR ss:planeon, ah;\r
- }\r
-planeloop:\r
- asm {\r
- mov dx, SC_INDEX;\r
- mov al, SC_MAPMASK;\r
- out dx, ax;\r
- mov dx, ss:drawheight;\r
- mov di, ss:t_dest;\r
- }\r
-yloop:\r
- asm {\r
- mov cx, ss:plaquewidth;\r
- xor al, al;\r
- }\r
-xloop:\r
- asm {\r
- mov si, [bx];\r
- add bx, 2;\r
- xor ah, ah;\r
- or ax, [bp+si];\r
- stosb;\r
- mov al, ah;\r
- loop xloop;\r
- stosb;\r
- mov WORD PTR es:[di], 0;\r
- add di, ss:plaquedelta;\r
- dec dx;\r
- jnz yloop;\r
- mov bx, ss:source2;\r
- mov ah, BYTE PTR ss:planeon;\r
- shl ah, 1;\r
- mov BYTE PTR ss:planeon, ah;\r
- cmp ah, 16;\r
- jnz planeloop;\r
- pop bp;\r
- mov ax, ss;\r
- mov ds, ax;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= LocatePlaque\r
-=\r
-============================\r
-*/\r
-\r
-Sint16 LocatePlaque(Sint16 elapsed)\r
-{\r
- switch (plaquephase)\r
- {\r
- case -1:\r
- //\r
- // pic starts to appear\r
- //\r
- plaqueseg = basepl[plaque];\r
- plaquewidth = baseplwidth[plaque];\r
- plaquewidthwords = (plaquewidth + 3) >> 1;\r
- plaqueheight = baseplheight[plaque];\r
- plaquedelta = linewidth - (plaquewidth + 1);\r
- plaqueplane = (plaquewidth * plaqueheight) << 1;\r
- plaquephase++;\r
- lastframe = elapsed;\r
- plaquey = 240;\r
- // no break or return here!\r
- case 0:\r
- //\r
- // pic is moving from the bottom to the center of the screen\r
- //\r
- plaquey -= (elapsed - lastframe) << 1;\r
- if (plaquey < 100)\r
- {\r
- plaquey = 100;\r
- plaquephase++;\r
- }\r
- lastframe = elapsed;\r
- return plaquey - (plaqueheight >> 1);\r
-\r
- case 1:\r
- //\r
- // pic is staying at the center position\r
- //\r
- if (elapsed - lastframe > 200)\r
- {\r
- plaquephase++;\r
- lastframe = elapsed;\r
- }\r
- return 100 - (plaqueheight >> 1);\r
-\r
- case 2:\r
- //\r
- // pic is moving up from the center to the top of the screen\r
- //\r
- plaquey -= (elapsed - lastframe) << 1;\r
- if (plaquey < -40)\r
- {\r
- plaquey = -40;\r
- if (++plaque < 4)\r
- {\r
- plaquephase = -1;\r
- }\r
- else\r
- {\r
- plaquephase = 3;\r
- }\r
- }\r
- lastframe = elapsed;\r
- return plaquey - (plaqueheight >> 1);\r
- }\r
-\r
- return -40;\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= SlideLetters\r
-=\r
-============================\r
-*/\r
-\r
-void SlideLetters(void)\r
-{\r
- Sint16 x, cPosX, screenxb;\r
- Uint16 elapsed, totaltics, dstofs;\r
- Sint16 cStart, cEnd, cTotalMove;\r
- Uint16 shift, srcseg, srcofs;\r
- Sint16 clearleft, copywidth, clearright;\r
- Uint16 srcdif, dstdif;\r
- Sint32 now;\r
-\r
- //\r
- // set up characteristics of the animation\r
- //\r
- EGAWRITEMODE(0);\r
- EGAREADMAP(0); // useless...\r
-\r
- keenstart = keen->width + 200;\r
- EGAREADMAP(1); // also useless ... I think...\r
-\r
- cEnd = 120 - commander->width;\r
- cStart = 320;\r
- cTotalMove = cEnd - cStart;\r
- totaltics = abs(cTotalMove);\r
-\r
- pageofs = pageon = 0;\r
- lasttimecount = TimeCount;\r
- while (TimeCount == lasttimecount);\r
- lasttimecount = TimeCount;\r
-\r
- for (elapsed=0; elapsed <= totaltics; elapsed += tics)\r
- {\r
- //\r
- // draw the credits pic\r
- //\r
- x = ((Sint32)keenstart * (Sint32)(totaltics-elapsed)) / (Sint32)totaltics;\r
- DrawPlaque(elapsed, x);\r
-\r
- //\r
- // get ready to draw draw the "COMMANDER" pic\r
- //\r
- cPosX = cStart + ((Sint32)cTotalMove * (Sint32)elapsed) / (Sint32)totaltics;\r
- cPosX += x & 7;\r
- screenxb = (cPosX + 0x800) / 8 + -0x100;\r
- shift = (cPosX + 0x800) & 7;\r
- srcseg = FP_SEG(cmdrshifts[shift]);\r
- srcofs = 0;\r
- dstofs = pageofs + x / 8;\r
- if (screenxb > 0)\r
- {\r
- clearleft = (screenxb + 1) / 2;\r
- if (screenxb & 1)\r
- dstofs--;\r
- copywidth = 21 - clearleft;\r
- clearright = 0;\r
- }\r
- else if (-commanderbwide + 40 < screenxb)\r
- {\r
- clearleft = 0;\r
- copywidth = 21;\r
- clearright = 0;\r
- srcofs -= screenxb;\r
- }\r
- else\r
- {\r
- clearleft = 0;\r
- copywidth = (commanderbwide + screenxb) / 2;\r
- clearright = 21 - copywidth;\r
- srcofs -= screenxb;\r
- }\r
- srcdif = commanderbwide - copywidth*2;\r
- dstdif = 248 - (clearleft + copywidth + clearright)*2;\r
-\r
- //\r
- // draw "COMMANDER" pic\r
- //\r
- EGAMAPMASK(2);\r
-\r
- asm {\r
- mov di, dstofs;\r
- mov es, screenseg;\r
- mov si, srcofs;\r
- mov lastsource, si;\r
- mov ds, srcseg;\r
- mov dx, 200;\r
- }\r
-yloop:\r
- asm {\r
- xor ax, ax;\r
- mov cx, clearleft;\r
- rep stosw;\r
- mov cx, copywidth;\r
- rep movsw;\r
- xor ax, ax;\r
- mov cx, clearright;\r
- rep stosw;\r
- test dx, 1;\r
- jnz oddline;\r
- mov si, ss:lastsource;\r
- jmp nextline;\r
- }\r
-oddline:\r
- asm {\r
- add si, srcdif;\r
- mov ss:lastsource, si;\r
- }\r
-nextline:\r
- asm {\r
- add di, dstdif;\r
- dec dx;\r
- jnz yloop;\r
- mov ax, ss;\r
- mov ds, ax;\r
- }\r
-\r
- //\r
- // page flip\r
- //\r
- VW_SetScreen(pageofs + x / 8, x & 7);\r
- pageon ^= 1;\r
- if (pageon)\r
- {\r
- pageofs = 124;\r
- }\r
- else\r
- {\r
- pageofs = 0;\r
- }\r
-\r
- //\r
- // handle timing\r
- //\r
- do\r
- {\r
- now = TimeCount;\r
- tics = now - lasttimecount;\r
- } while (tics < 2);\r
- lasttimecount = now;\r
-\r
- //\r
- // handle input\r
- //\r
- if (IN_IsUserInput() && LastScan != sc_F1)\r
- {\r
- LastScan = sc_Space;\r
- }\r
- if (LastScan)\r
- return;\r
- }\r
-\r
- byteadjust = x / 8;\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= DrawScan\r
-=\r
-============================\r
-*/\r
-\r
-void DrawScan(Sint16 far *source, Uint8 far *dest)\r
-{\r
- register Uint16 x;\r
- register Sint16 w;\r
- register Uint16 val;\r
- register Uint16 i;\r
-\r
- val = x = 0;\r
- for (;;)\r
- {\r
- //\r
- // first part: puts black pixels (<width> pixels wide)\r
- //\r
- w = *source++;\r
- if (w == -1)\r
- {\r
- *dest++ = val;\r
- *dest = 0;\r
- return;\r
- }\r
-\r
- x += w;\r
- if (x > 7)\r
- {\r
- *dest++ = val;\r
- val = 0;\r
- i = (x / 8) - 1;\r
- while (i--)\r
- {\r
- *dest++ = 0;\r
- }\r
- x &= 7;\r
- }\r
-\r
- //\r
- // second part: puts white pixels (<width> pixels wide)\r
- //\r
- w = *source++;\r
- if (w == -1)\r
- {\r
- *dest++ = val;\r
- *dest = 0;\r
- return;\r
- }\r
-\r
- val |= ortoend[x];\r
- x += w;\r
- if (x > 7)\r
- {\r
- *dest++ = val;\r
- val = 0xFF;\r
- i = (x / 8) - 1;\r
- while (i--)\r
- {\r
- *dest++ = 0xFF;\r
- }\r
- x &= 7;\r
- }\r
- val &= andtoend[x];\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= BuildScaleShape\r
-=\r
-============================\r
-*/\r
-\r
-void BuildScaleShape(void)\r
-{\r
- Sint16 px, w;\r
- Sint16 far *source;\r
- Sint16 far *dest;\r
- Sint16 y;\r
-\r
- MM_GetPtr((memptr*)&both, 30000);\r
- dest = MK_FP(FP_SEG(both), sizeof(shapehead));\r
-\r
- for (y=0; y<200; y++)\r
- {\r
- both->rowofs[y] = FP_OFF(dest);\r
- px = 0;\r
-\r
- EGAREADMAP(1); // this is pretty useless, we're not reading from EGA memory here\r
-\r
- source = (Sint16 far *)((byte _seg *)commander + commander->rowofs[y]);\r
- w = *source++;\r
- do\r
- {\r
- *dest++ = px;\r
- px = px + w;\r
- w = *source++;\r
- } while (w != -1);\r
-\r
- //\r
- // insert an 80 pixel gap between "COMMANDER" and "KEEN"\r
- //\r
- // This assumes that the rightmost column(s) of the "COMMANDER"\r
- // shape are black. Otherwise the gap would be filled with\r
- // white pixels and the "KEEN" image would use inverted colors\r
- // as a result.\r
- //\r
- px += 80;\r
-\r
- EGAREADMAP(0); // this is pretty useless, we're not reading from EGA memory here\r
-\r
- source = (Sint16 far *)((byte _seg *)keen + keen->rowofs[y]);\r
- source++; // kludgy bit, causes errors when left egde of "KEEN" is no rectangle\r
- w = *source++;\r
- do\r
- {\r
- *dest++ = px;\r
- px = px + w;\r
- w = *source++;\r
- } while (w != -1);\r
-\r
- *dest++ = px; // put last value\r
- *dest++ = -1; // put end-of-line\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= ScalePointScan\r
-=\r
-============================\r
-*/\r
-\r
-void ScalePointScan(Sint16 far *rowptr, Sint16 y, Sint16 toleft, Sint16 far *scaletable)\r
-{\r
- Uint8 far *dest;\r
- Sint16 left, endx;\r
- Uint16 w, val, x, right;\r
- register Sint16 px, sx;\r
-\r
- val = x = 0;\r
- endx = 320 - toleft;\r
- dest = MK_FP(0xA000, pageofs + byteadjust + ylookup[y]);\r
-\r
- if (toleft < 0)\r
- {\r
- left = -toleft;\r
- val = 0;\r
- x = 0;\r
-\r
- for (;;)\r
- {\r
- px = *rowptr++;\r
- sx = scaletable[px];\r
- if (sx > left)\r
- goto drawwhite;\r
-\r
- px = *rowptr++;\r
- sx = scaletable[px];\r
- if (sx > left)\r
- goto drawblack;\r
- }\r
- }\r
-\r
- //\r
- // regular\r
- //\r
- val = 0;\r
- x = toleft & 7;\r
- dest += (toleft >> 3);\r
- left = 0;\r
- rowptr++; // the first value is always 0, we need the next value\r
-drawloop:\r
- px = *rowptr++;\r
- sx = scaletable[px];\r
-\r
- //\r
- // draw/add black pixels\r
- //\r
-drawblack:\r
- w = sx - left;\r
- left = sx;\r
- x += w;\r
- if (x > 7)\r
- {\r
- asm {\r
- les di, dest;\r
- mov al, BYTE PTR val;\r
- stosb;\r
- mov cx, x;\r
- shr cx, 1;\r
- shr cx, 1;\r
- shr cx, 1;\r
- dec cx;\r
- xor al, al;\r
- mov BYTE PTR val, al;\r
- rep stosb;\r
- and x, 7;\r
- mov WORD PTR dest, di;\r
- }\r
- }\r
-\r
- //\r
- // stop if the right side of the screen is reached\r
- //\r
- if (sx > endx)\r
- return;\r
-\r
- //\r
- // stop if the end of the image row is reached\r
- // \r
- // This is only checked after drawing the black part, so the\r
- // combined shape must not end with white pixels on the right.\r
- // That means the rightmost column(s) of the "KEEN" shape must\r
- // always be black.\r
- //\r
- px = *rowptr++;\r
- if (px == -1)\r
- goto clearright;\r
-\r
- sx = scaletable[px];\r
-\r
- //\r
- // draw/add white pixels\r
- //\r
-drawwhite:\r
- w = sx - left;\r
- left = sx;\r
- val |= ortoend[x];\r
- x += w;\r
- if (x > 7)\r
- {\r
- asm {\r
- les di, dest;\r
- mov al, BYTE PTR val;\r
- stosb;\r
- mov cx, x;\r
- shr cx, 1;\r
- shr cx, 1;\r
- shr cx, 1;\r
- dec cx;\r
- mov al, 255;\r
- mov BYTE PTR val, al;\r
- rep stosb;\r
- and x, 7;\r
- mov WORD PTR dest, di;\r
- }\r
- }\r
-\r
- //\r
- // stop if the right side of the screen is reached\r
- //\r
- if (sx > endx)\r
- return;\r
-\r
- val &= andtoend[x];\r
- goto drawloop;\r
-\r
- //\r
- // clear the right side of the screen\r
- //\r
-clearright:\r
- w = 320 - left;\r
- x += w;\r
- if (x > 7)\r
- {\r
- *dest++ = val;\r
- val = 0;\r
- right = x / 8 - 1;\r
- while (right--)\r
- {\r
- *dest++ = 0;\r
- }\r
- x &= 7;\r
- return;\r
- }\r
- return;\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= ScaleDown\r
-=\r
-============================\r
-*/\r
-\r
-void ScaleDown(void)\r
-{\r
- Uint16 i;\r
- Uint16 toleft, ticselapsed, ticstotal, scale, endscale, rownum, rowinc;\r
- Sint32 now;\r
- Sint16 far *rowptr;\r
- Uint16 scaleheight, top, bottom, lastbottom[2];\r
- Sint32 leftorigin;\r
-\r
- //\r
- // set our new palette\r
- //\r
- SetPalette(termcolors2);\r
-\r
- EGAREADMAP(1); // this is pretty useless, we're not reading from EGA memory here\r
-\r
- leftorigin = 120l - commander->width;\r
- BuildScaleShape();\r
- MM_GetPtr(&scaletable, 2500*sizeof(Uint16));\r
-\r
- scale = 0x100; // 100%\r
- endscale = 0x21; // 13% (scale from 200px to 26px)\r
- endscale = 0x21; // redundant\r
- lastbottom[0] = lastbottom[1] = 200;\r
- ticselapsed = 1;\r
- ticstotal = 30; // time for the whole shrinking animation\r
-\r
- while (ticselapsed <= ticstotal)\r
- {\r
- //\r
- // get current scaling\r
- //\r
- if (ticselapsed == ticstotal)\r
- {\r
- scale = endscale;\r
- toleft = 0;\r
- top = 4;\r
- }\r
- else\r
- {\r
- scale = 0x100 - ((0x100-endscale) * ticselapsed) / ticstotal;\r
- toleft = (leftorigin * (ticstotal - ticselapsed)) / ticstotal;\r
- top = (ticselapsed * 4) / ticstotal;\r
- }\r
-\r
- //\r
- // build scale table: scaletable[i] = (i*scale) / 0x100;\r
- //\r
- asm {\r
- xor ax, ax;\r
- xor dx, dx;\r
- mov cx, 2500;\r
- mov bx, scale;\r
- mov es, scaletable;\r
- xor di, di;\r
- }\r
-l1:\r
- asm {\r
- mov es:[di], ah;\r
- inc di;\r
- mov es:[di], dl;\r
- inc di;\r
- add ax, bx;\r
- adc dx, 0;\r
- loop l1;\r
- }\r
-\r
- //\r
- // wait... didn't we already do this?\r
- //\r
- if (ticselapsed == ticstotal)\r
- {\r
- toleft = 0;\r
- }\r
- else\r
- {\r
- toleft = (leftorigin * (ticstotal - ticselapsed)) / ticstotal;\r
- }\r
-\r
- //\r
- // prepare scaled drawing process\r
- //\r
- scaleheight = ((Sint16 _seg *)scaletable)[200];\r
- rownum = 0;\r
- rowinc = 0x10000l / scale;\r
- bufferofs = pageofs + byteadjust;\r
-\r
- //\r
- // erase stuff at the top\r
- //\r
- if (top > 0)\r
- {\r
- VW_Bar(0, 0, 320, top, BLACK);\r
- }\r
-\r
- //\r
- // draw the scaled shape\r
- //\r
- EGAWRITEMODE(0);\r
- EGAMAPMASK(15);\r
-\r
- for (i=0; i<scaleheight; i++)\r
- {\r
- rowptr = (Sint16 far *)((byte _seg *)both + both->rowofs[rownum >> 8]);\r
- ScalePointScan(rowptr, i+top, toleft, scaletable);\r
-\r
- rownum += rowinc;\r
- }\r
-\r
- //\r
- // erase leftovers at the bottom of the screen\r
- //\r
- bufferofs = pageofs + byteadjust;\r
- bottom = scaleheight + top;\r
- if (lastbottom[pageon] > bottom)\r
- {\r
- VW_Bar(0, bottom, 320, lastbottom[pageon] - bottom, BLACK);\r
- lastbottom[pageon] = bottom;\r
- }\r
-\r
- //\r
- // page flip\r
- //\r
- VW_SetScreen(pageofs+byteadjust, 0);\r
- pageon ^= 1;\r
- if (pageon)\r
- {\r
- pageofs = 124;\r
- }\r
- else\r
- {\r
- pageofs = 0;\r
- }\r
-\r
- //\r
- // handle timing\r
- //\r
- now = TimeCount;\r
- tics = now - lasttimecount;\r
- lasttimecount = now;\r
- if (tics > 8)\r
- tics = 8; // don't skip too many frames on slow systems\r
-\r
- if (ticselapsed == ticstotal)\r
- break;\r
-\r
- ticselapsed += tics;\r
- if (ticselapsed > ticstotal)\r
- ticselapsed = ticstotal;\r
-\r
- //\r
- // handle input\r
- //\r
- if (IN_IsUserInput() && LastScan != sc_F1)\r
- {\r
- LastScan = sc_Space;\r
- }\r
- if (LastScan)\r
- return; // BUG: buffers aren't freed!\r
- }\r
-\r
- //\r
- // free the buffers\r
- //\r
- MM_FreePtr(&scaletable);\r
- MM_FreePtr((memptr*)&both);\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= FinishPage\r
-=\r
-============================\r
-*/\r
-\r
-void FinishPage(void)\r
-{\r
- Sint16 swap, temp, i, n, x, y;\r
- Uint16 ofs;\r
- Sint16 top, bottom, delta;\r
- Uint8 bitmask[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};\r
- Sint16 xtable[320], ytable[200];\r
-\r
- //\r
- // build lookup tables\r
- //\r
- for (i=0; i<320; i++)\r
- {\r
- xtable[i] = i;\r
- }\r
- for (i=0; i<320; i++)\r
- {\r
- swap = random(320);\r
- temp = xtable[swap];\r
- xtable[swap] = xtable[i];\r
- xtable[i] = temp;\r
- }\r
- for (i=0; i<200; i++)\r
- {\r
- ytable[i] = xtable[i];\r
- }\r
-\r
- //\r
- // set up display\r
- //\r
- VW_SetDefaultColors();\r
- if (pageon)\r
- {\r
- bufferofs = byteadjust + 124;\r
- displayofs = byteadjust;\r
- }\r
- else\r
- {\r
- bufferofs = byteadjust;\r
- displayofs = byteadjust + 124;\r
- }\r
- VW_SetScreen(displayofs, 0);\r
-\r
- //\r
- // draw title pic to the non-displayed buffer\r
- //\r
- VW_DrawPic(0, 0, TITLEPICPIC);\r
-\r
- //\r
- // copy "random" pixels from the non-displayed area\r
- // into the displayed area to create the "fizzle" effect\r
- //\r
- delta = displayofs - bufferofs;\r
-\r
- //\r
- // set ES register for the pixel copying code in the loops\r
- //\r
- // This is faster than setting the ES register in the loops,\r
- // but you need to make sure nothing in the loops overwrites\r
- // the ES register, otherwise the code won't work correctly.\r
- //\r
- asm mov es, screenseg;\r
-\r
- for (i = 0; i< 360; i++)\r
- {\r
- top = i - 160;\r
- if (top < 0)\r
- top = 0;\r
-\r
- bottom = i;\r
- if (bottom >= 200)\r
- bottom = 199;\r
-\r
- for (y = top; y <= bottom; y++)\r
- {\r
- ofs = bufferofs + ylookup[y];\r
- for (n=0; n<2; n++)\r
- {\r
- x = xtable[ytable[y]];\r
- if (++ytable[y] == 320)\r
- {\r
- ytable[y] = 0;\r
- }\r
-\r
- //\r
- // set bitmask for our x value\r
- //\r
- asm mov cx, x;\r
- asm mov si, cx;\r
- asm and si, 7;\r
- asm cli;\r
- asm mov dx, GC_INDEX;\r
- asm mov al, GC_BITMASK;\r
- asm mov ah, BYTE PTR bitmask[si];\r
- asm out dx, ax;\r
- asm sti;\r
-\r
- //\r
- // set up source and dest index registers\r
- //\r
- asm mov si, ofs;\r
- asm shr cx, 1;\r
- asm shr cx, 1;\r
- asm shr cx, 1;\r
- asm add si, cx;\r
- asm mov di, si;\r
- asm add di, delta;\r
-\r
- //\r
- // copy the pixel data (all 4 planes)\r
- //\r
- // "blue" plane:\r
- asm mov dx, SC_INDEX;\r
- asm mov ax, SC_MAPMASK + 1*256;\r
- asm out dx, ax;\r
- asm mov dx, GC_INDEX;\r
- asm mov ax, GC_READMAP + 0*256;\r
- asm out dx, ax;\r
- asm mov bl, es:[si];\r
- asm xchg bl, es:[di];\r
- // "green" plane:\r
- asm mov dx, SC_INDEX;\r
- asm mov ax, SC_MAPMASK + 2*256;\r
- asm out dx, ax;\r
- asm mov dx, GC_INDEX;\r
- asm mov ax, GC_READMAP + 1*256;\r
- asm out dx, ax;\r
- asm mov bl, es:[si];\r
- asm xchg bl, es:[di];\r
- // "red" plane:\r
- asm mov dx, SC_INDEX;\r
- asm mov ax, SC_MAPMASK + 4*256;\r
- asm out dx, ax;\r
- asm mov dx, GC_INDEX;\r
- asm mov ax, GC_READMAP + 2*256;\r
- asm out dx, ax;\r
- asm mov bl, es:[si];\r
- asm xchg bl, es:[di];\r
- // "intensity" plane:\r
- asm mov dx, SC_INDEX;\r
- asm mov ax, SC_MAPMASK + 8*256;\r
- asm out dx, ax;\r
- asm mov dx, GC_INDEX;\r
- asm mov ax, GC_READMAP + 3*256;\r
- asm out dx, ax;\r
- asm mov bl, es:[si];\r
- asm xchg bl, es:[di];\r
- }\r
- }\r
-\r
- VW_WaitVBL(1); // so the fizzle animation won't go super fast\r
-\r
- if (IN_IsUserInput() && LastScan != sc_F1)\r
- {\r
- LastScan = sc_Space;\r
- }\r
- if (LastScan)\r
- {\r
- EGABITMASK(0xFF);\r
- EGAMAPMASK(15);\r
- return;\r
- }\r
- }\r
-\r
- //\r
- // clean up EGA registers\r
- //\r
- EGABITMASK(0xFF);\r
- EGAMAPMASK(15);\r
-\r
- //\r
- // pause for 6 seconds\r
- //\r
- IN_UserInput(6 * TickBase, false);\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= Terminator\r
-=\r
-============================\r
-*/\r
-\r
-void Terminator(void)\r
-{\r
- Uint16 i, shift, bufsize;\r
- Sint16 far *source;\r
- Uint8 far *dest;\r
- Uint16 srcseg, destseg;\r
- boolean pagefinished;\r
- Uint16 rowofs[200];\r
-\r
- pagefinished = false;\r
- CA_SetAllPurge();\r
- SetPaletteEx(colors[0]); // all black\r
- VW_ClearVideo(BLACK);\r
- VW_SetLineWidth(248); // 1984 pixels total, we're using 992 per "page"\r
-\r
- CA_CacheGrChunk(TITLEPICPIC);\r
- CA_CacheGrChunk(BIGCOMMANDER);\r
- CA_CacheGrChunk(BIGKEEN);\r
- keen = grsegs[BIGKEEN];\r
- commander = grsegs[BIGCOMMANDER];\r
-\r
- EGAMAPMASK(1);\r
-\r
- keenstart = keen->width + 200;\r
- VW_SetScreen((keenstart/8)+1, 0);\r
-\r
- //\r
- // draw the "KEEN" pic (to first "page")\r
- //\r
- for (i=0; i<200; i++)\r
- {\r
- source = (Sint16 far *)((byte _seg *)keen + keen->rowofs[i]);\r
- dest = MK_FP(0xA000, ylookup[i]);\r
- dest += 25; // 25 bytes -> 200 pixels\r
- DrawScan(source, dest);\r
- }\r
- //\r
- // copy pic from first "page" to second "page"\r
- //\r
- VW_ScreenToScreen(0, 124, 109, 200);\r
-\r
- //\r
- // create pre-shifted image buffers for the "COMMANDER" pic\r
- // (only 100 pixels high instead of 200 pixels to save memory)\r
- //\r
- commanderbwide = (commander->width + 7) / 8;\r
- commanderbwide = (commanderbwide + 3) & ~1;\r
- bufsize = commanderbwide * 100; // half height\r
- for (shift = 0; shift < 8; shift++)\r
- {\r
- MM_GetPtr(&cmdrshifts[shift], bufsize);\r
- }\r
-\r
- //\r
- // re-assign shape pointers (memory manager might have moved the buffers)\r
- //\r
- keen = grsegs[BIGKEEN];\r
- commander = grsegs[BIGCOMMANDER];\r
-\r
- //\r
- // draw the first (unshifted) version of the "COMMANDER" pic to the buffer\r
- //\r
- for (i=0; i<100; i++)\r
- {\r
- rowofs[i*2] = rowofs[i*2+1] = i * commanderbwide;\r
- source = (Sint16 far *)((byte _seg *)commander + commander->rowofs[i*2]);\r
- dest = (Uint8 _seg *)cmdrshifts[0] + rowofs[i*2];\r
- DrawScan(source, dest);\r
- }\r
-\r
- //\r
- // create the shifted versions of the "COMMANDER" pic\r
- //\r
- for (shift = 1; shift < 8; shift++)\r
- {\r
- srcseg = FP_SEG(cmdrshifts[shift-1]);\r
- destseg = FP_SEG(cmdrshifts[shift]);\r
- asm {\r
- mov ds, srcseg;\r
- mov es, destseg;\r
- mov cx, bufsize;\r
- clc;\r
- xor si, si;\r
- xor di, di;\r
- }\r
-l1:\r
- asm {\r
- lodsb;\r
- rcr al, 1;\r
- stosb;\r
- loop l1;\r
- mov ax, ss;\r
- mov ds, ax;\r
- }\r
- }\r
-\r
- //\r
- // prepare (and set) the palettes\r
- //\r
- termcolors[16] = termcolors2[16] = termcolors[16] = bordercolor;\r
- SetPalette(termcolors);\r
-\r
- //\r
- // cache the credits pics (they are converted into a special\r
- // format to make shifted drawing easier during the animation)\r
- //\r
- for (i=0; i<4; i++)\r
- {\r
- LoadPlaque(i);\r
- }\r
-\r
- //\r
- // play the animation\r
- //\r
- plaque = lastframe = 0;\r
- plaquephase = -1;\r
- SlideLetters();\r
-\r
- //\r
- // free some of the buffers\r
- // (shrink animation needs additional memory)\r
- //\r
- for (i=0; i<4; i++)\r
- {\r
- MM_FreePtr(&basepl[i]);\r
- }\r
- for (shift=0; shift<8; shift++)\r
- {\r
- MM_FreePtr(&cmdrshifts[shift]);\r
- }\r
-\r
- //\r
- // do the shrinking and fizzle fade animations\r
- // (if intro wasn't aborted)\r
- //\r
- if (!LastScan)\r
- {\r
- ScaleDown();\r
- }\r
-\r
- if (!LastScan)\r
- {\r
- FinishPage();\r
- pagefinished = true;\r
- }\r
-\r
- //\r
- // free the remaining buffers\r
- //\r
- MM_SetPurge(&grsegs[BIGCOMMANDER], 3);\r
- MM_SetPurge(&grsegs[BIGKEEN], 3);\r
-\r
- //\r
- // switch back to default graphics settings\r
- //\r
- VW_ClearVideo(BLACK);\r
- VW_SetLineWidth(SCREENWIDTH);\r
- VW_SetDefaultColors();\r
- RF_FixOfs();\r
- CA_ClearMarks();\r
-\r
- //\r
- // handle input and main menu stuff\r
- //\r
- if (LastScan == sc_None)\r
- {\r
- return;\r
- }\r
-#ifndef KEEN6\r
- if (LastScan == sc_F1)\r
- {\r
- HelpScreens();\r
- return;\r
- }\r
-#endif\r
- if (!pagefinished)\r
- {\r
- RF_FixOfs(); //redundant\r
- CA_CacheGrChunk(TITLEPICPIC);\r
- VW_DrawPic(0, 0, TITLEPICPIC);\r
- VW_SetScreen(bufferofs, 0);\r
- IN_Ack();\r
- CA_ClearMarks();\r
- if (storedemo)\r
- {\r
- playstate = ex_resetgame;\r
- restartgame = gd_Normal;\r
- IN_ClearKeysDown();\r
- NewGame();\r
- return;\r
- }\r
- }\r
-\r
- US_ControlPanel();\r
- if (restartgame)\r
- {\r
- playstate = ex_resetgame;\r
- }\r
- else if (loadedgame)\r
- {\r
- playstate = ex_loadedgame;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- STAR WARS TEXT CRAWL\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-============================\r
-=\r
-= BuildBitTables\r
-=\r
-============================\r
-*/\r
-\r
-void BuildBitTables(void)\r
-{\r
- Uint16 bit1, bit2, i;\r
- Uint8 far *buffer;\r
-\r
- MM_GetPtr(&bittables, 0x4000);\r
- buffer = bittables;\r
-\r
- //\r
- // generate a lookup table that maps the bits of the "texture" (bit1)\r
- // to the appropriate bit for the screen position (bit2) to make the\r
- // scaler code faster and smaller\r
- //\r
- // table[((7-b1)*8+(7-b2))*256+i] = (i & (1 << (7-b1))) ? (1 << (7-b2)) : 0;\r
- //\r
- for (bit1 = 1; bit1 < 0x100; bit1 <<= 1)\r
- {\r
- for (bit2 = 1; bit2 < 0x100; bit2 <<= 1)\r
- {\r
- for (i = 0; i < 0x100; i++, buffer++)\r
- {\r
- if (i & bit1)\r
- {\r
- *buffer = bit2;\r
- }\r
- else\r
- {\r
- *buffer = 0;\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= CompileSWUpdate\r
-=\r
-============================\r
-*/\r
-\r
-void CompileSWUpdate(void)\r
-{\r
- Sint16 y;\r
- Uint16 i, width, scalestep, step;\r
- Sint32 scale, rowof, xpos, size;\r
- void far *buffer;\r
- Uint8 srcoff, srcbit, bitpos;\r
- Uint16 destoff, srcx, left, orindex, lastoff;\r
-\r
- BuildBitTables();\r
- size = 190000;\r
- MM_GetPtr(&linecode, size);\r
- buffer = linecode;\r
- //\r
- // Note: You should really lock the pointer to prevent the memmory manager\r
- // from moving the buffer around. This code stores a bunch of pointers to\r
- // this memory block in the linestarts array. Those pointers will not be\r
- // updated when the memory manager moves the buffer around and the game\r
- // might end up crashing (or worse) when trying to run the "code" at the\r
- // memory location after the data was moved. The game starts playing music\r
- // after this function is done, which may or may not cause the memory\r
- // manager to move memory blocks around.\r
- //\r
-\r
- //\r
- // move the buffer address into ES:DI (and keep it there)\r
- //\r
- asm mov es, WORD PTR buffer+2;\r
- asm mov di, WORD PTR buffer;\r
- //\r
- // Since the address is kept in ES:DI, we must save and restore\r
- // the ES register when calling other functions (push es / pop es).\r
- // The Borland C compiler always saves and restores the DI register\r
- // when a function modifies it, so we don't need to worry about\r
- // that register. This is a bit of an ugly hack, but it makes this\r
- // code a little faster and smaller.\r
- //\r
-\r
- scale = 320l << 11;\r
- scalestep = (((Uint32)(320-40) << 11) / 200); // roughly 1.4 pixels per step, going from 320 pixels to 40 pixels in 200 steps\r
- rowof = 0;\r
-\r
- for (y=199; y >= 0; y--)\r
- {\r
- //\r
- // draw a blue line for the current row\r
- //\r
- asm push es;\r
- VW_Hlin(0, 320, y, BLUE);\r
- asm pop es;\r
-\r
- //\r
- // update the buffer variable with the current (normalized) ES:DI address\r
- //\r
- asm mov WORD PTR buffer, di;\r
- asm mov WORD PTR buffer+2, es;\r
-\r
- //\r
- // store the address in the scaler lookup table\r
- //\r
- linestarts[y] = buffer;\r
-\r
- //\r
- // get current scaling factors\r
- //\r
- width = ((Uint16)((scale/2) >> 11)) << 1; // some trickery to make sure width is even\r
- sourceline[y] = (rowof >> 11);\r
- step = (336l << 11) / width;\r
- xpos = 0;\r
- rowof += step;\r
- left = 160 - (width >> 1);\r
- destoff = ylookup[y] + left / 8;\r
- bitpos = left & 7;\r
-\r
- //\r
- // generate the machine code\r
- //\r
- // MOV CX, SS\r
- // MOV SS, AX\r
- // ADD DI, <destoff>\r
- // XOR AL, AL\r
- //\r
- asm mov ax, 0D18Ch;\r
- asm stosw;\r
- asm mov ax, 0D08Eh;\r
- asm stosw;\r
- asm mov ax, 0C781h;\r
- asm stosw;\r
- asm mov ax, destoff;\r
- asm stosw;\r
- asm mov ax, 0C030h;\r
- asm stosw;\r
-\r
- lastoff = -1;\r
- for (i=0; i<width; i++)\r
- {\r
- srcx = (xpos >> 11);\r
- srcoff = (srcx / 8);\r
- srcbit = srcx & 7;\r
-\r
- orindex = ((7-srcbit)*8 + 7-bitpos) << 8;\r
- if (srcoff != lastoff)\r
- {\r
- //\r
- // MOV BL, [BP + <srcoff>]\r
- //\r
- asm mov ax, 5E8Ah;\r
- asm stosw;\r
- asm mov al, srcoff;\r
- asm stosb;\r
-\r
- lastoff = srcoff;\r
- }\r
-\r
- //\r
- // OR AL, [BX + <orindex>]\r
- //\r
- asm mov ax, 870Ah;\r
- asm stosw;\r
- asm mov ax, orindex;\r
- asm stosw;\r
-\r
- bitpos++;\r
- if (bitpos == 8)\r
- {\r
- bitpos = 0;\r
-\r
- //\r
- // STOSB\r
- // XOR AL, AL\r
- //\r
- asm mov ax, 30AAh;\r
- asm stosw;\r
- asm mov al, 0C0h;\r
- asm stosb;\r
- }\r
-\r
- xpos += step;\r
- }\r
-\r
- if (bitpos)\r
- {\r
- //\r
- // STOSB\r
- //\r
- asm mov al, 0AAh;\r
- asm stosb;\r
- }\r
- //\r
- // generate end of subroutine\r
- //\r
- // MOV SS, CX\r
- // RETF\r
- //\r
- asm mov ax, 0D18Eh;\r
- asm stosw;\r
- asm mov al, 0CBh;\r
- asm stosb;\r
-\r
- //\r
- // normalize ES:DI\r
- //\r
- asm mov ax, di;\r
- asm shr ax, 1;\r
- asm shr ax, 1;\r
- asm shr ax, 1;\r
- asm shr ax, 1;\r
- asm mov bx, es;\r
- asm add ax, bx;\r
- asm mov es, ax;\r
- asm and di, 0Fh;\r
-\r
- //\r
- // update scale value for next row\r
- //\r
- scale -= scalestep;\r
-\r
- //\r
- // replace the blue line with the row from the background image\r
- //\r
- asm push es;\r
- VW_ScreenToScreen(ylookup[y] + 0x8000, ylookup[y], 40, 1);\r
- asm pop es;\r
-\r
- if (LastScan)\r
- return;\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= TranslateString\r
-=\r
-============================\r
-*/\r
-\r
-void TranslateString(char *text)\r
-{\r
- char c;\r
-\r
- while (*text)\r
- {\r
- c = *text;\r
-\r
- if (c >= 'A' && c <= 'Z')\r
- {\r
- c = c + -33;\r
- }\r
- else if (c >= 'a' && c <= 'z')\r
- {\r
- c = c + -39;\r
- }\r
- else if (c == '.')\r
- {\r
- c = 84;\r
- }\r
- else if (c == ',')\r
- {\r
- c = 85;\r
- }\r
- else if (c == '-')\r
- {\r
- c = 86;\r
- }\r
- else if (c == '"')\r
- {\r
- c = 87;\r
- }\r
- else if (c == ' ')\r
- {\r
- c = 88;\r
- }\r
- else if (c == '!')\r
- {\r
- c = 89;\r
- }\r
- else if (c == '\'')\r
- {\r
- c = 90;\r
- }\r
- else if (c != '\n')\r
- {\r
- c = 84; // any unhandled character is drawn as '.'\r
- }\r
-\r
- *text++ = c;\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= DrawSWText\r
-=\r
-============================\r
-*/\r
-\r
-void DrawSWText(void)\r
-{\r
- char far *text;\r
- char *ptr;\r
- char c;\r
- char strbuf[80];\r
-\r
- WindowX = 0;\r
- WindowW = 336;\r
- PrintY = 1; // always leave the first line blank\r
- bufferofs = 0;\r
- panadjust = 0;\r
- text = swtext;\r
- masterlines = 0;\r
-\r
- //\r
- // draw the entire text to video memory\r
- //\r
- while (*text)\r
- {\r
- ptr = strbuf;\r
- do\r
- {\r
- c = *text++;\r
- *ptr++ = c;\r
- } while (c != '\n' && c != '\0');\r
- *ptr = '\0';\r
-\r
- TranslateString(strbuf);\r
-\r
- US_CPrint(strbuf);\r
-\r
- bufferofs += ylookup[PrintY];\r
- masterlines += PrintY;\r
- PrintY = 0;\r
- }\r
-\r
- //\r
- // allocate a buffer large enough to hold the entire text image\r
- // and move the image data from video memory into that buffer\r
- //\r
- MM_GetPtr(&sourcepic, bufferofs);\r
- EGAREADMAP(1); // read from "green" plane (doesn't really matter from which plane we read)\r
- movedata(screenseg, 0, FP_SEG(sourcepic), 0, bufferofs);\r
-\r
- //\r
- // erase the (first screen of the) text from video memory.\r
- // we're going to display this area and copy the backgound pic\r
- // here line-by-line as the scalers are generated and we don't\r
- // want to have parts of the text still visible at that point.\r
- //\r
- bufferofs = 0;\r
- VW_Bar(0, 0, 320, 200, BLACK);\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= ScrollSWText\r
-=\r
-============================\r
-*/\r
-\r
-void ScrollSWText(void)\r
-{\r
- Sint32 now;\r
- Uint16 pos;\r
- Sint16 i, rowof;\r
-\r
- tics = TimeCount = lasttimecount = 0;\r
-\r
- EGAWRITEMODE(0);\r
- EGAMAPMASK(8); // only draw to the "intensity" plane (so we don't erase the backgound pic)\r
-\r
- pos = 0;\r
- while (masterlines + 400 >= pos)\r
- {\r
- for (i = 199; i >= 0; i--)\r
- {\r
- rowof = pos - sourceline[i];\r
- if (rowof < 0 || rowof >= masterlines)\r
- {\r
- masterofs = 0; // draw the first (blank) line of the buffer\r
- }\r
- else\r
- {\r
- masterofs = rowof * 42;\r
- }\r
- routine = linestarts[i];\r
- asm {\r
- mov es, screenseg;\r
- mov di, pageofs;\r
- mov ds, bittables;\r
- push bp;\r
- mov bp, ss:masterofs;\r
- mov ax, ss:sourcepic;\r
- xor bh, bh;\r
- cli; // disable interrupts (scaler changes register SS, so interrupts would be fatal!)\r
- call ss:routine;\r
- sti; // enable interrupts again\r
- pop bp;\r
- mov ax, ss;\r
- mov ds, ax;\r
- }\r
- }\r
-\r
- VW_SetScreen(pageofs, 0);\r
- pageon ^= 1;\r
- pageofs = pageon << 15;\r
-\r
- now = TimeCount;\r
- tics = tics + (now - lasttimecount);\r
- lasttimecount = now;\r
- if (tics > 20)\r
- tics = 20;\r
-\r
- pos = pos + tics / 4;\r
- tics &= 3;\r
-\r
- if (IN_IsUserInput() && LastScan != sc_F1)\r
- LastScan = sc_Space;\r
-\r
- if (LastScan)\r
- break;\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= StarWars\r
-=\r
-============================\r
-*/\r
-\r
-void StarWars(void)\r
-{\r
- SetPaletteEx(colors[0]); // all black\r
- VW_ClearVideo(BLACK);\r
- VW_SetLineWidth(42); // 336 pixels\r
- VW_SetScreen(0, 0);\r
- pageon = pageofs = 0;\r
- CA_SetAllPurge();\r
- CA_CacheGrChunk(STARTFONT+2);\r
- fontnumber = 2;\r
- DrawSWText();\r
- fontnumber = 0;\r
-\r
- CA_CacheGrChunk(SW_BACKGROUNDPIC);\r
- bufferofs = 0x8000;\r
- VW_DrawPic(0, 0, SW_BACKGROUNDPIC);\r
- CA_SetAllPurge();\r
- SetPaletteEx(starcolors);\r
- bufferofs = 0;\r
- CompileSWUpdate();\r
-\r
- if (!LastScan)\r
- {\r
- StartMusic(STARWARSMUSIC);\r
- ScrollSWText();\r
- StopMusic();\r
- }\r
-\r
- MM_FreePtr(&linecode);\r
- MM_FreePtr(&bittables);\r
- MM_FreePtr(&sourcepic);\r
-\r
- VW_ClearVideo(BLACK);\r
- VW_SetLineWidth(SCREENWIDTH);\r
- VW_SetDefaultColors();\r
- RF_FixOfs();\r
- CA_ClearMarks();\r
-\r
- CheckLastScan();\r
-}\r
-\r
-#endif // if GRMODE == EGAGR\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= ShowTitle\r
-=\r
-============================\r
-*/\r
-\r
-void ShowTitle(void)\r
-{\r
- panadjust = 0;\r
- CA_CacheGrChunk(TITLEPICPIC);\r
- VW_DrawPic(0, 0, TITLEPICPIC);\r
-#if GRMODE == CGAGR\r
- VW_UpdateScreen();\r
-#else\r
- VW_SetScreen(displayofs, 0);\r
- VW_ScreenToScreen(bufferofs, displayofs, 42, 224);\r
-#endif\r
- IN_UserInput(6*TickBase, false);\r
- CA_ClearMarks();\r
- CheckLastScan();\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if GRMODE == CGAGR\r
-/*\r
-============================\r
-=\r
-= ShowCredits\r
-=\r
-============================\r
-*/\r
-\r
-void ShowCredits(void)\r
-{\r
- panadjust = 0;\r
- CA_CacheGrChunk(SW_BACKGROUNDPIC);\r
- VW_DrawPic(0, 0, SW_BACKGROUNDPIC);\r
- VW_UpdateScreen();\r
- IN_UserInput(6*TickBase, false);\r
- CA_ClearMarks();\r
- CheckLastScan();\r
-}\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= RunDemo\r
-=\r
-============================\r
-*/\r
-\r
-void RunDemo(Sint16 num)\r
-{\r
- Uint16 far *demodata;\r
- \r
- NewGame();\r
- num += DEMO0;\r
- CA_CacheGrChunk(num);\r
- demodata = grsegs[num];\r
- gamestate.mapon = demodata[0];\r
- DemoSize = demodata[1];\r
- MM_GetPtr(&(memptr)DemoBuffer, DemoSize);\r
- MM_SetLock(&(memptr)DemoBuffer, true);\r
- _fmemcpy(DemoBuffer, ((char _seg *)grsegs[num])+4, DemoSize);\r
- MM_FreePtr(&grsegs[num]);\r
- IN_StartDemoPlayback(DemoBuffer, DemoSize);\r
- SetupGameLevel(true);\r
- if (scorescreenkludge)\r
- {\r
- DrawHighScores();\r
- }\r
- PlayLoop();\r
- IN_StopDemo();\r
- MM_FreePtr(&(memptr)DemoBuffer);\r
- VW_FixRefreshBuffer();\r
- CA_ClearMarks();\r
- CheckLastScan();\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= DrawHighScores\r
-=\r
-============================\r
-*/\r
-\r
-void DrawHighScores(void)\r
-{\r
- Uint16 i, n;\r
- Uint16 width, height;\r
- HighScore *entry;\r
- Uint16 oldbufferofs;\r
- char buf[16], *bufptr;\r
- \r
- RF_NewPosition(0, 0);\r
- oldbufferofs = bufferofs;\r
- bufferofs = masterofs;\r
-#ifdef KEEN5\r
-#if GRMODE == CGAGR\r
- fontcolor = 2;\r
-#else\r
- fontcolor = BLUE ^ LIGHTMAGENTA; // blue text on light magenta background (XOR draw mode!)\r
-#endif\r
-#endif\r
- for (i=0, entry=&Scores[0]; i<MaxScores; i++, entry++)\r
- {\r
- PrintY = i*16 + HIGHSCORE_TOP;\r
- PrintX = HIGHSCORE_LEFT;\r
- US_Print(entry->name);\r
-#ifdef KEEN4\r
- PrintX = 152;\r
- for (n=0; n<entry->completed; n++)\r
- {\r
- VWB_DrawTile8(PrintX, PrintY+1, 71);\r
- PrintX += 8;\r
- }\r
-#endif\r
- ultoa(entry->score, buf, 10);\r
- for (bufptr=buf; *bufptr; bufptr++)\r
- {\r
- *bufptr = *bufptr + 81;\r
- }\r
- USL_MeasureString(buf, &width, &height);\r
- PrintX = HIGHSCORE_RIGHT - width;\r
- US_Print(buf);\r
- }\r
- fontcolor = WHITE; // back to default color\r
- bufferofs = oldbufferofs;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= CheckHighScore\r
-=\r
-============================\r
-*/\r
-\r
-void CheckHighScore(Sint32 score, Sint16 completed)\r
-{\r
- Uint16 i, n;\r
- Sint16 index;\r
- HighScore entry;\r
- \r
- strcpy(entry.name, ""); //Note: 'entry.name[0] = 0;' would be more efficient\r
- entry.score = score;\r
- entry.completed = completed;\r
- for (i=0, index=-1; i<MaxScores; i++)\r
- {\r
- if (Scores[i].score < entry.score ||\r
- (Scores[i].score == entry.score && Scores[i].completed < entry.completed))\r
- {\r
- n=MaxScores;\r
- while (--n > i)\r
- {\r
- Scores[n] = Scores[n-1];\r
- }\r
- Scores[i] = entry;\r
- index = i;\r
- HighScoresDirty = true;\r
- break;\r
- }\r
- }\r
- if (index != -1)\r
- {\r
- scorescreenkludge = true;\r
- gamestate.mapon = HIGHSCORE_MAP;\r
- SetupGameLevel(true);\r
- DrawHighScores();\r
-#ifdef KEEN5\r
-#if GRMODE == CGAGR\r
- fontcolor = 2;\r
-#else\r
- fontcolor = BLUE ^ LIGHTMAGENTA; // blue text on light magenta background (XOR draw mode!)\r
-#endif\r
-#endif\r
- RF_Refresh();\r
- RF_Refresh();\r
- PrintY = i*16 + HIGHSCORE_TOP;\r
- PrintX = HIGHSCORE_LEFT;\r
- US_LineInput(PrintX, PrintY, Scores[index].name, NULL, true, MaxHighName, 112);\r
- scorescreenkludge = false;\r
- }\r
-#ifdef KEEN5\r
- fontcolor = 15; // back to default color (white)\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= ShowHighScores\r
-=\r
-============================\r
-*/\r
-\r
-void ShowHighScores(void)\r
-{\r
- scorescreenkludge = true;\r
- IN_ClearKeysDown();\r
- RunDemo(4);\r
- scorescreenkludge = false;\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Uint16 fadecount;\r
-Sint16 levelcompleted;\r
-Sint32 chunkcount, chunkmax, handpic;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void FadeAndUnhook(void);\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= FreeGraphics\r
-=\r
-============================\r
-*/\r
-\r
-void FreeGraphics(void)\r
-{\r
- Sint16 i;\r
- for (i=STARTSPRITES; i<STARTSPRITES+NUMSPRITES; i++)\r
- {\r
- if (grsegs[i])\r
- {\r
- MM_SetPurge(&grsegs[i], PURGE_LAST);\r
- }\r
- }\r
- for (i=STARTTILE16; i<STARTEXTERNS; i++)\r
- {\r
- if (grsegs[i])\r
- {\r
- MM_SetPurge(&grsegs[i], PURGE_LAST);\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= NewGame\r
-=\r
-= Set up new game to start from the beginning\r
-=\r
-=====================\r
-*/\r
-\r
-void NewGame(void)\r
-{\r
- memset(&gamestate, 0, sizeof(gamestate));\r
- gamestate.nextextra = 20000;\r
- gamestate.lives = 3;\r
- gamestate.ammo = 5;\r
-}\r
-\r
-//===========================================================================\r
-\r
-#ifndef KEEN5\r
-/*\r
-============================\r
-=\r
-= GameOver\r
-=\r
-============================\r
-*/\r
-\r
-void GameOver(void)\r
-{\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(16, 3);\r
- US_PrintCentered("Game Over!");\r
- VW_UpdateScreen();\r
- IN_ClearKeysDown();\r
- IN_UserInput(4*TickBase, false);\r
-}\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= SaveTheGame\r
-=\r
-============================\r
-*/\r
-\r
-#define RLETAG 0xABCD\r
-\r
-boolean SaveTheGame(Sint16 handle)\r
-{\r
- Uint16 i,compressed,expanded;\r
- objtype *ob;\r
- memptr bigbuffer;\r
-\r
- gamestate.riding = NULL;\r
-\r
- if (!CA_FarWrite(handle, (byte far *)&gamestate, sizeof(gamestate)))\r
- return false;\r
-\r
- expanded = mapwidth * mapheight * 2;\r
- MM_GetPtr(&bigbuffer, expanded);\r
-\r
- for (i = 0; i < 3; i++)\r
- {\r
- compressed = CA_RLEWCompress(mapsegs[i], expanded, (Uint16 huge *)bigbuffer+1, RLETAG);\r
- *(Uint16 huge *)bigbuffer = compressed;\r
- if (!CA_FarWrite(handle, bigbuffer, compressed+2))\r
- {\r
- MM_FreePtr(&bigbuffer);\r
- return false;\r
- }\r
- }\r
- for (ob = player; ob; ob=ob->next)\r
- {\r
- if (!CA_FarWrite(handle, (byte far *)ob, sizeof(objtype)))\r
- {\r
- MM_FreePtr(&bigbuffer);\r
- return false;\r
- }\r
- }\r
- MM_FreePtr(&bigbuffer);\r
- return true;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= LoadTheGame\r
-=\r
-============================\r
-*/\r
-\r
-boolean LoadTheGame(Sint16 handle)\r
-{\r
- Uint16 i;\r
- objtype *prev,*next,*followed;\r
- Uint16 compressed,expanded;\r
- memptr bigbuffer;\r
-#ifdef KEEN5\r
- Sint16 numfuses;\r
-#endif\r
-\r
- if (!CA_FarRead(handle, (byte far *)&gamestate, sizeof(gamestate)))\r
- return false;\r
-\r
-#ifdef KEEN5\r
- //\r
- // remember the fuses value for later - SetupGameLevel calls\r
- // ScanInfoPlane, which resets this part of the gamestate\r
- //\r
- numfuses = gamestate.numfuses;\r
-#endif\r
-\r
- ca_levelbit >>= 1;\r
- ca_levelnum--;\r
- SetupGameLevel(false);\r
- if (mmerror)\r
- {\r
- mmerror = false;\r
- US_CenterWindow(20, 8);\r
- PrintY += 20;\r
- US_CPrint("Not enough memory\nto load game!");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- return false;\r
- }\r
- ca_levelbit <<= 1;\r
- ca_levelnum++;\r
-\r
- expanded = mapwidth * mapheight * 2;\r
- MM_BombOnError(true); //BUG: this should use false to avoid an instant crash\r
- MM_GetPtr(&bigbuffer, expanded);\r
- MM_BombOnError(false); //BUG: this should use true to force an instant crash\r
- if (mmerror)\r
- {\r
- mmerror = false;\r
- US_CenterWindow(20, 8);\r
- PrintY += 20;\r
- US_CPrint("Not enough memory\nto load game!");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- return false;\r
- }\r
- for (i = 0; i < 3; i++)\r
- {\r
- if (!CA_FarRead(handle, (byte far *)&compressed, sizeof(compressed)))\r
- {\r
- MM_FreePtr(&bigbuffer);\r
- return false;\r
- }\r
- if (!CA_FarRead(handle, (byte far *)bigbuffer, compressed))\r
- {\r
- MM_FreePtr(&bigbuffer);\r
- return false;\r
- }\r
- CA_RLEWexpand(bigbuffer, mapsegs[i], expanded, RLETAG);\r
- }\r
- MM_FreePtr(&bigbuffer);\r
-\r
- InitObjArray();\r
- new = player;\r
- prev = new->prev;\r
- next = new->next;\r
- if (!CA_FarRead(handle, (byte far *)new, sizeof(objtype)))\r
- {\r
- return false;\r
- }\r
- new->prev = prev;\r
- new->next = next;\r
- new->needtoreact = true;\r
- new->sprite = NULL;\r
- new = scoreobj;\r
- while (true)\r
- {\r
- prev = new->prev;\r
- next = new->next;\r
- if (!CA_FarRead(handle, (byte far *)new, sizeof(objtype)))\r
- {\r
- return false;\r
- }\r
- followed = new->next;\r
- new->prev = prev;\r
- new->next = next;\r
- new->needtoreact = true;\r
- new->sprite = NULL;\r
- if (new->obclass == stunnedobj)\r
- {\r
- new->temp3 = 0; //clear sprite ptr for the stars\r
- }\r
-#if defined KEEN4\r
- else if (new->obclass == platformobj)\r
- {\r
- new->temp2 = new->temp3 = 0; //clear sprite ptrs\r
- }\r
-#elif defined KEEN5\r
- else if (new->obclass == mineobj)\r
- {\r
- new->temp4 = 0; //clear sprite ptr\r
- }\r
- else if (new->obclass == spherefulobj)\r
- {\r
- new->temp1 = new->temp2 = new->temp3 = new->temp4 = 0; //clear sprite ptrs\r
- }\r
-#elif defined KEEN6\r
- else if (new->obclass == platformobj)\r
- {\r
- new->temp3 = 0; //clear sprite ptr\r
- }\r
-#endif\r
- if (followed)\r
- {\r
- GetNewObj(false);\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
- scoreobj->temp2 = -1;\r
- scoreobj->temp1 = -1;\r
- scoreobj->temp3 = -1;\r
- scoreobj->temp4 = -1;\r
-#ifdef KEEN5\r
- gamestate.numfuses = numfuses; // put value from saved game back in place \r
-#endif\r
- return true;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= ResetGame\r
-=\r
-============================\r
-*/\r
-\r
-void ResetGame(void)\r
-{\r
- NewGame();\r
- ca_levelnum--;\r
- ca_levelbit >>= 1;\r
- CA_ClearMarks();\r
- ca_levelbit <<= 1;\r
- ca_levelnum++;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= PatchWorldMap\r
-=\r
-= Takes out blocking squares and spawns flags\r
-=\r
-==========================\r
-*/\r
-\r
-void PatchWorldMap(void)\r
-{\r
- Uint16 x, y, planeoff, info, level, tag;\r
- Uint16 far *infoptr;\r
-\r
- planeoff = 0;\r
- infoptr = mapsegs[2];\r
- for (y = 0; y < mapheight; y++)\r
- {\r
- for (x = 0; x < mapwidth; x++, infoptr++, planeoff++)\r
- {\r
- info = *infoptr;\r
- level = info & 0xFF;\r
- if (level >= MINDONELEVEL && level <= MAXDONELEVEL && gamestate.leveldone[level])\r
- {\r
- tag = info >> 8;\r
- *infoptr = 0; // BUG: infoplane value should only be set to 0 if tag == 0xC0\r
- if (tag == 0xD0)\r
- {\r
- mapsegs[1][planeoff] = 0;\r
- }\r
- else if (tag == 0xF0)\r
- {\r
-#ifdef KEEN5\r
- SpawnFlag(x, y);\r
-#else\r
- if (levelcompleted == level)\r
- {\r
- SpawnThrowFlag(x, y);\r
- }\r
- else\r
- {\r
- SpawnFlag(x, y);\r
- }\r
-#endif\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= DelayedFade\r
-=\r
-= Fades out and latches FadeAndUnhook onto the refresh\r
-=\r
-==========================\r
-*/\r
-\r
-void DelayedFade(void)\r
-{\r
- VW_FadeOut();\r
- fadecount = 0;\r
- RF_SetRefreshHook(&FadeAndUnhook);\r
-}\r
-\r
-/*\r
-==========================\r
-=\r
-= FadeAndUnhook\r
-=\r
-= Latch this onto the refresh so the screen only gets faded in after two\r
-= refreshes. This lets all actors draw themselves to both pages before\r
-= fading the screen in.\r
-=\r
-==========================\r
-*/\r
-\r
-void FadeAndUnhook(void)\r
-{\r
- if (++fadecount == 2)\r
- {\r
- VW_FadeIn();\r
- RF_SetRefreshHook(NULL);\r
- TimeCount = lasttimecount; // don't adaptively time the fade\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= SetupGameLevel\r
-=\r
-= Load in map mapon and cache everything needed for it\r
-=\r
-==========================\r
-*/\r
-\r
-void SetupGameLevel(boolean loadnow)\r
-{\r
-//\r
-// randomize if not a demo\r
-//\r
- if (DemoMode)\r
- {\r
- US_InitRndT(false);\r
- gamestate.difficulty = gd_Normal;\r
- }\r
- else\r
- {\r
- US_InitRndT(true);\r
- }\r
-\r
-//\r
-// load the level header and three map planes\r
-//\r
- CA_CacheMap(gamestate.mapon);\r
-\r
-//\r
-// let the refresh manager set up some variables\r
-//\r
- RF_NewMap();\r
-\r
-//\r
-// decide which graphics are needed and spawn actors\r
-//\r
- CA_ClearMarks();\r
- ScanInfoPlane();\r
- if (mapon == 0)\r
- {\r
- PatchWorldMap();\r
- }\r
- RF_MarkTileGraphics();\r
-\r
-//\r
-// have the caching manager load and purge stuff to make sure all marks\r
-// are in memory\r
-//\r
- MM_BombOnError(false);\r
- CA_LoadAllSounds();\r
- if (loadnow)\r
- {\r
- if (scorescreenkludge)\r
- {\r
- CA_CacheMarks(NULL);\r
- }\r
- else if (DemoMode)\r
- {\r
- CA_CacheMarks("DEMO");\r
- }\r
-#ifdef KEEN5\r
- else if (mapon == 0 && player->tiletop > 100)\r
- {\r
- CA_CacheMarks("Keen steps out\nonto Korath III");\r
- }\r
-#endif\r
- else\r
- {\r
- _fstrcpy(str, levelenter[mapon]);\r
- CA_CacheMarks(str);\r
- }\r
- }\r
- MM_BombOnError(true);\r
-\r
- if (!mmerror && loadnow)\r
- {\r
- DelayedFade();\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= DialogDraw\r
-=\r
-==========================\r
-*/\r
-\r
-void DialogDraw(char *title, Uint16 numcache)\r
-{\r
- Sint16 i;\r
- Uint16 width, height;\r
- Sint32 totalfree;\r
-\r
- totalfree = MM_TotalFree();\r
- if (totalfree < 2048)\r
- {\r
- handpic = 5;\r
- }\r
- else\r
- {\r
- handpic = 0;\r
- for (i = 0; i < 6; i++)\r
- {\r
- CA_CacheGrChunk(i+KEENCOUNT1PIC);\r
- CA_UnmarkGrChunk(i+KEENCOUNT1PIC);\r
- if (grsegs[i+KEENCOUNT1PIC])\r
- {\r
- MM_SetPurge(&grsegs[i+KEENCOUNT1PIC], PURGE_FIRST);\r
- }\r
- else\r
- {\r
- mmerror = false;\r
- handpic = 5;\r
- break;\r
- }\r
- }\r
- }\r
- US_CenterWindow(26, 8);\r
- if (grsegs[KEENCOUNT1PIC])\r
- {\r
- VWB_DrawPic(WindowX, WindowY, KEENCOUNT1PIC);\r
- }\r
- else\r
- {\r
- handpic = 5;\r
- }\r
- CA_UnmarkGrChunk(KEENCOUNT1PIC); //redundant\r
- WindowW -= 48;\r
- WindowX += 48;\r
- SizeText(title, &width, &height);\r
- PrintY += (WindowH-height)/2 - 4;\r
- US_CPrint(title);\r
- VW_UpdateScreen();\r
- chunkmax = chunkcount = numcache / 6;\r
- if (!chunkmax && !handpic)\r
- {\r
- handpic = 5;\r
- if (grsegs[KEENCOUNT6PIC])\r
- VWB_DrawPic(WindowX-24, WindowY+40, KEENCOUNT6PIC);\r
- VW_UpdateScreen();\r
- }\r
-}\r
-\r
-/*\r
-==========================\r
-=\r
-= DialogUpdate\r
-=\r
-==========================\r
-*/\r
-\r
-void DialogUpdate(void)\r
-{\r
- if (--chunkcount || handpic > 4)\r
- return;\r
-\r
- chunkcount = chunkmax;\r
- if (grsegs[handpic+KEENCOUNT2PIC])\r
- {\r
- VWB_DrawPic(WindowX-24, WindowY+40, handpic+KEENCOUNT2PIC);\r
- }\r
- VW_UpdateScreen();\r
- handpic++;\r
-}\r
-\r
-/*\r
-==========================\r
-=\r
-= DialogFinish\r
-=\r
-==========================\r
-*/\r
-\r
-void DialogFinish(void)\r
-{\r
- //this is empty\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= StartDemoRecord\r
-=\r
-==================\r
-*/\r
-\r
-void StartDemoRecord(void)\r
-{\r
- Sint16 level;\r
- boolean esc;\r
-\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(30, 3);\r
- PrintY += 6;\r
- US_Print(" Record a demo from level(0-21):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput(px, py, str, NULL, true, 2, 0);\r
- if (!esc)\r
- {\r
- level = atoi(str);\r
- if (level >= 0 && level <= 21)\r
- {\r
- gamestate.mapon = level;\r
- playstate = ex_warped;\r
- IN_StartDemoRecord(0x1000);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-==================\r
-=\r
-= EndDemoRecord\r
-=\r
-==================\r
-*/\r
-\r
-void EndDemoRecord(void)\r
-{\r
- Sint16 handle;\r
- boolean esc;\r
- char filename[] = "DEMO?."EXTENSION;\r
-\r
- IN_StopDemo();\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(22, 3);\r
- PrintY += 6;\r
- US_Print(" Save as demo #(0-9):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput(px, py, str, NULL, true, 2, 0);\r
- if (!esc && str[0] >= '0' && str[0] <= '9')\r
- {\r
- filename[4] = str[0];\r
- handle = open(filename, O_BINARY|O_WRONLY|O_CREAT, S_IFREG|S_IREAD|S_IWRITE);\r
- if (handle == -1)\r
- {\r
- Quit("EndDemoRecord: Cannot write demo file!");\r
- }\r
- write(handle, &mapon, sizeof(mapon));\r
- write(handle, &DemoOffset, sizeof(DemoOffset));\r
- CA_FarWrite(handle, DemoBuffer, DemoOffset);\r
- close(handle);\r
- }\r
- IN_FreeDemoBuffer();\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= HandleDeath\r
-=\r
-==========================\r
-*/\r
-\r
-void HandleDeath(void)\r
-{\r
- Uint16 y, color, top, bottom, selection, w, h;\r
-\r
- _fstrcpy(str, levelnames[mapon]);\r
- SizeText(str, &w, &h);\r
-\r
- memset(gamestate.keys, 0, sizeof(gamestate.keys));\r
- gamestate.lives--;\r
- if (gamestate.lives >= 0)\r
- {\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(20, 8);\r
- PrintY += 3;\r
- US_CPrint("You didn't make it past");\r
- top = PrintY+22;\r
- if (h < 15)\r
- PrintY += 4;\r
- US_CPrint(str);\r
- PrintY = top+2;\r
- US_CPrint("Try Again");\r
- PrintY += 4;\r
- bottom = PrintY-2;\r
- US_CPrint("Exit to "WORLDMAPNAME);\r
-\r
- IN_ClearKeysDown();\r
- selection = 0;\r
- while (true)\r
- {\r
- if (selection)\r
- {\r
- y = bottom;\r
- }\r
- else\r
- {\r
- y = top;\r
- }\r
-\r
-// draw select bar\r
- if ((TimeCount / 16) & 1)\r
- {\r
- color = SECONDCOLOR;\r
- }\r
- else\r
- {\r
- color = FIRSTCOLOR;\r
- }\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y, color);\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y+1, color);\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y+12, color);\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y+13, color);\r
- VWB_Vlin(y+1, y+11, WindowX+4, color);\r
- VWB_Vlin(y+1, y+11, WindowX+5, color);\r
- VWB_Vlin(y+1, y+11, WindowX+WindowW-4, color);\r
- VWB_Vlin(y+1, y+11, WindowX+WindowW-5, color);\r
-\r
- VW_UpdateScreen();\r
-\r
-// erase select bar\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y, WHITE);\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y+1, WHITE);\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y+12, WHITE);\r
- VWB_Hlin(WindowX+4, WindowX+WindowW-4, y+13, WHITE);\r
- VWB_Vlin(y+1, y+11, WindowX+4, WHITE);\r
- VWB_Vlin(y+1, y+11, WindowX+5, WHITE);\r
- VWB_Vlin(y+1, y+11, WindowX+WindowW-4, WHITE);\r
- VWB_Vlin(y+1, y+11, WindowX+WindowW-5, WHITE);\r
-\r
- if (LastScan == sc_Escape)\r
- {\r
- gamestate.mapon = 0; // exit to world map\r
- IN_ClearKeysDown();\r
- return;\r
- }\r
-\r
- IN_ReadControl(0, &c);\r
- if (c.button0 || c.button1 || LastScan == sc_Return || LastScan == sc_Space)\r
- {\r
- if (selection)\r
- gamestate.mapon = 0; // exit to world map\r
- return;\r
- }\r
- if (c.yaxis == -1 || LastScan == sc_UpArrow)\r
- {\r
- selection = 0;\r
- }\r
- else if (c.yaxis == 1 || LastScan == sc_DownArrow)\r
- {\r
- selection = 1;\r
- }\r
- }\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= GameLoop\r
-=\r
-= A game has just started (after the cinematic or load game)\r
-=\r
-============================\r
-*/\r
-\r
-void GameLoop(void)\r
-{\r
- Uint16 temp;\r
-#ifdef KEEN6\r
- Uint16 i;\r
-#endif\r
-\r
-#ifdef KEEN6\r
- if (!storedemo)\r
- {\r
- if (!US_ManualCheck())\r
- {\r
- loadedgame = false;\r
- restartgame = gd_Continue;\r
- return;\r
- }\r
- }\r
-#endif\r
-\r
- if (playstate == ex_loadedgame)\r
- {\r
- goto loaded;\r
- }\r
-reset:\r
- gamestate.difficulty = restartgame;\r
- restartgame = gd_Continue;\r
- do\r
- {\r
-startlevel:\r
- SetupGameLevel(true);\r
- if (mmerror)\r
- {\r
- if (gamestate.mapon != 0)\r
- {\r
- mmerror = false;\r
- US_CenterWindow(20, 8);\r
- PrintY += 20;\r
- US_CPrint("Insufficient memory\nto load level!");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- gamestate.mapon = 0; // exit to world map\r
- SetupGameLevel(true);\r
- }\r
- if (mmerror)\r
- {\r
- Quit("GameLoop: Insufficient memory to load world map!");\r
- }\r
- }\r
-loaded:\r
- keenkilled = false;\r
- SD_WaitSoundDone();\r
-\r
- PlayLoop();\r
-\r
- if (playstate != ex_loadedgame)\r
- {\r
- memset(gamestate.keys, 0, sizeof(gamestate.keys));\r
-#ifdef KEEN5\r
- gamestate.keycard = false;\r
-#endif\r
- }\r
- VW_FixRefreshBuffer();\r
-\r
- if (tedlevel)\r
- {\r
- if (playstate == ex_loadedgame)\r
- {\r
- goto loaded;\r
- }\r
- else if (playstate == ex_died)\r
- {\r
- goto startlevel;\r
- }\r
- else\r
- {\r
- TEDDeath();\r
- }\r
- }\r
-\r
- levelcompleted = -1;\r
- switch (playstate)\r
- {\r
- case ex_resetgame:\r
- goto reset;\r
-\r
- case ex_loadedgame:\r
- goto loaded;\r
-\r
- case ex_died:\r
- HandleDeath();\r
- break;\r
-\r
-#if defined KEEN4\r
- case ex_rescued:\r
- if (mapon != 0)\r
- {\r
- SD_PlaySound(SND_LEVELDONE);\r
- }\r
- levelcompleted = mapon;\r
- gamestate.leveldone[mapon] = true;\r
- RescuedMember();\r
- if (gamestate.rescued != 8)\r
- {\r
- gamestate.mapon = 0;\r
- }\r
- else\r
- {\r
- FreeGraphics();\r
- RF_FixOfs();\r
- VW_FixRefreshBuffer();\r
- FinaleLayout();\r
- CheckHighScore(gamestate.score, gamestate.rescued);\r
- return;\r
- }\r
- break;\r
-\r
-#elif defined KEEN5\r
- case ex_fusebroke:\r
- SD_PlaySound(SND_LEVELDONE);\r
- levelcompleted = mapon;\r
- gamestate.leveldone[mapon] = ex_fusebroke;\r
- FinishedFuse();\r
- gamestate.mapon = 0;\r
- break;\r
-\r
- case ex_qedbroke:\r
- FreeGraphics();\r
- RF_FixOfs();\r
- VW_FixRefreshBuffer();\r
- FinaleLayout();\r
- CheckHighScore(gamestate.score, 0);\r
- return;\r
-\r
-#elif defined KEEN6\r
- case ex_hook:\r
- GotHook();\r
- goto completed;\r
-\r
- case ex_sandwich:\r
- GotSandwich();\r
- goto completed;\r
-\r
- case ex_card:\r
- GotPasscard();\r
- goto completed;\r
-\r
- case ex_molly:\r
- FreeGraphics();\r
- RF_FixOfs();\r
- VW_FixRefreshBuffer();\r
- FinaleLayout();\r
- goto check_score;\r
-\r
-#endif\r
- case ex_completed:\r
- case ex_foot:\r
- case ex_portout:\r
-completed:\r
- if (mapon != 0)\r
- {\r
- SD_PlaySound(SND_LEVELDONE);\r
- gamestate.mapon = 0;\r
- levelcompleted = mapon;\r
- gamestate.leveldone[mapon] = true;\r
- if (storedemo && mapon == 2)\r
- {\r
- IN_ClearKeysDown();\r
- return;\r
- }\r
- }\r
- else\r
- {\r
-#if GRMODE != CGAGR\r
- temp = bufferofs;\r
- bufferofs = displayofs;\r
-#endif\r
- US_CenterWindow(26, 8);\r
- PrintY += 25;\r
- US_CPrint("One moment");\r
-#if GRMODE == CGAGR\r
- VW_UpdateScreen();\r
-#else\r
- bufferofs = temp;\r
-#endif\r
- }\r
- break;\r
-\r
- case ex_abortgame:\r
- IN_ClearKeysDown();\r
- return;\r
- }\r
- } while (gamestate.lives >= 0);\r
-\r
- GameOver();\r
-\r
-check_score:\r
-#if defined KEEN4\r
- CheckHighScore(gamestate.score, gamestate.rescued);\r
-#else\r
- temp = 0;\r
-#if defined KEEN6\r
- for (i = 0; i < GAMELEVELS; i++)\r
- {\r
- if (gamestate.leveldone[i])\r
- temp++;\r
- }\r
-#endif\r
- CheckHighScore(gamestate.score, temp);\r
-#endif\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-CK_KEEN.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Keen (regular levels)\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Sint16 singlegravity; // left over from Keen Dreams, not used in Keen 4-6\r
-\r
-Uint16 bounceangle [8][8] =\r
-{\r
- { 0, 0, 0, 0, 0, 0, 0, 0},\r
- { 7, 6, 5, 4, 3, 2, 1, 0},\r
- { 5, 4, 3, 2, 1, 0, 15, 14},\r
- { 5, 4, 3, 2, 1, 0, 15, 14},\r
- { 3, 2, 1, 0, 15, 14, 13, 12},\r
- { 9, 8, 7, 6, 5, 4, 3, 2},\r
- { 9, 8, 7, 6, 5, 4, 3, 2},\r
- {11, 10, 9, 8, 7, 6, 5, 4}\r
-};\r
-\r
-#ifndef KEEN4\r
-arrowdirtype arrowflip[] = {arrow_South, arrow_West, arrow_North, arrow_East, arrow_SouthWest, arrow_NorthWest, arrow_NorthEast, arrow_SouthEast};\r
-#endif\r
-\r
-statetype s_keenstand = {KEENSTANDLSPR, KEENSTANDRSPR, stepthink, false, true, 4, 0, 32, KeenPauseThink, KeenContact, KeenStandReact, &s_keenstand};\r
-\r
-#ifdef KEEN5\r
-statetype s_keenride = {KEENONPLATSPR, KEENONPLATSPR, stepthink, false, true, 4, 0, 32, KeenStandThink, KeenContact, KeenStandReact, &s_keenride};\r
-#endif\r
-\r
-statetype s_keenpauselook = {KEENLOOKUSPR, KEENLOOKUSPR, stepthink, false, true, 60, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenstand};\r
-\r
-statetype s_keenwait1 = {KEENWAITR2SPR, KEENWAITR2SPR, stepthink, false, true, 90, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenwait2};\r
-statetype s_keenwait2 = {KEENWAITR1SPR, KEENWAITR1SPR, stepthink, false, true, 10, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenwait3};\r
-statetype s_keenwait3 = {KEENWAITR2SPR, KEENWAITR2SPR, stepthink, false, true, 90, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenwait4};\r
-statetype s_keenwait4 = {KEENWAITR1SPR, KEENWAITR1SPR, stepthink, false, true, 10, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenwait5};\r
-statetype s_keenwait5 = {KEENWAITR2SPR, KEENWAITR2SPR, stepthink, false, true, 90, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenwait6};\r
-statetype s_keenwait6 = {KEENWAITR3SPR, KEENWAITR3SPR, stepthink, false, true, 70, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenstand};\r
-\r
-#ifdef KEEN4\r
-statetype s_keenmoon1 = {KEENMOON1SPR, KEENMOON1SPR, stepthink, false, true, 20, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenmoon2};\r
-statetype s_keenmoon2 = {KEENMOON2SPR, KEENMOON2SPR, stepthink, false, true, 90, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenmoon3};\r
-statetype s_keenmoon3 = {KEENMOON1SPR, KEENMOON1SPR, stepthink, false, true, 20, 0, 0, KeenPauseThink, KeenContact, KeenStandReact, &s_keenstand};\r
-#endif\r
-\r
-statetype s_keenread = {KEENSITREAD1SPR, KEENSITREAD1SPR, step, false, true, 16, 0, 0, 0, KeenContact, KeenStandReact, &s_keenread2};\r
-statetype s_keenread2 = {KEENSITREAD2SPR, KEENSITREAD2SPR, step, false, true, 16, 0, 0, 0, KeenContact, KeenStandReact, &s_keenread3};\r
-statetype s_keenread3 = {KEENSITREAD3SPR, KEENSITREAD3SPR, step, false, true, 16, 0, 0, 0, KeenContact, KeenStandReact, &s_keenread4};\r
-statetype s_keenread4 = {KEENSITREAD4SPR, KEENSITREAD4SPR, step, false, true, 16, 0, 0, 0, KeenContact, KeenStandReact, &s_keenread5};\r
-statetype s_keenread5 = {KEENREAD1SPR, KEENREAD1SPR, stepthink, false, true, 300, 0, 0, KeenReadThink, KeenContact, KeenStandReact, &s_keenread6};\r
-statetype s_keenread6 = {KEENREAD2SPR, KEENREAD2SPR, stepthink, false, true, 16, 0, 0, KeenReadThink, KeenContact, KeenStandReact, &s_keenread7};\r
-statetype s_keenread7 = {KEENREAD3SPR, KEENREAD3SPR, stepthink, false, true, 16, 0, 0, KeenReadThink, KeenContact, KeenStandReact, &s_keenread5};\r
-statetype s_keenstopread = {KEENSTOPREAD1SPR, KEENSTOPREAD1SPR, step, false, true, 12, 0, 0, 0, KeenContact, KeenStandReact, &s_keenstopread2};\r
-statetype s_keenstopread2 = {KEENSTOPREAD2SPR, KEENSTOPREAD2SPR, step, false, true, 12, 0, 0, 0, KeenContact, KeenStandReact, &s_keenstopread3};\r
-statetype s_keenstopread3 = {KEENSITREAD2SPR, KEENSITREAD2SPR, step, false, true, 12, 0, 0, 0, KeenContact, KeenStandReact, &s_keenstand};\r
-\r
-statetype s_keenlookup = {KEENLOOKUSPR, KEENLOOKUSPR, stepthink, false, true, 30, 0, 0, KeenLookUpThink, KeenContact, KeenStandReact, &s_keenlookup2};\r
-statetype s_keenlookup2 = {KEENLOOKUSPR, KEENLOOKUSPR, think, false, true, 0, 0, 0, KeenLookUpThink, KeenPosContact, KeenStandReact, NULL};\r
-\r
-statetype s_keenlookdown = {KEENLOOKD1SPR, KEENLOOKD1SPR, stepthink, false, true, 6, 0, 0, KeenLookDownThink, KeenContact, KeenStandReact, &s_keenlookdown2};\r
-statetype s_keenlookdown2 = {KEENLOOKD2SPR, KEENLOOKD2SPR, stepthink, false, true, 24, 0, 0, KeenLookDownThink, KeenPosContact, KeenStandReact, &s_keenlookdown3};\r
-statetype s_keenlookdown3 = {KEENLOOKD2SPR, KEENLOOKD2SPR, think, false, true, 0, 0, 0, KeenLookDownThink, KeenPosContact, KeenStandReact, NULL};\r
-statetype s_keenlookdown4 = {KEENLOOKD1SPR, KEENLOOKD1SPR, step, false, true, 6, 0, 0, 0, KeenContact, KeenStandReact, &s_keenstand};\r
-\r
-statetype s_keendrop = {KEENLOOKD1SPR, KEENLOOKD1SPR, step, false, false, 0, 0, 0, KeenDropDownThink, KeenContact, KeenSimpleReact, &s_keenjump3};\r
-statetype s_keendead = {-1, -1, think, false, false, 10, 0, 0, 0, 0, R_Draw, NULL};\r
-\r
-statetype s_keendie1 = {KEENDIE1SPR, KEENDIE1SPR, think, false, false, 100, 0, 0, KeenDieThink, 0, R_Draw, &s_keendie1};\r
-statetype s_keendie2 = {KEENDIE2SPR, KEENDIE2SPR, think, false, false, 100, 0, 0, KeenDieThink, 0, R_Draw, &s_keendie2};\r
-\r
-#ifdef KEEN4\r
-statetype s_keensuitdie1 = {SCUBAKEENDEAD1SPR, SCUBAKEENDEAD1SPR, think, false, false, 100, 0, 0, KeenDieThink, NULL, R_Draw, &s_keensuitdie1};\r
-statetype s_keensuitdie2 = {SCUBAKEENDEAD2SPR, SCUBAKEENDEAD2SPR, think, false, false, 100, 0, 0, KeenDieThink, NULL, R_Draw, &s_keensuitdie2};\r
-#endif\r
-\r
-statetype s_keenshoot1 = {KEENSHOOTLSPR, KEENSHOOTRSPR, step, false, true, 9, 0, 0, KeenShootThink, KeenContact, KeenStandReact, &s_keenshoot2};\r
-statetype s_keenshoot2 = {KEENSHOOTLSPR, KEENSHOOTRSPR, step, false, true, 6, 0, 0, 0, KeenContact, KeenStandReact, &s_keenstand};\r
-\r
-statetype s_keenshootup1 = {KEENSHOOTUSPR, KEENSHOOTUSPR, step, false, true, 9, 0, 0, KeenShootThink, KeenContact, KeenStandReact, &s_keenshootup2};\r
-statetype s_keenshootup2 = {KEENSHOOTUSPR, KEENSHOOTUSPR, step, false, true, 6, 0, 0, 0, KeenContact, KeenStandReact, &s_keenlookup};\r
-\r
-statetype s_keenswitch = {KEENENTER1SPR, KEENENTER1SPR, step, false, true, 8, 0, 0, KeenSwitchThink, NULL, KeenStandReact, &s_keenswitch2};\r
-statetype s_keenswitch2 = {KEENENTER1SPR, KEENENTER1SPR, step, false, true, 8, 0, 0, 0, 0, KeenStandReact, &s_keenstand};\r
-statetype s_keenkey = {KEENENTER1SPR, KEENENTER1SPR, step, false, true, 6, 0, 0, KeenKeyThink, NULL, KeenStandReact, &s_keenswitch2};\r
-\r
-statetype s_keenlineup = {KEENENTER1SPR, KEENENTER1SPR, think, false, false, 0, 0, 0, T_LineUp, 0, R_Draw, NULL};\r
-#ifdef KEEN5\r
-statetype s_keenenter0 = {KEENENTER1SPR, KEENENTER1SPR, step, false, false, 45, 0, -64, NULL, NULL, R_Draw, &s_keenenter1};\r
-statetype s_keenteleport = {KEENWAITR2SPR, KEENWAITR2SPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, NULL};\r
-#endif\r
-\r
-statetype s_keenenter1 = {KEENENTER1SPR, KEENENTER1SPR, step, false, false, 9, 0, -64, WalkSound1, NULL, R_Draw, &s_keenenter2};\r
-statetype s_keenenter2 = {KEENENTER2SPR, KEENENTER2SPR, step, false, false, 9, 0, -64, WalkSound2, NULL, R_Draw, &s_keenenter3};\r
-statetype s_keenenter3 = {KEENENTER3SPR, KEENENTER3SPR, step, false, false, 9, 0, -64, WalkSound1, NULL, R_Draw, &s_keenenter4};\r
-statetype s_keenenter4 = {KEENENTER4SPR, KEENENTER4SPR, step, false, false, 9, 0, -64, WalkSound2, NULL, R_Draw, &s_keenenter5};\r
-statetype s_keenenter5 = {KEENENTER5SPR, KEENENTER5SPR, step, false, false, 9, 0, -64, KeenEnterThink, NULL, R_Draw, &s_keenstand};\r
-#ifdef KEEN5\r
-statetype s_keenenter6 = {-1, -1, step, false, false, 9, 0, -64, KeenEnterThink, 0, R_Draw, &s_keenstand};\r
-#endif\r
-\r
-statetype s_keenpole = {KEENSHINNYL1SPR, KEENSHINNYR1SPR, think, false, false, 0, 0, 0, KeenPoleThink, KeenPosContact, KeenSimpleReact, &s_keenpole};\r
-\r
-statetype s_keenclimb1 = {KEENSHINNYL1SPR, KEENSHINNYR1SPR, slidethink, false, false, 8, 0, 8, KeenClimbThink, KeenPosContact, KeenSimpleReact, &s_keenclimb2};\r
-statetype s_keenclimb2 = {KEENSHINNYL2SPR, KEENSHINNYR2SPR, slidethink, false, false, 8, 0, 8, KeenClimbThink, KeenPosContact, KeenSimpleReact, &s_keenclimb3};\r
-statetype s_keenclimb3 = {KEENSHINNYL3SPR, KEENSHINNYR3SPR, slidethink, false, false, 8, 0, 8, KeenClimbThink, KeenPosContact, KeenSimpleReact, &s_keenclimb1};\r
-\r
-statetype s_keenslide1 = {KEENSLIDED1SPR, KEENSLIDED1SPR, slide, false, false, 8, 0, 24, KeenDropThink, KeenPosContact, KeenPoleReact, &s_keenslide2};\r
-statetype s_keenslide2 = {KEENSLIDED2SPR, KEENSLIDED2SPR, slide, false, false, 8, 0, 24, KeenDropThink, KeenPosContact, KeenPoleReact, &s_keenslide3};\r
-statetype s_keenslide3 = {KEENSLIDED3SPR, KEENSLIDED3SPR, slide, false, false, 8, 0, 24, KeenDropThink, KeenPosContact, KeenPoleReact, &s_keenslide4};\r
-statetype s_keenslide4 = {KEENSLIDED4SPR, KEENSLIDED4SPR, slide, false, false, 8, 0, 24, KeenDropThink, KeenPosContact, KeenPoleReact, &s_keenslide1};\r
-\r
-statetype s_keenpoleshoot1 = {KEENPSHOOTLSPR, KEENPSHOOTRSPR, step, false, false, 9, 0, 0, KeenShootThink, KeenPosContact, KeenSimpleReact, &s_keenpoleshoot2};\r
-statetype s_keenpoleshoot2 = {KEENPSHOOTLSPR, KEENPSHOOTRSPR, step, false, false, 6, 0, 0, 0, KeenPosContact, KeenSimpleReact, &s_keenpole};\r
-\r
-statetype s_keenpoleshootup1 = {KEENPLSHOOTUSPR, KEENPRSHOOTUSPR, step, false, false, 9, 0, 0, KeenShootThink, KeenPosContact, KeenSimpleReact, &s_keenpoleshootup2};\r
-statetype s_keenpoleshootup2 = {KEENPLSHOOTUSPR, KEENPRSHOOTUSPR, step, false, false, 6, 0, 0, 0, KeenPosContact, KeenSimpleReact, &s_keenpole};\r
-\r
-statetype s_keenpoleshootdown1 = {KEENPLSHOOTDSPR, KEENPRSHOOTDSPR, step, false, false, 9, 0, 0, KeenShootThink, KeenPosContact, KeenSimpleReact, &s_keenpoleshootdown2};\r
-statetype s_keenpoleshootdown2 = {KEENPLSHOOTDSPR, KEENPRSHOOTDSPR, step, false, false, 6, 0, 0, 0, KeenPosContact, KeenSimpleReact, &s_keenpole};\r
-\r
-statetype s_keenwalk1 = {KEENRUNL1SPR, KEENRUNR1SPR, slidethink, true, true, 6, 24, 0, KeenWalkThink, KeenContact, KeenWalkReact, &s_keenwalk2};\r
-statetype s_keenwalk2 = {KEENRUNL2SPR, KEENRUNR2SPR, slidethink, true, true, 6, 24, 0, KeenWalkThink, KeenContact, KeenWalkReact, &s_keenwalk3};\r
-statetype s_keenwalk3 = {KEENRUNL3SPR, KEENRUNR3SPR, slidethink, true, true, 6, 24, 0, KeenWalkThink, KeenContact, KeenWalkReact, &s_keenwalk4};\r
-statetype s_keenwalk4 = {KEENRUNL4SPR, KEENRUNR4SPR, slidethink, true, true, 6, 24, 0, KeenWalkThink, KeenContact, KeenWalkReact, &s_keenwalk1};\r
-\r
-statetype s_keenpogodown = {KEENPOGOL2SPR, KEENPOGOR2SPR, step, true, false, 1, 0, 0, KeenBounceThink, KeenContact, KeenPogoReact, &s_keenpogo};\r
-statetype s_keenpogo = {KEENPOGOL2SPR, KEENPOGOR2SPR, think, true, false, 0, 0, 0, KeenPogoThink, KeenContact, KeenPogoReact, &s_keenpogo2};\r
-statetype s_keenpogo2 = {KEENPOGOL1SPR, KEENPOGOR1SPR, think, true, false, 0, 0, 0, KeenPogoThink, KeenContact, KeenPogoReact, NULL};\r
-\r
-statetype s_keenjump1 = {KEENJUMPL1SPR, KEENJUMPR1SPR, think, false, false, 0, 0, 0, KeenAirThink, KeenContact, KeenAirReact, &s_keenjump2};\r
-statetype s_keenjump2 = {KEENJUMPL2SPR, KEENJUMPR2SPR, think, false, false, 0, 0, 0, KeenAirThink, KeenContact, KeenAirReact, &s_keenjump3};\r
-statetype s_keenjump3 = {KEENJUMPL3SPR, KEENJUMPR3SPR, stepthink, false, false, 50, 0, 0, KeenAirThink, KeenContact, KeenAirReact, &s_keenjump4};\r
-statetype s_keenjump4 = {KEENJUMPL2SPR, KEENJUMPR2SPR, stepthink, false, false, 40, 0, 0, KeenAirThink, KeenContact, KeenAirReact, &s_keenjump3};\r
-\r
-statetype s_keenairshoot1 = {KEENJLSHOOTLSPR, KEENJRSHOOTRSPR, stepthink, false, false, 9, 0, 0, T_Projectile, KeenContact, KeenAirReact, &s_keenairshoot2};\r
-statetype s_keenairshoot2 = {KEENJLSHOOTLSPR, KEENJRSHOOTRSPR, stepthink, true, false, 1, 0, 0, KeenShootThink, KeenContact, KeenAirReact, &s_keenairshoot3};\r
-statetype s_keenairshoot3 = {KEENJLSHOOTLSPR, KEENJRSHOOTRSPR, stepthink, false, false, 6, 0, 0, T_Projectile, KeenContact, KeenAirReact, &s_keenjump3};\r
-\r
-statetype s_keenairshootup1 = {KEENJSHOOTUSPR, KEENJSHOOTUSPR, stepthink, false, false, 9, 0, 0, T_Projectile, KeenContact, KeenAirReact, &s_keenairshootup2};\r
-statetype s_keenairshootup2 = {KEENJSHOOTUSPR, KEENJSHOOTUSPR, stepthink, true, false, 1, 0, 0, KeenShootThink, KeenContact, KeenAirReact, &s_keenairshootup3};\r
-statetype s_keenairshootup3 = {KEENJSHOOTUSPR, KEENJSHOOTUSPR, stepthink, false, false, 6, 0, 0, T_Projectile, KeenContact, KeenAirReact, &s_keenjump3};\r
-\r
-statetype s_keenairshootdown1 = {KEENJSHOOTDSPR, KEENJSHOOTDSPR, stepthink, false, false, 9, 0, 0, T_Projectile, KeenContact, KeenAirReact, &s_keenairshootdown2};\r
-statetype s_keenairshootdown2 = {KEENJSHOOTDSPR, KEENJSHOOTDSPR, stepthink, true, false, 1, 0, 0, KeenShootThink, KeenContact, KeenAirReact, &s_keenairshootdown3};\r
-statetype s_keenairshootdown3 = {KEENJSHOOTDSPR, KEENJSHOOTDSPR, stepthink, false, false, 6, 0, 0, T_Projectile, KeenContact, KeenAirReact, &s_keenjump3};\r
-\r
-statetype s_keenholdon = {KEENHANGLSPR, KEENHANGRSPR, step, false, false, 12, 0, 0, 0, KeenPosContact, KeenSimpleReact, &s_keenholdon2};\r
-statetype s_keenholdon2 = {KEENHANGLSPR, KEENHANGRSPR, think, false, false, 0, 0, 0, KeenHoldThink, KeenPosContact, KeenSimpleReact, NULL};\r
-\r
-statetype s_keenclimbup = {KEENCLIMBEDGEL1SPR, KEENCLIMBEDGER1SPR, step, false, false, 10, 0, 0, T_PullUp1, KeenPosContact, KeenSimpleReact, &s_keenclimbup2};\r
-statetype s_keenclimbup2 = {KEENCLIMBEDGEL2SPR, KEENCLIMBEDGER2SPR, step, false, false, 10, 0, 0, T_PullUp2, KeenPosContact, KeenSimpleReact, &s_keenclimbup3};\r
-statetype s_keenclimbup3 = {KEENCLIMBEDGEL3SPR, KEENCLIMBEDGER3SPR, step, false, false, 10, 0, 0, T_PullUp3, KeenPosContact, KeenSimpleReact, &s_keenclimbup4};\r
-statetype s_keenclimbup4 = {KEENCLIMBEDGEL4SPR, KEENCLIMBEDGER4SPR, step, false, false, 10, 0, 0, T_PulledUp, KeenPosContact, KeenSimpleReact, &s_keenclimbup5};\r
-statetype s_keenclimbup5 = {KEENSTANDLSPR, KEENSTANDRSPR, step, false, false, 6, 0, 0, 0, KeenPosContact, KeenSimpleReact, &s_keenstand};\r
-\r
-Sint16 slopespeed[8] = {0, 0, 4, 4, 8, -4, -4, -8};\r
-Sint16 polexspeed[3] = {-8, 0, 8};\r
-\r
-Sint16 shotsinclip[4] = {0, 8, 5, 5};\r
-Sint16 bonussound[] = {\r
- SND_GETKEY,SND_GETKEY,SND_GETKEY,SND_GETKEY,\r
- SND_GETPOINTS,SND_GETPOINTS,SND_GETPOINTS,\r
- SND_GETPOINTS,SND_GETPOINTS,SND_GETPOINTS,\r
- SND_EXTRAKEEN,\r
- SND_GETAMMO\r
-#ifdef KEEN5\r
- ,SND_GETKEYCARD\r
-#endif\r
-};\r
-Sint16 bonuspoints[] = {\r
- 0, 0, 0, 0,\r
- 100, 200, 500,\r
- 1000, 2000, 5000,\r
- 0,\r
- 0\r
-#ifdef KEEN5\r
- ,0\r
-#endif\r
-};\r
-Sint16 bonussprite[] = {\r
- BONUSGEMSPR, BONUSGEMSPR, BONUSGEMSPR, BONUSGEMSPR,\r
- BONUS100SPR, BONUS200SPR, BONUS500SPR,\r
- BONUS1000SPR, BONUS2000SPR, BONUS5000SPR,\r
- BONUS1UPSPR,\r
- BONUSCLIPSPR\r
-#ifdef KEEN5\r
- ,BONUSCARDSPR\r
-#endif\r
-};\r
-\r
-Uint16 zeromap = 0;\r
-\r
-// uninitialized variables:\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Sint16 jumptime;\r
-Sint32 leavepoletime;\r
-Sint16 moonok;\r
-\r
-/*\r
-=============================================================================\r
-\r
- KEEN\r
-\r
-player->temp1 = pausetime / pointer to zees when sleeping\r
-player->temp2 = pausecount / stagecount\r
-player->temp3 =\r
-player->temp4 =\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnKeen\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnKeen(Sint16 x, Sint16 y, Sint16 dir)\r
-{\r
- player->obclass = keenobj;\r
- player->active = ac_allways;\r
- player->priority = 1;\r
- player->x = CONVERT_TILE_TO_GLOBAL(x);\r
- player->y = CONVERT_TILE_TO_GLOBAL(y) - 0xF1; //TODO: weird\r
-\r
- player->xdir = dir;\r
- player->ydir = 1;\r
- NewState(player, &s_keenstand);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CheckGrabPole\r
-=\r
-======================\r
-*/\r
-\r
-boolean CheckGrabPole(objtype *ob)\r
-{\r
- Uint16 far *map;\r
-\r
-//\r
-// kludgy bit to not let you grab a pole the instant you jump off it\r
-//\r
- if (lasttimecount < leavepoletime)\r
- {\r
- leavepoletime = 0;\r
- }\r
- else if (lasttimecount-leavepoletime < 19)\r
- {\r
- return false;\r
- }\r
-\r
- if (c.yaxis == -1)\r
- {\r
- map = mapsegs[1] + mapbwidthtable[(ob->top+6*PIXGLOBAL)/TILEGLOBAL]/2;\r
- }\r
- else\r
- {\r
- map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2;\r
- }\r
-\r
- map += ob->tilemidx;\r
-\r
- if ((tinf[INTILE + *map] & 0x7F) == INTILE_POLE)\r
- {\r
- ob->x = CONVERT_TILE_TO_GLOBAL(ob->tilemidx-1) + 8*PIXGLOBAL;\r
- xtry = 0;\r
- ytry = c.yaxis * 32;\r
- ob->needtoclip = cl_noclip; // can climb through pole holes\r
- ob->state = &s_keenpole;\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CheckEnterHouse\r
-=\r
-= Checks for tiles that Keen can interact with by pressing up\r
-=\r
-======================\r
-*/\r
-\r
-boolean CheckEnterHouse(objtype *ob)\r
-{\r
- Uint16 temp;\r
-#ifdef KEEN5\r
- Uint16 infoval;\r
-#endif\r
- Uint16 intile, intile2;\r
-\r
- intile = tinf[INTILE + *(mapsegs[1]+mapbwidthtable[ob->tiletop]/2+ob->tilemidx)];\r
- if (intile == INTILE_SWITCH0 || intile == INTILE_SWITCH1 || intile == INTILE_BRIDGESWITCH)\r
- {\r
- temp = CONVERT_TILE_TO_GLOBAL(ob->tilemidx) - 4*PIXGLOBAL;\r
- if (ob->x != temp)\r
- {\r
- ob->temp1 = temp;\r
- ob->state = &s_keenlineup;\r
- }\r
- else\r
- {\r
- ob->state = &s_keenswitch;\r
- }\r
- upheld = true;\r
- return true;\r
- }\r
- else if (intile == INTILE_DOOR || intile == INTILE_KEYCARDDOOR)\r
- {\r
- temp = CONVERT_TILE_TO_GLOBAL(ob->tilemidx) + 6*PIXGLOBAL;\r
- intile2 = tinf[INTILE + *(mapsegs[1]+mapbwidthtable[ob->tiletop]/2+ob->tilemidx-1)];\r
- if (intile2 == 2 || intile2 == 32)\r
- temp -= TILEGLOBAL;\r
-\r
- // BUG:\r
- //\r
- // The s_keenenter? states rely on Keen's ydir being set to 1,\r
- // which may not always be the case (e.g. if Keen was pushed off\r
- // a pole by another actor in the level).\r
- // If ydir is not 1, Keen will not move up during that animation\r
- // which means the teleport coordinates won't be read from the\r
- // intended tile position and Keen might end up teleporting to\r
- // position 0, 0 in the map and thus win the current level.\r
- // \r
- // That can easily be avoided by setting ob->ydir to 1 when\r
- // changing ob->state to s_keenenter0 or s_keenenter1.\r
-\r
- if (ob->x != temp)\r
- {\r
- ob->temp1 = temp;\r
- ob->state = &s_keenlineup;\r
- }\r
-#ifdef KEEN5\r
- else if (intile == INTILE_KEYCARDDOOR)\r
- {\r
- if (gamestate.keycard)\r
- {\r
- gamestate.keycard = false;\r
- SD_PlaySound(SND_OPENCARDDOOR);\r
- GetNewObj(false);\r
- new->x = ob->tilemidx - 2;\r
- new->y = ob->tilebottom - 4;\r
- new->active = ac_allways;\r
- new->needtoclip = cl_noclip;\r
- new->obclass = inertobj;\r
- NewState(new, &s_carddoor);\r
- // Note: no invincibility here - card doors were always used as level exits in Keen 5\r
- ob->state = &s_keenenter0;\r
- ob->priority = 0;\r
- upheld = true;\r
- return true;\r
- }\r
- else\r
- {\r
- SD_PlaySound(SND_NOWAY);\r
- ob->state = &s_keenstand;\r
- upheld = true;\r
- return false;\r
- }\r
- }\r
-#endif\r
- else\r
- {\r
- invincible = 110; //about 1.57 seconds\r
- ob->state = &s_keenenter1;\r
- ob->priority = 0;\r
-#ifdef KEEN5\r
- {\r
- infoval = *(mapsegs[2]+mapbwidthtable[ob->tiletop]/2+ob->tilemidx);\r
- if (!infoval)\r
- SpawnTeleport();\r
- }\r
-#endif\r
- }\r
- upheld = true;\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= WalkSound1\r
-=\r
-============================\r
-*/\r
-\r
-void WalkSound1(objtype *ob)\r
-{\r
- SD_PlaySound(SND_WORLDWALK1);\r
- ob++; // shut up compiler\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= WalkSound2\r
-=\r
-============================\r
-*/\r
-\r
-void WalkSound2(objtype *ob)\r
-{\r
- SD_PlaySound(SND_WORLDWALK2);\r
- ob++; // shut up compiler\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-============================\r
-=\r
-= KeenStandThink\r
-=\r
-============================\r
-*/\r
-\r
-void KeenStandThink(objtype *ob)\r
-{\r
-#ifdef KEEN5\r
- if (ob->hitnorth == 25 && ob->state != &s_keenride)\r
- {\r
- ob->state = &s_keenride;\r
- }\r
-#endif\r
-\r
- if (c.xaxis)\r
- {\r
- // started walking\r
- ob->state = &s_keenwalk1;\r
- KeenWalkThink(ob);\r
- xtry = (Sint16)(ob->xdir * ob->state->xmove * tics) / 4;\r
- }\r
- else if (firebutton && !fireheld)\r
- {\r
- // shoot current xdir\r
- fireheld = true;\r
- if (c.yaxis == -1)\r
- {\r
- ob->state = &s_keenshootup1;\r
- }\r
- else\r
- {\r
- ob->state = &s_keenshoot1;\r
- }\r
- }\r
- else if (jumpbutton && ! jumpheld)\r
- {\r
- // jump straight up\r
- jumpheld = true;\r
- SD_PlaySound(SND_JUMP);\r
- ob->xspeed = 0;\r
- ob->yspeed = -40;\r
- ytry = 0;\r
- jumptime = 18;\r
- ob->state = &s_keenjump1;\r
- }\r
- else if (pogobutton && !pogoheld)\r
- {\r
- // get on pogo\r
- pogoheld = true;\r
- SD_PlaySound(SND_JUMP);\r
- ob->state = &s_keenpogodown;\r
- ob->xspeed = 0;\r
- ob->yspeed = -48;\r
- ytry = 0;\r
- jumptime = 24;\r
- }\r
- else\r
- {\r
- switch (c.yaxis)\r
- {\r
- case -1:\r
- if (CheckGrabPole(ob))\r
- break;\r
- if (upheld || !CheckEnterHouse(ob))\r
- {\r
- ob->state = &s_keenlookup;\r
- }\r
- break;\r
- case 1:\r
- if (CheckGrabPole(ob))\r
- break;\r
- ob->state = &s_keenlookdown;\r
- }\r
- return;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenPauseThink\r
-=\r
-= Do special animations in time\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenPauseThink(objtype *ob)\r
-{\r
-#ifdef KEEN5\r
- if (ob->hitnorth == 25 && ob->state != &s_keenride)\r
- {\r
- ob->state = &s_keenride;\r
- }\r
-#endif\r
-\r
- if (c.dir != dir_None || jumpbutton || pogobutton || firebutton)\r
- {\r
- ob->temp1 = ob->temp2 = 0; // not paused any more\r
- ob->state = &s_keenstand;\r
- KeenStandThink(ob);\r
- }\r
- else\r
- {\r
- //only increase idle counter when NOT standing on a sprite:\r
- if ((ob->hitnorth & ~7) != 0x18)\r
- ob->temp1 = ob->temp1 + tics;\r
-\r
- switch (ob->temp2)\r
- {\r
- case 0:\r
- if (ob->temp1 > 200)\r
- {\r
- ob->temp2++;\r
- ob->state = &s_keenpauselook;\r
- ob->temp1 = 0;\r
- }\r
- break;\r
- case 1:\r
- if (ob->temp1 > 300)\r
- {\r
- ob->temp2++;\r
- ob->temp1 = 0;\r
-#ifdef KEEN4\r
- if (moonok == 1)\r
- {\r
- moonok = 2; //don't moon again unless the level is restarted\r
- ob->state = &s_keenmoon1;\r
- }\r
- else\r
-#endif\r
- {\r
- ob->state = &s_keenwait1;\r
- }\r
- }\r
- break;\r
- case 2:\r
- if (ob->temp1 > 700)\r
- {\r
- ob->temp2++;\r
- ob->state = &s_keenread;\r
- ob->temp1 = 0;\r
- }\r
- break;\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenReadThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenReadThink(objtype *ob)\r
-{\r
- if (storedemo)\r
- {\r
- playstate = ex_abortgame;\r
- IN_ClearKeysDown();\r
- }\r
- if (c.dir != dir_None || jumpbutton || pogobutton)\r
- {\r
- ob->temp1 = ob->temp2 = 0;\r
- ob->state = &s_keenstopread;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenLookUpThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenLookUpThink(objtype *ob)\r
-{\r
- if (c.yaxis != -1 || c.xaxis\r
- || (jumpbutton && !jumpheld)\r
- || (pogobutton && !pogoheld)\r
- || firebutton)\r
- {\r
- ob->state = &s_keenstand;\r
- KeenStandThink(ob);\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenLookDownThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenLookDownThink(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Sint16 y, ymove;\r
- Uint16 tile;\r
-\r
- if (jumpbutton && ! jumpheld && (ob->hitnorth & 7) == 1)\r
- {\r
- //\r
- // drop down a level\r
- //\r
- jumpheld = true;\r
-\r
- y = ob->tilebottom;\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[y]/2 + ob->tilemidx;\r
- tile = *map;\r
- if (tinf[WESTWALL+tile] || tinf[EASTWALL+tile] || tinf[SOUTHWALL+tile])\r
- return; // wall prevents drop down\r
-\r
- map += mapwidth;\r
- tile = *map;\r
- if (tinf[WESTWALL+tile] || tinf[EASTWALL+tile] || tinf[SOUTHWALL+tile])\r
- return; // wall prevents drop down\r
-\r
- ymove = max(4, tics) * PIXGLOBAL;\r
- if (gamestate.riding)\r
- ymove += gamestate.riding->ymove;\r
- ob->bottom += ymove;\r
- gamestate.riding = NULL;\r
- ob->y += ymove;\r
- xtry = ytry = 0;\r
- ob->state = &s_keenjump3;\r
- ob->xspeed = ob->yspeed = 0;\r
- SD_PlaySound(SND_PLUMMET);\r
- }\r
- else if (c.yaxis != 1 || c.xaxis\r
- || (jumpbutton && !jumpheld)\r
- || (pogobutton && !pogoheld))\r
- {\r
- ob->state = &s_keenlookdown4;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenWalkThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenWalkThink(objtype *ob)\r
-{\r
- Sint16 xmove;\r
-\r
- if (c.xaxis == 0)\r
- {\r
- //\r
- // stopped running\r
- //\r
- ob->state = &s_keenstand;\r
- KeenStandThink(ob);\r
- return;\r
- }\r
-\r
- ob->xdir = c.xaxis;\r
-\r
- switch (c.yaxis)\r
- {\r
- case -1:\r
- if (CheckGrabPole(ob))\r
- return;\r
- if (upheld)\r
- return;\r
- if (!CheckEnterHouse(ob))\r
- break;;\r
- return;\r
-\r
- case 1:\r
- if (!CheckGrabPole(ob))\r
- break;\r
- return;\r
- }\r
-\r
- if (firebutton && !fireheld)\r
- {\r
- //\r
- // shoot\r
- //\r
- fireheld = true;\r
- if (c.yaxis == -1)\r
- {\r
- ob->state = &s_keenshootup1;\r
- }\r
- else\r
- {\r
- ob->state = &s_keenshoot1;\r
- }\r
- return;\r
- }\r
-\r
- if (jumpbutton && !jumpheld)\r
- {\r
- //\r
- // running jump\r
- //\r
- jumpheld = true;\r
- SD_PlaySound(SND_JUMP);\r
- ob->xspeed = ob->xdir * 16;\r
- ob->yspeed = -40;\r
- xtry = ytry = 0;\r
- jumptime = 18;\r
- ob->state = &s_keenjump1;\r
- }\r
-\r
- if (pogobutton && !pogoheld)\r
- {\r
- //\r
- // get on pogo\r
- //\r
- pogoheld = true;\r
- ob->state = &s_keenpogodown;\r
- SD_PlaySound(SND_JUMP);\r
- ob->xspeed = ob->xdir * 16;\r
- ob->yspeed = -48;\r
- xtry = 0;\r
- jumptime = 24;\r
- return;\r
- }\r
-\r
- //\r
- // give speed for slopes\r
- //\r
- xmove = slopespeed[ob->hitnorth & 7] * tics;\r
- xtry += xmove;\r
-\r
- //\r
- // handle walking sounds\r
- //\r
- if (ob->state == &s_keenwalk1 && ob->temp3 == 0)\r
- {\r
- SD_PlaySound(SND_WORLDWALK1);\r
- ob->temp3 = 1;\r
- }\r
- else if (ob->state == &s_keenwalk3 && ob->temp3 == 0)\r
- {\r
- SD_PlaySound(SND_WORLDWALK2);\r
- ob->temp3 = 1;\r
- }\r
- else if (ob->state == &s_keenwalk2 ||ob->state == &s_keenwalk4)\r
- {\r
- ob->temp3 = 0;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= T_LineUp\r
-=\r
-= Lines up Keen's position for interacting with tiles (temp1 is desired x)\r
-=\r
-=======================\r
-*/\r
-\r
-void T_LineUp(objtype *ob)\r
-{\r
- Sint16 xmove;\r
-\r
- xmove = ob->temp1 - ob->x;\r
- if (xmove < 0)\r
- {\r
- xtry = xtry - tics * 16;\r
- if (xtry > xmove)\r
- return;\r
- }\r
- else if (xmove > 0)\r
- {\r
- xtry = xtry + tics * 16;\r
- if (xtry < xmove)\r
- return;\r
- }\r
- xtry = xmove;\r
- ob->temp1 = 0;\r
- if (!CheckEnterHouse(ob))\r
- ob->state = &s_keenstand;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenEnterThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenEnterThink(objtype *ob)\r
-{\r
- Uint16 info;\r
- Uint16 far *map;\r
-\r
- map = mapsegs[2] + mapbwidthtable[ob->tilebottom]/2 + ob->tileleft;\r
- info = *map;\r
-#ifdef KEEN5\r
- if (!info)\r
- {\r
- playstate = ex_portout;\r
- ob->state = &s_keenenter6;\r
- return;\r
- }\r
- else if (info == 0xB1B1)\r
- {\r
- playstate = ex_completed;\r
- ob->state = &s_keenenter6;\r
- return;\r
- }\r
-#endif\r
- ob->y = (CONVERT_TILE_TO_GLOBAL(info & 0xFF) - TILEGLOBAL) + 15;\r
- ob->x = CONVERT_TILE_TO_GLOBAL(info >> 8);\r
- ob->priority = 1;\r
- ob->needtoclip = cl_noclip;\r
- ChangeState(ob, ob->state->nextstate);\r
- ob->needtoclip = cl_midclip;\r
- CenterActor(ob);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenSwitchThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenSwitchThink(objtype *ob)\r
-{\r
- Uint16 intile, maptile, newtile, info, sx, sy, tileoff;\r
- Uint16 far *map;\r
- Uint16 tile, x, y;\r
- Sint8 manim;\r
-\r
- tileoff = mapbwidthtable[ob->tiletop]/2 + ob->tilemidx;\r
- maptile = mapsegs[1][tileoff];\r
- newtile = maptile + (Sint8)tinf[MANIM + maptile];\r
- info = mapsegs[2][tileoff];\r
- sx = info >> 8;\r
- sy = info & 0xFF;\r
- intile = tinf[INTILE + maptile];\r
-\r
- RF_MemToMap(&newtile, 1, ob->tilemidx, ob->tiletop, 1, 1);\r
- SD_PlaySound(SND_USESWITCH);\r
- if (intile == INTILE_BRIDGESWITCH)\r
- {\r
- //toggle bridge:\r
- for (y = sy; sy+2 > y; y++)\r
- {\r
- map = mapsegs[1] + mapbwidthtable[y]/2 + sx - (y != sy);\r
- for (x = sx - (y != sy); x < mapwidth; x++)\r
- {\r
- tile = *(map++);\r
- manim = tinf[MANIM + tile];\r
- if (!manim)\r
- break;\r
-\r
- tile += manim;\r
- RF_MemToMap(&tile, 1, x, y, 1, 1);\r
- }\r
- }\r
- }\r
- else\r
- {\r
- //toggle platform blocker:\r
- map = mapsegs[2] + mapbwidthtable[sy]/2 + sx;\r
- tile = *map;\r
-#ifdef KEEN5\r
- if (tile >= DIRARROWSTART && tile < DIRARROWEND)\r
- {\r
- *map = arrowflip[tile-DIRARROWSTART]+DIRARROWSTART;\r
- return;\r
- }\r
-#endif\r
- *map = tile ^ PLATFORMBLOCK;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenKeyThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenKeyThink(objtype *ob)\r
-{\r
- Uint16 newtile, info, x, y, tileoff;\r
- Uint16 far *map;\r
- Uint16 tile, h;\r
-\r
- tileoff = mapbwidthtable[ob->tilebottom]/2 + ob->tilemidx;\r
- newtile = mapsegs[1][tileoff] + 18;\r
- info = mapsegs[2][tileoff];\r
- x = info >> 8;\r
- y = info & 0xFF;\r
- RF_MemToMap(&newtile, 1, ob->tilemidx, ob->tilebottom, 1, 1);\r
- SD_PlaySound(SND_OPENDOOR);\r
- GetNewObj(false);\r
- new->x = x;\r
- new->y = y;\r
-\r
- if (x > mapwidth || x < 2 || y > mapheight || y < 2)\r
- Quit("Keyholder points to a bad spot!");\r
-\r
- map = mapsegs[1] + mapbwidthtable[y]/2 + x;\r
- tile = *map;\r
- h = 1;\r
- map += mapwidth;\r
- while (*map == tile)\r
- {\r
- h++;\r
- map += mapwidth;\r
- }\r
- new->temp1 = h;\r
- new->active = ac_allways;\r
- new->needtoclip = cl_noclip;\r
- new->obclass = inertobj;\r
- NewState(new, &s_door1);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenAirThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenAirThink(objtype *ob)\r
-{\r
- if (jumpcheat && jumpbutton)\r
- {\r
- ob->yspeed = -40;\r
- jumptime = 18;\r
- jumpheld = true;\r
- }\r
- if (jumptime)\r
- {\r
- if (jumptime <= tics)\r
- {\r
- ytry = ob->yspeed * jumptime;\r
- jumptime = 0;\r
- }\r
- else\r
- {\r
- ytry = ob->yspeed * tics;\r
- if (!jumpcheat)\r
- jumptime = jumptime - tics;\r
- }\r
- if (!jumpbutton)\r
- jumptime = 0;\r
-\r
- if (jumptime == 0 && ob->state->nextstate)\r
- ob->state = ob->state->nextstate; // switch to second jump stage\r
- }\r
- else\r
- {\r
- if (gamestate.difficulty == gd_Easy)\r
- {\r
- DoWeakGravity(ob);\r
- }\r
- else\r
- {\r
- DoGravity(ob);\r
- }\r
- if (ob->yspeed > 0 && ob->state != &s_keenjump3 && ob->state != &s_keenjump4)\r
- {\r
- ob->state = ob->state->nextstate; // switch to third jump stage\r
- }\r
- }\r
-\r
-//-------------\r
-\r
- if (c.xaxis)\r
- {\r
- ob->xdir = c.xaxis;\r
- AccelerateX(ob, c.xaxis*2, 24);\r
- }\r
- else\r
- {\r
- FrictionX(ob);\r
- }\r
-\r
- if (ob->hitsouth == 17) // going through a pole hole\r
- {\r
- ob->xspeed = xtry = 0;\r
- }\r
-\r
- if (firebutton && !fireheld)\r
- {\r
- fireheld = true;\r
- //\r
- // shoot\r
- //\r
- switch (c.yaxis)\r
- {\r
- case -1:\r
- ob->state = &s_keenairshootup1;\r
- return;\r
- case 0:\r
- ob->state = &s_keenairshoot1;\r
- return;\r
- case 1:\r
- ob->state = &s_keenairshootdown1;\r
- return;\r
- }\r
- }\r
-\r
- if (pogobutton && !pogoheld)\r
- {\r
- pogoheld = true;\r
- ob->state = &s_keenpogo;\r
- jumptime = 0;\r
- return;\r
- }\r
-\r
- if (c.yaxis == -1)\r
- CheckGrabPole(ob);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenBounceThink\r
-=\r
-= Gives an extra bit of height on the first pogo bounce and creates\r
-= the "impossible pogo trick" when the jump key is held down\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenBounceThink(objtype *ob)\r
-{\r
- ob->yspeed = -48;\r
- ytry = ob->yspeed * 6;\r
- jumptime = 24;\r
- SD_PlaySound(SND_POGOBOUNCE);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenPogoThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenPogoThink(objtype *ob)\r
-{\r
- if (jumptime)\r
- {\r
- if (jumpbutton || jumptime <= 9)\r
- {\r
- DoTinyGravity(ob);\r
- }\r
- else\r
- {\r
- DoGravity(ob);\r
- }\r
- if (jumptime <= tics)\r
- {\r
- jumptime = 0;\r
- }\r
- else\r
- {\r
- jumptime = jumptime - tics;\r
- }\r
- if (jumptime == 0 && ob->state->nextstate)\r
- ob->state = ob->state->nextstate;\r
- }\r
- else\r
- {\r
- if (gamestate.difficulty == gd_Easy)\r
- {\r
- DoWeakGravity(ob);\r
- }\r
- else\r
- {\r
- DoGravity(ob);\r
- }\r
- }\r
-\r
- if (c.xaxis)\r
- {\r
- if (ob->xspeed == 0)\r
- ob->xdir = c.xaxis;\r
- AccelerateX(ob, c.xaxis, 24);\r
- }\r
- else\r
- {\r
- xtry = xtry + ob->xspeed * tics;\r
- if (ob->xspeed > 0)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else if (ob->xspeed < 0)\r
- {\r
- ob->xdir = -1;\r
- }\r
- }\r
-\r
- if (ob->hitsouth == 17) // going through a pole hole\r
- {\r
- ob->xspeed = xtry = 0;\r
- }\r
-\r
- if (firebutton && !fireheld)\r
- {\r
- fireheld = true;\r
- switch (c.yaxis)\r
- {\r
- case -1:\r
- ob->state = &s_keenairshootup1;\r
- return;\r
- case 0:\r
- ob->state = &s_keenairshoot1;\r
- return;\r
- case 1:\r
- ob->state = &s_keenairshootdown1;\r
- return;\r
- }\r
- }\r
-\r
- if (pogobutton && !pogoheld)\r
- {\r
- pogoheld = true;\r
- ob->state = &s_keenjump3;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= PoleActions\r
-=\r
-=======================\r
-*/\r
-\r
-void PoleActions(objtype *ob)\r
-{\r
- if (c.xaxis)\r
- ob->xdir = c.xaxis;\r
-\r
- if (firebutton && !fireheld)\r
- {\r
- fireheld = true;\r
- switch (c.yaxis)\r
- {\r
- case -1:\r
- ob->state = &s_keenpoleshootup1;\r
- break;\r
- case 0:\r
- ob->state = &s_keenpoleshoot1;\r
- break;\r
- case 1:\r
- ob->state = &s_keenpoleshootdown1;\r
- break;\r
- }\r
- }\r
-\r
- if (jumpbutton && !jumpheld) // jump off the pole\r
- {\r
- jumpheld = true;\r
- SD_PlaySound(SND_JUMP);\r
- ob->xspeed = polexspeed[c.xaxis+1];\r
- ob->yspeed = -20;\r
- ob->needtoclip = cl_midclip;\r
- jumptime = 10;\r
- ob->state = &s_keenjump1;\r
- ob->ydir = 1;\r
- leavepoletime = lasttimecount;\r
- }\r
-}\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenPoleThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenPoleThink(objtype *ob)\r
-{\r
- Uint16 tile;\r
- Uint16 far *map;\r
-\r
- switch (c.yaxis)\r
- {\r
- case -1:\r
- ob->state = &s_keenclimb1;\r
- ob->ydir = -1;\r
- return;\r
- case 1:\r
- ob->state = &s_keenslide1;\r
- ob->ydir = 1;\r
- KeenDropThink(ob);\r
- return;\r
- }\r
-\r
- if (c.xaxis)\r
- {\r
- //\r
- // walk off pole if right next to ground\r
- //\r
- map = mapsegs[1] + (mapbwidthtable[ob->tilebottom+1]/2 + ob->tilemidx);\r
- tile = *map;\r
- if (tinf[NORTHWALL+tile])\r
- {\r
- ob->xspeed = 0;\r
- ob->yspeed = 0;\r
- ob->needtoclip = cl_midclip;\r
- jumptime = 0;\r
- ob->state = &s_keenjump3;\r
- ob->ydir = 1;\r
- SD_PlaySound(SND_PLUMMET);\r
- return;\r
- }\r
- }\r
- PoleActions(ob);\r
-}\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenClimbThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenClimbThink(objtype *ob)\r
-{\r
- Uint16 far *map;\r
-\r
- map = mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tilemidx;\r
- \r
- if ((tinf[INTILE+*map] & 0x7F) != INTILE_POLE)\r
- {\r
- ytry = 0;\r
- ob->state = &s_keenpole; // ran out of pole\r
- PoleActions(ob);\r
- return;\r
- }\r
-\r
- switch (c.yaxis)\r
- {\r
- case 0:\r
- ob->state = &s_keenpole;\r
- ob->ydir = 0;\r
- break;\r
-\r
- case 1:\r
- ob->state = &s_keenslide1;\r
- ob->ydir = 1;\r
- KeenDropThink(ob);\r
- break;\r
- }\r
-\r
- PoleActions(ob);\r
-}\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenDropThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenDropThink(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 y;\r
-\r
- y = CONVERT_GLOBAL_TO_TILE(ob->bottom - 4*PIXGLOBAL);\r
- map = mapsegs[1] + mapbwidthtable[y]/2 + ob->tilemidx;\r
-\r
- if ((tinf[INTILE+*map] & 0x7F) != INTILE_POLE)\r
- {\r
- SD_PlaySound(SND_PLUMMET);\r
- ob->state = &s_keenjump3; // ran out of pole\r
- jumptime = 0;\r
- ob->xspeed = polexspeed[c.xaxis+1];\r
- ob->yspeed = 0;\r
- ob->needtoclip = cl_midclip;\r
- ob->tilebottom--;\r
- return;\r
- }\r
-\r
- switch (c.yaxis)\r
- {\r
- case -1:\r
- ob->state = &s_keenclimb1;\r
- ob->ydir = -1;\r
- break;\r
-\r
- case 0:\r
- ob->state = &s_keenpole;\r
- ob->ydir = 0;\r
- break;\r
- }\r
-\r
- PoleActions(ob);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenDropDownThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenDropDownThink(objtype *ob)\r
-{\r
- ob->needtoclip = cl_midclip;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenHoldThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenHoldThink(objtype *ob)\r
-{\r
- Uint16 tile;\r
-\r
- if (c.yaxis == -1 || ob->xdir == c.xaxis)\r
- {\r
- ob->state = &s_keenclimbup;\r
- if (ob->xdir == 1)\r
- {\r
- tile = *(mapsegs[1]+mapbwidthtable[ob->tiletop-1]/2+ob->tileright);\r
- }\r
- else\r
- {\r
- tile = *(mapsegs[1]+mapbwidthtable[ob->tiletop-1]/2+ob->tileleft);\r
- }\r
- if (ob->xdir == 1)\r
- {\r
- ytry = -16*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- ytry = -8*PIXGLOBAL;\r
- }\r
- if (!(tinf[INTILE+tile] & INTILE_FOREGROUND))\r
- ob->priority = 3;\r
- }\r
- else if (c.yaxis == 1 || c.xaxis && ob->xdir != c.xaxis)\r
- {\r
- ob->state = &s_keenjump3;\r
- ob->needtoclip = cl_midclip;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenShootThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenShootThink(objtype *ob)\r
-{\r
-// can't use &<var> in a switch statement...\r
-\r
- if (ob->state == &s_keenshoot1)\r
- {\r
- if (ob->xdir == 1)\r
- {\r
- SpawnShot(ob->x + 16*PIXGLOBAL, ob->y + 4*PIXGLOBAL, dir_East);\r
- }\r
- else\r
- {\r
- SpawnShot(ob->x - 8*PIXGLOBAL, ob->y + 4*PIXGLOBAL, dir_West);\r
- }\r
- }\r
- if (ob->state == &s_keenairshoot2)\r
- {\r
- if (ob->xdir == 1)\r
- {\r
- SpawnShot(ob->x + 16*PIXGLOBAL, ob->y + 2*PIXGLOBAL, dir_East);\r
- }\r
- else\r
- {\r
- SpawnShot(ob->x, ob->y + 2*PIXGLOBAL, dir_West);\r
- }\r
- }\r
- if (ob->state == &s_keenairshootdown2)\r
- {\r
- SpawnShot(ob->x + 8*PIXGLOBAL, ob->y + 18*PIXGLOBAL, dir_South);\r
- }\r
- if (ob->state == &s_keenairshootup2)\r
- {\r
- SpawnShot(ob->x + 5*PIXGLOBAL, ob->y - 10*PIXGLOBAL, dir_North);\r
- }\r
- if (ob->state == &s_keenshootup1)\r
- {\r
- SpawnShot(ob->x + 5*PIXGLOBAL, ob->y - 10*PIXGLOBAL, dir_North);\r
- }\r
- if (ob->state == &s_keenpoleshoot1)\r
- {\r
- if (ob->xdir == 1)\r
- {\r
- SpawnShot(ob->x + 16*PIXGLOBAL, ob->y + 4*PIXGLOBAL, dir_East);\r
- }\r
- else\r
- {\r
- SpawnShot(ob->x - 8*PIXGLOBAL, ob->y + 4*PIXGLOBAL, dir_West);\r
- }\r
- }\r
- if (ob->state == &s_keenpoleshootup1)\r
- {\r
- if (ob->xdir == 1)\r
- {\r
- SpawnShot(ob->x + 6*PIXGLOBAL, ob->y + 4*PIXGLOBAL, dir_North);\r
- }\r
- else\r
- {\r
- SpawnShot(ob->x + 12*PIXGLOBAL, ob->y + 4*PIXGLOBAL, dir_North);\r
- }\r
- }\r
- if (ob->state == &s_keenpoleshootdown1)\r
- {\r
- if (ob->xdir == 1)\r
- {\r
- SpawnShot(ob->x + 6*PIXGLOBAL, ob->y + 24*PIXGLOBAL, dir_South);\r
- }\r
- else\r
- {\r
- SpawnShot(ob->x + 12*PIXGLOBAL, ob->y + 24*PIXGLOBAL, dir_South);\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= T_PullUp1\r
-=\r
-=======================\r
-*/\r
-\r
-void T_PullUp1(objtype *ob)\r
-{\r
- if (ob->xdir == 1)\r
- {\r
- xtry = 8*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- ytry = -8*PIXGLOBAL;\r
- }\r
-}\r
-\r
-/*\r
-=======================\r
-=\r
-= T_PullUp2\r
-=\r
-=======================\r
-*/\r
-\r
-void T_PullUp2(objtype *ob)\r
-{\r
- if (ob->xdir == 1)\r
- {\r
- xtry = 8*PIXGLOBAL;\r
- ytry = -8*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- xtry = -8*PIXGLOBAL;\r
- ytry = -8*PIXGLOBAL;\r
- }\r
-}\r
-\r
-/*\r
-=======================\r
-=\r
-= T_PullUp3\r
-=\r
-=======================\r
-*/\r
-\r
-#pragma argsused\r
-void T_PullUp3(objtype *ob)\r
-{\r
- ytry = -8*PIXGLOBAL;\r
-}\r
-\r
-/*\r
-=======================\r
-=\r
-= T_PulledUp\r
-=\r
-=======================\r
-*/\r
-\r
-void T_PulledUp(objtype *ob)\r
-{\r
- ob->needtoclip = cl_midclip;\r
- ob->priority = 1;\r
- ytry = 8*PIXGLOBAL;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= KeenDieThink\r
-=\r
-=======================\r
-*/\r
-\r
-void KeenDieThink(objtype *ob)\r
-{\r
- DoWeakGravity(ob);\r
- xtry = ob->xspeed * tics;\r
- if (!OnScreen(ob))\r
- playstate = ex_died;\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- CONTACT ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-============================\r
-=\r
-= KillKeen\r
-=\r
-============================\r
-*/\r
-\r
-void KillKeen(void)\r
-{\r
- if (invincible || godmode)\r
- return;\r
-\r
- if (player->state != &s_keendead)\r
- {\r
-\r
- moonok = 0;\r
- invincible = 30; //0.43 seconds\r
- keenkilled = true;\r
- player->needtoclip = cl_noclip;\r
- player->priority = 3;\r
-#ifdef KEEN4\r
- if (mapon == 17)\r
- {\r
- if (US_RndT() < 0x80)\r
- {\r
- ChangeState(player, &s_keensuitdie1);\r
- }\r
- else\r
- {\r
- ChangeState(player, &s_keensuitdie2);\r
- }\r
- }\r
- else\r
-#endif\r
- {\r
- if (US_RndT() < 0x80)\r
- {\r
- ChangeState(player, &s_keendie1);\r
- }\r
- else\r
- {\r
- ChangeState(player, &s_keendie2);\r
- }\r
- }\r
- SD_PlaySound(SND_KEENDEAD);\r
- player->yspeed = -40;\r
- player->xspeed = 16;\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= KeenContact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenContact(objtype *ob, objtype *hit)\r
-{\r
- switch (hit->obclass)\r
- {\r
- case bonusobj:\r
- switch (hit->temp1)\r
- {\r
- case 0:\r
- case 1:\r
- case 2:\r
- case 3:\r
- case 4:\r
- case 5:\r
- case 6:\r
- case 7:\r
- case 8:\r
- case 9:\r
- case 10:\r
- case 11:\r
-#ifdef KEEN5\r
- case 12:\r
-#endif\r
- SD_PlaySound(bonussound[hit->temp1]);\r
- hit->obclass = inertobj;\r
- hit->priority = 3;\r
- hit->shapenum = bonussprite[hit->temp1];\r
- GivePoints(bonuspoints[hit->temp1]);\r
- if (hit->temp1 < 4)\r
- {\r
- gamestate.keys[hit->temp1]++;\r
- }\r
- else if (hit->temp1 == 10)\r
- {\r
- gamestate.lives++;\r
- }\r
- else if (hit->temp1 == 11)\r
- {\r
- gamestate.ammo += shotsinclip[gamestate.difficulty];\r
- }\r
-#ifdef KEEN5\r
- else if (hit->temp1 == 12)\r
- {\r
- gamestate.keycard = true;\r
- }\r
-#endif\r
- ChangeState(hit, &s_bonusrise);\r
- }\r
- break;\r
-\r
-#if defined KEEN4\r
- case oracleobj:\r
- if (!ob->hitnorth)\r
- break;\r
-\r
- if (mapon == 14)\r
- {\r
- RescueJanitor();\r
- RF_ForceRefresh();\r
- RemoveObj(hit);\r
- }\r
- else\r
- {\r
- SD_PlaySound(SND_LINDSEY);\r
- playstate = ex_rescued;\r
- }\r
- break;\r
- case stunnedobj:\r
- if (hit->temp4 != bounderobj)\r
- break;\r
- //no break here -- drop through to platformobj is intended!\r
- case platformobj:\r
- if (!gamestate.riding)\r
- {\r
- ClipToSpriteTop(ob, hit);\r
- }\r
- else\r
- return;\r
- break;\r
- case bounderobj:\r
- ClipToSprite(ob, hit, false);\r
- break;\r
- case lindseyobj:\r
- PrincessLindsey();\r
- RemoveObj(hit);\r
- RF_ForceRefresh();\r
- break;\r
- case footobj:\r
- playstate = ex_foot;\r
- break;\r
-#elif defined KEEN5\r
- case platformobj:\r
- if (!gamestate.riding)\r
- ClipToSpriteTop(ob, hit);\r
- break;\r
-#elif defined KEEN6\r
- case stunshotobj:\r
- if (hit->temp4)\r
- {\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_keenstun);\r
- }\r
- // BUG: there is no break here - this causes the impossible bullet bug\r
- case platformobj:\r
- if (!gamestate.riding)\r
- ClipToSpriteTop(ob, hit);\r
- break;\r
-#endif\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= KeenPosContact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenPosContact(objtype *ob, objtype *hit)\r
-{\r
- switch (hit->obclass)\r
- {\r
-#if defined KEEN4\r
- case platformobj:\r
- // BUG: priority is not reset here\r
- ob->needtoclip = cl_midclip;\r
- ChangeState(ob, &s_keenjump3);\r
- jumptime = ob->xspeed = ob->yspeed = 0;\r
- ClipToSpriteTop(ob, hit);\r
- break;\r
- case madmushroomobj:\r
- case arachnutobj:\r
- case berkeloidobj:\r
- KillKeen();\r
- break;\r
- case bounderobj:\r
- ob->priority = 1;\r
- ob->needtoclip = cl_midclip;\r
- ChangeState(ob, &s_keenjump3);\r
- jumptime = ob->xspeed = ob->yspeed = 0;\r
- ClipToSprite(ob, hit, false);\r
- break;\r
-#elif defined KEEN5\r
- case platformobj:\r
- // BUG: priority is not reset here\r
- ob->needtoclip = cl_midclip;\r
- ChangeState(ob, &s_keenjump3);\r
- jumptime = ob->xspeed = ob->yspeed = 0;\r
- ClipToSpriteTop(ob, hit);\r
- break;\r
- case amptonobj:\r
- case scottieobj:\r
- ob->priority = 1;\r
- ob->needtoclip = cl_midclip;\r
- ChangeState(ob, &s_keenjump3);\r
- jumptime = ob->xspeed = ob->yspeed = 0;\r
- break;\r
-#elif defined KEEN6\r
- case platformobj:\r
- case gikobj:\r
- case flectobj:\r
- case bloogletobj:\r
- ob->priority = 1;\r
- ob->needtoclip = cl_midclip;\r
- ChangeState(ob, &s_keenjump3);\r
- jumptime = ob->xspeed = ob->yspeed = 0;\r
- ClipToSpriteTop(ob, hit); // BUG: allows Keen to stand on Blooglets and Flects\r
- break;\r
-#endif\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= HandleRiding\r
-=\r
-============================\r
-*/\r
-\r
-void HandleRiding(objtype *ob)\r
-{\r
- objtype *plat;\r
-\r
- plat = gamestate.riding;\r
- if (ob->right < plat->left || ob->left > plat->right)\r
- {\r
- gamestate.riding = NULL;\r
- }\r
- else if (ob->ymove < 0)\r
- {\r
- gamestate.riding = NULL;\r
- if (plat->ymove < 0)\r
- {\r
- xtry = 0;\r
- ytry = plat->ymove;\r
- PushObj(ob);\r
- }\r
- }\r
- else\r
- {\r
- xtry = plat->xmove;\r
- ytry = plat->top - ob->bottom - 16;\r
- PushObj(ob);\r
-\r
-#if GRMODE == CGAGR\r
- if (ob->xmove == plat->xmove)\r
- {\r
- ob->x &= ~0x3F;\r
- ob->x |= plat->x & 0x3F;\r
- }\r
-#else\r
- if (nopan)\r
- {\r
- ob->x &= ~0x7F;\r
- ob->x |= plat->x & 0x7F;\r
- }\r
- else\r
- {\r
- ob->x |= plat->x & 0x1F;\r
- }\r
-#endif\r
-\r
- if (ob->hitsouth)\r
- {\r
- gamestate.riding = NULL;\r
- }\r
- else\r
- {\r
- ob->hitnorth = 25;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= TileBonus\r
-=\r
-============================\r
-*/\r
-\r
-void TileBonus(Uint16 x, Uint16 y, Uint16 bonus)\r
-{\r
- RF_MemToMap(&zeromap, 1, x, y, 1, 1);\r
- SD_PlaySound(bonussound[bonus]);\r
- GivePoints(bonuspoints[bonus]);\r
- if (bonus < 4)\r
- {\r
- gamestate.keys[bonus]++;\r
- }\r
- else if (bonus == 10)\r
- {\r
- gamestate.lives++;\r
- }\r
- else if (bonus == 11)\r
- {\r
- gamestate.ammo += shotsinclip[gamestate.difficulty];\r
- }\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->priority = 3;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- new->ydir = -1;\r
- new->temp2 = new->shapenum = bonussprite[bonus];\r
- NewState(new, &s_bonusrise);\r
- new->needtoclip = cl_noclip;\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= GiveDrop\r
-=\r
-============================\r
-*/\r
-\r
-void GiveDrop(Uint16 x, Uint16 y)\r
-{\r
- RF_MemToMap(&zeromap, 1, x, y, 1, 1);\r
- SD_PlaySound(SND_GETWATER);\r
- SpawnSplash(x, y);\r
- if (++gamestate.drops == 100)\r
- {\r
- gamestate.drops = 0;\r
- SD_PlaySound(SND_EXTRAKEEN);\r
- gamestate.lives++;\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->priority = 3;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y-1);\r
- new->ydir = -1;\r
- new->temp2 = new->shapenum = BONUS100UPSPR;\r
- NewState(new, &s_bonusrise);\r
- new->needtoclip = cl_noclip;\r
- }\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= CheckInTiles\r
-=\r
-============================\r
-*/\r
-\r
-void CheckInTiles(objtype *ob)\r
-{\r
- Uint16 x, y;\r
- Uint16 far *map;\r
- Uint16 rowdelta, intile, midx;\r
-\r
- if (moonok == 1)\r
- moonok = 0;\r
-\r
- map = mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft;\r
- rowdelta = mapwidth - (ob->tileright - ob->tileleft + 1);\r
- for (y = ob->tiletop; y <= ob->tilebottom; y++, map += rowdelta)\r
- {\r
- for (x = ob->tileleft; x <= ob->tileright; x++, map++)\r
- {\r
- if ((intile = tinf[INTILE + *map] & INTILE_TYPEMASK) != 0)\r
- {\r
- switch (intile)\r
- {\r
- case INTILE_DEADLY:\r
- KillKeen();\r
- break;\r
-\r
- case INTILE_DROP:\r
- GiveDrop(x, y);\r
- break;\r
-\r
- case INTILE_GEMSOCKET0:\r
- case INTILE_GEMSOCKET1:\r
- case INTILE_GEMSOCKET2:\r
- case INTILE_GEMSOCKET3:\r
- if (ob->tilebottom != y || !ob->hitnorth\r
- || ob->state == &s_keenkey\r
- || !gamestate.keys[intile-INTILE_GEMSOCKET0])\r
- {\r
- return;\r
- }\r
-\r
- midx = CONVERT_TILE_TO_GLOBAL(x) + -4*PIXGLOBAL;\r
- if (ob->x != midx)\r
- {\r
- ob->temp1 = midx;\r
- ob->state = &s_keenlineup;\r
- return;\r
- }\r
- else\r
- {\r
- gamestate.keys[intile-INTILE_GEMSOCKET0]--;\r
- ChangeState(ob, &s_keenkey);\r
- }\r
- break;\r
-\r
- case INTILE_MOON:\r
- if (moonok == 0)\r
- moonok = 1;\r
- break;\r
-\r
- case INTILE_BONUS100:\r
- case INTILE_BONUS200:\r
- case INTILE_BONUS500:\r
- case INTILE_BONUS1000:\r
- case INTILE_BONUS2000:\r
- case INTILE_BONUS5000:\r
- case INTILE_EXTRALIFE:\r
- case INTILE_AMMO:\r
- TileBonus(x, y, (intile-INTILE_BONUS100)+4);\r
- break;\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- REACTION ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-============================\r
-=\r
-= KeenSimpleReact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenSimpleReact(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-\r
-/*\r
-============================\r
-=\r
-= KeenStandReact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenStandReact(objtype *ob)\r
-{\r
- if (!ob->hitnorth)\r
- {\r
- //\r
- // walked off an edge\r
- //\r
- SD_PlaySound(SND_PLUMMET);\r
- ob->xspeed = ob->xdir * 8;\r
- ob->yspeed = 0;\r
- ChangeState(ob, &s_keenjump3);\r
- jumptime = 0;\r
- }\r
- else if ((ob->hitnorth & ~7) == 8) // deadly floor!\r
- {\r
- KillKeen();\r
- }\r
- else if (ob->hitnorth == 41)\r
- {\r
- xtry = tics * 8;\r
- ytry = 0;\r
- ob->temp1 = 0;\r
- ClipToWalls(ob);\r
- }\r
- else if (ob->hitnorth == 49)\r
- {\r
- xtry = tics * -8;\r
- ytry = 0;\r
- ob->temp1 = 0;\r
- ClipToWalls(ob);\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= KeenWalkReact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenWalkReact(objtype *ob)\r
-{\r
- if (!ob->hitnorth)\r
- {\r
- //\r
- // walked off an edge\r
- //\r
- SD_PlaySound(SND_PLUMMET);\r
- ob->xspeed = ob->xdir * 8;\r
- ob->yspeed = 0;\r
- ChangeState(ob, &s_keenjump3);\r
- jumptime = 0;\r
- }\r
- else if ((ob->hitnorth & ~7) == 8) // deadly floor!\r
- {\r
- KillKeen();\r
- }\r
- else if (ob->hitnorth == 41)\r
- {\r
- xtry = tics * 8;\r
- ytry = 0;\r
- ClipToWalls(ob);\r
- }\r
- else if (ob->hitnorth == 49)\r
- {\r
- xtry = tics * -8;\r
- ytry = 0;\r
- ClipToWalls(ob);\r
- }\r
- else if (ob->hiteast && ob->xdir == -1 || ob->hitwest && ob->xdir == 1)\r
- {\r
- //\r
- // ran into a wall\r
- //\r
- ob->ticcount = 0;\r
- ob->state = &s_keenstand;\r
- ob->shapenum = ob->xdir == 1? s_keenstand.rightshapenum : s_keenstand.leftshapenum;\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= KeenAirReact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenAirReact(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 oldtop, graby, ty, tile;\r
-\r
- if (ob->hiteast && ob->xdir == -1 || ob->hitwest && ob->xdir == 1)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitsouth)\r
- {\r
- if (ob->hitsouth == 17) // jumping up through a pole hole\r
- {\r
- ob->y -= 2*PIXGLOBAL;\r
- ob->top -= 2*PIXGLOBAL;\r
- ob->xspeed = 0;\r
- ob->x = CONVERT_TILE_TO_GLOBAL(ob->tilemidx) - 2*PIXGLOBAL;\r
- }\r
- else\r
- {\r
-#ifdef KEEN6\r
- if (ob->hitsouth == 33)\r
- {\r
- FlipBigSwitch(ob, false);\r
- }\r
-#endif\r
- if (!jumpcheat)\r
- {\r
- SD_PlaySound(SND_HELMETHIT);\r
- if (ob->hitsouth > 1)\r
- {\r
- ob->yspeed += 16;\r
- if (ob->yspeed < 0) // push away from slopes\r
- ob->yspeed = 0;\r
- }\r
- else\r
- {\r
- ob->yspeed = 0;\r
- }\r
- jumptime = 0;\r
- }\r
- }\r
- }\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->ymove = 0;\r
- if ((ob->hitnorth & ~7) == 8) // deadly floor!\r
- {\r
- KillKeen();\r
- }\r
- else\r
- {\r
-#if defined KEEN5\r
- if (ob->hitnorth == 57)\r
- {\r
- SD_PlaySound(SND_LANDONFUSE);\r
- }\r
-#elif defined KEEN6\r
- if (ob->hitnorth == 33)\r
- {\r
- FlipBigSwitch(ob, true);\r
- }\r
-#endif\r
- if (ob->hitnorth != 25 || !jumptime) // KLUDGE to allow jumping off\r
- {\r
- ob->temp1 = ob->temp2 = 0;\r
- if (ob->state == &s_keenairshoot1)\r
- {\r
- ChangeState(ob, &s_keenshoot1);\r
- }\r
- else if (ob->state == &s_keenairshootup1)\r
- {\r
- ChangeState(ob, &s_keenshootup1);\r
- }\r
- else if (c.xaxis)\r
- {\r
- ChangeState(ob, &s_keenwalk1);\r
- }\r
- else\r
- {\r
- ChangeState(ob, &s_keenstand);\r
- }\r
- SD_PlaySound(SND_LAND);\r
- }\r
- }\r
- }\r
- else if (ob->ymove > 0)\r
- {\r
-//\r
-// check if there is an edge to grab\r
-//\r
- oldtop = ob->top - ob->ymove;\r
- graby = ((ob->top - 4*PIXGLOBAL) & 0xFF00) + 4*PIXGLOBAL;\r
- ty = CONVERT_GLOBAL_TO_TILE(graby) - 1;\r
- if (oldtop < graby && ob->top >= graby)\r
- {\r
- if (c.xaxis == -1)\r
- {\r
- map = mapsegs[1] + mapbwidthtable[ty]/2 + ob->tileleft;\r
- if (ob->hiteast)\r
- map--;\r
- tile = *map;\r
- if (!tinf[EASTWALL + tile] && !tinf[WESTWALL + tile]\r
- && !tinf[NORTHWALL + tile] && !tinf[SOUTHWALL + tile]\r
- && tinf[EASTWALL + map[mapwidth]] && tinf[NORTHWALL + map[mapwidth]]\r
- )\r
- {\r
- ob->xdir = -1;\r
- ob->needtoclip = cl_noclip;\r
- ob->x = (ob->x & 0xFF00) + 8*PIXGLOBAL;\r
- ob->y = graby - 4*PIXGLOBAL;\r
- ob->yspeed = ob->ymove = 0;\r
- ChangeState(ob, &s_keenholdon);\r
- }\r
- }\r
- else if (c.xaxis == 1)\r
- {\r
- map = mapsegs[1] + mapbwidthtable[ty]/2 + ob->tileright;\r
- if (ob->hitwest)\r
- map++;\r
- tile = *map;\r
- if (!tinf[EASTWALL + tile] && !tinf[WESTWALL + tile]\r
- && !tinf[NORTHWALL + tile] && !tinf[SOUTHWALL + tile]\r
- && tinf[WESTWALL + map[mapwidth]] && tinf[NORTHWALL + map[mapwidth]]\r
- )\r
- {\r
- ob->xdir = 1;\r
- ob->needtoclip = cl_noclip;\r
- ob->x = (ob->x & 0xFF00) + 16*PIXGLOBAL;\r
- ob->y = graby - 4*PIXGLOBAL;\r
- ob->yspeed = ob->ymove = 0;\r
- ChangeState(ob, &s_keenholdon);\r
- }\r
- }\r
- }\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-#ifdef KEEN5\r
-/*\r
-============================\r
-=\r
-= BreakFuse\r
-=\r
-============================\r
-*/\r
-\r
-void BreakFuse(Uint16 tileX, Uint16 tileY)\r
-{\r
- Uint16 tiles[] = {1932, 1950}; // should be 'static' for less overhead\r
-\r
- // The original disassembly had some code here equivalent to this:\r
- //\r
- // _AX = tiles[0];\r
- // _DX = 4;\r
- //\r
- // As it turned out, that was just a compiler quirk.\r
-\r
- SpawnFuseFlash(tileX, tileY);\r
- if (--gamestate.numfuses == 0)\r
- {\r
- SpawnDeadMachine();\r
- }\r
- RF_MemToMap(tiles, 1, tileX, tileY, 1, 2);\r
-}\r
-#endif\r
-\r
-/*\r
-============================\r
-=\r
-= KeenPogoReact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenPogoReact(objtype *ob)\r
-{\r
- if (ob->hiteast && ob->xdir == -1 || ob->hitwest && ob->xdir == 1)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitsouth)\r
- {\r
- if (ob->hitsouth == 17) // jumping up through a pole hole\r
- {\r
- ob->y -= 2*PIXGLOBAL;\r
- ob->top -= 2*PIXGLOBAL;\r
- ob->xspeed = 0;\r
- ob->x = CONVERT_TILE_TO_GLOBAL(ob->tilemidx) - 2*PIXGLOBAL;\r
- }\r
- else\r
- {\r
-#ifdef KEEN6\r
- if (ob->hitsouth == 33)\r
- {\r
- FlipBigSwitch(ob, false);\r
- }\r
-#endif\r
- if (!jumpcheat)\r
- {\r
- SD_PlaySound(SND_HELMETHIT);\r
- if (ob->hitsouth > 1)\r
- {\r
- ob->yspeed += 16;\r
- if (ob->yspeed < 0) // push away from slopes\r
- ob->yspeed = 0;\r
- }\r
- else\r
- {\r
- ob->yspeed = 0;\r
- }\r
- jumptime = 0;\r
- }\r
- }\r
- }\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->ymove = 0;\r
- if ((ob->hitnorth & ~7) == 8) // deadly floor!\r
- {\r
- KillKeen();\r
- }\r
- else\r
- {\r
-#if defined KEEN5\r
- if (ob->hitnorth == 57)\r
- {\r
- if (ob->yspeed < 48)\r
- {\r
- SD_PlaySound(SND_LANDONFUSE);\r
- }\r
- else\r
- {\r
- BreakFuse(ob->tilemidx, ob->tilebottom);\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- return;\r
- }\r
- }\r
-#elif defined KEEN6\r
- if (ob->hitnorth == 33)\r
- {\r
- FlipBigSwitch(ob, true);\r
- }\r
- else if (ob->hitnorth == 41)\r
- {\r
- ob->xspeed += 8;\r
- if (ob->xspeed > 8)\r
- ob->xspeed = 8;\r
- }\r
- else if (ob->hitnorth == 49)\r
- {\r
- ob->xspeed -= 8;\r
- if (ob->xspeed < -8)\r
- ob->xspeed = -8;\r
- }\r
-#endif\r
- if (ob->hitnorth != 25 || !jumptime) // KLUDGE to allow jumping off\r
- {\r
- ob->yspeed = -48;\r
- jumptime = 24;\r
- SD_PlaySound(SND_POGOBOUNCE);\r
- ChangeState(ob, &s_keenpogo);\r
- }\r
- }\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-============================\r
-=\r
-= KeenPoleReact\r
-=\r
-============================\r
-*/\r
-\r
-void KeenPoleReact(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 ymove;\r
-\r
- map = mapsegs[1] + mapbwidthtable[ob->tilebottom]/2 + ob->tilemidx;\r
- if (tinf[NORTHWALL + *map] == 1)\r
- {\r
- ymove = (ob->bottom & 0xFF) + 1;\r
- ob->y -= ymove;\r
- ob->bottom -= ymove;\r
- ob->tilebottom--;\r
- ob->needtoclip = cl_midclip;\r
- ChangeState(ob, &s_keenlookdown);\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-CK_KEEN2.C\r
-==========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Score Box & Demo sprites\r
-- Keen (world map)\r
-- Flags (world map)\r
-- Neural Stunner Shots\r
-- Gem Door Opener\r
-- Card Door Opener (Keen 5 only)\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-Direction opposite[8] = {dir_South, dir_SouthWest, dir_West, dir_NorthWest, dir_North, dir_NorthEast, dir_East, dir_SouthEast};\r
-\r
-/*\r
-=============================================================================\r
-\r
- SCORE BOX ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_score = { 0, 0, think, false, false, 0, 0, 0, NULL, NULL, NULL, NULL};\r
-statetype s_demo = {DEMOPLAQUESPR, DEMOPLAQUESPR, think, false, false, 0, 0, 0, NULL, NULL, NULL, NULL};\r
-\r
-/*\r
-======================\r
-=\r
-= SpawnScore\r
-=\r
-======================\r
-*/\r
-\r
-void SpawnScore(void)\r
-{\r
- scoreobj->obclass = inertobj;\r
- scoreobj->priority = 3;\r
- scoreobj->active = ac_allways;\r
- scoreobj->needtoclip = cl_noclip;\r
- scoreobj->temp2 = -1;\r
- scoreobj->temp1 = -1;\r
- scoreobj->temp3 = -1;\r
- scoreobj->temp4 = -1;\r
- if (scorescreenkludge)\r
- {\r
- scoreobj->state = &sc_deadstate;\r
- }\r
- else if (!DemoMode)\r
- {\r
- NewState(scoreobj, &s_score);\r
- }\r
- else\r
- {\r
- NewState(scoreobj, &s_demo);\r
- CA_MarkGrChunk(DEMOPLAQUESPR);\r
- }\r
-}\r
-\r
-\r
-// Taken from Keen Dreams: MemDrawChar and ShiftScore\r
-\r
-/*\r
-======================\r
-=\r
-= MemDrawChar\r
-=\r
-======================\r
-*/\r
-\r
-#if GRMODE == EGAGR\r
-\r
-void MemDrawChar(Sint16 char8, Uint8 far *dest, Uint16 width, Uint16 planesize)\r
-{\r
- Uint16 source = (Uint16)grsegs[STARTTILE8]; // Note: this differs from Keen Dreams source\r
-\r
-asm mov si,[char8]\r
-asm shl si,1\r
-asm shl si,1\r
-asm shl si,1\r
-asm shl si,1\r
-asm shl si,1 // index into char 8 segment\r
-\r
-asm mov ds,[WORD PTR source] // Note: this differs from Keen Dreams source\r
-asm mov es,[WORD PTR dest+2]\r
-\r
-asm mov cx,4 // draw four planes\r
-asm mov bx,[width]\r
-asm dec bx\r
-\r
-planeloop:\r
-\r
-asm mov di,[WORD PTR dest]\r
-\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-\r
-asm mov ax,[planesize]\r
-asm add [WORD PTR dest],ax\r
-\r
-asm loop planeloop\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-}\r
-\r
-#elif GRMODE == CGAGR\r
-\r
-void MemDrawChar (int char8,byte far *dest,unsigned width,unsigned planesize)\r
-{\r
-asm mov si,[char8]\r
-asm shl si,1\r
-asm shl si,1\r
-asm shl si,1\r
-asm shl si,1 // index into char 8 segment\r
-\r
-asm mov ds,[WORD PTR grsegs+STARTTILE8*2]\r
-asm mov es,[WORD PTR dest+2]\r
-\r
-asm mov bx,[width]\r
-asm sub bx,2\r
-\r
-asm mov di,[WORD PTR dest]\r
-\r
-asm movsw\r
-asm add di,bx\r
-asm movsw\r
-asm add di,bx\r
-asm movsw\r
-asm add di,bx\r
-asm movsw\r
-asm add di,bx\r
-asm movsw\r
-asm add di,bx\r
-asm movsw\r
-asm add di,bx\r
-asm movsw\r
-asm add di,bx\r
-asm movsw\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-\r
- planesize++; // shut the compiler up\r
-}\r
-#endif\r
-\r
-/*\r
-====================\r
-=\r
-= ShiftScore\r
-=\r
-====================\r
-*/\r
-#if GRMODE == EGAGR\r
-void ShiftScore (void)\r
-{\r
- spritetabletype far *spr;\r
- spritetype _seg *dest;\r
-\r
- spr = &spritetable[SCOREBOXSPR-STARTSPRITES];\r
- dest = (spritetype _seg *)grsegs[SCOREBOXSPR];\r
-\r
- CAL_ShiftSprite (FP_SEG(dest),dest->sourceoffset[0],\r
- dest->sourceoffset[1],spr->width,spr->height,2);\r
-\r
- CAL_ShiftSprite (FP_SEG(dest),dest->sourceoffset[0],\r
- dest->sourceoffset[2],spr->width,spr->height,4);\r
-\r
- CAL_ShiftSprite (FP_SEG(dest),dest->sourceoffset[0],\r
- dest->sourceoffset[3],spr->width,spr->height,6);\r
-}\r
-#endif\r
-\r
-/*\r
-===============\r
-=\r
-= UpdateScore\r
-=\r
-===============\r
-*/\r
-\r
-void UpdateScore(objtype *ob)\r
-{\r
- char str[10],*ch;\r
- spritetype _seg *block;\r
- Uint8 far *dest;\r
- Uint16 i, length, width, planesize, number;\r
- boolean changed;\r
-\r
- if (scorescreenkludge)\r
- return;\r
-\r
- if (DemoMode)\r
- {\r
- DrawDemoPlaque(ob);\r
- return;\r
- }\r
-\r
- if (!showscorebox)\r
- return;\r
-\r
- changed = false;\r
-\r
-//code below is a combination of ScoreThink and ScoreReact from Keen Dreams with minor changes\r
-\r
-//\r
-// score changed\r
-//\r
- if ((gamestate.score>>16) != ob->temp1\r
- || (Uint16)gamestate.score != ob->temp2 )\r
- {\r
- block = (spritetype _seg *)grsegs[SCOREBOXSPR];\r
- width = block->width[0];\r
- planesize = block->planesize[0];\r
- dest = (Uint8 far *)grsegs[SCOREBOXSPR]+block->sourceoffset[0]\r
- + planesize + width*4;\r
-\r
- ltoa (gamestate.score,str,10);\r
-\r
- // erase leading spaces\r
- length = strlen(str);\r
- for (i=9;i>length;i--)\r
- MemDrawChar (41,dest+=CHARWIDTH,width,planesize);\r
-\r
- // draw digits\r
- ch = str;\r
- while (*ch)\r
- MemDrawChar (*ch++ - '0'+42,dest+=CHARWIDTH,width,planesize);\r
-\r
-#if GRMODE == EGAGR\r
- ShiftScore ();\r
-#endif\r
- ob->needtoreact = true;\r
- ob->temp1 = gamestate.score>>16;\r
- ob->temp2 = gamestate.score;\r
-\r
- changed = true;\r
- }\r
-\r
-//\r
-// ammo changed\r
-//\r
- number = gamestate.ammo;\r
- if (number != ob->temp3)\r
- {\r
- block = (spritetype _seg *)grsegs[SCOREBOXSPR];\r
- width = block->width[0];\r
- planesize = block->planesize[0];\r
- dest = (byte far *)grsegs[SCOREBOXSPR]+block->sourceoffset[0]\r
- + planesize + width*20 + 7*CHARWIDTH;\r
-\r
- if (number > 99)\r
- strcpy (str,"99");\r
- else\r
- ltoa (number,str,10);\r
-\r
- // erase leading spaces\r
- length = strlen(str);\r
- for (i=2;i>length;i--)\r
- MemDrawChar (41,dest+=CHARWIDTH,width,planesize);\r
-\r
- // draw digits\r
- ch = str;\r
- while (*ch)\r
- MemDrawChar (*ch++ - '0'+42,dest+=CHARWIDTH,width,planesize);\r
-\r
-#if GRMODE == EGAGR\r
- ShiftScore ();\r
-#endif\r
- ob->needtoreact = true;\r
- ob->temp3 = number;\r
-\r
- changed = true;\r
- }\r
-\r
-//\r
-// lives changed\r
-//\r
- if (gamestate.lives != ob->temp4)\r
- {\r
- block = (spritetype _seg *)grsegs[SCOREBOXSPR];\r
- width = block->width[0];\r
- planesize = block->planesize[0];\r
- dest = (byte far *)grsegs[SCOREBOXSPR]+block->sourceoffset[0]\r
- + planesize + width*20 + 2*CHARWIDTH;\r
-\r
- if (gamestate.lives > 99)\r
- strcpy (str,"99");\r
- else\r
- ltoa (gamestate.lives,str,10);\r
-\r
- // erase leading spaces\r
- length = strlen(str);\r
- for (i=2;i>length;i--)\r
- MemDrawChar (41,dest+=CHARWIDTH,width,planesize);\r
-\r
- // draw digits\r
- ch = str;\r
- while (*ch)\r
- MemDrawChar (*ch++ - '0'+42,dest+=CHARWIDTH,width,planesize);\r
-\r
-#if GRMODE == EGAGR\r
- ShiftScore ();\r
-#endif\r
- ob->needtoreact = true;\r
- ob->temp4 = gamestate.lives;\r
-\r
- changed = true;\r
- }\r
-\r
-/*\r
-Note:\r
------\r
-\r
-It would be more efficient to use\r
-\r
- if (changed)\r
- ShiftScore();\r
-\r
-here instead of the individual ShiftScore() calls above. Because if the player\r
-gains a life by collecting points items, both the score and lives numbers need\r
-to be updated, which means the sprite would be shifted twice. And if the player\r
-fires a shot during the same frame, the ammo number also needs to be updated,\r
-leading to up to three shifts in one frame.\r
-*/\r
-\r
- if (ob->x != originxglobal || ob->y != originyglobal)\r
- {\r
- ob->x = originxglobal;\r
- ob->y = originyglobal;\r
- changed = true;\r
- }\r
-\r
- if (changed)\r
-#if GRMODE == EGAGR\r
- RF_PlaceSprite(&ob->sprite, ob->x+4*PIXGLOBAL, ob->y+4*PIXGLOBAL, SCOREBOXSPR, spritedraw, 3);\r
-#elif GRMODE == CGAGR\r
- RF_PlaceSprite(&ob->sprite, ob->x+8*PIXGLOBAL, ob->y+8*PIXGLOBAL, SCOREBOXSPR, spritedraw, 3);\r
-#endif\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= DrawDemoPlaque\r
-=\r
-===============\r
-*/\r
-\r
-void DrawDemoPlaque(objtype *ob)\r
-{\r
- if (ob->x != originxglobal || ob->y != originyglobal)\r
- {\r
- ob->x = originxglobal;\r
- ob->y = originyglobal;\r
- RF_PlaceSprite(&ob->sprite, ob->x + 160*PIXGLOBAL - 32*PIXGLOBAL, ob->y + 8*PIXGLOBAL, DEMOPLAQUESPR, spritedraw, 3);\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- MINI KEEN\r
-\r
-player->temp1 = dir\r
-player->temp2 = animation stage\r
-\r
-=============================================================================\r
-*/\r
-\r
-#ifdef KEEN4\r
-statetype s_keenonfoot1 = {WOLRDKEENRIDE1SPR, WOLRDKEENRIDE1SPR, stepthink, false, false, 30, 0, 0, T_FootFly, NULL, R_Draw, &s_keenonfoot2};\r
-statetype s_keenonfoot2 = {WOLRDKEENRIDE2SPR, WOLRDKEENRIDE2SPR, stepthink, false, false, 30, 0, 0, T_FootFly, NULL, R_Draw, &s_keenonfoot1};\r
-statetype s_worldswim = {0, 0, slide, true, false, 6, 16, 16, T_KeenWorldSwim, NULL, R_Draw, &s_worldswim};\r
-#endif\r
-\r
-#ifdef KEEN5\r
-statetype s_worldelevate = {-1, -1, think, true, false, 6, 16, 16, T_Elevate, NULL, R_Draw, NULL};\r
-#endif\r
-\r
-statetype s_worldkeen = {0, 0, stepthink, false, false, 360, 0, 0, T_KeenWorld, NULL, R_Draw, &s_worldkeenwave1};\r
-\r
-statetype s_worldkeenwave1 = {WORLDKEENWAVE1SPR, WORLDKEENWAVE1SPR, stepthink, false, false, 20, 0, 0, T_KeenWorld, NULL, R_Draw, &s_worldkeenwave2};\r
-statetype s_worldkeenwave2 = {WORLDKEENWAVE2SPR, WORLDKEENWAVE2SPR, stepthink, false, false, 20, 0, 0, T_KeenWorld, NULL, R_Draw, &s_worldkeenwave3};\r
-statetype s_worldkeenwave3 = {WORLDKEENWAVE1SPR, WORLDKEENWAVE1SPR, stepthink, false, false, 20, 0, 0, T_KeenWorld, NULL, R_Draw, &s_worldkeenwave4};\r
-statetype s_worldkeenwave4 = {WORLDKEENWAVE2SPR, WORLDKEENWAVE2SPR, stepthink, false, false, 20, 0, 0, T_KeenWorld, NULL, R_Draw, &s_worldkeenwave5};\r
-statetype s_worldkeenwave5 = {WORLDKEENWAVE1SPR, WORLDKEENWAVE1SPR, stepthink, false, false, 20, 0, 0, T_KeenWorldWalk, NULL, R_Draw, &s_worldkeen};\r
-\r
-statetype s_worldkeenwalk = {0, 0, slide, true, false, 4, 24, 24, T_KeenWorldWalk, NULL, R_Draw, &s_worldkeenwalk};\r
-\r
-Sint16 worldshapes[8] = {WORLDKEENU1SPR-1, WORLDKEENUR1SPR-1, WORLDKEENR1SPR-1, WORLDKEENDR1SPR-1, WORLDKEEND1SPR-1, WORLDKEENDL1SPR-1, WORLDKEENL1SPR-1, WORLDKEENUL1SPR-1}; //-1 to everything because worldanims values are 1-based\r
-Sint16 worldanims[4] = {2, 3, 1, 3};\r
-#ifdef KEEN4\r
-Sint16 swimshapes[8] = {WORLDKEENSWIMU1SPR, WORLDKEENSWIMUR1SPR, WORLDKEENSWIMR1SPR, WORLDKEENSWIMDR1SPR, WORLDKEENSWIMD1SPR, WORLDKEENSWIMDL1SPR, WORLDKEENSWIML1SPR, WORLDKEENSWIMUL1SPR};\r
-#endif\r
-#ifndef KEEN6\r
-Sint16 tiledir[4] = {dir_South, dir_West, dir_North, dir_East};\r
-#endif\r
-\r
-/*\r
-======================\r
-=\r
-= SpawnWorldKeen\r
-=\r
-======================\r
-*/\r
-\r
-void SpawnWorldKeen(Sint16 x, Sint16 y)\r
-{\r
-#ifdef KEEN4\r
- if (playstate == ex_foot)\r
- {\r
- player->needtoclip = cl_noclip;\r
- player->obclass = keenobj;\r
- player->x = gamestate.worldx;\r
- player->y = gamestate.worldy;\r
- player->active = ac_allways;\r
- player->priority = 3;\r
- player->xdir = 0;\r
- player->ydir = 0;\r
- if (gamestate.worldx < 20*TILEGLOBAL)\r
- {\r
- player->temp1 = 280;\r
- player->xspeed = (30*TILEGLOBAL - player->x)/280 + 1;\r
- player->yspeed = (55*TILEGLOBAL - player->y)/280 + 1;\r
- }\r
- else\r
- {\r
- player->temp1 = 140;\r
- player->xspeed = (Sint16)(16*TILEGLOBAL - player->x)/140 + 1;\r
- player->yspeed = (Sint16)(47*TILEGLOBAL - player->y)/140 + 1;\r
- }\r
- NewState(player, &s_keenonfoot1);\r
- return;\r
- }\r
-#endif\r
-\r
- player->obclass = keenobj;\r
- if (gamestate.worldx == 0)\r
- {\r
- player->x = CONVERT_TILE_TO_GLOBAL(x);\r
- player->y = CONVERT_TILE_TO_GLOBAL(y);\r
- }\r
- else\r
- {\r
- player->x = gamestate.worldx;\r
- player->y = gamestate.worldy;\r
- }\r
- player->active = ac_allways;\r
- player->priority = 1;\r
- player->xdir = 0;\r
- player->ydir = 0;\r
- player->temp1 = dir_West;\r
- player->temp2 = 3;\r
- player->temp3 = 0;\r
- player->shapenum = WORLDKEENL3SPR;\r
- NewState(player, &s_worldkeen);\r
-}\r
-\r
-#ifdef KEEN5\r
-/*\r
-======================\r
-=\r
-= SpawnWorldKeenPort\r
-=\r
-======================\r
-*/\r
-\r
-void SpawnWorldKeenPort(Uint16 tileX, Uint16 tileY)\r
-{\r
- player->obclass = keenobj;\r
- player->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- player->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- player->active = ac_allways;\r
- player->priority = 1;\r
- player->xdir = 0;\r
- player->ydir = 0;\r
- player->temp1 = dir_West;\r
- player->temp2 = 3;\r
- player->temp3 = 0;\r
- player->shapenum = WORLDKEENL3SPR;\r
- NewState(player, &s_worldkeen);\r
-}\r
-#endif\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CheckEnterLevel\r
-=\r
-======================\r
-*/\r
-\r
-void CheckEnterLevel(objtype *ob)\r
-{\r
- Uint16 x, y, info;\r
-\r
- for (y = ob->tiletop; y <= ob->tilebottom; y++)\r
- {\r
- for (x = ob->tileleft; x <= ob->tileright; x++)\r
- {\r
- info = *(mapsegs[2]+mapbwidthtable[y]/2 + x);\r
- if (info > 0xC000 && info <= (0xC000 + 18))\r
- {\r
- gamestate.worldx = ob->x;\r
- gamestate.worldy = ob->y;\r
- gamestate.mapon = info - 0xC000;\r
- playstate = ex_completed;\r
- SD_PlaySound(SND_ENTERLEVEL);\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= T_KeenWorld\r
-=\r
-======================\r
-*/\r
-\r
-void T_KeenWorld(objtype *ob)\r
-{\r
- if (c.dir != dir_None)\r
- {\r
- ob->state = &s_worldkeenwalk;\r
- ob->temp2 = 0;\r
- T_KeenWorldWalk(ob);\r
- }\r
- if (jumpbutton || pogobutton || firebutton)\r
- {\r
- CheckEnterLevel(ob);\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= T_KeenWorldWalk\r
-=\r
-======================\r
-*/\r
-\r
-void T_KeenWorldWalk(objtype *ob)\r
-{\r
- if (ob->temp3)\r
- {\r
- ob->temp3 -= 4;\r
- if (ob->temp3 < 0)\r
- ob->temp3 = 0;\r
- }\r
- else\r
- {\r
- ob->xdir = c.xaxis;\r
- ob->ydir = c.yaxis;\r
- if (pogobutton || firebutton || jumpbutton)\r
- {\r
- CheckEnterLevel(ob);\r
- }\r
- if (c.dir == dir_None)\r
- {\r
- ob->state = &s_worldkeen;\r
- ob->shapenum = worldshapes[ob->temp1] + 3;\r
- return;\r
- }\r
- ob->temp1 = c.dir;\r
- }\r
- if (++ob->temp2 == 4)\r
- ob->temp2 = 0;\r
- ob->shapenum = worldshapes[ob->temp1] + worldanims[ob->temp2];\r
-\r
- if (ob->temp2 == 1)\r
- {\r
- SD_PlaySound(SND_WORLDWALK1);\r
- }\r
- else if (ob->temp2 == 3)\r
- {\r
- SD_PlaySound(SND_WORLDWALK2);\r
- }\r
-}\r
-\r
-#ifdef KEEN4\r
-/*\r
-======================\r
-=\r
-= T_FootFly\r
-=\r
-======================\r
-*/\r
-\r
-void T_FootFly(objtype *ob)\r
-{\r
- ob->temp1 = ob->temp1 - tics;\r
- xtry = ob->xspeed * tics;\r
- ytry = ob->yspeed * tics;\r
- if (ob->temp1 <= 0)\r
- {\r
- xtry -= ob->xspeed * -ob->temp1;\r
- ytry -= ob->yspeed * -ob->temp1;\r
- ob->priority = 1;\r
- ob->temp1 = dir_West;\r
- ob->temp2 = 3;\r
- ob->temp3 = 0;\r
- player->xdir = 0;\r
- player->ydir = 0;\r
- ob->state = &s_worldkeen;\r
- ob->shapenum = WORLDKEENL3SPR;\r
- ob->needtoclip = cl_midclip;\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= T_KeenWorldSwim\r
-=\r
-======================\r
-*/\r
-\r
-void T_KeenWorldSwim(objtype *ob)\r
-{\r
- if (ob->temp3)\r
- {\r
- ob->temp3 -= 6;\r
- if (ob->temp3 < 0)\r
- ob->temp3 = 0;\r
- }\r
- else\r
- {\r
- ob->xdir = c.xaxis;\r
- ob->ydir = c.yaxis;\r
- if (c.xaxis || c.yaxis)\r
- ob->temp1 = c.dir;\r
- }\r
- ob->shapenum = swimshapes[ob->temp1] + ob->temp2;\r
- if (++ob->temp2 == 2)\r
- ob->temp2 = 0;\r
-\r
- if (ob->temp2 == 0)\r
- {\r
- SD_PlaySound(SND_SWIM1);\r
- }\r
- else\r
- {\r
- SD_PlaySound(SND_SWIM2);\r
- }\r
-}\r
-\r
-#else // NOT Keen 4 (i.e. Keen 5 & 6):\r
-\r
-/*\r
-======================\r
-=\r
-= Teleport\r
-=\r
-======================\r
-*/\r
-\r
-void Teleport(Uint16 tileX, Uint16 tileY)\r
-{\r
- Uint16 tile, globalx, globaly, duration, move;\r
- objtype *o;\r
- objtype *ob = player;\r
-\r
- //\r
- // enter the teleporter\r
- //\r
- SD_PlaySound(SND_TELEPORT);\r
- globalx = CONVERT_TILE_TO_GLOBAL(tileX);\r
- globaly = CONVERT_TILE_TO_GLOBAL(tileY);\r
-\r
-#ifdef KEEN6Ev15\r
- // We need to make the compiler "forget" that duration starts at 0\r
- // to make sure the while-loop check is performed when entering the\r
- // loop. Can't change compiler settings since we do need that loop\r
- // optimization for the for-loop at the end of this routine.\r
- if (true)\r
- duration = 0;\r
-#else\r
- duration = 0;\r
-#endif\r
-\r
- while (duration < 130)\r
- {\r
- RF_Refresh();\r
- move = tics*2;\r
- duration += tics;\r
-\r
- if (ob->x == globalx && ob->y == globaly)\r
- break;\r
-\r
- if (ob->y < globaly)\r
- {\r
- ob->y += move;\r
- if (ob->y > globaly)\r
- ob->y = globaly;\r
- }\r
- else if (ob->y > globaly)\r
- {\r
- ob->y -= move;\r
- if (ob->y < globaly)\r
- ob->y = globaly;\r
- }\r
-\r
- if (ob->x < globalx)\r
- {\r
- ob->x += move;\r
- if (ob->x > globalx)\r
- ob->x = globalx;\r
- }\r
- else if (ob->x > globalx)\r
- {\r
- ob->x -= move;\r
- if (ob->x < globalx)\r
- ob->x = globalx;\r
- }\r
-\r
- ob->shapenum = ((TimeCount >> 3) % 3) + WORLDKEENU1SPR;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- tile = ((TimeCount >> 2) & TELEPORERTILEMASK) + TELEPORTERTILE1;\r
- RF_MemToMap(&tile, 1, tileX, tileY, 1, 1);\r
- }\r
-\r
- tile = TELEPORTERTILE2;\r
- RF_MemToMap(&tile, 1, tileX, tileY, 1, 1);\r
-\r
- //\r
- // teleport to new location\r
- //\r
- tile = *(mapsegs[2]+mapbwidthtable[tileY]/2 + tileX);\r
- tileX = tile >> 8;\r
- tileY = tile & 0x7F; // BUG? y coordinate is limited to 1..127\r
- ob->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- ob->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- ob->xdir = 0;\r
- ob->ydir = 1;\r
- ob->temp1 = dir_South;\r
- NewState(ob, ob->state);\r
- CenterActor(ob);\r
-\r
- //\r
- // draw flags/signs for new location\r
- //\r
- for (o=player->next; o; o=o->next)\r
- {\r
- if (!o->active && o->obclass == flagobj\r
- && o->tileright >= originxtile-1 && o->tileleft <= originxtilemax+1\r
- && o->tiletop <= originytilemax+1 && o->tilebottom >= originytile-1)\r
- {\r
- o->needtoreact = true;\r
- o->active = ac_yes;\r
- RF_PlaceSprite(&o->sprite, o->x, o->y, o->shapenum, spritedraw, o->priority);\r
- }\r
- }\r
- UpdateScore(scoreobj);\r
- RF_Refresh();\r
- RF_Refresh();\r
-\r
- //\r
- // leave teleporter\r
- //\r
- SD_PlaySound(SND_TELEPORT);\r
-\r
- for (duration = 0; duration < 90; )\r
- {\r
- RF_Refresh();\r
- duration += tics;\r
- ob->y += tics*2 + tics;\r
-\r
- ob->shapenum = ((TimeCount >> 3) % 3) + WORLDKEEND1SPR;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- tile = ((TimeCount >> 2) & TELEPORERTILEMASK) + TELEPORTERTILE3;\r
- RF_MemToMap(&tile, 1, tileX, tileY, 1, 1);\r
- }\r
-\r
- tile = TELEPORTERTILE4;\r
- RF_MemToMap(&tile, 1, tileX, tileY, 1, 1);\r
- xtry = ytry = 0;\r
- ClipToWalls(ob);\r
-}\r
-\r
-#ifdef KEEN5\r
-\r
-/*\r
-======================\r
-=\r
-= T_Elevate\r
-=\r
-======================\r
-*/\r
-\r
-void T_Elevate(objtype *ob)\r
-{\r
- Sint16 i, x, y, tx, ty;\r
- Uint16 tiles[2][2];\r
-\r
- ytry = ob->ydir * 64 * tics;\r
- if (ob->x != ob->temp2)\r
- {\r
- xtry = ob->xdir * 12 * tics;\r
- if ( (ob->xdir == 1 && ob->x + xtry > ob->temp2)\r
- || (ob->xdir == -1 && ob->x + xtry < ob->temp2) )\r
- {\r
- xtry = ob->temp2 - ob->x;\r
- }\r
- }\r
-\r
- //\r
- // Keen has no sprite in this state, so we need to update the hitbox manually\r
- // to avoid issues (the screen scrolling routines use left/right/top/bottom)\r
- //\r
- ob->left = ob->x + xtry;\r
- ob->right = ob->left + (TILEGLOBAL-1);\r
- ob->top = ob->y + ytry;\r
- ob->bottom = ob->top + (TILEGLOBAL-1);\r
-\r
- if (ob->ydir == 1)\r
- {\r
- if (ob->y + ytry < ob->temp1)\r
- return;\r
- }\r
- else\r
- {\r
- if (ob->y + ytry > ob->temp1)\r
- return;\r
- }\r
-\r
- //\r
- // the invisible Keen has arrived at its destination\r
- //\r
- ytry = 0;\r
- xtry = 0;\r
- ob->x = ob->temp2;\r
- ob->y = ob->temp1;\r
- ob->priority = 1;\r
- ob->temp1 = 4;\r
- ob->temp2 = 3;\r
- ob->temp3 = 0;\r
- player->xdir = 0;\r
- player->ydir = 0;\r
- ob->state = &s_worldkeen;\r
- ob->shapenum = WORLDKEEND3SPR;\r
- ob->needtoclip = cl_midclip;\r
- tx = CONVERT_GLOBAL_TO_TILE(ob->x);\r
- ty = CONVERT_GLOBAL_TO_TILE(ob->y);\r
- WorldScrollScreen(ob);\r
- UpdateScore(scoreobj);\r
- RF_Refresh();\r
- RF_Refresh();\r
-\r
- ob->y -= TILEGLOBAL;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- //\r
- // open the elevator door\r
- //\r
- SD_PlaySound(SND_ELEVATORDOOR);\r
- for (i=0; i<=5; i++)\r
- {\r
- for (y=0; y<2; y++)\r
- {\r
- for (x=0; x<2; x++)\r
- {\r
- tiles[y][x] = *(mapsegs[1]+mapbwidthtable[y]/2 + i*2 + x);\r
- }\r
- }\r
- RF_MemToMap(&tiles[0][0], 1, tx, ty-2, 2, 2);\r
- RF_Refresh();\r
- VW_WaitVBL(8);\r
- }\r
-\r
- //\r
- // make Keen walk out of the elevator\r
- //\r
- for (y=0; y<32; y++)\r
- {\r
- ob->y += 8; // move half a pixel every frame for 32 frames -> move down 16 pixels total\r
- ob->shapenum = (y / 4) % 3 + WORLDKEEND1SPR;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- RF_Refresh();\r
- }\r
- ob->needtoclip = cl_midclip; // redundant, but doesn't do any harm\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= Elevator\r
-=\r
-======================\r
-*/\r
-\r
-void Elevator(Uint16 tileX, Uint16 tileY, Sint16 dir)\r
-{\r
- Uint16 info, globalx, globaly, duration, move;\r
- Sint16 x, y, i;\r
- Uint16 tiles[2][2];\r
- objtype *ob = player;\r
-\r
- globalx = CONVERT_TILE_TO_GLOBAL(tileX);\r
- globaly = CONVERT_TILE_TO_GLOBAL(tileY);\r
-\r
- //\r
- // make Keen walk into the elevator\r
- //\r
- for (duration = 0; duration < 130; )\r
- {\r
- CalcBounds(ob);\r
- WorldScrollScreen(ob);\r
- UpdateScore(scoreobj);\r
- RF_Refresh();\r
-\r
- move = tics * 2;\r
- duration += tics;\r
-\r
- if (ob->x == globalx && ob->y == globaly)\r
- break;\r
-\r
- if (ob->y < globaly)\r
- {\r
- ob->y += move;\r
- if (ob->y > globaly)\r
- ob->y = globaly;\r
- }\r
- else if (ob->y > globaly)\r
- {\r
- ob->y -= move;\r
- if (ob->y < globaly)\r
- ob->y = globaly;\r
- }\r
-\r
- if (ob->x < globalx)\r
- {\r
- ob->x += move;\r
- if (ob->x > globalx)\r
- ob->x = globalx;\r
- }\r
- else if (ob->x > globalx)\r
- {\r
- ob->x -= move;\r
- if (ob->x < globalx)\r
- ob->x = globalx;\r
- }\r
-\r
- ob->shapenum = ((duration / 8) % 3) + WORLDKEENU1SPR;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-\r
- //\r
- // close the elevator door\r
- //\r
- SD_PlaySound(SND_ELEVATORDOOR);\r
- for (i=5; i >= 0; i--)\r
- {\r
- for (y=0; y<2; y++)\r
- {\r
- for (x=0; x<2; x++)\r
- {\r
- tiles[y][x] = *(mapsegs[1]+mapbwidthtable[y]/2 + i*2 + x);\r
- }\r
- }\r
- RF_MemToMap(&tiles[0][0], 1, tileX+dir, tileY-1, 2, 2);\r
- RF_Refresh();\r
- VW_WaitVBL(8);\r
- }\r
-\r
- //\r
- // make Keen invisible (and not clipping) and send him to the destination\r
- //\r
- RF_RemoveSprite(&ob->sprite);\r
- info = *(mapsegs[2] + mapbwidthtable[tileY]/2 + tileX);\r
- ob->temp2 = CONVERT_TILE_TO_GLOBAL(info >> 8);\r
- ob->temp1 = CONVERT_TILE_TO_GLOBAL((info & 0x7F) + 1); // BUG? y coordinate is limited to 1..127\r
- if (ob->temp1 < ob->y)\r
- {\r
- ob->ydir = -1;\r
- }\r
- else\r
- {\r
- ob->ydir = 1;\r
- }\r
- if (ob->temp2 < ob->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
- ob->needtoclip = cl_noclip;\r
- ob->state = &s_worldelevate;\r
-}\r
-\r
-#endif //ifdef KEEN5\r
-\r
-#endif //ifdef KEEN4 ... else ...\r
-\r
-/*\r
-======================\r
-=\r
-= CheckWorldInTiles\r
-=\r
-======================\r
-*/\r
-\r
-void CheckWorldInTiles(objtype *ob)\r
-{\r
- Uint16 tx, ty, intile;\r
-\r
- if (ob->temp3)\r
- return;\r
-\r
- tx = ob->tilemidx;\r
- ty = CONVERT_GLOBAL_TO_TILE(ob->top + (ob->bottom-ob->top)/2);\r
- intile = tinf[INTILE + *(mapsegs[1]+mapbwidthtable[ty]/2+tx)];\r
-#if defined KEEN4\r
- if (intile == INTILE_SHORESOUTH || intile == INTILE_SHORENORTH\r
- || intile == INTILE_SHOREEAST || intile == INTILE_SHOREWEST)\r
- {\r
- if (!gamestate.wetsuit)\r
- {\r
- SD_PlaySound(SND_NOWAY);\r
- CantSwim();\r
- RF_ForceRefresh();\r
- xtry = -ob->xmove;\r
- ytry = -ob->ymove;\r
- ob->xdir = ob->ydir = 0;\r
- ClipToWalls(ob);\r
- }\r
- else\r
- {\r
- ob->temp1 = tiledir[intile-INTILE_SHORESOUTH];\r
- if (ob->state == &s_worldswim)\r
- {\r
- ob->temp1 = opposite[ob->temp1];\r
- }\r
- switch (ob->temp1)\r
- {\r
- case dir_North:\r
- ob->xdir = 0;\r
- ob->ydir = -1;\r
- break;\r
- case dir_East:\r
- ob->xdir = 1;\r
- ob->ydir = 0;\r
- break;\r
- case dir_South:\r
- ob->xdir = 0;\r
- ob->ydir = 1;\r
- break;\r
- case dir_West:\r
- ob->xdir = -1;\r
- ob->ydir = 0;\r
- break;\r
- }\r
- ob->temp2 = 0;\r
- ob->temp3 = 18;\r
- if (ob->state == &s_worldswim)\r
- {\r
- ChangeState(ob, &s_worldkeenwalk);\r
- }\r
- else\r
- {\r
- ChangeState(ob, &s_worldswim);\r
- }\r
- }\r
- }\r
-#elif defined KEEN5\r
- switch (intile)\r
- {\r
- case INTILE_TELEPORT:\r
- Teleport(tx, ty);\r
- break;\r
- case INTILE_ELEVATORLEFT:\r
- Elevator(tx, ty, 0);\r
- break;\r
- case INTILE_ELEVATORRIGHT:\r
- Elevator(tx, ty, -1);\r
- break;\r
- }\r
-#elif defined KEEN6\r
- switch (intile)\r
- {\r
- case INTILE_TELEPORT:\r
- Teleport(tx, ty);\r
- break;\r
- }\r
-#endif\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- FLAGS\r
-\r
-temp1 = x destination for the thrown flag\r
-temp2 = y destination for the thrown flag\r
-temp3 = amount of time passed since flag was thrown (in tics)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_flagwave1 = {FLAGFLAP1SPR, FLAGFLAP1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_flagwave2};\r
-statetype s_flagwave2 = {FLAGFLAP2SPR, FLAGFLAP2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_flagwave3};\r
-statetype s_flagwave3 = {FLAGFLAP3SPR, FLAGFLAP3SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_flagwave4};\r
-statetype s_flagwave4 = {FLAGFLAP4SPR, FLAGFLAP4SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_flagwave1};\r
-\r
-#ifndef KEEN5\r
-statetype s_throwflag0 = {FLAGFLIP1SPR, FLAGFLIP1SPR, think, false, false, 6, 0, 0, TossThink, NULL, R_Draw, &s_throwflag1};\r
-statetype s_throwflag1 = {FLAGFLIP1SPR, FLAGFLIP1SPR, stepthink, false, false, 12, 0, 0, PathThink, NULL, R_Draw, &s_throwflag2};\r
-statetype s_throwflag2 = {FLAGFLIP2SPR, FLAGFLIP2SPR, stepthink, false, false, 12, 0, 0, PathThink, NULL, R_Draw, &s_throwflag3};\r
-statetype s_throwflag3 = {FLAGFLIP3SPR, FLAGFLIP3SPR, stepthink, false, false, 12, 0, 0, PathThink, NULL, R_Draw, &s_throwflag4};\r
-statetype s_throwflag4 = {FLAGFLIP4SPR, FLAGFLIP4SPR, stepthink, false, false, 12, 0, 0, PathThink, NULL, R_Draw, &s_throwflag5};\r
-statetype s_throwflag5 = {FLAGFALL1SPR, FLAGFALL1SPR, stepthink, false, false, 12, 0, 0, PathThink, NULL, R_Draw, &s_throwflag6};\r
-statetype s_throwflag6 = {FLAGFALL1SPR, FLAGFALL1SPR, stepthink, true, false, 1, 0, 0, FlagAlign, NULL, R_Draw, &s_flagwave1};\r
-#endif\r
-\r
-Sint16 flagx, flagy;\r
-Point flagpath[30];\r
-\r
-/*\r
-======================\r
-=\r
-= SpawnFlag\r
-=\r
-======================\r
-*/\r
-\r
-void SpawnFlag(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 3;\r
- new->obclass = flagobj;\r
- new->active = ac_yes;\r
-#if defined KEEN4\r
- new->x = CONVERT_TILE_TO_GLOBAL(x) + 6*PIXGLOBAL;\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -30*PIXGLOBAL;\r
-#elif defined KEEN5\r
- new->x = CONVERT_TILE_TO_GLOBAL(x) + -5*PIXGLOBAL;\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -30*PIXGLOBAL;\r
-#elif defined KEEN6\r
- new->x = CONVERT_TILE_TO_GLOBAL(x) + 6*PIXGLOBAL; // useless!\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -30*PIXGLOBAL; // useless!\r
-#if GRMODE == CGAGR\r
- new->x = CONVERT_TILE_TO_GLOBAL(x) + 10*PIXGLOBAL;\r
-#else\r
- new->x = CONVERT_TILE_TO_GLOBAL(x) + 14*PIXGLOBAL;\r
-#endif\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -26*PIXGLOBAL;\r
- {\r
- Uint16 tile = *(mapsegs[1]+mapbwidthtable[y]/2 + x) + 1;\r
- RF_MemToMap(&tile, 1, x, y, 1, 1);\r
- }\r
-#endif\r
- new->ticcount = US_RndT() / 16;\r
- NewState(new, &s_flagwave1);\r
-}\r
-\r
-#ifndef KEEN5\r
-/*\r
-======================\r
-=\r
-= SpawnThrowFlag\r
-=\r
-======================\r
-*/\r
-\r
-void SpawnThrowFlag(Sint16 x, Sint16 y)\r
-{\r
- Sint16 i;\r
- Sint32 xdist, ydist;\r
-\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 3;\r
- new->obclass = flagobj;\r
- new->active = ac_allways;\r
- new->x = gamestate.worldx - 16*PIXGLOBAL;\r
- new->y = gamestate.worldy - 16*PIXGLOBAL;\r
-#if defined KEEN4\r
- new->temp1 = CONVERT_TILE_TO_GLOBAL(x) + 6*PIXGLOBAL;\r
- new->temp2 = CONVERT_TILE_TO_GLOBAL(y) + -38*PIXGLOBAL;\r
-#elif defined KEEN6\r
- flagx = x;\r
- flagy = y;\r
-#if GRMODE == CGAGR\r
- new->temp1 = CONVERT_TILE_TO_GLOBAL(x) + 10*PIXGLOBAL;\r
-#else\r
- new->temp1 = CONVERT_TILE_TO_GLOBAL(x) + 14*PIXGLOBAL;\r
-#endif\r
- new->temp2 = CONVERT_TILE_TO_GLOBAL(y) + -34*PIXGLOBAL;\r
-#endif\r
- xdist = (Sint32)new->temp1 - (Sint32)new->x;\r
- ydist = (Sint32)new->temp2 - (Sint32)new->y;\r
- for (i = 0; i < 30; i++)\r
- {\r
- flagpath[i].x = new->x + (xdist * min(i, 24))/24;\r
- flagpath[i].y = new->y + (ydist * i)/30;\r
- if (i < 10)\r
- {\r
- flagpath[i].y -= i*3*PIXGLOBAL;\r
- }\r
- else if (i < 15)\r
- {\r
- flagpath[i].y -= i*PIXGLOBAL + 20*PIXGLOBAL;\r
- }\r
- else if (i < 20)\r
- {\r
- flagpath[i].y -= (20-i)*PIXGLOBAL + 30*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- flagpath[i].y -= (29-i)*3*PIXGLOBAL;\r
- }\r
- }\r
- NewState(new, &s_throwflag0);\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= TossThink\r
-=\r
-======================\r
-*/\r
-\r
-void TossThink(objtype *ob)\r
-{\r
- if (screenfaded)\r
- return;\r
-\r
- SD_StopSound();\r
- SD_PlaySound(SND_FLAGSPIN);\r
- ob->state = ob->state->nextstate;\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= PathThink\r
-=\r
-======================\r
-*/\r
-\r
-void PathThink(objtype *ob)\r
-{\r
- ob->temp3 = ob->temp3 + tics;\r
- if (ob->temp3 > 58)\r
- ob->temp3 = 58;\r
-\r
- ob->x = flagpath[ob->temp3/2].x;\r
- ob->y = flagpath[ob->temp3/2].y;\r
- ob->needtoreact = true;\r
- if (ob->temp1 == 0)\r
- {\r
- SD_PlaySound(SND_FLAGSPIN);\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= FlagAlign\r
-=\r
-======================\r
-*/\r
-\r
-void FlagAlign(objtype *ob)\r
-{\r
- ob->x = ob->temp1;\r
- ob->y = ob->temp2 + 8*PIXGLOBAL;\r
- SD_PlaySound(SND_FLAGLAND);\r
-#ifdef KEEN6\r
- {\r
- Uint16 tile = *(mapsegs[1]+mapbwidthtable[flagy]/2 + flagx) + 1;\r
- RF_MemToMap(&tile, 1, flagx, flagy, 1, 1);\r
- }\r
-#endif\r
-}\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- NEURAL STUNNER\r
-\r
-=============================================================================\r
-*/\r
-statetype s_stunray1 = {STUN1SPR, STUN1SPR, slide, false, false, 6, 64, 64, T_Shot, NULL, R_Shot, &s_stunray2};\r
-statetype s_stunray2 = {STUN2SPR, STUN2SPR, slide, false, false, 6, 64, 64, T_Shot, NULL, R_Shot, &s_stunray3};\r
-statetype s_stunray3 = {STUN3SPR, STUN3SPR, slide, false, false, 6, 64, 64, T_Shot, NULL, R_Shot, &s_stunray4};\r
-statetype s_stunray4 = {STUN4SPR, STUN4SPR, slide, false, false, 6, 64, 64, T_Shot, NULL, R_Shot, &s_stunray1};\r
-\r
-statetype s_stunhit = {STUNHIT1SPR, STUNHIT1SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_stunhit2};\r
-statetype s_stunhit2 = {STUNHIT2SPR, STUNHIT2SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-======================\r
-=\r
-= SpawnShot\r
-=\r
-======================\r
-*/\r
-\r
-void SpawnShot(Uint16 x, Uint16 y, Direction dir)\r
-{\r
- if (!gamestate.ammo)\r
- {\r
- SD_PlaySound(SND_USESWITCH);\r
- return;\r
- }\r
-\r
- gamestate.ammo--;\r
- GetNewObj(true);\r
- new->x = x;\r
- new->y = y;\r
- new->priority = 0;\r
- new->obclass = stunshotobj;\r
- new->active = ac_allways;\r
- SD_PlaySound(SND_KEENFIRE);\r
- switch (dir)\r
- {\r
- case dir_North:\r
- new->xdir = 0;\r
- new->ydir = -1;\r
- break;\r
- case dir_East:\r
- new->xdir = 1;\r
- new->ydir = 0;\r
- break;\r
- case dir_South:\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- break;\r
- case dir_West:\r
- new->xdir = -1;\r
- new->ydir = 0;\r
- break;\r
- default:\r
- Quit("SpawnShot: Bad dir!");\r
- break;\r
- }\r
- NewState(new, &s_stunray1);\r
-\r
-#ifdef KEEN6\r
- {\r
- objtype *ob;\r
-\r
- for (ob=player->next; ob; ob=ob->next)\r
- {\r
- if (ob->active\r
- && new->right > ob->left && new->left < ob->right\r
- && new->top < ob->bottom && new->bottom > ob->top\r
- && ob->state->contact)\r
- {\r
- ob->state->contact(ob, new);\r
- return;\r
- }\r
- }\r
- }\r
-#endif\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= ExplodeShot\r
-=\r
-======================\r
-*/\r
-\r
-void ExplodeShot(objtype *ob)\r
-{\r
- ob->obclass = inertobj;\r
- ChangeState(ob, &s_stunhit);\r
- SD_PlaySound(SND_SHOTEXPLODE);\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= T_Shot\r
-=\r
-======================\r
-*/\r
-\r
-void T_Shot(objtype *ob)\r
-{\r
- objtype *ob2;\r
-\r
- if (ob->tileright >= originxtile && ob->tilebottom >= originytile\r
- && ob->tileleft <= originxtilemax && ob->tiletop <= originytilemax)\r
- {\r
- //object is visible, so do nothing\r
- return;\r
- }\r
-\r
- if (ob->tileright+10 < originxtile\r
- || ob->tileleft-10 > originxtilemax\r
- || ob->tilebottom+6 < originytile\r
- || ob->tiletop-6 > originytilemax)\r
- {\r
- //shot is off-screen by more than half a screen, so remove it\r
- RemoveObj(ob);\r
- return;\r
- }\r
-\r
- //check for collisions with INACTIVE objects\r
- for (ob2 = player->next; ob2; ob2 = ob2->next)\r
- {\r
- if (!ob2->active && ob->right > ob2->left && ob->left < ob2->right\r
- && ob->top < ob2->bottom && ob->bottom > ob2->top)\r
- {\r
- if (ob2->state->contact)\r
- {\r
- ob2->state->contact(ob2, ob);\r
- ob2->needtoreact = true;\r
- ob2->active = ac_yes;\r
- }\r
-\r
- if (ob->obclass == nothing) //BUG: obclass is 'inertobj' for the exploded shot\r
- break;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= R_Shot\r
-=\r
-======================\r
-*/\r
-\r
-void R_Shot(objtype *ob)\r
-{\r
- Uint16 tile;\r
-\r
- if (ob->hitnorth == 1 && ob->tileleft != ob->tileright)\r
- {\r
- tile = *(mapsegs[1]+mapbwidthtable[ob->tiletop-1]/2+ob->tileright);\r
- if (tinf[NORTHWALL+tile] == 17)\r
- {\r
- ob->hitnorth = 17;\r
- ob->x += 0x100 - (ob->x & 0xFF);\r
- }\r
- }\r
- else if (ob->hitnorth == 17 && ob->tileleft != ob->tileright)\r
- {\r
- ob->x &= 0xFF00;\r
- }\r
- if (ob->hitsouth == 1 && ob->tileleft != ob->tileright)\r
- {\r
- tile = *(mapsegs[1]+mapbwidthtable[ob->tilebottom+1]/2+ob->tileright);\r
- if (tinf[SOUTHWALL+tile] == 17)\r
- {\r
- ob->hitsouth = 17;\r
- ob->x += 0x100 - (ob->x & 0xFF);\r
- }\r
- }\r
- else if (ob->hitsouth == 17 && ob->tileleft != ob->tileright)\r
- {\r
- ob->x &= 0xFF00;\r
- }\r
- if (ob->hitnorth == 17 || ob->hitsouth == 17)\r
- {\r
- ytry = ob->state->ymove * tics * ob->ydir;\r
- ob->y += ytry;\r
- ob->top += ytry;\r
- ob->bottom += ytry;\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- }\r
- else if (ob->hitnorth || ob->hitsouth || ob->hiteast || ob->hitwest)\r
- {\r
- ExplodeShot(ob);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- DOOR\r
-\r
-temp1 = height of the door's main section (identical tiles!), in tiles\r
- DoorOpen changes two more tiles at the bottom end of the door\r
- (total door height in tiles is temp1 + 2)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_door1 = {0, 0, step, false, false, 10, 0, 0, DoorOpen, NULL, NULL, &s_door2};\r
-statetype s_door2 = {0, 0, step, false, false, 10, 0, 0, DoorOpen, NULL, NULL, &s_door3};\r
-statetype s_door3 = {0, 0, step, false, false, 10, 0, 0, DoorOpen, NULL, NULL, NULL};\r
-\r
-/*\r
-======================\r
-=\r
-= DoorOpen\r
-=\r
-======================\r
-*/\r
-\r
-void DoorOpen(objtype *ob)\r
-{\r
- Sint16 i;\r
- Uint16 far *map;\r
- Uint16 tiles[50];\r
-\r
- map = mapsegs[1] + mapbwidthtable[ob->y]/2 + ob->x;\r
- for (i=0; i < ob->temp1+2; i++, map+=mapwidth)\r
- {\r
- tiles[i] = *map + 1;\r
- }\r
- RF_MemToMap(tiles, 1, ob->x, ob->y, 1, ob->temp1+2);\r
-}\r
-\r
-#ifdef KEEN5\r
-/*\r
-=============================================================================\r
-\r
- CARD DOOR\r
-\r
-temp1 = frame counter\r
-\r
-=============================================================================\r
-*/\r
-statetype s_carddoor = {0, 0, step, false, false, 15, 0, 0, CardDoorOpen, NULL, NULL, &s_carddoor};\r
-\r
-/*\r
-======================\r
-=\r
-= CardDoorOpen\r
-=\r
-======================\r
-*/\r
-\r
-void CardDoorOpen(objtype *ob)\r
-{\r
- Sint16 x, y;\r
- Uint16 far *map;\r
- Uint16 tiles[16], *tileptr;\r
-\r
- tileptr = tiles;\r
- map = mapsegs[1] + mapbwidthtable[ob->y]/2 + ob->x;\r
- for (y=0; y<4; y++, map+=mapwidth)\r
- {\r
- for (x=0; x<4; x++)\r
- {\r
- *tileptr++ = map[x]-4;\r
- }\r
- }\r
- RF_MemToMap(tiles, 1, ob->x, ob->y, 4, 4);\r
-\r
- if (++ob->temp1 == 3)\r
- ob->state = NULL;\r
-}\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// CK_MAIN.C\r
-/*\r
-=============================================================================\r
-\r
- COMMANDER KEEN\r
-\r
- An Id Software production\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean tedlevel;\r
-Uint16 tedlevelnum;\r
-\r
-char str[80], str2[20];\r
-boolean storedemo, jerk;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= SizeText\r
-=\r
-= Calculates width and height of a string that contains line breaks\r
-= (Note: only the height is ever used, width is NOT calculated correctly)\r
-=\r
-=====================\r
-*/\r
-\r
-void SizeText(char *text, Uint16 *width, Uint16 *height)\r
-{\r
- register char *ptr;\r
- char c;\r
- Uint16 w, h;\r
- char strbuf[80];\r
-\r
- *width = *height = 0;\r
- ptr = &strbuf[0];\r
- while ((c=*(text++)) != '\0')\r
- {\r
- *(ptr++) = c;\r
- if (c == '\n' || !*text)\r
- {\r
- USL_MeasureString(strbuf, &w, &h); // BUG: strbuf may not have a terminating '\0' at the end!\r
- *height += h;\r
- if (*width < w)\r
- {\r
- *width = w;\r
- }\r
- ptr = &strbuf[0];\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= ShutdownId\r
-=\r
-= Shuts down all ID_?? managers\r
-=\r
-==========================\r
-*/\r
-\r
-void ShutdownId(void)\r
-{\r
- US_Shutdown();\r
- SD_Shutdown();\r
- IN_Shutdown();\r
- RF_Shutdown();\r
- VW_Shutdown();\r
- CA_Shutdown();\r
- MM_Shutdown();\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= InitGame\r
-=\r
-= Load a few things right away\r
-=\r
-==========================\r
-*/\r
-\r
-void InitGame(void)\r
-{\r
- static char *ParmStrings[] = {"JERK", ""};\r
- void MML_UseSpace (Uint16 segstart, Uint16 seglength);\r
-\r
- Uint16 segstart,seglength;\r
- Sint16 i;\r
-\r
- // Note: The value of the jerk variable is replaced with the value\r
- // read from the config file during US_Startup, which means the\r
- // JERK parameter has absolutely no effect if a valid config file\r
- // exists. The parameter check should be moved to some place after\r
- // US_Startup to make it work reliably.\r
- \r
- for (i=1; i < _argc; i++)\r
- {\r
- if (US_CheckParm(_argv[i], ParmStrings) == 0)\r
- {\r
- jerk = true;\r
- }\r
- }\r
-\r
- US_TextScreen();\r
-\r
- MM_Startup();\r
- VW_Startup();\r
- RF_Startup();\r
- IN_Startup();\r
- SD_Startup();\r
- US_Startup();\r
-\r
- US_UpdateTextScreen();\r
-\r
- CA_Startup();\r
- US_Setup();\r
-\r
- US_SetLoadSaveHooks(&LoadTheGame, &SaveTheGame, &ResetGame);\r
- drawcachebox = DialogDraw;\r
- updatecachebox = DialogUpdate;\r
- finishcachebox = DialogFinish;\r
-\r
-//\r
-// load in and lock down some basic chunks\r
-//\r
-\r
- CA_ClearMarks();\r
-\r
- CA_MarkGrChunk(STARTFONT);\r
- CA_MarkGrChunk(STARTTILE8);\r
- CA_MarkGrChunk(STARTTILE8M);\r
-#if GRMODE == EGAGR\r
- CA_MarkGrChunk(CORDPICM);\r
- CA_MarkGrChunk(METALPOLEPICM);\r
-#endif\r
-\r
- CA_CacheMarks(NULL);\r
-\r
- MM_SetLock(&grsegs[STARTFONT], true);\r
- MM_SetLock(&grsegs[STARTTILE8], true);\r
- MM_SetLock(&grsegs[STARTTILE8M], true);\r
-#if GRMODE == EGAGR\r
- MM_SetLock(&grsegs[CORDPICM], true);\r
- MM_SetLock(&grsegs[METALPOLEPICM], true);\r
-#endif\r
-\r
- fontcolor = WHITE;\r
-\r
- US_FinishTextScreen();\r
-\r
-//\r
-// reclaim the memory from the linked in text screen\r
-//\r
- segstart = FP_SEG(&introscn);\r
- seglength = 4000/16;\r
- if (FP_OFF(&introscn))\r
- {\r
- segstart++;\r
- seglength--;\r
- }\r
- MML_UseSpace (segstart,seglength);\r
-\r
- VW_SetScreenMode(GRMODE);\r
-#if GRMODE == CGAGR\r
- VW_ColorBorder(BROWN);\r
-#else\r
- VW_ColorBorder(CYAN);\r
-#endif\r
- VW_ClearVideo(BLACK);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= Quit\r
-=\r
-==========================\r
-*/\r
-\r
-void Quit(char *error)\r
-{\r
- Uint16 finscreen;\r
-\r
- if (!error)\r
- {\r
- CA_SetAllPurge();\r
- CA_CacheGrChunk(ORDERSCREEN);\r
- finscreen = (Uint16)grsegs[ORDERSCREEN];\r
- }\r
-\r
- // BUG: VW_ClearVideo may brick the system if screenseg is 0\r
- // (i.e. VW_SetScreenMode has not been executed) - this may\r
- // happen if the code runs into an error during InitGame\r
- // (EMS/XMS errors, files not found etc.)\r
- VW_ClearVideo(BLACK);\r
- VW_SetLineWidth(40);\r
-\r
- ShutdownId();\r
- if (error && *error)\r
- {\r
- puts(error);\r
- if (tedlevel)\r
- {\r
- getch();\r
- execlp("TED5.EXE", "TED5.EXE", "/LAUNCH", NULL);\r
- }\r
- else if (US_ParmPresent("windows"))\r
- {\r
- bioskey(0);\r
- }\r
- exit(1);\r
- }\r
-\r
- if (!NoWait)\r
- {\r
- movedata(finscreen, 7, 0xB800, 0, 4000);\r
- gotoxy(1, 24);\r
- if (US_ParmPresent("windows"))\r
- {\r
- bioskey(0);\r
- }\r
- }\r
-\r
- exit(0);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= TEDDeath\r
-=\r
-==================\r
-*/\r
-\r
-void TEDDeath(void)\r
-{\r
- ShutdownId();\r
- execlp("TED5.EXE", "TED5.EXE", "/LAUNCH", NULL);\r
- // BUG: should call exit(1); here in case starting TED5 fails\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= CheckMemory\r
-=\r
-==================\r
-*/\r
-\r
-void CheckMemory(void)\r
-{\r
- Uint16 finscreen;\r
-\r
- if (mminfo.nearheap+mminfo.farheap+mminfo.EMSmem+mminfo.XMSmem >= MINMEMORY)\r
- return;\r
-\r
- CA_CacheGrChunk (OUTOFMEM);\r
- finscreen = (Uint16)grsegs[OUTOFMEM];\r
- ShutdownId();\r
- movedata (finscreen,7,0xb800,0,4000);\r
- gotoxy (1,24);\r
- exit(1);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= DemoLoop\r
-=\r
-=====================\r
-*/\r
-\r
-void DemoLoop(void)\r
-{\r
- static char *ParmStrings[] = {"easy", "normal", "hard", ""};\r
-\r
- register Sint16 i, state;\r
- Sint16 level;\r
-\r
-//\r
-// check for launch from ted\r
-//\r
- if (tedlevel)\r
- {\r
- NewGame();\r
- CA_LoadAllSounds();\r
- gamestate.mapon = tedlevelnum;\r
- restartgame = gd_Normal;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- if ( (level = US_CheckParm(_argv[i],ParmStrings)) == -1)\r
- continue;\r
-\r
- restartgame = level+gd_Easy;\r
- break;\r
- }\r
- GameLoop();\r
- TEDDeath();\r
- }\r
-\r
-//\r
-// demo loop\r
-//\r
- state = 0;\r
- playstate = ex_stillplaying;\r
- while (1)\r
- {\r
- switch (state++)\r
- {\r
- case 0:\r
-#if GRMODE == CGAGR\r
- ShowTitle();\r
-#else\r
- if (nopan)\r
- {\r
- ShowTitle();\r
- }\r
- else\r
- {\r
- Terminator();\r
- }\r
-#endif\r
- break;\r
-\r
- case 1:\r
- RunDemo(0);\r
- break;\r
-\r
- case 2:\r
-#if GRMODE == CGAGR\r
- ShowCredits();\r
-#else\r
- StarWars();\r
-#endif\r
- break;\r
-\r
- case 3:\r
- RunDemo(1);\r
- break;\r
-\r
- case 4:\r
- ShowHighScores();\r
- break;\r
-\r
- case 5:\r
- RunDemo(2);\r
- break;\r
-\r
- case 6:\r
- state = 0;\r
- RunDemo(3);\r
- break;\r
- }\r
-\r
- while (playstate == ex_resetgame || playstate == ex_loadedgame)\r
- {\r
- GameLoop();\r
- ShowHighScores();\r
- if (playstate == ex_resetgame || playstate == ex_loadedgame)\r
- {\r
- continue; // don't show title screen, go directly to GameLoop();\r
- }\r
- ShowTitle();\r
- ///////////////\r
- // this is completely useless:\r
- if (playstate == ex_resetgame || playstate == ex_loadedgame)\r
- {\r
- continue;\r
- }\r
- ///////////////\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if (GRMODE == EGAGR) && !(defined KEEN6)\r
-/*\r
-=====================\r
-=\r
-= CheckCutFile\r
-=\r
-=====================\r
-*/\r
-\r
-#define FILE_GR1 GREXT"1."EXTENSION\r
-#define FILE_GR2 GREXT"2."EXTENSION\r
-#define FILE_GRAPH GREXT"GRAPH."EXTENSION\r
-\r
-static void CheckCutFile(void)\r
-{\r
- register Sint16 ohandle, ihandle;\r
- Sint16 handle;\r
- Sint32 size;\r
- void far *buffer;\r
-\r
- if ( (handle = open(FILE_GRAPH, O_BINARY|O_RDONLY)) != -1)\r
- {\r
- close(handle);\r
- return;\r
- }\r
- puts("Combining "FILE_GR1" and "FILE_GR2" into "FILE_GRAPH"...");\r
- if (rename(FILE_GR1, FILE_GRAPH) == -1)\r
- {\r
- puts("Can't rename "FILE_GR1"!");\r
- exit(1);\r
- }\r
- if ( (ohandle = open(FILE_GRAPH, O_BINARY|O_APPEND|O_WRONLY)) == -1)\r
- {\r
- puts("Can't open "FILE_GRAPH"!");\r
- exit(1);\r
- }\r
- lseek(ohandle, 0, SEEK_END);\r
- if ( (ihandle = open(FILE_GR2, O_BINARY|O_RDONLY)) == -1)\r
- {\r
- puts("Can't find "FILE_GR2"!");\r
- exit(1);\r
- }\r
- size = filelength(ihandle);\r
- buffer = farmalloc(32000);\r
- while (size)\r
- {\r
- if (size > 32000)\r
- {\r
- CA_FarRead(ihandle, buffer, 32000);\r
- CA_FarWrite(ohandle, buffer, 32000);\r
- size -= 32000;\r
- }\r
- else\r
- {\r
- CA_FarRead(ihandle, buffer, size);\r
- CA_FarWrite(ohandle, buffer, size);\r
- size = 0;\r
- }\r
- }\r
- farfree(buffer);\r
- close(ohandle);\r
- close(ihandle);\r
- unlink(FILE_GR2);\r
-}\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= main\r
-=\r
-==========================\r
-*/\r
-\r
-void main(void)\r
-{\r
-#if (GRMODE == EGAGR) && !(defined KEEN6)\r
- CheckCutFile();\r
-#endif\r
-\r
- if (US_ParmPresent("DEMO"))\r
- storedemo = true;\r
-\r
- if (US_ParmPresent("JOYPAD"))\r
- joypad = true; // Note: the joypad variable is never used\r
- \r
- InitGame();\r
- CheckMemory();\r
- if (NoWait || tedlevel)\r
- debugok = true;\r
-\r
- DemoLoop();\r
- Quit("Demo loop exited???");\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-ScanCode firescan = sc_Space;\r
-\r
-boolean singlestep, jumpcheat, godmode, keenkilled;\r
-\r
-exittype playstate;\r
-gametype gamestate;\r
-\r
-objtype *new, *check, *player, *scoreobj;\r
-\r
-Uint16 originxtilemax;\r
-Uint16 originytilemax;\r
-\r
-ControlInfo c;\r
-boolean button2, button3; // never used\r
-\r
-objtype dummyobj;\r
-\r
-Sint16 invincible;\r
-\r
-boolean oldshooting, showscorebox, joypad;\r
-\r
-Sint16 groundslam;\r
-\r
-boolean debugok;\r
-boolean jumpbutton, jumpheld, pogobutton, pogoheld, firebutton, fireheld, upheld;\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-objtype *obj;\r
-\r
-Uint16 centerlevel;\r
-\r
-Uint16 objectcount;\r
-objtype objarray[MAXACTORS];\r
-objtype *lastobj;\r
-objtype *objfreelist;\r
-\r
-Sint16 inactivateleft;\r
-Sint16 inactivateright;\r
-Sint16 inactivatetop;\r
-Sint16 inactivatebottom;\r
-\r
-#ifdef KEEN6Ev15\r
-Uint16 __dummy__; // never used, but must be present to recreate the original EXE\r
-#endif\r
-\r
-Uint16 extravbls;\r
-\r
-Uint16 windowofs;\r
-Sint16 vislines;\r
-boolean scrollup;\r
-\r
-Sint16 oldfirecount;\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= CountObjects\r
-=\r
-==================\r
-*/\r
-\r
-void CountObjects(void)\r
-{\r
- Uint16 activeobjects, inactiveobjects;\r
- objtype *ob;\r
-\r
- activeobjects = inactiveobjects = 0;\r
- for (ob=player; ob; ob=ob->next)\r
- {\r
- if (ob->active)\r
- {\r
- activeobjects++;\r
- }\r
- else\r
- {\r
- inactiveobjects++;\r
- }\r
- }\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(18, 4);\r
- PrintY += 7;\r
- US_Print("Active Objects :");\r
- US_PrintUnsigned(activeobjects);\r
- US_Print("\nInactive Objects:");\r
- US_PrintUnsigned(inactiveobjects);\r
- VW_UpdateScreen();\r
- IN_Ack();\r
-}\r
-\r
-/*\r
-==================\r
-=\r
-= DebugMemory\r
-=\r
-==================\r
-*/\r
-\r
-void DebugMemory(void)\r
-{\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(16, 7);\r
- US_CPrint("Memory Usage");\r
- US_CPrint("------------");\r
- US_Print("Total :");\r
- US_PrintUnsigned((mminfo.mainmem+mminfo.EMSmem+mminfo.XMSmem)/1024);\r
- US_Print("k\nFree :");\r
- US_PrintUnsigned(MM_UnusedMemory()/1024);\r
- US_Print("k\nWith purge:");\r
- US_PrintUnsigned(MM_TotalFree()/1024);\r
- US_Print("k\n");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
-#if GRMODE != CGAGR\r
- MM_ShowMemory();\r
-#endif\r
-}\r
-\r
-/*\r
-===================\r
-=\r
-= TestSprites\r
-=\r
-===================\r
-*/\r
-\r
-void TestSprites(void)\r
-{\r
- Uint16 infox, infoy;\r
- Sint16 chunk, oldchunk;\r
- Sint16 shift;\r
- Uint16 infobottom, drawx;\r
- spritetabletype far *info;\r
- Uint8 _seg *block;\r
- Uint16 size;\r
- Uint16 scan;\r
- Uint32 totalsize;\r
-\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(30, 17);\r
- totalsize = 0;\r
- US_CPrint("Sprite Test");\r
- US_CPrint("-----------");\r
- infoy = PrintY;\r
- infox = (PrintX + 56) & ~7;\r
- drawx = infox + 40;\r
- US_Print("Chunk:\nWidth:\nHeight:\nOrgx:\nOrgy:\nXl:\nYl:\nXh:\nYh:\nShifts:\nMem:\n");\r
- infobottom = PrintY;\r
- chunk = STARTSPRITES;\r
- shift = 0;\r
- while (1)\r
- {\r
- if (chunk >= STARTSPRITES+NUMSPRITES)\r
- {\r
- chunk = STARTSPRITES+NUMSPRITES-1;\r
- }\r
- else if (chunk < STARTSPRITES)\r
- {\r
- chunk = STARTSPRITES;\r
- }\r
- info = &spritetable[chunk-STARTSPRITES];\r
- block = grsegs[chunk];\r
- VWB_Bar(infox, infoy, 40, infobottom-infoy, WHITE);\r
- PrintX = infox;\r
- PrintY = infoy;\r
- US_PrintUnsigned(chunk);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintUnsigned(info->width);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintUnsigned(info->height);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintSigned(info->orgx);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintSigned(info->orgy);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintSigned(info->xl);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintSigned(info->yl);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintSigned(info->xh);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintSigned(info->yh);\r
- US_Print("\n");\r
- PrintX = infox;\r
- US_PrintSigned(info->shifts);\r
- US_Print("\n");\r
- PrintX = infox;\r
- if (!block)\r
- {\r
- US_Print("-----");\r
- }\r
- else\r
- {\r
- size = ((spritetype far *)block)->sourceoffset[3] + ((spritetype far *)block)->planesize[3]*5;\r
- size = (size + 15) & ~15; //round up to multiples of 16\r
- totalsize += size; //useless: the value stored in 'totalsize' is never used\r
- US_PrintUnsigned(size);\r
- US_Print("=");\r
- }\r
- oldchunk = chunk;\r
- do\r
- {\r
- VWB_Bar(drawx, infoy, 110, infobottom-infoy, WHITE);\r
- if (block)\r
- {\r
- PrintX = drawx;\r
- PrintY = infoy;\r
- US_Print("Shift:");\r
- US_PrintUnsigned(shift);\r
- US_Print("\n");\r
- VWB_DrawSprite(drawx + 2*shift + 16, PrintY, chunk);\r
- }\r
- VW_UpdateScreen();\r
- scan = IN_WaitForKey();\r
- switch (scan)\r
- {\r
- case sc_UpArrow:\r
- chunk++;\r
- break;\r
- case sc_DownArrow:\r
- chunk--;\r
- break;\r
- case sc_PgUp:\r
- chunk += 10;\r
- if (chunk >= STARTSPRITES+NUMSPRITES)\r
- {\r
- chunk = STARTSPRITES+NUMSPRITES-1;\r
- }\r
- break;\r
- case sc_PgDn:\r
- chunk -= 10;\r
- if (chunk < STARTSPRITES)\r
- {\r
- chunk = STARTSPRITES;\r
- }\r
- break;\r
- case sc_LeftArrow:\r
- if (--shift == -1)\r
- {\r
- shift = 3;\r
- }\r
- break;\r
- case sc_RightArrow:\r
- if (++shift == 4)\r
- {\r
- shift = 0;\r
- }\r
- break;\r
- case sc_Escape:\r
- return;\r
- }\r
-\r
- } while (chunk == oldchunk);\r
-\r
- }\r
-}\r
-\r
-/*\r
-===================\r
-=\r
-= PicturePause\r
-=\r
-===================\r
-*/\r
-\r
-void PicturePause(void)\r
-{\r
- Uint16 source;\r
- Sint16 y;\r
-\r
-//\r
-// wait for a key press, abort if it's not Enter\r
-//\r
- IN_ClearKeysDown();\r
- while (!LastScan);\r
- if (LastScan != sc_Enter)\r
- {\r
- IN_ClearKeysDown();\r
- return;\r
- }\r
-\r
- SD_PlaySound(SND_JUMP);\r
- SD_WaitSoundDone();\r
-\r
-//\r
-// rearrange onscreen image into base EGA layout, so that it\r
-// can be grabbed correctly by an external screenshot tool\r
-//\r
- source = displayofs + panadjust;\r
-\r
- VW_ColorBorder(15); // white (can't use WHITE as parameter, since that's defined as 3 for CGA and this must use 15)\r
- VW_SetLineWidth(40);\r
- VW_SetScreen(0, 0);\r
-\r
- if (source < 0x10000l-200*64)\r
- {\r
- //\r
- // copy top line first\r
- //\r
- for (y=0; y<200; y++)\r
- {\r
- VW_ScreenToScreen(source+y*64, y*40, 40, 1);\r
- }\r
- }\r
- else\r
- {\r
- //\r
- // copy bottom line first\r
- //\r
- for (y=199; y>=0; y--)\r
- {\r
- VW_ScreenToScreen(source+y*64, y*40, 40, 1);\r
- }\r
- }\r
-\r
-//\r
-// shut down input manager so that screenshot tool can see input again\r
-//\r
- IN_Shutdown();\r
-\r
- SD_PlaySound(SND_EXTRAKEEN);\r
- SD_WaitSoundDone();\r
-\r
-//\r
-// shut down the remaining ID managers, except VW (stay in graphics mode!)\r
-//\r
- US_Shutdown();\r
- SD_Shutdown();\r
- IN_Shutdown();\r
- RF_Shutdown();\r
- CA_Shutdown();\r
- MM_Shutdown();\r
-\r
-//\r
-// wait until user hits Escape\r
-//\r
- while (((bioskey(0) >> 8) & 0xFF) != sc_Escape);\r
-\r
-//\r
-// back to text mode and exit to DOS\r
-//\r
- VW_Shutdown();\r
- exit(0);\r
-}\r
-\r
-/*\r
-===================\r
-=\r
-= MaskOnTile\r
-=\r
-===================\r
-*/\r
-\r
-void MaskOnTile(Uint16 dest, Uint16 source)\r
-{\r
- Sint16 i;\r
- Uint16 _seg *sourceseg;\r
- Uint16 _seg *destseg;\r
- Uint16 sourceval, maskindex, sourcemask;\r
-\r
- sourceseg = (grsegs+STARTTILE16M)[source];\r
- destseg = (grsegs+STARTTILE16M)[dest];\r
- for (i=0; i<64; i++)\r
- {\r
- maskindex = i & 15;\r
-#ifdef KEEN6Ev15\r
- sourceval = sourceseg[16+i];\r
-#else\r
- sourceval = (sourceseg+16)[i];\r
-#endif\r
- sourcemask = sourceseg[maskindex];\r
- destseg[maskindex] &= sourcemask;\r
- destseg[16+i] &= sourcemask;\r
- destseg[16+i] |= sourceval;\r
- }\r
-}\r
-\r
-/*\r
-===================\r
-=\r
-= WallDebug\r
-=\r
-===================\r
-*/\r
-\r
-void WallDebug(void)\r
-{\r
- Sint16 i, val;\r
-\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(24, 3);\r
- US_PrintCentered("WORKING");\r
- VW_UpdateScreen();\r
- for (i=STARTTILE16M+108; i<STARTTILE16M+124; i++)\r
- {\r
- CA_CacheGrChunk(i);\r
- }\r
- for (i=0; i<NUMTILE16M; i++)\r
- {\r
- if (!grsegs[STARTTILE16M+i])\r
- {\r
- continue;\r
- }\r
- val = tinf[i+NORTHWALL] & 7;\r
- if (val)\r
- {\r
- MaskOnTile(i, val+107);\r
- }\r
- val = tinf[i+SOUTHWALL] & 7;\r
- if (val)\r
- {\r
- MaskOnTile(i, val+115);\r
- }\r
- val = tinf[i+EASTWALL] & 7;\r
- if (val > 1)\r
- {\r
- strcpy(str, "WallDebug: East wall other than 1:");\r
- itoa(i, str2, 10);\r
- strcat(str, str2);\r
- Quit(str);\r
- }\r
- if (val)\r
- {\r
- MaskOnTile(i, val+114); //Note: val is always 1 here, so you could use 115 as 2nd arg\r
- }\r
- val = tinf[i+WESTWALL] & 7;\r
- if (val > 1)\r
- {\r
- strcpy(str, "WallDebug: West wall other than 1:");\r
- itoa(i, str2, 10);\r
- strcat(str, str2);\r
- Quit(str);\r
- }\r
- if (val)\r
- {\r
- MaskOnTile(i, val+122); //Note: val is always 1 here, so you could use 123 as 2nd arg\r
- }\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-================\r
-=\r
-= DebugKeys\r
-=\r
-================\r
-*/\r
-\r
-boolean DebugKeys(void)\r
-{\r
- Sint16 level, i, esc;\r
-\r
- if (Keyboard[sc_B] && ingame) // B = border color\r
- {\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(24, 3);\r
- PrintY += 6;\r
- US_Print(" Border color (0-15):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput(px, py, str, NULL, true, 2, 0);\r
- if (!esc)\r
- {\r
- level = atoi(str);\r
- if (level >= 0 && level <= 15)\r
- {\r
- VW_ColorBorder(level);\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- if (Keyboard[sc_C] && ingame) // C = count objects\r
- {\r
- CountObjects();\r
- return true;\r
- }\r
-\r
- if (Keyboard[sc_D] && ingame) // D = start / end demo record\r
- {\r
- if (DemoMode == demo_Off)\r
- {\r
- StartDemoRecord();\r
- }\r
- else if (DemoMode == demo_Record)\r
- {\r
- EndDemoRecord();\r
- playstate = ex_completed;\r
- }\r
- return true;\r
- }\r
-\r
- if (Keyboard[sc_E] && ingame) // E = quit level\r
- {\r
- if (tedlevel)\r
- {\r
- TEDDeath();\r
- }\r
- playstate = ex_completed;\r
- //BUG? there is no return in this branch (should return false)\r
- }\r
-\r
- if (Keyboard[sc_G] && ingame) // G = god mode\r
- {\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(12, 2);\r
- if (godmode)\r
- {\r
- US_PrintCentered("God mode OFF");\r
- }\r
- else\r
- {\r
- US_PrintCentered("God mode ON");\r
- }\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- godmode ^= true;\r
- return true;\r
- }\r
- else if (Keyboard[sc_I]) // I = item cheat\r
- {\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(12, 3);\r
- US_PrintCentered("Free items!");\r
- for (i=0; i<4; i++)\r
- {\r
- gamestate.keys[i] = 99;\r
- }\r
- gamestate.ammo = 99;\r
-#if defined KEEN4\r
- gamestate.wetsuit = true;\r
-#elif defined KEEN5\r
- gamestate.keycard = true;\r
-#elif defined KEEN6\r
- gamestate.passcardstate=gamestate.hookstate=gamestate.sandwichstate = 1;\r
-#endif\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- GivePoints(3000);\r
- return true;\r
- }\r
- else if (Keyboard[sc_J]) // J = jump cheat\r
- {\r
- jumpcheat ^= true;\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(18, 3);\r
- if (jumpcheat)\r
- {\r
- US_PrintCentered("Jump cheat ON");\r
- }\r
- else\r
- {\r
- US_PrintCentered("Jump cheat OFF");\r
- }\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- return true;\r
- }\r
- else if (Keyboard[sc_M]) // M = memory info\r
- {\r
- DebugMemory();\r
- return true;\r
- }\r
- else if (Keyboard[sc_N]) // N = no clip\r
- {\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(18, 3);\r
- if (player->needtoclip)\r
- {\r
- US_PrintCentered("No clipping ON");\r
- player->needtoclip = cl_noclip;\r
- }\r
- else\r
- {\r
- US_PrintCentered("No clipping OFF");\r
- player->needtoclip = cl_midclip;\r
- }\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- return true;\r
- }\r
- else if (Keyboard[sc_P]) // P = pause with no screen disruptioon\r
- {\r
- IN_ClearKeysDown();\r
- PicturePause();\r
- return true;\r
- }\r
- else if (Keyboard[sc_S] && ingame) // S = slow motion\r
- {\r
- singlestep ^= true;\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(18, 3);\r
- if (singlestep)\r
- {\r
- US_PrintCentered("Slow motion ON");\r
- }\r
- else\r
- {\r
- US_PrintCentered("Slow motion OFF");\r
- }\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- return true;\r
- }\r
- else if (Keyboard[sc_T]) // T = sprite test\r
- {\r
- TestSprites();\r
- return true;\r
- }\r
- else if (Keyboard[sc_V]) // V = extra VBLs\r
- {\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(30, 3);\r
- PrintY += 6;\r
- US_Print(" Add how many extra VBLs(0-8):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput(px, py, str, NULL, true, 2, 0);\r
- if (!esc)\r
- {\r
- level = atoi(str);\r
- if (level >= 0 && level <= 8)\r
- {\r
- extravbls = level;\r
- }\r
- }\r
- return true;\r
- }\r
- else if (Keyboard[sc_W] && ingame) // W = warp to level\r
- {\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(26, 3);\r
- PrintY += 6;\r
- US_Print(" Warp to which level(1-18):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput(px, py, str, NULL, true, 2, 0);\r
- if (!esc)\r
- {\r
- level = atoi(str);\r
- if (level > 0 && level <= 18)\r
- {\r
- gamestate.mapon = level;\r
- playstate = ex_warped;\r
- }\r
- }\r
- return true;\r
- }\r
- else if (Keyboard[sc_Y]) // Y = wall debug\r
- {\r
- WallDebug();\r
- return true;\r
- }\r
- else if (Keyboard[sc_Z]) // Z = game over\r
- {\r
- gamestate.lives = 0;\r
- KillKeen();\r
- return false;\r
- }\r
- return false;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-================\r
-=\r
-= UserCheat\r
-=\r
-================\r
-*/\r
-\r
-void UserCheat(void)\r
-{\r
- Sint16 i;\r
-\r
- for (i=sc_A; i<=sc_Z; i++) //Note: this does NOT check the keys in alphabetical order!\r
- {\r
- if (i != sc_B && i != sc_A && i != sc_T && Keyboard[i])\r
- {\r
- return;\r
- }\r
- }\r
- US_CenterWindow(20, 7);\r
- PrintY += 2;\r
- US_CPrint(\r
- "Cheat Option!\n"\r
- "\n"\r
- "You just got all\n"\r
- "the keys, 99 shots,\n"\r
- "and an extra keen!");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- RF_ForceRefresh();\r
- gamestate.ammo = 99;\r
- gamestate.lives++;\r
-#ifdef KEEN5\r
- gamestate.keycard = true;\r
-#endif\r
- gamestate.keys[0] = gamestate.keys[1] = gamestate.keys[2] = gamestate.keys[3] = 1;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= CheckKeys\r
-=\r
-=====================\r
-*/\r
-\r
-void CheckKeys(void)\r
-{\r
- if (screenfaded) // don't do anything with a faded screen\r
- {\r
- return;\r
- }\r
-\r
-//\r
-// Enter for status screen\r
-//\r
- if (Keyboard[sc_Enter] || (GravisGamepad && GravisAction[ga_Status]))\r
- {\r
- StatusWindow();\r
- IN_ClearKeysDown();\r
- RF_ForceRefresh();\r
- lasttimecount = TimeCount; // BUG: should be the other way around\r
- }\r
-\r
-//\r
-// pause key wierdness can't be checked as a scan code\r
-//\r
- if (Paused)\r
- {\r
- SD_MusicOff();\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(8, 3);\r
- US_PrintCentered("PAUSED");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- RF_ForceRefresh();\r
- Paused = false;\r
- SD_MusicOn();\r
- }\r
-\r
-#ifndef KEEN6\r
-//\r
-// F1 to enter help screens\r
-//\r
- if (LastScan == sc_F1)\r
- {\r
- StopMusic();\r
- HelpScreens();\r
- StartMusic(gamestate.mapon);\r
- if (showscorebox)\r
- {\r
- scoreobj->temp2 = -1;\r
- scoreobj->temp1 = -1;\r
- scoreobj->temp3 = -1;\r
- scoreobj->temp4 = -1;\r
- }\r
- RF_ForceRefresh();\r
- }\r
-#endif\r
-\r
- if (!storedemo)\r
- {\r
-//\r
-// F2-F7/ESC to enter control panel\r
-//\r
- if (LastScan >= sc_F2 && LastScan <= sc_F7 || LastScan == sc_Escape)\r
- {\r
- VW_FixRefreshBuffer();\r
- StopMusic();\r
- US_ControlPanel();\r
- RF_FixOfs();\r
- StartMusic(gamestate.mapon);\r
- if (!showscorebox && scoreobj->sprite)\r
- {\r
- RF_RemoveSprite(&scoreobj->sprite);\r
- }\r
- if (showscorebox)\r
- {\r
- scoreobj->temp2 = -1;\r
- scoreobj->temp1 = -1;\r
- scoreobj->temp3 = -1;\r
- scoreobj->temp4 = -1;\r
- }\r
- IN_ClearKeysDown();\r
- if (restartgame)\r
- {\r
- playstate = ex_resetgame;\r
- }\r
- else if (!loadedgame)\r
- {\r
- RF_ForceRefresh();\r
- }\r
- if (abortgame)\r
- {\r
- abortgame = false;\r
- playstate = ex_abortgame;\r
- }\r
- if (loadedgame)\r
- {\r
- playstate = ex_loadedgame;\r
- }\r
- lasttimecount = TimeCount; // BUG: should be the other way around\r
- }\r
-\r
-//\r
-// F9 boss key\r
-//\r
- if (LastScan == sc_F9)\r
- {\r
- VW_Shutdown();\r
- SD_MusicOff();\r
- cputs("C:>");\r
- IN_ClearKeysDown();\r
- while (LastScan != sc_Escape);\r
- VW_SetScreenMode(GRMODE);\r
- VW_ColorBorder(bordercolor);\r
- RF_ForceRefresh();\r
- IN_ClearKeysDown();\r
- lasttimecount = TimeCount; // BUG: should be the other way around\r
- SD_MusicOn();\r
- }\r
- }\r
-\r
-//\r
-// B-A-T cheat code\r
-//\r
- if (Keyboard[sc_B] && Keyboard[sc_A] && Keyboard[sc_T])\r
- {\r
- UserCheat();\r
- }\r
-\r
-//\r
-// F10-? debug keys\r
-//\r
- if (debugok && Keyboard[sc_F10])\r
- {\r
- if (DebugKeys())\r
- {\r
- RF_ForceRefresh();\r
- lasttimecount = TimeCount; // BUG: should be the other way around\r
- }\r
- }\r
-\r
-//\r
-// Ctrl-S toggles sound (only in storedemo mode)\r
-//\r
- if (storedemo && Keyboard[sc_Control] && LastScan == sc_S)\r
- {\r
- if (SoundMode != sdm_Off)\r
- {\r
- SD_SetSoundMode(sdm_Off);\r
- SD_SetMusicMode(smm_Off);\r
- }\r
- else\r
- {\r
- if (AdLibPresent)\r
- {\r
- SD_SetSoundMode(sdm_AdLib);\r
- QuietFX = false;\r
- SD_SetMusicMode(smm_AdLib);\r
- }\r
- else\r
- {\r
- SD_SetSoundMode(sdm_PC);\r
- SD_SetMusicMode(smm_Off);\r
- }\r
- CA_LoadAllSounds();\r
- }\r
- }\r
-\r
-//\r
-// Ctrl-Q quick quit\r
-//\r
- if (Keyboard[sc_Control] && LastScan == sc_Q)\r
- {\r
- IN_ClearKeysDown();\r
- Quit(NULL);\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= PrintNumbers\r
-=\r
-==================\r
-*/\r
-\r
-void PrintNumbers(Sint16 x, Sint16 y, Sint16 maxlen, Sint16 basetile, Sint32 number)\r
-{\r
- register Sint16 i;\r
- Sint16 len;\r
- char buffer[20];\r
-\r
- ltoa(number, buffer, 10);\r
- len = strlen(buffer);\r
- i = maxlen;\r
- while (i>len)\r
- {\r
- VWB_DrawTile8(x, y, basetile);\r
- i--;\r
- x += 8;\r
- }\r
- while (i>0)\r
- {\r
- VWB_DrawTile8(x, y, basetile+buffer[len-i]+(1-'0'));\r
- i--;\r
- x += 8;\r
- }\r
-}\r
-\r
-/*\r
-==================\r
-=\r
-= DrawStatusWindow\r
-=\r
-==================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define BACKCOLOR WHITE\r
-#define TEXTBACK BLACK\r
-#define NUMBERBACK BLACK\r
-\r
-#else\r
-\r
-#define BACKCOLOR LIGHTGRAY\r
-#define TEXTBACK WHITE\r
-#define NUMBERBACK BLACK\r
-\r
-#endif\r
-\r
-void DrawStatusWindow(void)\r
-{\r
- Sint16 off, x, y, w, h, i;\r
- Uint16 width, height;\r
-\r
- x = 64;\r
- y = 16;\r
- w = 184;\r
- h = 144;\r
- VWB_DrawTile8(x, y, 54);\r
- VWB_DrawTile8(x, y+h, 60);\r
- for (i=x+8; i<=x+w-8; i+=8)\r
- {\r
- VWB_DrawTile8(i, y, 55);\r
- VWB_DrawTile8(i, y+h, 61);\r
- }\r
- VWB_DrawTile8(i, y, 56);\r
- VWB_DrawTile8(i, y+h, 62);\r
- for (i=y+8; i<=y+h-8; i+=8)\r
- {\r
- VWB_DrawTile8(x, i, 57);\r
- VWB_DrawTile8(x+w, i, 59);\r
- }\r
- VWB_Bar(72, 24, 176, 136, BACKCOLOR);\r
-\r
- PrintY = 28;\r
- WindowX = 80;\r
- WindowW = 160;\r
- US_CPrint("LOCATION");\r
- VWB_Bar(79, 38, 162, 20, TEXTBACK);\r
-#ifdef KEEN5\r
- if (mapon == 0 && player->y > 100*TILEGLOBAL)\r
- _fstrcpy(str, levelnames[13]);\r
- else\r
- _fstrcpy(str, levelnames[gamestate.mapon]);\r
-#else\r
- _fstrcpy(str, levelnames[gamestate.mapon]);\r
-#endif\r
- SizeText(str, &width, &height);\r
- PrintY = (20-height)/2+40-2;\r
- US_CPrint(str);\r
-\r
- PrintY = 61;\r
- WindowX = 80;\r
- WindowW = 64;\r
- US_CPrint("SCORE");\r
- VWB_Bar(79, 71, 66, 10, NUMBERBACK);\r
- PrintNumbers(80, 72, 8, 41, gamestate.score);\r
-\r
- PrintY = 61;\r
- WindowX = 176;\r
- WindowW = 64;\r
- US_CPrint("EXTRA");\r
- VWB_Bar(175, 71, 66, 10, NUMBERBACK);\r
- PrintNumbers(176, 72, 8, 41, gamestate.nextextra);\r
-\r
-#if defined KEEN4\r
- PrintY = 85;\r
- WindowX = 80;\r
- WindowW = 64;\r
- US_CPrint("RESCUED");\r
- VWB_Bar(79, 95, 66, 10, NUMBERBACK);\r
- for (i = 0; i < gamestate.rescued; i++, off+=8)\r
- {\r
- VWB_DrawTile8(i*8 + 80, 96, 40);\r
- }\r
-#elif defined KEEN5\r
- PrintY = 92;\r
- PrintX = 80;\r
- US_Print("KEYCARD");\r
- VWB_Bar(135, 91, 10, 10, NUMBERBACK);\r
- if (gamestate.keycard)\r
- {\r
- VWB_DrawTile8(136, 92, 40);\r
- }\r
-#endif\r
-\r
- PrintY = 85;\r
- WindowX = 176;\r
- WindowW = 64;\r
- US_CPrint("LEVEL");\r
- VWB_Bar(175, 95, 66, 10, TEXTBACK);\r
- PrintY = 96;\r
- WindowX = 176;\r
- WindowW = 64;\r
- switch (gamestate.difficulty)\r
- {\r
- case gd_Easy:\r
- US_CPrint("Easy");\r
- break;\r
- case gd_Normal:\r
- US_CPrint("Normal");\r
- break;\r
- case gd_Hard:\r
- US_CPrint("Hard");\r
- break;\r
- }\r
-\r
-#ifdef KEEN6\r
- PrintX = 80;\r
- PrintY = 96;\r
- US_Print("ITEMS");\r
- VWB_Bar(127, 95, 26, 10, NUMBERBACK);\r
- if (gamestate.sandwichstate == 1)\r
- {\r
- VWB_DrawTile8(128, 96, 2);\r
- }\r
- else\r
- {\r
- VWB_DrawTile8(128, 96, 1);\r
- }\r
- if (gamestate.hookstate == 1)\r
- {\r
- VWB_DrawTile8(136, 96, 4);\r
- }\r
- else\r
- {\r
- VWB_DrawTile8(136, 96, 3);\r
- }\r
- if (gamestate.passcardstate == 1)\r
- {\r
- VWB_DrawTile8(144, 96, 6);\r
- }\r
- else\r
- {\r
- VWB_DrawTile8(144, 96, 5);\r
- }\r
-#endif\r
-\r
- PrintX = 80;\r
- PrintY = 112;\r
- US_Print("KEYS");\r
- VWB_Bar(119, 111, 34, 10, NUMBERBACK);\r
- for (i = 0; i < 4; i++)\r
- {\r
- if (gamestate.keys[i])\r
- {\r
- VWB_DrawTile8(i*8+120, 112, 36+i);\r
- }\r
- }\r
-\r
- PrintX = 176;\r
- PrintY = 112;\r
- US_Print("AMMO");\r
- VWB_Bar(215, 111, 26, 10, NUMBERBACK);\r
- PrintNumbers(216, 112, 3, 41, gamestate.ammo);\r
-\r
- PrintX = 80;\r
- PrintY = 128;\r
- US_Print("KEENS");\r
- VWB_Bar(127, 127, 18, 10, NUMBERBACK);\r
- PrintNumbers(128, 128, 2, 41, gamestate.lives);\r
-\r
- PrintX = 176;\r
- PrintY = 128;\r
- US_Print(DROPSNAME);\r
- VWB_Bar(224, 127, 16, 10, NUMBERBACK);\r
- PrintNumbers(224, 128, 2, 41, gamestate.drops);\r
-\r
-#ifdef KEEN4\r
- VWB_Bar(79, 143, 66, 10, TEXTBACK);\r
- PrintY = 144;\r
- WindowX = 80;\r
- WindowW = 64;\r
- if (gamestate.wetsuit)\r
- {\r
- US_CPrint("Wetsuit");\r
- }\r
- else\r
- {\r
- US_CPrint("???");\r
- }\r
-#endif\r
-\r
- // draw the tiles for "PRESS A KEY":\r
- for (i = 0; i < 10; i++)\r
- {\r
- VWB_DrawTile8(i*8+STATUS_PRESSKEY_X, 140, i+72);\r
- VWB_DrawTile8(i*8+STATUS_PRESSKEY_X, 148, i+82);\r
- }\r
-}\r
-\r
-/*\r
-==================\r
-=\r
-= ScrollStatusWindow\r
-=\r
-==================\r
-*/\r
-\r
-void ScrollStatusWindow(void)\r
-{\r
- Uint16 source, dest;\r
- Sint16 height;\r
-\r
- if (vislines > 152)\r
- {\r
- height = vislines - 152;\r
- source = windowofs + panadjust + 8;\r
- dest = bufferofs + panadjust + 8;\r
- VW_ScreenToScreen(source, dest, 192/BYTEPIXELS, height);\r
- VW_ClipDrawMPic((pansx+136)/BYTEPIXELS, -(16-height)+pansy, METALPOLEPICM);\r
- source = windowofs + panadjust + 16*SCREENWIDTH + 8*CHARWIDTH;\r
- dest = bufferofs + panadjust + height*SCREENWIDTH + 8;\r
- height = 152;\r
- }\r
- else\r
- {\r
- source = windowofs + panadjust + (152-vislines)*SCREENWIDTH + 16*SCREENWIDTH + 8*CHARWIDTH;\r
- dest = bufferofs + panadjust + 8;\r
- height = vislines;\r
- }\r
- if (height > 0)\r
- {\r
- VW_ScreenToScreen(source, dest, 192/BYTEPIXELS, height);\r
- }\r
- if (scrollup)\r
- {\r
- height = 168-vislines;\r
- source = masterofs + panadjust + vislines*SCREENWIDTH + 8;\r
- dest = bufferofs + panadjust + vislines*SCREENWIDTH + 8;\r
- VW_ScreenToScreen(source, dest, 192/BYTEPIXELS, height);\r
- height = vislines;\r
- source = windowofs + panadjust + 8 - 24/BYTEPIXELS;\r
- dest = bufferofs + panadjust + 8 - 24/BYTEPIXELS;\r
- if (height > 0)\r
- VW_ScreenToScreen(source, dest, 24/BYTEPIXELS, height);\r
- }\r
- else\r
- {\r
- height = vislines + -72;\r
- if (height > 0)\r
- {\r
- source = windowofs + panadjust + 8 - 24/BYTEPIXELS;\r
- dest = bufferofs + panadjust + 8 - 24/BYTEPIXELS;\r
- if (height > 0)\r
- VW_ScreenToScreen(source, dest, 24/BYTEPIXELS, height);\r
- }\r
- }\r
- if (vislines >= 72)\r
- {\r
- VW_ClipDrawMPic((pansx+40)/BYTEPIXELS, vislines-168+pansy, CORDPICM);\r
- }\r
- VW_UpdateScreen();\r
-}\r
-\r
-/*\r
-==================\r
-=\r
-= StatusWindow\r
-=\r
-==================\r
-*/\r
-\r
-void StatusWindow(void)\r
-{\r
-#if GRMODE == CGAGR\r
-\r
- if (Keyboard[sc_A] && Keyboard[sc_2])\r
- {\r
- US_CenterWindow(20, 2);\r
- PrintY += 2;\r
- US_Print("Debug keys active");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- debugok = true;\r
- }\r
-\r
- WindowX = 0;\r
- WindowW = 320;\r
- WindowY = 0;\r
- WindowH = 200;\r
- DrawStatusWindow();\r
- VW_UpdateScreen();\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
-#else\r
-\r
- Uint16 oldbufferofs;\r
-\r
- WindowX = 0;\r
- WindowW = 320;\r
- WindowY = 0;\r
- WindowH = 200;\r
-\r
- if (Keyboard[sc_A] && Keyboard[sc_2])\r
- {\r
- US_CenterWindow(20, 2);\r
- PrintY += 2;\r
- US_Print("Debug keys active");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- debugok = true;\r
- }\r
-\r
- RF_Refresh();\r
- RFL_InitAnimList();\r
- oldbufferofs = bufferofs;\r
- bufferofs = windowofs = RF_FindFreeBuffer();\r
- VW_ScreenToScreen(displayofs, displayofs, 44, 224); // useless (source and dest offsets are identical)\r
- VW_ScreenToScreen(displayofs, masterofs, 44, 224);\r
- VW_ScreenToScreen(displayofs, bufferofs, 44, 168);\r
- DrawStatusWindow();\r
- bufferofs = oldbufferofs;\r
- RF_Refresh();\r
-\r
- SD_PlaySound(SND_SHOWSTATUS);\r
- vislines = 16;\r
- scrollup = false;\r
- RF_SetRefreshHook(ScrollStatusWindow);\r
-\r
- while (true)\r
- {\r
- RF_Refresh();\r
- if (vislines == 168)\r
- break;\r
- vislines = vislines + tics*8;\r
- if (vislines > 168)\r
- vislines = 168;\r
- }\r
-\r
- RF_Refresh();\r
- RF_SetRefreshHook(NULL);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- SD_PlaySound(SND_HIDESTATUS);\r
- vislines -= 16;\r
- scrollup = true;\r
- RF_SetRefreshHook(ScrollStatusWindow);\r
-\r
- while (true)\r
- {\r
- RF_Refresh();\r
- if (vislines == 0)\r
- break;\r
- vislines = vislines - tics*8;\r
- if (vislines < 0)\r
- vislines = 0;\r
- }\r
-\r
- RF_SetRefreshHook(NULL);\r
-\r
- scoreobj->x = 0; //force scorebox to redraw?\r
-\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= CenterActor\r
-=\r
-==================\r
-*/\r
-\r
-void CenterActor(objtype *ob)\r
-{\r
- Uint16 orgx, orgy;\r
-\r
- centerlevel = 140;\r
- if (ob->x < 152*PIXGLOBAL)\r
- {\r
- orgx = 0;\r
- }\r
- else\r
- {\r
- orgx = ob->x - 152*PIXGLOBAL;\r
- }\r
- if (mapon == 0)\r
- {\r
- if (ob->y < 80*PIXGLOBAL)\r
- {\r
- orgy = 0;\r
- }\r
- else\r
- {\r
- orgy = ob->y - 80*PIXGLOBAL;\r
- }\r
- }\r
- else\r
- {\r
- if (ob->bottom < 140*PIXGLOBAL)\r
- {\r
- orgy = 0;\r
- }\r
- else\r
- {\r
- orgy = ob->bottom - 140*PIXGLOBAL;\r
- }\r
- }\r
- if (!scorescreenkludge)\r
- {\r
- RF_NewPosition(orgx, orgy);\r
- }\r
-\r
-//\r
-// update limits for onscreen and inactivate checks\r
-//\r
- originxtilemax = (originxtile + PORTTILESWIDE) - 1;\r
- originytilemax = (originytile + PORTTILESHIGH) - 1;\r
- inactivateleft = originxtile - INACTIVATEDIST;\r
- if (inactivateleft < 0)\r
- {\r
- inactivateleft = 0;\r
- }\r
- inactivateright = originxtilemax + INACTIVATEDIST;\r
- if (inactivateright < 0)\r
- {\r
- inactivateright = 0;\r
- }\r
- inactivatetop = originytile - INACTIVATEDIST;\r
- if (inactivatetop < 0)\r
- {\r
- inactivatetop = 0;\r
- }\r
- inactivatebottom = originytilemax + INACTIVATEDIST;\r
- if (inactivatebottom < 0)\r
- {\r
- inactivatebottom = 0;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= WorldScrollScreen\r
-=\r
-= Scroll if Keen is nearing an edge\r
-=\r
-==================\r
-*/\r
-\r
-void WorldScrollScreen(objtype *ob)\r
-{\r
- Sint16 xscroll, yscroll;\r
-\r
- if (keenkilled)\r
- return;\r
-\r
- if (ob->left < originxglobal + 9*TILEGLOBAL)\r
- {\r
- xscroll = ob->left - (originxglobal + 9*TILEGLOBAL);\r
- }\r
- else if (ob->right > originxglobal + 12*TILEGLOBAL)\r
- {\r
- xscroll = ob->right + 16 - (originxglobal + 12*TILEGLOBAL);\r
- }\r
- else\r
- {\r
- xscroll = 0;\r
- }\r
-\r
- if (ob->top < originyglobal + 5*TILEGLOBAL)\r
- {\r
- yscroll = ob->top - (originyglobal + 5*TILEGLOBAL);\r
- }\r
- else if (ob->bottom > originyglobal + 7*TILEGLOBAL)\r
- {\r
- yscroll = ob->bottom - (originyglobal + 7*TILEGLOBAL);\r
- }\r
- else\r
- {\r
- yscroll = 0;\r
- }\r
-\r
- if (!xscroll && !yscroll)\r
- return;\r
-\r
-//\r
-// don't scroll more than one tile per frame\r
-//\r
- if (xscroll >= 0x100)\r
- {\r
- xscroll = 0xFF;\r
- }\r
- else if (xscroll <= -0x100)\r
- {\r
- xscroll = -0xFF;\r
- }\r
- if (yscroll >= 0x100)\r
- {\r
- yscroll = 0xFF;\r
- }\r
- else if (yscroll <= -0x100)\r
- {\r
- yscroll = -0xFF;\r
- }\r
-\r
- RF_Scroll(xscroll, yscroll);\r
-\r
-//\r
-// update limits for onscreen and inactivate checks\r
-//\r
- originxtilemax = (originxtile + PORTTILESWIDE) - 1;\r
- originytilemax = (originytile + PORTTILESHIGH) - 1;\r
- inactivateleft = originxtile - INACTIVATEDIST;\r
- if (inactivateleft < 0)\r
- {\r
- inactivateleft = 0;\r
- }\r
- inactivateright = originxtilemax + INACTIVATEDIST;\r
- if (inactivateright < 0)\r
- {\r
- inactivateright = 0;\r
- }\r
- inactivatetop = originytile - INACTIVATEDIST;\r
- if (inactivatetop < 0)\r
- {\r
- inactivatetop = 0;\r
- }\r
- inactivatebottom = originytilemax + INACTIVATEDIST;\r
- if (inactivatebottom < 0)\r
- {\r
- inactivatebottom = 0;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= ScrollScreen\r
-=\r
-= Scroll if Keen is nearing an edge\r
-= Set playstate to ex_completes\r
-=\r
-==================\r
-*/\r
-\r
-void ScrollScreen(objtype *ob)\r
-{\r
- Sint16 xscroll, yscroll, pix, speed;\r
- Uint16 bottom;\r
-\r
- if (keenkilled)\r
- return;\r
-\r
-//\r
-// walked off edge of map?\r
-//\r
- if (ob->left < originxmin || ob->right > originxmax + 320*PIXGLOBAL)\r
- {\r
- playstate = ex_completed;\r
- return;\r
- }\r
-\r
-//\r
-// fallen off bottom of world?\r
-//\r
- if (ob->bottom > originymax + 13*TILEGLOBAL)\r
- {\r
- ob->y -= ob->bottom - (originymax + 13*TILEGLOBAL);\r
- SD_PlaySound(SND_PLUMMET);\r
- godmode = false;\r
- KillKeen();\r
- return;\r
- }\r
-\r
- xscroll=yscroll=0;\r
-\r
- if (ob->x < originxglobal + 9*TILEGLOBAL)\r
- {\r
- xscroll = ob->x - (originxglobal + 9*TILEGLOBAL);\r
- }\r
- else if (ob->x > originxglobal + 12*TILEGLOBAL)\r
- {\r
- xscroll = ob->x - (originxglobal + 12*TILEGLOBAL);\r
- }\r
-\r
- if (ob->state == &s_keenlookup2)\r
- {\r
- if (centerlevel+tics > 167)\r
- {\r
- pix = 167-centerlevel;\r
- }\r
- else\r
- {\r
- pix = tics;\r
- }\r
- centerlevel += pix;\r
- yscroll = CONVERT_PIXEL_TO_GLOBAL(-pix);\r
- }\r
- else if (ob->state == &s_keenlookdown3)\r
- {\r
- if (centerlevel-tics < 33)\r
- {\r
- pix = centerlevel + -33;\r
- }\r
- else\r
- {\r
- pix = tics;\r
- }\r
- centerlevel -= pix;\r
- yscroll = CONVERT_PIXEL_TO_GLOBAL(pix);\r
- }\r
-\r
-#ifdef KEEN6\r
- if (groundslam)\r
- {\r
- static Sint16 shaketable[] = {0,\r
- -64, -64, -64, 64, 64, 64,\r
- -200, -200, -200, 200, 200, 200,\r
- -250, -250, -250, 250, 250, 250,\r
- -250, -250, -250, 250, 250, 250\r
- };\r
- yscroll = yscroll + (bottom - (ob->bottom + shaketable[groundslam])); // BUG: 'bottom' has not been initialized yet!\r
- }\r
- else\r
-#endif\r
- if ( (ob->hitnorth || !ob->needtoclip || ob->state == &s_keenholdon))\r
- {\r
- if ( ob->state != &s_keenclimbup\r
- && ob->state != &s_keenclimbup2\r
- && ob->state != &s_keenclimbup3\r
- && ob->state != &s_keenclimbup4)\r
- {\r
- yscroll += ob->ymove;\r
- bottom = originyglobal + yscroll + CONVERT_PIXEL_TO_GLOBAL(centerlevel);\r
- if (ob->bottom == bottom)\r
- {\r
- // player didn't move, no additional scrolling\r
- }\r
- else\r
- {\r
- if (ob->bottom < bottom)\r
- {\r
- pix = bottom - ob->bottom;\r
- }\r
- else\r
- {\r
- pix = ob->bottom - bottom;\r
- }\r
- speed = CONVERT_PIXEL_TO_GLOBAL(pix) >> 7;\r
- if (speed > 0x30)\r
- {\r
- speed = 0x30;\r
- }\r
- speed *= tics;\r
- if (speed < 0x10)\r
- {\r
- if (pix < 0x10)\r
- {\r
- speed = pix;\r
- }\r
- else\r
- {\r
- speed = 0x10;\r
- }\r
- }\r
- if (ob->bottom < bottom)\r
- {\r
- yscroll -= speed;\r
- }\r
- else\r
- {\r
- yscroll += speed;\r
- }\r
- }\r
- }\r
- }\r
- else\r
- {\r
- centerlevel = 140;\r
- }\r
-\r
- pix = (ob->bottom-32*PIXGLOBAL)-(originyglobal+yscroll);\r
- if (pix < 0)\r
- {\r
- yscroll += pix;\r
- }\r
- pix = (ob->bottom+32*PIXGLOBAL)-(originyglobal+yscroll+200*PIXGLOBAL);\r
- if (pix > 0)\r
- {\r
- yscroll += pix;\r
- }\r
-\r
- if (xscroll == 0 && yscroll == 0)\r
- return;\r
-\r
-//\r
-// don't scroll more than one tile per frame\r
-//\r
- if (xscroll >= 0x100)\r
- {\r
- xscroll = 0xFF;\r
- }\r
- else if (xscroll <= -0x100)\r
- {\r
- xscroll = -0xFF;\r
- }\r
- if (yscroll >= 0x100)\r
- {\r
- yscroll = 0xFF;\r
- }\r
- else if (yscroll <= -0x100)\r
- {\r
- yscroll = -0xFF;\r
- }\r
- RF_Scroll(xscroll, yscroll);\r
-\r
-//\r
-// update limits for onscreen and inactivate checks\r
-//\r
- originxtilemax = (originxtile + PORTTILESWIDE) - 1;\r
- originytilemax = (originytile + PORTTILESHIGH) - 1;\r
- inactivateleft = originxtile - INACTIVATEDIST;\r
- if (inactivateleft < 0)\r
- {\r
- inactivateleft = 0;\r
- }\r
- inactivateright = originxtilemax + INACTIVATEDIST;\r
- if (inactivateright < 0)\r
- {\r
- inactivateright = 0;\r
- }\r
- inactivatetop = originytile - INACTIVATEDIST;\r
- if (inactivatetop < 0)\r
- {\r
- inactivatetop = 0;\r
- }\r
- inactivatebottom = originytilemax + INACTIVATEDIST;\r
- if (inactivatebottom < 0)\r
- {\r
- inactivatebottom = 0;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-#############################################################################\r
-\r
- The objarray data structure\r
-\r
-#############################################################################\r
-\r
-Objarray contains structures for every actor currently playing. The structure\r
-is accessed as a linked list starting at *player, ending when ob->next ==\r
-NULL. GetNewObj inserts a new object at the end of the list, meaning that\r
-if an actor spawns another actor, the new one WILL get to think and react the\r
-same frame. RemoveObj unlinks the given object and returns it to the free\r
-list, but does not damage the objects ->next pointer, so if the current object\r
-removes itself, a linked list following loop can still safely get to the\r
-next element.\r
-\r
-<backwardly linked free list>\r
-\r
-#############################################################################\r
-*/\r
-\r
-\r
-/*\r
-=========================\r
-=\r
-= InitObjArray\r
-=\r
-= Call to clear out the entire object list, returning them all to the free\r
-= list. Allocates a special spot for the player.\r
-=\r
-=========================\r
-*/\r
-\r
-void InitObjArray(void)\r
-{\r
- Sint16 i;\r
-\r
- for (i=0; i<MAXACTORS; i++)\r
- {\r
- objarray[i].prev = &objarray[i+1];\r
- objarray[i].next = NULL;\r
- }\r
-\r
- objarray[MAXACTORS-1].prev = NULL;\r
-\r
- objfreelist = &objarray[0];\r
- lastobj = NULL;\r
-\r
- objectcount = 0;\r
-\r
-//\r
-// give the player and score the first free spots\r
-//\r
- GetNewObj(false);\r
- player = new;\r
- GetNewObj(false);\r
- scoreobj = new;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= GetNewObj\r
-=\r
-= Sets the global variable new to point to a free spot in objarray.\r
-= The free spot is inserted at the end of the liked list\r
-=\r
-= When the object list is full, the caller can either have it bomb out or\r
-= return a dummy object pointer that will never get used\r
-=\r
-= Returns -1 when list was full, otherwise returns 0.\r
-=\r
-=========================\r
-*/\r
-\r
-Sint16 GetNewObj(boolean usedummy)\r
-{\r
- if (!objfreelist)\r
- {\r
- if (usedummy)\r
- {\r
- new = &dummyobj;\r
- return -1;\r
- }\r
- Quit("GetNewObj: No free spots in objarray!");\r
- }\r
- new = objfreelist;\r
- objfreelist = new->prev;\r
- memset(new, 0, sizeof(*new));\r
- if (lastobj)\r
- {\r
- lastobj->next = new;\r
- }\r
- new->prev = lastobj; // new->next is allready NULL from memset\r
-\r
- new->active = ac_yes;\r
- new->needtoclip = cl_midclip;\r
- lastobj = new;\r
-\r
- objectcount++;\r
- return 0;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= RemoveObj\r
-=\r
-= Add the given object back into the free list, and unlink it from it's\r
-= neighbors\r
-=\r
-=========================\r
-*/\r
-\r
-void RemoveObj(objtype *ob)\r
-{\r
- if (ob == player)\r
- Quit("RemoveObj: Tried to remove the player!");\r
-\r
-//\r
-// erase it from the refresh manager\r
-//\r
- RF_RemoveSprite(&ob->sprite);\r
- if (ob->obclass == stunnedobj)\r
- {\r
- RF_RemoveSprite((void **)&ob->temp3);\r
- }\r
-\r
-//\r
-// fix the next object's back link\r
-//\r
- if (ob == lastobj)\r
- {\r
- lastobj = ob->prev;\r
- }\r
- else\r
- {\r
- ob->next->prev = ob->prev;\r
- }\r
-\r
-//\r
-// fix the previous object's forward link\r
-//\r
- ob->prev->next = ob->next;\r
-\r
-//\r
-// add it back in to the free list\r
-//\r
- ob->prev = objfreelist;\r
- objfreelist = ob;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= GivePoints\r
-=\r
-= Grants extra men at 20k,40k,80k,160k,320k\r
-=\r
-====================\r
-*/\r
-\r
-void GivePoints(Uint16 points)\r
-{\r
- gamestate.score += points;\r
- if (!DemoMode && gamestate.score >= gamestate.nextextra)\r
- {\r
- SD_PlaySound(SND_EXTRAKEEN);\r
- gamestate.lives++;\r
- gamestate.nextextra *= 2;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= PollControls\r
-=\r
-===================\r
-*/\r
-\r
-void PollControls(void)\r
-{\r
- IN_ReadControl(0, &c);\r
- if (c.yaxis != -1)\r
- upheld = false;\r
-\r
- if (GravisGamepad && !DemoMode)\r
- {\r
- jumpbutton = GravisAction[ga_Jump];\r
- pogobutton = GravisAction[ga_Pogo];\r
- firebutton = GravisAction[ga_Fire];\r
- if (!jumpbutton)\r
- jumpheld = false;\r
- if (!pogobutton)\r
- pogoheld = false;\r
- if (!firebutton)\r
- fireheld = false;\r
- }\r
- else if (oldshooting || DemoMode)\r
- {\r
- if (c.button0 && c.button1)\r
- {\r
- firebutton = true;\r
- jumpbutton = pogobutton = jumpheld = pogoheld = false;\r
- }\r
- else\r
- {\r
- firebutton = fireheld = false;\r
- if (c.button0)\r
- {\r
- jumpbutton = true;\r
- }\r
- else\r
- {\r
- jumpbutton = jumpheld = false;\r
- }\r
- if (c.button1)\r
- {\r
- if (oldfirecount <= 8)\r
- {\r
- oldfirecount = oldfirecount + tics;\r
- }\r
- else\r
- {\r
- pogobutton = true;\r
- }\r
- }\r
- else\r
- {\r
- if (oldfirecount != 0)\r
- {\r
- pogobutton = true;\r
- }\r
- else\r
- {\r
- pogobutton = pogoheld = false;\r
- }\r
- oldfirecount = 0;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- jumpbutton = c.button0;\r
- pogobutton = c.button1;\r
- firebutton = Keyboard[firescan];\r
- if (!jumpbutton)\r
- jumpheld = false;\r
- if (!pogobutton)\r
- pogoheld = false;\r
- if (!firebutton)\r
- fireheld = false;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= StopMusic\r
-=\r
-=================\r
-*/\r
-\r
-void StopMusic(void)\r
-{\r
- Sint16 i;\r
-\r
- SD_MusicOff();\r
- for (i=0; i<LASTMUSIC; i++)\r
- {\r
- if (audiosegs[STARTMUSIC+i])\r
- {\r
-#ifdef FIX_MUSIC_MEMORY_ISSUES\r
- //unlock any music blocks so that they can be purged\r
- MM_SetLock(&(memptr)audiosegs[STARTMUSIC+i], false);\r
-#endif\r
- MM_SetPurge(&(memptr)audiosegs[STARTMUSIC+i], PURGE_FIRST);\r
- }\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=================\r
-=\r
-= StartMusic\r
-=\r
-=================\r
-*/\r
-\r
-void StartMusic(Uint16 num)\r
-{\r
- static Sint16 songs[] =\r
- {\r
-#if defined KEEN4\r
- SHADOWS_MUS,\r
- KICKPANT_MUS,\r
- OASIS_MUS,\r
- OASIS_MUS,\r
- TOOHOT_MUS,\r
- TOOHOT_MUS,\r
- KICKPANT_MUS,\r
- OASIS_MUS,\r
- VEGGIES_MUS,\r
- VEGGIES_MUS,\r
- VEGGIES_MUS,\r
- TOOHOT_MUS,\r
- TOOHOT_MUS,\r
- TOOHOT_MUS,\r
- TOOHOT_MUS,\r
- TOOHOT_MUS,\r
- TOOHOT_MUS,\r
- VEGGIES_MUS,\r
- OASIS_MUS,\r
- -1\r
-#elif defined KEEN5\r
- ROBOROCK_MUS,\r
- WEDNESDY_MUS,\r
- BREATHE_MUS,\r
- SPHEREFUL_MUS,\r
- TIGHTER_MUS,\r
- SPHEREFUL_MUS,\r
- TIGHTER_MUS,\r
- SPHEREFUL_MUS,\r
- TIGHTER_MUS,\r
- SPHEREFUL_MUS,\r
- TIGHTER_MUS,\r
- SNOOPING_MUS,\r
- FEARSOME_MUS,\r
- BAGPIPES_MUS,\r
- FANFARE_MUS,\r
- SKATING_MUS,\r
- ROCK_ME_MUS,\r
- HAVING_T_MUS,\r
- CAMEIN_MUS,\r
- SHIKAIRE_MUS,\r
-#elif defined KEEN6\r
- ALIENATE_MUS,\r
- FASTER_MUS,\r
- BRERTAR_MUS,\r
- MAMSNAKE_MUS,\r
- MAMSNAKE_MUS,\r
- MAMSNAKE_MUS,\r
- METAL_MUS,\r
- TOFUTURE_MUS,\r
- METAL_MUS,\r
- BRERTAR_MUS,\r
- FASTER_MUS,\r
- TOFUTURE_MUS,\r
- BRERTAR_MUS,\r
- SPACFUNK_MUS,\r
- SPACFUNK_MUS,\r
- OMINOUS_MUS,\r
- TOFUTURE_MUS,\r
- WONDER_MUS,\r
- WONDER_MUS,\r
- WONDER_MUS\r
-#endif\r
- };\r
-\r
- Sint16 song;\r
- boolean wasfaded;\r
-\r
- if (num >= ARRAYLENGTH(songs) && num != 0xFFFF)\r
- {\r
- Quit("StartMusic() - bad level number");\r
- }\r
-\r
-#ifdef FIX_MUSIC_MEMORY_ISSUES\r
- StopMusic();\r
-#else\r
- SD_MusicOff();\r
-#endif\r
-\r
-#ifdef KEEN4\r
- if (num == 0xFFFF)\r
- {\r
- song = WONDER_MUS;\r
- }\r
- else\r
- {\r
- song = songs[num];\r
- }\r
-#else\r
- song = songs[num];\r
-#endif\r
-\r
- if (song == -1 || MusicMode != smm_AdLib)\r
- {\r
- return;\r
- }\r
-\r
- MM_BombOnError(false);\r
- CA_CacheAudioChunk(STARTMUSIC+song);\r
- MM_BombOnError(true);\r
- if (mmerror)\r
- {\r
- mmerror = false;\r
- if (!DemoMode)\r
- {\r
- US_CenterWindow(20, 8);\r
- PrintY += 20;\r
- US_CPrint("Insufficient memory\nfor background music!");\r
- VW_UpdateScreen();\r
- wasfaded = screenfaded;\r
- if (wasfaded)\r
- {\r
- VW_SetDefaultColors();\r
- }\r
- IN_ClearKeysDown();\r
- IN_UserInput(3*TickBase, false);\r
- if (wasfaded)\r
- {\r
- VW_FadeOut();\r
- }\r
- }\r
- }\r
- else\r
- {\r
-#ifdef FIX_MUSIC_MEMORY_ISSUES\r
- //The current music should be locked, so the memory manager will not\r
- //mess with it when compressing memory blocks in MM_SortMem().\r
- MM_SetLock(&(memptr)audiosegs[STARTMUSIC+song], true);\r
-#endif\r
- SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC+song]);\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= PlayLoop\r
-=\r
-===================\r
-*/\r
-\r
-void PlayLoop(void)\r
-{\r
- objtype *check;\r
-\r
- StartMusic(gamestate.mapon);\r
- fireheld = pogoheld = upheld = jumpheld = false;\r
- ingame = true;\r
- playstate = ex_stillplaying;\r
- invincible = keenkilled = oldfirecount = 0;\r
-\r
- CenterActor(player);\r
-\r
- if (DemoMode)\r
- {\r
- US_InitRndT(false);\r
- }\r
- else\r
- {\r
- US_InitRndT(true);\r
- }\r
- TimeCount = lasttimecount = tics = 3;\r
-\r
- do\r
- {\r
- PollControls();\r
-\r
-//\r
-// go through state changes and propose movements\r
-//\r
- for (obj=player; obj; obj=obj->next)\r
- {\r
- if (!obj->active && obj->tileright >= originxtile-1\r
- && obj->tileleft <= originxtilemax+1 && obj->tiletop <= originytilemax+1\r
- && obj->tilebottom >= originytile-1)\r
- {\r
- obj->needtoreact = true;\r
- obj->active = ac_yes;\r
- }\r
- if (obj->active)\r
- {\r
- if (obj->tileright < inactivateleft\r
- || obj->tileleft > inactivateright\r
- || obj->tiletop > inactivatebottom\r
- || obj->tilebottom < inactivatetop)\r
- {\r
- if (obj->active == ac_removable)\r
- {\r
- RemoveObj(obj);\r
- continue;\r
- }\r
- else if (obj->active != ac_allways)\r
- {\r
- if (US_RndT() < tics*2 || screenfaded || loadedgame)\r
- {\r
- RF_RemoveSprite(&obj->sprite);\r
- if (obj->obclass == stunnedobj)\r
- RF_RemoveSprite((void **)&obj->temp3);\r
- obj->active = ac_no;\r
- continue;\r
- }\r
- }\r
- }\r
- StateMachine(obj);\r
- }\r
- }\r
-\r
- if (gamestate.riding)\r
- {\r
- HandleRiding(player);\r
- }\r
-\r
-//\r
-// check for and handle collisions between objects\r
-//\r
- for (obj=player; obj; obj=obj->next)\r
- {\r
- if (obj->active)\r
- {\r
- for (check=obj->next; check; check=check->next)\r
- {\r
- if (!check->active)\r
- {\r
- continue;\r
- }\r
- if (obj->right > check->left && obj->left < check->right\r
- && obj->top < check->bottom && obj->bottom > check->top)\r
- {\r
- if (obj->state->contact)\r
- {\r
- obj->state->contact(obj, check);\r
- }\r
- if (check->state->contact)\r
- {\r
- check->state->contact(check, obj);\r
- }\r
- if (obj->obclass == nothing) //useless -- obclass is NOT set to nothing by RemoveObj\r
- {\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
-//\r
-// check intiles\r
-//\r
- if (mapon != 0)\r
- {\r
- CheckInTiles(player);\r
- }\r
- else\r
- {\r
- CheckWorldInTiles(player);\r
- }\r
-\r
-//\r
-// react to whatever happened, and post sprites to the refresh manager\r
-//\r
- for (obj=player; obj; obj=obj->next)\r
- {\r
- if (!obj->active)\r
- {\r
- continue;\r
- }\r
- if (obj->tilebottom >= mapheight-1)\r
- {\r
- if (obj->obclass == keenobj)\r
- {\r
- playstate = ex_died;\r
- }\r
- else\r
- {\r
- RemoveObj(obj);\r
- }\r
- continue;\r
- }\r
- if (obj->needtoreact && obj->state->react)\r
- {\r
- obj->needtoreact = false;\r
- obj->state->react(obj);\r
- }\r
- }\r
-\r
-//\r
-// scroll the screen and update the score box\r
-//\r
-#ifdef KEEN4\r
- if (mapon != 0 && mapon != 17)\r
-#else\r
- if (mapon != 0)\r
-#endif\r
- {\r
- ScrollScreen(player);\r
- }\r
- else\r
- {\r
- WorldScrollScreen(player);\r
- }\r
- UpdateScore(scoreobj);\r
- if (loadedgame)\r
- {\r
- loadedgame = false;\r
- }\r
-\r
-//\r
-// update the screen and calculate the number of tics it took to execute\r
-// this cycle of events (for adaptive timing of next cycle)\r
-//\r
- RF_Refresh();\r
-\r
- if (invincible)\r
- {\r
- if ((invincible = invincible - tics) < 0)\r
- invincible = 0;\r
- }\r
-\r
-#ifdef KEEN6\r
- if (groundslam)\r
- {\r
- if ((groundslam = groundslam - tics) < 0)\r
- groundslam = 0;\r
- }\r
-#endif\r
-//\r
-// single step debug mode\r
-//\r
- if (singlestep)\r
- {\r
- VW_WaitVBL(14); //reduces framerate to 5 fps on VGA or 4.3 fps on EGA cards\r
- lasttimecount = TimeCount;\r
- }\r
-//\r
-// extra VBLs debug mode\r
-//\r
- if (extravbls)\r
- {\r
- VW_WaitVBL(extravbls);\r
- }\r
-\r
-//\r
-// handle user inputs\r
-//\r
- if (DemoMode == demo_Playback)\r
- {\r
- if (!screenfaded && IN_IsUserInput())\r
- {\r
- playstate = ex_completed;\r
- if (LastScan != sc_F1)\r
- {\r
- LastScan = sc_Space;\r
- }\r
- }\r
- }\r
- else if (DemoMode == demo_PlayDone)\r
- {\r
- playstate = ex_completed;\r
- }\r
- else\r
- {\r
- CheckKeys();\r
- }\r
-\r
-//\r
-// E-N-D cheat\r
-//\r
- if (Keyboard[sc_E] && Keyboard[sc_N] && Keyboard[sc_D])\r
- {\r
-#if defined KEEN4\r
- gamestate.rescued = 7;\r
- playstate = ex_rescued;\r
-#elif defined KEEN5\r
- playstate = ex_qedbroke;\r
-#elif defined KEEN6\r
- playstate = ex_molly;\r
-#endif\r
- }\r
-\r
- } while (playstate == ex_stillplaying);\r
-\r
- ingame = false;\r
- StopMusic();\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Sint16 wallclip[8][16] = { // the height of a given point in a tile\r
-{ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256},\r
-{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
-{ 0,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78},\r
-{0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8},\r
-{ 0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0},\r
-{0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08, 0},\r
-{0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x98,0x90,0x88,0x80},\r
-{0xf0,0xe0,0xd0,0xc0,0xb0,0xa0,0x90,0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10, 0}\r
-};\r
-\r
-Sint16 xtry, ytry;\r
-boolean playerkludgeclipcancel;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Uint16 oldtileleft, oldtiletop, oldtileright, oldtilebottom, oldtilemidx;\r
-Uint16 oldleft, oldtop, oldright, oldbottom, oldmidx;\r
-Sint16 leftmoved, topmoved, rightmoved, bottommoved, midxmoved;\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MoveObjVert\r
-=\r
-====================\r
-*/\r
-\r
-void MoveObjVert(objtype *ob, Sint16 ymove)\r
-{\r
- ob->y += ymove;\r
- ob->top += ymove;\r
- ob->bottom += ymove;\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= MoveObjHoriz\r
-=\r
-====================\r
-*/\r
-\r
-void MoveObjHoriz(objtype *ob, Sint16 xmove)\r
-{\r
- //BUG? ob->midx is not adjusted in Keen 4 & 5\r
- ob->x += xmove;\r
- ob->left += xmove;\r
- ob->right += xmove;\r
-#ifdef KEEN6\r
- ob->midx += xmove; //BUG? ob->tilemidx is not updated\r
-#endif\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= PlayerBottomKludge\r
-=\r
-====================\r
-*/\r
-\r
-void PlayerBottomKludge(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 wall, clip, xpix;\r
- Sint16 xmove, ymove;\r
-\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tilebottom-1]/2;\r
- if (ob->xdir == 1)\r
- {\r
- xpix = 0;\r
- map += ob->tileright;\r
- xmove = ob->right - ob->midx;\r
- if (tinf[*(map-mapwidth)+WESTWALL] || tinf[*map+WESTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- xpix = 15;\r
- map += ob->tileleft;\r
- xmove = ob->left - ob->midx;\r
- if (tinf[*(map-mapwidth)+EASTWALL] || tinf[*map+EASTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- if ((_AX = tinf[*map+NORTHWALL]) != 0) // the _AX = ... part is just to recreate the original code's quirks, feel free to delete this\r
- {\r
- return;\r
- }\r
- map += mapwidth;\r
- if ((wall = tinf[*map+NORTHWALL]) != 1)\r
- {\r
- return;\r
- }\r
- clip = wallclip[wall&7][xpix];\r
- ymove = CONVERT_TILE_TO_GLOBAL(ob->tilebottom) + clip - 1 -ob->bottom;\r
- if (ymove <= 0 && ymove >= -bottommoved)\r
- {\r
- ob->hitnorth = wall;\r
- MoveObjVert(ob, ymove);\r
- MoveObjHoriz(ob, xmove);\r
- }\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= PlayerTopKludge\r
-=\r
-====================\r
-*/\r
-\r
-void PlayerTopKludge(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 xpix, wall, clip;\r
- Sint16 move;\r
-\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tiletop+1]/2;\r
- if (ob->xdir == 1)\r
- {\r
- xpix = 0;\r
- map += ob->tileright;\r
- if (tinf[*(map+mapwidth)+WESTWALL] || tinf[*(map+2*mapwidth)+WESTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- xpix = 15;\r
- map += ob->tileleft;\r
- if (tinf[*(map+mapwidth)+EASTWALL] || tinf[*(map+2*mapwidth)+EASTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- if ((_AX = tinf[*map+SOUTHWALL]) != 0) // the _AX = ... part is just to recreate the original code's quirks, feel free to delete this\r
- {\r
- return;\r
- }\r
- map -= mapwidth;\r
- if ((wall = tinf[*map+SOUTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall&7][xpix];\r
- move = CONVERT_TILE_TO_GLOBAL(ob->tiletop+1) - clip - ob->top;\r
- if (move >= 0 && move <= -topmoved)\r
- {\r
- ob->hitsouth = wall;\r
- MoveObjVert(ob, move);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= ClipToEnds\r
-=\r
-===========================\r
-*/\r
-\r
-void ClipToEnds(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 wall, y, clip;\r
- Sint16 totalmove, maxmove, move;\r
- Uint16 midxpix;\r
- \r
- midxpix = CONVERT_GLOBAL_TO_PIXEL(ob->midx & 0xF0);\r
- maxmove = -abs(midxmoved)-bottommoved-16;\r
- map = (Uint16 far *)mapsegs[1] + (mapbwidthtable-1)[oldtilebottom]/2 + ob->tilemidx;\r
- for (y=oldtilebottom-1; y <= ob->tilebottom; y++,map+=mapwidth)\r
- {\r
- if ((wall = tinf[*map + NORTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall&7][midxpix];\r
- move = (CONVERT_TILE_TO_GLOBAL(y) + clip)-1-ob->bottom;\r
- if (move < 0 && move >= maxmove)\r
- {\r
- ob->hitnorth = wall;\r
- MoveObjVert(ob, move);\r
- return;\r
- }\r
- }\r
- }\r
- maxmove = abs(midxmoved)-topmoved+16;\r
- map = (Uint16 far *)mapsegs[1] + (mapbwidthtable+1)[oldtiletop]/2 + ob->tilemidx;\r
- for (y=oldtiletop+1; y >= ob->tiletop; y--,map-=mapwidth) // BUG: unsigned comparison - loop never ends if ob->tiletop is 0\r
- {\r
- if ((wall = tinf[*map + SOUTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall&7][midxpix];\r
- move = CONVERT_TILE_TO_GLOBAL(y+1) - clip - ob->top;\r
- if (move > 0 && move <= maxmove)\r
- {\r
- totalmove = ytry+move;\r
- if (totalmove < 0x100 && totalmove > -0x100)\r
- {\r
- ob->hitsouth = wall;\r
- MoveObjVert(ob, move);\r
- //BUG? no return here\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= ClipToSides\r
-=\r
-===========================\r
-*/\r
-\r
-void ClipToSides(objtype *ob)\r
-{\r
- Sint16 move, y, top, bottom;\r
- Uint16 far *map;\r
- \r
- top = ob->tiletop;\r
- if (ob->hitsouth > 1)\r
- {\r
- top++;\r
- }\r
- bottom = ob->tilebottom;\r
- if (ob->hitnorth > 1)\r
- {\r
- bottom--;\r
- }\r
- for (y=top; y<=bottom; y++)\r
- {\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[y]/2 + ob->tileleft;\r
- if ((ob->hiteast = tinf[*map+EASTWALL]) != 0)\r
- {\r
- move = CONVERT_TILE_TO_GLOBAL(ob->tileleft+1) - ob->left;\r
- MoveObjHoriz(ob, move);\r
- return;\r
- }\r
- }\r
- for (y=top; y<=bottom; y++)\r
- {\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[y]/2 + ob->tileright;\r
- if ((ob->hitwest = tinf[*map+WESTWALL]) != 0)\r
- {\r
- move = (CONVERT_TILE_TO_GLOBAL(ob->tileright)-1)-ob->right;\r
- MoveObjHoriz(ob, move);\r
- return;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= CheckPosition\r
-=\r
-===========================\r
-*/\r
-\r
-boolean CheckPosition(objtype *ob)\r
-{\r
-#ifdef KEEN6Ev15\r
- // This version is pretty much a compiler-optimized version of the other\r
- // version below, but I simply could not get the compiler to optimize it\r
- // in exactly the same way.\r
-\r
- Uint16 tile, x, tileright;\r
- Uint16 far *map;\r
- Uint16 rowdiff;\r
- Uint16 tileleft, y, tilebottom;\r
- \r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft;\r
- rowdiff = mapwidth-(ob->tileright-ob->tileleft+1);\r
-\r
- y = ob->tiletop;\r
- tileleft = ob->tileleft;\r
- tileright = _AX = ob->tileright;\r
- tilebottom = ob->tilebottom;\r
-\r
- for (; tilebottom>=y; y++,map+=rowdiff)\r
- {\r
- for (x=tileleft; tileright>=x; x++)\r
- {\r
- tile = *(map++);\r
- if (tinf[tile+NORTHWALL] || tinf[tile+EASTWALL] || tinf[tile+SOUTHWALL] || tinf[tile+WESTWALL])\r
- {\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
-#else\r
- Uint16 tile, x, y;\r
- Uint16 far *map;\r
- Uint16 rowdiff;\r
- \r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft;\r
- rowdiff = mapwidth-(ob->tileright-ob->tileleft+1);\r
- for (y=ob->tiletop; y<=ob->tilebottom; y++,map+=rowdiff)\r
- {\r
- for (x=ob->tileleft; x<=ob->tileright; x++)\r
- {\r
- tile = *(map++);\r
- if (tinf[tile+NORTHWALL] || tinf[tile+EASTWALL] || tinf[tile+SOUTHWALL] || tinf[tile+WESTWALL])\r
- {\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
-#endif\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= StatePositionOk\r
-=\r
-===========================\r
-*/\r
-\r
-boolean StatePositionOk(objtype *ob, statetype *state)\r
-{\r
- spritetabletype far *shape;\r
-\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
- return CheckPosition(ob);\r
-}\r
-\r
-#ifdef KEEN5\r
-/*\r
-===========================\r
-=\r
-= CalcBounds\r
-=\r
-===========================\r
-*/\r
-\r
-void CalcBounds(objtype *ob) //not present in Keen 4 & 6\r
-{\r
- spritetabletype far *shape;\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-================\r
-=\r
-= ClipToWalls\r
-=\r
-= Moves the current object xtry/ytry units, clipping to walls\r
-=\r
-================\r
-*/\r
-\r
-void ClipToWalls(objtype *ob)\r
-{\r
- Uint16 oldx, oldy;\r
-#ifdef KEEN6\r
- Uint16 y;\r
-#endif\r
- spritetabletype far *shape;\r
- boolean pushed;\r
-\r
- oldx = ob->x;\r
- oldy = ob->y;\r
- pushed = false;\r
-\r
-//\r
-// make sure it stays in contact with a 45 degree slope\r
-//\r
- if (ob->state->pushtofloor)\r
- {\r
- if (ob->hitnorth == 25)\r
- {\r
- ytry = 145;\r
- }\r
- else\r
- {\r
- if (xtry > 0)\r
- {\r
- ytry = xtry+16;\r
- }\r
- else\r
- {\r
- ytry = -xtry+16;\r
- }\r
- pushed = true;\r
- }\r
- }\r
-\r
-//\r
-// move the shape\r
-//\r
- if (xtry > 239)\r
- {\r
- xtry = 239;\r
- }\r
- else if (xtry < -239)\r
- {\r
- xtry = -239;\r
- }\r
- if (ytry > 255) // +16 for push to floor\r
- {\r
- ytry = 255;\r
- }\r
- else if (ytry < -239)\r
- {\r
- ytry = -239;\r
- }\r
-\r
- ob->x += xtry;\r
- ob->y += ytry;\r
-\r
- ob->needtoreact = true;\r
-\r
- if (!ob->shapenum) // can't get a hit rect with no shape!\r
- {\r
- return;\r
- }\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
-\r
- oldtileright = ob->tileright;\r
- oldtiletop = ob->tiletop;\r
- oldtileleft = ob->tileleft;\r
- oldtilebottom = ob->tilebottom;\r
- oldtilemidx = ob->tilemidx;\r
-\r
- oldright = ob->right;\r
- oldtop = ob->top;\r
- oldleft = ob->left;\r
- oldbottom = ob->bottom;\r
- oldmidx = ob->midx;\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
-\r
- ob->hitnorth=ob->hiteast=ob->hitsouth=ob->hitwest=0;\r
-\r
- if (ob->needtoclip)\r
- {\r
- leftmoved = ob->left - oldleft;\r
- rightmoved = ob->right - oldright;\r
- topmoved = ob->top - oldtop;\r
- bottommoved = ob->bottom - oldbottom;\r
- midxmoved = ob->midx - oldmidx;\r
-\r
- //\r
- // clip it\r
- //\r
- ClipToEnds(ob);\r
-\r
- if (ob == player && !playerkludgeclipcancel) // zero tolerance near the edge when player gets pushed!\r
- {\r
- if (!ob->hitnorth && bottommoved > 0)\r
- {\r
- PlayerBottomKludge(ob);\r
- }\r
- if (!ob->hitsouth && topmoved < 0)\r
- {\r
- PlayerTopKludge(ob);\r
- }\r
- }\r
- ClipToSides(ob);\r
-\r
-#ifdef KEEN6\r
- //\r
- // special hack to prevent player from getting stuck on slopes?\r
- //\r
- if (ob == player && (ob->hitnorth & 7) > 1 && (ob->hiteast || ob->hitwest))\r
- {\r
- Uint16 far *map;\r
- Uint16 pixx, clip, move;\r
- Uint16 wall;\r
-\r
- pixx = CONVERT_GLOBAL_TO_PIXEL(ob->midx & (15*PIXGLOBAL));\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[oldtilebottom]/2 + ob->tilemidx;\r
-\r
- for (y=oldtilebottom; ob->tilebottom+1 >= y; y++, map+=mapwidth)\r
- {\r
- if ((wall = tinf[*map + NORTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall & 7][pixx];\r
- move = CONVERT_TILE_TO_GLOBAL(y) + clip - 1 - ob->bottom;\r
- ob->hitnorth = wall;\r
- MoveObjVert(ob, move);\r
- return;\r
- }\r
- }\r
- }\r
-#endif\r
- }\r
- if (pushed && !ob->hitnorth)\r
- {\r
- ob->y = oldy;\r
- ob->x = oldx + xtry;\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
- }\r
-\r
- ob->xmove = ob->xmove + (ob->x - oldx);\r
- ob->ymove = ob->ymove + (ob->y - oldy);\r
-}\r
-\r
-/*\r
-================\r
-=\r
-= FullClipToWalls\r
-=\r
-= Moves the current object xtry/ytry units, clipping to walls\r
-=\r
-================\r
-*/\r
-\r
-void FullClipToWalls(objtype *ob)\r
-{\r
- Uint16 oldx, oldy, w, h;\r
- spritetabletype far *shape;\r
-\r
- oldx = ob->x;\r
- oldy = ob->y;\r
-\r
-//\r
-// move the shape\r
-//\r
- if (xtry > 239)\r
- {\r
- xtry = 239;\r
- }\r
- else if (xtry < -239)\r
- {\r
- xtry = -239;\r
- }\r
- if (ytry > 239)\r
- {\r
- ytry = 239;\r
- }\r
- else if (ytry < -239)\r
- {\r
- ytry = -239;\r
- }\r
-\r
- ob->x += xtry;\r
- ob->y += ytry;\r
-\r
- ob->needtoreact = true;\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
-\r
- switch (ob->obclass)\r
- {\r
-#if defined KEEN4\r
- case keenobj:\r
- w = 40*PIXGLOBAL;\r
- h = 24*PIXGLOBAL;\r
- break;\r
- case eggbirdobj:\r
- w = 64*PIXGLOBAL;\r
- h = 32*PIXGLOBAL;\r
- break;\r
- case dopefishobj:\r
- w = 88*PIXGLOBAL;\r
- h = 64*PIXGLOBAL;\r
- break;\r
- case schoolfishobj:\r
- w = 16*PIXGLOBAL;\r
- h = 8*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN5\r
- case slicestarobj:\r
- case spherefulobj:\r
- w = h = 32*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN6\r
- case blorbobj:\r
- w = h = 32*PIXGLOBAL;\r
- break;\r
-#endif\r
-\r
- default:\r
- Quit("FullClipToWalls: Bad obclass");\r
- break;\r
- }\r
-\r
- ob->right = ob->x + w;\r
- ob->left = ob->x;\r
- ob->top = ob->y;\r
- ob->bottom = ob->y + h;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
-\r
- ob->hitnorth=ob->hiteast=ob->hitsouth=ob->hitwest=0;\r
-\r
-//\r
-// clip it\r
-//\r
- if (!CheckPosition(ob))\r
- {\r
- MoveObjHoriz(ob, -xtry); //undo x movement\r
- if (CheckPosition(ob))\r
- {\r
- if (xtry > 0)\r
- {\r
- ob->hitwest = 1;\r
- }\r
- else\r
- {\r
- ob->hiteast = 1;\r
- }\r
- }\r
- else\r
- {\r
- if (ytry > 0)\r
- {\r
- ob->hitnorth = 1;\r
- }\r
- else\r
- {\r
- ob->hitsouth = 1;\r
- }\r
- MoveObjHoriz(ob, xtry); //redo x movement\r
- MoveObjVert(ob, -ytry); //undo y movement\r
- if (!CheckPosition(ob))\r
- {\r
- MoveObjHoriz(ob, -xtry); //undo x movement\r
- if (xtry > 0)\r
- {\r
- ob->hitwest = 1;\r
- }\r
- else\r
- {\r
- ob->hiteast = 1;\r
- }\r
- }\r
- }\r
- }\r
-\r
- ob->xmove = ob->xmove + (ob->x - oldx);\r
- ob->ymove = ob->ymove + (ob->y - oldy);\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-}\r
-\r
-/*\r
-================\r
-=\r
-= PushObj\r
-=\r
-= Moves the current object xtry/ytry units, clipping to walls\r
-=\r
-================\r
-*/\r
-\r
-void PushObj(objtype *ob)\r
-{\r
- Uint16 oldx, oldy;\r
- spritetabletype far *shape;\r
- \r
- oldx = ob->x;\r
- oldy = ob->y;\r
-\r
-//\r
-// move the shape\r
-//\r
- ob->x += xtry;\r
- ob->y += ytry;\r
-\r
- ob->needtoreact = true;\r
-\r
- if (!ob->shapenum) // can't get a hit rect with no shape!\r
- {\r
- return;\r
- }\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
-\r
- oldtileright = ob->tileright;\r
- oldtiletop = ob->tiletop;\r
- oldtileleft = ob->tileleft;\r
- oldtilebottom = ob->tilebottom;\r
- oldtilemidx = ob->tilemidx;\r
-\r
- oldright = ob->right;\r
- oldtop = ob->top;\r
- oldleft = ob->left;\r
- oldbottom = ob->bottom;\r
- oldmidx = ob->midx;\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
-\r
- if (ob->needtoclip)\r
- {\r
- leftmoved = ob->left - oldleft;\r
- rightmoved = ob->right - oldright;\r
- topmoved = ob->top - oldtop;\r
- bottommoved = ob->bottom - oldbottom;\r
- midxmoved = ob->midx - oldmidx;\r
-\r
- ClipToEnds(ob);\r
- ClipToSides(ob);\r
- }\r
-\r
- ob->xmove = ob->xmove + (ob->x - oldx);\r
- ob->ymove = ob->ymove + (ob->y - oldy);\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= ClipToSpriteSide\r
-=\r
-= Clips push to solid\r
-=\r
-==================\r
-*/\r
-\r
-void ClipToSpriteSide(objtype *push, objtype *solid)\r
-{\r
- Sint16 xmove, leftinto, rightinto;\r
-\r
- //\r
- // amount the push shape can be pushed\r
- //\r
- xmove = solid->xmove - push->xmove;\r
-\r
- //\r
- // amount it is inside\r
- //\r
- leftinto = solid->right - push->left;\r
- rightinto = push->right - solid->left;\r
-\r
- if (leftinto > 0 && leftinto <= xmove)\r
- {\r
- xtry = leftinto;\r
- if (push->state->pushtofloor)\r
- {\r
- ytry = leftinto+16;\r
- }\r
- ClipToWalls(push);\r
- push->hiteast = 1;\r
- }\r
- else if (rightinto > 0 && rightinto <= -xmove)\r
- {\r
- xtry = -rightinto;\r
- if (push->state->pushtofloor)\r
- {\r
- ytry = rightinto+16;\r
- }\r
- ClipToWalls(push);\r
- push->hitwest = 1;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= ClipToSpriteTop\r
-=\r
-= Clips push to solid\r
-=\r
-==================\r
-*/\r
-\r
-void ClipToSpriteTop(objtype *push, objtype *solid)\r
-{\r
- Sint16 temp, ymove, bottominto;\r
-\r
- //\r
- // amount the push shape can be pushed\r
- //\r
- ymove = push->ymove - solid->ymove;\r
-\r
- //\r
- // amount it is inside\r
- //\r
- bottominto = push->bottom - solid->top;\r
-\r
- if (bottominto >= 0 && bottominto <= ymove)\r
- {\r
- if (push == player)\r
- {\r
- gamestate.riding = solid;\r
- }\r
- ytry = -bottominto;\r
- temp = push->state->pushtofloor;\r
- push->state->pushtofloor = false;\r
- ClipToWalls(push);\r
- push->state->pushtofloor = temp;\r
- if (!push->hitsouth)\r
- {\r
- push->hitnorth = 25;\r
- }\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= ClipToSprite\r
-=\r
-= Clips push to solid\r
-=\r
-==================\r
-*/\r
-\r
-void ClipToSprite(objtype *push, objtype *solid, boolean squish)\r
-{\r
- Sint16 xmove, ymove, leftinto, rightinto, topinto, bottominto;\r
- \r
- xmove = solid->xmove - push->xmove;\r
- xtry = ytry = 0;\r
-\r
- //\r
- // left / right\r
- //\r
- leftinto = solid->right - push->left;\r
- rightinto = push->right - solid->left;\r
-\r
- if (leftinto > 0 && xmove+1 >= leftinto)\r
- {\r
- xtry = leftinto;\r
- push->xspeed = 0;\r
- PushObj(push);\r
- if (squish && push->hitwest)\r
- {\r
- KillKeen();\r
- }\r
- push->hiteast = 1;\r
- return;\r
- }\r
- else if (rightinto > 0 && -xmove+1 >= rightinto)\r
- {\r
- xtry = -rightinto;\r
- push->xspeed = 0;\r
- PushObj(push);\r
- if (squish && push->hiteast)\r
- {\r
- KillKeen();\r
- }\r
- push->hitwest = 1;\r
- return;\r
- }\r
-\r
- //\r
- // top / bottom\r
- //\r
- ymove = push->ymove - solid->ymove;\r
- topinto = solid->bottom - push->top;\r
- bottominto = push->bottom - solid->top;\r
- if (bottominto >= 0 && bottominto <= ymove)\r
- {\r
- if (push == player)\r
- {\r
- gamestate.riding = solid;\r
- }\r
- ytry = -bottominto;\r
- PushObj(push);\r
- if (squish && push->hitsouth)\r
- {\r
- KillKeen();\r
- }\r
- if (!push->hitsouth)\r
- {\r
- push->hitnorth = 25;\r
- }\r
- return;\r
- }\r
- else if (topinto >= 0 && topinto <= ymove) // BUG: should be 'topinto <= -ymove'\r
- {\r
- ytry = topinto;\r
- ClipToWalls(push);\r
- if (squish && push->hitnorth)\r
- {\r
- KillKeen();\r
- }\r
- push->hitsouth = 25;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= DoActor\r
-=\r
-= Moves an actor in its current state by a given number of tics.\r
-= If that time takes it into the next state, it changes the state\r
-= and returns the number of excess tics after the state change\r
-=\r
-==================\r
-*/\r
-\r
-Sint16 DoActor(objtype *ob, Sint16 numtics)\r
-{\r
- Sint16 ticcount, usedtics, excesstics;\r
- statetype *state;\r
- \r
- state = ob->state;\r
-\r
- if (state->progress == think)\r
- {\r
- if (state->think)\r
- {\r
- if (ob->nothink)\r
- {\r
- ob->nothink--;\r
- }\r
- else\r
- {\r
- state->think(ob);\r
- }\r
- }\r
- return 0;\r
- }\r
-\r
- ticcount = ob->ticcount + numtics;\r
-\r
- if (state->tictime > ticcount || state->tictime == 0)\r
- {\r
- ob->ticcount = ticcount;\r
- if (state->progress == slide || state->progress == slidethink)\r
- {\r
- if (ob->xdir)\r
- {\r
- xtry += ob->xdir == 1? numtics*state->xmove : -numtics*state->xmove;\r
- }\r
- if (ob->ydir)\r
- {\r
- ytry += ob->ydir == 1? numtics*state->ymove : -numtics*state->ymove;\r
- }\r
- }\r
- if ((state->progress == slidethink || state->progress == stepthink) && state->think)\r
- {\r
- if (ob->nothink)\r
- {\r
- ob->nothink--;\r
- }\r
- else\r
- {\r
- state->think(ob);\r
- }\r
- }\r
- return 0;\r
- }\r
- else\r
- {\r
- usedtics = state->tictime - ob->ticcount;\r
- excesstics = ticcount - state->tictime;\r
- ob->ticcount = 0;\r
- if (state->progress == slide || state->progress == slidethink)\r
- {\r
- if (ob->xdir)\r
- {\r
- xtry += ob->xdir == 1? usedtics*state->xmove : -usedtics*state->xmove;\r
- }\r
- if (ob->ydir)\r
- {\r
- ytry += ob->ydir == 1? usedtics*state->ymove : -usedtics*state->ymove;\r
- }\r
- }\r
- else\r
- {\r
- if (ob->xdir)\r
- {\r
- xtry += ob->xdir == 1? state->xmove : -state->xmove;\r
- }\r
- if (ob->ydir)\r
- {\r
- ytry += ob->ydir == 1? state->ymove : -state->ymove;\r
- }\r
- }\r
-\r
- if (state->think)\r
- {\r
- if (ob->nothink)\r
- {\r
- ob->nothink--;\r
- }\r
- else\r
- {\r
- state->think(ob);\r
- }\r
- }\r
-\r
- if (state == ob->state)\r
- {\r
- ob->state = state->nextstate; // go to next state\r
- }\r
- else if (!ob->state)\r
- {\r
- return 0; // object removed itself\r
- }\r
- return excesstics;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= StateMachine\r
-=\r
-= Change state and give directions\r
-=\r
-====================\r
-*/\r
-\r
-void StateMachine(objtype *ob)\r
-{\r
- Sint16 excesstics, oldshapenum;\r
- statetype *state;\r
- \r
- ob->xmove=ob->ymove=xtry=ytry=0;\r
- oldshapenum = ob->shapenum;\r
-\r
- state = ob->state;\r
-\r
- excesstics = DoActor(ob, tics);\r
- if (ob->state != state)\r
- {\r
- ob->ticcount = 0; // start the new state at 0, then use excess\r
- state = ob->state;\r
- }\r
-\r
- while (excesstics)\r
- {\r
- //\r
- // passed through to next state\r
- //\r
- if (!state->skippable && state->tictime <= excesstics)\r
- {\r
- excesstics = DoActor(ob, state->tictime-1);\r
- }\r
- else\r
- {\r
- excesstics = DoActor(ob, excesstics);\r
- }\r
- if (ob->state != state)\r
- {\r
- ob->ticcount = 0; // start the new state at 0, then use excess\r
- state = ob->state;\r
- }\r
- }\r
-\r
- if (!state) // object removed itself\r
- {\r
- RemoveObj(ob);\r
- return;\r
- }\r
-\r
- //\r
- // if state->rightshapenum == NULL, the state does not have a standard\r
- // shape (the think routine should have set it)\r
- //\r
- if (state->rightshapenum)\r
- {\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- }\r
- if ((Sint16)ob->shapenum == -1)\r
- {\r
- ob->shapenum = 0; // make it invisable this time\r
- }\r
-\r
- if (xtry || ytry || ob->shapenum != oldshapenum || ob->hitnorth == 25)\r
- {\r
- //\r
- // actor moved or changed shape\r
- // make sure the movement is within limits (one tile)\r
- //\r
- if (ob->needtoclip == cl_fullclip)\r
- {\r
- FullClipToWalls(ob);\r
- }\r
- else\r
- {\r
- ClipToWalls(ob);\r
- }\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= NewState\r
-=\r
-====================\r
-*/\r
-\r
-void NewState(objtype *ob, statetype *state)\r
-{\r
- Sint16 temp;\r
- \r
- ob->state = state;\r
-\r
- if (state->rightshapenum)\r
- {\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- }\r
-\r
- if ((Sint16)ob->shapenum == -1)\r
- {\r
- ob->shapenum = 0;\r
- }\r
-\r
- temp = ob->needtoclip;\r
- ob->needtoclip = cl_noclip;\r
-\r
- xtry = ytry = 0; // no movement\r
- ClipToWalls(ob); // just calculate values\r
-\r
- ob->needtoclip = temp;\r
-\r
- if (ob->needtoclip == cl_fullclip)\r
- {\r
- FullClipToWalls(ob);\r
- }\r
- else if (ob->needtoclip == cl_midclip)\r
- {\r
- ClipToWalls(ob);\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= ChangeState\r
-=\r
-====================\r
-*/\r
-\r
-void ChangeState(objtype *ob, statetype *state)\r
-{\r
- ob->state = state;\r
- ob->ticcount = 0;\r
- if (state->rightshapenum)\r
- {\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- }\r
-\r
- if ((Sint16)ob->shapenum == -1)\r
- {\r
- ob->shapenum = 0;\r
- }\r
-\r
- ob->needtoreact = true; // it will need to be redrawn this frame\r
-\r
- xtry = ytry = 0; // no movement\r
-\r
- if (ob->hitnorth != 25)\r
- {\r
- ClipToWalls(ob);\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= OnScreen\r
-=\r
-====================\r
-*/\r
-\r
-boolean OnScreen(objtype *ob)\r
-{\r
- if (ob->tileright < originxtile || ob->tilebottom < originytile\r
- || ob->tileleft > originxtilemax || ob->tiletop > originytilemax)\r
- {\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= DoGravity\r
-=\r
-====================\r
-*/\r
-\r
-void DoGravity(objtype *ob)\r
-{\r
- Sint32 i;\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i = lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i&1)\r
- {\r
- if (ob->yspeed < 0 && ob->yspeed >= -4)\r
- {\r
- ytry += ob->yspeed;\r
- ob->yspeed = 0;\r
- return;\r
- }\r
- ob->yspeed += 4;\r
- if (ob->yspeed > 70)\r
- {\r
- ob->yspeed = 70;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= DoWeakGravity\r
-=\r
-====================\r
-*/\r
-\r
-void DoWeakGravity(objtype *ob)\r
-{\r
- Sint32 i;\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i = lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i&1)\r
- {\r
- if (ob->yspeed < 0 && ob->yspeed >= -3)\r
- {\r
- ytry += ob->yspeed;\r
- ob->yspeed = 0;\r
- return;\r
- }\r
- ob->yspeed += 3;\r
- if (ob->yspeed > 70)\r
- {\r
- ob->yspeed = 70;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= DoTinyGravity\r
-=\r
-====================\r
-*/\r
-\r
-void DoTinyGravity(objtype *ob)\r
-{\r
- Sint32 i;\r
-//\r
-// only accelerate every 4 tics, because of limited precision\r
-//\r
- for (i = lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (!i & 3) //BUG: this is equal to ((!i) & 3), not (!(i & 3))\r
- {\r
- ob->yspeed++;\r
- if (ob->yspeed > 70)\r
- {\r
- ob->yspeed = 70;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= AccelerateX\r
-=\r
-===============\r
-*/\r
-\r
-void AccelerateX(objtype *ob, Sint16 dir, Sint16 maxspeed)\r
-{\r
- Sint32 i;\r
- Uint16 oldsign;\r
- \r
- oldsign = ob->xspeed & 0x8000;\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->xspeed += dir;\r
- if ((ob->xspeed & 0x8000) != oldsign)\r
- {\r
- oldsign = ob->xspeed & 0x8000;\r
- ob->xdir = oldsign? -1 : 1;\r
- }\r
- if (ob->xspeed > maxspeed)\r
- {\r
- ob->xspeed = maxspeed;\r
- }\r
- else if (ob->xspeed < -maxspeed)\r
- {\r
- ob->xspeed = -maxspeed;\r
- }\r
- }\r
- xtry += ob->xspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= AccelerateXv\r
-=\r
-= Doesn't change object's xdir\r
-=\r
-===============\r
-*/\r
-\r
-void AccelerateXv(objtype *ob, Sint16 dir, Sint16 maxspeed)\r
-{\r
- Sint32 i;\r
-\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->xspeed += dir;\r
- if (ob->xspeed > maxspeed)\r
- {\r
- ob->xspeed = maxspeed;\r
- }\r
- else if (ob->xspeed < -maxspeed)\r
- {\r
- ob->xspeed = -maxspeed;\r
- }\r
- }\r
- xtry += ob->xspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= AccelerateY\r
-=\r
-===============\r
-*/\r
-\r
-void AccelerateY(objtype *ob, Sint16 dir, Sint16 maxspeed)\r
-{\r
- Sint32 i;\r
-\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->yspeed += dir;\r
- if (ob->yspeed > maxspeed)\r
- {\r
- ob->yspeed = maxspeed;\r
- }\r
- else if (ob->yspeed < -maxspeed)\r
- {\r
- ob->yspeed = -maxspeed;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= FrictionX\r
-=\r
-===============\r
-*/\r
-\r
-void FrictionX(objtype *ob)\r
-{\r
- Sint16 friction, oldsign;\r
- Sint32 i;\r
-\r
- oldsign = ob->xspeed & 0x8000;\r
- if (ob->xspeed > 0)\r
- {\r
- friction = -1;\r
- }\r
- else if (ob->xspeed < 0)\r
- {\r
- friction = 1;\r
- }\r
- else\r
- {\r
- friction = 0;\r
- }\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
-\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->xspeed += friction;\r
- if ((ob->xspeed & 0x8000) != oldsign)\r
- {\r
- ob->xspeed = 0;\r
- }\r
- }\r
- xtry += ob->xspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= FrictionY\r
-=\r
-===============\r
-*/\r
-\r
-void FrictionY(objtype *ob)\r
-{\r
- Sint16 friction, oldsign;\r
- Sint32 i;\r
-\r
- if (ob->yspeed > 0)\r
- {\r
- friction = -1;\r
- }\r
- else if (ob->yspeed < 0)\r
- {\r
- friction = 1;\r
- }\r
- else\r
- {\r
- friction = 0;\r
- }\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->yspeed += friction;\r
- if ((ob->yspeed & 0x8000) != oldsign) //BUG: oldsign is not initialized!\r
- {\r
- ob->yspeed = 0;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= StunObj\r
-=\r
-===============\r
-*/\r
-\r
-void StunObj(objtype *ob, objtype *shot, statetype *stunstate)\r
-{\r
- ExplodeShot(shot);\r
- ob->temp1 = ob->temp2 = ob->temp3 = 0; // Note: ob->nothink should also be set to 0\r
- ob->temp4 = ob->obclass;\r
- ChangeState(ob, stunstate);\r
- ob->obclass = stunnedobj;\r
-#ifndef KEEN4\r
- ob->yspeed -= 24;\r
- if (ob->yspeed < -48)\r
- ob->yspeed = -48;\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= T_Projectile\r
-=\r
-===============\r
-*/\r
-\r
-void T_Projectile(objtype *ob)\r
-{\r
- DoGravity(ob);\r
- xtry = ob->xspeed*tics;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_WeakProjectile\r
-=\r
-===============\r
-*/\r
-\r
-void T_WeakProjectile(objtype *ob)\r
-{\r
- DoWeakGravity(ob);\r
- xtry = ob->xspeed*tics;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Velocity\r
-=\r
-===============\r
-*/\r
-\r
-void T_Velocity(objtype *ob)\r
-{\r
- xtry = ob->xspeed*tics;\r
- ytry = ob->yspeed*tics;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= SetReactThink\r
-=\r
-===============\r
-*/\r
-\r
-void SetReactThink(objtype *ob)\r
-{\r
- ob->needtoreact = true;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Stunned\r
-=\r
-===============\r
-*/\r
-\r
-void T_Stunned(objtype *ob)\r
-{\r
- ob->temp1 = 0;\r
- ob->needtoreact = true;\r
- if (++ob->temp2 == 3)\r
- ob->temp2 = 0;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= C_Lethal\r
-=\r
-===============\r
-*/\r
-\r
-void C_Lethal(objtype *ob, objtype *hit)\r
-{\r
- ob++; // shut up compiler\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_Draw\r
-=\r
-===============\r
-*/\r
-\r
-void R_Draw(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_Walk\r
-=\r
-===============\r
-*/\r
-\r
-void R_Walk(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_WalkNormal\r
-=\r
-= Actor will not walk onto tiles with special (e.g. deadly) north walls\r
-=\r
-===============\r
-*/\r
-\r
-void R_WalkNormal(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth || (ob->hitnorth & ~7))\r
- {\r
- ob->x -= ob->xmove*2;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= BadState\r
-=\r
-===============\r
-*/\r
-\r
-void BadState(void)\r
-{\r
- Quit("Object with bad state!");\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_Stunned\r
-=\r
-===============\r
-*/\r
-\r
-void R_Stunned(objtype *ob)\r
-{\r
- Sint16 starx, stary;\r
-\r
- if (ob->hitwest || ob->hiteast)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->xspeed = ob->yspeed = 0;\r
- if (ob->state->nextstate)\r
- ChangeState(ob, ob->state->nextstate);\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- starx = stary = 0;\r
- switch (ob->temp4)\r
- {\r
-#if defined KEEN4\r
- case mimrockobj:\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case eggobj:\r
- starx = 8*PIXGLOBAL;\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case treasureeaterobj:\r
- starx = 8*PIXGLOBAL;\r
- break;\r
- case bounderobj:\r
- starx = 4*PIXGLOBAL;\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case wormouthobj:\r
- starx = 4*PIXGLOBAL;\r
- stary = -350; // -21.875 pixels (this one is a bit strange)\r
- break;\r
- case lickobj:\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case inchwormobj:\r
- starx = -4*PIXGLOBAL;\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case slugobj:\r
- stary = -8*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN5\r
- case sparkyobj:\r
- starx += 4*PIXGLOBAL;\r
- break;\r
- case amptonobj:\r
- stary -= 8*PIXGLOBAL;\r
- asm jmp done; // just to recreate the original code's quirks, feel free to delete this\r
- break;\r
- case scottieobj:\r
- stary -= 8*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN6\r
- case blooguardobj:\r
- starx = 16*PIXGLOBAL;\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case flectobj:\r
- starx = 4*PIXGLOBAL;\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case bloogobj:\r
- case nospikeobj:\r
- starx = 8*PIXGLOBAL;\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case bloogletobj:\r
- case babobbaobj:\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case fleexobj:\r
- starx = 16*PIXGLOBAL;\r
- stary = 8*PIXGLOBAL;\r
- break;\r
- case ceilickobj:\r
- stary = 12*PIXGLOBAL;\r
- break;\r
- default:\r
- Quit("No star spec for object!");\r
-#endif\r
- }\r
-done:\r
-\r
- ob->temp1 = ob->temp1 + tics;\r
- if (ob->temp1 > 10)\r
- {\r
- ob->temp1 -= 10;\r
- if (++ob->temp2 == 3)\r
- ob->temp2 = 0;\r
- }\r
-\r
- RF_PlaceSprite((void **)&ob->temp3, ob->x+starx, ob->y+stary, ob->temp2+STUNSTARS1SPR, spritedraw, 3);\r
-}\r
-\r
-//==========================================================================\r
-\r
-statetype sc_deadstate = {0, 0, think, false, false, 0, 0, 0, NULL, NULL, NULL, NULL};\r
-#pragma warn -sus //BadState is not a valid think/contact/react function. Nobody cares.\r
-statetype sc_badstate = {0, 0, think, false, false, 0, 0, 0, &BadState, &BadState, &BadState, NULL};\r
-#pragma warn +sus
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Wolfenstein 3-D Source Code\r
- * Copyright (C) 1992 id Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
-TEXT FORMATTING COMMANDS\r
-------------------------\r
-^C<hex digit> Change text color\r
-^E[enter] End of layout (all pages)\r
-^G<y>,<x>,<pic>[enter] Draw a graphic and push margins\r
-^P[enter] start new page, must be the first chars in a layout\r
-^L<x>,<y>[ENTER] Locate to a specific spot, x in pixels, y in lines\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-#ifdef KEEN5\r
-#define BACKCOLOR 2 // CGA magenta\r
-#else\r
-#define BACKCOLOR WHITE\r
-#endif\r
-#else\r
-#define BACKCOLOR RED\r
-#endif\r
-\r
-#define WORDLIMIT 80\r
-#define FONTHEIGHT 10\r
-#define TOPMARGIN 10\r
-#define BOTTOMMARGIN 10\r
-#define LEFTMARGIN 10\r
-#define RIGHTMARGIN 10\r
-#define PICMARGIN 8\r
-#define SPACEWIDTH 7\r
-#define TEXTROWS ((200-TOPMARGIN-BOTTOMMARGIN)/FONTHEIGHT)\r
-#define SCREENPIXWIDTH 320\r
-#define SCREENMID (SCREENPIXWIDTH/2)\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Sint16 pagenum,numpages;\r
-Uint16 leftmargin[TEXTROWS],rightmargin[TEXTROWS];\r
-char far *text;\r
-Uint16 rowon;\r
-Sint16 picx,picy,picnum,picdelay;\r
-boolean layoutdone;\r
-\r
-Sint16 helpmenupos;\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RipToEOL\r
-=\r
-=====================\r
-*/\r
-\r
-void RipToEOL(void)\r
-{\r
- while (*text++ != '\n');\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= ParseNumber\r
-=\r
-=====================\r
-*/\r
-\r
-Sint16 ParseNumber(void)\r
-{\r
- char c, buffer[80];\r
- char *bufptr;\r
-\r
-//\r
-// scan until a number is found\r
-//\r
- c = *text;\r
- while (c < '0' || c > '9')\r
- c = *++text;\r
-\r
-//\r
-// copy the number out\r
-//\r
- bufptr = buffer;\r
- do\r
- {\r
- *bufptr = c;\r
- bufptr++;\r
- text++;\r
- c = *text;\r
- } while (c >= '0' && c <= '9');\r
- *bufptr = 0;\r
-\r
- return atoi(buffer);\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= ParsePicCommand\r
-=\r
-= Call with text pointing just after a ^P\r
-= Upon exit text points to the start of next line\r
-=\r
-=====================\r
-*/\r
-\r
-void ParsePicCommand(void)\r
-{\r
- picy = ParseNumber();\r
- picx = ParseNumber();\r
- picnum = ParseNumber();\r
- RipToEOL();\r
-}\r
-\r
-void ParseTimedCommand(void)\r
-{\r
- picy = ParseNumber();\r
- picx = ParseNumber();\r
- picnum = ParseNumber();\r
- picdelay = ParseNumber();\r
- RipToEOL();\r
-}\r
-\r
-/*\r
-=====================\r
-=\r
-= TimedPicCommand\r
-=\r
-= Call with text pointing just after a ^P\r
-= Upon exit text points to the start of next line\r
-=\r
-=====================\r
-*/\r
-\r
-void TimedPicCommand(void)\r
-{\r
- ParseTimedCommand();\r
-\r
-//\r
-// update the screen, and wait for time delay\r
-//\r
-#if GRMODE == CGAGR\r
- VW_UpdateScreen();\r
-#else\r
- VW_WaitVBL(1);\r
- VW_ScreenToScreen(bufferofs, displayofs, 40, 200);\r
-#endif\r
-\r
-//\r
-// wait for time\r
-//\r
- TimeCount = 0;\r
- while (picdelay > TimeCount)\r
- ;\r
-\r
-//\r
-// draw pic\r
-//\r
- VWB_DrawPic(picx & ~7, picy, picnum);\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= HandleCommand\r
-=\r
-=====================\r
-*/\r
-\r
-void HandleCommand(void)\r
-{\r
- Sint16 i,margin,top,bottom;\r
- Sint16 picwidth,picheight,picmid;\r
-\r
- switch (toupper(*(++text)))\r
- {\r
- case 'B':\r
- picy = ParseNumber();\r
- picx = ParseNumber();\r
- picwidth = ParseNumber();\r
- picheight = ParseNumber();\r
- VWB_Bar(picx, picy, picwidth, picheight, BACKCOLOR);\r
- RipToEOL();\r
- break;\r
-\r
- case 'P': // ^P is start of next page, ^E is end of file\r
- case 'E':\r
- layoutdone = true;\r
- text--;\r
- break;\r
-\r
- case 'C': // ^c<hex digit> changes text color\r
- i = toupper(*(++text));\r
- if (i >= '0' && i <= '9')\r
- {\r
- fontcolor = i + 0 - '0';\r
- }\r
- else if (i >= 'A' && i <= 'F')\r
- {\r
- fontcolor = i + 10 - 'A';\r
- }\r
-#if GRMODE == CGAGR\r
- {\r
- static Sint16 colormap[16] = {2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0};\r
- // Note: This mapping is a bit problematic for Keen 5 CGA,\r
- // since some colors get mapped to CGA magenta, which is\r
- // used as the background color in that version. Luckily\r
- // those colors aren't used in the Keen 5 texts anyway.\r
-\r
- fontcolor = colormap[fontcolor];\r
- }\r
-#endif\r
- fontcolor ^= BACKCOLOR;\r
- text++;\r
- break;\r
-\r
- case 'L':\r
- py = ParseNumber();\r
- rowon = (py - 10)/10;\r
- py = rowon * 10 + 10;\r
- px = ParseNumber();\r
- while (*(text++) != '\n') // scan to end of line\r
- ;\r
- break;\r
-\r
- case 'T': // ^Tyyy,xxx,ppp,ttt waits ttt tics, then draws pic\r
- TimedPicCommand();\r
- break;\r
-\r
- case 'G': // ^Gyyy,xxx,ppp draws graphic\r
- ParsePicCommand();\r
- VWB_DrawPic(picx & ~7, picy, picnum);\r
- picwidth = pictable[picnum-STARTPICS].width * BYTEPIXELS;\r
- picheight = pictable[picnum-STARTPICS].height;\r
- picmid = picx + picwidth/2;\r
- //\r
- // adjust margins\r
- //\r
- if (picmid > SCREENMID)\r
- {\r
- margin = picx-PICMARGIN; // new right margin\r
- }\r
- else\r
- {\r
- margin = picx+picwidth+PICMARGIN; // new left margin\r
- }\r
- top = (picy-TOPMARGIN)/FONTHEIGHT;\r
- if (top < 0)\r
- {\r
- top = 0;\r
- }\r
- bottom = (picy+picheight-TOPMARGIN)/FONTHEIGHT;\r
- if (bottom >= TEXTROWS)\r
- {\r
- bottom = TEXTROWS-1;\r
- }\r
-\r
- for (i=top; i<=bottom; i++)\r
- {\r
- if (picmid > SCREENMID)\r
- {\r
- rightmargin[i] = margin;\r
- }\r
- else\r
- {\r
- leftmargin[i] = margin;\r
- }\r
- }\r
-\r
- //\r
- // adjust this line if needed\r
- //\r
- if (leftmargin[rowon] > px)\r
- {\r
- px = leftmargin[rowon];\r
- }\r
- break;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= NewLine\r
-=\r
-=====================\r
-*/\r
-\r
-void NewLine(void)\r
-{\r
- char c;\r
-\r
- if (++rowon == TEXTROWS)\r
- {\r
- //\r
- // overflowed the page, so skip until next page break\r
- //\r
- layoutdone = true;\r
- do\r
- {\r
- if (*text == '^')\r
- {\r
- c = toupper(text[1]);\r
- if (c == 'E' || c == 'P')\r
- {\r
- layoutdone = true;\r
- return;\r
- }\r
- }\r
- text++;\r
- } while (1);\r
- }\r
- px = leftmargin[rowon];\r
- py += FONTHEIGHT;\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= HandleCtrls\r
-=\r
-=====================\r
-*/\r
-\r
-void HandleCtrls(void)\r
-{\r
- char c;\r
-\r
- c = *(text++); // get the character and advance\r
-\r
- if (c == '\n')\r
- {\r
- NewLine();\r
- return;\r
- }\r
-}\r
-\r
-/*\r
-=====================\r
-=\r
-= HandleWord\r
-=\r
-=====================\r
-*/\r
-\r
-void HandleWord(void)\r
-{\r
- Uint16 wwidth, wheight, newpos, wordindex;\r
- char word[WORDLIMIT];\r
-\r
- //\r
- // copy the next word into [word]\r
- //\r
- word[0] = *(text++);\r
- wordindex = 1;\r
- while (*text > ' ')\r
- {\r
- word[wordindex] = *(text++);\r
- if (++wordindex == WORDLIMIT)\r
- {\r
- Quit("PageLayout: Word limit exceeded");\r
- }\r
- }\r
- word[wordindex] = 0; // stick a null at end for C\r
-\r
- //\r
- // see if it fits on this line\r
- //\r
- VW_MeasurePropString(word, &wwidth, &wheight);\r
- \r
- while (rightmargin[rowon] < px+wwidth)\r
- {\r
- NewLine();\r
- if (layoutdone)\r
- {\r
- return; // overflowed page\r
- }\r
- }\r
-\r
- //\r
- // print it\r
- //\r
- newpos = px+wwidth;\r
- VWB_DrawPropString(word);\r
- px = newpos;\r
-\r
- //\r
- // suck up any extra spaces\r
- //\r
- while (*text == ' ')\r
- {\r
- px += SPACEWIDTH;\r
- text++;\r
- }\r
-}\r
-\r
-/*\r
-=====================\r
-=\r
-= PageLayout\r
-=\r
-= Clears the screen, draws the pics on the page, and word wraps the text.\r
-= Returns a pointer to the terminating command\r
-=\r
-=====================\r
-*/\r
-\r
-void PageLayout(boolean shownumber)\r
-{\r
- Sint16 oldcolor, i;\r
- char c;\r
-\r
- oldcolor = fontcolor;\r
-\r
-#if GRMODE == CGAGR\r
- fontcolor = BLACK^BACKCOLOR;\r
-#else\r
- fontcolor = YELLOW^BACKCOLOR;\r
-#endif\r
-\r
-//\r
-// clear the screen\r
-//\r
- VWB_Bar(0, 0, 320, 200, BACKCOLOR);\r
-#ifndef KEEN6\r
- VWB_DrawPic( 0, 0, H_TOPWINDOWPIC);\r
- VWB_DrawPic( 0, 8, H_LEFTWINDOWPIC);\r
- VWB_DrawPic(312, 8, H_RIGHTWINDOWPIC);\r
- if (shownumber)\r
- {\r
- VWB_DrawPic(8, 176, H_BOTTOMINFOPIC);\r
- }\r
- else\r
- {\r
- VWB_DrawPic(8, 192, H_BOTTOMWINDOWPIC);\r
- }\r
-#endif\r
-\r
- for (i=0; i<TEXTROWS; i++)\r
- {\r
- leftmargin[i] = LEFTMARGIN;\r
- rightmargin[i] = SCREENPIXWIDTH-RIGHTMARGIN;\r
- }\r
-\r
- px = LEFTMARGIN;\r
- py = TOPMARGIN;\r
- rowon = 0;\r
- layoutdone = false;\r
-\r
-//\r
-// make sure we are starting layout text (^P first command)\r
-//\r
- while (*text <= ' ')\r
- {\r
- text++;\r
- }\r
- if (*text != '^' || toupper(*(++text)) != 'P')\r
- {\r
- Quit("PageLayout: Text not headed with ^P");\r
- }\r
- while (*(text++) != '\n')\r
- ;\r
-\r
-//\r
-// process text stream\r
-//\r
- do\r
- {\r
- c = *text;\r
- if (c == '^')\r
- {\r
- HandleCommand();\r
- }\r
- else if (c <= ' ')\r
- {\r
- HandleCtrls();\r
- }\r
- else\r
- {\r
- HandleWord();\r
- }\r
- } while (!layoutdone);\r
-\r
- pagenum++;\r
-\r
- if (shownumber)\r
- {\r
- strcpy(str, "pg ");\r
- itoa(pagenum, str2, 10);\r
- strcat(str, str2);\r
- strcat(str, " of ");\r
- itoa(numpages, str2, 10);\r
- strcat(str, str2);\r
-#if GRMODE == CGAGR\r
- fontcolor = BLACK^BACKCOLOR;\r
-#else\r
- fontcolor = LIGHTRED^BACKCOLOR;\r
-#endif\r
- py = 186;\r
- px = 218;\r
- VWB_DrawPropString(str);\r
- }\r
-\r
- fontcolor = oldcolor;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= BackPage\r
-=\r
-= Scans for a previous ^P\r
-=\r
-=====================\r
-*/\r
-\r
-void BackPage(void)\r
-{\r
- pagenum--;\r
- do\r
- {\r
- text--;\r
- if (text[0] == '^' && toupper(text[1]) == 'P')\r
- {\r
- return;\r
- }\r
- } while (1);\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= CacheLayoutGraphics\r
-=\r
-= Scans an entire layout file (until a ^E) marking all graphics used, and\r
-= counting pages, then caches the graphics in\r
-=\r
-=====================\r
-*/\r
-void CacheLayoutGraphics(void)\r
-{\r
- char far *bombpoint, far *textstart;\r
- char ch;\r
-\r
- textstart = text;\r
- bombpoint = text+30000;\r
- numpages = pagenum = 0;\r
-\r
-#ifndef KEEN6\r
- CA_MarkGrChunk(H_TOPWINDOWPIC);\r
- CA_MarkGrChunk(H_LEFTWINDOWPIC);\r
- CA_MarkGrChunk(H_RIGHTWINDOWPIC);\r
- CA_MarkGrChunk(H_BOTTOMINFOPIC);\r
- CA_MarkGrChunk(H_BOTTOMWINDOWPIC);\r
-#endif\r
-\r
- do\r
- {\r
- if (*text == '^')\r
- {\r
- ch = toupper(*(++text));\r
- if (ch == 'P') // start of a page\r
- {\r
- numpages++;\r
- }\r
- if (ch == 'E') // end of file, so load graphics and return\r
- {\r
- CA_CacheMarks(NULL);\r
- text = textstart;\r
- return;\r
- }\r
- if (ch == 'G') // draw graphic command, so mark graphics\r
- {\r
- ParsePicCommand();\r
- CA_MarkGrChunk(picnum);\r
- }\r
- if (ch == 'T') // timed draw graphic command, so mark graphics\r
- {\r
- ParseTimedCommand();\r
- CA_MarkGrChunk(picnum);\r
- }\r
- }\r
- else\r
- {\r
- text++;\r
- }\r
-\r
- } while (text < bombpoint);\r
-\r
- Quit("CacheLayoutGraphics: No ^E to terminate file!");\r
-}\r
-\r
-//===========================================================================\r
-\r
-#ifndef KEEN6\r
-/*\r
-=================\r
-=\r
-= HelpMenu\r
-=\r
-=================\r
-*/\r
-Sint16 HelpMenu(void)\r
-{\r
- CursorInfo cursor;\r
- ControlInfo control;\r
- Sint16 ydelta;\r
- Uint16 key;\r
-\r
- VWB_Bar(0, 0, 320, 200, BACKCOLOR);\r
-\r
- CA_CacheGrChunk(H_HELPPIC);\r
- CA_CacheGrChunk(H_HANDPIC);\r
- CA_CacheGrChunk(H_TOPWINDOWPIC);\r
- CA_CacheGrChunk(H_LEFTWINDOWPIC);\r
- CA_CacheGrChunk(H_RIGHTWINDOWPIC);\r
- CA_CacheGrChunk(H_BOTTOMWINDOWPIC);\r
-\r
- VWB_DrawPic( 0, 0, H_TOPWINDOWPIC);\r
- VWB_DrawPic( 0, 8, H_LEFTWINDOWPIC);\r
- VWB_DrawPic(312, 8, H_RIGHTWINDOWPIC);\r
- VWB_DrawPic( 8, 192, H_BOTTOMWINDOWPIC);\r
- VWB_DrawPic( 96, 8, H_HELPPIC);\r
-\r
- ydelta = 0;\r
- IN_ClearKeysDown();\r
- do\r
- {\r
- if (helpmenupos < 0)\r
- {\r
- helpmenupos = 0;\r
- }\r
-#ifdef GOODTIMES\r
- else if (helpmenupos > 3)\r
- {\r
- helpmenupos = 3;\r
- }\r
-#else\r
- else if (helpmenupos > 4)\r
- {\r
- helpmenupos = 4;\r
- }\r
-#endif\r
- VWB_DrawPic(48, 24*helpmenupos+48, H_HANDPIC);\r
- VW_UpdateScreen();\r
- VWB_Bar(48, 24*helpmenupos+48, 39, 24, BACKCOLOR);\r
- IN_ReadControl(0, &control);\r
- IN_ReadCursor(&cursor);\r
- if (LastScan)\r
- {\r
- key = LastScan;\r
- IN_ClearKeysDown();\r
- switch (key)\r
- {\r
- case sc_UpArrow:\r
- helpmenupos--;\r
- break;\r
- case sc_DownArrow:\r
- helpmenupos++;\r
- break;\r
- case sc_Enter:\r
- VW_ClearVideo(BACKCOLOR);\r
- return helpmenupos;\r
- case sc_Escape:\r
- VW_ClearVideo(BACKCOLOR);\r
- return -1;\r
- }\r
- }\r
- ydelta += cursor.y;\r
- if (cursor.button0 || cursor.button1 || control.button0 || control.button1)\r
- {\r
- VW_ClearVideo(BACKCOLOR);\r
- return helpmenupos;\r
- }\r
- if (ydelta < -40)\r
- {\r
- ydelta += 40;\r
- helpmenupos--;\r
- }\r
- else if (ydelta > 40)\r
- {\r
- ydelta -= 40;\r
- helpmenupos++;\r
- }\r
- } while (1);\r
-}\r
-\r
-/*\r
-=================\r
-=\r
-= HelpScreens\r
-=\r
-=================\r
-*/\r
-void HelpScreens(void)\r
-{\r
- static Uint16 layouttable[5] =\r
- {\r
- T_HELPART,\r
- T_CONTRART,\r
- T_STORYART,\r
-#ifndef GOODTIMES\r
- T_ORDERART,\r
-#endif\r
- T_IDART\r
- };\r
-\r
- Uint16 olddisplayofs, oldbufferofs, oldfontnumber, temp;\r
- Sint16 pos;\r
- boolean newpage;\r
-\r
- oldfontnumber = fontnumber;\r
- olddisplayofs = displayofs;\r
- oldbufferofs = bufferofs;\r
- fontnumber = 0;\r
-\r
-#if GRMODE == EGAGR\r
- EGAMAPMASK(15);\r
-#endif\r
-\r
- CA_UpLevel();\r
- CA_SetGrPurge();\r
- VW_ClearVideo(BACKCOLOR);\r
-\r
-#if GRMODE == EGAGR\r
- RF_FixOfs();\r
- bufferofs = 0;\r
- displayofs = 0x8000;\r
- VW_SetScreen(displayofs, 0);\r
-#endif\r
-\r
-#ifdef KEEN5\r
- StartMusic(19);\r
-#endif\r
-\r
- do\r
- {\r
- pos = HelpMenu();\r
-\r
- VW_ClearVideo(BACKCOLOR);\r
-\r
- if (pos == -1)\r
- {\r
- CA_DownLevel();\r
- IN_ClearKeysDown();\r
- bufferofs = oldbufferofs;\r
- displayofs = olddisplayofs;\r
- fontnumber = oldfontnumber;\r
- VW_ClearVideo(BACKCOLOR);\r
- RF_FixOfs();\r
-#ifdef KEEN5\r
- StopMusic(); // Note: it's safer to call StopMusic BEFORE CA_DownLevel\r
-#endif\r
- return;\r
- }\r
-\r
- pos = layouttable[pos];\r
- CA_CacheGrChunk(pos);\r
- text = grsegs[pos];\r
- CacheLayoutGraphics();\r
-\r
- newpage = true;\r
- do\r
- {\r
- if (newpage)\r
- {\r
- newpage = false;\r
- PageLayout(true);\r
-#if GRMODE == CGAGR\r
- VW_UpdateScreen();\r
-#else\r
- VW_SetScreen(bufferofs, 0);\r
- temp = displayofs;\r
- displayofs = bufferofs;\r
- bufferofs = temp;\r
-#endif\r
- }\r
-\r
- LastScan = 0;\r
- while (!LastScan);\r
-\r
- switch (LastScan)\r
- {\r
- case sc_UpArrow:\r
- case sc_LeftArrow:\r
- case sc_PgUp:\r
- if (pagenum > 1)\r
- {\r
- BackPage();\r
- BackPage();\r
- newpage = true;\r
- }\r
- break;\r
- case sc_DownArrow:\r
- case sc_RightArrow:\r
- case sc_PgDn:\r
- if (pagenum < numpages)\r
- {\r
- newpage = true;\r
- }\r
- break;\r
- }\r
- } while (LastScan != sc_Escape);\r
-\r
- MM_FreePtr(&grsegs[pos]);\r
- IN_ClearKeysDown();\r
- } while (true);\r
-}\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=================\r
-=\r
-= FinaleLayout\r
-=\r
-=================\r
-*/\r
-void FinaleLayout(void)\r
-{\r
- char _seg *textseg;\r
- Sint16 i;\r
-\r
- VW_ClearVideo(BACKCOLOR);\r
- RF_FixOfs();\r
- CA_UpLevel();\r
- CA_SetGrPurge();\r
- CA_CacheGrChunk(H_FLASHARROW2PIC);\r
- CA_CacheGrChunk(H_FLASHARROW1PIC);\r
-\r
-#ifdef KEEN5\r
- if (gamestate.leveldone[13] == ex_fusebroke)\r
- {\r
- CA_CacheGrChunk(T_ENDART2);\r
- textseg = grsegs[T_ENDART2];\r
- }\r
- else\r
- {\r
- CA_CacheGrChunk(T_ENDART);\r
- textseg = grsegs[T_ENDART];\r
- }\r
-#else\r
- CA_CacheGrChunk(T_ENDART);\r
- textseg = grsegs[T_ENDART];\r
-#endif\r
-\r
- text = textseg;\r
- CacheLayoutGraphics();\r
-\r
- StartMusic(ENDINGMUSIC);\r
-\r
- while (pagenum < numpages)\r
- {\r
- PageLayout(false);\r
- IN_ClearKeysDown();\r
-#if GRMODE == CGAGR\r
- VW_UpdateScreen();\r
-#else\r
- VW_SetScreen(bufferofs, 0);\r
-#endif\r
-\r
- do\r
- {\r
- VWB_DrawPic(298, 184, H_FLASHARROW1PIC);\r
-#if GRMODE == CGAGR\r
- VW_UpdateScreen();\r
-#endif\r
- for (i=0; i<TickBase; i++)\r
- {\r
- if (IN_IsUserInput())\r
- {\r
- goto nextpage;\r
- }\r
- VW_WaitVBL(1);\r
- }\r
-\r
- VWB_DrawPic(298, 184, H_FLASHARROW2PIC);\r
-#if GRMODE == CGAGR\r
- VW_UpdateScreen();\r
-#endif\r
- for (i=0; i<TickBase; i++)\r
- {\r
- if (IN_IsUserInput())\r
- {\r
- goto nextpage;\r
- }\r
- VW_WaitVBL(1);\r
- }\r
- } while (1);\r
-\r
-nextpage:\r
- ; // Borland C++ 2.0 needs a semicolon here...\r
- }\r
-\r
- StopMusic();\r
-\r
-#ifdef KEEN5\r
- if (gamestate.leveldone[13] == ex_fusebroke)\r
- {\r
- MM_FreePtr(&grsegs[T_ENDART2]);\r
- }\r
- else\r
- {\r
- MM_FreePtr(&grsegs[H_FLASHARROW1PIC]); // BUG! this should free T_ENDART, the arrow should be freed after the else branch!\r
- }\r
-#else\r
- MM_FreePtr(&grsegs[T_ENDART]);\r
- MM_FreePtr(&grsegs[H_FLASHARROW1PIC]);\r
-#endif\r
- MM_FreePtr(&grsegs[H_FLASHARROW2PIC]);\r
- CA_DownLevel();\r
- IN_ClearKeysDown();\r
-#if GRMODE != CGAGR\r
- VW_ClearVideo(BACKCOLOR);\r
- RF_FixOfs();\r
-#endif\r
- CA_FreeGraphics();\r
-}
\ No newline at end of file
+++ /dev/null
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_CA.C\r
-\r
-/*\r
-=============================================================================\r
-\r
-Id Software Caching Manager\r
----------------------------\r
-\r
-Must be started BEFORE the memory manager, because it needs to get the headers\r
-loaded into the data segment\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-#pragma warn -pro\r
-#pragma warn -use\r
-\r
-#define THREEBYTEGRSTARTS\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-typedef struct\r
-{\r
- unsigned bit0,bit1; // 0-255 is a character, > is a pointer to a node\r
-} huffnode;\r
-\r
-\r
-typedef struct\r
-{\r
- unsigned RLEWtag;\r
- long headeroffsets[100];\r
- byte tileinfo[];\r
-} mapfiletype;\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-byte _seg *tinf;\r
-int mapon;\r
-\r
-unsigned _seg *mapsegs[3];\r
-maptype _seg *mapheaderseg[NUMMAPS];\r
-byte _seg *audiosegs[NUMSNDCHUNKS];\r
-void _seg *grsegs[NUMCHUNKS];\r
-\r
-byte far grneeded[NUMCHUNKS];\r
-byte ca_levelbit,ca_levelnum;\r
-\r
-int profilehandle,debughandle;\r
-\r
-void (*drawcachebox) (char *title, unsigned numcache);\r
-void (*updatecachebox) (void);\r
-void (*finishcachebox) (void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern long far CGAhead;\r
-extern long far EGAhead;\r
-extern byte CGAdict;\r
-extern byte EGAdict;\r
-extern byte far maphead;\r
-extern byte mapdict;\r
-extern byte far audiohead;\r
-extern byte audiodict;\r
-\r
-\r
-long _seg *grstarts; // array of offsets in egagraph, -1 for sparse\r
-long _seg *audiostarts; // array of offsets in audio / audiot\r
-\r
-#ifdef GRHEADERLINKED\r
-huffnode *grhuffman;\r
-#else\r
-huffnode grhuffman[255];\r
-#endif\r
-\r
-#ifdef AUDIOHEADERLINKED\r
-huffnode *audiohuffman;\r
-#else\r
-huffnode audiohuffman[255];\r
-#endif\r
-\r
-\r
-int grhandle; // handle to EGAGRAPH\r
-int maphandle; // handle to MAPTEMP / GAMEMAPS\r
-int audiohandle; // handle to AUDIOT / AUDIO\r
-\r
-long chunkcomplen,chunkexplen;\r
-\r
-SDMode oldsoundmode;\r
-\r
-\r
-\r
-void CAL_DialogDraw (char *title,unsigned numcache);\r
-void CAL_DialogUpdate (void);\r
-void CAL_DialogFinish (void);\r
-void CAL_CarmackExpand (unsigned far *source, unsigned far *dest,\r
- unsigned length);\r
-\r
-\r
-#ifdef THREEBYTEGRSTARTS\r
-#define FILEPOSSIZE 3\r
-//#define GRFILEPOS(c) (*(long far *)(((byte far *)grstarts)+(c)*3)&0xffffff)\r
-long GRFILEPOS(int c)\r
-{\r
- long value;\r
- int offset;\r
-\r
- offset = c*3;\r
-\r
- value = *(long far *)(((byte far *)grstarts)+offset);\r
-\r
- value &= 0x00ffffffl;\r
-\r
- if (value == 0xffffffl)\r
- value = -1;\r
-\r
- return value;\r
-};\r
-#else\r
-#define FILEPOSSIZE 4\r
-#define GRFILEPOS(c) (grstarts[c])\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOW LEVEL ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-============================\r
-=\r
-= CA_OpenDebug / CA_CloseDebug\r
-=\r
-= Opens a binary file with the handle "debughandle"\r
-=\r
-============================\r
-*/\r
-\r
-void CA_OpenDebug (void)\r
-{\r
- unlink ("DEBUG.TXT");\r
- debughandle = open("DEBUG.TXT", O_CREAT | O_WRONLY | O_TEXT);\r
-}\r
-\r
-void CA_CloseDebug (void)\r
-{\r
- close (debughandle);\r
-}\r
-\r
-\r
-\r
-/*\r
-============================\r
-=\r
-= CAL_GetGrChunkLength\r
-=\r
-= Gets the length of an explicit length chunk (not tiles)\r
-= The file pointer is positioned so the compressed data can be read in next.\r
-=\r
-============================\r
-*/\r
-\r
-void CAL_GetGrChunkLength (int chunk)\r
-{\r
- lseek(grhandle,GRFILEPOS(chunk),SEEK_SET);\r
- read(grhandle,&chunkexplen,sizeof(chunkexplen));\r
- chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_FarRead\r
-=\r
-= Read from a file to a far pointer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_FarRead (int handle, byte far *dest, long length)\r
-{\r
- if (length>0xffffl)\r
- Quit ("CA_FarRead doesn't support 64K reads yet!");\r
-\r
-asm push ds\r
-asm mov bx,[handle]\r
-asm mov cx,[WORD PTR length]\r
-asm mov dx,[WORD PTR dest]\r
-asm mov ds,[WORD PTR dest+2]\r
-asm mov ah,0x3f // READ w/handle\r
-asm int 21h\r
-asm pop ds\r
-asm jnc good\r
- errno = _AX;\r
- return false;\r
-good:\r
-asm cmp ax,[WORD PTR length]\r
-asm je done\r
- errno = EINVFMT; // user manager knows this is bad read\r
- return false;\r
-done:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_SegWrite\r
-=\r
-= Write from a file to a far pointer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_FarWrite (int handle, byte far *source, long length)\r
-{\r
- if (length>0xffffl)\r
- Quit ("CA_FarWrite doesn't support 64K reads yet!");\r
-\r
-asm push ds\r
-asm mov bx,[handle]\r
-asm mov cx,[WORD PTR length]\r
-asm mov dx,[WORD PTR source]\r
-asm mov ds,[WORD PTR source+2]\r
-asm mov ah,0x40 // WRITE w/handle\r
-asm int 21h\r
-asm pop ds\r
-asm jnc good\r
- errno = _AX;\r
- return false;\r
-good:\r
-asm cmp ax,[WORD PTR length]\r
-asm je done\r
- errno = ENOMEM; // user manager knows this is bad write\r
- return false;\r
-\r
-done:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_ReadFile\r
-=\r
-= Reads a file into an allready allocated buffer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_ReadFile (char *filename, memptr *ptr)\r
-{\r
- int handle;\r
- long size;\r
-\r
- if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- return false;\r
-\r
- size = filelength (handle);\r
- if (!CA_FarRead (handle,*ptr,size))\r
- {\r
- close (handle);\r
- return false;\r
- }\r
- close (handle);\r
- return true;\r
-}\r
-\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_LoadFile\r
-=\r
-= Allocate space for and load a file\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_LoadFile (char *filename, memptr *ptr)\r
-{\r
- int handle;\r
- long size;\r
-\r
- if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- return false;\r
-\r
- size = filelength (handle);\r
- MM_GetPtr (ptr,size);\r
- if (!CA_FarRead (handle,*ptr,size))\r
- {\r
- close (handle);\r
- return false;\r
- }\r
- close (handle);\r
- return true;\r
-}\r
-\r
-/*\r
-============================================================================\r
-\r
- COMPRESSION routines, see JHUFF.C for more\r
-\r
-============================================================================\r
-*/\r
-\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= CAL_OptimizeNodes\r
-=\r
-= Goes through a huffman table and changes the 256-511 node numbers to the\r
-= actular address of the node. Must be called before CAL_HuffExpand\r
-=\r
-===============\r
-*/\r
-\r
-void CAL_OptimizeNodes (huffnode *table)\r
-{\r
- huffnode *node;\r
- int i;\r
-\r
- node = table;\r
-\r
- for (i=0;i<255;i++)\r
- {\r
- if (node->bit0 >= 256)\r
- node->bit0 = (unsigned)(table+(node->bit0-256));\r
- if (node->bit1 >= 256)\r
- node->bit1 = (unsigned)(table+(node->bit1-256));\r
- node++;\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_HuffExpand\r
-=\r
-= Length is the length of the EXPANDED data\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_HuffExpand (byte huge *source, byte huge *dest,\r
- long length,huffnode *hufftable)\r
-{\r
-// unsigned bit,byte,node,code;\r
- unsigned sourceseg,sourceoff,destseg,destoff,endoff;\r
- huffnode *headptr;\r
-// huffnode *nodeon;\r
-\r
- headptr = hufftable+254; // head node is allways node 254\r
-\r
- source++; // normalize\r
- source--;\r
- dest++;\r
- dest--;\r
-\r
- sourceseg = FP_SEG(source);\r
- sourceoff = FP_OFF(source);\r
- destseg = FP_SEG(dest);\r
- destoff = FP_OFF(dest);\r
- endoff = destoff+length;\r
-\r
-//\r
-// ds:si source\r
-// es:di dest\r
-// ss:bx node pointer\r
-//\r
-\r
- if (length <0xfff0)\r
- {\r
-\r
-//--------------------------\r
-// expand less than 64k of data\r
-//--------------------------\r
-\r
-asm mov bx,[headptr]\r
-\r
-asm mov si,[sourceoff]\r
-asm mov di,[destoff]\r
-asm mov es,[destseg]\r
-asm mov ds,[sourceseg]\r
-asm mov ax,[endoff]\r
-\r
-asm mov ch,[si] // load first byte\r
-asm inc si\r
-asm mov cl,1\r
-\r
-expandshort:\r
-asm test ch,cl // bit set?\r
-asm jnz bit1short\r
-asm mov dx,[ss:bx] // take bit0 path from node\r
-asm shl cl,1 // advance to next bit position\r
-asm jc newbyteshort\r
-asm jnc sourceupshort\r
-\r
-bit1short:\r
-asm mov dx,[ss:bx+2] // take bit1 path\r
-asm shl cl,1 // advance to next bit position\r
-asm jnc sourceupshort\r
-\r
-newbyteshort:\r
-asm mov ch,[si] // load next byte\r
-asm inc si\r
-asm mov cl,1 // back to first bit\r
-\r
-sourceupshort:\r
-asm or dh,dh // if dx<256 its a byte, else move node\r
-asm jz storebyteshort\r
-asm mov bx,dx // next node = (huffnode *)code\r
-asm jmp expandshort\r
-\r
-storebyteshort:\r
-asm mov [es:di],dl\r
-asm inc di // write a decopmpressed byte out\r
-asm mov bx,[headptr] // back to the head node for next bit\r
-\r
-asm cmp di,ax // done?\r
-asm jne expandshort\r
- }\r
- else\r
- {\r
-\r
-//--------------------------\r
-// expand more than 64k of data\r
-//--------------------------\r
-\r
- length--;\r
-\r
-asm mov bx,[headptr]\r
-asm mov cl,1\r
-\r
-asm mov si,[sourceoff]\r
-asm mov di,[destoff]\r
-asm mov es,[destseg]\r
-asm mov ds,[sourceseg]\r
-\r
-asm lodsb // load first byte\r
-\r
-expand:\r
-asm test al,cl // bit set?\r
-asm jnz bit1\r
-asm mov dx,[ss:bx] // take bit0 path from node\r
-asm jmp gotcode\r
-bit1:\r
-asm mov dx,[ss:bx+2] // take bit1 path\r
-\r
-gotcode:\r
-asm shl cl,1 // advance to next bit position\r
-asm jnc sourceup\r
-asm lodsb\r
-asm cmp si,0x10 // normalize ds:si\r
-asm jb sinorm\r
-asm mov cx,ds\r
-asm inc cx\r
-asm mov ds,cx\r
-asm xor si,si\r
-sinorm:\r
-asm mov cl,1 // back to first bit\r
-\r
-sourceup:\r
-asm or dh,dh // if dx<256 its a byte, else move node\r
-asm jz storebyte\r
-asm mov bx,dx // next node = (huffnode *)code\r
-asm jmp expand\r
-\r
-storebyte:\r
-asm mov [es:di],dl\r
-asm inc di // write a decopmpressed byte out\r
-asm mov bx,[headptr] // back to the head node for next bit\r
-\r
-asm cmp di,0x10 // normalize es:di\r
-asm jb dinorm\r
-asm mov dx,es\r
-asm inc dx\r
-asm mov es,dx\r
-asm xor di,di\r
-dinorm:\r
-\r
-asm sub [WORD PTR ss:length],1\r
-asm jnc expand\r
-asm dec [WORD PTR ss:length+2]\r
-asm jns expand // when length = ffff ffff, done\r
-\r
- }\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_CarmackExpand\r
-=\r
-= Length is the length of the EXPANDED data\r
-=\r
-======================\r
-*/\r
-\r
-#define NEARTAG 0xa7\r
-#define FARTAG 0xa8\r
-\r
-void CAL_CarmackExpand (unsigned far *source, unsigned far *dest, unsigned length)\r
-{\r
- unsigned ch,chhigh,count,offset;\r
- unsigned far *copyptr, far *inptr, far *outptr;\r
-\r
- length/=2;\r
-\r
- inptr = source;\r
- outptr = dest;\r
-\r
- while (length)\r
- {\r
- ch = *inptr++;\r
- chhigh = ch>>8;\r
- if (chhigh == NEARTAG)\r
- {\r
- count = ch&0xff;\r
- if (!count)\r
- { // have to insert a word containing the tag byte\r
- ch |= *((unsigned char far *)inptr)++;\r
- *outptr++ = ch;\r
- length--;\r
- }\r
- else\r
- {\r
- offset = *((unsigned char far *)inptr)++;\r
- copyptr = outptr - offset;\r
- length -= count;\r
- while (count--)\r
- *outptr++ = *copyptr++;\r
- }\r
- }\r
- else if (chhigh == FARTAG)\r
- {\r
- count = ch&0xff;\r
- if (!count)\r
- { // have to insert a word containing the tag byte\r
- ch |= *((unsigned char far *)inptr)++;\r
- *outptr++ = ch;\r
- length --;\r
- }\r
- else\r
- {\r
- offset = *inptr++;\r
- copyptr = dest + offset;\r
- length -= count;\r
- while (count--)\r
- *outptr++ = *copyptr++;\r
- }\r
- }\r
- else\r
- {\r
- *outptr++ = ch;\r
- length --;\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_RLEWcompress\r
-=\r
-======================\r
-*/\r
-\r
-long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,\r
- unsigned rlewtag)\r
-{\r
- long complength;\r
- unsigned value,count,i;\r
- unsigned huge *start,huge *end;\r
-\r
- start = dest;\r
-\r
- end = source + (length+1)/2;\r
-\r
-//\r
-// compress it\r
-//\r
- do\r
- {\r
- count = 1;\r
- value = *source++;\r
- while (*source == value && source<end)\r
- {\r
- count++;\r
- source++;\r
- }\r
- if (count>3 || value == rlewtag)\r
- {\r
- //\r
- // send a tag / count / value string\r
- //\r
- *dest++ = rlewtag;\r
- *dest++ = count;\r
- *dest++ = value;\r
- }\r
- else\r
- {\r
- //\r
- // send word without compressing\r
- //\r
- for (i=1;i<=count;i++)\r
- *dest++ = value;\r
- }\r
-\r
- } while (source<end);\r
-\r
- complength = 2*(dest-start);\r
- return complength;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_RLEWexpand\r
-= length is EXPANDED length\r
-=\r
-======================\r
-*/\r
-\r
-void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,\r
- unsigned rlewtag)\r
-{\r
-// unsigned value,count,i;\r
- unsigned huge *end;\r
- unsigned sourceseg,sourceoff,destseg,destoff,endseg,endoff;\r
-\r
-\r
-//\r
-// expand it\r
-//\r
-#if 0\r
- do\r
- {\r
- value = *source++;\r
- if (value != rlewtag)\r
- //\r
- // uncompressed\r
- //\r
- *dest++=value;\r
- else\r
- {\r
- //\r
- // compressed string\r
- //\r
- count = *source++;\r
- value = *source++;\r
- for (i=1;i<=count;i++)\r
- *dest++ = value;\r
- }\r
- } while (dest<end);\r
-#endif\r
-\r
- end = dest + (length)/2;\r
- sourceseg = FP_SEG(source);\r
- sourceoff = FP_OFF(source);\r
- destseg = FP_SEG(dest);\r
- destoff = FP_OFF(dest);\r
- endseg = FP_SEG(end);\r
- endoff = FP_OFF(end);\r
-\r
-\r
-//\r
-// ax = source value\r
-// bx = tag value\r
-// cx = repeat counts\r
-// dx = scratch\r
-//\r
-// NOTE: A repeat count that produces 0xfff0 bytes can blow this!\r
-//\r
-\r
-asm mov bx,rlewtag\r
-asm mov si,sourceoff\r
-asm mov di,destoff\r
-asm mov es,destseg\r
-asm mov ds,sourceseg\r
-\r
-expand:\r
-asm lodsw\r
-asm cmp ax,bx\r
-asm je repeat\r
-asm stosw\r
-asm jmp next\r
-\r
-repeat:\r
-asm lodsw\r
-asm mov cx,ax // repeat count\r
-asm lodsw // repeat value\r
-asm rep stosw\r
-\r
-next:\r
-\r
-asm cmp si,0x10 // normalize ds:si\r
-asm jb sinorm\r
-asm mov ax,si\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm mov dx,ds\r
-asm add dx,ax\r
-asm mov ds,dx\r
-asm and si,0xf\r
-sinorm:\r
-asm cmp di,0x10 // normalize es:di\r
-asm jb dinorm\r
-asm mov ax,di\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm mov dx,es\r
-asm add dx,ax\r
-asm mov es,dx\r
-asm and di,0xf\r
-dinorm:\r
-\r
-asm cmp di,ss:endoff\r
-asm jne expand\r
-asm mov ax,es\r
-asm cmp ax,ss:endseg\r
-asm jb expand\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- CACHE MANAGER ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupGrFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupGrFile (void)\r
-{\r
- int handle;\r
- memptr compseg;\r
-\r
-#ifdef GRHEADERLINKED\r
-\r
-#if GRMODE == EGAGR\r
- grhuffman = (huffnode *)&EGAdict;\r
- grstarts = (long _seg *)FP_SEG(&EGAhead);\r
-#endif\r
-#if GRMODE == CGAGR\r
- grhuffman = (huffnode *)&CGAdict;\r
- grstarts = (long _seg *)FP_SEG(&CGAhead);\r
-#endif\r
-\r
- CAL_OptimizeNodes (grhuffman);\r
-\r
-#else\r
-\r
-//\r
-// load ???dict.ext (huffman dictionary for graphics files)\r
-//\r
-\r
- if ((handle = open(GREXT"DICT."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"DICT."EXTENSION"!");\r
-\r
- read(handle, &grhuffman, sizeof(grhuffman));\r
- close(handle);\r
- CAL_OptimizeNodes (grhuffman);\r
-//\r
-// load the data offsets from ???head.ext\r
-//\r
- MM_GetPtr (&(memptr)grstarts,(NUMCHUNKS+1)*FILEPOSSIZE);\r
-\r
- if ((handle = open(GREXT"HEAD."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"HEAD."EXTENSION"!");\r
-\r
- CA_FarRead(handle, (memptr)grstarts, (NUMCHUNKS+1)*FILEPOSSIZE);\r
-\r
- close(handle);\r
-\r
-\r
-#endif\r
-\r
-//\r
-// Open the graphics file, leaving it open until the game is finished\r
-//\r
- grhandle = open(GREXT"GRAPH."EXTENSION, O_RDONLY | O_BINARY);\r
- if (grhandle == -1)\r
- Quit ("Cannot open "GREXT"GRAPH."EXTENSION"!");\r
-\r
-\r
-//\r
-// load the pic and sprite headers into the arrays in the data segment\r
-//\r
-#if NUMPICS>0\r
- MM_GetPtr(&(memptr)pictable,NUMPICS*sizeof(pictabletype));\r
- CAL_GetGrChunkLength(STRUCTPIC); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)pictable,NUMPICS*sizeof(pictabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-#if NUMPICM>0\r
- MM_GetPtr(&(memptr)picmtable,NUMPICM*sizeof(pictabletype));\r
- CAL_GetGrChunkLength(STRUCTPICM); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)picmtable,NUMPICS*sizeof(pictabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-#if NUMSPRITES>0\r
- MM_GetPtr(&(memptr)spritetable,NUMSPRITES*sizeof(spritetabletype));\r
- CAL_GetGrChunkLength(STRUCTSPRITE); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)spritetable,NUMSPRITES*sizeof(spritetabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupMapFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupMapFile (void)\r
-{\r
- int handle;\r
- long length;\r
-\r
-//\r
-// load maphead.ext (offsets and tileinfo for map file)\r
-//\r
-#ifndef MAPHEADERLINKED\r
- if ((handle = open("MAPHEAD."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPHEAD."EXTENSION"!");\r
- length = filelength(handle);\r
- MM_GetPtr (&(memptr)tinf,length);\r
- CA_FarRead(handle, tinf, length);\r
- close(handle);\r
-#else\r
-\r
- tinf = (byte _seg *)FP_SEG(&maphead);\r
-\r
-#endif\r
-\r
-//\r
-// open the data file\r
-//\r
-#ifdef MAPHEADERLINKED\r
- if ((maphandle = open("GAMEMAPS."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open GAMEMAPS."EXTENSION"!");\r
-#else\r
- if ((maphandle = open("MAPTEMP."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPTEMP."EXTENSION"!");\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupAudioFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupAudioFile (void)\r
-{\r
- int handle;\r
- long length;\r
-\r
-//\r
-// load maphead.ext (offsets and tileinfo for map file)\r
-//\r
-#ifndef AUDIOHEADERLINKED\r
- if ((handle = open("AUDIOHED."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOHED."EXTENSION"!");\r
- length = filelength(handle);\r
- MM_GetPtr (&(memptr)audiostarts,length);\r
- CA_FarRead(handle, (byte far *)audiostarts, length);\r
- close(handle);\r
-#else\r
- audiohuffman = (huffnode *)&audiodict;\r
- CAL_OptimizeNodes (audiohuffman);\r
- audiostarts = (long _seg *)FP_SEG(&audiohead);\r
-#endif\r
-\r
-//\r
-// open the data file\r
-//\r
-#ifndef AUDIOHEADERLINKED\r
- if ((audiohandle = open("AUDIOT."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOT."EXTENSION"!");\r
-#else\r
- if ((audiohandle = open("AUDIO."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIO."EXTENSION"!");\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_Startup\r
-=\r
-= Open all files and load in headers\r
-=\r
-======================\r
-*/\r
-\r
-void CA_Startup (void)\r
-{\r
-#ifdef PROFILE\r
- unlink ("PROFILE.TXT");\r
- profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT);\r
-#endif\r
-\r
-#ifndef NOMAPS\r
- CAL_SetupMapFile ();\r
-#endif\r
-#ifndef NOGRAPHICS\r
- CAL_SetupGrFile ();\r
-#endif\r
-#ifndef NOAUDIO\r
- CAL_SetupAudioFile ();\r
-#endif\r
-\r
- mapon = -1;\r
- ca_levelbit = 1;\r
- ca_levelnum = 0;\r
-\r
- drawcachebox = CAL_DialogDraw;\r
- updatecachebox = CAL_DialogUpdate;\r
- finishcachebox = CAL_DialogFinish;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_Shutdown\r
-=\r
-= Closes all files\r
-=\r
-======================\r
-*/\r
-\r
-void CA_Shutdown (void)\r
-{\r
-#ifdef PROFILE\r
- close (profilehandle);\r
-#endif\r
-\r
- close (maphandle);\r
- close (grhandle);\r
- close (audiohandle);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheAudioChunk\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheAudioChunk (int chunk)\r
-{\r
- long pos,compressed;\r
-#ifdef AUDIOHEADERLINKED\r
- long expanded;\r
- memptr bigbufferseg;\r
- byte far *source;\r
-#endif\r
-\r
- if (audiosegs[chunk])\r
- {\r
- MM_SetPurge (&(memptr)audiosegs[chunk],0);\r
- return; // allready in memory\r
- }\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = audiostarts[chunk];\r
- compressed = audiostarts[chunk+1]-pos;\r
-\r
- lseek(audiohandle,pos,SEEK_SET);\r
-\r
-#ifndef AUDIOHEADERLINKED\r
-\r
- MM_GetPtr (&(memptr)audiosegs[chunk],compressed);\r
- if (mmerror)\r
- return;\r
-\r
- CA_FarRead(audiohandle,audiosegs[chunk],compressed);\r
-\r
-#else\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(audiohandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(audiohandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- expanded = *(long far *)source;\r
- source += 4; // skip over length\r
- MM_GetPtr (&(memptr)audiosegs[chunk],expanded);\r
- if (mmerror)\r
- goto done;\r
- CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman);\r
-\r
-done:\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_LoadAllSounds\r
-=\r
-= Purges all sounds, then loads all new ones (mode switch)\r
-=\r
-======================\r
-*/\r
-\r
-void CA_LoadAllSounds (void)\r
-{\r
- unsigned start,i;\r
-\r
- switch (oldsoundmode)\r
- {\r
- case sdm_Off:\r
- goto cachein;\r
- case sdm_PC:\r
- start = STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- start = STARTADLIBSOUNDS;\r
- break;\r
- }\r
-\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- if (audiosegs[start])\r
- MM_SetPurge (&(memptr)audiosegs[start],3); // make purgable\r
-\r
-cachein:\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_Off:\r
- return;\r
- case sdm_PC:\r
- start = STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- start = STARTADLIBSOUNDS;\r
- break;\r
- }\r
-\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- CA_CacheAudioChunk (start);\r
-\r
- oldsoundmode = SoundMode;\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if GRMODE == EGAGR\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ShiftSprite\r
-=\r
-= Make a shifted (one byte wider) copy of a sprite into another area\r
-=\r
-======================\r
-*/\r
-\r
-unsigned static sheight,swidth;\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift)\r
-{\r
-\r
- sheight = height; // because we are going to reassign bp\r
- swidth = width;\r
-\r
-asm mov ax,[segment]\r
-asm mov ds,ax // source and dest are in same segment, and all local\r
-\r
-asm mov bx,[source]\r
-asm mov di,[dest]\r
-\r
-asm mov bp,[pixshift]\r
-asm shl bp,1\r
-asm mov bp,WORD PTR [shifttabletable+bp] // bp holds pointer to shift table\r
-\r
-//\r
-// table shift the mask\r
-//\r
-asm mov dx,[ss:sheight]\r
-\r
-domaskrow:\r
-\r
-asm mov BYTE PTR [di],255 // 0xff first byte\r
-asm mov cx,ss:[swidth]\r
-\r
-domaskbyte:\r
-\r
-asm mov al,[bx] // source\r
-asm not al\r
-asm inc bx // next source byte\r
-asm xor ah,ah\r
-asm shl ax,1\r
-asm mov si,ax\r
-asm mov ax,[bp+si] // table shift into two bytes\r
-asm not ax\r
-asm and [di],al // and with first byte\r
-asm inc di\r
-asm mov [di],ah // replace next byte\r
-\r
-asm loop domaskbyte\r
-\r
-asm inc di // the last shifted byte has 1s in it\r
-asm dec dx\r
-asm jnz domaskrow\r
-\r
-//\r
-// table shift the data\r
-//\r
-asm mov dx,ss:[sheight]\r
-asm shl dx,1\r
-asm shl dx,1 // four planes of data\r
-\r
-dodatarow:\r
-\r
-asm mov BYTE PTR [di],0 // 0 first byte\r
-asm mov cx,ss:[swidth]\r
-\r
-dodatabyte:\r
-\r
-asm mov al,[bx] // source\r
-asm inc bx // next source byte\r
-asm xor ah,ah\r
-asm shl ax,1\r
-asm mov si,ax\r
-asm mov ax,[bp+si] // table shift into two bytes\r
-asm or [di],al // or with first byte\r
-asm inc di\r
-asm mov [di],ah // replace next byte\r
-\r
-asm loop dodatabyte\r
-\r
-asm inc di // the last shifted byte has 0s in it\r
-asm dec dx\r
-asm jnz dodatarow\r
-\r
-//\r
-// done\r
-//\r
-\r
-asm mov ax,ss // restore data segment\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_CacheSprite\r
-=\r
-= Generate shifts and set up sprite structure for a given sprite\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_CacheSprite (int chunk, byte far *compressed)\r
-{\r
- int i;\r
- unsigned shiftstarts[5];\r
- unsigned smallplane,bigplane,expanded;\r
- spritetabletype far *spr;\r
- spritetype _seg *dest;\r
-\r
-#if GRMODE == CGAGR\r
-//\r
-// CGA has no pel panning, so shifts are never needed\r
-//\r
- spr = &spritetable[chunk-STARTSPRITES];\r
- smallplane = spr->width*spr->height;\r
- MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6);\r
- if (mmerror)\r
- return;\r
- dest = (spritetype _seg *)grsegs[chunk];\r
- dest->sourceoffset[0] = MAXSHIFTS*6; // start data after 3 unsigned tables\r
- dest->planesize[0] = smallplane;\r
- dest->width[0] = spr->width;\r
-\r
-//\r
-// expand the unshifted shape\r
-//\r
- CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,grhuffman);\r
-\r
-#endif\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-//\r
-// calculate sizes\r
-//\r
- spr = &spritetable[chunk-STARTSPRITES];\r
- smallplane = spr->width*spr->height;\r
- bigplane = (spr->width+1)*spr->height;\r
-\r
- shiftstarts[0] = MAXSHIFTS*6; // start data after 3 unsigned tables\r
- shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite\r
- shiftstarts[2] = shiftstarts[1] + bigplane*5;\r
- shiftstarts[3] = shiftstarts[2] + bigplane*5;\r
- shiftstarts[4] = shiftstarts[3] + bigplane*5; // nothing ever put here\r
-\r
- expanded = shiftstarts[spr->shifts];\r
- MM_GetPtr (&grsegs[chunk],expanded);\r
- if (mmerror)\r
- return;\r
- dest = (spritetype _seg *)grsegs[chunk];\r
-\r
-//\r
-// expand the unshifted shape\r
-//\r
- CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,grhuffman);\r
-\r
-//\r
-// make the shifts!\r
-//\r
- switch (spr->shifts)\r
- {\r
- case 1:\r
- for (i=0;i<4;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[0];\r
- dest->planesize[i] = smallplane;\r
- dest->width[i] = spr->width;\r
- }\r
- break;\r
-\r
- case 2:\r
- for (i=0;i<2;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[0];\r
- dest->planesize[i] = smallplane;\r
- dest->width[i] = spr->width;\r
- }\r
- for (i=2;i<4;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[1];\r
- dest->planesize[i] = bigplane;\r
- dest->width[i] = spr->width+1;\r
- }\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[2],spr->width,spr->height,4);\r
- break;\r
-\r
- case 4:\r
- dest->sourceoffset[0] = shiftstarts[0];\r
- dest->planesize[0] = smallplane;\r
- dest->width[0] = spr->width;\r
-\r
- dest->sourceoffset[1] = shiftstarts[1];\r
- dest->planesize[1] = bigplane;\r
- dest->width[1] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[1],spr->width,spr->height,2);\r
-\r
- dest->sourceoffset[2] = shiftstarts[2];\r
- dest->planesize[2] = bigplane;\r
- dest->width[2] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[2],spr->width,spr->height,4);\r
-\r
- dest->sourceoffset[3] = shiftstarts[3];\r
- dest->planesize[3] = bigplane;\r
- dest->width[3] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[3],spr->width,spr->height,6);\r
-\r
- break;\r
-\r
- default:\r
- Quit ("CAL_CacheSprite: Bad shifts number!");\r
- }\r
-\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ExpandGrChunk\r
-=\r
-= Does whatever is needed with a pointer to a compressed chunk\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_ExpandGrChunk (int chunk, byte far *source)\r
-{\r
- long expanded;\r
-\r
-\r
- if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)\r
- {\r
- //\r
- // expanded sizes of tile8/16/32 are implicit\r
- //\r
-\r
-#if GRMODE == EGAGR\r
-#define BLOCK 32\r
-#define MASKBLOCK 40\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-#define BLOCK 16\r
-#define MASKBLOCK 32\r
-#endif\r
-\r
- if (chunk<STARTTILE8M) // tile 8s are all in one chunk!\r
- expanded = BLOCK*NUMTILE8;\r
- else if (chunk<STARTTILE16)\r
- expanded = MASKBLOCK*NUMTILE8M;\r
- else if (chunk<STARTTILE16M) // all other tiles are one/chunk\r
- expanded = BLOCK*4;\r
- else if (chunk<STARTTILE32)\r
- expanded = MASKBLOCK*4;\r
- else if (chunk<STARTTILE32M)\r
- expanded = BLOCK*16;\r
- else\r
- expanded = MASKBLOCK*16;\r
- }\r
- else\r
- {\r
- //\r
- // everything else has an explicit size longword\r
- //\r
- expanded = *(long far *)source;\r
- source += 4; // skip over length\r
- }\r
-\r
-//\r
-// allocate final space, decompress it, and free bigbuffer\r
-// Sprites need to have shifts made and various other junk\r
-//\r
- if (chunk>=STARTSPRITES && chunk< STARTTILE8)\r
- CAL_CacheSprite(chunk,source);\r
- else\r
- {\r
- MM_GetPtr (&grsegs[chunk],expanded);\r
- if (mmerror)\r
- return;\r
- CAL_HuffExpand (source,grsegs[chunk],expanded,grhuffman);\r
- }\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ReadGrChunk\r
-=\r
-= Gets a chunk off disk, optimizing reads to general buffer\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_ReadGrChunk (int chunk)\r
-{\r
- long pos,compressed;\r
- memptr bigbufferseg;\r
- byte far *source;\r
- int next;\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = GRFILEPOS(chunk);\r
- if (pos<0) // $FFFFFFFF start is a sparse tile\r
- return;\r
-\r
- next = chunk +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(grhandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (chunk,source);\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheGrChunk\r
-=\r
-= Makes sure a given chunk is in memory, loadiing it if needed\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheGrChunk (int chunk)\r
-{\r
- long pos,compressed;\r
- memptr bigbufferseg;\r
- byte far *source;\r
- int next;\r
-\r
- grneeded[chunk] |= ca_levelbit; // make sure it doesn't get removed\r
- if (grsegs[chunk])\r
- {\r
- MM_SetPurge (&grsegs[chunk],0);\r
- return; // allready in memory\r
- }\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = GRFILEPOS(chunk);\r
- if (pos<0) // $FFFFFFFF start is a sparse tile\r
- return;\r
-\r
- next = chunk +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(grhandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (chunk,source);\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-}\r
-\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheMap\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheMap (int mapnum)\r
-{\r
- long pos,compressed;\r
- int plane;\r
- memptr *dest,bigbufferseg;\r
- unsigned size;\r
- unsigned far *source;\r
-#ifdef MAPHEADERLINKED\r
- memptr buffer2seg;\r
- long expanded;\r
-#endif\r
-\r
-\r
-//\r
-// free up memory from last map\r
-//\r
- if (mapon>-1 && mapheaderseg[mapon])\r
- MM_SetPurge (&(memptr)mapheaderseg[mapon],3);\r
- for (plane=0;plane<MAPPLANES;plane++)\r
- if (mapsegs[plane])\r
- MM_FreePtr (&(memptr)mapsegs[plane]);\r
-\r
- mapon = mapnum;\r
-\r
-\r
-//\r
-// load map header\r
-// The header will be cached if it is still around\r
-//\r
- if (!mapheaderseg[mapnum])\r
- {\r
- pos = ((mapfiletype _seg *)tinf)->headeroffsets[mapnum];\r
- if (pos<0) // $FFFFFFFF start is a sparse map\r
- Quit ("CA_CacheMap: Tried to load a non existent map!");\r
-\r
- MM_GetPtr(&(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
- lseek(maphandle,pos,SEEK_SET);\r
- CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
- }\r
- else\r
- MM_SetPurge (&(memptr)mapheaderseg[mapnum],0);\r
-\r
-//\r
-// load the planes in\r
-// If a plane's pointer still exists it will be overwritten (levels are\r
-// allways reloaded, never cached)\r
-//\r
-\r
- size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2;\r
-\r
- for (plane = 0; plane<MAPPLANES; plane++)\r
- {\r
- pos = mapheaderseg[mapnum]->planestart[plane];\r
- compressed = mapheaderseg[mapnum]->planelength[plane];\r
-\r
- if (!compressed)\r
- continue; // the plane is not used in this game\r
-\r
- dest = &(memptr)mapsegs[plane];\r
- MM_GetPtr(dest,size);\r
-\r
- lseek(maphandle,pos,SEEK_SET);\r
- if (compressed<=BUFFERSIZE)\r
- source = bufferseg;\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- MM_SetLock (&bigbufferseg,true);\r
- source = bigbufferseg;\r
- }\r
-\r
- CA_FarRead(maphandle,(byte far *)source,compressed);\r
-#ifdef MAPHEADERLINKED\r
- //\r
- // unhuffman, then unRLEW\r
- // The huffman'd chunk has a two byte expanded length first\r
- // The resulting RLEW chunk also does, even though it's not really\r
- // needed\r
- //\r
- expanded = *source;\r
- source++;\r
- MM_GetPtr (&buffer2seg,expanded);\r
- CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);\r
- CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,\r
- ((mapfiletype _seg *)tinf)->RLEWtag);\r
- MM_FreePtr (&buffer2seg);\r
-\r
-#else\r
- //\r
- // unRLEW, skipping expanded length\r
- //\r
- CA_RLEWexpand (source+1, *dest,size,\r
- ((mapfiletype _seg *)tinf)->RLEWtag);\r
-#endif\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_UpLevel\r
-=\r
-= Goes up a bit level in the needed lists and clears it out.\r
-= Everything is made purgable\r
-=\r
-======================\r
-*/\r
-\r
-void CA_UpLevel (void)\r
-{\r
- if (ca_levelnum==7)\r
- Quit ("CA_UpLevel: Up past level 7!");\r
-\r
- ca_levelbit<<=1;\r
- ca_levelnum++;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_DownLevel\r
-=\r
-= Goes down a bit level in the needed lists and recaches\r
-= everything from the lower level\r
-=\r
-======================\r
-*/\r
-\r
-void CA_DownLevel (void)\r
-{\r
- if (!ca_levelnum)\r
- Quit ("CA_DownLevel: Down past level 0!");\r
- ca_levelbit>>=1;\r
- ca_levelnum--;\r
- CA_CacheMarks(NULL);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_ClearMarks\r
-=\r
-= Clears out all the marks at the current level\r
-=\r
-======================\r
-*/\r
-\r
-void CA_ClearMarks (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- grneeded[i]&=~ca_levelbit;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_ClearAllMarks\r
-=\r
-= Clears out all the marks on all the levels\r
-=\r
-======================\r
-*/\r
-\r
-void CA_ClearAllMarks (void)\r
-{\r
- _fmemset (grneeded,0,sizeof(grneeded));\r
- ca_levelbit = 1;\r
- ca_levelnum = 0;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_FreeGraphics\r
-=\r
-======================\r
-*/\r
-\r
-void CA_FreeGraphics (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grsegs[i])\r
- MM_SetPurge (&(memptr)grsegs[i],3);\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_SetAllPurge\r
-=\r
-= Make everything possible purgable\r
-=\r
-======================\r
-*/\r
-\r
-void CA_SetAllPurge (void)\r
-{\r
- int i;\r
-\r
- CA_ClearMarks ();\r
-\r
-//\r
-// free cursor sprite and background save\r
-//\r
- VW_FreeCursor ();\r
-\r
-//\r
-// free map headers and map planes\r
-//\r
- for (i=0;i<NUMMAPS;i++)\r
- if (mapheaderseg[i])\r
- MM_SetPurge (&(memptr)mapheaderseg[i],3);\r
-\r
- for (i=0;i<3;i++)\r
- if (mapsegs[i])\r
- MM_FreePtr (&(memptr)mapsegs[i]);\r
-\r
-//\r
-// free sounds\r
-//\r
- for (i=0;i<NUMSNDCHUNKS;i++)\r
- if (audiosegs[i])\r
- MM_SetPurge (&(memptr)audiosegs[i],3);\r
-\r
-//\r
-// free graphics\r
-//\r
- CA_FreeGraphics ();\r
-}\r
-\r
-\r
-void CA_SetGrPurge (void)\r
-{\r
- int i;\r
-\r
-//\r
-// free graphics\r
-//\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grsegs[i])\r
- MM_SetPurge (&(memptr)grsegs[i],3);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogDraw\r
-=\r
-======================\r
-*/\r
-\r
-#define NUMBARS (17l*8)\r
-#define BARSTEP 8\r
-\r
-unsigned thx,thy,lastx;\r
-long barx,barstep;\r
-\r
-void CAL_DialogDraw (char *title,unsigned numcache)\r
-{\r
- unsigned homex,homey,x;\r
-\r
- barstep = (NUMBARS<<16)/numcache;\r
-\r
-//\r
-// draw dialog window (masked tiles 12 - 20 are window borders)\r
-//\r
- US_CenterWindow (20,8);\r
- homex = PrintX;\r
- homey = PrintY;\r
-\r
- US_CPrint ("Loading");\r
- fontcolor = F_SECONDCOLOR;\r
- US_CPrint (title);\r
- fontcolor = F_BLACK;\r
-\r
-//\r
-// draw thermometer bar\r
-//\r
- thx = homex + 8;\r
- thy = homey + 32;\r
-#ifdef CAT3D\r
- VWB_DrawTile8(thx,thy,0); // CAT3D numbers\r
- VWB_DrawTile8(thx,thy+8,3);\r
- VWB_DrawTile8(thx,thy+16,6);\r
- VWB_DrawTile8(thx+17*8,thy,2);\r
- VWB_DrawTile8(thx+17*8,thy+8,5);\r
- VWB_DrawTile8(thx+17*8,thy+16,8);\r
- for (x=thx+8;x<thx+17*8;x+=8)\r
- {\r
- VWB_DrawTile8(x,thy,1);\r
- VWB_DrawTile8(x,thy+8,4);\r
- VWB_DrawTile8(x,thy+16,7);\r
- }\r
-#else\r
- VWB_DrawTile8(thx,thy,11); // KEEN numbers\r
- VWB_DrawTile8(thx,thy+8,14);\r
- VWB_DrawTile8(thx,thy+16,17);\r
- VWB_DrawTile8(thx+17*8,thy,13);\r
- VWB_DrawTile8(thx+17*8,thy+8,16);\r
- VWB_DrawTile8(thx+17*8,thy+16,19);\r
- for (x=thx+8;x<thx+17*8;x+=8)\r
- {\r
- VWB_DrawTile8(x,thy,12);\r
- VWB_DrawTile8(x,thy+8,15);\r
- VWB_DrawTile8(x,thy+16,18);\r
- }\r
-#endif\r
-\r
- thx += 4; // first line location\r
- thy += 5;\r
- barx = (long)thx<<16;\r
- lastx = thx;\r
-\r
- VW_UpdateScreen();\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogUpdate\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_DialogUpdate (void)\r
-{\r
- unsigned x,xh;\r
-\r
- barx+=barstep;\r
- xh = barx>>16;\r
- if (xh - lastx > BARSTEP)\r
- {\r
- for (x=lastx;x<=xh;x++)\r
-#if GRMODE == EGAGR\r
- VWB_Vlin (thy,thy+13,x,14);\r
-#endif\r
-#if GRMODE == CGAGR\r
- VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
-#endif\r
- lastx = xh;\r
- VW_UpdateScreen();\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogFinish\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_DialogFinish (void)\r
-{\r
- unsigned x,xh;\r
-\r
- xh = thx + NUMBARS;\r
- for (x=lastx;x<=xh;x++)\r
-#if GRMODE == EGAGR\r
- VWB_Vlin (thy,thy+13,x,14);\r
-#endif\r
-#if GRMODE == CGAGR\r
- VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
-#endif\r
- VW_UpdateScreen();\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheMarks\r
-=\r
-======================\r
-*/\r
-#define MAXEMPTYREAD 1024\r
-\r
-void CA_CacheMarks (char *title)\r
-{\r
- boolean dialog;\r
- int i,next,numcache;\r
- long pos,endpos,nextpos,nextendpos,compressed;\r
- long bufferstart,bufferend; // file position of general buffer\r
- byte far *source;\r
- memptr bigbufferseg;\r
-\r
- dialog = (title!=NULL);\r
-\r
- numcache = 0;\r
-//\r
-// go through and make everything not needed purgable\r
-//\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grneeded[i]&ca_levelbit)\r
- {\r
- if (grsegs[i]) // its allready in memory, make\r
- MM_SetPurge(&grsegs[i],0); // sure it stays there!\r
- else\r
- numcache++;\r
- }\r
- else\r
- {\r
- if (grsegs[i]) // not needed, so make it purgeable\r
- MM_SetPurge(&grsegs[i],3);\r
- }\r
-\r
- if (!numcache) // nothing to cache!\r
- return;\r
-\r
- if (dialog)\r
- {\r
-#ifdef PROFILE\r
- write(profilehandle,title,strlen(title));\r
- write(profilehandle,"\n",1);\r
-#endif\r
- if (drawcachebox)\r
- drawcachebox(title,numcache);\r
- }\r
-\r
-//\r
-// go through and load in anything still needed\r
-//\r
- bufferstart = bufferend = 0; // nothing good in buffer now\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if ( (grneeded[i]&ca_levelbit) && !grsegs[i])\r
- {\r
-//\r
-// update thermometer\r
-//\r
- if (dialog && updatecachebox)\r
- updatecachebox ();\r
-\r
- pos = GRFILEPOS(i);\r
- if (pos<0)\r
- continue;\r
-\r
- next = i +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
- endpos = pos+compressed;\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- if (bufferstart<=pos\r
- && bufferend>= endpos)\r
- {\r
- // data is allready in buffer\r
- source = (byte _seg *)bufferseg+(pos-bufferstart);\r
- }\r
- else\r
- {\r
- // load buffer with a new block from disk\r
- // try to get as many of the needed blocks in as possible\r
- while ( next < NUMCHUNKS )\r
- {\r
- while (next < NUMCHUNKS &&\r
- !(grneeded[next]&ca_levelbit && !grsegs[next]))\r
- next++;\r
- if (next == NUMCHUNKS)\r
- continue;\r
-\r
- nextpos = GRFILEPOS(next);\r
- while (GRFILEPOS(++next) == -1) // skip past any sparse tiles\r
- ;\r
- nextendpos = GRFILEPOS(next);\r
- if (nextpos - endpos <= MAXEMPTYREAD\r
- && nextendpos-pos <= BUFFERSIZE)\r
- endpos = nextendpos;\r
- else\r
- next = NUMCHUNKS; // read pos to posend\r
- }\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
- CA_FarRead(grhandle,bufferseg,endpos-pos);\r
- bufferstart = pos;\r
- bufferend = endpos;\r
- source = bufferseg;\r
- }\r
- }\r
- else\r
- {\r
- // big chunk, allocate temporary buffer\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- lseek(grhandle,pos,SEEK_SET);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (i,source);\r
- if (mmerror)\r
- return;\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-\r
- }\r
-\r
-//\r
-// finish up any thermometer remnants\r
-//\r
- if (dialog && finishcachebox)\r
- finishcachebox();\r
-}\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_CA.H\r
-\r
-#ifndef __TYPES__\r
-#include "ID_TYPES.H"\r
-#endif\r
-\r
-#ifndef __ID_MM__\r
-#include "ID_MM.H"\r
-#endif\r
-\r
-#ifndef __ID_GLOB__\r
-#include "ID_GLOB.H"\r
-#endif\r
-\r
-#define __ID_CA__\r
-\r
-//===========================================================================\r
-\r
-//#define NOMAPS\r
-//#define NOGRAPHICS\r
-//#define NOAUDIO\r
-\r
-#define MAPHEADERLINKED\r
-#define GRHEADERLINKED\r
-#define AUDIOHEADERLINKED\r
-\r
-#define NUMMAPS 30\r
-#define MAPPLANES 3\r
-\r
-#ifndef CAT3D\r
-//\r
-// tile info defines, as bytes after tinf the table starts\r
-//\r
-\r
-\r
-//\r
-// TILEINFO offsets\r
-//\r
-#define SPEED 402\r
-#define ANIM (SPEED+NUMTILE16)\r
-\r
-//\r
-// TILEINFOM offsets\r
-//\r
-#define NORTHWALL (ANIM+NUMTILE16)\r
-#define EASTWALL (NORTHWALL+NUMTILE16M)\r
-#define SOUTHWALL (EASTWALL+NUMTILE16M)\r
-#define WESTWALL (SOUTHWALL+NUMTILE16M)\r
-#define MANIM (WESTWALL+NUMTILE16M)\r
-#define INTILE (MANIM+NUMTILE16M)\r
-#define MSPEED (INTILE+NUMTILE16M)\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-typedef struct\r
-{\r
- long planestart[3];\r
- unsigned planelength[3];\r
- unsigned width,height;\r
- char name[16];\r
-} maptype;\r
-\r
-//===========================================================================\r
-\r
-extern byte _seg *tinf;\r
-extern int mapon;\r
-\r
-extern unsigned _seg *mapsegs[3];\r
-extern maptype _seg *mapheaderseg[NUMMAPS];\r
-extern byte _seg *audiosegs[NUMSNDCHUNKS];\r
-extern void _seg *grsegs[NUMCHUNKS];\r
-\r
-extern byte far grneeded[NUMCHUNKS];\r
-extern byte ca_levelbit,ca_levelnum;\r
-\r
-extern char *titleptr[8];\r
-\r
-extern int profilehandle,debughandle;\r
-\r
-//\r
-// hooks for custom cache dialogs\r
-//\r
-extern void (*drawcachebox) (char *title, unsigned numcache);\r
-extern void (*updatecachebox) (void);\r
-extern void (*finishcachebox) (void);\r
-\r
-//===========================================================================\r
-\r
-// just for the score box reshifting\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift);\r
-\r
-//===========================================================================\r
-\r
-void CA_OpenDebug (void);\r
-void CA_CloseDebug (void);\r
-boolean CA_FarRead (int handle, byte far *dest, long length);\r
-boolean CA_FarWrite (int handle, byte far *source, long length);\r
-boolean CA_ReadFile (char *filename, memptr *ptr);\r
-boolean CA_LoadFile (char *filename, memptr *ptr);\r
-\r
-long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,\r
- unsigned rlewtag);\r
-\r
-void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,\r
- unsigned rlewtag);\r
-\r
-void CA_Startup (void);\r
-void CA_Shutdown (void);\r
-\r
-void CA_CacheAudioChunk (int chunk);\r
-void CA_LoadAllSounds (void);\r
-\r
-void CA_UpLevel (void);\r
-void CA_DownLevel (void);\r
-\r
-void CA_SetAllPurge (void);\r
-\r
-void CA_ClearMarks (void);\r
-void CA_ClearAllMarks (void);\r
-\r
-#define CA_MarkGrChunk(chunk) grneeded[chunk]|=ca_levelbit\r
-\r
-void CA_CacheGrChunk (int chunk);\r
-void CA_CacheMap (int mapnum);\r
-\r
-void CA_CacheMarks (char *title);\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_IN.c - Input Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-//\r
-// This module handles dealing with the various input devices\r
-//\r
-// Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),\r
-// User Mgr (for command line parms)\r
-//\r
-// Globals:\r
-// LastScan - The keyboard scan code of the last key pressed\r
-// LastASCII - The ASCII value of the last key pressed\r
-// DEBUG - there are more globals\r
-//\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-#define KeyInt 9 // The keyboard ISR number\r
-\r
-// Stuff for the joystick\r
-#define JoyScaleMax 32768\r
-#define JoyScaleShift 8\r
-#define MaxJoyValue 5000\r
-\r
-// Global variables\r
- boolean Keyboard[NumCodes],\r
- JoysPresent[MaxJoys],\r
- MousePresent;\r
- boolean Paused;\r
- char LastASCII;\r
- ScanCode LastScan;\r
- KeyboardDef KbdDefs[MaxKbds] = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};\r
- JoystickDef JoyDefs[MaxJoys];\r
- ControlType Controls[MaxPlayers];\r
- boolean GravisGamepad;\r
- word GravisAction[4];\r
- word GravisMap[4];\r
-\r
- boolean Latch;\r
- long MouseDownCount;\r
- boolean LatchedButton0[MaxPlayers];\r
- boolean LatchedButton1[MaxPlayers];\r
-\r
- Demo DemoMode = demo_Off;\r
- byte _seg *DemoBuffer;\r
- word DemoOffset,DemoSize;\r
-\r
-// Internal variables\r
-static boolean IN_Started;\r
-static boolean CapsLock;\r
-static ScanCode CurCode,LastCode;\r
-static byte far ASCIINames[] = // Unshifted ASCII for scan codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0\r
- 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1\r
- 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2\r
- 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4\r
- '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
- far ShiftNames[] = // Shifted ASCII for scan codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0\r
- 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1\r
- 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2\r
- 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4\r
- '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
- far SpecialNames[] = // ASCII for 0xe0 prefixed codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2\r
- 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
-\r
- *ScanNames[] = // Scan code names with single chars\r
- {\r
- "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",\r
- "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",\r
- "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",\r
- "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",\r
- "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"\r
- }, // DEBUG - consolidate these\r
- far ExtScanCodes[] = // Scan codes with >1 char names\r
- {\r
- 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,\r
- 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,\r
- 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,\r
- 0x50,0x4b,0x4d,0x00\r
- },\r
- *ExtScanNames[] = // Names corresponding to ExtScanCodes\r
- {\r
- "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",\r
- "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",\r
- "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",\r
- "Down","Left","Right",""\r
- };\r
-static Direction DirTable[] = // Quick lookup for total direction\r
- {\r
- dir_NorthWest, dir_North, dir_NorthEast,\r
- dir_West, dir_None, dir_East,\r
- dir_SouthWest, dir_South, dir_SouthEast\r
- };\r
-\r
-static void (*INL_KeyHook)(void);\r
-static void interrupt (*OldKeyVect)(void);\r
-\r
-static char *ParmStrings[] = {"nojoys","nomouse",nil};\r
-\r
-// Internal routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_KeyService() - Handles a keyboard interrupt (key up/down)\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void interrupt\r
-INL_KeyService(void)\r
-{\r
-static boolean special;\r
- byte k,c,\r
- temp;\r
- int player;\r
-\r
- k = inportb(0x60); // Get the scan code\r
-\r
- // Tell the XT keyboard controller to clear the key\r
- outportb(0x61,(temp = inportb(0x61)) | 0x80);\r
- outportb(0x61,temp);\r
-\r
- if (k == 0xe0) // Special key prefix\r
- special = true;\r
- else if (k == 0xe1) // Handle Pause key\r
- Paused = true;\r
- else\r
- {\r
- if (k & 0x80) // Break code\r
- {\r
- k &= 0x7f;\r
-\r
-// DEBUG - handle special keys: ctl-alt-delete, print scrn\r
-\r
- Keyboard[k] = false;\r
- }\r
- else // Make code\r
- {\r
- LastCode = CurCode;\r
- CurCode = LastScan = k;\r
- Keyboard[k] = true;\r
-\r
- if (Latch)\r
- {\r
- for (player = 0; player < MaxPlayers; player++)\r
- {\r
- if (Controls[player] == ctrl_Keyboard1)\r
- {\r
- if (CurCode == KbdDefs[0].button0)\r
- LatchedButton0[player] = true;\r
- else if (CurCode == KbdDefs[0].button1)\r
- LatchedButton1[player] = true;\r
- }\r
- else if (Controls[player] == ctrl_Keyboard1) // BUG? should probably check for ctrl_Keyboard2 here...\r
- {\r
- if (CurCode == KbdDefs[1].button0)\r
- LatchedButton0[player] = true;\r
- else if (CurCode == KbdDefs[1].button1)\r
- LatchedButton1[player] = true;\r
- }\r
- }\r
- }\r
-\r
- if (special)\r
- c = SpecialNames[k];\r
- else\r
- {\r
- if (k == sc_CapsLock)\r
- {\r
- CapsLock ^= true;\r
- // DEBUG - make caps lock light work\r
- }\r
-\r
- if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted\r
- {\r
- c = ShiftNames[k];\r
- if ((c >= 'A') && (c <= 'Z') && CapsLock)\r
- c += 'a' - 'A';\r
- }\r
- else\r
- {\r
- c = ASCIINames[k];\r
- if ((c >= 'a') && (c <= 'z') && CapsLock)\r
- c -= 'a' - 'A';\r
- }\r
- }\r
- if (c)\r
- LastASCII = c;\r
- }\r
-\r
- special = false;\r
- }\r
-\r
- if (INL_KeyHook && !special)\r
- INL_KeyHook();\r
- outportb(0x20,0x20);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetMouseDelta() - Gets the amount that the mouse has moved from the\r
-// mouse driver\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_GetMouseDelta(int *x,int *y)\r
-{\r
- Mouse(MDelta);\r
- *x = _CX;\r
- *y = _DX;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetMouseButtons() - Gets the status of the mouse buttons from the\r
-// mouse driver\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static word\r
-INL_GetMouseButtons(void)\r
-{\r
- word buttons;\r
-\r
- Mouse(MButtons);\r
- buttons = _BX;\r
- return(buttons);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_GetJoyAbs() - Reads the absolute position of the specified joystick\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_GetJoyAbs(word joy,word *xp,word *yp)\r
-{\r
- byte xb,yb,\r
- xs,ys;\r
- word x,y;\r
-\r
- x = y = 0;\r
- xs = joy? 2 : 0; // Find shift value for x axis\r
- xb = 1 << xs; // Use shift value to get x bit mask\r
- ys = joy? 3 : 1; // Do the same for y axis\r
- yb = 1 << ys;\r
-\r
-// Read the absolute joystick values\r
-asm pushf // Save some registers\r
-asm push si\r
-asm push di\r
-asm cli // Make sure an interrupt doesn't screw the timings\r
-\r
-\r
-asm mov dx,0x201\r
-asm in al,dx\r
-asm out dx,al // Clear the resistors\r
-\r
-asm mov ah,[xb] // Get masks into registers\r
-asm mov ch,[yb]\r
-\r
-asm xor si,si // Clear count registers\r
-asm xor di,di\r
-asm xor bh,bh // Clear high byte of bx for later\r
-\r
-asm push bp // Don't mess up stack frame\r
-asm mov bp,MaxJoyValue\r
-\r
-loop:\r
-asm in al,dx // Get bits indicating whether all are finished\r
-\r
-asm dec bp // Check bounding register\r
-asm jz done // We have a silly value - abort\r
-\r
-asm mov bl,al // Duplicate the bits\r
-asm and bl,ah // Mask off useless bits (in [xb])\r
-asm add si,bx // Possibly increment count register\r
-asm mov cl,bl // Save for testing later\r
-\r
-asm mov bl,al\r
-asm and bl,ch // [yb]\r
-asm add di,bx\r
-\r
-asm add cl,bl\r
-asm jnz loop // If both bits were 0, drop out\r
-\r
-done:\r
-asm pop bp\r
-\r
-asm mov cl,[xs] // Get the number of bits to shift\r
-asm shr si,cl // and shift the count that many times\r
-\r
-asm mov cl,[ys]\r
-asm shr di,cl\r
-\r
-asm mov [x],si // Store the values into the variables\r
-asm mov [y],di\r
-\r
-asm pop di\r
-asm pop si\r
-asm popf // Restore the registers\r
-\r
- *xp = x;\r
- *yp = y;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetJoyDelta() - Returns the relative movement of the specified\r
-// joystick (from +/-127, scaled adaptively)\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)\r
-{\r
- word x,y;\r
- longword time;\r
- JoystickDef *def;\r
-static longword lasttime;\r
-\r
- IN_GetJoyAbs(joy,&x,&y);\r
- def = JoyDefs + joy;\r
-\r
- if (x < def->threshMinX)\r
- {\r
- if (x < def->joyMinX)\r
- x = def->joyMinX;\r
-\r
- x = -(x - def->threshMinX);\r
- x *= def->joyMultXL;\r
- x >>= JoyScaleShift;\r
- *dx = (x > 127)? -127 : -x;\r
- }\r
- else if (x > def->threshMaxX)\r
- {\r
- if (x > def->joyMaxX)\r
- x = def->joyMaxX;\r
-\r
- x = x - def->threshMaxX;\r
- x *= def->joyMultXH;\r
- x >>= JoyScaleShift;\r
- *dx = (x > 127)? 127 : x;\r
- }\r
- else\r
- *dx = 0;\r
-\r
- if (y < def->threshMinY)\r
- {\r
- if (y < def->joyMinY)\r
- y = def->joyMinY;\r
-\r
- y = -(y - def->threshMinY);\r
- y *= def->joyMultYL;\r
- y >>= JoyScaleShift;\r
- *dy = (y > 127)? -127 : -y;\r
- }\r
- else if (y > def->threshMaxY)\r
- {\r
- if (y > def->joyMaxY)\r
- y = def->joyMaxY;\r
-\r
- y = y - def->threshMaxY;\r
- y *= def->joyMultYH;\r
- y >>= JoyScaleShift;\r
- *dy = (y > 127)? 127 : y;\r
- }\r
- else\r
- *dy = 0;\r
-\r
- if (adaptive)\r
- {\r
- time = (TimeCount - lasttime) / 2;\r
- if (time)\r
- {\r
- if (time > 8)\r
- time = 8;\r
- *dx *= time;\r
- *dy *= time;\r
- }\r
- }\r
- lasttime = TimeCount;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetJoyButtons() - Returns the button status of the specified\r
-// joystick\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static word\r
-INL_GetJoyButtons(word joy)\r
-{\r
-register word result;\r
-\r
- result = inportb(0x201); // Get all the joystick buttons\r
- if (joy == 2)\r
- {\r
- // all 4 buttons (for Gravis Gamepad option)\r
- result >>= 4;\r
- result &= 15;\r
- result ^= 15;\r
- }\r
- else\r
- {\r
- result >>= joy? 6 : 4; // Shift into bits 0-1\r
- result &= 3; // Mask off the useless bits\r
- result ^= 3;\r
- }\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_GetJoyButtonsDB() - Returns the de-bounced button status of the\r
-// specified joystick\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-word\r
-IN_GetJoyButtonsDB(word joy)\r
-{\r
- longword endtime;\r
- word result1,result2;\r
-\r
- do\r
- {\r
- result1 = INL_GetJoyButtons(joy);\r
- endtime = TimeCount + 2;\r
- while (TimeCount <= endtime)\r
- ;\r
- result2 = INL_GetJoyButtons(joy);\r
- } while (result1 != result2);\r
- return(result1);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_StartKbd() - Sets up my keyboard stuff for use\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_StartKbd(void)\r
-{\r
- INL_KeyHook = 0; // Clear key hook\r
-\r
- IN_ClearKeysDown();\r
-\r
- OldKeyVect = getvect(KeyInt);\r
- setvect(KeyInt,INL_KeyService);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_ShutKbd() - Restores keyboard control to the BIOS\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_ShutKbd(void)\r
-{\r
- poke(0x40,0x17,peek(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags\r
-\r
- setvect(KeyInt,OldKeyVect);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_StartMouse() - Detects and sets up the mouse\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-INL_StartMouse(void)\r
-{\r
- if (getvect(MouseInt))\r
- {\r
- Mouse(MReset);\r
- if (_AX == 0xffff)\r
- return(true);\r
- }\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_ShutMouse() - Cleans up after the mouse\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_ShutMouse(void)\r
-{\r
-}\r
-\r
-//\r
-// INL_SetJoyScale() - Sets up scaling values for the specified joystick\r
-//\r
-static void\r
-INL_SetJoyScale(word joy)\r
-{\r
- JoystickDef *def;\r
-\r
- def = &JoyDefs[joy];\r
- def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);\r
- def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);\r
- def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);\r
- def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()\r
-// to set up scaling values\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)\r
-{\r
- word d,r;\r
- JoystickDef *def;\r
-\r
- def = &JoyDefs[joy];\r
-\r
- def->joyMinX = minx;\r
- def->joyMaxX = maxx;\r
- r = maxx - minx;\r
- d = r / 5;\r
- def->threshMinX = ((r / 2) - d) + minx;\r
- def->threshMaxX = ((r / 2) + d) + minx;\r
-\r
- def->joyMinY = miny;\r
- def->joyMaxY = maxy;\r
- r = maxy - miny;\r
- d = r / 5;\r
- def->threshMinY = ((r / 2) - d) + miny;\r
- def->threshMaxY = ((r / 2) + d) + miny;\r
-\r
- INL_SetJoyScale(joy);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_StartJoy() - Detects & auto-configures the specified joystick\r
-// The auto-config assumes the joystick is centered\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-INL_StartJoy(word joy)\r
-{\r
- word x,y;\r
-\r
- IN_GetJoyAbs(joy,&x,&y);\r
-\r
- if\r
- (\r
- ((x == 0) || (x > MaxJoyValue - 10))\r
- || ((y == 0) || (y > MaxJoyValue - 10))\r
- )\r
- return(false);\r
- else\r
- {\r
- IN_SetupJoy(joy,0,x * 2,0,y * 2);\r
- return(true);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_ShutJoy() - Cleans up the joystick stuff\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_ShutJoy(word joy)\r
-{\r
- JoysPresent[joy] = false;\r
-}\r
-\r
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ClearButtonLatch() - Clears the button latch stuff\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ClearButtonLatch(void)\r
-{\r
- int player;\r
-\r
-asm pushf\r
-asm cli\r
-\r
- MouseDownCount = 0;\r
-\r
- for (player = 0; player < MaxPlayers; player++)\r
- {\r
- LatchedButton0[player] = LatchedButton1[player] = 0;\r
- }\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// LatchSndHook() - Hook routine for joystick button latch\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-LatchSndHook(void)\r
-{\r
- int player;\r
- ControlType ctrl;\r
- word buttons;\r
-\r
- for (player = 0; player < MaxPlayers; player++)\r
- {\r
- ctrl = Controls[player];\r
-\r
- if (ctrl == ctrl_Joystick1 || ctrl == ctrl_Joystick2)\r
- {\r
- buttons = INL_GetJoyButtons(ctrl - ctrl_Joystick1);\r
-\r
- if (buttons & 1)\r
- LatchedButton0[player] = true;\r
- if (buttons & 2)\r
- LatchedButton1[player] = true;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_LatchButtons() - Enables or disables button latch\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void IN_LatchButtons(boolean enabled)\r
-{\r
- if (enabled)\r
- {\r
- Latch = false;\r
- IN_ClearButtonLatch();\r
- }\r
-\r
- Latch = enabled;\r
- SD_SetUserHook(Latch ? LatchSndHook : NULL);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Startup() - Starts up the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Startup(void)\r
-{\r
- boolean checkjoys,checkmouse;\r
- word i;\r
-\r
- if (IN_Started)\r
- return;\r
-\r
- checkjoys = true;\r
- checkmouse = true;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],ParmStrings))\r
- {\r
- case 0:\r
- checkjoys = false;\r
- break;\r
- case 1:\r
- checkmouse = false;\r
- break;\r
- }\r
- }\r
-\r
- INL_StartKbd();\r
- MousePresent = checkmouse? INL_StartMouse() : false;\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;\r
-\r
- IN_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Default() - Sets up default conditions for the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Default(boolean gotit,ControlType in)\r
-{\r
- if\r
- (\r
- (!gotit)\r
- || ((in == ctrl_Joystick1) && !JoysPresent[0])\r
- || ((in == ctrl_Joystick2) && !JoysPresent[1])\r
- || ((in == ctrl_Mouse) && !MousePresent)\r
- )\r
- in = ctrl_Keyboard1;\r
- IN_SetControlType(0,in);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Shutdown() - Shuts down the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Shutdown(void)\r
-{\r
- word i;\r
-\r
- if (!IN_Started)\r
- return;\r
-\r
- INL_ShutMouse();\r
- for (i = 0;i < MaxJoys;i++)\r
- INL_ShutJoy(i);\r
- INL_ShutKbd();\r
-\r
- IN_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()\r
-// everytime a real make/break code gets hit\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_SetKeyHook(void (*hook)())\r
-{\r
- // BUG: interrupts should be disabled while setting INL_KeyHook!\r
- INL_KeyHook = hook;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ClearKeyDown() - Clears the keyboard array\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ClearKeysDown(void)\r
-{\r
- int i;\r
-\r
- LastScan = sc_None;\r
- LastASCII = key_None;\r
- for (i = 0;i < NumCodes;i++)\r
- Keyboard[i] = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)\r
-{\r
- if (buttons & (1 << 0))\r
- info->button0 = true;\r
- if (buttons & (1 << 1))\r
- info->button1 = true;\r
-\r
- info->x += dx;\r
- info->y += dy;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ReadCursor() - Reads the input devices and fills in the cursor info\r
-// struct\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ReadCursor(CursorInfo *info)\r
-{\r
- word i,\r
- player,\r
- buttons;\r
- int dx,dy;\r
-\r
- info->x = info->y = 0;\r
- info->button0 = info->button1 = false;\r
-\r
- if (MousePresent)\r
- {\r
- buttons = INL_GetMouseButtons();\r
- INL_GetMouseDelta(&dx,&dy);\r
- INL_AdjustCursor(info,buttons,dx,dy);\r
- }\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- {\r
- if (!JoysPresent[i])\r
- continue;\r
-\r
- for (player = 0;player < MaxPlayers; player++)\r
- {\r
- if (Controls[player] == ctrl_Joystick1+i)\r
- goto joyok;\r
- }\r
- continue;\r
-\r
-joyok:\r
- buttons = INL_GetJoyButtons(i);\r
- INL_GetJoyDelta(i,&dx,&dy,true);\r
- dx /= 64;\r
- dy /= 64;\r
- INL_AdjustCursor(info,buttons,dx,dy);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ReadControl() - Reads the device associated with the specified\r
-// player and fills in the control info struct\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ReadControl(int player,ControlInfo *info)\r
-{\r
- boolean realdelta;\r
- byte dbyte;\r
- word buttons;\r
- int i;\r
- int dx,dy;\r
- Motion mx,my;\r
- ControlType type;\r
-register KeyboardDef *def;\r
-\r
- dx = dy = 0;\r
- mx = my = motion_None;\r
- buttons = 0;\r
-\r
- if (DemoMode == demo_Playback)\r
- {\r
- dbyte = DemoBuffer[DemoOffset + 1];\r
- my = (dbyte & 3) - 1;\r
- mx = ((dbyte >> 2) & 3) - 1;\r
- buttons = (dbyte >> 4) & 3;\r
-\r
- if (!(--DemoBuffer[DemoOffset]))\r
- {\r
- DemoOffset += 2;\r
- if (DemoOffset >= DemoSize)\r
- DemoMode = demo_PlayDone;\r
- }\r
-\r
- realdelta = false;\r
- }\r
- else if (DemoMode == demo_PlayDone)\r
- Quit("Demo playback exceeded");\r
- else\r
- {\r
- switch (type = Controls[player])\r
- {\r
- case ctrl_Keyboard1:\r
- case ctrl_Keyboard2:\r
- def = &KbdDefs[type - ctrl_Keyboard];\r
-\r
- if (Keyboard[def->upleft])\r
- mx = motion_Left,my = motion_Up;\r
- else if (Keyboard[def->upright])\r
- mx = motion_Right,my = motion_Up;\r
- else if (Keyboard[def->downleft])\r
- mx = motion_Left,my = motion_Down;\r
- else if (Keyboard[def->downright])\r
- mx = motion_Right,my = motion_Down;\r
-\r
- if (Keyboard[def->up])\r
- my = motion_Up;\r
- else if (Keyboard[def->down])\r
- my = motion_Down;\r
-\r
- if (Keyboard[def->left])\r
- mx = motion_Left;\r
- else if (Keyboard[def->right])\r
- mx = motion_Right;\r
-\r
- if (Keyboard[def->button0])\r
- buttons += 1 << 0;\r
- if (Keyboard[def->button1])\r
- buttons += 1 << 1;\r
- realdelta = false;\r
- break;\r
- case ctrl_Joystick1:\r
- case ctrl_Joystick2:\r
- INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);\r
- if (GravisGamepad)\r
- {\r
- buttons = INL_GetJoyButtons(2);\r
- for (i=0; i<4; i++)\r
- {\r
- GravisAction[i] = buttons & (1 << GravisMap[i]);\r
- }\r
- }\r
- buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
- realdelta = true;\r
- break;\r
- case ctrl_Mouse:\r
- INL_GetMouseDelta(&dx,&dy);\r
- buttons = INL_GetMouseButtons();\r
- realdelta = true;\r
- break;\r
- }\r
- }\r
-\r
- if (realdelta)\r
- {\r
- mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);\r
- my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);\r
- }\r
- else\r
- {\r
- dx = mx * 127;\r
- dy = my * 127;\r
- }\r
-\r
- info->x = dx;\r
- info->xaxis = mx;\r
- info->y = dy;\r
- info->yaxis = my;\r
- info->button0 = buttons & (1 << 0);\r
- info->button1 = buttons & (1 << 1);\r
- info->dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
-\r
- if (DemoMode == demo_Record)\r
- {\r
- // Pack the control info into a byte\r
- dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);\r
-\r
- if\r
- (\r
- (DemoBuffer[DemoOffset + 1] == dbyte)\r
- && (DemoBuffer[DemoOffset] < 255)\r
- )\r
- (DemoBuffer[DemoOffset])++;\r
- else\r
- {\r
- if (DemoOffset || DemoBuffer[DemoOffset])\r
- DemoOffset += 2;\r
-\r
- if (DemoOffset >= DemoSize)\r
- Quit("Demo buffer overflow");\r
-\r
- DemoBuffer[DemoOffset] = 1;\r
- DemoBuffer[DemoOffset + 1] = dbyte;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_SetControlType() - Sets the control type to be used by the specified\r
-// player\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_SetControlType(int player,ControlType type)\r
-{\r
- // DEBUG - check that requested type is present?\r
- Controls[player] = type;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_StartDemoRecord() - Starts the demo recording, using a buffer the\r
-// size passed. Returns if the buffer allocation was successful\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-IN_StartDemoRecord(word bufsize)\r
-{\r
- if (!bufsize)\r
- return(false);\r
-\r
- MM_GetPtr((memptr *)&DemoBuffer,bufsize);\r
- DemoMode = demo_Record;\r
- DemoSize = bufsize & ~1;\r
- DemoOffset = 0;\r
- DemoBuffer[0] = DemoBuffer[1] = 0;\r
-\r
- return(true);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_StartDemoPlayback() - Plays back the demo pointed to of the given size\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_StartDemoPlayback(byte _seg *buffer,word bufsize)\r
-{\r
- DemoBuffer = buffer;\r
- DemoMode = demo_Playback;\r
- DemoSize = bufsize & ~1;\r
- DemoOffset = 0;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_StopDemo() - Turns off demo mode\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_StopDemo(void)\r
-{\r
- if ((DemoMode == demo_Record) && DemoOffset)\r
- DemoOffset += 2;\r
-\r
- DemoMode = demo_Off;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_FreeDemoBuffer(void)\r
-{\r
- if (DemoBuffer)\r
- MM_FreePtr((memptr *)&DemoBuffer);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_GetScanName() - Returns a string containing the name of the\r
-// specified scan code\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-byte *\r
-IN_GetScanName(ScanCode scan)\r
-{\r
- byte **p;\r
- ScanCode far *s;\r
-\r
- for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)\r
- if (*s == scan)\r
- return(*p);\r
-\r
- return(ScanNames[scan]);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_WaitForKey() - Waits for a scan code, then clears LastScan and\r
-// returns the scan code\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-ScanCode\r
-IN_WaitForKey(void)\r
-{\r
- ScanCode result;\r
-\r
- while (!(result = LastScan))\r
- ;\r
- LastScan = 0;\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and\r
-// returns the ASCII value\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-char\r
-IN_WaitForASCII(void)\r
-{\r
- char result;\r
-\r
- while (!(result = LastASCII))\r
- ;\r
- LastASCII = '\0';\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_AckBack() - Waits for either an ASCII keypress or a button press\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_AckBack(void)\r
-{\r
- word i;\r
-\r
- while (!LastScan)\r
- {\r
- if (MousePresent)\r
- {\r
- if (INL_GetMouseButtons())\r
- {\r
- while (INL_GetMouseButtons())\r
- ;\r
- return;\r
- }\r
- }\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- {\r
- if (JoysPresent[i] || GravisGamepad)\r
- {\r
- if (IN_GetJoyButtonsDB(i))\r
- {\r
- while (IN_GetJoyButtonsDB(i))\r
- ;\r
- return;\r
- }\r
- }\r
- }\r
- }\r
-\r
- IN_ClearKey(LastScan);\r
- LastScan = sc_None;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Ack() - Clears user input & then calls IN_AckBack()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Ack(void)\r
-{\r
- word i;\r
-\r
- IN_ClearKey(LastScan);\r
- LastScan = sc_None;\r
-\r
- if (MousePresent)\r
- while (INL_GetMouseButtons())\r
- ;\r
- for (i = 0;i < MaxJoys;i++)\r
- if (JoysPresent[i] || GravisGamepad)\r
- while (IN_GetJoyButtonsDB(i))\r
- ;\r
-\r
- IN_AckBack();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_IsUserInput() - Returns true if a key has been pressed or a button\r
-// is down\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-IN_IsUserInput(void)\r
-{\r
- boolean result;\r
- word i;\r
-\r
- result = LastScan;\r
-\r
- if (MousePresent)\r
- if (INL_GetMouseButtons())\r
- result = true;\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- if (JoysPresent[i] || GravisGamepad)\r
- if (INL_GetJoyButtons(i))\r
- result = true;\r
-\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_UserInput() - Waits for the specified delay time (in ticks) or the\r
-// user pressing a key or a mouse button. If the clear flag is set, it\r
-// then either clears the key or waits for the user to let the mouse\r
-// button up.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-IN_UserInput(longword delay,boolean clear)\r
-{\r
- longword lasttime;\r
-\r
- lasttime = TimeCount;\r
- do\r
- {\r
- if (IN_IsUserInput())\r
- {\r
- if (clear)\r
- IN_AckBack();\r
- return(true);\r
- }\r
- } while (TimeCount - lasttime < delay);\r
- return(false);\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_IN.h - Header file for Input Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-#ifndef __TYPES__\r
-#include "ID_Types.h"\r
-#endif\r
-\r
-#ifndef __ID_IN__\r
-#define __ID_IN__\r
-\r
-#ifdef __DEBUG__\r
-#define __DEBUG_InputMgr__\r
-#endif\r
-\r
-#define MaxPlayers 4\r
-#define MaxKbds 2\r
-#define MaxJoys 2\r
-#define NumCodes 128\r
-\r
-typedef byte ScanCode;\r
-#define sc_None 0\r
-#define sc_Bad 0xff\r
-#define sc_Return 0x1c\r
-#define sc_Enter sc_Return\r
-#define sc_Escape 0x01\r
-#define sc_Space 0x39\r
-#define sc_BackSpace 0x0e\r
-#define sc_Tab 0x0f\r
-#define sc_Alt 0x38\r
-#define sc_Control 0x1d\r
-#define sc_CapsLock 0x3a\r
-#define sc_LShift 0x2a\r
-#define sc_RShift 0x36\r
-#define sc_UpArrow 0x48\r
-#define sc_DownArrow 0x50\r
-#define sc_LeftArrow 0x4b\r
-#define sc_RightArrow 0x4d\r
-#define sc_Insert 0x52\r
-#define sc_Delete 0x53\r
-#define sc_Home 0x47\r
-#define sc_End 0x4f\r
-#define sc_PgUp 0x49\r
-#define sc_PgDn 0x51\r
-#define sc_F1 0x3b\r
-#define sc_F2 0x3c\r
-#define sc_F3 0x3d\r
-#define sc_F4 0x3e\r
-#define sc_F5 0x3f\r
-#define sc_F6 0x40\r
-#define sc_F7 0x41\r
-#define sc_F8 0x42\r
-#define sc_F9 0x43\r
-#define sc_F10 0x44\r
-#define sc_F11 0x57\r
-#define sc_F12 0x59 // BUG: F12 uses scan code 0x58!\r
-\r
-#define sc_A 0x1e\r
-#define sc_B 0x30\r
-#define sc_C 0x2e\r
-#define sc_D 0x20\r
-#define sc_E 0x12\r
-#define sc_F 0x21\r
-#define sc_G 0x22\r
-#define sc_H 0x23\r
-#define sc_I 0x17\r
-#define sc_J 0x24\r
-#define sc_K 0x25\r
-#define sc_L 0x26\r
-#define sc_M 0x32\r
-#define sc_N 0x31\r
-#define sc_O 0x18\r
-#define sc_P 0x19\r
-#define sc_Q 0x10\r
-#define sc_R 0x13\r
-#define sc_S 0x1f\r
-#define sc_T 0x14\r
-#define sc_U 0x16\r
-#define sc_V 0x2f\r
-#define sc_W 0x11\r
-#define sc_X 0x2d\r
-#define sc_Y 0x15\r
-#define sc_Z 0x2c\r
-\r
-#define sc_1 0x02\r
-#define sc_2 0x03\r
-#define sc_3 0x04\r
-#define sc_4 0x05\r
-#define sc_5 0x06\r
-#define sc_6 0x07\r
-#define sc_7 0x08\r
-#define sc_8 0x09\r
-#define sc_9 0x0a\r
-#define sc_0 0x0b\r
-\r
-#define key_None 0\r
-#define key_Return 0x0d\r
-#define key_Enter key_Return\r
-#define key_Escape 0x1b\r
-#define key_Space 0x20\r
-#define key_BackSpace 0x08\r
-#define key_Tab 0x09\r
-#define key_Delete 0x7f\r
-\r
-// Stuff for the mouse\r
-#define MReset 0\r
-#define MButtons 3\r
-#define MDelta 11\r
-\r
-#define MouseInt 0x33\r
-#define Mouse(x) _AX = x,geninterrupt(MouseInt)\r
-\r
-typedef enum {\r
- demo_Off,demo_Record,demo_Playback,demo_PlayDone\r
- } Demo;\r
-typedef enum {\r
- ctrl_Keyboard,\r
- ctrl_Keyboard1 = ctrl_Keyboard,ctrl_Keyboard2,\r
- ctrl_Joystick,\r
- ctrl_Joystick1 = ctrl_Joystick,ctrl_Joystick2,\r
- ctrl_Mouse\r
- } ControlType;\r
-typedef enum {\r
- motion_Left = -1,motion_Up = -1,\r
- motion_None = 0,\r
- motion_Right = 1,motion_Down = 1\r
- } Motion;\r
-typedef enum {\r
- dir_North,dir_NorthEast,\r
- dir_East,dir_SouthEast,\r
- dir_South,dir_SouthWest,\r
- dir_West,dir_NorthWest,\r
- dir_None\r
- } Direction;\r
-typedef enum {\r
- ga_Jump,\r
- ga_Pogo,\r
- ga_Fire,\r
- ga_Status\r
- } GravisAType;\r
-typedef struct {\r
- boolean button0,button1;\r
- int x,y;\r
- Motion xaxis,yaxis;\r
- Direction dir;\r
- } CursorInfo;\r
-typedef CursorInfo ControlInfo;\r
-typedef struct {\r
- ScanCode button0,button1,\r
- upleft, up, upright,\r
- left, right,\r
- downleft, down, downright;\r
- } KeyboardDef;\r
-typedef struct {\r
- word joyMinX,joyMinY,\r
- threshMinX,threshMinY,\r
- threshMaxX,threshMaxY,\r
- joyMaxX,joyMaxY,\r
- joyMultXL,joyMultYL,\r
- joyMultXH,joyMultYH;\r
- } JoystickDef;\r
-// Global variables\r
-extern boolean Keyboard[],\r
- MousePresent,\r
- JoysPresent[];\r
-extern boolean Paused;\r
-extern char LastASCII;\r
-extern ScanCode LastScan;\r
-extern KeyboardDef KbdDefs[];\r
-extern JoystickDef JoyDefs[];\r
-extern ControlType Controls[MaxPlayers];\r
-extern boolean GravisGamepad;\r
-extern word GravisAction[4];\r
-extern word GravisMap[4];\r
-\r
-extern Demo DemoMode;\r
-extern byte _seg *DemoBuffer;\r
-extern word DemoOffset,DemoSize;\r
-\r
-// Function prototypes\r
-#define IN_KeyDown(code) (Keyboard[(code)])\r
-#define IN_ClearKey(code) {Keyboard[code] = false;\\r
- if (code == LastScan) LastScan = sc_None;}\r
-\r
-// DEBUG - put names in prototypes\r
-extern void IN_Startup(void),IN_Shutdown(void),\r
- IN_Default(boolean gotit,ControlType in),\r
- IN_SetKeyHook(void (*)()),\r
- IN_ClearKeysDown(void),\r
- IN_ReadCursor(CursorInfo *),\r
- IN_ReadControl(int,ControlInfo *),\r
- IN_SetControlType(int,ControlType),\r
- IN_GetJoyAbs(word joy,word *xp,word *yp),\r
- IN_SetupJoy(word joy,word minx,word maxx,\r
- word miny,word maxy),\r
- IN_StartDemoPlayback(byte _seg *buffer,word bufsize),\r
- IN_StopDemo(void),IN_FreeDemoBuffer(void),\r
- IN_Ack(void),IN_AckBack(void);\r
-extern boolean IN_UserInput(longword delay,boolean clear),\r
- IN_IsUserInput(void),\r
- IN_StartDemoRecord(word bufsize);\r
-extern byte *IN_GetScanName(ScanCode);\r
-extern char IN_WaitForASCII(void);\r
-extern ScanCode IN_WaitForKey(void);\r
-extern word IN_GetJoyButtonsDB(word joy);\r
-\r
-#endif\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// NEWMM.C\r
-\r
-/*\r
-=============================================================================\r
-\r
- ID software memory manager\r
- --------------------------\r
-\r
-Primary coder: John Carmack\r
-\r
-RELIES ON\r
----------\r
-Quit (char *error) function\r
-\r
-\r
-WORK TO DO\r
-----------\r
-MM_SizePtr to change the size of a given pointer\r
-\r
-Multiple purge levels utilized\r
-\r
-EMS / XMS unmanaged routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-#pragma warn -pro\r
-#pragma warn -use\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL INFO\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define LOCKBIT 0x80 // if set in attributes, block cannot be moved\r
-#define PURGEBITS 3 // 0-3 level, 0= unpurgable, 3= purge first\r
-#define PURGEMASK 0xfffc\r
-#define BASEATTRIBUTES 0 // unlocked, non purgable\r
-\r
-#define MAXUMBS 10\r
-\r
-typedef struct mmblockstruct\r
-{\r
- unsigned start,length;\r
- unsigned attributes;\r
- memptr *useptr; // pointer to the segment start\r
- struct mmblockstruct far *next;\r
-} mmblocktype;\r
-\r
-\r
-//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!")\\r
-// ;mmfree=mmfree->next;}\r
-\r
-#define GETNEWBLOCK {if(!mmfree)MML_ClearBlock();mmnew=mmfree;mmfree=mmfree->next;}\r
-\r
-#define FREEBLOCK(x) {*x->useptr=NULL;x->next=mmfree;mmfree=x;}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-mminfotype mminfo;\r
-memptr bufferseg;\r
-boolean mmerror;\r
-\r
-void (* beforesort) (void);\r
-void (* aftersort) (void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean mmstarted;\r
-\r
-void far *farheap;\r
-void *nearheap;\r
-\r
-mmblocktype far mmblocks[MAXBLOCKS]\r
- ,far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
-\r
-boolean bombonerror;\r
-\r
-unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
-\r
-void (* XMSaddr) (void); // far pointer to XMS driver\r
-\r
-unsigned numUMBs,UMBbase[MAXUMBS];\r
-\r
-//==========================================================================\r
-\r
-//\r
-// local prototypes\r
-//\r
-\r
-boolean MML_CheckForEMS (void);\r
-void MML_ShutdownEMS (void);\r
-void MM_MapEMS (void);\r
-boolean MML_CheckForXMS (void);\r
-void MML_ShutdownXMS (void);\r
-void MML_UseSpace (unsigned segstart, unsigned seglength);\r
-void MML_ClearBlock (void);\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForEMS\r
-=\r
-= Routine from p36 of Extending DOS\r
-=\r
-=======================\r
-*/\r
-\r
-char emmname[9] = "EMMXXXX0";\r
-\r
-boolean MML_CheckForEMS (void)\r
-{\r
-asm mov dx,OFFSET emmname[0]\r
-asm mov ax,0x3d00\r
-asm int 0x21 // try to open EMMXXXX0 device\r
-asm jc error\r
-\r
-asm mov bx,ax\r
-asm mov ax,0x4400\r
-\r
-asm int 0x21 // get device info\r
-asm jc error\r
-\r
-asm and dx,0x80\r
-asm jz error\r
-\r
-asm mov ax,0x4407\r
-\r
-asm int 0x21 // get status\r
-asm jc error\r
-asm or al,al\r
-asm jz error\r
-\r
-asm mov ah,0x3e\r
-asm int 0x21 // close handle\r
-asm jc error\r
-\r
-//\r
-// EMS is good\r
-//\r
- return true;\r
-\r
-error:\r
-//\r
-// EMS is bad\r
-//\r
- return false;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupEMS\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_SetupEMS (void)\r
-{\r
- char str[80],str2[10];\r
- unsigned error;\r
-\r
- totalEMSpages = freeEMSpages = EMSpageframe = EMSpagesmapped = 0;\r
-\r
-asm {\r
- mov ah,EMS_STATUS\r
- int EMS_INT // make sure EMS hardware is present\r
- or ah,ah\r
- jnz error\r
-\r
- mov ah,EMS_VERSION\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- cmp al,0x32 // only work on ems 3.2 or greater\r
- jb error\r
-\r
- mov ah,EMS_GETFRAME\r
- int EMS_INT // find the page frame address\r
- or ah,ah\r
- jnz error\r
- mov [EMSpageframe],bx\r
-\r
- mov ah,EMS_GETPAGES\r
- int EMS_INT // find out how much EMS is there\r
- or ah,ah\r
- jnz error\r
- mov [totalEMSpages],dx\r
- mov [freeEMSpages],bx\r
- or bx,bx\r
- jz noEMS // no EMS at all to allocate\r
-\r
- cmp bx,4\r
- jle getpages // there is only 1,2,3,or 4 pages\r
- mov bx,4 // we can't use more than 4 pages\r
- }\r
-\r
-getpages:\r
-asm {\r
- mov [EMSpagesmapped],bx\r
- mov ah,EMS_ALLOCPAGES // allocate up to 64k of EMS\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- mov [EMShandle],dx\r
- }\r
- return;\r
-\r
-error:\r
- error = _AH;\r
- strcpy (str,"MML_SetupEMS: EMS error 0x");\r
- itoa(error,str2,16);\r
- strcpy (str,str2);\r
- Quit (str);\r
-\r
-noEMS:\r
-;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownEMS\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_ShutdownEMS (void)\r
-{\r
- if (!EMShandle)\r
- return;\r
-\r
-asm {\r
- mov ah,EMS_FREEPAGES\r
- mov dx,[EMShandle]\r
- int EMS_INT\r
- or ah,ah\r
- jz ok\r
- }\r
-\r
- Quit ("MML_ShutdownEMS: Error freeing EMS!");\r
-\r
-ok:\r
-;\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= MM_MapEMS\r
-=\r
-= Maps the 64k of EMS used by memory manager into the page frame\r
-= for general use. This only needs to be called if you are keeping\r
-= other things in EMS.\r
-=\r
-====================\r
-*/\r
-\r
-void MM_MapEMS (void)\r
-{\r
- char str[80],str2[10];\r
- unsigned error;\r
- int i;\r
-\r
- for (i=0;i<EMSpagesmapped;i++)\r
- {\r
- asm {\r
- mov ah,EMS_MAPPAGE\r
- mov bx,[i] // logical page\r
- mov al,bl // physical page\r
- mov dx,[EMShandle] // handle\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- }\r
- }\r
-\r
- return;\r
-\r
-error:\r
- error = _AH;\r
- strcpy (str,"MM_MapEMS: EMS error 0x");\r
- itoa(error,str2,16);\r
- strcpy (str,str2);\r
- Quit (str);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForXMS\r
-=\r
-= Check for XMM driver\r
-=\r
-=======================\r
-*/\r
-\r
-boolean MML_CheckForXMS (void)\r
-{\r
- numUMBs = 0;\r
-\r
-asm {\r
- mov ax,0x4300\r
- int 0x2f // query status of installed diver\r
- cmp al,0x80\r
- je good\r
- }\r
- return false;\r
-good:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupXMS\r
-=\r
-= Try to allocate all upper memory block\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_SetupXMS (void)\r
-{\r
- unsigned base,size;\r
-\r
-asm {\r
- mov ax,0x4310\r
- int 0x2f\r
- mov [WORD PTR XMSaddr],bx\r
- mov [WORD PTR XMSaddr+2],es // function pointer to XMS driver\r
- }\r
-\r
-getmemory:\r
-asm {\r
- mov ah,XMS_ALLOCUMB\r
- mov dx,0xffff // try for largest block possible\r
- call [DWORD PTR XMSaddr]\r
- or ax,ax\r
- jnz gotone\r
-\r
- cmp bl,0xb0 // error: smaller UMB is available\r
- jne done;\r
-\r
- mov ah,XMS_ALLOCUMB\r
- call [DWORD PTR XMSaddr] // DX holds largest available UMB\r
- or ax,ax\r
- jz done // another error...\r
- }\r
-\r
-gotone:\r
-asm {\r
- mov [base],bx\r
- mov [size],dx\r
- }\r
- MML_UseSpace (base,size);\r
- mminfo.XMSmem += size*16;\r
- UMBbase[numUMBs] = base;\r
- numUMBs++;\r
- if (numUMBs < MAXUMBS)\r
- goto getmemory;\r
-\r
-done:;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownXMS\r
-=\r
-======================\r
-*/\r
-\r
-void MML_ShutdownXMS (void)\r
-{\r
- int i;\r
- unsigned base;\r
-\r
- for (i=0;i<numUMBs;i++)\r
- {\r
- base = UMBbase[i];\r
-\r
-asm mov ah,XMS_FREEUMB\r
-asm mov dx,[base]\r
-asm call [DWORD PTR XMSaddr]\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_UseSpace\r
-=\r
-= Marks a range of paragraphs as usable by the memory manager\r
-= This is used to mark space for the near heap, far heap, ems page frame,\r
-= and upper memory blocks\r
-=\r
-======================\r
-*/\r
-\r
-void MML_UseSpace (unsigned segstart, unsigned seglength)\r
-{\r
- mmblocktype far *scan,far *last;\r
- unsigned oldend;\r
- long extra;\r
-\r
- scan = last = mmhead;\r
- mmrover = mmhead; // reset rover to start of memory\r
-\r
-//\r
-// search for the block that contains the range of segments\r
-//\r
- while (scan->start+scan->length < segstart)\r
- {\r
- last = scan;\r
- scan = scan->next;\r
- }\r
-\r
-//\r
-// take the given range out of the block\r
-//\r
- oldend = scan->start + scan->length;\r
- extra = oldend - (segstart+seglength);\r
- if (extra < 0)\r
- Quit ("MML_UseSpace: Segment spans two blocks!");\r
-\r
- if (segstart == scan->start)\r
- {\r
- last->next = scan->next; // unlink block\r
- FREEBLOCK(scan);\r
- scan = last;\r
- }\r
- else\r
- scan->length = segstart-scan->start; // shorten block\r
-\r
- if (extra > 0)\r
- {\r
- GETNEWBLOCK;\r
- mmnew->useptr = NULL; // Keen addition\r
-\r
- mmnew->next = scan->next;\r
- scan->next = mmnew;\r
- mmnew->start = segstart+seglength;\r
- mmnew->length = extra;\r
- mmnew->attributes = LOCKBIT;\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MML_ClearBlock\r
-=\r
-= We are out of blocks, so free a purgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MML_ClearBlock (void)\r
-{\r
- mmblocktype far *scan,far *last;\r
-\r
- scan = mmhead->next;\r
-\r
- while (scan)\r
- {\r
- if (!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS) )\r
- {\r
- MM_FreePtr(scan->useptr);\r
- return;\r
- }\r
- scan = scan->next;\r
- }\r
-\r
- Quit ("MM_ClearBlock: No purgable blocks!");\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= MM_Startup\r
-=\r
-= Grabs all space from turbo with malloc/farmalloc\r
-= Allocates bufferseg misc buffer\r
-=\r
-===================\r
-*/\r
-\r
-static char *ParmStrings[] = {"noems","noxms",""};\r
-\r
-void MM_Startup (void)\r
-{\r
- int i;\r
- unsigned long length;\r
- void far *start;\r
- unsigned segstart,seglength,endfree;\r
-\r
- if (mmstarted)\r
- MM_Shutdown ();\r
-\r
-\r
- mmstarted = true;\r
- bombonerror = true;\r
-//\r
-// set up the linked list (everything in the free list;\r
-//\r
- mmhead = NULL;\r
- mmfree = &mmblocks[0];\r
- for (i=0;i<MAXBLOCKS-1;i++)\r
- mmblocks[i].next = &mmblocks[i+1];\r
- mmblocks[i].next = NULL;\r
-\r
-//\r
-// locked block of all memory until we punch out free space\r
-//\r
- GETNEWBLOCK;\r
- mmhead = mmnew; // this will allways be the first node\r
- mmnew->start = 0;\r
- mmnew->length = 0xffff;\r
- mmnew->attributes = LOCKBIT;\r
- mmnew->next = NULL;\r
- mmrover = mmhead;\r
-\r
-\r
-//\r
-// get all available near conventional memory segments\r
-//\r
- length=coreleft();\r
- start = (void far *)(nearheap = malloc(length));\r
-\r
- length -= 16-(FP_OFF(start)&15);\r
- length -= SAVENEARHEAP;\r
- seglength = length / 16; // now in paragraphs\r
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
- MML_UseSpace (segstart,seglength);\r
- mminfo.nearheap = length;\r
-\r
-//\r
-// get all available far conventional memory segments\r
-//\r
- length=farcoreleft();\r
- start = farheap = farmalloc(length);\r
- length -= 16-(FP_OFF(start)&15);\r
- length -= SAVEFARHEAP;\r
- seglength = length / 16; // now in paragraphs\r
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
- MML_UseSpace (segstart,seglength);\r
- mminfo.farheap = length;\r
- mminfo.mainmem = mminfo.nearheap + mminfo.farheap;\r
-\r
-\r
-//\r
-// detect EMS and allocate up to 64K at page frame\r
-//\r
- mminfo.EMSmem = 0;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- if ( US_CheckParm(_argv[i],ParmStrings) == 0)\r
- goto emsskip; // param NOEMS\r
- }\r
-\r
- if (MML_CheckForEMS())\r
- {\r
- MML_SetupEMS(); // allocate space\r
- MML_UseSpace (EMSpageframe,EMSpagesmapped*0x400);\r
- MM_MapEMS(); // map in used pages\r
- mminfo.EMSmem = EMSpagesmapped*0x4000l;\r
- }\r
-\r
-//\r
-// detect XMS and get upper memory blocks\r
-//\r
-emsskip:\r
- mminfo.XMSmem = 0;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- if ( US_CheckParm(_argv[i],ParmStrings) == 0) // BUG: NOXMS is index 1, not 0\r
- goto xmsskip; // param NOXMS\r
- }\r
-\r
- if (MML_CheckForXMS())\r
- MML_SetupXMS(); // allocate as many UMBs as possible\r
-\r
-//\r
-// allocate the misc buffer\r
-//\r
-xmsskip:\r
- mmrover = mmhead; // start looking for space after low block\r
-\r
- MM_GetPtr (&bufferseg,BUFFERSIZE);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_Shutdown\r
-=\r
-= Frees all conventional, EMS, and XMS allocated\r
-=\r
-====================\r
-*/\r
-\r
-void MM_Shutdown (void)\r
-{\r
- if (!mmstarted)\r
- return;\r
-\r
- farfree (farheap);\r
- free (nearheap);\r
- MML_ShutdownEMS ();\r
- MML_ShutdownXMS ();\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_GetPtr\r
-=\r
-= Allocates an unlocked, unpurgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MM_GetPtr (memptr *baseptr,unsigned long size)\r
-{\r
- mmblocktype far *scan,far *lastscan,far *endscan\r
- ,far *purge,far *next;\r
- int search;\r
- unsigned needed,startseg;\r
-\r
- needed = (size+15)/16; // convert size from bytes to paragraphs\r
-\r
- GETNEWBLOCK; // fill in start and next after a spot is found\r
- mmnew->length = needed;\r
- mmnew->useptr = baseptr;\r
- mmnew->attributes = BASEATTRIBUTES;\r
-\r
- for (search = 0; search<3; search++)\r
- {\r
- //\r
- // first search: try to allocate right after the rover, then on up\r
- // second search: search from the head pointer up to the rover\r
- // third search: compress memory, then scan from start\r
- if (search == 1 && mmrover == mmhead)\r
- search++;\r
-\r
- switch (search)\r
- {\r
- case 0:\r
- lastscan = mmrover;\r
- scan = mmrover->next;\r
- endscan = NULL;\r
- break;\r
- case 1:\r
- lastscan = mmhead;\r
- scan = mmhead->next;\r
- endscan = mmrover;\r
- break;\r
- case 2:\r
- MM_SortMem ();\r
- lastscan = mmhead;\r
- scan = mmhead->next;\r
- endscan = NULL;\r
- break;\r
- }\r
-\r
- startseg = lastscan->start + lastscan->length;\r
-\r
- while (scan != endscan)\r
- {\r
- if (scan->start - startseg >= needed)\r
- {\r
- //\r
- // got enough space between the end of lastscan and\r
- // the start of scan, so throw out anything in the middle\r
- // and allocate the new block\r
- //\r
- purge = lastscan->next;\r
- lastscan->next = mmnew;\r
- mmnew->start = *(unsigned *)baseptr = startseg;\r
- mmnew->next = scan;\r
- while ( purge != scan)\r
- { // free the purgable block\r
- next = purge->next;\r
- FREEBLOCK(purge);\r
- purge = next; // purge another if not at scan\r
- }\r
- mmrover = mmnew;\r
- return; // good allocation!\r
- }\r
-\r
- //\r
- // if this block is purge level zero or locked, skip past it\r
- //\r
- if ( (scan->attributes & LOCKBIT)\r
- || !(scan->attributes & PURGEBITS) )\r
- {\r
- lastscan = scan;\r
- startseg = lastscan->start + lastscan->length;\r
- }\r
-\r
-\r
- scan=scan->next; // look at next line\r
- }\r
- }\r
-\r
- if (bombonerror)\r
- Quit ("MM_GetPtr: Out of memory!");\r
- else\r
- mmerror = true;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_FreePtr\r
-=\r
-= Allocates an unlocked, unpurgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MM_FreePtr (memptr *baseptr)\r
-{\r
- mmblocktype far *scan,far *last;\r
-\r
- last = mmhead;\r
- scan = last->next;\r
-\r
- if (baseptr == mmrover->useptr) // removed the last allocated block\r
- mmrover = mmhead;\r
-\r
- while (scan->useptr != baseptr && scan)\r
- {\r
- last = scan;\r
- scan = scan->next;\r
- }\r
-\r
- if (!scan)\r
- Quit ("MM_FreePtr: Block not found!");\r
-\r
- last->next = scan->next;\r
-\r
- FREEBLOCK(scan);\r
-}\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SetPurge\r
-=\r
-= Sets the purge level for a block (locked blocks cannot be made purgable)\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SetPurge (memptr *baseptr, int purge)\r
-{\r
- mmblocktype far *start;\r
-\r
- start = mmrover;\r
-\r
- do\r
- {\r
- if (mmrover->useptr == baseptr)\r
- break;\r
-\r
- mmrover = mmrover->next;\r
-\r
- if (!mmrover)\r
- mmrover = mmhead;\r
- else if (mmrover == start)\r
- Quit ("MM_SetPurge: Block not found!");\r
-\r
- } while (1);\r
-\r
- mmrover->attributes &= ~PURGEBITS;\r
- mmrover->attributes |= purge;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SetLock\r
-=\r
-= Locks / unlocks the block\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SetLock (memptr *baseptr, boolean locked)\r
-{\r
- mmblocktype far *start;\r
-\r
- start = mmrover;\r
-\r
- do\r
- {\r
- if (mmrover->useptr == baseptr)\r
- break;\r
-\r
- mmrover = mmrover->next;\r
-\r
- if (!mmrover)\r
- mmrover = mmhead;\r
- else if (mmrover == start)\r
- Quit ("MM_SetLock: Block not found!");\r
-\r
- } while (1);\r
-\r
- mmrover->attributes &= ~LOCKBIT;\r
- mmrover->attributes |= locked*LOCKBIT;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SortMem\r
-=\r
-= Throws out all purgable stuff and compresses movable blocks\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SortMem (void)\r
-{\r
- mmblocktype far *scan,far *last,far *next;\r
- unsigned start,length,source,dest,oldborder;\r
- int playing;\r
-\r
- //\r
- // lock down a currently playing sound\r
- //\r
- playing = SD_SoundPlaying ();\r
- if (playing)\r
- {\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- playing += STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- playing += STARTADLIBSOUNDS;\r
- break;\r
- }\r
- MM_SetLock(&(memptr)audiosegs[playing],true);\r
- }\r
-\r
-\r
- SD_StopSound();\r
- oldborder = bordercolor;\r
- VW_ColorBorder (15);\r
-\r
- if (beforesort)\r
- beforesort();\r
-\r
- scan = mmhead;\r
-\r
- last = NULL; // shut up compiler warning\r
-\r
- while (scan)\r
- {\r
- if (scan->attributes & LOCKBIT)\r
- {\r
- //\r
- // block is locked, so try to pile later blocks right after it\r
- //\r
- start = scan->start + scan->length;\r
- }\r
- else\r
- {\r
- if (scan->attributes & PURGEBITS)\r
- {\r
- //\r
- // throw out the purgable block\r
- //\r
- next = scan->next;\r
- FREEBLOCK(scan);\r
- last->next = next;\r
- scan = next;\r
- continue;\r
- }\r
- else\r
- {\r
- //\r
- // push the non purgable block on top of the last moved block\r
- //\r
- if (scan->start != start)\r
- {\r
- length = scan->length;\r
- source = scan->start;\r
- dest = start;\r
- while (length > 0xf00)\r
- {\r
- movedata(source,0,dest,0,0xf00*16);\r
- length -= 0xf00;\r
- source += 0xf00;\r
- dest += 0xf00;\r
- }\r
- movedata(source,0,dest,0,length*16);\r
-\r
- scan->start = start;\r
- *(unsigned *)scan->useptr = start;\r
- }\r
- start = scan->start + scan->length;\r
- }\r
- }\r
-\r
- last = scan;\r
- scan = scan->next; // go to next block\r
- }\r
-\r
- mmrover = mmhead;\r
-\r
- if (aftersort)\r
- aftersort();\r
-\r
- VW_ColorBorder (oldborder);\r
-\r
- if (playing)\r
- MM_SetLock(&(memptr)audiosegs[playing],false);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_ShowMemory\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_ShowMemory (void)\r
-{\r
- mmblocktype far *scan;\r
- unsigned color,temp;\r
- long end,owner;\r
- char scratch[80],str[10];\r
-\r
- VW_SetDefaultColors();\r
- VW_SetLineWidth(40);\r
- temp = bufferofs;\r
- bufferofs = 0;\r
- VW_SetScreen (0,0);\r
-\r
- scan = mmhead;\r
-\r
- end = -1;\r
-\r
-//CA_OpenDebug ();\r
-\r
- while (scan)\r
- {\r
- if (scan->attributes & PURGEBITS)\r
- color = 5; // dark purple = purgable\r
- else\r
- color = 9; // medium blue = non purgable\r
- if (scan->attributes & LOCKBIT)\r
- color = 12; // red = locked\r
- if (scan->start<=end)\r
- Quit ("MM_ShowMemory: Memory block order corrupted!");\r
- end = scan->start+scan->length-1;\r
- VW_Hlin(scan->start,(unsigned)end,0,color);\r
- VW_Plot(scan->start,0,15);\r
- if (scan->next->start > end+1)\r
- VW_Hlin(end+1,scan->next->start,0,0); // black = free\r
-\r
-#if 0\r
-strcpy (scratch,"Size:");\r
-ltoa ((long)scan->length*16,str,10);\r
-strcat (scratch,str);\r
-strcat (scratch,"\tOwner:0x");\r
-owner = (unsigned)scan->useptr;\r
-ultoa (owner,str,16);\r
-strcat (scratch,str);\r
-strcat (scratch,"\n");\r
-write (debughandle,scratch,strlen(scratch));\r
-#endif\r
-\r
- scan = scan->next;\r
- }\r
-\r
-//CA_CloseDebug ();\r
-\r
- IN_Ack();\r
- VW_SetLineWidth(64);\r
- bufferofs = temp;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MM_UnusedMemory\r
-=\r
-= Returns the total free space without purging\r
-=\r
-======================\r
-*/\r
-\r
-long MM_UnusedMemory (void)\r
-{\r
- unsigned free;\r
- mmblocktype far *scan;\r
-\r
- free = 0;\r
- scan = mmhead;\r
-\r
- while (scan->next)\r
- {\r
- free += scan->next->start - (scan->start + scan->length);\r
- scan = scan->next;\r
- }\r
-\r
- return free*16l;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MM_TotalFree\r
-=\r
-= Returns the total free space with purging\r
-=\r
-======================\r
-*/\r
-\r
-long MM_TotalFree (void)\r
-{\r
- unsigned free;\r
- mmblocktype far *scan;\r
-\r
- free = 0;\r
- scan = mmhead;\r
-\r
- while (scan->next)\r
- {\r
- if ((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
- free += scan->length;\r
- free += scan->next->start - (scan->start + scan->length);\r
- scan = scan->next;\r
- }\r
-\r
- return free*16l;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_BombOnError\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_BombOnError (boolean bomb)\r
-{\r
- bombonerror = bomb;\r
-}\r
-\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_MM.H\r
-\r
-#ifndef __ID_CA__\r
-\r
-#define __ID_CA__\r
-\r
-#define SAVENEARHEAP 0x400 // space to leave in data segment\r
-#define SAVEFARHEAP 0 // space to leave in far heap\r
-\r
-#define BUFFERSIZE 0x1000 // miscelanious, allways available buffer\r
-\r
-#ifdef CAT3D\r
-#define MAXBLOCKS 600\r
-#else\r
-#define MAXBLOCKS 1200\r
-#endif\r
-\r
-\r
-//--------\r
-\r
-#define EMS_INT 0x67\r
-\r
-#define EMS_STATUS 0x40\r
-#define EMS_GETFRAME 0x41\r
-#define EMS_GETPAGES 0x42\r
-#define EMS_ALLOCPAGES 0x43\r
-#define EMS_MAPPAGE 0x44\r
-#define EMS_FREEPAGES 0x45\r
-#define EMS_VERSION 0x46\r
-\r
-//--------\r
-\r
-#define XMS_VERSION 0x00\r
-\r
-#define XMS_ALLOCHMA 0x01\r
-#define XMS_FREEHMA 0x02\r
-\r
-#define XMS_GENABLEA20 0x03\r
-#define XMS_GDISABLEA20 0x04\r
-#define XMS_LENABLEA20 0x05\r
-#define XMS_LDISABLEA20 0x06\r
-#define XMS_QUERYA20 0x07\r
-\r
-#define XMS_QUERYREE 0x08\r
-#define XMS_ALLOC 0x09\r
-#define XMS_FREE 0x0A\r
-#define XMS_MOVE 0x0B\r
-#define XMS_LOCK 0x0C\r
-#define XMS_UNLOCK 0x0D\r
-#define XMS_GETINFO 0x0E\r
-#define XMS_RESIZE 0x0F\r
-\r
-#define XMS_ALLOCUMB 0x10\r
-#define XMS_FREEUMB 0x11\r
-\r
-//==========================================================================\r
-\r
-typedef void _seg * memptr;\r
-\r
-typedef struct\r
-{\r
- long nearheap,farheap,EMSmem,XMSmem,mainmem;\r
-} mminfotype;\r
-\r
-//==========================================================================\r
-\r
-extern mminfotype mminfo;\r
-extern memptr bufferseg;\r
-extern boolean mmerror;\r
-\r
-extern void (* beforesort) (void);\r
-extern void (* aftersort) (void);\r
-\r
-//==========================================================================\r
-\r
-void MM_Startup (void);\r
-void MM_Shutdown (void);\r
-void MM_MapEMS (void);\r
-\r
-void MM_GetPtr (memptr *baseptr,unsigned long size);\r
-void MM_FreePtr (memptr *baseptr);\r
-\r
-void MM_SetPurge (memptr *baseptr, int purge);\r
-void MM_SetLock (memptr *baseptr, boolean locked);\r
-void MM_SortMem (void);\r
-\r
-void MM_ShowMemory (void);\r
-\r
-long MM_UnusedMemory (void);\r
-long MM_TotalFree (void);\r
-\r
-void MM_BombOnError (boolean bomb);\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_RF.C\r
-\r
-/*\r
-=============================================================================\r
-\r
-notes\r
------\r
-\r
-scrolling more than one tile / refresh forces a total redraw\r
-\r
-two overlapping sprites of equal priority can change drawing order when\r
-updated\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define SCREENTILESWIDE 20\r
-#define SCREENTILESHIGH 13\r
-\r
-#define SCREENSPACE (SCREENWIDTH*240)\r
-#define FREEEGAMEM (0x10000l-3l*SCREENSPACE)\r
-\r
-//\r
-// the update array must have enough space for two screens that can float\r
-// up two two tiles each way\r
-//\r
-// (PORTTILESWIDE+1)*PORTTILESHIGH must be even so the arrays can be cleared\r
-// by word width instructions\r
-\r
-#define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)\r
-#define UPDATESPARESIZE (UPDATEWIDE*2+4)\r
-#define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
-\r
-#define G_EGASX_SHIFT 7 // global >> ?? = screen x\r
-#define G_CGASX_SHIFT 6 // global >> ?? = screen x\r
-#define G_SY_SHIFT 4 // global >> ?? = screen y\r
-\r
-unsigned SX_T_SHIFT; // screen x >> ?? = tile EGA = 1, CGA = 2;\r
-#define SY_T_SHIFT 4 // screen y >> ?? = tile\r
-\r
-\r
-#define EGAPORTSCREENWIDE 42\r
-#define CGAPORTSCREENWIDE 84\r
-#define PORTSCREENHIGH 224\r
-\r
-#define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)\r
-#define UPDATESPARESIZE (UPDATEWIDE*2+4)\r
-#define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
-\r
-#define MAXSCROLLEDGES 6\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL TYPES\r
-\r
-=============================================================================\r
-*/\r
-\r
-typedef struct spriteliststruct\r
-{\r
- int screenx,screeny;\r
- int width,height;\r
-\r
- unsigned grseg,sourceofs,planesize;\r
- drawtype draw;\r
- unsigned tilex,tiley,tilewide,tilehigh;\r
- int priority,updatecount;\r
- struct spriteliststruct **prevptr,*nextsprite;\r
-} spritelisttype;\r
-\r
-\r
-typedef struct\r
-{\r
- int screenx,screeny;\r
- int width,height;\r
-} eraseblocktype;\r
-\r
-\r
-typedef struct\r
-{\r
- unsigned current; // foreground tiles have high bit set\r
- int count;\r
-#ifdef KEEN6\r
- unsigned soundtile;\r
- unsigned visible;\r
- int sound;\r
-#endif\r
-} tiletype;\r
-\r
-\r
-typedef struct animtilestruct\r
-{\r
- unsigned x,y,tile;\r
- tiletype *chain;\r
- unsigned far *mapplane;\r
- struct animtilestruct **prevptr,*nexttile;\r
-} animtiletype;\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-unsigned tics;\r
-long lasttimecount;\r
-\r
-boolean compatability; // crippled refresh for wierdo SVGAs\r
-\r
-unsigned mapwidth,mapheight,mapbyteswide,mapwordswide\r
- ,mapbytesextra,mapwordsextra;\r
-unsigned mapbwidthtable[MAXMAPHEIGHT];\r
-\r
-//\r
-// Global : Actor coordinates are in this, at 1/16 th of a pixel, to allow\r
-// for fractional movement and acceleration.\r
-//\r
-// Tiles : Tile offsets from the upper left corner of the current map.\r
-//\r
-// Screen : Graphics level offsets from map origin, x in bytes, y in pixels.\r
-// originxscreen is the same spot as originxtile, just with extra precision\r
-// so graphics don't need to be done in tile boundaries.\r
-//\r
-\r
-unsigned originxglobal,originyglobal;\r
-unsigned originxtile,originytile;\r
-unsigned originxscreen,originyscreen;\r
-unsigned originmap;\r
-unsigned originxmin,originxmax,originymin,originymax;\r
-\r
-unsigned masterofs;\r
-\r
-//\r
-// Table of the offsets from bufferofs of each tile spot in the\r
-// view port. The extra wide tile should never be drawn, but the space\r
-// is needed to account for the extra 0 in the update arrays. Built by\r
-// RF_Startup\r
-//\r
-\r
-unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
-unsigned updatemapofs[UPDATEWIDE*UPDATEHIGH];\r
-\r
-unsigned uwidthtable[PORTTILESHIGH]; // lookup instead of multiply\r
-\r
-byte update[2][UPDATESIZE];\r
-byte *updateptr,*baseupdateptr, // current start of update window\r
- *updatestart[2],\r
- *baseupdatestart[2];\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-static char scratch[20],str[80];\r
-\r
-tiletype allanims[MAXANIMTYPES];\r
-unsigned numanimchains;\r
-\r
-void (*refreshvector) (void);\r
-\r
-unsigned screenstart[3] =\r
- {0,SCREENSPACE,SCREENSPACE*2};\r
-\r
-unsigned xpanmask; // prevent panning to odd pixels\r
-\r
-unsigned screenpage; // screen currently being displayed\r
-unsigned otherpage;\r
-\r
-\r
-spritelisttype spritearray[MAXSPRITES],*prioritystart[PRIORITIES],\r
- *spritefreeptr;\r
-\r
-animtiletype animarray[MAXANIMTILES],*animhead,*animfreeptr;\r
-\r
-int animfreespot;\r
-\r
-eraseblocktype eraselist[2][MAXSPRITES],*eraselistptr[2];\r
-\r
-int hscrollblocks,vscrollblocks;\r
-int hscrolledge[MAXSCROLLEDGES],vscrolledge[MAXSCROLLEDGES];\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL PROTOTYPES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void RFL_NewTile (unsigned updateoffset);\r
-void RFL_MaskForegroundTiles (void);\r
-void RFL_UpdateTiles (void);\r
-\r
-void RFL_BoundScroll (int x, int y);\r
-void RFL_CalcOriginStuff (long x, long y);\r
-void RFL_ClearScrollBlocks (void);\r
-void RFL_InitSpriteList (void);\r
-void RFL_InitAnimList (void);\r
-void RFL_CheckForAnimTile (unsigned x, unsigned y);\r
-void RFL_AnimateTiles (void);\r
-void RFL_RemoveAnimsOnX (unsigned x);\r
-void RFL_RemoveAnimsOnY (unsigned y);\r
-void RFL_EraseBlocks (void);\r
-void RFL_UpdateSprites (void);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GRMODE INDEPENDANT ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Startup\r
-=\r
-=====================\r
-*/\r
-\r
-static char *ParmStrings[] = {"comp",""};\r
-\r
-void RF_Startup (void)\r
-{\r
- int i,x,y;\r
- unsigned *blockstart;\r
-\r
-#ifndef KEEN\r
- //\r
- // Keen 4-6 store the compatability setting in the game's config file.\r
- // The setting is loaded from that file AFTER RF_Startup is executed,\r
- // making this check useless (unless the config file doesn't exist).\r
- // Instead, US_Startup now checks for that parameter after the config\r
- // file has been read.\r
- //\r
- if (grmode == EGAGR)\r
- for (i = 1;i < _argc;i++)\r
- if (US_CheckParm(_argv[i],ParmStrings) == 0)\r
- {\r
- compatability = true;\r
- break;\r
- }\r
-#endif\r
-\r
- for (i=0;i<PORTTILESHIGH;i++)\r
- uwidthtable[i] = UPDATEWIDE*i;\r
-\r
- originxmin = originymin = MAPBORDER*TILEGLOBAL;\r
-\r
- eraselistptr[0] = &eraselist[0][0];\r
- eraselistptr[1] = &eraselist[1][0];\r
-\r
-\r
-\r
- if (grmode == EGAGR)\r
- {\r
- SX_T_SHIFT = 1;\r
-\r
- baseupdatestart[0] = &update[0][UPDATESPARESIZE];\r
- baseupdatestart[1] = &update[1][UPDATESPARESIZE];\r
-\r
- screenpage = 0;\r
- otherpage = 1;\r
- displayofs = screenstart[screenpage];\r
- bufferofs = screenstart[otherpage];\r
- masterofs = screenstart[2];\r
-\r
- updateptr = baseupdatestart[otherpage];\r
-\r
- blockstart = &blockstarts[0];\r
- for (y=0;y<UPDATEHIGH;y++)\r
- for (x=0;x<UPDATEWIDE;x++)\r
- *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;\r
-\r
- xpanmask = 6; // dont pan to odd pixels\r
- }\r
-\r
- else if (grmode == CGAGR)\r
- {\r
- SX_T_SHIFT = 2;\r
-\r
- updateptr = baseupdateptr = &update[0][UPDATESPARESIZE];\r
-\r
- bufferofs = 0;\r
- masterofs = 0x8000;\r
-\r
- blockstart = &blockstarts[0];\r
- for (y=0;y<UPDATEHIGH;y++)\r
- for (x=0;x<UPDATEWIDE;x++)\r
- *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;\r
- }\r
-}\r
-\r
-\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Shutdown\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Shutdown (void)\r
-{\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_FixOfs\r
-=\r
-= Sets bufferofs,displayofs, and masterofs to regular values, for the\r
-= occasions when you have moved them around manually\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_FixOfs (void)\r
-{\r
- screenstart[0] = 0;\r
- screenstart[1] = SCREENSPACE;\r
- screenstart[2] = SCREENSPACE*2;\r
-\r
- if (grmode == EGAGR)\r
- {\r
- screenpage = 0;\r
- otherpage = 1;\r
- panx = pany = pansx = pansy = panadjust = 0;\r
- displayofs = screenstart[screenpage];\r
- bufferofs = screenstart[otherpage];\r
- masterofs = screenstart[2];\r
- VW_SetScreen (displayofs,0);\r
- }\r
- else\r
- {\r
- panx = pany = pansx = pansy = panadjust = 0;\r
- bufferofs = 0;\r
- masterofs = 0x8000;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_NewMap\r
-=\r
-= Makes some convienient calculations based on maphead->\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_NewMap (void)\r
-{\r
- int i,x,y;\r
- unsigned spot,*table;\r
-\r
- mapwidth = mapheaderseg[mapon]->width;\r
- mapbyteswide = 2*mapwidth;\r
- mapheight = mapheaderseg[mapon]->height;\r
- mapwordsextra = mapwidth-PORTTILESWIDE;\r
- mapbytesextra = 2*mapwordsextra;\r
-\r
-//\r
-// make a lookup table for the maps left edge\r
-//\r
- if (mapheight > MAXMAPHEIGHT)\r
- Quit ("RF_NewMap: Map too tall!");\r
- spot = 0;\r
- for (i=0;i<mapheight;i++)\r
- {\r
- mapbwidthtable[i] = spot;\r
- spot += mapbyteswide;\r
- }\r
-\r
-//\r
-// fill in updatemapofs with the new width info\r
-//\r
- table = &updatemapofs[0];\r
- for (y=0;y<PORTTILESHIGH;y++)\r
- for (x=0;x<UPDATEWIDE;x++)\r
- *table++ = mapbwidthtable[y]+x*2;\r
-\r
-//\r
-// the y max value clips off the bottom half of a tile so a map that is\r
-// 13 + MAPBORDER*2 tile high will not scroll at all vertically\r
-//\r
- originxmax = (mapwidth-MAPBORDER-SCREENTILESWIDE)*TILEGLOBAL;\r
- originymax = (mapheight-MAPBORDER-SCREENTILESHIGH)*TILEGLOBAL;\r
- if (originxmax<originxmin) // for very small maps\r
- originxmax=originxmin;\r
- if (originymax<originymin)\r
- originymax=originymin;\r
-\r
-//\r
-// clear out the lists\r
-//\r
- RFL_InitSpriteList ();\r
- RFL_InitAnimList ();\r
- RFL_ClearScrollBlocks ();\r
- RF_SetScrollBlock (0,MAPBORDER-1,true);\r
- RF_SetScrollBlock (0,mapheight-MAPBORDER,true);\r
- RF_SetScrollBlock (MAPBORDER-1,0,false);\r
- RF_SetScrollBlock (mapwidth-MAPBORDER,0,false);\r
-\r
-\r
- lasttimecount = TimeCount; // setup for adaptive timing\r
- tics = 1;\r
-}\r
-\r
-//===========================================================================\r
-\r
-#ifdef KEEN6\r
-/*\r
-==========================\r
-=\r
-= RFL_CheckTileSound\r
-=\r
-= Checks if the tile plays a sound and if so adds that info to the animation\r
-=\r
-==========================\r
-*/\r
-\r
-#define NUMSOUNDTILES 2\r
-typedef struct {\r
- unsigned tilenums[NUMSOUNDTILES];\r
- int sounds[NUMSOUNDTILES];\r
-} tilesoundtype;\r
-\r
-tilesoundtype far soundtiles = {\r
- {2152|0x8000, 2208|0x8000},\r
- {SND_STOMP, SND_FLAME}\r
-};\r
-\r
-void RFL_CheckTileSound(tiletype *anim, unsigned tile)\r
-{\r
- int i;\r
-\r
- for (i=0; i<NUMSOUNDTILES; i++)\r
- {\r
- if (soundtiles.tilenums[i] == tile)\r
- {\r
- anim->soundtile = tile;\r
- anim->sound = soundtiles.sounds[i];\r
- break;\r
- }\r
- }\r
-}\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= RF_MarkTileGraphics\r
-=\r
-= Goes through mapplane[0/1] and marks all background/foreground tiles\r
-= needed, then follows all animation sequences to make sure animated\r
-= tiles get all the stages. Every unique animating tile is given an\r
-= entry in allanims[], so every instance of that tile will animate at the\r
-= same rate. The info plane for each animating tile will hold a pointer\r
-= into allanims[], therefore you can't have both an animating foreground\r
-= and background tile in the same spot!\r
-=\r
-==========================\r
-*/\r
-\r
-void RF_MarkTileGraphics (void)\r
-{\r
- unsigned size;\r
- int tile,next,anims,change;\r
- unsigned far *start,far *end,far *info;\r
- unsigned i,tilehigh;\r
- char str[80],str2[10];\r
-\r
- memset (allanims,0,sizeof(allanims));\r
- numanimchains = 0;\r
-\r
- size = mapwidth*mapheight;\r
-\r
-//\r
-// background plane\r
-//\r
- start = mapsegs[0];\r
- info = mapsegs[2];\r
- end = start+size;\r
- do\r
- {\r
- tile = *start++;\r
- if (tile>=0) // <0 is a tile that is never drawn\r
- {\r
- CA_MarkGrChunk(STARTTILE16+tile);\r
- if (tinf[ANIM+tile])\r
- {\r
- // this tile will animated\r
-\r
- if (tinf[SPEED+tile])\r
- {\r
- if (!tinf[ANIM+tile])\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Background anim of 0:");\r
- itoa (tile,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- for (i=0;i<numanimchains;i++)\r
- if (allanims[i].current == tile)\r
- {\r
- *info = (unsigned)&allanims[i];\r
- goto nextback;\r
- }\r
-\r
- // new chain of animating tiles\r
-\r
- if (i>=MAXANIMTYPES)\r
- Quit ("RF_MarkTileGraphics: Too many unique animated tiles!");\r
- allanims[i].current = tile;\r
- allanims[i].count = tinf[SPEED+tile];\r
-#ifdef KEEN6\r
- allanims[i].visible = 0;\r
- allanims[i].sound = -1;\r
-#endif\r
- *info = (unsigned)&allanims[i];\r
- numanimchains++;\r
- }\r
-#ifdef KEEN6\r
- RFL_CheckTileSound(&allanims[i], tile);\r
-#endif\r
-\r
- anims = 0;\r
- change = (signed char)(tinf[ANIM+tile]);\r
- next = tile+change;\r
- while (change && next != tile)\r
- {\r
-#ifdef KEEN6\r
- RFL_CheckTileSound(&allanims[i], next);\r
-#endif\r
- CA_MarkGrChunk(STARTTILE16+next);\r
- change = (signed char)(tinf[ANIM+next]);\r
- next += change;\r
- if (++anims > 20)\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Unending background animation:");\r
- itoa (next,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- }\r
-\r
- }\r
- }\r
-nextback:\r
- info++;\r
- } while (start<end);\r
-\r
-//\r
-// foreground plane\r
-//\r
- start = mapsegs[1];\r
- info = mapsegs[2];\r
- end = start+size;\r
- do\r
- {\r
- tile = *start++;\r
- if (tile>=0) // <0 is a tile that is never drawn\r
- {\r
- CA_MarkGrChunk(STARTTILE16M+tile);\r
- if (tinf[MANIM+tile])\r
- {\r
- // this tile will animated\r
-\r
- if (tinf[MSPEED+tile])\r
- {\r
- if (!tinf[MANIM+tile])\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Foreground anim of 0:");\r
- itoa (tile,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- tilehigh = tile | 0x8000; // foreground tiles have high bit\r
- for (i=0;i<numanimchains;i++)\r
- if (allanims[i].current == tilehigh)\r
- {\r
- *info = (unsigned)&allanims[i];\r
- goto nextfront;\r
- }\r
-\r
- // new chain of animating tiles\r
-\r
- if (i>=MAXANIMTYPES)\r
- Quit ("RF_MarkTileGraphics: Too many unique animated tiles!");\r
- allanims[i].current = tilehigh;\r
- allanims[i].count = tinf[MSPEED+tile];\r
-#ifdef KEEN6\r
- allanims[i].visible = 0;\r
- allanims[i].sound = -1;\r
-#endif\r
- *info = (unsigned)&allanims[i];\r
- numanimchains++;\r
- }\r
-\r
-#ifdef KEEN6\r
- RFL_CheckTileSound(&allanims[i], tilehigh);\r
-#endif\r
- anims = 0;\r
- change = (signed char)(tinf[MANIM+tile]);\r
- next = tile+change;\r
- while (change && next != tile)\r
- {\r
-#ifdef KEEN6\r
- RFL_CheckTileSound(&allanims[i], next | 0x8000); // foreground tiles have high bit\r
-#endif\r
- CA_MarkGrChunk(STARTTILE16M+next);\r
- change = (signed char)(tinf[MANIM+next]);\r
- next += change;\r
- if (++anims > 20)\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Unending foreground animation:");\r
- itoa (next,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- }\r
-\r
- }\r
- }\r
-nextfront:\r
- info++;\r
- } while (start<end);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=========================\r
-=\r
-= RFL_InitAnimList\r
-=\r
-= Call to clear out the entire animating tile list and return all of them to\r
-= the free list.\r
-=\r
-=========================\r
-*/\r
-\r
-void RFL_InitAnimList (void)\r
-{\r
- int i;\r
-\r
- animfreeptr = &animarray[0];\r
-\r
- for (i=0;i<MAXANIMTILES-1;i++)\r
- animarray[i].nexttile = &animarray[i+1];\r
-\r
- animarray[i].nexttile = NULL;\r
-\r
- animhead = NULL; // nothing in list\r
-\r
-#ifdef KEEN6\r
- {\r
- tiletype *anim;\r
-\r
- for (anim = allanims; anim->current != 0; anim++)\r
- anim->visible = 0;\r
- }\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_CheckForAnimTile\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_CheckForAnimTile (unsigned x, unsigned y)\r
-{\r
- unsigned tile,offset,speed,lasttime,thistime,timemissed;\r
- unsigned far *map;\r
- animtiletype *anim,*next;\r
-\r
-// the info plane of each animating tile has a near pointer into allanims[]\r
-// which gives the current state of all concurrently animating tiles\r
-\r
- offset = mapbwidthtable[y]/2+x;\r
-\r
-//\r
-// background\r
-//\r
- map = mapsegs[0]+offset;\r
- tile = *map;\r
- if (tinf[ANIM+tile] && tinf[SPEED+tile])\r
- {\r
- if (!animfreeptr)\r
- Quit ("RF_CheckForAnimTile: No free spots in tilearray!");\r
- anim = animfreeptr;\r
- animfreeptr = animfreeptr->nexttile;\r
- next = animhead; // stick it at the start of the list\r
- animhead = anim;\r
- if (next)\r
- next->prevptr = &anim->nexttile;\r
- anim->nexttile = next;\r
- anim->prevptr = &animhead;\r
-\r
- anim->x = x;\r
- anim->y = y;\r
- anim->tile = tile;\r
- anim->mapplane = map;\r
- anim->chain = (tiletype *)*(mapsegs[2]+offset);\r
-#ifdef KEEN6\r
- anim->chain->visible++;\r
-#endif\r
- }\r
-\r
-//\r
-// foreground\r
-//\r
- map = mapsegs[1]+offset;\r
- tile = *map;\r
- if (tinf[MANIM+tile] && tinf[MSPEED+tile])\r
- {\r
- if (!animfreeptr)\r
- Quit ("RF_CheckForAnimTile: No free spots in tilearray!");\r
- anim = animfreeptr;\r
- animfreeptr = animfreeptr->nexttile;\r
- next = animhead; // stick it at the start of the list\r
- animhead = anim;\r
- if (next)\r
- next->prevptr = &anim->nexttile;\r
- anim->nexttile = next;\r
- anim->prevptr = &animhead;\r
-\r
- anim->x = x;\r
- anim->y = y;\r
- anim->tile = tile;\r
- anim->mapplane = map;\r
- anim->chain = (tiletype *)*(mapsegs[2]+offset);\r
-#ifdef KEEN6\r
- anim->chain->visible++;\r
-#endif\r
- }\r
-\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_RemoveAnimsOnX\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_RemoveAnimsOnX (unsigned x)\r
-{\r
- animtiletype *current,*next;\r
-\r
- current = animhead;\r
- while (current)\r
- {\r
- if (current->x == x)\r
- {\r
-#ifdef KEEN6\r
- current->chain->visible--;\r
-#endif\r
- *(void **)current->prevptr = current->nexttile;\r
- if (current->nexttile)\r
- current->nexttile->prevptr = current->prevptr;\r
- next = current->nexttile;\r
- current->nexttile = animfreeptr;\r
- animfreeptr = current;\r
- current = next;\r
- }\r
- else\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_RemoveAnimsOnY\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_RemoveAnimsOnY (unsigned y)\r
-{\r
- animtiletype *current,*next;\r
-\r
- current = animhead;\r
- while (current)\r
- {\r
- if (current->y == y)\r
- {\r
-#ifdef KEEN6\r
- current->chain->visible--;\r
-#endif\r
- *(void **)current->prevptr = current->nexttile;\r
- if (current->nexttile)\r
- current->nexttile->prevptr = current->prevptr;\r
- next = current->nexttile;\r
- current->nexttile = animfreeptr;\r
- animfreeptr = current;\r
- current = next;\r
- }\r
- else\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_RemoveAnimsInBlock\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_RemoveAnimsInBlock (unsigned x, unsigned y, unsigned width, unsigned height)\r
-{\r
- animtiletype *current,*next;\r
-\r
- current = animhead;\r
- while (current)\r
- {\r
- if (current->x - x < width && current->y - y < height)\r
- {\r
-#ifdef KEEN6\r
- current->chain->visible--;\r
-#endif\r
- *(void **)current->prevptr = current->nexttile;\r
- if (current->nexttile)\r
- current->nexttile->prevptr = current->prevptr;\r
- next = current->nexttile;\r
- current->nexttile = animfreeptr;\r
- animfreeptr = current;\r
- current = next;\r
- }\r
- else\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_AnimateTiles\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_AnimateTiles (void)\r
-{\r
- animtiletype *current;\r
- unsigned updateofs,tile,x,y;\r
- tiletype *anim;\r
-\r
-//\r
-// animate the lists of tiles\r
-//\r
- anim = &allanims[0];\r
- while (anim->current)\r
- {\r
- anim->count-=tics;\r
- while ( anim->count < 1)\r
- {\r
- if (anim->current & 0x8000)\r
- {\r
- tile = anim->current & 0x7fff;\r
- tile += (signed char)tinf[MANIM+tile];\r
- anim->count += tinf[MSPEED+tile];\r
- tile |= 0x8000;\r
- }\r
- else\r
- {\r
- tile = anim->current;\r
- tile += (signed char)tinf[ANIM+tile];\r
- anim->count += tinf[SPEED+tile];\r
- }\r
- anim->current = tile;\r
-#ifdef KEEN6\r
- if (anim->visible && anim->current == anim->soundtile && anim->sound != -1)\r
- {\r
- SD_PlaySound(anim->sound);\r
- }\r
-#endif\r
- }\r
- anim++;\r
- }\r
-\r
-\r
-//\r
-// traverse the list of animating tiles\r
-//\r
- current = animhead;\r
- while (current)\r
- {\r
- tile =current->chain->current;\r
- if ( tile != current->tile)\r
- {\r
- // tile has animated\r
- //\r
- // remove tile from master screen cache,\r
- // change a tile to its next state, set the structure up for\r
- // next animation, and post an update region to both update pages\r
- //\r
- current->tile = tile;\r
-\r
- *(current->mapplane) = tile & 0x7fff; // change in map\r
-\r
- x = current->x-originxtile;\r
- y = current->y-originytile;\r
-\r
- if (x>=PORTTILESWIDE || y>=PORTTILESHIGH)\r
- Quit ("RFL_AnimateTiles: Out of bounds!");\r
-\r
- updateofs = uwidthtable[y] + x;\r
- RFL_NewTile(updateofs); // puts "1"s in both pages\r
- }\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= RFL_InitSpriteList\r
-=\r
-= Call to clear out the entire sprite list and return all of them to\r
-= the free list.\r
-=\r
-=========================\r
-*/\r
-\r
-void RFL_InitSpriteList (void)\r
-{\r
- int i;\r
-\r
- spritefreeptr = &spritearray[0];\r
- for (i=0;i<MAXSPRITES-1;i++)\r
- spritearray[i].nextsprite = &spritearray[i+1];\r
-\r
- spritearray[i].nextsprite = NULL;\r
-\r
-// NULL in all priority levels\r
-\r
- memset (prioritystart,0,sizeof(prioritystart));\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_CalcOriginStuff\r
-=\r
-= Calculate all the global variables for a new position\r
-= Long parms so position can be clipped to a maximum near 64k\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_CalcOriginStuff (long x, long y)\r
-{\r
- originxglobal = x;\r
- originyglobal = y;\r
- originxtile = originxglobal>>G_T_SHIFT;\r
- originytile = originyglobal>>G_T_SHIFT;\r
- originxscreen = originxtile<<SX_T_SHIFT;\r
- originyscreen = originytile<<SY_T_SHIFT;\r
- originmap = mapbwidthtable[originytile] + originxtile*2;\r
-\r
-#if GRMODE == EGAGR\r
- panx = (originxglobal>>G_P_SHIFT) & 15;\r
- pansx = panx & 8;\r
- pany = pansy = (originyglobal>>G_P_SHIFT) & 15;\r
- panadjust = panx/8 + ylookup[pany];\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- panx = (originxglobal>>G_P_SHIFT) & 15;\r
- pansx = panx & 12;\r
- pany = pansy = (originyglobal>>G_P_SHIFT) & 15;\r
- panadjust = pansx/4 + ylookup[pansy];\r
-#endif\r
-\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_ClearScrollBlocks\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_ClearScrollBlocks (void)\r
-{\r
- hscrollblocks = vscrollblocks = 0;\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= RF_SetScrollBlock\r
-=\r
-= Sets a horizontal or vertical scroll block\r
-= a horizontal block is ----, meaning it blocks up/down movement\r
-=\r
-=================\r
-*/\r
-\r
-void RF_SetScrollBlock (int x, int y, boolean horizontal)\r
-{\r
- if (horizontal)\r
- {\r
- hscrolledge[hscrollblocks] = y;\r
- if (hscrollblocks++ == MAXSCROLLEDGES)\r
- Quit ("RF_SetScrollBlock: Too many horizontal scroll blocks");\r
- }\r
- else\r
- {\r
- vscrolledge[vscrollblocks] = x;\r
- if (vscrollblocks++ == MAXSCROLLEDGES)\r
- Quit ("RF_SetScrollBlock: Too many vertical scroll blocks");\r
- }\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_BoundScroll\r
-=\r
-= Bound a given x/y movement to scroll blocks\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_BoundScroll (int x, int y)\r
-{\r
- int check,newxtile,newytile;\r
-\r
- originxglobal += x;\r
- originyglobal += y;\r
-\r
- newxtile= originxglobal >> G_T_SHIFT;\r
- newytile = originyglobal >> G_T_SHIFT;\r
-\r
- if (x>0)\r
- {\r
- newxtile+=SCREENTILESWIDE;\r
- for (check=0;check<vscrollblocks;check++)\r
- if (vscrolledge[check] == newxtile)\r
- {\r
- originxglobal = originxglobal&0xff00;\r
- break;\r
- }\r
- }\r
- else if (x<0)\r
- {\r
- for (check=0;check<vscrollblocks;check++)\r
- if (vscrolledge[check] == newxtile)\r
- {\r
- originxglobal = (originxglobal&0xff00)+0x100;\r
- break;\r
- }\r
- }\r
-\r
-\r
- if (y>0)\r
- {\r
- newytile+=SCREENTILESHIGH;\r
- for (check=0;check<hscrollblocks;check++)\r
- if (hscrolledge[check] == newytile)\r
- {\r
- originyglobal = originyglobal&0xff00;\r
- break;\r
- }\r
- }\r
- else if (y<0)\r
- {\r
- for (check=0;check<hscrollblocks;check++)\r
- if (hscrolledge[check] == newytile)\r
- {\r
- originyglobal = (originyglobal&0xff00)+0x100;\r
- break;\r
- }\r
- }\r
-\r
-\r
- RFL_CalcOriginStuff (originxglobal, originyglobal);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_SetRefreshHook\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_SetRefreshHook (void (*func) (void) )\r
-{\r
- refreshvector = func;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_NewRow\r
-=\r
-= Bring a new row of tiles onto the port, spawning animating tiles\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_NewRow (int dir)\r
-{\r
- unsigned count,updatespot,updatestep;\r
- int x,y,xstep,ystep;\r
-\r
- switch (dir)\r
- {\r
- case 0: // top row\r
- updatespot = 0;\r
- updatestep = 1;\r
- x = originxtile;\r
- y = originytile;\r
- xstep = 1;\r
- ystep = 0;\r
- count = PORTTILESWIDE;\r
- break;\r
-\r
- case 1: // right row\r
- updatespot = PORTTILESWIDE-1;\r
- updatestep = UPDATEWIDE;\r
- x = originxtile + PORTTILESWIDE-1;\r
- y = originytile;\r
- xstep = 0;\r
- ystep = 1;\r
- count = PORTTILESHIGH;\r
- break;\r
-\r
- case 2: // bottom row\r
- updatespot = UPDATEWIDE*(PORTTILESHIGH-1);\r
- updatestep = 1;\r
- x = originxtile;\r
- y = originytile + PORTTILESHIGH-1;\r
- xstep = 1;\r
- ystep = 0;\r
- count = PORTTILESWIDE;\r
- break;\r
-\r
- case 3: // left row\r
- updatespot = 0;\r
- updatestep = UPDATEWIDE;\r
- x = originxtile;\r
- y = originytile;\r
- xstep = 0;\r
- ystep = 1;\r
- count = PORTTILESHIGH;\r
- break;\r
- default:\r
- Quit ("RFL_NewRow: Bad dir!");\r
- }\r
-\r
- while (count--)\r
- {\r
- RFL_NewTile(updatespot);\r
- RFL_CheckForAnimTile (x,y);\r
- updatespot+=updatestep;\r
- x+=xstep;\r
- y+=ystep;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_ForceRefresh\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_ForceRefresh (void)\r
-{\r
- RF_NewPosition (originxglobal,originyglobal);\r
- RF_Refresh ();\r
- RF_Refresh ();\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_MapToMap\r
-=\r
-= Copies a block of tiles (all three planes) from one point\r
-= in the map to another, accounting for animating tiles\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_MapToMap (unsigned srcx, unsigned srcy,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height)\r
-{\r
- int x,y;\r
- unsigned source,destofs,xspot,yspot;\r
- unsigned linedelta,p0,p1,p2,updatespot;\r
- unsigned far *source0, far *source1, far *source2;\r
- unsigned far *dest0, far *dest1, far *dest2;\r
- boolean changed;\r
-\r
- RFL_RemoveAnimsInBlock (destx,desty,width,height);\r
-\r
- source = mapbwidthtable[srcy]/2 + srcx;\r
-\r
- source0 = mapsegs[0]+source;\r
- source1 = mapsegs[1]+source;\r
- source2 = mapsegs[2]+source;\r
-\r
- destofs = mapbwidthtable[desty]/2 + destx;\r
- destofs -= source;\r
-\r
- linedelta = mapwidth - width;\r
-\r
- for (y=0;y<height;y++,source0+=linedelta,source1+=linedelta,source2+=linedelta)\r
- for (x=0;x<width;x++,source0++,source1++,source2++)\r
- {\r
- p0 = *source0;\r
- p1 = *source1;\r
- p2 = *source2;\r
-\r
- dest0 = source0 + destofs;\r
- dest1 = source1 + destofs;\r
- dest2 = source2 + destofs;\r
-\r
-//\r
-// only make a new tile if it is different\r
-//\r
- if (p0 != *dest0 || p1 != *dest1 || p2 != *dest2)\r
- {\r
- *dest0 = p0;\r
- *dest1 = p1;\r
- *dest2 = p2;\r
- changed = true;\r
- }\r
- else\r
- changed = false;\r
-\r
-//\r
-// if tile is on the view port\r
-//\r
- xspot = destx+x-originxtile;\r
- yspot = desty+y-originytile;\r
- if (yspot < PORTTILESHIGH && xspot < PORTTILESWIDE)\r
- {\r
- if (changed)\r
- {\r
- updatespot = uwidthtable[yspot]+xspot;\r
- RFL_NewTile(updatespot);\r
- }\r
- RFL_CheckForAnimTile (destx+x,desty+y);\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_MemToMap\r
-=\r
-= Copies a string of tiles from main memory to the map,\r
-= accounting for animating tiles\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_MemToMap (unsigned far *source, unsigned plane,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height)\r
-{\r
- int x,y;\r
- unsigned xspot,yspot;\r
- unsigned linedelta,updatespot;\r
- unsigned far *dest,old,new;\r
- boolean changed;\r
-\r
- RFL_RemoveAnimsInBlock (destx,desty,width,height);\r
-\r
- dest = mapsegs[plane] + mapbwidthtable[desty]/2 + destx;\r
-\r
- linedelta = mapwidth - width;\r
-\r
- for (y=0;y<height;y++,dest+=linedelta)\r
- for (x=0;x<width;x++)\r
- {\r
- old = *dest;\r
- new = *source++;\r
- if (old != new)\r
- {\r
- *dest = new;\r
- changed = true;\r
- }\r
- else\r
- changed = false;\r
-\r
- dest++;\r
- xspot = destx+x-originxtile;\r
- yspot = desty+y-originytile;\r
- if (yspot < PORTTILESHIGH && xspot < PORTTILESWIDE)\r
- {\r
- if (changed)\r
- {\r
- updatespot = uwidthtable[yspot]+xspot;\r
- RFL_NewTile(updatespot);\r
- }\r
- RFL_CheckForAnimTile (destx+x,desty+y);\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RFL_BoundNewOrigin\r
-=\r
-= Copies a string of tiles from main memory to the map,\r
-= accounting for animating tiles\r
-=\r
-=====================\r
-*/\r
-\r
-void RFL_BoundNewOrigin (unsigned orgx,unsigned orgy)\r
-{\r
- int check,edge;\r
-\r
-//\r
-// calculate new origin related globals\r
-//\r
- if (orgx<originxmin)\r
- orgx=originxmin;\r
- else if (orgx>originxmax)\r
- orgx=originxmax;\r
-\r
- if (orgy<originymin)\r
- orgy=originymin;\r
- else if (orgy>originymax)\r
- orgy=originymax;\r
-\r
- originxtile = orgx>>G_T_SHIFT;\r
- originytile = orgy>>G_T_SHIFT;\r
-\r
- for (check=0;check<vscrollblocks;check++)\r
- {\r
- edge = vscrolledge[check];\r
- if (edge>=originxtile && edge <=originxtile+10)\r
- {\r
- orgx = (edge+1)*TILEGLOBAL;\r
- break;\r
- }\r
- if (edge>=originxtile+11 && edge <=originxtile+20)\r
- {\r
- orgx = (edge-20)*TILEGLOBAL;\r
- break;\r
- }\r
- }\r
-\r
- for (check=0;check<hscrollblocks;check++)\r
- {\r
- edge = hscrolledge[check];\r
- if (edge>=originytile && edge <=originytile+6)\r
- {\r
- orgy = (edge+1)*TILEGLOBAL;\r
- break;\r
- }\r
- if (edge>=originytile+7 && edge <=originytile+13)\r
- {\r
- orgy = (edge-13)*TILEGLOBAL;\r
- break;\r
- }\r
- }\r
-\r
-\r
- RFL_CalcOriginStuff (orgx,orgy);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_ClearBlock\r
-=\r
-= Posts erase blocks to clear a certain area of the screen to the master\r
-= screen, to erase text or something draw directly to the screen\r
-=\r
-= Parameters in pixels, but erasure is byte bounded\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_ClearBlock (int x, int y, int width, int height)\r
-{\r
- eraseblocktype block;\r
-\r
-#if GRMODE == EGAGR\r
- block.screenx = x/8+originxscreen;\r
- block.screeny = y+originyscreen;\r
- block.width = (width+(x&7)+7)/8;\r
- block.height = height;\r
- memcpy (eraselistptr[0]++,&block,sizeof(block));\r
- memcpy (eraselistptr[1]++,&block,sizeof(block));\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- block.screenx = x/4+originxscreen;\r
- block.screeny = y+originyscreen;\r
- block.width = (width+(x&3)+3)/4;\r
- block.height = height;\r
- memcpy (eraselistptr[0]++,&block,sizeof(block));\r
-#endif\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_RedrawBlock\r
-=\r
-= Causes a number of tiles to be redrawn to the master screen and updated\r
-=\r
-= Parameters in pixels, but erasure is tile bounded\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_RedrawBlock (int x, int y, int width, int height)\r
-{\r
- int xx,yy,xl,xh,yl,yh;\r
-\r
- xl=(x+panx)/16;\r
- xh=(x+panx+width+15)/16;\r
- yl=(y+pany)/16;\r
- yh=(y+pany+height+15)/16;\r
- for (yy=yl;yy<=yh;yy++)\r
- for (xx=xl;xx<=xh;xx++)\r
- RFL_NewTile (yy*UPDATEWIDE+xx);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_CalcTics\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_CalcTics (void)\r
-{\r
- long newtime,oldtimecount;\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- if (lasttimecount > TimeCount)\r
- TimeCount = lasttimecount; // if the game was paused a LONG time\r
-\r
- if (DemoMode) // demo recording and playback needs\r
- { // to be constant\r
-//\r
-// take DEMOTICS or more tics, and modify Timecount to reflect time taken\r
-//\r
- oldtimecount = lasttimecount;\r
- while (TimeCount<oldtimecount+DEMOTICS*2)\r
- ;\r
- lasttimecount = oldtimecount + DEMOTICS;\r
- TimeCount = lasttimecount + DEMOTICS;\r
- tics = DEMOTICS;\r
- }\r
- else\r
- {\r
-//\r
-// non demo, so report actual time\r
-//\r
- do\r
- {\r
- newtime = TimeCount;\r
- tics = newtime-lasttimecount;\r
- } while (tics<MINTICS);\r
- lasttimecount = newtime;\r
-\r
-#ifdef PROFILE\r
- strcpy (scratch,"\tTics:");\r
- itoa (tics,str,10);\r
- strcat (scratch,str);\r
- strcat (scratch,"\n");\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
- if (tics>MAXTICS)\r
- {\r
- TimeCount -= (tics-MAXTICS);\r
- tics = MAXTICS;\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_FindFreeBuffer\r
-=\r
-= Finds the start of unused, non visable buffer space\r
-=\r
-=====================\r
-*/\r
-\r
-unsigned RF_FindFreeBuffer (void)\r
-{\r
- unsigned spot,i,j;\r
- boolean ok;\r
-\r
- for (i=0;i<3;i++)\r
- {\r
- spot = screenstart[i]+SCREENSPACE;\r
- ok = true;\r
- for (j=0;j<3;j++)\r
- if (spot == screenstart[j])\r
- {\r
- ok = false;\r
- break;\r
- }\r
- if (ok)\r
- return spot;\r
- }\r
-\r
- return 0; // never get here...\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- EGA specific routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == EGAGR\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_NewPosition EGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_NewPosition (unsigned x, unsigned y)\r
-{\r
- int mx,my;\r
- byte *page0ptr,*page1ptr;\r
- unsigned updatenum;\r
-\r
- RFL_BoundNewOrigin (x,y);\r
-//\r
-// clear out all animating tiles\r
-//\r
- RFL_InitAnimList ();\r
-\r
-//\r
-// set up the new update arrays at base position\r
-//\r
- updatestart[0] = baseupdatestart[0];\r
- updatestart[1] = baseupdatestart[1];\r
- updateptr = updatestart[otherpage];\r
-\r
- page0ptr = updatestart[0]+PORTTILESWIDE; // used to stick "0"s after rows\r
- page1ptr = updatestart[1]+PORTTILESWIDE;\r
-\r
- updatenum = 0; // start at first visable tile\r
-\r
- for (my=0;my<PORTTILESHIGH;my++)\r
- {\r
- for (mx=0;mx<PORTTILESWIDE;mx++)\r
- {\r
- RFL_NewTile(updatenum); // puts "1"s in both pages\r
- RFL_CheckForAnimTile(mx+originxtile,my+originytile);\r
- updatenum++;\r
- }\r
- updatenum++;\r
- *page0ptr = *page1ptr = 0; // set a 0 at end of a line of tiles\r
- page0ptr+=(PORTTILESWIDE+1);\r
- page1ptr+=(PORTTILESWIDE+1);\r
- }\r
- *(word *)(page0ptr-PORTTILESWIDE)\r
- = *(word *)(page1ptr-PORTTILESWIDE) = UPDATETERMINATE;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Scroll EGA\r
-=\r
-= Move the origin x/y global coordinates, readjust the screen panning, and\r
-= scroll if needed. If the scroll distance is greater than one tile, the\r
-= entire screen will be redrawn (this could be generalized, but scrolling\r
-= more than one tile per refresh is a bad idea!).\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Scroll (int x, int y)\r
-{\r
- long neworgx,neworgy;\r
- int i,deltax,deltay,absdx,absdy;\r
- int oldxt,oldyt,move,yy;\r
- unsigned updatespot;\r
- byte *update0,*update1;\r
- unsigned oldpanx,oldpanadjust,oldscreen,newscreen,screencopy;\r
- int screenmove;\r
-\r
- oldxt = originxtile;\r
- oldyt = originytile;\r
- oldpanadjust = panadjust;\r
- oldpanx = panx;\r
-\r
- RFL_BoundScroll (x,y);\r
-\r
- deltax = originxtile - oldxt;\r
- absdx = abs(deltax);\r
- deltay = originytile - oldyt;\r
- absdy = abs(deltay);\r
-\r
- if (absdx>1 || absdy>1)\r
- {\r
- //\r
- // scrolled more than one tile, so start from scratch\r
- //\r
- RF_NewPosition(originxglobal,originyglobal);\r
- return;\r
- }\r
-\r
- if (!absdx && !absdy)\r
- return; // the screen has not scrolled an entire tile\r
-\r
-\r
-//\r
-// adjust screens and handle SVGA crippled compatability mode\r
-//\r
- screenmove = deltay*16*SCREENWIDTH + deltax*TILEWIDTH;\r
- for (i=0;i<3;i++)\r
- {\r
- screenstart[i]+= screenmove;\r
- if (compatability && screenstart[i] > (0x10000l-SCREENSPACE) )\r
- {\r
- //\r
- // move the screen to the opposite end of the buffer\r
- //\r
- screencopy = screenmove>0 ? FREEEGAMEM : -FREEEGAMEM;\r
- oldscreen = screenstart[i] - screenmove;\r
- newscreen = oldscreen + screencopy;\r
- screenstart[i] = newscreen + screenmove;\r
- VW_ScreenToScreen (oldscreen,newscreen,\r
- PORTTILESWIDE*2,PORTTILESHIGH*16);\r
-\r
- if (i==screenpage)\r
- VW_SetScreen(newscreen+oldpanadjust,oldpanx & xpanmask);\r
- }\r
- }\r
- bufferofs = screenstart[otherpage];\r
- displayofs = screenstart[screenpage];\r
- masterofs = screenstart[2];\r
-\r
-\r
-//\r
-// float the update regions\r
-//\r
- move = deltax;\r
- if (deltay==1)\r
- move += UPDATEWIDE;\r
- else if (deltay==-1)\r
- move -= UPDATEWIDE;\r
-\r
- updatestart[0]+=move;\r
- updatestart[1]+=move;\r
-\r
-//\r
-// draw the new tiles just scrolled on to the master screen, and\r
-// mark them as needing to be copied to each screen next refreshes\r
-// Make sure a zero is at the end of each row in update\r
-//\r
-\r
- if (deltax)\r
- {\r
- if (deltax==1)\r
- {\r
- RFL_NewRow (1); // new right row\r
- RFL_RemoveAnimsOnX (originxtile-1);\r
- }\r
- else\r
- {\r
- RFL_NewRow (3); // new left row\r
- RFL_RemoveAnimsOnX (originxtile+PORTTILESWIDE);\r
- }\r
-\r
- update0 = updatestart[0]+PORTTILESWIDE;\r
- update1 = updatestart[1]+PORTTILESWIDE;\r
- for (yy=0;yy<PORTTILESHIGH;yy++)\r
- {\r
- *update0 = *update1 = 0; // drop a 0 at end of each row\r
- update0+=UPDATEWIDE;\r
- update1+=UPDATEWIDE;\r
- }\r
- }\r
-\r
-//----------------\r
-\r
- if (deltay)\r
- {\r
- if (deltay==1)\r
- {\r
- updatespot = UPDATEWIDE*(PORTTILESHIGH-1);\r
- RFL_NewRow (2); // new bottom row\r
- RFL_RemoveAnimsOnY (originytile-1);\r
- }\r
- else\r
- {\r
- updatespot = 0;\r
- RFL_NewRow (0); // new top row\r
- RFL_RemoveAnimsOnY (originytile+PORTTILESHIGH);\r
- }\r
-\r
- *(updatestart[0]+updatespot+PORTTILESWIDE) =\r
- *(updatestart[1]+updatespot+PORTTILESWIDE) = 0;\r
- }\r
-\r
-//----------------\r
-\r
- //\r
- // place a new terminator\r
- //\r
- update0 = updatestart[0]+UPDATEWIDE*PORTTILESHIGH-1;\r
- update1 = updatestart[1]+UPDATEWIDE*PORTTILESHIGH-1;\r
- *update0++ = *update1++ = 0;\r
- *(unsigned *)update0 = *(unsigned *)update1 = UPDATETERMINATE;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_PlaceSprite EGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_PlaceSprite (void **user,unsigned globalx,unsigned globaly,\r
- unsigned spritenumber, drawtype draw, int priority)\r
-{\r
- spritelisttype register *sprite,*next;\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned shift,pixx;\r
- char str[80],str2[10];\r
-\r
- if (!spritenumber || spritenumber == (unsigned)-1)\r
- {\r
- RF_RemoveSprite (user);\r
- return;\r
- }\r
-\r
- sprite = (spritelisttype *)*user;\r
-\r
- if (sprite)\r
- {\r
- // sprite allready exists in the list, so we can use it's block\r
-\r
- //\r
- // post an erase block to both pages by copying screenx,screeny,width,height\r
- // both pages may not need to be erased if the sprite just changed last frame\r
- //\r
- if (sprite->updatecount<2)\r
- {\r
- if (!sprite->updatecount)\r
- memcpy (eraselistptr[otherpage]++,sprite,sizeof(eraseblocktype));\r
- memcpy (eraselistptr[screenpage]++,sprite,sizeof(eraseblocktype));\r
- }\r
-\r
- if (priority != sprite->priority)\r
- {\r
- // sprite mvoed to another priority, so unlink the old one and\r
- // relink it in the new priority\r
-\r
- next = sprite->nextsprite; // cut old links\r
- if (next)\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
- goto linknewspot;\r
- }\r
- }\r
- else\r
- {\r
- // this is a brand new sprite, so allocate a block from the array\r
-\r
- if (!spritefreeptr)\r
- Quit ("RF_PlaceSprite: No free spots in spritearray!");\r
-\r
- sprite = spritefreeptr;\r
- spritefreeptr = spritefreeptr->nextsprite;\r
-\r
-linknewspot:\r
- next = prioritystart[priority]; // stick it in new spot\r
- if (next)\r
- next->prevptr = &sprite->nextsprite;\r
- sprite->nextsprite = next;\r
- prioritystart[priority] = sprite;\r
- sprite->prevptr = &prioritystart[priority];\r
- }\r
-\r
-//\r
-// write the new info to the sprite\r
-//\r
- spr = &spritetable[spritenumber-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[spritenumber];\r
-\r
- if (!block)\r
- {\r
- strcpy (str,"RF_PlaceSprite: Placed an uncached sprite:");\r
- itoa (spritenumber,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
-\r
- globaly+=spr->orgy;\r
- globalx+=spr->orgx;\r
-\r
- pixx = globalx >> G_SY_SHIFT;\r
- if (nopan)\r
- shift = 0;\r
- else\r
- shift = (pixx&7)/2;\r
-\r
- sprite->screenx = pixx >> (G_EGASX_SHIFT-G_SY_SHIFT);\r
- sprite->screeny = globaly >> G_SY_SHIFT;\r
- sprite->width = block->width[shift];\r
- sprite->height = spr->height;\r
- sprite->grseg = spritenumber;\r
- sprite->sourceofs = block->sourceoffset[shift];\r
- sprite->planesize = block->planesize[shift];\r
- sprite->draw = draw;\r
- sprite->priority = priority;\r
- sprite->tilex = sprite->screenx >> SX_T_SHIFT;\r
- sprite->tiley = sprite->screeny >> SY_T_SHIFT;\r
- sprite->tilewide = ( (sprite->screenx + sprite->width -1) >> SX_T_SHIFT )\r
- - sprite->tilex + 1;\r
- sprite->tilehigh = ( (sprite->screeny + sprite->height -1) >> SY_T_SHIFT )\r
- - sprite->tiley + 1;\r
-\r
- sprite->updatecount = 2; // draw on next two refreshes\r
-\r
-// save the sprite pointer off in the user's pointer so it can be moved\r
-// again later\r
-\r
- *user = sprite;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_RemoveSprite EGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_RemoveSprite (void **user)\r
-{\r
- spritelisttype *sprite,*next;\r
-\r
- sprite = (spritelisttype *)*user;\r
- if (!sprite)\r
- return;\r
-\r
-//\r
-// post an erase block to both pages by copying screenx,screeny,width,height\r
-// both pages may not need to be erased if the sprite just changed last frame\r
-//\r
- if (sprite->updatecount<2)\r
- {\r
- if (!sprite->updatecount)\r
- memcpy (eraselistptr[otherpage]++,sprite,sizeof(eraseblocktype));\r
- memcpy (eraselistptr[screenpage]++,sprite,sizeof(eraseblocktype));\r
- }\r
-\r
-//\r
-// unlink the sprite node\r
-//\r
- next = sprite->nextsprite;\r
- if (next) // if (!next), sprite is last in chain\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
-\r
-//\r
-// add it back to the free list\r
-//\r
- sprite->nextsprite = spritefreeptr;\r
- spritefreeptr = sprite;\r
-\r
-//\r
-// null the users pointer, so next time that actor gets placed, it will\r
-// allocate a new block\r
-//\r
-\r
- *user = 0;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_EraseBlocks EGA\r
-=\r
-= Write mode 1 should be set\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_EraseBlocks (void)\r
-{\r
- eraseblocktype *block,*done;\r
- int screenxh,screenyh;\r
- unsigned pos,xtl,ytl,xth,yth,x,y;\r
- byte *updatespot;\r
- unsigned updatedelta;\r
- unsigned erasecount;\r
-\r
-#ifdef PROFILE\r
- erasecount = 0;\r
-#endif\r
-\r
- block = otherpage ? &eraselist[1][0] : &eraselist[0][0];\r
-\r
- done = eraselistptr[otherpage];\r
-\r
- while (block != done)\r
- {\r
-\r
- //\r
- // clip the block to the current screen view\r
- //\r
- block->screenx -= originxscreen;\r
- block->screeny -= originyscreen;\r
-\r
- if (block->screenx < 0)\r
- {\r
- block->width += block->screenx;\r
- if (block->width<1)\r
- goto next;\r
- block->screenx = 0;\r
- }\r
-\r
- if (block->screeny < 0)\r
- {\r
- block->height += block->screeny;\r
- if (block->height<1)\r
- goto next;\r
- block->screeny = 0;\r
- }\r
-\r
- screenxh = block->screenx + block->width;\r
- screenyh = block->screeny + block->height;\r
-\r
- if (screenxh > EGAPORTSCREENWIDE)\r
- {\r
- block->width = EGAPORTSCREENWIDE-block->screenx;\r
- screenxh = block->screenx + block->width;\r
- }\r
-\r
- if (screenyh > PORTSCREENHIGH)\r
- {\r
- block->height = PORTSCREENHIGH-block->screeny;\r
- screenyh = block->screeny + block->height;\r
- }\r
-\r
- if (block->width<1 || block->height<1)\r
- goto next;\r
-\r
- //\r
- // erase the block by copying from the master screen\r
- //\r
- pos = ylookup[block->screeny]+block->screenx;\r
- VW_ScreenToScreen (masterofs+pos,bufferofs+pos,\r
- block->width,block->height);\r
-\r
- //\r
- // put 2s in update where the block was, to force sprites to update\r
- //\r
- xtl = block->screenx >> SX_T_SHIFT;\r
- xth = (block->screenx+block->width-1) >> SX_T_SHIFT;\r
- ytl = block->screeny >> SY_T_SHIFT;\r
- yth = (block->screeny+block->height-1) >> SY_T_SHIFT;\r
-\r
- updatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 2;\r
- updatespot += updatedelta; // down to next line\r
- }\r
-#ifdef PROFILE\r
- erasecount++;\r
-#endif\r
-\r
-next:\r
- block++;\r
- }\r
- eraselistptr[otherpage] = otherpage ? &eraselist[1][0] : &eraselist[0][0];\r
-#ifdef PROFILE\r
- strcpy (scratch,"\tErase:");\r
- itoa (erasecount,str,10);\r
- strcat (scratch,str);\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_UpdateSprites EGA\r
-=\r
-= NOTE: Implement vertical clipping!\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_UpdateSprites (void)\r
-{\r
- spritelisttype *sprite;\r
- int portx,porty,x,y,xtl,xth,ytl,yth;\r
- int priority;\r
- unsigned dest;\r
- byte *updatespot,*baseupdatespot;\r
- unsigned updatedelta;\r
- unsigned updatecount;\r
- unsigned height,sourceofs;\r
-\r
-#ifdef PROFILE\r
- updatecount = 0;\r
-#endif\r
-\r
- for (priority=0;priority<PRIORITIES;priority++)\r
- {\r
- if (priority==MASKEDTILEPRIORITY)\r
- RFL_MaskForegroundTiles ();\r
-\r
- for (sprite = prioritystart[priority]; sprite ;\r
- sprite = (spritelisttype *)sprite->nextsprite)\r
- {\r
- //\r
- // see if the sprite has any visable area in the port\r
- //\r
-\r
- portx = sprite->screenx - originxscreen;\r
- porty = sprite->screeny - originyscreen;\r
- xtl = portx >> SX_T_SHIFT;\r
- xth = (portx + sprite->width-1) >> SX_T_SHIFT;\r
- ytl = porty >> SY_T_SHIFT;\r
- yth = (porty + sprite->height-1) >> SY_T_SHIFT;\r
-\r
- if (xtl<0)\r
- xtl = 0;\r
- if (xth>=PORTTILESWIDE)\r
- xth = PORTTILESWIDE-1;\r
- if (ytl<0)\r
- ytl = 0;\r
- if (yth>=PORTTILESHIGH)\r
- yth = PORTTILESHIGH-1;\r
-\r
- if (xtl>xth || ytl>yth)\r
- continue;\r
-\r
- //\r
- // see if it's visable area covers any non 0 update tiles\r
- //\r
- updatespot = baseupdatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- if (sprite->updatecount)\r
- {\r
- sprite->updatecount--; // the sprite was just placed,\r
- goto redraw; // so draw it for sure\r
- }\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- if (*updatespot++)\r
- goto redraw;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- continue; // no need to update\r
-\r
-redraw:\r
- //\r
- // set the tiles it covers to 3, because those tiles are being\r
- // updated\r
- //\r
- updatespot = baseupdatespot;\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 3;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- //\r
- // draw it!\r
- //\r
- height = sprite->height;\r
- sourceofs = sprite->sourceofs;\r
- if (porty<0)\r
- {\r
- height += porty; // clip top off\r
- sourceofs -= porty*sprite->width;\r
- porty = 0;\r
- }\r
- else if (porty+height>PORTSCREENHIGH)\r
- {\r
- height = PORTSCREENHIGH - porty; // clip bottom off\r
- }\r
-\r
- dest = bufferofs + ylookup[porty] + portx;\r
-\r
- switch (sprite->draw)\r
- {\r
- case spritedraw:\r
- VW_MaskBlock(grsegs[sprite->grseg], sourceofs,\r
- dest,sprite->width,height,sprite->planesize);\r
- break;\r
-\r
- case maskdraw:\r
- VW_InverseMask(grsegs[sprite->grseg], sourceofs,\r
- dest,sprite->width,height);\r
- break;\r
-\r
- }\r
-#ifdef PROFILE\r
- updatecount++;\r
-#endif\r
-\r
-\r
- }\r
- }\r
-#ifdef PROFILE\r
- strcpy (scratch,"\tSprites:");\r
- itoa (updatecount,str,10);\r
- strcat (scratch,str);\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Refresh EGA\r
-=\r
-= All routines will draw at the port at bufferofs, possibly copying from\r
-= the port at masterofs. The EGA version then page flips, while the\r
-= CGA version updates the screen from the buffer port.\r
-=\r
-= Screenpage is the currently displayed page, not the one being drawn\r
-= Otherpage is the page to be worked with now\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Refresh (void)\r
-{\r
- byte *newupdate;\r
-\r
- updateptr = updatestart[otherpage];\r
-\r
- RFL_AnimateTiles (); // DEBUG\r
-\r
-//\r
-// update newly scrolled on tiles and animated tiles from the master screen\r
-//\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
- RFL_UpdateTiles ();\r
- RFL_EraseBlocks ();\r
-\r
-//\r
-// Update is all 0 except where sprites have changed or new area has\r
-// been scrolled on. Go through all sprites and update the ones that cover\r
-// a non 0 update tile\r
-//\r
- EGAWRITEMODE(0);\r
- RFL_UpdateSprites ();\r
-\r
-//\r
-// if the main program has a refresh hook set, call their function before\r
-// displaying the new page\r
-//\r
- if (refreshvector)\r
- refreshvector();\r
-\r
-//\r
-// display the changed screen\r
-//\r
- VW_SetScreen(bufferofs+panadjust,panx & xpanmask);\r
-\r
-//\r
-// prepare for next refresh\r
-//\r
-// Set the update array to the middle position and clear it out to all "0"s\r
-// with an UPDATETERMINATE at the end\r
-//\r
- updatestart[otherpage] = newupdate = baseupdatestart[otherpage];\r
-asm mov ax,ds\r
-asm mov es,ax\r
-asm xor ax,ax\r
-asm mov cx,(UPDATESCREENSIZE-2)/2\r
-asm mov di,[newupdate]\r
-asm rep stosw\r
-asm mov [WORD PTR es:di],UPDATETERMINATE\r
-\r
- screenpage ^= 1;\r
- otherpage ^= 1;\r
- bufferofs = screenstart[otherpage];\r
- displayofs = screenstart[screenpage];\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- RF_CalcTics ();\r
-}\r
-\r
-#endif // GRMODE == EGAGR\r
-\r
-/*\r
-=============================================================================\r
-\r
- CGA specific routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_NewPosition CGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_NewPosition (unsigned x, unsigned y)\r
-{\r
- int mx,my;\r
- byte *spotptr;\r
- unsigned updatenum;\r
-\r
- RFL_BoundNewOrigin (x,y);\r
-\r
-//\r
-// clear out all animating tiles\r
-//\r
- RFL_InitAnimList ();\r
-\r
-//\r
-// set up the new update arrays at base position\r
-//\r
- updateptr = baseupdateptr;\r
-\r
- spotptr = updateptr + PORTTILESWIDE; // used to stick "0"s after rows\r
-\r
- updatenum = 0; // start at first visable tile\r
-\r
- for (my=0;my<PORTTILESHIGH;my++)\r
- {\r
- for (mx=0;mx<PORTTILESWIDE;mx++)\r
- {\r
- RFL_NewTile(updatenum); // puts "1"s in both pages\r
- RFL_CheckForAnimTile(mx+originxtile,my+originytile);\r
- updatenum++;\r
- }\r
- updatenum++;\r
- *spotptr = 0; // set a 0 at end of a line of tiles\r
- spotptr +=(PORTTILESWIDE+1);\r
- }\r
- *(word *)(spotptr-PORTTILESWIDE) = UPDATETERMINATE;\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Scroll CGA\r
-=\r
-= Move the origin x/y global coordinates, readjust the screen panning, and\r
-= scroll if needed. If the scroll distance is greater than one tile, the\r
-= entire screen will be redrawn (this could be generalized, but scrolling\r
-= more than one tile per refresh is a bad idea!).\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Scroll (int x, int y)\r
-{\r
- long neworgx,neworgy;\r
- int i,deltax,deltay,absdx,absdy;\r
- int oldxt,oldyt,move,yy;\r
- unsigned updatespot;\r
- byte *spotptr;\r
- unsigned oldoriginmap,oldscreen,newscreen,screencopy;\r
- int screenmove;\r
-\r
- oldxt = originxtile;\r
- oldyt = originytile;\r
-\r
- RFL_BoundScroll (x,y);\r
-\r
- deltax = originxtile - oldxt;\r
- absdx = abs(deltax);\r
- deltay = originytile - oldyt;\r
- absdy = abs(deltay);\r
-\r
- if (absdx>1 || absdy>1)\r
- {\r
- //\r
- // scrolled more than one tile, so start from scratch\r
- //\r
- RF_NewPosition(originxglobal,originyglobal);\r
- return;\r
- }\r
-\r
- if (!absdx && !absdy)\r
- return; // the screen has not scrolled an entire tile\r
-\r
-\r
-//\r
-// float screens\r
-//\r
- screenmove = deltay*16*SCREENWIDTH + deltax*TILEWIDTH;\r
- bufferofs += screenmove;\r
- masterofs += screenmove;\r
-\r
-\r
-//\r
-// float the update regions\r
-//\r
- move = deltax;\r
- if (deltay==1)\r
- move += UPDATEWIDE;\r
- else if (deltay==-1)\r
- move -= UPDATEWIDE;\r
-\r
- updateptr+=move;\r
-\r
-//\r
-// draw the new tiles just scrolled on to the master screen, and\r
-// mark them as needing to be copied to each screen next refreshes\r
-// Make sure a zero is at the end of each row in update\r
-//\r
-\r
- if (deltax)\r
- {\r
- if (deltax==1)\r
- {\r
- RFL_NewRow (1); // new right row\r
- RFL_RemoveAnimsOnX (originxtile-1);\r
- }\r
- else\r
- {\r
- RFL_NewRow (3); // new left row\r
- RFL_RemoveAnimsOnX (originxtile+PORTTILESWIDE);\r
- }\r
-\r
- spotptr = updateptr+PORTTILESWIDE;\r
- for (yy=0;yy<PORTTILESHIGH;yy++)\r
- {\r
- *spotptr = 0; // drop a 0 at end of each row\r
- spotptr+=UPDATEWIDE;\r
- }\r
- }\r
-\r
-//----------------\r
-\r
- if (deltay)\r
- {\r
- if (deltay==1)\r
- {\r
- RFL_NewRow (2); // new bottom row\r
- *(updateptr+UPDATEWIDE*(PORTTILESHIGH-1)+PORTTILESWIDE) = 0;\r
- RFL_RemoveAnimsOnY (originytile-1);\r
- }\r
- else\r
- {\r
- RFL_NewRow (0); // new top row\r
- *(updateptr+PORTTILESWIDE) = 0;\r
- RFL_RemoveAnimsOnY (originytile+PORTTILESHIGH);\r
- }\r
- }\r
-\r
-//----------------\r
-\r
- //\r
- // place a new terminator\r
- //\r
- spotptr = updateptr+UPDATEWIDE*PORTTILESHIGH-1;\r
- *spotptr++ = 0;\r
- *(unsigned *)spotptr = UPDATETERMINATE;\r
-}\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_PlaceSprite CGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_PlaceSprite (void **user,unsigned globalx,unsigned globaly,\r
- unsigned spritenumber, drawtype draw, int priority)\r
-{\r
- spritelisttype register *sprite,*next;\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned shift,pixx;\r
- char str[80],str2[10];\r
-\r
- if (!spritenumber || spritenumber == (unsigned)-1)\r
- {\r
- RF_RemoveSprite (user);\r
- return;\r
- }\r
-\r
- sprite = (spritelisttype *)*user;\r
-\r
- if (sprite)\r
- {\r
- // sprite allready exists in the list, so we can use it's block\r
-\r
- //\r
- // post an erase block to erase the old position by copying\r
- // screenx,screeny,width,height\r
- //\r
- if (!sprite->updatecount) // may not have been drawn at all yet\r
- memcpy (eraselistptr[0]++,sprite,sizeof(eraseblocktype));\r
-\r
- if (priority != sprite->priority)\r
- {\r
- // sprite moved to another priority, so unlink the old one and\r
- // relink it in the new priority\r
-\r
- next = sprite->nextsprite; // cut old links\r
- if (next)\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
- goto linknewspot;\r
- }\r
- }\r
- else\r
- {\r
- // this is a brand new sprite, so allocate a block from the array\r
-\r
- if (!spritefreeptr)\r
- Quit ("RF_PlaceSprite: No free spots in spritearray!");\r
-\r
- sprite = spritefreeptr;\r
- spritefreeptr = spritefreeptr->nextsprite;\r
-\r
-linknewspot:\r
- next = prioritystart[priority]; // stick it in new spot\r
- if (next)\r
- next->prevptr = &sprite->nextsprite;\r
- sprite->nextsprite = next;\r
- prioritystart[priority] = sprite;\r
- sprite->prevptr = &prioritystart[priority];\r
- }\r
-\r
-//\r
-// write the new info to the sprite\r
-//\r
- spr = &spritetable[spritenumber-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[spritenumber];\r
-\r
- if (!block)\r
- {\r
- strcpy (str,"RF_PlaceSprite: Placed an uncached sprite!");\r
- itoa (spritenumber,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
-\r
-\r
- globaly+=spr->orgy;\r
- globalx+=spr->orgx;\r
-\r
- sprite->screenx = globalx >> G_CGASX_SHIFT;\r
- sprite->screeny = globaly >> G_SY_SHIFT;\r
- sprite->width = block->width[0];\r
- sprite->height = spr->height;\r
- sprite->grseg = spritenumber;\r
- sprite->sourceofs = block->sourceoffset[0];\r
- sprite->planesize = block->planesize[0];\r
- sprite->draw = draw;\r
- sprite->priority = priority;\r
- sprite->tilex = sprite->screenx >> SX_T_SHIFT;\r
- sprite->tiley = sprite->screeny >> SY_T_SHIFT;\r
- sprite->tilewide = ( (sprite->screenx + sprite->width -1) >> SX_T_SHIFT )\r
- - sprite->tilex + 1;\r
- sprite->tilehigh = ( (sprite->screeny + sprite->height -1) >> SY_T_SHIFT )\r
- - sprite->tiley + 1;\r
-\r
- sprite->updatecount = 1; // draw on next refresh\r
-\r
-// save the sprite pointer off in the user's pointer so it can be moved\r
-// again later\r
-\r
- *user = sprite;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_RemoveSprite CGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_RemoveSprite (void **user)\r
-{\r
- spritelisttype *sprite,*next;\r
-\r
- sprite = (spritelisttype *)*user;\r
- if (!sprite)\r
- return;\r
-\r
-//\r
-// post an erase block to erase the old position by copying\r
-// screenx,screeny,width,height\r
-//\r
- if (!sprite->updatecount)\r
- {\r
- memcpy (eraselistptr[0]++,sprite,sizeof(eraseblocktype));\r
- }\r
-\r
-//\r
-// unlink the sprite node\r
-//\r
- next = sprite->nextsprite;\r
- if (next) // if (!next), sprite is last in chain\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
-\r
-//\r
-// add it back to the free list\r
-//\r
- sprite->nextsprite = spritefreeptr;\r
- spritefreeptr = sprite;\r
-\r
-//\r
-// null the users pointer, so next time that actor gets placed, it will\r
-// allocate a new block\r
-//\r
-\r
- *user = 0;\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_EraseBlocks CGA\r
-=\r
-= Write mode 1 should be set\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_EraseBlocks (void)\r
-{\r
- eraseblocktype *block,*done;\r
- int screenxh,screenyh;\r
- unsigned pos,xtl,ytl,xth,yth,x,y;\r
- byte *updatespot;\r
- unsigned updatedelta;\r
-\r
- block = &eraselist[0][0];\r
-\r
- done = eraselistptr[0];\r
-\r
- while (block != done)\r
- {\r
-\r
- //\r
- // clip the block to the current screen view\r
- //\r
- block->screenx -= originxscreen;\r
- block->screeny -= originyscreen;\r
-\r
- if (block->screenx < 0)\r
- {\r
- block->width += block->screenx;\r
- if (block->width<1)\r
- goto next;\r
- block->screenx = 0;\r
- }\r
-\r
- if (block->screeny < 0)\r
- {\r
- block->height += block->screeny;\r
- if (block->height<1)\r
- goto next;\r
- block->screeny = 0;\r
- }\r
-\r
- screenxh = block->screenx + block->width;\r
- screenyh = block->screeny + block->height;\r
-\r
- if (screenxh > CGAPORTSCREENWIDE)\r
- {\r
- block->width = CGAPORTSCREENWIDE-block->screenx;\r
- screenxh = block->screenx + block->width;\r
- }\r
-\r
- if (screenyh > PORTSCREENHIGH)\r
- {\r
- block->height = PORTSCREENHIGH-block->screeny;\r
- screenyh = block->screeny + block->height;\r
- }\r
-\r
- if (block->width<1 || block->height<1)\r
- goto next;\r
-\r
- //\r
- // erase the block by copying from the master screen\r
- //\r
- pos = ylookup[block->screeny]+block->screenx;\r
- block->width = (block->width + (pos&1) + 1)& ~1;\r
- pos &= ~1; // make sure a word copy gets used\r
- VW_ScreenToScreen (masterofs+pos,bufferofs+pos,\r
- block->width,block->height);\r
-\r
- //\r
- // put 2s in update where the block was, to force sprites to update\r
- //\r
- xtl = block->screenx >> SX_T_SHIFT;\r
- xth = (block->screenx+block->width-1) >> SX_T_SHIFT;\r
- ytl = block->screeny >> SY_T_SHIFT;\r
- yth = (block->screeny+block->height-1) >> SY_T_SHIFT;\r
-\r
- updatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 2;\r
- updatespot += updatedelta; // down to next line\r
- }\r
-\r
-next:\r
- block++;\r
- }\r
- eraselistptr[0] = &eraselist[0][0];\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_UpdateSprites CGA\r
-=\r
-= NOTE: Implement vertical clipping!\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_UpdateSprites (void)\r
-{\r
- spritelisttype *sprite;\r
- int portx,porty,x,y,xtl,xth,ytl,yth;\r
- int priority;\r
- unsigned dest;\r
- byte *updatespot,*baseupdatespot;\r
- unsigned updatedelta;\r
-\r
- unsigned updatecount;\r
- unsigned height,sourceofs;\r
-\r
-#ifdef PROFILE\r
- updatecount = 0;\r
-#endif\r
-\r
-\r
- for (priority=0;priority<PRIORITIES;priority++)\r
- {\r
- if (priority==MASKEDTILEPRIORITY)\r
- RFL_MaskForegroundTiles ();\r
-\r
- for (sprite = prioritystart[priority]; sprite ;\r
- sprite = (spritelisttype *)sprite->nextsprite)\r
- {\r
- //\r
- // see if the sprite has any visable area in the port\r
- //\r
-\r
- portx = sprite->screenx - originxscreen;\r
- porty = sprite->screeny - originyscreen;\r
- xtl = portx >> SX_T_SHIFT;\r
- xth = (portx + sprite->width-1) >> SX_T_SHIFT;\r
- ytl = porty >> SY_T_SHIFT;\r
- yth = (porty + sprite->height-1) >> SY_T_SHIFT;\r
-\r
- if (xtl<0)\r
- xtl = 0;\r
- if (xth>=PORTTILESWIDE)\r
- xth = PORTTILESWIDE-1;\r
- if (ytl<0)\r
- ytl = 0;\r
- if (yth>=PORTTILESHIGH)\r
- yth = PORTTILESHIGH-1;\r
-\r
- if (xtl>xth || ytl>yth)\r
- continue;\r
-\r
- //\r
- // see if it's visable area covers any non 0 update tiles\r
- //\r
- updatespot = baseupdatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- if (sprite->updatecount)\r
- {\r
- sprite->updatecount--; // the sprite was just placed,\r
- goto redraw; // so draw it for sure\r
- }\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- if (*updatespot++)\r
- goto redraw;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- continue; // no need to update\r
-\r
-redraw:\r
- //\r
- // set the tiles it covers to 3, because those tiles are being\r
- // updated\r
- //\r
- updatespot = baseupdatespot;\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 3;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- //\r
- // draw it!\r
- //\r
- height = sprite->height;\r
- sourceofs = sprite->sourceofs;\r
- if (porty<0)\r
- {\r
- height += porty; // clip top off\r
- sourceofs -= porty*sprite->width;\r
- porty = 0;\r
- }\r
- else if (porty+height>PORTSCREENHIGH)\r
- {\r
- height = PORTSCREENHIGH - porty; // clip bottom off\r
- }\r
-\r
- dest = bufferofs + ylookup[porty] + portx;\r
-\r
- switch (sprite->draw)\r
- {\r
- case spritedraw:\r
- VW_MaskBlock(grsegs[sprite->grseg], sourceofs,\r
- dest,sprite->width,height,sprite->planesize);\r
- break;\r
-\r
- case maskdraw:\r
- VW_InverseMask(grsegs[sprite->grseg], sourceofs,\r
- dest,sprite->width,height);\r
- break;\r
-\r
- }\r
-#ifdef PROFILE\r
- updatecount++;\r
-#endif\r
-\r
-\r
- }\r
- }\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Refresh CGA\r
-=\r
-= All routines will draw at the port at bufferofs, possibly copying from\r
-= the port at masterofs. The EGA version then page flips, while the\r
-= CGA version updates the screen from the buffer port.\r
-=\r
-= Screenpage is the currently displayed page, not the one being drawn\r
-= Otherpage is the page to be worked with now\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Refresh (void)\r
-{\r
- long newtime,oldtimecount;\r
-\r
- RFL_AnimateTiles ();\r
-\r
-//\r
-// update newly scrolled on tiles and animated tiles from the master screen\r
-//\r
- RFL_UpdateTiles ();\r
- RFL_EraseBlocks ();\r
-\r
-//\r
-// Update is all 0 except where sprites have changed or new area has\r
-// been scrolled on. Go through all sprites and update the ones that cover\r
-// a non 0 update tile\r
-//\r
- RFL_UpdateSprites ();\r
-\r
-//\r
-// if the main program has a refresh hook set, call their function before\r
-// displaying the new page\r
-//\r
- if (refreshvector)\r
- refreshvector();\r
-\r
-//\r
-// update everything to the screen\r
-//\r
- VW_CGAFullUpdate ();\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- RF_CalcTics ();\r
-}\r
-\r
-#endif // GRMODE == CGAGR\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_RF.H\r
-\r
-#define __ID_RF__\r
-\r
-#ifndef __ID_MM__\r
-#include "ID_MM.H"\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define MINTICS 2\r
-#define MAXTICS 5\r
-#define DEMOTICS 3\r
-\r
-#define MAPBORDER 2 // map border must be at least 1\r
-\r
-#ifdef KEEN5\r
-\r
-#define MAXSPRITES 60 // max tracked sprites\r
-#define MAXANIMTILES 90 // max animating tiles on screen\r
-#define MAXANIMTYPES 80 // max different unique anim tiles on map\r
-\r
-#define MAXMAPHEIGHT 250\r
-\r
-#else\r
-\r
-#define MAXSPRITES 60 // max tracked sprites\r
-#define MAXANIMTILES 90 // max animating tiles on screen\r
-#define MAXANIMTYPES 65 // max different unique anim tiles on map\r
-\r
-#define MAXMAPHEIGHT 200\r
-\r
-#endif\r
-\r
-#define PRIORITIES 4\r
-#define MASKEDTILEPRIORITY 3 // planes go: 0,1,2,MTILES,3\r
-\r
-#define TILEGLOBAL 256\r
-#define PIXGLOBAL 16\r
-\r
-#define G_T_SHIFT 8 // global >> ?? = tile\r
-#define G_P_SHIFT 4 // global >> ?? = pixels\r
-#define P_T_SHIFT 4 // pixels >> ?? = tile\r
-\r
-#define PORTTILESWIDE 21 // all drawing takes place inside a\r
-#define PORTTILESHIGH 14 // non displayed port of this size\r
-\r
-//#define PORTGLOBALWIDE (21*TILEGLOBAL)\r
-//#define PORTGLOBALHIGH (14*TILEGLOBAL)\r
-\r
-#define UPDATEWIDE (PORTTILESWIDE+1)\r
-#define UPDATEHIGH PORTTILESHIGH\r
-\r
-\r
-//===========================================================================\r
-\r
-typedef enum {spritedraw,maskdraw} drawtype;\r
-\r
-/*\r
-=============================================================================\r
-\r
- PUBLIC VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-extern boolean compatability; // crippled refresh for wierdo SVGAs\r
-\r
-extern unsigned tics;\r
-extern long lasttimecount;\r
-\r
-extern unsigned originxglobal,originyglobal;\r
-extern unsigned originxtile,originytile;\r
-extern unsigned originxscreen,originyscreen;\r
-\r
-extern unsigned mapwidth,mapheight,mapbyteswide,mapwordswide\r
- ,mapbytesextra,mapwordsextra;\r
-extern unsigned mapbwidthtable[MAXMAPHEIGHT];\r
-\r
-extern unsigned originxmin,originxmax,originymin,originymax;\r
-\r
-extern unsigned masterofs;\r
-\r
-//\r
-// the floating update window is also used by the view manager for\r
-// double buffer tracking\r
-//\r
-\r
-extern byte *updateptr; // current start of update window\r
-\r
-#if GRMODE == CGAGR\r
-extern byte *baseupdateptr;\r
-#endif\r
-\r
-extern unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
-extern unsigned updatemapofs[UPDATEWIDE*UPDATEHIGH];\r
-extern unsigned uwidthtable[UPDATEHIGH]; // lookup instead of multiple\r
-\r
-#define UPDATETERMINATE 0x0301\r
-\r
-/*\r
-=============================================================================\r
-\r
- PUBLIC FUNCTIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void RF_Startup (void);\r
-void RF_Shutdown (void);\r
-\r
-void RF_FixOfs (void);\r
-void RF_NewMap (void);\r
-void RF_MarkTileGraphics (void);\r
-void RF_SetScrollBlock (int x, int y, boolean horizontal);\r
-void RF_NewPosition (unsigned x, unsigned y);\r
-void RF_Scroll (int x, int y);\r
-\r
-void RF_MapToMap (unsigned srcx, unsigned srcy,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height);\r
-void RF_MemToMap (unsigned far *source, unsigned plane,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height);\r
-\r
-void RF_ClearBlock (int x, int y, int width, int height);\r
-void RF_RedrawBlock (int x, int y, int width, int height);\r
-\r
-void RF_PlaceSprite (void **user,unsigned globalx,unsigned globaly,\r
- unsigned spritenumber, drawtype draw, int priority);\r
-void RF_RemoveSprite (void **user);\r
-\r
-void RF_CalcTics (void);\r
-\r
-void RF_Refresh (void);\r
-void RF_ForceRefresh (void);\r
-void RF_SetRefreshHook (void (*func) (void) );\r
-\r
-unsigned RF_FindFreeBuffer (void);\r
-\r
+++ /dev/null
-; Catacomb 3-D Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-; ID_RF_A.ASM\r
-\r
-IDEAL\r
-MODEL MEDIUM,C\r
-\r
-INCLUDE "ID_ASM.EQU"\r
-\r
-;============================================================================\r
-\r
-TILESWIDE = 21\r
-TILESHIGH = 14\r
-\r
-UPDATESIZE = (TILESWIDE+1)*TILESHIGH+1\r
-\r
-DATASEG\r
-\r
-EXTRN screenseg:WORD\r
-EXTRN updateptr:WORD\r
-EXTRN updatestart:WORD\r
-EXTRN masterofs:WORD ;start of master tile port\r
-EXTRN bufferofs:WORD ;start of current buffer port\r
-EXTRN screenstart:WORD ;starts of three screens (0/1/master) in EGA mem\r
-EXTRN grsegs:WORD\r
-EXTRN mapsegs:WORD\r
-EXTRN originmap:WORD\r
-EXTRN updatemapofs:WORD\r
-EXTRN tinf:WORD ;seg pointer to map header and tile info\r
-EXTRN blockstarts:WORD ;offsets from bufferofs for each update block\r
-\r
-planemask db ?\r
-planenum db ?\r
-\r
-CODESEG\r
-\r
-screenstartcs dw ? ;in code segment for accesability\r
-\r
-\r
-\r
-\r
-IFE GRMODE-CGAGR\r
-;============================================================================\r
-;\r
-; CGA refresh routines\r
-;\r
-;============================================================================\r
-\r
-TILEWIDTH = 4\r
-\r
-;=================\r
-;\r
-; RFL_NewTile\r
-;\r
-; Draws a composit two plane tile to the master screen and sets the update\r
-; spot to 1 in both update pages, forcing the tile to be copied to the\r
-; view pages the next two refreshes\r
-;\r
-; Called to draw newlly scrolled on strips and animating tiles\r
-;\r
-;=================\r
-\r
-PROC RFL_NewTile updateoffset:WORD\r
-PUBLIC RFL_NewTile\r
-USES SI,DI\r
-\r
-;\r
-; mark both update lists at this spot\r
-;\r
- mov di,[updateoffset]\r
-\r
- mov bx,[updateptr] ;start of update matrix\r
- mov [BYTE bx+di],1\r
-\r
- mov dx,SCREENWIDTH-TILEWIDTH ;add to get to start of next line\r
-\r
-;\r
-; set di to the location in screenseg to draw the tile\r
-;\r
- shl di,1\r
- mov si,[updatemapofs+di] ;offset in map from origin\r
- add si,[originmap]\r
- mov di,[blockstarts+di] ;screen location for tile\r
- add di,[masterofs]\r
-\r
-;\r
-; set BX to the foreground tile number and SI to the background number\r
-; If either BX or SI = 0xFFFF, the tile does not need to be masked together\r
-; as one of the planes totally eclipses the other\r
-;\r
- mov es,[mapsegs+2] ;foreground plane\r
- mov bx,[es:si]\r
- mov es,[mapsegs] ;background plane\r
- mov si,[es:si]\r
-\r
- mov es,[screenseg]\r
-\r
- or bx,bx\r
- jz @@singletile\r
- jmp @@maskeddraw ;draw both together\r
-\r
-;=============\r
-;\r
-; Draw single background tile from main memory\r
-;\r
-;=============\r
-\r
-@@singletile:\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;block is segment aligned\r
-\r
-REPT 15\r
- movsw\r
- movsw\r
- add di,dx\r
-ENDM\r
- movsw\r
- movsw\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
- ret\r
-\r
-\r
-;=========\r
-;\r
-; Draw a masked tile combo\r
-; Interupts are disabled and the stack segment is reassigned\r
-;\r
-;=========\r
-@@maskeddraw:\r
- cli ; don't allow ints when SS is set\r
- shl bx,1\r
- mov ss,[grsegs+STARTTILE16M*2+bx]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;first word of tile data\r
-\r
-REPT 16\r
- mov ax,[si] ;background tile\r
- and ax,[ss:si] ;mask\r
- or ax,[ss:si+64] ;masked data\r
- stosw\r
- mov ax,[si+2] ;background tile\r
- and ax,[ss:si+2] ;mask\r
- or ax,[ss:si+66] ;masked data\r
- stosw\r
- add si,4\r
- add di,dx\r
-ENDM\r
-\r
- mov ax,@DATA\r
- mov ss,ax\r
- sti\r
- mov ds,ax\r
- ret\r
-ENDP\r
-\r
-ENDIF\r
-\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-;===========================================================================\r
-;\r
-; EGA refresh routines\r
-;\r
-;===========================================================================\r
-\r
-TILEWIDTH = 2\r
-\r
-;=================\r
-;\r
-; RFL_NewTile\r
-;\r
-; Draws a composit two plane tile to the master screen and sets the update\r
-; spot to 1 in both update pages, forcing the tile to be copied to the\r
-; view pages the next two refreshes\r
-;\r
-; Called to draw newlly scrolled on strips and animating tiles\r
-;\r
-; Assumes write mode 0\r
-;\r
-;=================\r
-\r
-PROC RFL_NewTile updateoffset:WORD\r
-PUBLIC RFL_NewTile\r
-USES SI,DI\r
-\r
-;\r
-; mark both update lists at this spot\r
-;\r
- mov di,[updateoffset]\r
-\r
- mov bx,[updatestart] ;page 0 pointer\r
- mov [BYTE bx+di],1\r
- mov bx,[updatestart+2] ;page 1 pointer\r
- mov [BYTE bx+di],1\r
-\r
-;\r
-; set screenstartcs to the location in screenseg to draw the tile\r
-;\r
- shl di,1\r
- mov si,[updatemapofs+di] ;offset in map from origin\r
- add si,[originmap]\r
- mov di,[blockstarts+di] ;screen location for tile\r
- add di,[masterofs]\r
- mov [cs:screenstartcs],di\r
-\r
-;\r
-; set BX to the foreground tile number and SI to the background number\r
-; If either BX or SI = 0xFFFF, the tile does not need to be masked together\r
-; as one of the planes totally eclipses the other\r
-;\r
- mov es,[mapsegs+2] ;foreground plane\r
- mov bx,[es:si]\r
- mov es,[mapsegs] ;background plane\r
- mov si,[es:si]\r
-\r
- mov es,[screenseg]\r
- mov dx,SC_INDEX ;for stepping through map mask planes\r
-\r
- or bx,bx\r
- jz @@singletile\r
- jmp @@maskeddraw ;draw both together\r
-\r
-;=========\r
-;\r
-; No foreground tile, so draw a single background tile.\r
-;\r
-;=========\r
-@@singletile:\r
-\r
- mov bx,SCREENWIDTH-2 ;add to get to start of next line\r
- shl si,1\r
-\r
- mov ax,[cs:screenstartcs]\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
-\r
- mov cx,4 ;draw four planes\r
-@@planeloop:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[cs:screenstartcs] ;start at same place in all planes\r
-\r
-REPT 15\r
- movsw\r
- add di,bx\r
-ENDM\r
- movsw\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- loop @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
- ret\r
-\r
-\r
-;=========\r
-;\r
-; Draw a masked tile combo\r
-; Interupts are disabled and the stack segment is reassigned\r
-;\r
-;=========\r
-@@maskeddraw:\r
- cli ; don't allow ints when SS is set\r
- shl bx,1\r
- mov ss,[grsegs+STARTTILE16M*2+bx]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;first word of tile data\r
-\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
-\r
- mov di,[cs:screenstartcs]\r
-@@planeloopm:\r
- WORDOUT\r
-tileofs = 0\r
-lineoffset = 0\r
-REPT 16\r
- mov bx,[si+tileofs] ;background tile\r
- and bx,[ss:tileofs] ;mask\r
- or bx,[ss:si+tileofs+32] ;masked data\r
- mov [es:di+lineoffset],bx\r
-tileofs = tileofs + 2\r
-lineoffset = lineoffset + SCREENWIDTH\r
-ENDM\r
- add si,32\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b\r
- je @@done ;drawn all four planes\r
- jmp @@planeloopm\r
-\r
-@@done:\r
- mov ax,@DATA\r
- mov ss,ax\r
- sti\r
- mov ds,ax\r
- ret\r
-ENDP\r
-\r
-ENDIF\r
-\r
-IFE GRMODE-VGAGR\r
-;============================================================================\r
-;\r
-; VGA refresh routines\r
-;\r
-;============================================================================\r
-\r
-\r
-ENDIF\r
-\r
-\r
-;============================================================================\r
-;\r
-; reasonably common refresh routines\r
-;\r
-;============================================================================\r
-\r
-\r
-;=================\r
-;\r
-; RFL_UpdateTiles\r
-;\r
-; Scans through the update matrix pointed to by updateptr, looking for 1s.\r
-; A 1 represents a tile that needs to be copied from the master screen to the\r
-; current screen (a new row or an animated tiled). If more than one adjacent\r
-; tile in a horizontal row needs to be copied, they will be copied as a group.\r
-;\r
-; Assumes write mode 1\r
-;\r
-;=================\r
-\r
-\r
-; AX 0/1 for scasb, temp for segment register transfers\r
-; BX width for block copies\r
-; CX REP counter\r
-; DX line width deltas\r
-; SI source for copies\r
-; DI scas dest / movsb dest\r
-; BP pointer to UPDATETERMINATE\r
-;\r
-; DS\r
-; ES\r
-; SS\r
-\r
-PROC RFL_UpdateTiles\r
-PUBLIC RFL_UpdateTiles\r
-USES SI,DI,BP\r
-\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- ret\r
-\r
-@@realstart:\r
- mov di,[updateptr]\r
- mov bp,(TILESWIDE+1)*TILESHIGH+1\r
- add bp,di ; when di = bx, all tiles have been scanned\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-\r
-;\r
-; scan for a 1 in the update list, meaning a tile needs to be copied\r
-; from the master screen to the current screen\r
-;\r
-@@findtile:\r
- pop di ; place to continue scaning from\r
- mov ax,ss\r
- mov es,ax ; search in the data segment\r
- mov ds,ax\r
- mov al,1\r
- repne scasb\r
- cmp di,bp\r
- je @@done\r
-\r
- cmp [BYTE di],al\r
- jne @@singletile\r
- jmp @@tileblock\r
-\r
-;============\r
-;\r
-; copy a single tile\r
-;\r
-;============\r
-EVEN\r
-@@singletile:\r
- inc di ; we know the next tile is nothing\r
- push di ; save off the spot being scanned\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-4+di] ; start of tile location on screen\r
- mov si,di\r
- add di,[bufferofs] ; dest in current screen\r
- add si,[masterofs] ; source in master screen\r
-\r
- mov dx,SCREENWIDTH-TILEWIDTH\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-;--------------------------\r
-\r
-IFE GRMODE-CGAGR\r
-\r
-REPT 15\r
- movsw\r
- movsw\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsw\r
- movsw\r
-\r
-ENDIF\r
-\r
-;--------------------------\r
-\r
-IFE GRMODE-EGAGR\r
-\r
-REPT 15\r
- movsb\r
- movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
-ENDIF\r
-\r
-;--------------------------\r
-\r
- jmp @@findtile\r
-\r
-;============\r
-;\r
-; more than one tile in a row needs to be updated, so do it as a group\r
-;\r
-;============\r
-EVEN\r
-@@tileblock:\r
- mov dx,di ; hold starting position + 1 in dx\r
- inc di ; we know the next tile also gets updated\r
- repe scasb ; see how many more in a row\r
- push di ; save off the spot being scanned\r
-\r
- mov bx,di\r
- sub bx,dx ; number of tiles in a row\r
- shl bx,1 ; number of bytes / row\r
-\r
- mov di,dx ; lookup position of start tile\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-2+di] ; start of tile location\r
- mov si,di\r
- add di,[bufferofs] ; dest in current screen\r
- add si,[masterofs] ; source in master screen\r
-\r
- mov dx,SCREENWIDTH\r
- sub dx,bx ; offset to next line on screen\r
-IFE GRMODE-CGAGR\r
- sub dx,bx ; bx is words wide in CGA tiles\r
-ENDIF\r
-\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- mov cx,bx\r
-IFE GRMODE-CGAGR\r
- rep movsw\r
-ENDIF\r
-IFE GRMODE-EGAGR\r
- rep movsb\r
-ENDIF\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- mov cx,bx\r
-IFE GRMODE-CGAGR\r
- rep movsw\r
-ENDIF\r
-IFE GRMODE-EGAGR\r
- rep movsb\r
-ENDIF\r
-\r
- dec cx ; was 0 from last rep movsb, now $ffff for scasb\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;=================\r
-;\r
-; RFL_MaskForegroundTiles\r
-;\r
-; Scan through update looking for 3's. If the foreground tile there is a\r
-; masked foreground tile, draw it to the screen\r
-;\r
-;=================\r
-\r
-PROC RFL_MaskForegroundTiles\r
-PUBLIC RFL_MaskForegroundTiles\r
-USES SI,DI,BP\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- ret\r
-\r
-@@realstart:\r
- mov di,[updateptr]\r
- mov bp,(TILESWIDE+1)*TILESHIGH+2\r
- add bp,di ; when di = bx, all tiles have been scanned\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-;\r
-; scan for a 3 in the update list\r
-;\r
-@@findtile:\r
- mov ax,ss\r
- mov es,ax ; scan in the data segment\r
- mov al,3\r
- pop di ; place to continue scaning from\r
- repne scasb\r
- cmp di,bp\r
- je @@done\r
-\r
-;============\r
-;\r
-; found a tile, see if it needs to be masked on\r
-;\r
-;============\r
-\r
- push di\r
-\r
- sub di,[updateptr]\r
- shl di,1\r
- mov si,[updatemapofs-2+di] ; offset from originmap\r
- add si,[originmap]\r
-\r
- mov es,[mapsegs+2] ; foreground map plane segment\r
- mov si,[es:si] ; foreground tile number\r
-\r
- or si,si\r
- jz @@findtile ; 0 = no foreground tile\r
-\r
- mov bx,si\r
- add bx,INTILE ;INTILE tile info table\r
- mov es,[tinf]\r
- test [BYTE PTR es:bx],80h ;high bit = masked tile\r
- jz @@findtile\r
-\r
-;-------------------\r
-\r
-IFE GRMODE-CGAGR\r
-;=================\r
-;\r
-; mask the tile CGA\r
-;\r
-;=================\r
-\r
- mov di,[blockstarts-2+di]\r
- add di,[bufferofs]\r
- mov es,[screenseg]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16M*2+si]\r
-\r
- mov bx,64 ;data starts 64 bytes after mask\r
-\r
- xor si,si\r
-\r
-lineoffset = 0\r
-REPT 16\r
- mov ax,[es:di+lineoffset] ;background\r
- and ax,[si] ;mask\r
- or ax,[si+bx] ;masked data\r
- mov [es:di+lineoffset],ax ;background\r
- inc si\r
- inc si\r
- mov ax,[es:di+lineoffset+2] ;background\r
- and ax,[si] ;mask\r
- or ax,[si+bx] ;masked data\r
- mov [es:di+lineoffset+2],ax ;background\r
- inc si\r
- inc si\r
-lineoffset = lineoffset + SCREENWIDTH\r
-ENDM\r
-ENDIF\r
-\r
-;-------------------\r
-\r
-IFE GRMODE-EGAGR\r
-;=================\r
-;\r
-; mask the tile\r
-;\r
-;=================\r
-\r
- mov [BYTE planemask],1\r
- mov [BYTE planenum],0\r
-\r
- mov di,[blockstarts-2+di]\r
- add di,[bufferofs]\r
- mov [cs:screenstartcs],di\r
- mov es,[screenseg]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16M*2+si]\r
-\r
- mov bx,32 ;data starts 32 bytes after mask\r
-\r
-@@planeloopm:\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[ss:planemask]\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov al,GC_READMAP\r
- mov ah,[ss:planenum]\r
- WORDOUT\r
-\r
- xor si,si\r
- mov di,[cs:screenstartcs]\r
-lineoffset = 0\r
-REPT 16\r
- mov cx,[es:di+lineoffset] ;background\r
- and cx,[si] ;mask\r
- or cx,[si+bx] ;masked data\r
- inc si\r
- inc si\r
- mov [es:di+lineoffset],cx\r
-lineoffset = lineoffset + SCREENWIDTH\r
-ENDM\r
- add bx,32 ;the mask is now further away\r
- inc [ss:planenum]\r
- shl [ss:planemask],1 ;shift plane mask over for next plane\r
- cmp [ss:planemask],10000b ;done all four planes?\r
- je @@drawn ;drawn all four planes\r
- jmp @@planeloopm\r
-\r
-@@drawn:\r
-ENDIF\r
-\r
-;-------------------\r
-\r
- mov ax,ss\r
- mov ds,ax\r
- mov cx,-1 ;definately scan the entire thing\r
-\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-END\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_SD.c - Sound Manager\r
-// v1.1d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-//\r
-// This module handles dealing with generating sound on the appropriate\r
-// hardware\r
-//\r
-// Depends on: User Mgr (for parm checking)\r
-//\r
-// Globals:\r
-// For User Mgr:\r
-// SoundSourcePresent - Sound Source thingie present?\r
-// SoundBlasterPresent - SoundBlaster card present?\r
-// AdLibPresent - AdLib card present?\r
-// SoundMode - What device is used for sound effects\r
-// (Use SM_SetSoundMode() to set)\r
-// MusicMode - What device is used for music\r
-// (Use SM_SetMusicMode() to set)\r
-// For Cache Mgr:\r
-// NeedsDigitized - load digitized sounds?\r
-// NeedsMusic - load music?\r
-//\r
-\r
-#pragma hdrstop // Wierdo thing with MUSE\r
-\r
-#include <dos.h>\r
-\r
-#ifdef _MUSE_ // Will be defined in ID_Types.h\r
-#include "ID_SD.h"\r
-#else\r
-#include "ID_HEADS.H"\r
-#endif\r
-#pragma hdrstop\r
-#pragma warn -pia\r
-\r
-#define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;}\r
-\r
-// Macros for AdLib stuff\r
-#define selreg(n) outportb(0x388,n)\r
-#define writereg(n) outportb(0x389,n)\r
-#define readstat() inportb(0x388)\r
-\r
-// Global variables\r
- boolean SoundSourcePresent,SoundBlasterPresent,AdLibPresent,QuietFX,\r
- NeedsDigitized,NeedsMusic;\r
- SDMode SoundMode;\r
- SMMode MusicMode;\r
- longword TimeCount;\r
- word HackCount;\r
- word *SoundTable; // Really * _seg *SoundTable, but that don't work\r
- boolean ssIsTandy;\r
- word ssPort = 2;\r
-\r
-// Internal variables\r
-static boolean SD_Started;\r
-static boolean TimerDone;\r
-static word TimerVal,TimerDelay10,TimerDelay25,TimerDelay100;\r
-static longword TimerDivisor,TimerCount;\r
-static char *ParmStrings[] =\r
- {\r
- "noal",\r
- "adlib",\r
- nil\r
- };\r
-static void (*SoundUserHook)(void);\r
-static word SoundNumber,SoundPriority;\r
-static void interrupt (*t0OldService)(void);\r
-//static word t0CountTable[] = {8,8,8,8,40,40};\r
-static long LocalTime;\r
-\r
-// PC Sound variables\r
-static byte pcLastSample,far *pcSound;\r
-static longword pcLengthLeft;\r
-static word pcSoundLookup[255];\r
-\r
-// AdLib variables\r
-static boolean alNoCheck;\r
-static byte far *alSound;\r
-static word alBlock;\r
-static longword alLengthLeft;\r
-static longword alTimeCount;\r
-static Instrument alZeroInst;\r
-\r
-// This table maps channel numbers to carrier and modulator op cells\r
-static byte carriers[9] = { 3, 4, 5,11,12,13,19,20,21},\r
- modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},\r
-// This table maps percussive voice numbers to op cells\r
- pcarriers[5] = {19,0xff,0xff,0xff,0xff},\r
- pmodifiers[5] = {16,17,18,20,21};\r
-\r
-// Sequencer variables\r
-static boolean sqActive;\r
-static word alFXReg;\r
-static ActiveTrack *tracks[sqMaxTracks],\r
- mytracks[sqMaxTracks];\r
-static word sqMode,sqFadeStep;\r
-static word far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;\r
-static long sqHackTime;\r
-\r
-// Internal routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SetTimer0() - Sets system timer 0 to the specified speed\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#pragma argsused\r
-static void\r
-SDL_SetTimer0(word speed)\r
-{\r
-#ifndef TPROF // If using Borland's profiling, don't screw with the timer\r
- outportb(0x43,0x36); // Change timer 0\r
- outportb(0x40,speed);\r
- outportb(0x40,speed >> 8);\r
- TimerDivisor = speed;\r
-#else\r
- TimerDivisor = 0x10000;\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of\r
-// interrupts generated by system timer 0 per second\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_SetIntsPerSec(word ints)\r
-{\r
- SDL_SetTimer0(1192030 / ints);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_TimingService() - Used by SDL_InitDelay() to determine a timing\r
-// value for the current system that we're running on\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void interrupt\r
-SDL_TimingService(void)\r
-{\r
- TimerVal = _CX;\r
- TimerDone++;\r
-\r
- outportb(0x20,0x20); // Ack interrupt\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_InitDelay() - Sets up TimerDelay's for SDL_Delay()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_InitDelay(void)\r
-{\r
- int i;\r
- word timer;\r
-\r
- setvect(8,SDL_TimingService); // Set to my timer 0 ISR\r
-\r
- SDL_SetIntsPerSec(1000); // Time 1ms\r
-\r
- for (i = 0,timer = 0;i < 10;i++) // Do timing test 10 times\r
- {\r
- asm xor dx,dx // Zero DX\r
- asm mov cx,0xffff // Put starting value in CX\r
- asm mov [TimerDone],cx // TimerDone = false - 1\r
-startloop:\r
- asm or [TimerDone],0\r
- asm jnz startloop // Make sure we're at the start\r
-loop:\r
- asm test [TimerDone],1 // See if TimerDone flag got hit\r
- asm jnz done // Yep - drop out of the loop\r
- asm loop loop\r
-done:\r
-\r
- if (0xffff - TimerVal > timer)\r
- timer = 0xffff - TimerVal;\r
- }\r
- timer += timer / 2; // Use some slop\r
- TimerDelay10 = timer / (1000 / 10);\r
- TimerDelay25 = timer / (1000 / 25);\r
- TimerDelay100 = timer / (1000 / 100);\r
-\r
- SDL_SetTimer0(0); // Reset timer 0\r
-\r
- setvect(8,t0OldService); // Set back to old ISR\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_Delay() - Delays the specified amount of time\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_Delay(word delay)\r
-{\r
- if (!delay)\r
- return;\r
-\r
-asm mov cx,[delay]\r
-loop:\r
-asm test [TimerDone],0 // Useless code - just for timing equivilency\r
-asm jnz done\r
-asm loop loop\r
-done:;\r
-}\r
-#endif\r
-\r
-//\r
-// PC Sound code\r
-//\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCPlaySound() - Plays the specified sound on the PC speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_PCPlaySound(PCSound far *sound)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- pcLastSample = -1;\r
- pcLengthLeft = sound->common.length;\r
- pcSound = sound->data;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCStopSound() - Stops the current sound playing on the PC Speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_PCStopSound(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- (long)pcSound = 0;\r
-\r
-asm in al,0x61 // Turn the speaker off\r
-asm and al,0xfd // ~2\r
-asm out 0x61,al\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCService() - Handles playing the next sample in a PC sound\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_PCService(void)\r
-{\r
- byte s;\r
- word t;\r
-\r
- if (pcSound)\r
- {\r
- s = *pcSound++;\r
- if (s != pcLastSample)\r
- {\r
- asm pushf\r
- asm cli\r
-\r
- pcLastSample = s;\r
- if (s) // We have a frequency!\r
- {\r
- t = pcSoundLookup[s];\r
- asm mov bx,[t]\r
-\r
- asm mov al,0xb6 // Write to channel 2 (speaker) timer\r
- asm out 43h,al\r
- asm mov al,bl\r
- asm out 42h,al // Low byte\r
- asm mov al,bh\r
- asm out 42h,al // High byte\r
-\r
- asm in al,0x61 // Turn the speaker & gate on\r
- asm or al,3\r
- asm out 0x61,al\r
- }\r
- else // Time for some silence\r
- {\r
- asm in al,0x61 // Turn the speaker & gate off\r
- asm and al,0xfc // ~3\r
- asm out 0x61,al\r
- }\r
-\r
- asm popf\r
- }\r
-\r
- if (!(--pcLengthLeft))\r
- {\r
- SDL_PCStopSound();\r
- SDL_SoundFinished();\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutPC() - Turns off the pc speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutPC(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- pcSound = 0;\r
-\r
-asm in al,0x61 // Turn the speaker & gate off\r
-asm and al,0xfc // ~3\r
-asm out 0x61,al\r
-\r
-asm popf\r
-}\r
-\r
-// AdLib Code\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// alOut(n,b) - Puts b in AdLib card register n\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-alOut(byte n,byte b)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
-asm mov dx,0x388\r
-asm mov al,[n]\r
-asm out dx,al\r
-#if 0\r
- SDL_Delay(TimerDelay10);\r
-#else\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-#endif\r
-\r
-asm mov dx,0x389\r
-asm mov al,[b]\r
-asm out dx,al\r
-\r
-asm popf\r
-\r
-#if 0\r
- SDL_Delay(TimerDelay25);\r
-#else\r
-asm mov dx,0x388\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-#endif\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SetInstrument() - Puts an instrument into a generator\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)\r
-{\r
- byte c,m;\r
-\r
- if (percussive)\r
- {\r
- c = pcarriers[which];\r
- m = pmodifiers[which];\r
- }\r
- else\r
- {\r
- c = carriers[which];\r
- m = modifiers[which];\r
- }\r
-\r
- tracks[track - 1]->inst = *inst;\r
- tracks[track - 1]->percussive = percussive;\r
-\r
- alOut(m + alChar,inst->mChar);\r
- alOut(m + alScale,inst->mScale);\r
- alOut(m + alAttack,inst->mAttack);\r
- alOut(m + alSus,inst->mSus);\r
- alOut(m + alWave,inst->mWave);\r
-\r
- // Most percussive instruments only use one cell\r
- if (c != 0xff)\r
- {\r
- alOut(c + alChar,inst->cChar);\r
- alOut(c + alScale,inst->cScale);\r
- alOut(c + alAttack,inst->cAttack);\r
- alOut(c + alSus,inst->cSus);\r
- alOut(c + alWave,inst->cWave);\r
- }\r
-\r
- alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right\r
-}\r
-#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ALStopSound() - Turns off any sound effects playing through the\r
-// AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_ALStopSound(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- (long)alSound = 0;\r
- alOut(alFreqH + 0,0);\r
-\r
-asm popf\r
-}\r
-\r
-static void\r
-SDL_AlSetFXInst(Instrument far *inst)\r
-{\r
- byte c,m;\r
- byte scale; // added for "quiet AdLib" mode\r
-\r
- m = modifiers[0];\r
- c = carriers[0];\r
- alOut(m + alChar,inst->mChar);\r
- alOut(m + alScale,inst->mScale);\r
- alOut(m + alAttack,inst->mAttack);\r
- alOut(m + alSus,inst->mSus);\r
- alOut(m + alWave,inst->mWave);\r
- alOut(c + alChar,inst->cChar);\r
-#if 1\r
- // quiet AdLib code:\r
- scale = inst->cScale;\r
- if (QuietFX)\r
- {\r
- scale = 0x3F-scale;\r
- scale = (scale>>1) + (scale>>2); // basically 'scale *= 0.75;'\r
- scale = 0x3F-scale;\r
- }\r
- alOut(c + alScale,scale);\r
-#else\r
- // old code:\r
- alOut(c + alScale,inst->cScale);\r
-#endif\r
- alOut(c + alAttack,inst->cAttack);\r
- alOut(c + alSus,inst->cSus);\r
- alOut(c + alWave,inst->cWave);\r
- // DEBUG!!! - I just put this in\r
-// alOut(alFeedCon,inst->nConn);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ALPlaySound() - Plays the specified sound on the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_ALPlaySound(AdLibSound far *sound)\r
-{\r
- Instrument far *inst;\r
-\r
- SDL_ALStopSound();\r
-\r
-asm pushf\r
-asm cli\r
-\r
- alLengthLeft = sound->common.length;\r
- alSound = sound->data;\r
- alBlock = ((sound->block & 7) << 2) | 0x20;\r
- inst = &sound->inst;\r
-\r
- if (!(inst->mSus | inst->cSus))\r
- {\r
- asm popf\r
- Quit("SDL_ALPlaySound() - Bad instrument");\r
- }\r
-\r
- SDL_AlSetFXInst(inst);\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ALSoundService() - Plays the next sample out through the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ALSoundService(void)\r
-{\r
- byte s;\r
-\r
- if (alSound)\r
- {\r
- s = *alSound++;\r
- if (!s)\r
- alOut(alFreqH + 0,0);\r
- else\r
- {\r
- alOut(alFreqL + 0,s);\r
- alOut(alFreqH + 0,alBlock);\r
- }\r
-\r
- if (!(--alLengthLeft))\r
- {\r
- (long)alSound = 0;\r
- alOut(alFreqH + 0,0);\r
- SDL_SoundFinished();\r
- }\r
- }\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SelectMeasure() - sets up sequencing variables for a given track\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_SelectMeasure(ActiveTrack *track)\r
-{\r
- track->seq = track->moods[track->mood];\r
- track->nextevent = 0;\r
-}\r
-#endif\r
-\r
-static void\r
-SDL_ALService(void)\r
-{\r
- byte a,v;\r
- word w;\r
-\r
- if (!sqActive)\r
- return;\r
-\r
- while (sqHackLen && (sqHackTime <= alTimeCount))\r
- {\r
- w = *sqHackPtr++;\r
- sqHackTime = alTimeCount + *sqHackPtr++;\r
- asm mov dx,[w]\r
- asm mov [a],dl\r
- asm mov [v],dh\r
- alOut(a,v);\r
- sqHackLen -= 4;\r
- }\r
- alTimeCount++;\r
- if (!sqHackLen)\r
- {\r
- sqHackPtr = (word far *)sqHack;\r
- sqHackLen = sqHackSeqLen;\r
- alTimeCount = sqHackTime = 0;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutAL() - Shuts down the AdLib card for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutAL(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- alOut(alEffects,0);\r
- alOut(alFreqH + 0,0);\r
- SDL_AlSetFXInst(&alZeroInst);\r
- alSound = 0;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CleanAL() - Totally shuts down the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_CleanAL(void)\r
-{\r
- int i;\r
-\r
-asm pushf\r
-asm cli\r
-\r
- alOut(alEffects,0);\r
- for (i = 1;i < 0xf5;i++)\r
- alOut(i,0);\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_StartAL() - Starts up the AdLib card for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_StartAL(void)\r
-{\r
- alFXReg = 0;\r
- alOut(alEffects,alFXReg);\r
- SDL_AlSetFXInst(&alZeroInst);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster\r
-// emulating an AdLib) present\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-SDL_DetectAdLib(boolean force)\r
-{\r
- byte status1,status2;\r
- int i;\r
-\r
- alOut(4,0x60); // Reset T1 & T2\r
- alOut(4,0x80); // Reset IRQ\r
- status1 = readstat();\r
- alOut(2,0xff); // Set timer 1\r
- alOut(4,0x21); // Start timer 1\r
-#if 0\r
- SDL_Delay(TimerDelay100);\r
-#else\r
- asm mov dx, 0x388;\r
- asm mov cx, 100;\r
-waitloop:\r
- asm in al, dx;\r
- asm jmp here;\r
-here:\r
- asm loop waitloop;\r
-#endif\r
-\r
- status2 = readstat();\r
- alOut(4,0x60);\r
- alOut(4,0x80);\r
-\r
- if (force || (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0)))\r
- {\r
- for (i = 1;i <= 0xf5;i++) // Zero all the registers\r
- alOut(i,0);\r
-\r
- alOut(1,0x20); // Set WSE=1\r
- alOut(8,0); // Set CSM=0 & SEL=0\r
-\r
- return(true);\r
- }\r
- else\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_t0Service() - My timer 0 ISR which handles the different timings and\r
-// dispatches to whatever other routines are appropriate\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void interrupt\r
-SDL_t0Service(void)\r
-{\r
-static word count = 1;\r
-\r
-#if 0 // for debugging\r
-asm mov dx,STATUS_REGISTER_1\r
-asm in al,dx\r
-asm mov dx,ATR_INDEX\r
-asm mov al,ATR_OVERSCAN\r
-asm out dx,al\r
-asm mov al,4 // red\r
-asm out dx,al\r
-#endif\r
-\r
- HackCount++;\r
-\r
- if (MusicMode == smm_AdLib)\r
- {\r
- SDL_ALService();\r
- if (!(++count & 7))\r
- {\r
- LocalTime++;\r
- TimeCount++;\r
- if (SoundUserHook)\r
- SoundUserHook();\r
- }\r
- if (!(count & 3))\r
- {\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCService();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALSoundService();\r
- break;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- if (!(++count & 1))\r
- {\r
- LocalTime++;\r
- TimeCount++;\r
- if (SoundUserHook)\r
- SoundUserHook();\r
- }\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCService();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALSoundService();\r
- break;\r
- }\r
- }\r
-\r
-asm mov ax,[WORD PTR TimerCount]\r
-asm add ax,[WORD PTR TimerDivisor]\r
-asm mov [WORD PTR TimerCount],ax\r
-asm jnc myack\r
- t0OldService(); // If we overflow a word, time to call old int handler\r
-asm jmp olddone\r
-myack:;\r
- outportb(0x20,0x20); // Ack the interrupt\r
-olddone:;\r
-\r
-#if 0 // for debugging\r
-asm mov dx,STATUS_REGISTER_1\r
-asm in al,dx\r
-asm mov dx,ATR_INDEX\r
-asm mov al,ATR_OVERSCAN\r
-asm out dx,al\r
-asm mov al,3 // blue\r
-asm out dx,al\r
-asm mov al,0x20 // normal\r
-asm out dx,al\r
-#endif\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutDevice() - turns off whatever device was being used for sound fx\r
-//\r
-////////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutDevice(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_ShutPC();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ShutAL();\r
- break;\r
- }\r
- SoundMode = sdm_Off;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CleanDevice() - totally shuts down all sound devices\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_CleanDevice(void)\r
-{\r
- if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))\r
- SDL_CleanAL();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_StartDevice() - turns on whatever device is to be used for sound fx\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_StartDevice(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_AdLib:\r
- SDL_StartAL();\r
- break;\r
- }\r
- SoundNumber = SoundPriority = 0;\r
-}\r
-\r
-static void\r
-SDL_SetTimerSpeed(void)\r
-{\r
- word rate;\r
-\r
- if (MusicMode == smm_AdLib)\r
- rate = TickBase * 8;\r
- else\r
- rate = TickBase * 2;\r
- SDL_SetIntsPerSec(rate);\r
-}\r
-\r
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetSoundMode() - Sets which sound hardware to use for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_SetSoundMode(SDMode mode)\r
-{\r
- boolean result;\r
- word tableoffset;\r
-\r
- SD_StopSound();\r
-\r
-#ifndef _MUSE_\r
- switch (mode)\r
- {\r
- case sdm_Off:\r
- NeedsDigitized = false;\r
- result = true;\r
- break;\r
- case sdm_PC:\r
- tableoffset = STARTPCSOUNDS;\r
- NeedsDigitized = false;\r
- result = true;\r
- break;\r
- case sdm_AdLib:\r
- if (AdLibPresent)\r
- {\r
- tableoffset = STARTADLIBSOUNDS;\r
- NeedsDigitized = false;\r
- result = true;\r
- }\r
- break;\r
- default:\r
- result = false;\r
- break;\r
- }\r
-#endif\r
-\r
- if (result && (mode != SoundMode))\r
- {\r
- SDL_ShutDevice();\r
- SoundMode = mode;\r
-#ifndef _MUSE_\r
- SoundTable = (word *)(&audiosegs[tableoffset]);\r
-#endif\r
- SDL_StartDevice();\r
- }\r
-\r
- SDL_SetTimerSpeed();\r
-\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetMusicMode() - sets the device to use for background music\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_SetMusicMode(SMMode mode)\r
-{\r
- boolean result;\r
-\r
- SD_FadeOutMusic();\r
- while (SD_MusicPlaying())\r
- ;\r
-\r
- switch (mode)\r
- {\r
- case smm_Off:\r
- NeedsMusic = false;\r
- result = true;\r
- break;\r
- case smm_AdLib:\r
- if (AdLibPresent)\r
- {\r
- NeedsMusic = true;\r
- result = true;\r
- }\r
- break;\r
- default:\r
- result = false;\r
- break;\r
- }\r
-\r
- if (result)\r
- MusicMode = mode;\r
-\r
- SDL_SetTimerSpeed();\r
-\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Startup() - starts up the Sound Mgr\r
-// Detects all additional sound hardware and installs my ISR\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Startup(void)\r
-{\r
- int i;\r
- boolean alForce;\r
-\r
- alForce = false;\r
-\r
- if (SD_Started)\r
- return;\r
-\r
- ssIsTandy = false;\r
- alNoCheck = false;\r
-#ifndef _MUSE_\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],ParmStrings))\r
- {\r
- case 0: // No AdLib detection\r
- alNoCheck = true;\r
- break;\r
-\r
- case 1:\r
- alForce = true;\r
- break;\r
- }\r
- }\r
-#endif\r
-\r
- SoundUserHook = 0;\r
-\r
- t0OldService = getvect(8); // Get old timer 0 ISR\r
-\r
- //SDL_InitDelay(); // SDL_InitDelay() uses t0OldService\r
-\r
- setvect(8,SDL_t0Service); // Set to my timer 0 ISR\r
- LocalTime = TimeCount = alTimeCount = 0;\r
-\r
- SD_SetSoundMode(sdm_Off);\r
- SD_SetMusicMode(smm_Off);\r
-\r
- if (!alNoCheck)\r
- AdLibPresent = SDL_DetectAdLib(alForce);\r
-\r
- for (i = 0;i < 255;i++)\r
- pcSoundLookup[i] = i * 60;\r
-\r
- SD_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Default() - Sets up the default behaviour for the Sound Mgr whether\r
-// the config file was present or not.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Default(boolean gotit,SDMode sd,SMMode sm)\r
-{\r
- boolean gotsd,gotsm;\r
-\r
- gotsd = gotsm = gotit;\r
-\r
- if (gotsd) // Make sure requested sound hardware is available\r
- {\r
- switch (sd)\r
- {\r
- case sdm_AdLib:\r
- gotsd = AdLibPresent;\r
- break;\r
- }\r
- }\r
- if (!gotsd)\r
- {\r
- if (AdLibPresent)\r
- sd = sdm_AdLib;\r
- else\r
- sd = sdm_PC;\r
- }\r
- if (sd != SoundMode)\r
- SD_SetSoundMode(sd);\r
-\r
-\r
- if (gotsm) // Make sure requested music hardware is available\r
- {\r
- switch (sm)\r
- {\r
- case sdm_AdLib: // BUG: this should use smm_AdLib!\r
- gotsm = AdLibPresent;\r
- break;\r
- }\r
- }\r
- if (!gotsm)\r
- {\r
- if (AdLibPresent)\r
- sm = smm_AdLib;\r
- else\r
- sm = smm_Off;\r
- }\r
- if (sm != MusicMode)\r
- SD_SetMusicMode(sm);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Shutdown() - shuts down the Sound Mgr\r
-// Removes sound ISR and turns off whatever sound hardware was active\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Shutdown(void)\r
-{\r
- if (!SD_Started)\r
- return;\r
-\r
- SD_MusicOff();\r
- SDL_ShutDevice();\r
- SDL_CleanDevice();\r
-\r
- asm pushf\r
- asm cli\r
-\r
- SDL_SetTimer0(0);\r
-\r
- setvect(8,t0OldService);\r
-\r
- asm popf\r
-\r
- SD_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th\r
-// of a second from its timer 0 ISR\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_SetUserHook(void (* hook)(void))\r
-{\r
- // BUG: interrupts should be disabled while setting SoundUserHook!\r
- SoundUserHook = hook;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_PlaySound() - plays the specified sound on the appropriate hardware\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_PlaySound(soundnames sound)\r
-{\r
- SoundCommon far *s;\r
-\r
- if ((SoundMode == sdm_Off) /*|| (sound == -1)*/)\r
- return;\r
-\r
- s = MK_FP(SoundTable[sound],0);\r
- if (!s)\r
- Quit("SD_PlaySound() - Uncached sound");\r
- if (!s->length)\r
- Quit("SD_PlaySound() - Zero length sound");\r
- if (s->priority < SoundPriority)\r
- return;\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCPlaySound((void far *)s);\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALPlaySound((void far *)s);\r
- break;\r
- }\r
-\r
- SoundNumber = sound;\r
- SoundPriority = s->priority;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SoundPlaying() - returns the sound number that's playing, or 0 if\r
-// no sound is playing\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-word\r
-SD_SoundPlaying(void)\r
-{\r
- boolean result = false;\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- result = pcSound? true : false;\r
- break;\r
- case sdm_AdLib:\r
- result = alSound? true : false;\r
- break;\r
- }\r
-\r
- if (result)\r
- return(SoundNumber);\r
- else\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_StopSound() - if a sound is playing, stops it\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_StopSound(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCStopSound();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALStopSound();\r
- break;\r
- }\r
-\r
- SDL_SoundFinished();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_WaitSoundDone() - waits until the current sound is done playing\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_WaitSoundDone(void)\r
-{\r
- while (SD_SoundPlaying())\r
- ;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicOn() - turns on the sequencer\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_MusicOn(void)\r
-{\r
- sqActive = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicOff() - turns off the sequencer and any playing notes\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_MusicOff(void)\r
-{\r
- word i;\r
-\r
-\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- alFXReg = 0;\r
- alOut(alEffects,0);\r
- for (i = 0;i < sqMaxTracks;i++)\r
- alOut(alFreqH + i + 1,0);\r
- break;\r
- }\r
- sqActive = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_StartMusic() - starts playing the music pointed to\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_StartMusic(MusicGroup far *music)\r
-{\r
- SD_MusicOff();\r
-asm pushf\r
-asm cli\r
-\r
- if (MusicMode == smm_AdLib)\r
- {\r
- sqHackPtr = sqHack = music->values;\r
- sqHackSeqLen = sqHackLen = music->length;\r
- sqHackTime = 0;\r
- alTimeCount = 0;\r
- SD_MusicOn();\r
- }\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()\r
-// to see if the fadeout is complete\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_FadeOutMusic(void)\r
-{\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- // DEBUG - quick hack to turn the music off\r
- SD_MusicOff();\r
- break;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicPlaying() - returns true if music is currently playing, false if\r
-// not\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_MusicPlaying(void)\r
-{\r
- boolean result;\r
-\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- result = false;\r
- // DEBUG - not written\r
- break;\r
- default:\r
- result = false;\r
- }\r
-\r
- return(result);\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_SD.h - Sound Manager Header\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-#ifndef __TYPES__\r
-#include "ID_Types.h"\r
-#endif\r
-\r
-#ifndef __ID_SD__\r
-#define __ID_SD__\r
-\r
-#ifdef __DEBUG__\r
-#define __DEBUG_SoundMgr__\r
-#endif\r
-\r
-#define TickBase 70 // 70Hz per tick - used as a base for timer 0\r
-\r
-typedef enum {\r
- sdm_Off,\r
- sdm_PC,sdm_AdLib,\r
- } SDMode;\r
-typedef enum {\r
- smm_Off,smm_AdLib\r
- } SMMode;\r
-\r
-typedef struct\r
- {\r
- longword length;\r
- word priority;\r
- } SoundCommon;\r
-\r
-// PC Sound stuff\r
-#define pcTimer 0x42\r
-#define pcTAccess 0x43\r
-#define pcSpeaker 0x61\r
-\r
-#define pcSpkBits 3\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- byte data[1];\r
- } PCSound;\r
-\r
-// Registers for the Sound Blaster card - needs to be offset by n0\r
-#define sbReset 0x206\r
-#define sbReadData 0x20a\r
-#define sbWriteCmd 0x20c\r
-#define sbWriteData 0x20c\r
-#define sbWriteStat 0x20c\r
-#define sbDataAvail 0x20e\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- word hertz;\r
- byte bits,\r
- reference,\r
- data[1];\r
- } SampledSound;\r
-\r
-// Registers for the AdLib card\r
-// Operator stuff\r
-#define alChar 0x20\r
-#define alScale 0x40\r
-#define alAttack 0x60\r
-#define alSus 0x80\r
-#define alWave 0xe0\r
-// Channel stuff\r
-#define alFreqL 0xa0\r
-#define alFreqH 0xb0\r
-#define alFeedCon 0xc0\r
-// Global stuff\r
-#define alEffects 0xbd\r
-\r
-typedef struct\r
- {\r
- byte mChar,cChar,\r
- mScale,cScale,\r
- mAttack,cAttack,\r
- mSus,cSus,\r
- mWave,cWave,\r
- nConn,\r
-\r
- // These are only for Muse - these bytes are really unused\r
- voice,\r
- mode,\r
- unused[3];\r
- } Instrument;\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- Instrument inst;\r
- byte block,\r
- data[1];\r
- } AdLibSound;\r
-\r
-//\r
-// Sequencing stuff\r
-//\r
-#define sqMaxTracks 10\r
-#define sqMaxMoods 1 // DEBUG\r
-\r
-#define sev_Null 0 // Does nothing\r
-#define sev_NoteOff 1 // Turns a note off\r
-#define sev_NoteOn 2 // Turns a note on\r
-#define sev_NotePitch 3 // Sets the pitch of a currently playing note\r
-#define sev_NewInst 4 // Installs a new instrument\r
-#define sev_NewPerc 5 // Installs a new percussive instrument\r
-#define sev_PercOn 6 // Turns a percussive note on\r
-#define sev_PercOff 7 // Turns a percussive note off\r
-#define sev_SeqEnd -1 // Terminates a sequence\r
-\r
-// Flags for MusicGroup.flags\r
-#define sf_Melodic 0\r
-#define sf_Percussive 1\r
-\r
-#if 1\r
-typedef struct\r
- {\r
- word length,\r
- values[1];\r
- } MusicGroup;\r
-#else\r
-typedef struct\r
- {\r
- word flags,\r
- count,\r
- offsets[1];\r
- } MusicGroup;\r
-#endif\r
-\r
-typedef struct\r
- {\r
- /* This part needs to be set up by the user */\r
- word mood,far *moods[sqMaxMoods];\r
-\r
- /* The rest is set up by the code */\r
- Instrument inst;\r
- boolean percussive;\r
- word far *seq;\r
- longword nextevent;\r
- } ActiveTrack;\r
-\r
-#define sqmode_Normal 0\r
-#define sqmode_FadeIn 1\r
-#define sqmode_FadeOut 2\r
-\r
-#define sqMaxFade 64 // DEBUG\r
-\r
-\r
-// Global variables\r
-extern boolean AdLibPresent,\r
- NeedsMusic, // For Caching Mgr\r
- QuietFX;\r
-extern SDMode SoundMode;\r
-extern SMMode MusicMode;\r
-extern longword TimeCount; // Global time in ticks\r
-\r
-// Function prototypes\r
-extern void SD_Startup(void),\r
- SD_Shutdown(void),\r
- SD_Default(boolean gotit,SDMode sd,SMMode sm),\r
- SD_PlaySound(soundnames sound),\r
- SD_StopSound(void),\r
- SD_WaitSoundDone(void),\r
- SD_StartMusic(MusicGroup far *music),\r
- SD_MusicOn(void),\r
- SD_MusicOff(void),\r
- SD_FadeOutMusic(void),\r
- SD_SetUserHook(void (*hook)(void));\r
-extern boolean SD_MusicPlaying(void),\r
- SD_SetSoundMode(SDMode mode),\r
- SD_SetMusicMode(SMMode mode);\r
-extern word SD_SoundPlaying(void);\r
-\r
-#ifdef _MUSE_ // MUSE Goes directly to the lower level routines\r
-extern void SDL_PCPlaySound(PCSound far *sound),\r
- SDL_PCStopSound(void),\r
- SDL_ALPlaySound(AdLibSound far *sound),\r
- SDL_ALStopSound(void);\r
-#endif\r
-\r
-#endif\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US.h - Header file for the User Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-#ifndef __TYPES__\r
-#include "ID_Types.h"\r
-#endif\r
-\r
-#ifndef __ID_US__\r
-#define __ID_US__\r
-\r
-#ifdef __DEBUG__\r
-#define __DEBUG_UserMgr__\r
-#endif\r
-\r
-//#define HELPTEXTLINKED\r
-\r
-#define MaxX 320\r
-#define MaxY 200\r
-\r
-#define MaxHelpLines 500\r
-\r
-#define MaxHighName 57\r
-#ifdef CAT3D\r
-#define MaxScores 7\r
-#else\r
-#define MaxScores 8\r
-#endif\r
-typedef struct\r
- {\r
- char name[MaxHighName + 1];\r
- long score;\r
- word completed;\r
- } HighScore;\r
-\r
-#define MaxGameName 32\r
-#define MaxSaveGames 6\r
-typedef struct\r
- {\r
- char signature[4];\r
- word *oldtest;\r
- boolean present;\r
- char name[MaxGameName + 1];\r
- } SaveGame;\r
-\r
-#define MaxString 128 // Maximum input string size\r
-\r
-typedef struct\r
- {\r
- int x,y,\r
- w,h,\r
- px,py;\r
- } WindowRec; // Record used to save & restore screen windows\r
-\r
-typedef enum\r
- {\r
- gd_Continue,\r
- gd_Easy,\r
- gd_Normal,\r
- gd_Hard\r
- } GameDiff;\r
-\r
-// Hack import for TED launch support\r
-extern boolean tedlevel;\r
-extern word tedlevelnum;\r
-extern void TEDDeath(void);\r
-\r
-extern boolean ingame, // Set by game code if a game is in progress\r
- abortgame, // Set if a game load failed\r
- loadedgame, // Set if the current game was loaded\r
-#ifdef KEEN6\r
- checkpassed,\r
-#endif\r
- NoWait,\r
- HighScoresDirty;\r
-extern char *abortprogram; // Set to error msg if program is dying\r
-extern GameDiff restartgame; // Normally gd_Continue, else starts game\r
-extern word PrintX,PrintY; // Current printing location in the window\r
-extern word WindowX,WindowY,// Current location of window\r
- WindowW,WindowH;// Current size of window\r
-\r
-extern boolean Button0,Button1,\r
- CursorBad;\r
-extern int CursorX,CursorY;\r
-\r
-extern void (*USL_MeasureString)(char far *,word *,word *),\r
- (*USL_DrawString)(char far *);\r
-\r
-extern boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
-extern void (*USL_ResetGame)(void);\r
-extern SaveGame Games[MaxSaveGames];\r
-extern HighScore Scores[];\r
-\r
-#define US_HomeWindow() {PrintX = WindowX; PrintY = WindowY;}\r
-\r
-extern void US_Startup(void),\r
- US_Setup(void),\r
- US_Shutdown(void),\r
- US_InitRndT(boolean randomize),\r
- US_SetLoadSaveHooks(boolean (*load)(int),\r
- boolean (*save)(int),\r
- void (*reset)(void)),\r
- US_TextScreen(void),\r
- US_UpdateTextScreen(void),\r
- US_FinishTextScreen(void),\r
- US_ControlPanel(void),\r
- US_DrawWindow(word x,word y,word w,word h),\r
- US_CenterWindow(word,word),\r
- US_SaveWindow(WindowRec *win),\r
- US_RestoreWindow(WindowRec *win),\r
- US_ClearWindow(void),\r
- US_SetPrintRoutines(void (*measure)(char far *,word *,word *),\r
- void (*print)(char far *)),\r
- US_PrintCentered(char *s),\r
- US_CPrint(char *s),\r
- US_CPrintLine(char *s),\r
- US_Print(char *s),\r
- US_PrintUnsigned(longword n),\r
- US_PrintSigned(long n),\r
- US_StartCursor(void),\r
- US_ShutCursor(void),\r
- US_ControlPanel(void),\r
- US_CheckHighScore(long score,word other),\r
- US_DisplayHighScores(int which);\r
-extern boolean US_UpdateCursor(void),\r
- US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
- int maxchars,int maxwidth);\r
-extern int US_CheckParm(char *parm,char **strings),\r
- US_RndT(void);\r
-\r
-extern boolean US_ParmPresent(char *arg);\r
-\r
- void USL_PrintInCenter(char *s,Rect r);\r
- char *USL_GiveSaveName(word game);\r
-#endif\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US_1.c - User Manager - General routines\r
-// v1.1d1\r
-// By Jason Blochowiak\r
-// Hacked up for Catacomb 3D\r
-//\r
-\r
-//\r
-// This module handles dealing with user input & feedback\r
-//\r
-// Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,\r
-// and Refresh Mgrs, Memory Mgr for background save/restore\r
-//\r
-// Globals:\r
-// ingame - Flag set by game indicating if a game is in progress\r
-// abortgame - Flag set if the current game should be aborted (if a load\r
-// game fails)\r
-// loadedgame - Flag set if a game was loaded\r
-// abortprogram - Normally nil, this points to a terminal error message\r
-// if the program needs to abort\r
-// restartgame - Normally set to gd_Continue, this is set to one of the\r
-// difficulty levels if a new game should be started\r
-// PrintX, PrintY - Where the User Mgr will print (global coords)\r
-// WindowX,WindowY,WindowW,WindowH - The dimensions of the current\r
-// window\r
-//\r
-\r
-#include "ID_HEADS.H"\r
-\r
-#pragma hdrstop\r
-\r
-#pragma warn -pia\r
-\r
-\r
-// Special imports\r
-extern boolean showscorebox;\r
-#ifdef KEEN\r
-extern boolean jerk;\r
-extern boolean oldshooting;\r
-extern ScanCode firescan;\r
-#else\r
- ScanCode firescan;\r
-#endif\r
-\r
-// Global variables\r
- char *abortprogram;\r
- boolean NoWait,\r
- HighScoresDirty;\r
- word PrintX,PrintY;\r
- word WindowX,WindowY,WindowW,WindowH;\r
-\r
-// Internal variables\r
-#define ConfigVersion 4\r
-\r
-static char *ParmStrings[] = {"TEDLEVEL","NOWAIT"},\r
- *ParmStrings2[] = {"COMP","NOCOMP"};\r
-static boolean US_Started;\r
-\r
- boolean Button0,Button1,\r
- CursorBad;\r
- int CursorX,CursorY;\r
-\r
- void (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,\r
- (*USL_DrawString)(char far *) = VWB_DrawPropString;\r
-\r
- boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
- void (*USL_ResetGame)(void);\r
- SaveGame Games[MaxSaveGames];\r
- HighScore Scores[MaxScores] =\r
- {\r
-#if defined CAT3D\r
- {"Sir Lancelot",500,3},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
-#elif defined GOODTIMES\r
- {"Id Software",10000,0},\r
- {"Adrian Carmack",10000,0},\r
- {"John Carmack",10000,0},\r
- {"Kevin Cloud",10000,0},\r
- {"Shawn Green",10000,0},\r
- {"Tom Hall",10000,0},\r
- {"John Romero",10000,0},\r
- {"Jay Wilbur",10000,0},\r
-#else\r
- {"Id Software - '91",10000,0},\r
- {"",10000,0},\r
- {"Jason Blochowiak",10000,0},\r
- {"Adrian Carmack",10000,0},\r
- {"John Carmack",10000,0},\r
- {"Tom Hall",10000,0},\r
- {"John Romero",10000,0},\r
- {"",10000,0},\r
-#endif\r
- };\r
-\r
-// Internal routines\r
-\r
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
-// from DOS.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#pragma warn -par\r
-#pragma warn -rch\r
-int\r
-USL_HardError(word errval,int ax,int bp,int si)\r
-{\r
-#define IGNORE 0\r
-#define RETRY 1\r
-#define ABORT 2\r
-extern void ShutdownId(void);\r
-\r
-static char buf[32];\r
-static WindowRec wr;\r
- int di;\r
- char c,*s,*t;\r
-\r
-\r
- di = _DI;\r
-\r
- if (ax < 0)\r
- s = "Device Error";\r
- else\r
- {\r
- if ((di & 0x00ff) == 0)\r
- s = "Drive ~ is Write Protected";\r
- else\r
- s = "Error on Drive ~";\r
- for (t = buf;*s;s++,t++) // Can't use sprintf()\r
- if ((*t = *s) == '~')\r
- *t = (ax & 0x00ff) + 'A';\r
- *t = '\0';\r
- s = buf;\r
- }\r
-\r
- c = peekb(0x40,0x49); // Get the current screen mode\r
- if ((c < 4) || (c == 7))\r
- goto oh_kill_me;\r
-\r
- // DEBUG - handle screen cleanup\r
-\r
- US_SaveWindow(&wr);\r
- US_CenterWindow(30,3);\r
- US_CPrint(s);\r
- US_CPrint("(R)etry or (A)bort?");\r
- VW_UpdateScreen();\r
- IN_ClearKeysDown();\r
-\r
-asm sti // Let the keyboard interrupts come through\r
-\r
- while (true)\r
- {\r
- switch (IN_WaitForASCII())\r
- {\r
- case key_Escape:\r
- case 'a':\r
- case 'A':\r
- goto oh_kill_me;\r
- break;\r
- case key_Return:\r
- case key_Space:\r
- case 'r':\r
- case 'R':\r
- US_ClearWindow();\r
- VW_UpdateScreen();\r
- US_RestoreWindow(&wr);\r
- return(RETRY);\r
- break;\r
- }\r
- }\r
-\r
-oh_kill_me:\r
- abortprogram = s;\r
- ShutdownId();\r
- fprintf(stderr,"Terminal Error: %s\n",s);\r
- if (tedlevel)\r
- fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
-\r
- return(ABORT);\r
-#undef IGNORE\r
-#undef RETRY\r
-#undef ABORT\r
-}\r
-#pragma warn +par\r
-#pragma warn +rch\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_GiveSaveName() - Returns a pointer to a static buffer that contains\r
-// the filename to use for the specified save game\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-char *\r
-USL_GiveSaveName(word game)\r
-{\r
-static char name[] = "SAVEGAMx."EXTENSION;\r
-\r
- name[7] = '0' + game;\r
- return(name);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after\r
-// reading or writing the save game headers\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))\r
-{\r
- USL_LoadGame = load;\r
- USL_SaveGame = save;\r
- USL_ResetGame = reset;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ReadConfig() - Reads the configuration file, if present, and sets\r
-// things up accordingly. If it's not present, uses defaults. This file\r
-// includes the high scores.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ReadConfig(void)\r
-{\r
- boolean gotit, hadAdLib;\r
- char sig[sizeof(EXTENSION)];\r
- word version;\r
- int file;\r
- SDMode sd;\r
- SMMode sm;\r
- ControlType ctl;\r
-\r
- if ((file = open("CONFIG."EXTENSION,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- read(file,sig,sizeof(EXTENSION));\r
- read(file,&version,sizeof(version));\r
- if (strcmp(sig,EXTENSION) || (version != ConfigVersion))\r
- {\r
- close(file);\r
- goto rcfailed;\r
- }\r
- read(file,Scores,sizeof(HighScore) * MaxScores);\r
- read(file,&sd,sizeof(sd));\r
- read(file,&sm,sizeof(sm));\r
- read(file,&ctl,sizeof(ctl));\r
- read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
- read(file,&showscorebox,sizeof(showscorebox));\r
- read(file,&compatability,sizeof(compatability));\r
- read(file,&QuietFX,sizeof(QuietFX));\r
- read(file,&hadAdLib,sizeof(hadAdLib));\r
- read(file,&jerk,sizeof(jerk));\r
-#ifdef KEEN\r
- read(file,&oldshooting,sizeof(oldshooting));\r
- read(file,&firescan,sizeof(firescan));\r
-#endif\r
- read(file,&GravisGamepad,sizeof(GravisGamepad));\r
- read(file,&GravisMap,sizeof(GravisMap));\r
- close(file);\r
-\r
- HighScoresDirty = false;\r
- gotit = true;\r
- }\r
- else\r
- {\r
-rcfailed:\r
- sd = sdm_Off;\r
- sm = smm_Off;\r
- ctl = ctrl_Keyboard;\r
- showscorebox = true;\r
-#ifdef KEEN\r
- oldshooting = false;\r
-#endif\r
-\r
- gotit = false;\r
- HighScoresDirty = true;\r
- }\r
-\r
- SD_Default(gotit? (hadAdLib==AdLibPresent) : false, sd,sm);\r
- IN_Default(gotit,ctl);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_WriteConfig() - Writes out the current configuration, including the\r
-// high scores.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_WriteConfig(void)\r
-{\r
- word version;\r
- int file;\r
-\r
- version = ConfigVersion;\r
- file = open("CONFIG."EXTENSION,O_CREAT | O_BINARY | O_WRONLY,\r
- S_IREAD | S_IWRITE | S_IFREG);\r
- if (file != -1)\r
- {\r
- write(file,EXTENSION,sizeof(EXTENSION));\r
- write(file,&version,sizeof(version));\r
- write(file,Scores,sizeof(HighScore) * MaxScores);\r
- write(file,&SoundMode,sizeof(SoundMode));\r
- write(file,&MusicMode,sizeof(MusicMode));\r
-#ifdef CAT3D\r
- if // Hack\r
- (\r
- (Controls[0] == ctrl_Joystick1)\r
- || (Controls[0] == ctrl_Joystick2)\r
- )\r
- Controls[0] = ctrl_Keyboard;\r
-#endif\r
- write(file,&(Controls[0]),sizeof(Controls[0]));\r
- write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
- write(file,&showscorebox,sizeof(showscorebox));\r
- write(file,&compatability,sizeof(compatability));\r
- write(file,&QuietFX,sizeof(QuietFX));\r
- write(file,&AdLibPresent,sizeof(AdLibPresent));\r
- write(file,&jerk,sizeof(jerk));\r
-#ifdef KEEN\r
- write(file,&oldshooting,sizeof(oldshooting));\r
- write(file,&firescan,sizeof(firescan));\r
-#endif\r
- write(file,&GravisGamepad,sizeof(GravisGamepad));\r
- write(file,&GravisMap,sizeof(GravisMap));\r
- close(file);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CheckSavedGames() - Checks to see which saved games are present\r
-// & valid\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef KEEN\r
-void\r
-#else\r
-static void\r
-#endif\r
-USL_CheckSavedGames(void)\r
-{\r
- boolean ok;\r
- char *filename;\r
- word i;\r
- int file;\r
- SaveGame *game;\r
-\r
-#ifdef CAT3D\r
- USL_SaveGame = 0;\r
- USL_LoadGame = 0;\r
-#endif\r
-\r
- for (i = 0,game = Games;i < MaxSaveGames;i++,game++)\r
- {\r
- filename = USL_GiveSaveName(i);\r
- ok = false;\r
- if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- if\r
- (\r
- (read(file,game,sizeof(*game)) == sizeof(*game))\r
- && (!strcmp(game->signature,EXTENSION))\r
- && (game->oldtest == &PrintX)\r
- )\r
- ok = true;\r
-\r
- close(file);\r
- }\r
-\r
- if (ok)\r
- game->present = true;\r
- else\r
- {\r
- strcpy(game->signature,EXTENSION);\r
- game->present = false;\r
- strcpy(game->name,"Empty");\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Startup() - Starts the User Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Startup(void)\r
-{\r
- int i;\r
-\r
- if (US_Started)\r
- return;\r
-\r
- harderr(USL_HardError); // Install the fatal error handler\r
-\r
- US_InitRndT(true); // Initialize the random number generator\r
-\r
- USL_ReadConfig(); // Read config file\r
-\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],ParmStrings2))\r
- {\r
- case 0:\r
- if (grmode == EGAGR)\r
- compatability = true;\r
- break;\r
- case 1:\r
- compatability = false;\r
- break;\r
- }\r
- }\r
-\r
- US_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Setup() - Does the disk access part of the User Mgr's startup\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Setup(void)\r
-{\r
-#ifndef CAT3D\r
- USL_SaveGame = 0;\r
- USL_LoadGame = 0;\r
-#endif\r
- USL_CheckSavedGames(); // Check which saved games are present\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Shutdown() - Shuts down the User Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Shutdown(void)\r
-{\r
- if (!US_Started)\r
- return;\r
-\r
- if (!abortprogram)\r
- USL_WriteConfig();\r
-\r
- US_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CheckParm() - checks to see if a string matches one of a set of\r
-// strings. The check is case insensitive. The routine returns the\r
-// index of the string that matched, or -1 if no matches were found\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-int\r
-US_CheckParm(char *parm,char **strings)\r
-{\r
- char cp,cs,\r
- *p,*s;\r
- int i;\r
-\r
- while (!isalpha(*parm)) // Skip non-alphas\r
- parm++;\r
-\r
- for (i = 0;*strings && **strings;i++)\r
- {\r
- for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
- {\r
- cs = *s++;\r
- if (!cs)\r
- return(i);\r
- cp = *p++;\r
-\r
- if (isupper(cs))\r
- cs = tolower(cs);\r
- if (isupper(cp))\r
- cp = tolower(cp);\r
- }\r
- }\r
- return(-1);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ParmPresent() - checks if a given string was passed as a command\r
-// line parameter at startup\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-US_ParmPresent(char *arg)\r
-{\r
- int i;\r
- char *strings[2];\r
-\r
- strings[0] = arg;\r
- strings[1] = NULL;\r
-\r
- for (i=1; i<_argc; i++)\r
- {\r
- if (US_CheckParm(_argv[i], strings) != -1)\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ScreenDraw() - Draws a chunk of the text screen (called only by\r
-// US_TextScreen())\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ScreenDraw(word x,word y,char *s,byte attr)\r
-{\r
- byte far *screen,far *oscreen;\r
-\r
- screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));\r
- oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) + 1;\r
- while (*s)\r
- {\r
- *screen++ = *s++;\r
- if (attr != 0xff)\r
- {\r
- *screen++ = (attr & 0x8f) | (*oscreen & 0x70);\r
- oscreen += 2;\r
- }\r
- else\r
- screen++;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,\r
-// and moves the cursor to the leftmost column of the bottom line\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ClearTextScreen(void)\r
-{\r
- // Set to 80x25 color text mode\r
- _AL = 3; // Mode 3\r
- _AH = 0x00;\r
- geninterrupt(0x10);\r
-\r
- // Use BIOS to move the cursor to the bottom of the screen\r
- _AH = 0x0f;\r
- geninterrupt(0x10); // Get current video mode into _BH\r
- _DL = 0; // Lefthand side of the screen\r
- _DH = 24; // Bottom row\r
- _AH = 0x02;\r
- geninterrupt(0x10);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_TextScreen() - Puts up the startup text screen\r
-// Note: These are the only User Manager functions that can be safely called\r
-// before the User Mgr has been started up\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_TextScreen(void)\r
-{\r
- word i,n;\r
-\r
- USL_ClearTextScreen();\r
-\r
- _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);\r
-\r
- // Check for TED launching here\r
- for (i = 1;i < _argc;i++)\r
- {\r
- n = US_CheckParm(_argv[i],ParmStrings);\r
- if (n == 0)\r
- {\r
- tedlevelnum = atoi(_argv[i + 1]);\r
- if (tedlevelnum >= 0)\r
- {\r
- tedlevel = true;\r
- return;\r
- }\r
- else\r
- break;\r
- }\r
- else if (n == 1)\r
- {\r
- NoWait = true;\r
- return;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_Show() - Changes the appearance of one of the fields on the text\r
-// screen. Possibly adds a checkmark in front of it and highlights it\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_Show(word x,word y,word w,boolean show,boolean hilight)\r
-{\r
- byte far *screen,far *oscreen;\r
-\r
- screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));\r
- oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) - 1;\r
- *screen++ = show? 251 : ' '; // Checkmark char or space\r
-// *screen = 0x48;\r
-// *screen = (*oscreen & 0xf0) | 8;\r
- oscreen += 2;\r
- if (show && hilight)\r
- {\r
- for (w++;w--;screen += 2,oscreen += 2)\r
- *screen = (*oscreen & 0xf0) | 0x0f;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ShowMem() - Right justifies a longword in one of the memory fields on\r
-// the text screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ShowMem(word x,word y,long mem)\r
-{\r
- char buf[16];\r
- word i;\r
-\r
- for (i = strlen(ltoa(mem,buf,10));i < 5;i++)\r
- USL_ScreenDraw(x++,y," ",0xff);\r
- USL_ScreenDraw(x,y,buf,0xff);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_UpdateTextScreen() - Called after the ID libraries are started up.\r
-// Displays what hardware is present.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_UpdateTextScreen(void)\r
-{\r
- boolean b;\r
- longword totalmem;\r
-\r
- // Show video card info\r
- b = (grmode == CGAGR);\r
- USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);\r
- b = (grmode == EGAGR || grmode == VGAGR);\r
- USL_Show(21,8,7,(videocard >= EGAcard) && (videocard <= VGAcard),b);\r
-// b = (grmode == VGAGR);\r
-// USL_Show(21,9,4,videocard == VGAcard,b);\r
-#if GRMODE != CGAGR\r
- if (compatability)\r
- USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);\r
-#endif\r
-\r
- // Show input device info\r
- USL_Show(60,7,8,true,true);\r
- USL_Show(60,8,11,JoysPresent[0],true);\r
- USL_Show(60,9,11,JoysPresent[1],true);\r
- USL_Show(60,10,5,MousePresent,true);\r
-\r
- // Show sound hardware info\r
- USL_Show(21,14,11,true,SoundMode == sdm_PC);\r
- b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);\r
- USL_Show(21,15,14,AdLibPresent,b);\r
- if (b && AdLibPresent) // Hack because of two lines\r
- {\r
- byte far *screen,far *oscreen;\r
- word x,y,w;\r
-\r
- x = 21;\r
- y = 16;\r
- w = 14;\r
- screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2) - 1);\r
- oscreen = (&introscn + 7) + (x * 2) + (y * 80 * 2) - 1;\r
- oscreen += 2;\r
- for (w++;w--;screen += 2,oscreen += 2)\r
- *screen = (*oscreen & 0xf0) | 0x0f;\r
- }\r
-\r
- // Show memory available/used\r
- USL_ShowMem(63,15,mminfo.mainmem / 1024);\r
- USL_Show(53,15,23,true,true);\r
- USL_ShowMem(63,16,mminfo.EMSmem / 1024);\r
- USL_Show(53,16,23,mminfo.EMSmem? true : false,true);\r
- USL_ShowMem(63,17,mminfo.XMSmem / 1024);\r
- USL_Show(53,17,23,mminfo.XMSmem? true : false,true);\r
- totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;\r
- USL_ShowMem(63,18,totalmem / 1024);\r
- USL_Show(53,18,23,true,true); // DEBUG\r
- USL_ScreenDraw(52,18," ",0xff);\r
-\r
- // Change Initializing... to Loading...\r
- USL_ScreenDraw(27,22," Loading... ",0x9c);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_FinishTextScreen() - After the main program has finished its initial\r
-// loading, this routine waits for a keypress and then clears the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_FinishTextScreen(void)\r
-{\r
-static byte colors[] = {4,6,13,15,15,15,15,15,15};\r
- boolean up;\r
- int i,c;\r
-\r
- // Change Loading... to Press a Key\r
-\r
- if (!(tedlevel || NoWait))\r
- {\r
- IN_ClearKeysDown();\r
- for (i = 0,up = true;!IN_UserInput(4,true);)\r
- {\r
- c = colors[i];\r
- if (up)\r
- {\r
- if (++i == 9)\r
- i = 8,up = false;\r
- }\r
- else\r
- {\r
- if (--i < 0)\r
- i = 1,up = true;\r
- }\r
-\r
- USL_ScreenDraw(29,22," Ready - Press a Key ",0x00 + c);\r
- }\r
- }\r
- else\r
- USL_ScreenDraw(29,22," Ready - Press a Key ",0x9a);\r
-\r
- IN_ClearKeysDown();\r
-\r
- USL_ClearTextScreen();\r
-}\r
-\r
-// Window/Printing routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SetPrintRoutines() - Sets the routines used to measure and print\r
-// from within the User Mgr. Primarily provided to allow switching\r
-// between masked and non-masked fonts\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))\r
-{\r
- USL_MeasureString = measure;\r
- USL_DrawString = print;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Print() - Prints a string in the current window. Newlines are\r
-// supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Print(char *s)\r
-{\r
- char c,*se;\r
- word w,h;\r
-\r
- while (*s)\r
- {\r
- se = s;\r
- while ((c = *se) && (c != '\n'))\r
- se++;\r
- *se = '\0';\r
-\r
- USL_MeasureString(s,&w,&h);\r
- px = PrintX;\r
- py = PrintY;\r
- USL_DrawString(s);\r
-\r
- s = se;\r
- if (c)\r
- {\r
- *se = c;\r
- s++;\r
-\r
- PrintX = WindowX;\r
- PrintY += h;\r
- }\r
- else\r
- PrintX += w;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintUnsigned() - Prints an unsigned long\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintUnsigned(longword n)\r
-{\r
- char buffer[32];\r
-\r
- US_Print(ultoa(n,buffer,10));\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintSigned() - Prints a signed long\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintSigned(long n)\r
-{\r
- char buffer[32];\r
-\r
- US_Print(ltoa(n,buffer,10));\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_PrintInCenter() - Prints a string in the center of the given rect\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-USL_PrintInCenter(char *s,Rect r)\r
-{\r
- word w,h,\r
- rw,rh;\r
-\r
- USL_MeasureString(s,&w,&h);\r
- rw = r.lr.x - r.ul.x;\r
- rh = r.lr.y - r.ul.y;\r
-\r
- px = r.ul.x + ((rw - w) / 2);\r
- py = r.ul.y + ((rh - h) / 2);\r
- USL_DrawString(s);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintCentered() - Prints a string centered in the current window.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintCentered(char *s)\r
-{\r
- Rect r;\r
-\r
- r.ul.x = WindowX;\r
- r.ul.y = WindowY;\r
- r.lr.x = r.ul.x + WindowW;\r
- r.lr.y = r.ul.y + WindowH;\r
-\r
- USL_PrintInCenter(s,r);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CPrintLine() - Prints a string centered on the current line and\r
-// advances to the next line. Newlines are not supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CPrintLine(char *s)\r
-{\r
- word w,h;\r
-\r
- USL_MeasureString(s,&w,&h);\r
-\r
- if (w > WindowW)\r
- Quit("US_CPrintLine() - String exceeds width");\r
- px = WindowX + ((WindowW - w) / 2);\r
- py = PrintY;\r
- USL_DrawString(s);\r
- PrintY += h;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CPrint() - Prints a string in the current window. Newlines are\r
-// supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CPrint(char *s)\r
-{\r
- char c,*se;\r
-\r
- while (*s)\r
- {\r
- se = s;\r
- while ((c = *se) && (c != '\n'))\r
- se++;\r
- *se = '\0';\r
-\r
- US_CPrintLine(s);\r
-\r
- s = se;\r
- if (c)\r
- {\r
- *se = c;\r
- s++;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ClearWindow() - Clears the current window to white and homes the\r
-// cursor\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_ClearWindow(void)\r
-{\r
- VWB_Bar(WindowX,WindowY,WindowW,WindowH,WHITE);\r
- PrintX = WindowX;\r
- PrintY = WindowY;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_DrawWindow() - Draws a frame and sets the current window parms\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_DrawWindow(word x,word y,word w,word h)\r
-{\r
- word i,\r
- sx,sy,sw,sh;\r
-\r
- WindowX = x * 8;\r
- WindowY = y * 8;\r
- WindowW = w * 8;\r
- WindowH = h * 8;\r
-\r
- PrintX = WindowX;\r
- PrintY = WindowY;\r
-\r
- sx = (x - 1) * 8;\r
- sy = (y - 1) * 8;\r
- sw = (w + 1) * 8;\r
- sh = (h + 1) * 8;\r
-\r
- US_ClearWindow();\r
-\r
- VWB_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);\r
- for (i = sx + 8;i <= sx + sw - 8;i += 8)\r
- VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);\r
- VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);\r
-\r
- for (i = sy + 8;i <= sy + sh - 8;i += 8)\r
- VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CenterWindow() - Generates a window of a given width & height in the\r
-// middle of the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CenterWindow(word w,word h)\r
-{\r
- US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CenterSaveWindow() - Generates a window of a given width & height in\r
-// the middle of the screen, saving the background\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CenterSaveWindow(word w,word h,memptr *save)\r
-{\r
- word x,y,\r
- screen;\r
-\r
- x = ((MaxX / 8) - w) / 2;\r
- y = ((MaxY / 8) - h) / 2;\r
- MM_GetPtr(save,(w * h) * CHARWIDTH);\r
- screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);\r
- VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);\r
- US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_RestoreSaveWindow() - Restores the background of the size of the\r
-// current window from the memory specified by save\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_RestoreSaveWindow(memptr *save)\r
-{\r
- word screen;\r
-\r
- screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);\r
- VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);\r
- MM_FreePtr(save);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SaveWindow() - Saves the current window parms into a record for\r
-// later restoration\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SaveWindow(WindowRec *win)\r
-{\r
- win->x = WindowX;\r
- win->y = WindowY;\r
- win->w = WindowW;\r
- win->h = WindowH;\r
-\r
- win->px = PrintX;\r
- win->py = PrintY;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_RestoreWindow() - Sets the current window parms to those held in the\r
-// record\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_RestoreWindow(WindowRec *win)\r
-{\r
- WindowX = win->x;\r
- WindowY = win->y;\r
- WindowW = win->w;\r
- WindowH = win->h;\r
-\r
- PrintX = win->px;\r
- PrintY = win->py;\r
-}\r
-\r
-// Cursor routines\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_StartCursor() - Sets up the cursor for User Mgr use\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_StartCursor(void)\r
-{\r
- CursorInfo info;\r
-\r
- VW_SetCursor(CURSORARROWSPR);\r
- CursorX = MaxX / 2;\r
- CursorY = MaxY / 2;\r
- VW_MoveCursor(CursorX,CursorY);\r
- VW_ShowCursor();\r
-\r
- IN_ReadCursor(&info); // Dispose of any accumulated movement\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ShutCursor() - Cleans up after US_StartCursor()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_ShutCursor(void)\r
-{\r
- VW_HideCursor();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_UpdateCursor() - Gets the new cursor position & button states from\r
-// the Input Mgr and tells the View Mgr where the cursor is\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-US_UpdateCursor(void)\r
-{\r
- CursorInfo info;\r
-\r
- IN_ReadCursor(&info);\r
- if (info.x || info.y || CursorBad)\r
- {\r
- CursorX += info.x;\r
- if (CursorX >= MaxX)\r
- CursorX = MaxX - 1;\r
- else if (CursorX < 0)\r
- CursorX = 0;\r
-\r
- CursorY += info.y;\r
- if (CursorY >= MaxY)\r
- CursorY = MaxY - 1;\r
- else if (CursorY < 0)\r
- CursorY = 0;\r
-\r
- VW_MoveCursor(CursorX,CursorY);\r
- CursorBad = false;\r
- }\r
- Button0 = info.button0;\r
- Button1 = info.button1;\r
- return(Button0 || Button1);\r
-}\r
-#endif\r
-\r
-// Input routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_XORICursor(int x,int y,char *s,word cursor)\r
-{\r
- char buf[MaxString];\r
- word w,h;\r
-\r
- strcpy(buf,s);\r
- buf[cursor] = '\0';\r
- USL_MeasureString(buf,&w,&h);\r
-\r
- px = x + w - 1;\r
- py = y;\r
- USL_DrawString("\x80");\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_LineInput() - Gets a line of user input at (x,y), the string defaults\r
-// to whatever is pointed at by def. Input is restricted to maxchars\r
-// chars or maxwidth pixels wide. If the user hits escape (and escok is\r
-// true), nothing is copied into buf, and false is returned. If the\r
-// user hits return, the current string is copied into buf, and true is\r
-// returned\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
- int maxchars,int maxwidth)\r
-{\r
- boolean redraw,\r
- cursorvis,cursormoved,\r
- done,result;\r
- ScanCode sc;\r
- char c,\r
- s[MaxString],olds[MaxString];\r
- word i,\r
- cursor,\r
- w,h,\r
- len;\r
- longword lasttime;\r
-\r
- VW_HideCursor();\r
-\r
- if (def)\r
- strcpy(s,def);\r
- else\r
- *s = '\0';\r
- *olds = '\0';\r
- cursor = strlen(s);\r
- cursormoved = redraw = true;\r
-\r
- cursorvis = done = false;\r
- lasttime = TimeCount;\r
- LastASCII = key_None;\r
- LastScan = sc_None;\r
-\r
- while (!done)\r
- {\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
-\r
- asm pushf\r
- asm cli\r
-\r
- sc = LastScan;\r
- LastScan = sc_None;\r
- c = LastASCII;\r
- LastASCII = key_None;\r
-\r
- asm popf\r
-\r
- switch (sc)\r
- {\r
- case sc_LeftArrow:\r
- if (cursor)\r
- cursor--;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_RightArrow:\r
- if (s[cursor])\r
- cursor++;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_Home:\r
- cursor = 0;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_End:\r
- cursor = strlen(s);\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
-\r
- case sc_Return:\r
- strcpy(buf,s);\r
- done = true;\r
- result = true;\r
- c = key_None;\r
- break;\r
- case sc_Escape:\r
- if (escok)\r
- {\r
- done = true;\r
- result = false;\r
- }\r
- c = key_None;\r
- break;\r
-\r
- case sc_BackSpace:\r
- if (cursor)\r
- {\r
- strcpy(s + cursor - 1,s + cursor);\r
- cursor--;\r
- redraw = true;\r
- }\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_Delete:\r
- if (s[cursor])\r
- {\r
- strcpy(s + cursor,s + cursor + 1);\r
- redraw = true;\r
- }\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
-\r
- case 0x4c: // Keypad 5\r
- case sc_UpArrow:\r
- case sc_DownArrow:\r
- case sc_PgUp:\r
- case sc_PgDn:\r
- case sc_Insert:\r
- c = key_None;\r
- break;\r
- }\r
-\r
- if (c)\r
- {\r
- len = strlen(s);\r
- USL_MeasureString(s,&w,&h);\r
-\r
- if\r
- (\r
- isprint(c)\r
- && (len < MaxString - 1)\r
- && ((!maxchars) || (len < maxchars))\r
- && ((!maxwidth) || (w < maxwidth))\r
- )\r
- {\r
- for (i = len + 1;i > cursor;i--)\r
- s[i] = s[i - 1];\r
- s[cursor++] = c;\r
- redraw = true;\r
- }\r
- }\r
-\r
- if (redraw)\r
- {\r
- px = x;\r
- py = y;\r
- USL_DrawString(olds);\r
- strcpy(olds,s);\r
-\r
- px = x;\r
- py = y;\r
- USL_DrawString(s);\r
-\r
- redraw = false;\r
- }\r
-\r
- if (cursormoved)\r
- {\r
- cursorvis = false;\r
- lasttime = TimeCount - TickBase;\r
-\r
- cursormoved = false;\r
- }\r
- if (TimeCount - lasttime > TickBase / 2)\r
- {\r
- lasttime = TimeCount;\r
-\r
- cursorvis ^= true;\r
- }\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
-\r
- VW_UpdateScreen();\r
- }\r
-\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
- if (!result)\r
- {\r
- px = x;\r
- py = y;\r
- USL_DrawString(olds);\r
- }\r
- VW_ShowCursor();\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- return(result);\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US.c - User Manager - User interface\r
-// v1.1d1\r
-// By Jason Blochowiak\r
-// Hacked up for Catacomb 3D\r
-//\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-#pragma warn -pia\r
-\r
-// Special imports\r
-extern boolean showscorebox;\r
-#ifdef KEEN\r
-extern boolean jerk;\r
-extern boolean oldshooting;\r
-extern ScanCode firescan;\r
-void USL_CheckSavedGames(void);\r
-#else\r
- ScanCode firescan;\r
-#endif\r
-\r
-// Global variables\r
- boolean ingame,abortgame,loadedgame;\r
- GameDiff restartgame = gd_Continue;\r
-\r
-// Internal variables\r
-static boolean GameIsDirty,\r
- QuitToDos,\r
- CtlPanelDone;\r
-\r
-#ifdef KEEN6\r
- int listindex = -1;\r
- boolean checkpassed;\r
-#endif\r
-\r
-// Forward reference prototypes\r
-static void USL_SetupCard(void);\r
-\r
-// Control panel data\r
-\r
-#define CtlPanelSX 74\r
-#define CtlPanelSY 48\r
-#define CtlPanelEX 234\r
-#define CtlPanelEY 150\r
-#define CtlPanelW (CtlPanelEX - CtlPanelSX)\r
-#define CtlPanelH (CtlPanelEY - CtlPanelSY)\r
-\r
-#ifdef KEEN\r
-\r
-#define TileBase 92\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define BackColor 0\r
-#define HiliteColor (BackColor ^ 3)\r
-#define NohiliteColor (BackColor ^ 2)\r
-\r
-#else\r
-\r
-#define BackColor 8\r
-#define HiliteColor (BackColor ^ 10)\r
-#define NohiliteColor (BackColor ^ 2)\r
-\r
-#endif // if GRMODE == CGAGR ... else ...\r
-\r
-#else // ifdef KEEN\r
-\r
-#define TileBase 92\r
-\r
-// DEBUG - CGA\r
-#define BackColor 0\r
-#define HiliteColor (BackColor ^ 12)\r
-#define NohiliteColor (BackColor ^ 4)\r
-\r
-#endif\r
-\r
-typedef enum\r
- {\r
- uc_None,\r
- uc_Return,\r
- uc_Abort,\r
- uc_Quit,\r
- uc_Loaded,\r
- uc_SEasy,\r
- uc_SNormal,\r
- uc_SHard,\r
- } UComm;\r
-typedef enum\r
- {\r
- uii_Bad,\r
- uii_Button,uii_RadioButton,uii_Folder\r
- } UIType;\r
-typedef enum\r
- {\r
- ui_Normal = 0,\r
- ui_Pushed = 1,\r
- ui_Selected = 2,\r
- ui_Disabled = 4,\r
- ui_Separated = 8\r
- } UIFlags;\r
-#define UISelectFlags (ui_Pushed | ui_Selected | ui_Disabled)\r
-\r
-typedef enum\r
- {\r
- uic_SetupCard,uic_DrawCard,uic_TouchupCard,\r
- uic_DrawIcon,uic_Draw,uic_Hit\r
- } UserCall;\r
-\r
-typedef struct UserItem\r
- {\r
- UIType type;\r
- UIFlags flags;\r
- ScanCode hotkey;\r
- char *text;\r
- UComm comm;\r
- void far *child; // Should be (UserItemGroup *)\r
-\r
- word x,y;\r
- } UserItem;\r
-typedef struct UserItemGroup\r
- {\r
- word x,y;\r
- graphicnums title;\r
- ScanCode hotkey;\r
- UserItem far *items;\r
- boolean (*custom)(UserCall,struct UserItem far *); // Custom routine\r
-\r
- word cursor;\r
- struct UserItemGroup far *parent;\r
- } UserItemGroup;\r
-\r
-static char *BottomS1,*BottomS2,*BottomS3;\r
-static UComm Communication;\r
-static ScanCode *KeyMaps[] =\r
- {\r
- &KbdDefs[0].button0,\r
- &KbdDefs[0].button1,\r
- &firescan,\r
- &KbdDefs[0].upleft,\r
- &KbdDefs[0].up,\r
- &KbdDefs[0].upright,\r
- &KbdDefs[0].right,\r
- &KbdDefs[0].downright,\r
- &KbdDefs[0].down,\r
- &KbdDefs[0].downleft,\r
- &KbdDefs[0].left\r
- };\r
-\r
-// Custom routine prototypes\r
-static boolean USL_ConfigCustom(UserCall call,struct UserItem far *item),\r
- USL_KeyCustom(UserCall call,struct UserItem far *item),\r
- USL_KeySCustom(UserCall call,struct UserItem far *item),\r
- USL_Joy1Custom(UserCall call,struct UserItem far *item),\r
- USL_Joy2Custom(UserCall call,struct UserItem far *item),\r
- USL_JoyGCustom(UserCall call,struct UserItem far *item),\r
- USL_LoadCustom(UserCall call,struct UserItem far *item),\r
- USL_SaveCustom(UserCall call,struct UserItem far *item),\r
- USL_ScoreCustom(UserCall call,struct UserItem far *item),\r
- USL_CompCustom(UserCall call,struct UserItem far *item),\r
- USL_SmoothCustom(UserCall call,struct UserItem far *item),\r
-#ifdef KEEN\r
- USL_TwoCustom(UserCall call,struct UserItem far *item),\r
-#endif\r
- USL_PongCustom(UserCall call,struct UserItem far *item);\r
-\r
-#define DefButton(key,text) uii_Button,ui_Normal,key,text\r
-#define DefRButton(key,text) uii_RadioButton,ui_Normal,key,text\r
-#define DefFolder(key,text,child) uii_Folder,ui_Normal,key,text,uc_None,child\r
-#define CustomGroup(title,key,custom) 0,0,title,key,0,custom\r
- UserItem far holder[] =\r
- {\r
- {DefButton(sc_None,"DEBUG")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far holdergroup = {0,0,CP_MAINMENUPIC,sc_None,holder};\r
-\r
- // Sound menu\r
- UserItem far soundi[] =\r
- {\r
- {DefRButton(sc_N,"NO SOUND EFFECTS")},\r
- {DefRButton(sc_P,"PC SPEAKER")},\r
- {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
- {DefRButton(sc_Q,"QUIET ADLIB/SOUNDBLASTER")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far soundgroup = {8,0,CP_SOUNDMENUPIC,sc_None,soundi};\r
-\r
- // Music menu\r
- UserItem far musici[] =\r
- {\r
- {DefRButton(sc_N,"NO MUSIC")},\r
- {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far musicgroup = {8,0,CP_MUSICMENUPIC,sc_None,musici};\r
-\r
- // New game menu\r
- UserItem far newgamei[] =\r
- {\r
- {DefButton(sc_E,"BEGIN EASY GAME"),uc_SEasy},\r
- {DefButton(sc_N,"BEGIN NORMAL GAME"),uc_SNormal},\r
- {DefButton(sc_H,"BEGIN HARD GAME"),uc_SHard},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far newgamegroup = {8,0,CP_NEWGAMEMENUPIC,sc_None,newgamei,0,1};\r
-\r
- // Load/Save game menu\r
- UserItem far loadsavegamei[] =\r
- {\r
-#ifdef CAT3D\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
-#else\r
- {uii_Button,ui_Normal,sc_1},\r
- {uii_Button,ui_Normal,sc_2},\r
- {uii_Button,ui_Normal,sc_3},\r
- {uii_Button,ui_Normal,sc_4},\r
- {uii_Button,ui_Normal,sc_5},\r
- {uii_Button,ui_Normal,sc_6},\r
-#endif\r
- {uii_Bad}\r
- };\r
- UserItemGroup far loadgamegroup = {4,3,CP_LOADMENUPIC,sc_None,loadsavegamei,USL_LoadCustom};\r
- UserItemGroup far savegamegroup = {4,3,CP_SAVEMENUPIC,sc_None,loadsavegamei,USL_SaveCustom};\r
-\r
- // Options menu\r
- UserItemGroup far scoregroup = {0,0,0,sc_None,0,USL_ScoreCustom};\r
-#ifdef KEEN\r
- UserItemGroup far twogroup = {0,0,0,sc_None,0,USL_TwoCustom};\r
-#endif\r
-#if GRMODE != CGAGR\r
- UserItemGroup far smoothgroup = {0,0,0,sc_None,0,USL_SmoothCustom};\r
- UserItemGroup far compgroup = {0,0,0,sc_None,0,USL_CompCustom};\r
-#endif\r
-\r
- UserItem far optionsi[] =\r
- {\r
- {DefFolder(sc_S,"",&scoregroup)},\r
-#ifdef KEEN\r
- {DefFolder(sc_T,"",&twogroup)},\r
-#endif\r
-#if GRMODE != CGAGR\r
- {DefFolder(sc_M,"",&smoothgroup)},\r
- {DefFolder(sc_C,"",&compgroup)},\r
-#endif\r
- {uii_Bad}\r
- };\r
- UserItemGroup far optionsgroup = {8,0,CP_OPTIONSMENUPIC,sc_None,optionsi};\r
-\r
- // Keyboard menu\r
- UserItem far keyi[] =\r
- {\r
- {DefButton(sc_None,"UP & LEFT")},\r
- {DefButton(sc_None,"UP")},\r
- {DefButton(sc_None,"UP & RIGHT")},\r
- {DefButton(sc_None,"RIGHT")},\r
- {DefButton(sc_None,"DOWN & RIGHT")},\r
- {DefButton(sc_None,"DOWN")},\r
- {DefButton(sc_None,"DOWN & LEFT")},\r
- {DefButton(sc_None,"LEFT")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far keygroup = {0,0,CP_KEYMOVEMENTPIC,sc_None,keyi,USL_KeyCustom};\r
- UserItem far keybi[] =\r
- {\r
-#ifdef KEEN\r
- {DefButton(sc_J,"JUMP")},\r
- {DefButton(sc_P,"POGO")},\r
- {DefButton(sc_F,"FIRE")},\r
-#endif\r
-#ifdef CAT3D\r
- {DefButton(sc_J,"FIRE")},\r
- {DefButton(sc_P,"STRAFE")},\r
-#endif\r
-#ifdef CPD\r
- {DefButton(sc_J,"SHOOT")},\r
- {DefButton(sc_P,"BOMB")},\r
-#endif\r
- {uii_Bad}\r
- };\r
- UserItemGroup far keybgroup = {0,0,CP_KEYBUTTONPIC,sc_None,keybi,USL_KeyCustom};\r
- UserItem far keysi[] =\r
- {\r
- {DefFolder(sc_M,"MOVEMENT",&keygroup)},\r
- {DefFolder(sc_B,"BUTTONS",&keybgroup)},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far keysgroup = {8,0,CP_KEYBOARDMENUPIC,sc_None,keysi,USL_KeySCustom};\r
-\r
- // Joystick #1 & #2\r
- UserItemGroup far joy1group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy1Custom)};\r
- UserItemGroup far joy2group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy2Custom)};\r
- UserItemGroup far gravisgroup = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_JoyGCustom)};\r
-\r
- // Config menu\r
- UserItem far configi[] =\r
- {\r
- {DefFolder(sc_S,"SOUND",&soundgroup)},\r
- {DefFolder(sc_M,"MUSIC",&musicgroup)},\r
-#ifndef CAT3D\r
- {DefFolder(sc_O,"OPTIONS",&optionsgroup)},\r
-#endif\r
- {uii_Folder,ui_Separated,sc_K,"USE KEYBOARD",uc_None,&keysgroup},\r
- {DefFolder(sc_1,"USE JOYSTICK #1",&joy1group)},\r
- {DefFolder(sc_2,"USE JOYSTICK #2",&joy2group)},\r
- {DefFolder(sc_G,"",&gravisgroup)},\r
- {uii_Bad}\r
- };\r
-#ifdef CAT3D\r
- UserItemGroup far configgroup = {8,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
-#else\r
- UserItemGroup far configgroup = {0,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
-#endif\r
-\r
- // Main menu\r
- UserItemGroup far ponggroup = {0,0,0,sc_None,0,USL_PongCustom};\r
- UserItem far rooti[] =\r
- {\r
- {DefFolder(sc_N,"NEW GAME",&newgamegroup)},\r
- {DefFolder(sc_L,"LOAD GAME",&loadgamegroup)},\r
- {DefFolder(sc_S,"SAVE GAME",&savegamegroup)},\r
- {DefFolder(sc_C,"CONFIGURE",&configgroup)},\r
- {DefButton(sc_R,nil),uc_Return}, // Return to Game/Demo\r
- {DefButton(sc_E,"END GAME"),uc_Abort},\r
-#ifdef KEEN\r
- {DefFolder(sc_P,"PADDLE WAR",&ponggroup)},\r
-#elif defined CAT3D\r
- {DefFolder(sc_B,"SKULL 'N' BONES",&ponggroup)},\r
-#endif\r
- {DefButton(sc_Q,"QUIT"),uc_Quit},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far rootgroup = {32,4,CP_MAINMENUPIC,sc_None,rooti};\r
-#undef DefButton\r
-#undef DefFolder\r
-\r
-#define MaxCards 7\r
- word cstackptr;\r
- UserItemGroup far *cardstack[MaxCards],\r
- far *topcard;\r
-\r
-// Card stack code\r
-static void\r
-USL_SetupStack(void)\r
-{\r
- cstackptr = 0;\r
- cardstack[0] = topcard = &rootgroup;\r
-}\r
-\r
-static void\r
-USL_PopCard(void)\r
-{\r
- if (!cstackptr)\r
- return;\r
-\r
- topcard = cardstack[--cstackptr];\r
-}\r
-\r
-static void\r
-USL_PushCard(UserItemGroup far *card)\r
-{\r
- if (cstackptr == MaxCards - 1)\r
- return;\r
-\r
- topcard = cardstack[++cstackptr] = card;\r
-}\r
-\r
-static void\r
-USL_DrawItemIcon(UserItem far *item)\r
-{\r
- word flags,tile;\r
-\r
- if (topcard->custom && topcard->custom(uic_DrawIcon,item))\r
- return;\r
-\r
- flags = item->flags;\r
- if (flags & ui_Disabled)\r
- tile = TileBase + ((flags & ui_Selected)? 5 : 4);\r
- else if ((item->type == uii_RadioButton) && (!(flags & ui_Pushed)))\r
- tile = TileBase + ((flags & ui_Selected)? 3 : 2);\r
- else\r
- tile = TileBase + ((flags & ui_Selected)? 1 : 0);\r
- VWB_DrawTile8(item->x,item->y,tile);\r
-}\r
-\r
-static void\r
-USL_DrawItem(UserItem far *item)\r
-{\r
- if (topcard->custom && topcard->custom(uic_Draw,item))\r
- return;\r
-\r
- VWB_Bar(CtlPanelSX + 1,item->y,\r
- CtlPanelEX - CtlPanelSX - 1,8,BackColor); // Clear out background\r
- USL_DrawItemIcon(item);\r
- if ((item->flags & ui_Selected) && !(item->flags & ui_Disabled))\r
- fontcolor = HiliteColor;\r
- else\r
- fontcolor = NohiliteColor;\r
- px = item->x + 8;\r
- py = item->y + 1;\r
- USL_DrawString(item->text);\r
- fontcolor = F_BLACK;\r
-}\r
-\r
-#ifdef KEEN\r
-#if GRMODE == CGAGR\r
-#define MyLine(y) VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,3);\r
-#else\r
-#define MyLine(y) VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,10);\r
-#endif\r
-#else\r
-#define MyLine(y) VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,12);\r
-#endif\r
-\r
-static void\r
-USL_DrawBottom(void)\r
-{\r
- word w,h;\r
-\r
- fontcolor = NohiliteColor;\r
-\r
- px = CtlPanelSX + 4;\r
- py = CtlPanelEY - 15;\r
- USL_DrawString(BottomS1);\r
-\r
- USL_MeasureString(BottomS2,&w,&h);\r
- px = CtlPanelEX - 4 - w;\r
- USL_DrawString(BottomS2);\r
-\r
- USL_MeasureString(BottomS3,&w,&h);\r
- px = CtlPanelSX + ((CtlPanelEX - CtlPanelSX - w) / 2);\r
- py += h + 1;\r
- USL_DrawString(BottomS3);\r
-\r
- fontcolor = F_WHITE;\r
- MyLine(CtlPanelEY - 17);\r
-}\r
-\r
-static void\r
-USL_DrawCtlPanelContents(void)\r
-{\r
- int x,y;\r
- UserItem far *item;\r
-\r
- if (topcard->custom && topcard->custom(uic_DrawCard,nil))\r
- return;\r
-\r
- if (topcard->title)\r
- {\r
- // Draw the title\r
- MyLine(CtlPanelSY + 7);\r
- VWB_DrawPic(CtlPanelSX + 6,CtlPanelSY,topcard->title);\r
- }\r
-\r
- USL_DrawBottom();\r
-\r
- if (!topcard->items)\r
- return;\r
-\r
- x = topcard->x + CtlPanelSX;\r
- if (x % 8)\r
- x += 8 - (x % 8);\r
- y = topcard->y + CtlPanelSY + 12;\r
- for (item = topcard->items;item->type != uii_Bad;item++)\r
- {\r
- if (item->flags & ui_Separated)\r
- y += 8;\r
-\r
- item->x = x;\r
- item->y = y;\r
- USL_DrawItem(item);\r
- y += 8;\r
- }\r
- if (topcard->custom)\r
- topcard->custom(uic_TouchupCard,nil);\r
-}\r
-\r
-static void\r
-USL_DrawCtlPanel(void)\r
-{\r
- if (topcard->items || topcard->title)\r
- {\r
- // Draw the backdrop\r
- VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
-\r
- // Draw the contents\r
- USL_DrawCtlPanelContents();\r
- }\r
-\r
- // Refresh the screen\r
- VW_UpdateScreen();\r
-}\r
-\r
-static void\r
-USL_DialogSetup(word w,word h,word *x,word *y)\r
-{\r
- VWB_DrawMPic(CtlPanelSX,CtlPanelSY,CP_MENUMASKPICM);\r
-\r
- *x = CtlPanelSX + ((CtlPanelW - w) / 2);\r
- *y = CtlPanelSY + ((CtlPanelH - h) / 2);\r
- VWB_Bar(*x,*y,w + 1,h + 1,BackColor);\r
- VWB_Hlin(*x - 1,*x + w + 1,*y - 1,NohiliteColor);\r
- VWB_Hlin(*x - 1,*x + w + 1,*y + h + 1,NohiliteColor);\r
- VWB_Vlin(*y - 1,*y + h + 1,*x - 1,NohiliteColor);\r
- VWB_Vlin(*y - 1,*y + h + 1,*x + w + 1,NohiliteColor);\r
-}\r
-\r
-static void\r
-USL_ShowLoadSave(char *s,char *name)\r
-{\r
- word x,y,\r
- w,h,\r
- tw,sw;\r
- char msg[MaxGameName + 4];\r
-\r
- strcpy(msg,"'");\r
- strcat(msg,name);\r
- strcat(msg,"'");\r
- USL_MeasureString(s,&sw,&h);\r
- USL_MeasureString(msg,&w,&h);\r
- tw = ((sw > w)? sw : w) + 6;\r
- USL_DialogSetup(tw,(h * 2) + 2,&x,&y);\r
- py = y + 2;\r
- px = x + ((tw - sw) / 2);\r
- USL_DrawString(s);\r
- py += h;\r
- px = x + ((tw - w) / 2);\r
- USL_DrawString(msg);\r
-\r
- VW_UpdateScreen();\r
-#ifdef CAT3D\r
- IN_UserInput(100, true);\r
-#endif\r
-}\r
-\r
-static boolean\r
-USL_CtlDialog(char *s1,char *s2,char *s3)\r
-{\r
- word w,h,sh,\r
- w1,w2,w3,\r
- x,y;\r
- ScanCode c;\r
- CursorInfo cursorinfo;\r
-\r
- USL_MeasureString(s1,&w1,&h);\r
- USL_MeasureString(s2,&w2,&h);\r
- if (s3)\r
- USL_MeasureString(s3,&w3,&h);\r
- else\r
- w3 = 0;\r
- w = (w1 > w2)? ((w1 > w3)? w1 : w3) : ((w2 > w3)? w2 : w3);\r
- w += 7;\r
- sh = h;\r
- h *= s3? 5 : 4;\r
-\r
- USL_DialogSetup(w,h,&x,&y);\r
-\r
- fontcolor = HiliteColor;\r
- px = x + ((w - w1) / 2);\r
- py = y + sh + 1;\r
- USL_DrawString(s1);\r
- py += (sh * 2) - 1;\r
-\r
- VWB_Hlin(x + 3,x + w - 3,py,NohiliteColor);\r
- py += 2;\r
-\r
- fontcolor = NohiliteColor;\r
- px = x + ((w - w2) / 2);\r
- USL_DrawString(s2);\r
- py += sh;\r
-\r
- if (s3)\r
- {\r
- px = x + ((w - w3) / 2);\r
- USL_DrawString(s3);\r
- }\r
-\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- if (cursorinfo.button0)\r
- c = sc_Y;\r
- else if (cursorinfo.button1)\r
- c = sc_Escape;\r
- else\r
- c = LastScan;\r
- } while (c == sc_None);\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- } while (cursorinfo.button0 || cursorinfo.button1);\r
-\r
- IN_ClearKeysDown();\r
- USL_DrawCtlPanel();\r
- return(c == sc_Y);\r
-}\r
-\r
-static boolean\r
-USL_ConfirmComm(UComm comm)\r
-{\r
- boolean confirm,dialog;\r
- char *s1,*s2,*s3;\r
-\r
- if (!comm)\r
- Quit("USL_ConfirmComm() - empty comm");\r
-\r
- confirm = true;\r
- dialog = false;\r
- s3 = "ESC TO BACK OUT";\r
- switch (comm)\r
- {\r
- case uc_Abort:\r
- s1 = "REALLY END CURRENT GAME?";\r
- s2 = "PRESS Y TO END IT";\r
- if (ingame && GameIsDirty)\r
- dialog = true;\r
- break;\r
- case uc_Quit:\r
- s1 = "REALLY QUIT?";\r
- s2 = "PRESS Y TO QUIT";\r
- dialog = true;\r
- break;\r
- case uc_Loaded:\r
- s1 = "YOU'RE IN A GAME";\r
- s2 = "PRESS Y TO LOAD GAME";\r
- if (ingame && GameIsDirty)\r
- dialog = true;\r
- break;\r
- case uc_SEasy:\r
- case uc_SNormal:\r
- case uc_SHard:\r
- s1 = "YOU'RE IN A GAME";\r
- s2 = "PRESS Y FOR NEW GAME";\r
- if (ingame && GameIsDirty)\r
- dialog = true;\r
- break;\r
- }\r
-\r
- confirm = dialog? USL_CtlDialog(s1,s2,s3) : true;\r
- if (confirm)\r
- {\r
- Communication = comm;\r
- CtlPanelDone = true;\r
- }\r
- return(confirm);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_HandleError() - Handles telling the user that there's been an error\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_HandleError(int num)\r
-{\r
- char buf[64];\r
-\r
- strcpy(buf,"Error: ");\r
- if (num < 0)\r
- strcat(buf,"Unknown");\r
- else if (num == ENOMEM)\r
- strcat(buf,"Disk is Full");\r
- else if (num == EINVFMT)\r
- strcat(buf,"File is Incomplete");\r
- else\r
- strcat(buf,sys_errlist[num]);\r
-\r
- VW_HideCursor();\r
-\r
- USL_CtlDialog(buf,"PRESS ANY KEY",nil);\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- VW_ShowCursor();\r
- VW_UpdateScreen();\r
-}\r
-\r
-// Custom routines\r
-#if 0\r
-static boolean\r
-USL_GenericCustom(UserCall call,UserItem far *item)\r
-{\r
- boolean result;\r
-\r
- result = false;\r
- switch (call)\r
- {\r
- }\r
- return(result);\r
-}\r
-#endif\r
-\r
-static void\r
-USL_SetOptionsText(void)\r
-{\r
- optionsi[0].text = showscorebox? "SCORE BOX (ON)" : "SCORE BOX (OFF)";\r
- optionsi[1].text = oldshooting? "TWO-BUTTON FIRING (ON)" : "TWO-BUTTON FIRING (OFF)";\r
-#if GRMODE != CGAGR\r
- optionsi[2].text = jerk? "FIX JERKY MOTION (ON)" : "FIX JERKY MOTION (OFF)";\r
- optionsi[3].text = compatability? "SVGA COMPATIBILITY (ON)" : "SVGA COMPATIBILITY (OFF)";\r
-#endif\r
-\r
- keybi[2].flags &= ~ui_Disabled;\r
- if (oldshooting)\r
- keybi[2].flags |= ui_Disabled;\r
-\r
- // gravis option is only enabled when a joystick is selected\r
- configi[6].flags |= ui_Disabled;\r
- if (Controls[0] == ctrl_Joystick1 || Controls[0] == ctrl_Joystick2)\r
- configi[6].flags &= ~ui_Disabled;\r
-\r
- configi[6].text = GravisGamepad? "USE GRAVIS GAMEPAD (ON)" : "USE GRAVIS GAMEPAD (OFF)";\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_ScoreCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- showscorebox ^= true;\r
- USL_CtlDialog(showscorebox? "Score box now on" : "Score box now off",\r
- "Press any key",nil);\r
- USL_SetOptionsText();\r
- return(true);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_SmoothCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- jerk ^= true;\r
- USL_CtlDialog(jerk? "Jerky motion fix enabled" : "Jerky motion fix disabled",\r
- "Press any key",nil);\r
- USL_SetOptionsText();\r
- return(true);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_CompCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- compatability ^= true;\r
- USL_CtlDialog(compatability? "SVGA compatibility now on" : "SVGA compatibility now off",\r
- "Press any key",nil);\r
- USL_SetOptionsText();\r
- return(true);\r
-}\r
-\r
-#ifdef KEEN\r
-#pragma argsused\r
-static boolean\r
-USL_TwoCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- oldshooting ^= true;\r
- USL_CtlDialog(oldshooting? "Two-button firing now on" : "Two-button firing now off",\r
- "Press any key",nil);\r
- USL_SetOptionsText();\r
- return(true);\r
-}\r
-#endif\r
-\r
-static boolean\r
-USL_ConfigCustom(UserCall call,UserItem far *item)\r
-{\r
-static char *CtlNames[] = {"KEYBOARD","KEYBOARD","JOYSTICK #1","JOYSTICK #2","MOUSE"};\r
- char *s;\r
- word w,h,\r
- tw;\r
-\r
- if (call == uic_TouchupCard)\r
- {\r
- s = "CONTROL: ";\r
- USL_MeasureString(s,&w,&h);\r
- tw = w;\r
- USL_MeasureString(CtlNames[Controls[0]],&w,&h);\r
- tw += w;\r
- py = CtlPanelEY - 18 - h;\r
- px = CtlPanelSX + ((CtlPanelW - tw) / 2);\r
- fontcolor = NohiliteColor;\r
- USL_DrawString(s);\r
- USL_DrawString(CtlNames[Controls[0]]);\r
- }\r
- item++; // Shut the compiler up\r
- return(false);\r
-}\r
-\r
-static void\r
-USL_CKSetKey(UserItem far *item,word i)\r
-{\r
- boolean on;\r
- word j;\r
- ScanCode scan;\r
- longword time;\r
- CursorInfo cursorinfo;\r
-\r
- on = false;\r
- time = 0;\r
- LastScan = sc_None;\r
- fontcolor = HiliteColor;\r
- do\r
- {\r
- if (TimeCount >= time)\r
- {\r
- on ^= true;\r
- VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
- VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
- if (on)\r
- VWB_DrawTile8(item->x + 90 + 16,item->y,TileBase + 8);\r
- VW_UpdateScreen();\r
-\r
- time = TimeCount + (TickBase / 2);\r
- }\r
-\r
- IN_ReadCursor(&cursorinfo);\r
- while (cursorinfo.button0 || cursorinfo.button1)\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- LastScan = sc_Escape;\r
- }\r
-\r
- asm pushf\r
- asm cli\r
- if (LastScan == sc_LShift)\r
- LastScan = sc_None;\r
- asm popf\r
- } while (!(scan = LastScan));\r
-\r
- if (scan != sc_Escape)\r
- {\r
- for (j = 0,on = false;j < 11;j++)\r
- {\r
- if (j == i)\r
- continue;\r
- if (*(KeyMaps[j]) == scan)\r
- {\r
- on = true;\r
- break;\r
- }\r
- }\r
- if (on)\r
-#ifdef KEEN\r
- USL_CtlDialog("Key already used","Press any key",nil);\r
-#else\r
- USL_CtlDialog("Key already used","Press a key",nil);\r
-#endif\r
- else\r
- *(KeyMaps[i]) = scan;\r
- }\r
- IN_ClearKeysDown();\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_KeySCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call == uic_SetupCard)\r
- {\r
- Controls[0] = ctrl_Keyboard;\r
- GravisGamepad = false;\r
- USL_SetOptionsText();\r
- }\r
- return(false);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_KeyCustom(UserCall call,UserItem far *item)\r
-{\r
- boolean result;\r
- word i;\r
-\r
- result = false;\r
- i = (topcard == &keygroup)? (3 + (item - keyi)) : (item - keybi);\r
- switch (call)\r
- {\r
- case uic_SetupCard:\r
- Controls[0] = ctrl_Keyboard;\r
- break;\r
- case uic_Draw:\r
- VWB_Bar(CtlPanelSX + 1,item->y,\r
- CtlPanelEX - CtlPanelSX - 1,8,BackColor); // Clear out background\r
- USL_DrawItemIcon(item);\r
- fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
- px = item->x + 8;\r
- py = item->y + 1;\r
- USL_DrawString(item->text);\r
- VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
- VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
- px = item->x + 90 + 6;\r
- py = item->y + 1;\r
- USL_DrawString(IN_GetScanName(*KeyMaps[i]));\r
- result = true;\r
- break;\r
- case uic_Hit:\r
- USL_KeyCustom(uic_Draw,item);\r
- USL_CKSetKey(item,i);\r
- USL_DrawCtlPanel();\r
- result = true;\r
- break;\r
- }\r
- return(result);\r
-}\r
-\r
-static void\r
-USL_CJDraw(char *s1,char *s2)\r
-{\r
- word w,h;\r
-\r
- USL_MeasureString(s1,&w,&h);\r
- px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
- py = CtlPanelEY - 34;\r
- VWB_Bar(CtlPanelSX + 1,py,CtlPanelW - 2,h * 2,BackColor);\r
- fontcolor = HiliteColor;\r
- USL_DrawString(s1);\r
- py += h;\r
- USL_MeasureString(s2,&w,&h);\r
- px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
- USL_DrawString(s2);\r
-}\r
-\r
-static boolean\r
-USL_CJGet(word joy,word button,word x,word y,word *xaxis,word *yaxis)\r
-{\r
- boolean on;\r
- longword time;\r
-\r
- while (IN_GetJoyButtonsDB(joy))\r
- if (LastScan == sc_Escape)\r
- return(false);\r
-\r
- on = false;\r
- time = 0;\r
- while (!(IN_GetJoyButtonsDB(joy) & (1 << button)))\r
- {\r
- if (TimeCount >= time)\r
- {\r
- on ^= true;\r
- time = TimeCount + (TickBase / 2);\r
- VWB_DrawTile8(x,y,TileBase + on);\r
- VW_UpdateScreen();\r
- }\r
-\r
- if (LastScan == sc_Escape)\r
- return(false);\r
- }\r
- IN_GetJoyAbs(joy,xaxis,yaxis);\r
- return(true);\r
-}\r
-\r
-static boolean\r
-USL_ConfigJoystick(word joy)\r
-{\r
- word x,y,\r
- minx,miny,\r
- maxx,maxy;\r
-\r
- BottomS1 = BottomS2 = "";\r
-#ifdef KEEN\r
- BottomS3 = "ESC to back out";\r
-#else\r
- BottomS3 = "Esc to back out";\r
-#endif\r
- USL_DrawCtlPanel();\r
- x = CtlPanelSX + 60;\r
- y = CtlPanelSY + 19;\r
- VWB_DrawPic(x,y,CP_JOYSTICKPIC);\r
-\r
- USL_CJDraw("Move Joystick to upper left","and press button #1");\r
- VWB_DrawTile8(x + 24,y + 8,TileBase + 6);\r
- VWB_DrawTile8(x + 8,y + 8,TileBase + 1);\r
- VWB_DrawTile8(x + 8,y + 24,TileBase + 0);\r
- VW_UpdateScreen();\r
- if (!USL_CJGet(joy,0,x + 8,y + 8,&minx,&miny))\r
- return(false);\r
-\r
- USL_CJDraw("Move Joystick to lower right","and press button #2");\r
- VWB_DrawTile8(x + 24,y + 8,TileBase - 25);\r
- VWB_DrawTile8(x + 40,y + 24,TileBase + 7);\r
- VWB_DrawTile8(x + 8,y + 8,TileBase + 0);\r
- VWB_DrawTile8(x + 8,y + 24,TileBase + 1);\r
- VW_UpdateScreen();\r
- if (!USL_CJGet(joy,1,x + 8,y + 24,&maxx,&maxy))\r
- return(false);\r
-\r
- while (IN_GetJoyButtonsDB(joy))\r
- ;\r
-\r
-#ifdef KEEN\r
- if (minx != maxx && miny != maxy)\r
- {\r
- IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
- return(true);\r
- }\r
- return(false);\r
-#else\r
- IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
- return(true);\r
-#endif\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_Joy1Custom(UserCall call,UserItem far *item)\r
-{\r
- if (call == uic_SetupCard)\r
- {\r
- if (USL_ConfigJoystick(0))\r
- {\r
- Controls[0] = ctrl_Joystick1;\r
- USL_CtlDialog("USING JOYSTICK #1","PRESS ANY KEY",nil);\r
- USL_SetOptionsText();\r
- }\r
- return(true);\r
- }\r
- else\r
- return(false);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_Joy2Custom(UserCall call,UserItem far *item)\r
-{\r
- if (call == uic_SetupCard)\r
- {\r
- if (USL_ConfigJoystick(1))\r
- {\r
- Controls[0] = ctrl_Joystick2;\r
- USL_CtlDialog("USING JOYSTICK #2","PRESS ANY KEY",nil);\r
- USL_SetOptionsText();\r
- }\r
- return(true);\r
- }\r
- else\r
- return(false);\r
-}\r
-\r
-static void\r
-USL_CGDraw(char *s1, char *s2, int buttonsDone)\r
-{\r
- static char *GButtonNames[4] = {"Red","Blue","Yellow","Green"};\r
- static char *GActionNames[4] = {"Jump","Pogo","Fire","Status"};\r
-\r
- int i, n;\r
- char *actionstr;\r
- word w, h;\r
-\r
- VWB_Bar(CtlPanelSX+1, CtlPanelSY+16, CtlPanelW-2, 68, BackColor);\r
- px = CtlPanelSX+8;\r
- py = CtlPanelSY+16;\r
- USL_DrawString("Make sure that the button");\r
- px = CtlPanelSX+8;\r
- py = CtlPanelSY+24;\r
- USL_DrawString("switch is set for 4 buttons");\r
-\r
- for (i=0; i<4; i++)\r
- {\r
- px = CtlPanelSX+8;\r
- py = i*8 + CtlPanelSY+40;\r
- USL_DrawString(GButtonNames[i]);\r
- USL_DrawString(":");\r
- actionstr = "?";\r
- for (n=0;n<buttonsDone;n++)\r
- {\r
- if (GravisMap[n] == i)\r
- actionstr = GActionNames[n];\r
- }\r
- px = CtlPanelSX+56;\r
- USL_DrawString(actionstr);\r
- }\r
-\r
- USL_MeasureString(s1, &w, &h);\r
- px = w;\r
- USL_MeasureString(s2, &w, &h);\r
- px = (CtlPanelW-px-w)/2 + CtlPanelSX;\r
- py = CtlPanelSY+76;\r
- USL_DrawString(s1);\r
- USL_DrawString(s2);\r
- VW_UpdateScreen();\r
-}\r
-\r
-static boolean\r
-USL_CGGet(int buttonsDone, char *action)\r
-{\r
- word buttons, i, n;\r
-\r
- USL_CGDraw("PRESS BUTTON FOR ", action, buttonsDone);\r
-\r
-redo:\r
- do\r
- {\r
- if (LastScan == sc_Escape)\r
- {\r
- Keyboard[sc_Escape] = false;\r
- if (LastScan == sc_Escape)\r
- LastScan = sc_None;\r
- return false;\r
- }\r
-\r
- buttons = IN_GetJoyButtonsDB(2);\r
- if (!buttons)\r
- continue;\r
-\r
- for(i=n=0; i<4; i++)\r
- {\r
- if (buttons & (1 << i))\r
- n += i+1;\r
- }\r
-\r
- if (!n || n >= 5)\r
- continue;\r
-\r
- n--;\r
- for (i=0; i<buttonsDone; i++)\r
- {\r
- if (GravisMap[i] == n)\r
- goto redo;\r
- }\r
-\r
- GravisMap[buttonsDone] = n;\r
- return true;\r
- } while (true);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_JoyGCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call == uic_SetupCard)\r
- {\r
- if (GravisGamepad)\r
- {\r
- GravisGamepad = false;\r
- }\r
- else\r
- {\r
- BottomS1 = BottomS2 = "";\r
- BottomS3 = "ESC to back out";\r
- USL_DrawCtlPanel();\r
- fontcolor = HiliteColor;\r
- px = CtlPanelSX + 8;\r
- py = CtlPanelSX + 8;\r
- fontcolor = HiliteColor; // redundant...\r
- IN_ClearKeysDown();\r
- if ( USL_CGGet(0, "JUMP")\r
- && USL_CGGet(1, "POGO")\r
- && USL_CGGet(2, "FIRE")\r
- && USL_CGGet(3, "STATUS") )\r
- {\r
- GravisGamepad = true;\r
- USL_CGDraw("PRESS ANY KEY", "", 4);\r
- IN_Ack();\r
- }\r
- else\r
- {\r
- GravisGamepad = false;\r
- }\r
- }\r
- USL_SetOptionsText();\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-static void\r
-USL_DrawFileIcon(UserItem far *item)\r
-{\r
- word color;\r
-\r
- item->y = topcard->y + CtlPanelSY + 12;\r
- item->y += (item - loadsavegamei) * 11;\r
-\r
- fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
- color = fontcolor ^ BackColor; // Blech!\r
- VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y,color);\r
- VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y + 9,color);\r
- VWB_Vlin(item->y,item->y + 9,item->x,color);\r
- VWB_Vlin(item->y,item->y + 9,item->x + (CtlPanelW - 12),color);\r
-}\r
-\r
-static void\r
-USL_DoLoadGame(UserItem far *item)\r
-{\r
- char *filename;\r
- word n,\r
- err;\r
- int file;\r
- SaveGame *game;\r
-\r
- if (!USL_ConfirmComm(uc_Loaded))\r
- return;\r
-\r
- n = item - loadsavegamei;\r
- game = &Games[n];\r
-\r
- USL_ShowLoadSave("Loading",game->name);\r
-\r
- err = 0;\r
- filename = USL_GiveSaveName(n);\r
- if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- if (read(file,game,sizeof(*game)) == sizeof(*game))\r
- {\r
- if (USL_LoadGame)\r
- if (!USL_LoadGame(file))\r
- USL_HandleError(err = errno);\r
- }\r
- else\r
- USL_HandleError(err = errno);\r
- close(file);\r
- }\r
- else\r
- USL_HandleError(err = errno);\r
- if (err)\r
- {\r
- abortgame = true;\r
- Communication = uc_None;\r
- CtlPanelDone = false;\r
- }\r
- else\r
- loadedgame = true;\r
- game->present = true;\r
-\r
- if (loadedgame)\r
- Paused = true;\r
-\r
- USL_DrawCtlPanel();\r
-}\r
-\r
-static boolean\r
-USL_LoadCustom(UserCall call,UserItem far *item)\r
-{\r
- boolean result;\r
- word i;\r
-\r
- result = false;\r
- switch (call)\r
- {\r
- case uic_SetupCard:\r
-#ifdef KEEN\r
- if (getenv("UID"))\r
- USL_CheckSavedGames();\r
-#endif\r
- for (i = 0;i < MaxSaveGames;i++)\r
- {\r
- if (Games[i].present)\r
- loadsavegamei[i].flags &= ~ui_Disabled;\r
- else\r
- loadsavegamei[i].flags |= ui_Disabled;\r
- }\r
- break;\r
- case uic_DrawIcon:\r
- USL_DrawFileIcon(item);\r
- result = true;\r
- break;\r
- case uic_Draw:\r
- USL_DrawFileIcon(item);\r
- VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
-\r
- i = item - loadsavegamei;\r
- if (Games[i].present)\r
- px = item->x + 2;\r
- else\r
- px = item->x + 60;\r
- py = item->y + 2;\r
- USL_DrawString(Games[i].present? Games[i].name : "Empty");\r
- result = true;\r
- break;\r
- case uic_Hit:\r
- USL_DoLoadGame(item);\r
- result = true;\r
- break;\r
- }\r
- return(result);\r
-}\r
-\r
-static void\r
-USL_DoSaveGame(UserItem far *item)\r
-{\r
- boolean ok;\r
- char *filename;\r
- word n,err;\r
- int file;\r
- SaveGame *game;\r
-\r
- BottomS1 = "Type name";\r
- BottomS2 = "Enter accepts";\r
- USL_DrawCtlPanel();\r
-\r
- n = item - loadsavegamei;\r
- game = &Games[n];\r
- fontcolor = HiliteColor;\r
- VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
- game->oldtest = &PrintX;\r
- ok = US_LineInput(item->x + 2,item->y + 2,\r
- game->name,game->present? game->name : nil,\r
- true,MaxGameName,\r
- CtlPanelW - 22);\r
- if (!strlen(game->name))\r
- strcpy(game->name,"Untitled");\r
- if (ok)\r
- {\r
- USL_ShowLoadSave("Saving",game->name);\r
-\r
- filename = USL_GiveSaveName(n);\r
- err = 0;\r
- file = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
- S_IREAD | S_IWRITE | S_IFREG);\r
- if (file != -1)\r
- {\r
- if (write(file,game,sizeof(*game)) == sizeof(*game))\r
- {\r
- if (USL_SaveGame)\r
- ok = USL_SaveGame(file);\r
- if (!ok)\r
- USL_HandleError(err = errno);\r
- }\r
- else\r
- USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
- close(file);\r
- }\r
- else\r
- USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
- if (err)\r
- {\r
- remove(filename);\r
- ok = false;\r
- }\r
-\r
- }\r
-\r
- if (!game->present)\r
- game->present = ok;\r
-\r
- if (ok)\r
- GameIsDirty = false;\r
- USL_SetupCard();\r
-}\r
-\r
-static boolean\r
-USL_SaveCustom(UserCall call,UserItem far *item)\r
-{\r
- word i;\r
-\r
- switch (call)\r
- {\r
- case uic_SetupCard:\r
-#ifdef KEEN\r
- if (getenv("UID"))\r
- USL_CheckSavedGames();\r
-#endif\r
- for (i = 0;i < MaxSaveGames;i++)\r
- loadsavegamei[i].flags &= ~ui_Disabled;\r
- return(false);\r
- case uic_Hit:\r
- USL_DoSaveGame(item);\r
- return(true);\r
-// break;\r
- }\r
- return(USL_LoadCustom(call,item));\r
-}\r
-\r
-#define PaddleMinX (CtlPanelSX + 4)\r
-#define PaddleMaxX (CtlPanelEX - 15)\r
-#define BallMinX (CtlPanelSX + 4)\r
-#define BallMinY (CtlPanelSY + 12 + 2)\r
-#define BallMaxX (CtlPanelEX - 6)\r
-#define BallMaxY (CtlPanelEY - 13)\r
-#define CPaddleY (BallMinY + 4)\r
-#define KPaddleY (BallMaxY - 2)\r
-void\r
-USL_DrawPongScore(word k,word c)\r
-{\r
- fontcolor = HiliteColor;\r
- PrintY = py = CtlPanelSY + 4;\r
- px = CtlPanelSX + 6;\r
- VWB_Bar(px,py,42,6,BackColor);\r
- USL_DrawString("KEEN:");\r
- PrintX = px;\r
- US_PrintUnsigned(k);\r
- px = CtlPanelSX + 108;\r
- VWB_Bar(px,py,50,6,BackColor);\r
- USL_DrawString("COMP:");\r
- PrintX = px;\r
- US_PrintUnsigned(c);\r
-}\r
-\r
-void\r
-USL_PlayPong(void)\r
-{\r
- boolean ball,killball,revdir,done,lastscore;\r
- word cycle,\r
- x,y,\r
- kx,cx,\r
- rx,\r
- bx,by,\r
- oldkx,oldcx,oldbx,oldby,\r
- kscore,cscore,\r
- speedup;\r
- int bdx,bdy;\r
- longword balltime,lasttime,waittime;\r
- CursorInfo cursorinfo;\r
-\r
- kx = cx = PaddleMinX + ((PaddleMaxX - PaddleMinX) / 2);\r
- bx = by = bdx = bdy = 0;\r
- oldbx = oldcx = oldkx = PaddleMinX;\r
- oldby = BallMinY;\r
- kscore = cscore = 0;\r
- USL_DrawPongScore(0,0);\r
- cycle = 0;\r
- revdir = false;\r
- killball = true;\r
- done = false;\r
- lastscore = false;\r
- lasttime = TimeCount;\r
- do\r
- {\r
- while ((waittime = TimeCount - lasttime) == 0)\r
- ;\r
-\r
- lasttime = TimeCount;\r
- if (waittime > 4)\r
- waittime = 4;\r
-\r
- while (waittime-- && !done && LastScan != sc_Escape)\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- if (((cursorinfo.x < 0) || IN_KeyDown(sc_LeftArrow)) && (kx > PaddleMinX))\r
- kx -= 2;\r
- else if (((cursorinfo.x > 0) || IN_KeyDown(sc_RightArrow)) && (kx < PaddleMaxX))\r
- kx += 2;\r
-\r
- if (killball)\r
- {\r
- ball = false;\r
- balltime = TickBase;\r
- speedup = 10;\r
- killball = false;\r
- VWB_Bar(oldbx,oldby,5,5,BackColor);\r
- }\r
-\r
- if (ball && (cycle++ % 3))\r
- {\r
- x = (bx >> 2);\r
- if (!(x & 1))\r
- x += (US_RndT() & 1);\r
-\r
- if ((cx + 6 < x) && (cx < PaddleMaxX))\r
- cx += 1;\r
- else if ((cx + 6 > x) && (cx > PaddleMinX))\r
- cx -= 1;\r
- }\r
-\r
- if (!ball && !--balltime)\r
- {\r
- ball = true;\r
- bdx = 1 - (US_RndT() % 3);\r
- bdy = 3;\r
- if (lastscore)\r
- bdy = -bdy;\r
- bx = (BallMinX + ((BallMaxX - BallMinX) / 2)) << 2;\r
- by = (BallMinY + ((BallMaxY - BallMinY) / 2)) << 2;\r
- }\r
-\r
- if (ball)\r
- {\r
- if\r
- (\r
- (((bx + bdx) >> 2) > BallMaxX)\r
- || (((bx + bdx) >> 2) < BallMinX)\r
- )\r
- {\r
- SD_PlaySound(BALLBOUNCESND);\r
- bdx = -bdx;\r
- }\r
- bx += bdx;\r
-\r
- if (((by + bdy) >> 2) > BallMaxY)\r
- {\r
- killball = true;\r
- lastscore = false;\r
- cscore++;\r
- SD_PlaySound(COMPSCOREDSND);\r
- USL_DrawPongScore(kscore,cscore);\r
- if (cscore == 21)\r
- {\r
- USL_CtlDialog("You lost!","Press any key",nil);\r
- done = true;\r
- continue;\r
- }\r
- }\r
- else if (((by + bdy) >> 2) < BallMinY)\r
- {\r
- killball = true;\r
- lastscore = true;\r
- kscore++;\r
- SD_PlaySound(KEENSCOREDSND);\r
- USL_DrawPongScore(kscore,cscore);\r
- if (kscore == 21)\r
- {\r
- USL_CtlDialog("You won!","Press any key",nil);\r
- done = true;\r
- continue;\r
- }\r
- }\r
- by += bdy;\r
-\r
- x = bx >> 2;\r
- y = by >> 2;\r
- if (!killball)\r
- {\r
- if\r
- (\r
- (bdy < 0)\r
- && ((y >= CPaddleY) && (y < CPaddleY + 3))\r
- && ((x >= (cx - 5)) && (x < (cx + 11)))\r
- )\r
- {\r
- rx = cx;\r
- revdir = true;\r
- SD_PlaySound(COMPPADDLESND);\r
- }\r
- else if\r
- (\r
- (bdy > 0)\r
- && ((y >= (KPaddleY - 3)) && (y < KPaddleY))\r
- && ((x >= (kx - 5)) && (x < (kx + 11)))\r
- )\r
- {\r
- if (((bdy >> 2) < 3) && !(--speedup))\r
- {\r
- bdy++;\r
- speedup = 10;\r
- }\r
- rx = kx;\r
- revdir = true;\r
- SD_PlaySound(KEENPADDLESND);\r
- }\r
- if (revdir)\r
- {\r
- bdy = -bdy;\r
- bdx = ((x + 5 - rx) >> 1) - (1 << 2);\r
- if (!bdx)\r
- bdx--;\r
- revdir = false;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (ball)\r
- {\r
- VWB_Bar(oldbx,oldby,5,5,BackColor);\r
- oldbx = x;\r
- oldby = y;\r
-#if GRMODE == CGAGR\r
- {\r
- static int ballsprites[4] = {BALLSPR, BALL1PIXELTOTHERIGHTSPR, BALL2PIXELSTOTHERIGHTSPR, BALL3PIXELSTOTHERIGHTSPR};\r
- VWB_DrawSprite(x,y,ballsprites[x & 3]);\r
- }\r
-#else\r
- VWB_DrawSprite(x,y,(x & 1)? BALL1PIXELTOTHERIGHTSPR : BALLSPR);\r
-#endif\r
- }\r
- VWB_Bar(oldcx-3,CPaddleY,16,3,BackColor);\r
- oldcx = cx;\r
- VWB_DrawSprite(cx,CPaddleY,PADDLESPR);\r
- VWB_Bar(oldkx-3,KPaddleY,16,3,BackColor);\r
- oldkx = kx;\r
- VWB_DrawSprite(kx,KPaddleY,PADDLESPR);\r
-\r
- VW_UpdateScreen();\r
- } while ((LastScan != sc_Escape) && !done);\r
- IN_ClearKeysDown();\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_PongCustom(UserCall call,struct UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
- VWB_DrawPic(CtlPanelSX + 56,CtlPanelSY,CP_PADDLEWARPIC);\r
- VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelSY + 12,HiliteColor ^ BackColor);\r
- VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelEY - 7,HiliteColor ^ BackColor);\r
- USL_PlayPong();\r
-\r
- return(true);\r
-}\r
-\r
-// Flag management stuff\r
-static void\r
-USL_ClearFlags(UserItemGroup far *node)\r
-{\r
- UserItem far *i;\r
-\r
- if (!node->items)\r
- return;\r
-\r
- for (i = node->items;i->type != uii_Bad;i++)\r
- {\r
- i->flags &= ~UISelectFlags;\r
- if (i->child)\r
- USL_ClearFlags((UserItemGroup far *)i->child);\r
- }\r
-}\r
-\r
-static int\r
-USL_FindPushedItem(UserItemGroup far *group)\r
-{\r
- word i;\r
- UserItem far *item;\r
-\r
- for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
- if (item->flags & ui_Pushed)\r
- return(i);\r
- return(-1);\r
-}\r
-\r
-static void\r
-USL_SelectItem(UserItemGroup far *group,word index,boolean draw)\r
-{\r
- UserItem far *item;\r
-\r
- if (index != group->cursor)\r
- {\r
- item = &group->items[group->cursor];\r
- item->flags &= ~ui_Selected;\r
- if (draw)\r
- USL_DrawItem(item);\r
- }\r
-\r
- group->cursor = index;\r
- item = &group->items[group->cursor];\r
- group->items[group->cursor].flags |= ui_Selected;\r
- if (draw)\r
- USL_DrawItem(item);\r
-}\r
-\r
-static void\r
-USL_PushItem(UserItemGroup far *group,word index,boolean draw)\r
-{\r
- word i;\r
- UserItem far *item;\r
-\r
- USL_SelectItem(group,index,draw);\r
- for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
- {\r
- if (item->type != uii_RadioButton)\r
- continue;\r
-\r
- if (i == index)\r
- {\r
- item->flags |= ui_Pushed;\r
- if (draw)\r
- USL_DrawItem(item);\r
- }\r
- else if (item->flags & ui_Pushed)\r
- {\r
- item->flags &= ~ui_Pushed;\r
- if (draw)\r
- USL_DrawItem(item);\r
- }\r
- }\r
-}\r
-\r
-static void\r
-USL_NextItem(void)\r
-{\r
- if (topcard->items[topcard->cursor + 1].type == uii_Bad)\r
- return;\r
- USL_SelectItem(topcard,topcard->cursor + 1,true);\r
-}\r
-\r
-static void\r
-USL_PrevItem(void)\r
-{\r
- if (!topcard->cursor)\r
- return;\r
- USL_SelectItem(topcard,topcard->cursor - 1,true);\r
-}\r
-\r
-static void\r
-USL_SetupCard(void)\r
-{\r
- BottomS1 = "Arrows move";\r
- BottomS2 = "Enter selects";\r
- BottomS3 = cstackptr? "ESC to back out" : "ESC to quit";\r
-\r
- USL_SelectItem(topcard,topcard->cursor,false);\r
- USL_DrawCtlPanel(); // Contents?\r
-}\r
-\r
-static void\r
-USL_DownLevel(UserItemGroup far *group)\r
-{\r
- if (!group)\r
- Quit("USL_DownLevel() - nil card");\r
- USL_PushCard(group);\r
- if (group->custom && group->custom(uic_SetupCard,nil))\r
- USL_PopCard();\r
- USL_SetupCard();\r
-}\r
-\r
-static void\r
-USL_UpLevel(void)\r
-{\r
- if (!cstackptr)\r
- {\r
- USL_ConfirmComm(uc_Quit);\r
- return;\r
- }\r
-\r
- if (topcard->items)\r
- topcard->items[topcard->cursor].flags &= ~ui_Selected;\r
- USL_PopCard();\r
- USL_SetupCard();\r
-}\r
-\r
-static void\r
-USL_DoItem(void)\r
-{\r
- // DEBUG - finish this routine\r
- UserItem far *item;\r
-\r
- item = &topcard->items[topcard->cursor];\r
- if (item->flags & ui_Disabled)\r
- SD_PlaySound(NOWAYSND);\r
- else\r
- {\r
- switch (item->type)\r
- {\r
- case uii_Button:\r
- if (!(topcard->custom && topcard->custom(uic_Hit,item)))\r
- USL_ConfirmComm(item->comm);\r
- break;\r
- case uii_RadioButton:\r
- USL_PushItem(topcard,topcard->cursor,true);\r
- break;\r
- case uii_Folder:\r
- USL_DownLevel(item->child);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-static void\r
-USL_SetControlValues(void)\r
-{\r
- int sndindex;\r
-\r
- sndindex = SoundMode;\r
- if (sndindex == sdm_AdLib && QuietFX)\r
- sndindex++;\r
-\r
- USL_PushItem(&soundgroup,sndindex,false);\r
- USL_PushItem(&musicgroup,MusicMode,false);\r
- if (!AdLibPresent)\r
- {\r
- soundi[2].flags |= ui_Disabled; // AdLib sound effects\r
- soundi[3].flags |= ui_Disabled; // Quiet AdLib sound effects\r
- musici[1].flags |= ui_Disabled; // AdLib music\r
- }\r
-\r
-#ifdef CAT3D\r
- if (!JoysPresent[0])\r
- configi[3].flags |= ui_Disabled;\r
- if (!JoysPresent[1])\r
- configi[4].flags |= ui_Disabled;\r
-#else\r
- if (!JoysPresent[0])\r
- configi[4].flags |= ui_Disabled;\r
- if (!JoysPresent[1])\r
- configi[5].flags |= ui_Disabled;\r
- if (!JoysPresent[0] && !JoysPresent[1])\r
- configi[6].flags |= ui_Disabled;\r
-#endif\r
-\r
- rooti[4].text = ingame? "RETURN TO GAME" : "RETURN TO DEMO";\r
- if (!ingame)\r
- {\r
- rooti[2].flags |= ui_Disabled; // Save Game\r
- rooti[5].flags |= ui_Disabled; // End Game\r
- }\r
- rootgroup.cursor = ingame? 4 : 0;\r
- USL_SetOptionsText();\r
- // DEBUG - write the rest of this\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the\r
-// values of all the appropriate variables\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_SetUpCtlPanel(void)\r
-{\r
- int i;\r
-\r
- // Cache in all of the stuff for the control panel\r
- CA_UpLevel();\r
- for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)\r
- CA_MarkGrChunk(i);\r
- for (i = PADDLE_LUMP_START;i <= PADDLE_LUMP_END;i++)\r
- CA_MarkGrChunk(i);\r
- CA_MarkGrChunk(STARTFONT+1); // Little font\r
- CA_MarkGrChunk(CP_MENUMASKPICM); // Mask for dialogs\r
- CA_CacheMarks("Control Panel");\r
- CA_LoadAllSounds();\r
-\r
- // Do some other setup\r
- fontnumber = 1;\r
- US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);\r
- fontcolor = F_BLACK;\r
-#ifdef CAT3D\r
- VW_Bar (0,0,320,200,3); // CAT3D patch\r
-#else\r
- VW_ClearVideo(3);\r
-#endif\r
- RF_FixOfs();\r
- VW_InitDoubleBuffer();\r
-\r
- Communication = uc_None;\r
- USL_ClearFlags(&rootgroup);\r
- USL_SetControlValues();\r
- USL_SetupStack();\r
- USL_SetupCard();\r
-\r
- if (ingame)\r
- GameIsDirty = true;\r
-\r
- IN_ClearKeysDown();\r
-}\r
-\r
-static void\r
-USL_HandleComm(UComm comm)\r
-{\r
- switch (comm)\r
- {\r
- case uc_Loaded:\r
- case uc_Return:\r
- break;\r
- case uc_Abort:\r
- abortgame = true;\r
- break;\r
- case uc_Quit:\r
- QuitToDos = true;\r
- break;\r
- case uc_SEasy:\r
- restartgame = gd_Easy;\r
- break;\r
- case uc_SNormal:\r
- restartgame = gd_Normal;\r
- break;\r
- case uc_SHard:\r
- restartgame = gd_Hard;\r
- break;\r
-\r
- default:\r
- Quit("USL_HandleComm() - unknown");\r
- break;\r
- }\r
-}\r
-\r
-static void\r
-USL_GetControlValues(void)\r
-{\r
- int i;\r
-\r
- // DEBUG - write the rest of this\r
- i = USL_FindPushedItem(&soundgroup);\r
- if (i == 3)\r
- {\r
- QuietFX = true;\r
- i--;\r
- }\r
- else\r
- {\r
- QuietFX = false;\r
- }\r
- if (i != SoundMode)\r
- SD_SetSoundMode(i);\r
-\r
- i = USL_FindPushedItem(&musicgroup);\r
- if (i != MusicMode)\r
- SD_SetMusicMode(i);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_TearDownCtlPanel() - Given the state of the control panel, sets the\r
-// modes and values as appropriate\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_TearDownCtlPanel(void)\r
-{\r
- USL_GetControlValues();\r
- if (Communication)\r
- USL_HandleComm(Communication);\r
-\r
- fontnumber = 0; // Normal font\r
- fontcolor = F_BLACK;\r
- if (restartgame && USL_ResetGame)\r
- USL_ResetGame();\r
- else if (QuitToDos)\r
- {\r
- if (tedlevel)\r
- TEDDeath();\r
- else\r
- {\r
- US_CenterWindow(20,3);\r
- fontcolor = F_SECONDCOLOR;\r
- US_PrintCentered("Quitting...");\r
- fontcolor = F_BLACK;\r
- VW_UpdateScreen();\r
- Quit(nil);\r
- }\r
- }\r
-\r
- IN_ClearKeysDown();\r
- SD_WaitSoundDone();\r
-#ifdef CAT3D\r
- VW_Bar (0,0,320,200,3); // CAT3D patch\r
-#else\r
- VW_ClearVideo(3);\r
-#endif\r
- CA_DownLevel();\r
- CA_LoadAllSounds();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ControlPanel() - This is the main routine for the control panel\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#define MoveMin 40\r
-void\r
-US_ControlPanel(void)\r
-{\r
-extern void HelpScreens(void);\r
-\r
- boolean resetitem,on;\r
- word i;\r
- int ydelta;\r
- longword flashtime;\r
- UserItem far *item;\r
- CursorInfo cursorinfo;\r
-\r
-#if 0\r
- // DEBUG!!!\r
- {\r
- USL_SetUpCtlPanel();\r
- Communication = uc_Loaded;\r
- CtlPanelDone = true;\r
- loadedgame = true;\r
- USL_TearDownCtlPanel();\r
- return;\r
- }\r
-#endif\r
-\r
- if ((LastScan < sc_F1) || (LastScan > sc_F10))\r
- IN_ClearKeysDown();\r
-\r
- USL_SetUpCtlPanel();\r
- USL_DrawCtlPanel();\r
-\r
- ydelta = 0;\r
- for (CtlPanelDone = false,resetitem = on = true;!CtlPanelDone;)\r
- {\r
- item = &(topcard->items[topcard->cursor]);\r
-\r
- if (resetitem)\r
- {\r
- flashtime = TimeCount + (TickBase / 2);\r
- resetitem = false;\r
- }\r
-\r
- if (TimeCount >= flashtime)\r
- {\r
- on ^= true;\r
- resetitem = true;\r
- if (!on)\r
- item->flags &= ~ui_Selected;\r
- USL_DrawItemIcon(item);\r
- item->flags |= ui_Selected;\r
- }\r
-\r
- VW_UpdateScreen();\r
-\r
- if (LastScan)\r
- {\r
- switch (LastScan)\r
- {\r
- case sc_UpArrow:\r
- USL_PrevItem();\r
- resetitem = true;\r
- break;\r
- case sc_DownArrow:\r
- USL_NextItem();\r
- resetitem = true;\r
- break;\r
- case sc_Return:\r
- USL_DoItem();\r
- resetitem = true;\r
- break;\r
- case sc_Escape:\r
- USL_UpLevel();\r
- resetitem = true;\r
- break;\r
-#ifndef KEEN6\r
- case sc_F1:\r
- HelpScreens();\r
- USL_DrawCtlPanel();\r
- resetitem = true;\r
- break;\r
-#endif\r
- }\r
-\r
- if\r
- (\r
- (!resetitem)\r
- && (\r
- (LastScan == KbdDefs[0].button0)\r
- || (LastScan == KbdDefs[0].button1)\r
- )\r
- )\r
- {\r
- USL_DoItem();\r
- resetitem = true;\r
- }\r
-\r
- if (!resetitem)\r
- {\r
- for (item = topcard->items,i = 0;item->type != uii_Bad;item++,i++)\r
- {\r
- if (item->hotkey == LastScan)\r
- {\r
- USL_SelectItem(topcard,i,true);\r
- resetitem = true;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- IN_ClearKeysDown();\r
- }\r
- else\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- ydelta += cursorinfo.y;\r
- if (cursorinfo.button0)\r
- {\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- } while (cursorinfo.button0);\r
- USL_DoItem();\r
- resetitem = true;\r
- }\r
- else if (cursorinfo.button1)\r
- {\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- } while (cursorinfo.button1);\r
- USL_UpLevel();\r
- resetitem = true;\r
- }\r
- else if (ydelta < -MoveMin)\r
- {\r
- ydelta += MoveMin;\r
- USL_PrevItem();\r
- resetitem = true;\r
- }\r
- else if (ydelta > MoveMin)\r
- {\r
- ydelta -= MoveMin;\r
- USL_NextItem();\r
- resetitem = true;\r
- }\r
- }\r
- }\r
-\r
- USL_TearDownCtlPanel();\r
-}\r
-\r
-#ifdef KEEN6\r
-\r
-boolean US_ManualCheck(void)\r
-{\r
- typedef struct {\r
- char far *name;\r
- int shapenum;\r
- int x, y;\r
- } creatureinfo;\r
-\r
- static creatureinfo list[] = {\r
- {"BIP", BIPSHIPRSPR, -2, 0},\r
- {"BABOBBA", BABOBBAR1SPR, 0, 0},\r
- {"BLORB", BLORB1SPR, -2, 0},\r
- {"GIK", GIKWALKR1SPR, -1, 0},\r
- {"CEILICK", CEILICK1SPR, 0, 0},\r
- {"BLOOGLET", RBLOOGLETWALKR1SPR, -2, 0},\r
- {"BLOOGUARD", BLOOGUARDWALKL1SPR, -3, -1},\r
- {"FLECT", FLECTSTANDSPR, -1, 0},\r
- {"BOBBA", BOBBAR1SPR, -2, 0},\r
- {"NOSPIKE", NOSPIKESTANDSPR, -2, 0},\r
- {"ORBATRIX", ORBATRIXR1SPR, -2, 1},\r
- {"FLEEX", FLEEXWALKR1SPR, -2, 0}\r
- };\r
-\r
- boolean correct;\r
- char far *name;\r
- char c;\r
- char *ptr;\r
- unsigned spriteheight, spritewidth;\r
- int x, y;\r
- int editwidth;\r
- creatureinfo info;\r
- char strbuf[16];\r
-\r
- if (checkpassed)\r
- return true;\r
-\r
- correct = false;\r
- if (listindex == -1)\r
- {\r
- _AH = 0x2C; // get time\r
- geninterrupt(0x21);\r
- x = _CH; // store hours\r
- _AH = 0x2A; // get date\r
- geninterrupt(0x21);\r
- y = _DL; // store day\r
-\r
- listindex = (x + y) % (int)(sizeof(list)/sizeof(creatureinfo));\r
- }\r
-\r
- CA_UpLevel();\r
- info = list[listindex];\r
- name = info.name;\r
- CA_ClearMarks();\r
- CA_MarkGrChunk(info.shapenum);\r
- CA_CacheMarks(NULL);\r
-\r
- VWB_Bar(0, 0, 320, 200, BackColor);\r
- spritewidth = spritetable[info.shapenum - STARTSPRITES].width;\r
- spriteheight = spritetable[info.shapenum - STARTSPRITES].height;\r
- US_CenterWindow(30, (spriteheight+41)/8 + 1);\r
- PrintY = WindowY + 2;\r
- US_CPrint("What is the name of this creature?");\r
-\r
- x = WindowX + (WindowW-spritewidth)/2 + info.x*8;\r
- y = WindowY + 15;\r
- if (info.shapenum == CEILICK1SPR)\r
- {\r
- y++;\r
- }\r
- else\r
- {\r
- y += info.y * 8;\r
- }\r
- VWB_DrawSprite(x, y, info.shapenum);\r
-\r
- y = WindowY + WindowH - 16;\r
- editwidth = 100;\r
- x = WindowX + (WindowW - 100) / 2;\r
- VWB_Bar(x, y, editwidth, 14, BLACK);\r
- VWB_Bar(x+1, y+1, editwidth-2, 12, WHITE);\r
- x += 2;\r
- y += 2;\r
- editwidth -= 8;\r
- VW_UpdateScreen();\r
-\r
- if (US_LineInput(x, y, strbuf, NULL, true, sizeof(strbuf), editwidth))\r
- {\r
- ptr = strbuf;\r
- correct = true;\r
- while (*name)\r
- {\r
- c = *ptr;\r
- if ((islower(c)? _toupper(c) : c) != *name)\r
- {\r
- correct = false;\r
- }\r
-\r
- ptr++;\r
- name++;\r
- }\r
- if (*ptr)\r
- {\r
- correct = false;\r
- }\r
-\r
- if (!correct)\r
- {\r
- VWB_Bar(0, 0, 320, 200, BackColor);\r
- US_CenterWindow(35, 5);\r
- PrintY += 11;\r
- US_CPrint("Sorry, that's not quite right.");\r
- US_CPrint("Please check your manual and try again.");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- }\r
- }\r
-\r
- VWB_Bar(0, 0, 320, 200, BackColor);\r
- CA_DownLevel();\r
- checkpassed = correct;\r
- return correct;\r
-}\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-; Catacomb 3-D Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-IDEAL\r
-MODEL MEDIUM,C\r
-\r
-; Assembly portion of the User Mgr. This is just John Carmack's table\r
-; driven pseudo-random number generator, and we put it in the User Mgr\r
-; because we couldn't figure out where it should go\r
-\r
-\r
-;============================================================================\r
-;\r
-; RANDOM ROUTINES\r
-;\r
-;============================================================================\r
-\r
- FARDATA\r
-\r
-rndindex dw ?\r
-\r
-rndtable db 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66\r
- db 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36\r
- db 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188\r
- db 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224\r
- db 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242\r
- db 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0\r
- db 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235\r
- db 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113\r
- db 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75\r
- db 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196\r
- db 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113\r
- db 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241\r
- db 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224\r
- db 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95\r
- db 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226\r
- db 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36\r
- db 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106\r
- db 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136\r
- db 120, 163, 236, 249\r
-\r
-\r
- CODESEG\r
-\r
-LastRnd dw ?\r
-\r
-;=================================================\r
-;\r
-; void US_InitRndT (boolean randomize)\r
-; Init table based RND generator\r
-; if randomize is false, the counter is set to 0\r
-;\r
-;=================================================\r
-\r
-PROC US_InitRndT randomize:word\r
- uses si,di\r
- public US_InitRndT\r
-\r
- mov ax,SEG rndtable\r
- mov es,ax\r
- mov ax,[randomize]\r
- or ax,ax\r
- jne @@timeit ;if randomize is true, really random\r
-\r
- mov dx,0 ;set to a definite value\r
- jmp @@setit\r
-\r
-@@timeit:\r
- mov ah,2ch\r
- int 21h ;GetSystemTime\r
- and dx,0ffh\r
-\r
-@@setit:\r
- mov [es:rndindex],dx\r
- ret\r
-\r
-ENDP\r
-\r
-;=================================================\r
-;\r
-; int US_RndT (void)\r
-; Return a random # between 0-255\r
-; Exit : AX = value\r
-;\r
-;=================================================\r
-PROC US_RndT\r
- public US_RndT\r
-\r
- mov ax,SEG rndtable\r
- mov es,ax\r
- mov bx,[es:rndindex]\r
- inc bx\r
- and bx,0ffh\r
- mov [es:rndindex],bx\r
- mov al,[es:rndtable+BX]\r
- xor ah,ah\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-END\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_VW.C\r
-\r
-#include "ID_HEADS.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define VIEWWIDTH 40\r
-\r
-#define PIXTOBLOCK 4 // 16 pixels to an update block\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-cardtype videocard; // set by VW_Startup\r
-grtype grmode; // CGAgr, EGAgr, VGAgr\r
-\r
-unsigned bufferofs; // hidden area to draw to before displaying\r
-unsigned displayofs; // origin of the visable screen\r
-unsigned panx,pany; // panning adjustments inside port in pixels\r
-unsigned pansx,pansy; // panning adjustments inside port in screen\r
- // block limited pixel values (ie 0/8 for ega x)\r
-unsigned panadjust; // panx/pany adjusted by screen resolution\r
-\r
-unsigned screenseg; // normally 0xa000 / 0xb800\r
-unsigned linewidth;\r
-unsigned ylookup[VIRTUALHEIGHT];\r
-\r
-unsigned fontnumber; // 0 based font number for drawing\r
-\r
-boolean screenfaded;\r
-\r
-pictabletype _seg *pictable;\r
-pictabletype _seg *picmtable;\r
-spritetabletype _seg *spritetable;\r
-\r
-int bordercolor;\r
-boolean nopan;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void VWL_MeasureString (char far *string, word *width, word *height,\r
- fontstruct _seg *font);\r
-void VWL_DrawCursor (void);\r
-void VWL_EraseCursor (void);\r
-void VWL_DBSetup (void);\r
-void VWL_UpdateScreenBlocks (void);\r
-\r
-\r
-int bordercolor;\r
-int cursorvisible;\r
-int cursornumber,cursorwidth,cursorheight,cursorx,cursory;\r
-memptr cursorsave;\r
-unsigned cursorspot;\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_Startup\r
-=\r
-=======================\r
-*/\r
-\r
-static char *ParmStrings[] = {"HIDDENCARD","NOPAN",""};\r
-\r
-void VW_Startup (void)\r
-{\r
- int i,n;\r
-\r
- asm cld;\r
-\r
- videocard = 0;\r
-\r
- for (i = 1;i < _argc;i++)\r
- {\r
- n = US_CheckParm(_argv[i],ParmStrings);\r
- if (n == 0)\r
- {\r
- videocard = EGAcard;\r
- }\r
- else if (n == 1)\r
- {\r
- nopan = true;\r
- }\r
- }\r
-\r
- if (!videocard)\r
- videocard = VW_VideoID ();\r
-\r
-#if GRMODE == EGAGR\r
- grmode = EGAGR;\r
- if (videocard != EGAcard && videocard != VGAcard)\r
-#ifdef KEEN\r
-Quit ("Improper video card! If you really have an EGA/VGA card that I am not\n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#else\r
-Quit ("Improper video card! If you really have an EGA/VGA card that I am not \n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#endif\r
- EGAWRITEMODE(0);\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- grmode = CGAGR;\r
- if (videocard < CGAcard || videocard > VGAcard)\r
-#ifdef KEEN\r
-Quit ("Improper video card! If you really have a CGA card that I am not\n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#else\r
-Quit ("Improper video card! If you really have a CGA card that I am not \n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
-#endif\r
- MM_GetPtr (&(memptr)screenseg,0x10000l); // grab 64k for floating screen\r
-#endif\r
-\r
- cursorvisible = 0;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_Shutdown\r
-=\r
-=======================\r
-*/\r
-\r
-void VW_Shutdown (void)\r
-{\r
- VW_SetScreenMode (TEXTGR);\r
-#if GRMODE == EGAGR\r
- VW_SetLineWidth (80);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-========================\r
-=\r
-= VW_SetScreenMode\r
-= Call BIOS to set TEXT / CGAgr / EGAgr / VGAgr\r
-=\r
-========================\r
-*/\r
-\r
-void VW_SetScreenMode (int grmode)\r
-{\r
- switch (grmode)\r
- {\r
- case TEXTGR: _AX = 3;\r
- geninterrupt (0x10);\r
-#ifdef CAT3D\r
- screenseg=0xb000;\r
-#endif\r
- break;\r
- case CGAGR: _AX = 4;\r
- geninterrupt (0x10); // screenseg is actually a main mem buffer\r
- break;\r
- case EGAGR: _AX = 0xd;\r
- geninterrupt (0x10);\r
- screenseg=0xa000;\r
- break;\r
-#ifdef VGAGAME\r
- case VGAGR:{\r
- char extern VGAPAL; // deluxepaint vga pallet .OBJ file\r
- void far *vgapal = &VGAPAL;\r
- SetCool256 (); // custom 256 color mode\r
- screenseg=0xa000;\r
- _ES = FP_SEG(vgapal);\r
- _DX = FP_OFF(vgapal);\r
- _BX = 0;\r
- _CX = 0x100;\r
- _AX = 0x1012;\r
- geninterrupt(0x10); // set the deluxepaint pallet\r
-\r
- break;\r
-#endif\r
- }\r
- VW_SetLineWidth(SCREENWIDTH);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SCREEN FADES\r
-\r
-=============================================================================\r
-*/\r
-\r
-char colors[7][17]=\r
-{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},\r
- {0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,0},\r
- {0,0,0,0,0,0,0,0,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},\r
- {0,1,2,3,4,5,6,7,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},\r
- {0,1,2,3,4,5,6,7,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0},\r
- {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}};\r
-\r
-\r
-void VW_ColorBorder (int color)\r
-{\r
- _AH=0x10;\r
- _AL=1;\r
- _BH=color;\r
- geninterrupt (0x10);\r
- bordercolor = color;\r
-}\r
-\r
-void VW_SetPalette(byte *palette)\r
-{\r
- byte p;\r
- word i;\r
-\r
- for (i = 0;i < 15;i++)\r
- {\r
- p = palette[i];\r
- colors[0][i] = 0;\r
- colors[1][i] = (p > 0x10)? (p & 0x0f) : 0;\r
- colors[2][i] = (p > 0x10)? p : 0;\r
- colors[3][i] = p;\r
- colors[4][i] = (p > 0x10)? 0x1f : p;\r
- colors[5][i] = 0x1f;\r
- }\r
-}\r
-\r
-void VW_SetDefaultColors(void)\r
-{\r
-#if GRMODE == EGAGR\r
- colors[3][16] = bordercolor;\r
- _ES=FP_SEG(&colors[3]);\r
- _DX=FP_OFF(&colors[3]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-\r
-void VW_FadeOut(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=3;i>=0;i--)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = true;\r
-#endif\r
-}\r
-\r
-\r
-void VW_FadeIn(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=0;i<4;i++)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-void VW_FadeUp(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=3;i<6;i++)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = true;\r
-#endif\r
-}\r
-\r
-void VW_FadeDown(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=5;i>2;i--)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= VW_SetAtrReg\r
-=\r
-= Sets an attribute (pallete / border) register\r
-= Does NOT vsync!\r
-=\r
-========================\r
-*/\r
-\r
-void VW_SetAtrReg (int reg, int value)\r
-{\r
- asm cli\r
- asm mov dx,STATUS_REGISTER_1\r
- asm in al,dx\r
- asm mov dx,ATR_INDEX\r
-\r
- asm mov al,BYTE PTR [reg]\r
- asm out dx,al\r
- asm mov al,BYTE PTR [value]\r
- asm out dx,al\r
- asm mov dx,0x3da\r
- asm in al,dx\r
- asm mov dx,ATR_INDEX\r
- asm mov al,0x20\r
- asm out dx,al\r
- asm sti\r
-}\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetLineWidth\r
-=\r
-= Must be an even number of bytes\r
-=\r
-====================\r
-*/\r
-\r
-void VW_SetLineWidth (int width)\r
-{\r
- int i,offset;\r
-\r
-#if GRMODE == EGAGR\r
-//\r
-// set wide virtual screen\r
-//\r
-asm mov dx,CRTC_INDEX\r
-asm mov al,CRTC_OFFSET\r
-asm mov ah,[BYTE PTR width]\r
-asm shr ah,1\r
-asm out dx,ax\r
-#endif\r
-\r
-//\r
-// set up lookup tables\r
-//\r
- linewidth = width;\r
-\r
- offset = 0;\r
-\r
- for (i=0;i<VIRTUALHEIGHT;i++)\r
- {\r
- ylookup[i]=offset;\r
- offset += width;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetSplitScreen\r
-=\r
-====================\r
-*/\r
-#ifdef CAT3D\r
-void VW_SetSplitScreen (int linenum)\r
-{\r
- VW_WaitVBL (1);\r
- if (videocard==VGAcard)\r
- linenum=linenum*2-1;\r
- outportb (CRTC_INDEX,CRTC_LINECOMPARE);\r
- outportb (CRTC_INDEX+1,linenum % 256);\r
- outportb (CRTC_INDEX,CRTC_OVERFLOW);\r
- outportb (CRTC_INDEX+1, 1+16*(linenum/256));\r
- if (videocard==VGAcard)\r
- {\r
- outportb (CRTC_INDEX,CRTC_MAXSCANLINE);\r
- outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));\r
- }\r
-}\r
-#endif\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_ClearVideo\r
-=\r
-====================\r
-*/\r
-\r
-void VW_ClearVideo (int color)\r
-{\r
-#if GRMODE == EGAGR\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- color = (color << 8) & color; //BUG: color is always 0 after this\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- color = (color << 12) & (color << 8) & (color << 4) & color; //BUG: color is always 0 after this\r
-#endif\r
-\r
- VW_WaitVBL(1);\r
-\r
-asm mov es, screenseg;\r
-asm mov di, displayofs;\r
-asm and di, not 1;\r
-asm mov cx, 8000h;\r
-asm mov ax, color;\r
-asm rep stosw;\r
-\r
-#if GRMODE == EGAGR\r
- EGAWRITEMODE(0);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if NUMPICS>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawPic\r
-=\r
-= X in bytes, y in pixels, chunknum is the #defined picnum\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICS;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = pictable[picnum].width;\r
- height = pictable[picnum].height;\r
-\r
- VW_MemToScreen(source,dest,width,height);\r
-}\r
-\r
-\r
-#endif\r
-\r
-#if NUMPICM>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawMPic\r
-=\r
-= X in bytes, y in pixels, chunknum is the #defined picnum\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
-\r
- VW_MaskBlock(source,0,dest,width,height,width*height);\r
-}\r
-\r
-void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,ofs,plane;\r
- int height;\r
-\r
- source = grsegs[chunknum];\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
- plane = width*height;\r
-\r
- ofs = 0;\r
- if (y<0)\r
- {\r
- ofs= -y*width;\r
- height+=y;\r
- y=0;\r
- }\r
- else if (y+height>216)\r
- {\r
- height-=(y-216);\r
- }\r
- dest = ylookup[y]+x+bufferofs;\r
- if (height<1)\r
- return;\r
-\r
- VW_MaskBlock(source,ofs,dest,width,height,plane);\r
-}\r
-\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-#if NUMSPRITES>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawSprite\r
-=\r
-= X and Y in pixels, it will match the closest shift possible\r
-=\r
-= To do:\r
-= Add vertical clipping!\r
-= Make the shifts act as center points, rather than break points\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawSprite(int x, int y, unsigned chunknum)\r
-{\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned dest,shift;\r
-\r
- spr = &spritetable[chunknum-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[chunknum];\r
-\r
- y+=spr->orgy>>G_P_SHIFT;\r
- x+=spr->orgx>>G_P_SHIFT;\r
-\r
-#if GRMODE == EGAGR\r
- shift = (x&7)/2;\r
-#endif\r
-#if GRMODE == CGAGR\r
- shift = 0;\r
-#endif\r
-\r
- dest = bufferofs + ylookup[y];\r
- if (x>=0)\r
- dest += x/SCREENXDIV;\r
- else\r
- dest += (x+1)/SCREENXDIV;\r
-\r
- VW_MaskBlock (block,block->sourceoffset[shift],dest,\r
- block->width[shift],spr->height,block->planesize[shift]);\r
-}\r
-\r
-#endif\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= VW_Hlin\r
-=\r
-==================\r
-*/\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-unsigned char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1};\r
-unsigned char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};\r
-\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)\r
-{\r
- unsigned dest,xlb,xhb,maskleft,maskright,mid;\r
-\r
- xlb=xl/8;\r
- xhb=xh/8;\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- maskleft = leftmask[xl&7];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
-\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_BITMASK\r
- asm mov ah,[BYTE PTR maskleft]\r
- asm out dx,ax // mask off pixels\r
-\r
- asm mov al,[BYTE PTR color]\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
- goto done;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov dx,GC_INDEX\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskleft]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm mov bl,[es:di] // load latches\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskright]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm xchg bh,[es:di] // load latches and write pixels\r
-\r
-done:\r
- EGABITMASK(255);\r
- EGAWRITEMODE(0);\r
-}\r
-#endif\r
-\r
-\r
-#if GRMODE == CGAGR\r
-\r
-unsigned char pixmask[4] = {0xc0,0x30,0x0c,0x03};\r
-unsigned char leftmask[4] = {0xff,0x3f,0x0f,0x03};\r
-unsigned char rightmask[4] = {0xc0,0xf0,0xfc,0xff};\r
-unsigned char colorbyte[4] = {0,0x55,0xaa,0xff};\r
-\r
-//\r
-// could be optimized for rep stosw\r
-//\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)\r
-{\r
- unsigned dest,xlb,xhb,mid;\r
- byte maskleft,maskright;\r
-\r
- color = colorbyte[color]; // expand 2 color bits to 8\r
-\r
- xlb=xl/4;\r
- xhb=xh/4;\r
-\r
- maskleft = leftmask[xl&3];\r
- maskright = rightmask[xh&3];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-asm mov es,[screenseg]\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
- maskleft&=maskright;\r
-\r
- asm mov ah,[maskleft]\r
- asm mov bl,[BYTE PTR color]\r
- asm and bl,[maskleft]\r
- asm not ah\r
-\r
- asm mov di,[dest]\r
-\r
- asm mov al,[es:di]\r
- asm and al,ah // mask out pixels\r
- asm or al,bl // or in color\r
- asm mov [es:di],al\r
- return;\r
- }\r
-\r
-asm mov di,[dest]\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov ah,[maskleft]\r
-asm mov bl,bh\r
-asm and bl,[maskleft]\r
-asm not ah\r
-asm mov al,[es:di]\r
-asm and al,ah // mask out pixels\r
-asm or al,bl // or in color\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov ah,[maskright]\r
-asm mov bl,bh\r
-asm and bl,[maskright]\r
-asm not ah\r
-asm mov al,[es:di]\r
-asm and al,ah // mask out pixels\r
-asm or al,bl // or in color\r
-asm stosb\r
-}\r
-#endif\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= VW_Bar\r
-=\r
-= Pixel addressable block fill routine\r
-=\r
-==================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color)\r
-{\r
- unsigned xh = x+width-1;\r
-\r
- while (height--)\r
- VW_Hlin (x,xh,y++,color);\r
-}\r
-\r
-#endif\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color)\r
-{\r
- unsigned dest,xh,xlb,xhb,maskleft,maskright,mid;\r
-\r
- xh = x+width-1;\r
- xlb=x/8;\r
- xhb=xh/8;\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- maskleft = leftmask[x&7];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
-\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_BITMASK\r
- asm mov ah,[BYTE PTR maskleft]\r
- asm out dx,ax // mask off pixels\r
-\r
- asm mov ah,[BYTE PTR color]\r
- asm mov dx,[linewidth]\r
-yloop1:\r
- asm mov al,ah\r
- asm xchg al,[es:di] // load latches and write pixels\r
- asm add di,dx // down to next line\r
- asm dec [height]\r
- asm jnz yloop1\r
-\r
- goto done;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov bh,[BYTE PTR color]\r
-asm mov dx,GC_INDEX\r
-asm mov si,[linewidth]\r
-asm sub si,[mid] // add to di at end of line to get to next scan\r
-asm dec si\r
-\r
-//\r
-// draw left side\r
-//\r
-yloop2:\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskleft]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm mov bl,[es:di] // load latches\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskright]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm xchg al,[es:di] // load latches and write pixels\r
-\r
-asm add di,si // move to start of next line\r
-asm dec [height]\r
-asm jnz yloop2\r
-\r
-done:\r
- EGABITMASK(255);\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= VW_MeasureString\r
-=\r
-==================\r
-*/\r
-\r
-#if NUMFONT+NUMFONTM>0\r
-void\r
-VWL_MeasureString (char far *string, word *width, word *height, fontstruct _seg *font)\r
-{\r
- *height = font->height;\r
- for (*width = 0;*string;string++)\r
- *width += font->width[*((byte far *)string)]; // proportional width\r
-}\r
-\r
-void VW_MeasurePropString (char far *string, word *width, word *height)\r
-{\r
- VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONT+fontnumber]);\r
-}\r
-\r
-void VW_MeasureMPropString (char far *string, word *width, word *height)\r
-{\r
- VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONTM+fontnumber]);\r
-}\r
-\r
-\r
-#endif\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- CGA stuff\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define CGACRTCWIDTH 40\r
-\r
-/*\r
-==========================\r
-=\r
-= VW_CGAFullUpdate\r
-=\r
-==========================\r
-*/\r
-\r
-void VW_CGAFullUpdate (void)\r
-{\r
- byte *update;\r
- boolean halftile;\r
- unsigned x,y,middlerows,middlecollumns;\r
-\r
- displayofs = bufferofs+panadjust;\r
-\r
-asm mov ax,0xb800\r
-asm mov es,ax\r
-\r
-asm mov si,[displayofs]\r
-asm xor di,di\r
-\r
-asm mov bx,100 // pairs of scan lines to copy\r
-asm mov dx,[linewidth]\r
-asm sub dx,80\r
-\r
-asm mov ds,[screenseg]\r
-asm test si,1\r
-asm jz evenblock\r
-\r
-//\r
-// odd source\r
-//\r
-asm mov ax,39 // words accross screen\r
-copytwolineso:\r
-asm movsb\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm movsb\r
-asm add si,dx\r
-asm add di,0x2000-80 // go to the interlaced bank\r
-asm movsb\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm movsb\r
-asm add si,dx\r
-asm sub di,0x2000 // go to the non interlaced bank\r
-\r
-asm dec bx\r
-asm jnz copytwolineso\r
-asm jmp blitdone\r
-\r
-//\r
-// even source\r
-//\r
-evenblock:\r
-asm mov ax,40 // words accross screen\r
-copytwolines:\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm add si,dx\r
-asm add di,0x2000-80 // go to the interlaced bank\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm add si,dx\r
-asm sub di,0x2000 // go to the non interlaced bank\r
-\r
-asm dec bx\r
-asm jnz copytwolines\r
-\r
-blitdone:\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-asm mov es,ax\r
-\r
-asm xor ax,ax // clear out the update matrix\r
-asm mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-\r
-asm mov di,[baseupdateptr]\r
-asm rep stosw\r
-\r
- updateptr = baseupdateptr;\r
- *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;\r
-}\r
-\r
-\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- CURSOR ROUTINES\r
-\r
-These only work in the context of the double buffered update routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-====================\r
-=\r
-= VWL_DrawCursor\r
-=\r
-= Background saves, then draws the cursor at cursorspot\r
-=\r
-====================\r
-*/\r
-\r
-void VWL_DrawCursor (void)\r
-{\r
- cursorspot = bufferofs + ylookup[cursory+pansy]+(cursorx+pansx)/SCREENXDIV;\r
- VW_ScreenToMem(cursorspot,cursorsave,cursorwidth,cursorheight);\r
- VWB_DrawSprite(cursorx,cursory,cursornumber);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VWL_EraseCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VWL_EraseCursor (void)\r
-{\r
- VW_MemToScreen(cursorsave,cursorspot,cursorwidth,cursorheight);\r
- VW_MarkUpdateBlock ((cursorx+pansx)&SCREENXMASK,cursory+pansy,\r
- ( (cursorx+pansx)&SCREENXMASK)+cursorwidth*SCREENXDIV-1,\r
- cursory+pansy+cursorheight-1);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VW_ShowCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VW_ShowCursor (void)\r
-{\r
- cursorvisible++;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_HideCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VW_HideCursor (void)\r
-{\r
- cursorvisible--;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_MoveCursor\r
-=\r
-====================\r
-*/\r
-#define MAXCURSORX (319-24)\r
-#define MAXCURSORY (199-24)\r
-\r
-void VW_MoveCursor (int x, int y)\r
-{\r
-#ifdef CAT3D\r
- if (x>MAXCURSORX)\r
- x=MAXCURSORX;\r
- if (y>MAXCURSORY)\r
- y=MAXCURSORY; // catacombs hack to keep cursor on screen\r
-#endif\r
-\r
- cursorx = x;\r
- cursory = y;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetCursor\r
-=\r
-= Load in a sprite to be used as a cursor, and allocate background save space\r
-=\r
-====================\r
-*/\r
-\r
-void VW_SetCursor (int spritenum)\r
-{\r
- VW_FreeCursor ();\r
-\r
- cursornumber = spritenum;\r
-\r
- CA_CacheGrChunk (spritenum);\r
- MM_SetLock (&grsegs[spritenum],true);\r
-\r
- cursorwidth = spritetable[spritenum-STARTSPRITES].width+1;\r
- cursorheight = spritetable[spritenum-STARTSPRITES].height;\r
-\r
- MM_GetPtr (&cursorsave,cursorwidth*cursorheight*5);\r
- MM_SetLock (&cursorsave,true);\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VW_FreeCursor\r
-=\r
-= Frees the memory used by the cursor and its background save\r
-=\r
-====================\r
-*/\r
-\r
-void VW_FreeCursor (void)\r
-{\r
- if (cursornumber)\r
- {\r
- MM_SetLock (&grsegs[cursornumber],false);\r
- MM_SetPurge (&grsegs[cursornumber],3);\r
- MM_SetLock (&cursorsave,false);\r
- MM_FreePtr (&cursorsave);\r
- cursornumber = 0;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- Double buffer management routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-======================\r
-=\r
-= VW_InitDoubleBuffer\r
-=\r
-======================\r
-*/\r
-\r
-void VW_InitDoubleBuffer (void)\r
-{\r
-#if GRMODE == EGAGR\r
- VW_SetScreen (displayofs+panadjust,0); // no pel pan\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= VW_FixRefreshBuffer\r
-=\r
-= Copies the view page to the buffer page on page flipped refreshes to\r
-= avoid a one frame shear around pop up windows\r
-=\r
-======================\r
-*/\r
-\r
-void VW_FixRefreshBuffer (void)\r
-{\r
-#if GRMODE == EGAGR\r
- VW_ScreenToScreen (displayofs,bufferofs,PORTTILESWIDE*4*CHARWIDTH,\r
- (PORTTILESHIGH-1)*16);\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= VW_QuitDoubleBuffer\r
-=\r
-======================\r
-*/\r
-\r
-void VW_QuitDoubleBuffer (void)\r
-{\r
-}\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_MarkUpdateBlock\r
-=\r
-= Takes a pixel bounded block and marks the tiles in bufferblocks\r
-= Returns 0 if the entire block is off the buffer screen\r
-=\r
-=======================\r
-*/\r
-\r
-int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2)\r
-{\r
- int x,y,xt1,yt1,xt2,yt2,nextline;\r
- byte *mark;\r
-\r
- xt1 = x1>>PIXTOBLOCK;\r
- yt1 = y1>>PIXTOBLOCK;\r
-\r
- xt2 = x2>>PIXTOBLOCK;\r
- yt2 = y2>>PIXTOBLOCK;\r
-\r
- if (xt1<0)\r
- xt1=0;\r
- else if (xt1>=UPDATEWIDE-1)\r
- return 0;\r
-\r
- if (yt1<0)\r
- yt1=0;\r
- else if (yt1>UPDATEHIGH)\r
- return 0;\r
-\r
- if (xt2<0)\r
- return 0;\r
- else if (xt2>=UPDATEWIDE-1)\r
- xt2 = UPDATEWIDE-2;\r
-\r
- if (yt2<0)\r
- return 0;\r
- else if (yt2>=UPDATEHIGH)\r
- yt2 = UPDATEHIGH-1;\r
-\r
- mark = updateptr + uwidthtable[yt1] + xt1;\r
- nextline = UPDATEWIDE - (xt2-xt1) - 1;\r
-\r
- for (y=yt1;y<=yt2;y++)\r
- {\r
- for (x=xt1;x<=xt2;x++)\r
- *mark++ = 1; // this tile will need to be updated\r
-\r
- mark += nextline;\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-\r
-/*\r
-===========================\r
-=\r
-= VW_UpdateScreen\r
-=\r
-= Updates any changed areas of the double buffer and displays the cursor\r
-=\r
-===========================\r
-*/\r
-\r
-void VW_UpdateScreen (void)\r
-{\r
- if (cursorvisible>0)\r
- VWL_DrawCursor();\r
-\r
-#if GRMODE == EGAGR\r
- VWL_UpdateScreenBlocks();\r
-#endif\r
-#if GRMODE == CGAGR\r
- VW_CGAFullUpdate();\r
-#endif\r
-\r
- if (cursorvisible>0)\r
- VWL_EraseCursor();\r
-}\r
-\r
-\r
-\r
-void VWB_DrawTile8 (int x, int y, int tile)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7))\r
- VW_DrawTile8 (x/SCREENXDIV,y,tile);\r
-}\r
-\r
-void VWB_DrawTile8M (int x, int y, int tile)\r
-{\r
- int xb;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- xb = x/SCREENXDIV; // use intermediate because VW_DT8M is macro\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7))\r
- VW_DrawTile8M (xb,y,tile);\r
-}\r
-\r
-void VWB_DrawTile16 (int x, int y, int tile)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))\r
- VW_DrawTile16 (x/SCREENXDIV,y,tile);\r
-}\r
-\r
-void VWB_DrawTile16M (int x, int y, int tile)\r
-{\r
- int xb;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- xb = x/SCREENXDIV; // use intermediate because VW_DT16M is macro\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))\r
- VW_DrawTile16M (xb,y,tile);\r
-}\r
-\r
-#if NUMPICS\r
-void VWB_DrawPic (int x, int y, int chunknum)\r
-{\r
-// mostly copied from drawpic\r
- int picnum = chunknum - STARTPICS;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- x/= SCREENXDIV;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = pictable[picnum].width;\r
- height = pictable[picnum].height;\r
-\r
- if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))\r
- VW_MemToScreen(source,dest,width,height);\r
-}\r
-#endif\r
-\r
-#if NUMPICM>0\r
-void VWB_DrawMPic(int x, int y, int chunknum)\r
-{\r
-// mostly copied from drawmpic\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- x/=SCREENXDIV;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
-\r
- if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))\r
- VW_MaskBlock(source,0,dest,width,height,width*height);\r
-}\r
-#endif\r
-\r
-\r
-void VWB_Bar (int x, int y, int width, int height, int color)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x,y,x+width,y+height-1) )\r
- VW_Bar (x,y,width,height,color);\r
-}\r
-\r
-\r
-#if NUMFONT\r
-void VWB_DrawPropString (char far *string)\r
-{\r
- int x,y;\r
- x = px+pansx;\r
- y = py+pansy;\r
- VW_DrawPropString (string);\r
- VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);\r
-}\r
-#endif\r
-\r
-\r
-#if NUMFONTM\r
-void VWB_DrawMPropString (char far *string)\r
-{\r
- int x,y;\r
- x = px+pansx;\r
- y = py+pansy;\r
- VW_DrawMPropString (string);\r
- VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);\r
-}\r
-#endif\r
-\r
-#if NUMSPRITES\r
-void VWB_DrawSprite(int x, int y, int chunknum)\r
-{\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned dest,shift,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
-\r
- spr = &spritetable[chunknum-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[chunknum];\r
-\r
- y+=spr->orgy>>G_P_SHIFT;\r
- x+=spr->orgx>>G_P_SHIFT;\r
-\r
-\r
-#if GRMODE == EGAGR\r
- shift = (x&7)/2;\r
-#endif\r
-#if GRMODE == CGAGR\r
- shift = 0;\r
-#endif\r
-\r
- dest = bufferofs + ylookup[y];\r
- if (x>=0)\r
- dest += x/SCREENXDIV;\r
- else\r
- dest += (x+1)/SCREENXDIV;\r
-\r
- width = block->width[shift];\r
- height = spr->height;\r
-\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+width*SCREENXDIV-1\r
- ,y+height-1))\r
- VW_MaskBlock (block,block->sourceoffset[shift],dest,\r
- width,height,block->planesize[shift]);\r
-}\r
-#endif\r
-\r
-void VWB_Plot (int x, int y, int color)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x,y,x,y))\r
- VW_Plot(x,y,color);\r
-}\r
-\r
-void VWB_Hlin (int x1, int x2, int y, int color)\r
-{\r
- x1+=pansx;\r
- x2+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x1,y,x2,y))\r
- VW_Hlin(x1,x2,y,color);\r
-}\r
-\r
-void VWB_Vlin (int y1, int y2, int x, int color)\r
-{\r
- x+=pansx;\r
- y1+=pansy;\r
- y2+=pansy;\r
- if (VW_MarkUpdateBlock (x,y1,x,y2))\r
- VW_Vlin(y1,y2,x,color);\r
-}\r
-\r
-\r
-//===========================================================================\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_VW.H\r
-\r
-#ifndef __TYPES__\r
-#include "ID_TYPES.H"\r
-#endif\r
-\r
-#ifndef __ID_MM__\r
-#include "ID_MM.H"\r
-#endif\r
-\r
-#ifndef __ID_GLOB__\r
-#include "ID_GLOB.H"\r
-#endif\r
-\r
-#define __ID_VW__\r
-\r
-//===========================================================================\r
-\r
-#define G_P_SHIFT 4 // global >> ?? = pixels\r
-\r
-#if GRMODE == EGAGR\r
-#ifdef CAT3D\r
-#define SCREENWIDTH 40\r
-#else\r
-#define SCREENWIDTH 64\r
-#endif\r
-#define CHARWIDTH 1\r
-#define TILEWIDTH 2\r
-#define GRPLANES 4\r
-#define BYTEPIXELS 8\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-#define SCREENWIDTH 128\r
-#define CHARWIDTH 2\r
-#define TILEWIDTH 4\r
-#define GRPLANES 1\r
-#define BYTEPIXELS 4\r
-#endif\r
-\r
-#define VIRTUALHEIGHT 300\r
-#define VIRTUALWIDTH 512\r
-\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define MAXSHIFTS 1\r
-\r
-#define WHITE 3 // graphics mode independant colors\r
-#define BLACK 0\r
-#define FIRSTCOLOR 1\r
-#define SECONDCOLOR 2\r
-#define F_WHITE 0 // for XOR font drawing\r
-#define F_BLACK 3\r
-#define F_FIRSTCOLOR 2\r
-#define F_SECONDCOLOR 1\r
-\r
-#endif\r
-\r
-#if GRMODE == EGAGR\r
-\r
-#define MAXSHIFTS 4\r
-\r
-#define WHITE 15 // graphics mode independant colors\r
-#define BLACK 0\r
-#define FIRSTCOLOR 1\r
-#define SECONDCOLOR 12\r
-#define F_WHITE 0 // for XOR font drawing\r
-#define F_BLACK 15\r
-#define F_FIRSTCOLOR 14\r
-#define F_SECONDCOLOR 3\r
-\r
-#endif\r
-\r
-#if GRMODE == EGAGR\r
-#define SCREENXMASK (~7)\r
-#define SCREENXPLUS (7)\r
-#define SCREENXDIV (8)\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-#define SCREENXMASK (~3)\r
-#define SCREENXDIV (4)\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-\r
-#define SC_INDEX 0x3C4\r
-#define SC_RESET 0\r
-#define SC_CLOCK 1\r
-#define SC_MAPMASK 2\r
-#define SC_CHARMAP 3\r
-#define SC_MEMMODE 4\r
-\r
-#define CRTC_INDEX 0x3D4\r
-#define CRTC_H_TOTAL 0\r
-#define CRTC_H_DISPEND 1\r
-#define CRTC_H_BLANK 2\r
-#define CRTC_H_ENDBLANK 3\r
-#define CRTC_H_RETRACE 4\r
-#define CRTC_H_ENDRETRACE 5\r
-#define CRTC_V_TOTAL 6\r
-#define CRTC_OVERFLOW 7\r
-#define CRTC_ROWSCAN 8\r
-#define CRTC_MAXSCANLINE 9\r
-#define CRTC_CURSORSTART 10\r
-#define CRTC_CURSOREND 11\r
-#define CRTC_STARTHIGH 12\r
-#define CRTC_STARTLOW 13\r
-#define CRTC_CURSORHIGH 14\r
-#define CRTC_CURSORLOW 15\r
-#define CRTC_V_RETRACE 16\r
-#define CRTC_V_ENDRETRACE 17\r
-#define CRTC_V_DISPEND 18\r
-#define CRTC_OFFSET 19\r
-#define CRTC_UNDERLINE 20\r
-#define CRTC_V_BLANK 21\r
-#define CRTC_V_ENDBLANK 22\r
-#define CRTC_MODE 23\r
-#define CRTC_LINECOMPARE 24\r
-\r
-\r
-#define GC_INDEX 0x3CE\r
-#define GC_SETRESET 0\r
-#define GC_ENABLESETRESET 1\r
-#define GC_COLORCOMPARE 2\r
-#define GC_DATAROTATE 3\r
-#define GC_READMAP 4\r
-#define GC_MODE 5\r
-#define GC_MISCELLANEOUS 6\r
-#define GC_COLORDONTCARE 7\r
-#define GC_BITMASK 8\r
-\r
-#define ATR_INDEX 0x3c0\r
-#define ATR_MODE 16\r
-#define ATR_OVERSCAN 17\r
-#define ATR_COLORPLANEENABLE 18\r
-#define ATR_PELPAN 19\r
-#define ATR_COLORSELECT 20\r
-\r
-#define STATUS_REGISTER_1 0x3da\r
-\r
-//===========================================================================\r
-\r
-typedef enum {NOcard,MDAcard,CGAcard,EGAcard,MCGAcard,VGAcard,\r
- HGCcard=0x80,HGCPcard,HICcard} cardtype;\r
-\r
-typedef struct\r
-{\r
- int width,\r
- height,\r
- orgx,orgy,\r
- xl,yl,xh,yh,\r
- shifts;\r
-} spritetabletype;\r
-\r
-typedef struct\r
-{\r
- unsigned sourceoffset[MAXSHIFTS];\r
- unsigned planesize[MAXSHIFTS];\r
- unsigned width[MAXSHIFTS];\r
- byte data[];\r
-} spritetype; // the memptr for each sprite points to this\r
-\r
-typedef struct\r
-{\r
- int width,height;\r
-} pictabletype;\r
-\r
-\r
-typedef struct\r
-{\r
- int height;\r
- int location[256];\r
- char width[256];\r
-} fontstruct;\r
-\r
-\r
-typedef enum {CGAgr,EGAgr,VGAgr} grtype;\r
-\r
-//===========================================================================\r
-\r
-extern cardtype videocard; // set by VW_Startup\r
-extern grtype grmode; // CGAgr, EGAgr, VGAgr\r
-\r
-extern unsigned bufferofs; // hidden port to draw to before displaying\r
-extern unsigned displayofs; // origin of port on visable screen\r
-extern unsigned panx,pany; // panning adjustments inside port in pixels\r
-extern unsigned pansx,pansy;\r
-extern unsigned panadjust; // panx/pany adjusted by screen resolution\r
-\r
-extern unsigned screenseg; // normally 0xa000 or buffer segment\r
-\r
-extern unsigned linewidth;\r
-extern unsigned ylookup[VIRTUALHEIGHT];\r
-\r
-extern boolean screenfaded;\r
-extern char colors[7][17]; // pallets for fades\r
-\r
-extern pictabletype _seg *pictable;\r
-extern pictabletype _seg *picmtable;\r
-extern spritetabletype _seg *spritetable;\r
-\r
-extern unsigned fontnumber; // 0 based font number for drawing\r
-extern int px,py;\r
-extern byte pdrawmode,fontcolor;\r
-\r
-extern int bordercolor;\r
-extern boolean nopan;\r
-\r
-//\r
-// asm globals\r
-//\r
-\r
-extern unsigned *shifttabletable[8];\r
-extern unsigned bufferwidth,bufferheight,screenspot; // used by font drawing stuff\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-void VW_Startup (void);\r
-void VW_Shutdown (void);\r
-\r
-cardtype VW_VideoID (void);\r
-\r
-//\r
-// EGA hardware routines\r
-//\r
-\r
-#define EGAWRITEMODE(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_MODE+256*x;out dx,ax;sti;}\r
-#define EGABITMASK(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_BITMASK+256*x;out dx,ax;sti;}\r
-#define EGAMAPMASK(x) asm{cli;mov dx,SC_INDEX;mov ax,SC_MAPMASK+x*256;out dx,ax;sti;}\r
-#define EGAREADMAP(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_READMAP+x*256;out dx,ax;sti;}\r
-\r
-void VW_SetLineWidth(int width);\r
-void VW_SetSplitScreen(int width);\r
-void VW_SetScreen (unsigned CRTC, unsigned pelpan);\r
-\r
-void VW_SetScreenMode (int grmode);\r
-void VW_ClearVideo (int color);\r
-void VW_WaitVBL (int number);\r
-\r
-void VW_ColorBorder (int color);\r
-void VW_SetPalette(byte *palette);\r
-void VW_SetDefaultColors(void);\r
-void VW_FadeOut(void);\r
-void VW_FadeIn(void);\r
-void VW_FadeUp(void);\r
-void VW_FadeDown(void);\r
-\r
-void VW_SetAtrReg (int reg, int value);\r
-\r
-//\r
-// block primitives\r
-//\r
-\r
-void VW_MaskBlock(memptr segm,unsigned ofs,unsigned dest,\r
- unsigned wide,unsigned height,unsigned planesize);\r
-void VW_InverseMask(memptr segm,unsigned ofs,unsigned dest,\r
- unsigned wide,unsigned height);\r
-void VW_MemToScreen(memptr source,unsigned dest,unsigned width,unsigned height);\r
-void VW_ScreenToMem(unsigned source,memptr dest,unsigned width,unsigned height);\r
-void VW_ScreenToScreen(unsigned source,unsigned dest,unsigned width,unsigned height);\r
-\r
-\r
-//\r
-// block addressable routines\r
-//\r
-\r
-void VW_DrawTile8(unsigned x, unsigned y, unsigned tile);\r
-\r
-#if GRMODE == EGAGR\r
-\r
-#define VW_DrawTile8M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE8M],(t)*40,bufferofs+ylookup[y]+(x),1,8,8)\r
-#define VW_DrawTile16(x,y,t) \\r
- VW_MemToScreen(grsegs[STARTTILE16+t],bufferofs+ylookup[y]+(x),2,16)\r
-#define VW_DrawTile16M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE16M],(t)*160,bufferofs+ylookup[y]+(x),2,16,32)\r
-\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define VW_DrawTile8M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE8M],(t)*32,bufferofs+ylookup[y]+(x),2,8,16)\r
-#define VW_DrawTile16(x,y,t) \\r
- VW_MemToScreen(grsegs[STARTTILE16+t],bufferofs+ylookup[y]+(x),4,16)\r
-#define VW_DrawTile16M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE16M],(t)*128,bufferofs+ylookup[y]+(x),4,16,64)\r
-\r
-#endif\r
-\r
-void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum);\r
-void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum);\r
-void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum);\r
-\r
-//\r
-// pixel addressable routines\r
-//\r
-void VW_MeasurePropString (char far *string, word *width, word *height);\r
-void VW_MeasureMPropString (char far *string, word *width, word *height);\r
-\r
-void VW_DrawPropString (char far *string);\r
-void VW_DrawMPropString (char far *string);\r
-void VW_DrawSprite(int x, int y, unsigned sprite);\r
-void VW_Plot(unsigned x, unsigned y, unsigned color);\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color);\r
-void VW_Vlin(unsigned yl, unsigned yh, unsigned x, unsigned color);\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color);\r
-\r
-//===========================================================================\r
-\r
-//\r
-// Double buffer management routines\r
-//\r
-\r
-void VW_InitDoubleBuffer (void);\r
-void VW_FixRefreshBuffer (void);\r
-int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2);\r
-void VW_UpdateScreen (void);\r
-void VW_CGAFullUpdate (void);\r
-\r
-//\r
-// cursor\r
-//\r
-\r
-void VW_ShowCursor (void);\r
-void VW_HideCursor (void);\r
-void VW_MoveCursor (int x, int y);\r
-void VW_SetCursor (int spritenum);\r
-void VW_FreeCursor (void);\r
-\r
-//\r
-// mode independant routines\r
-// coordinates in pixels, rounded to best screen res\r
-// regions marked in double buffer\r
-//\r
-\r
-void VWB_DrawTile8 (int x, int y, int tile);\r
-void VWB_DrawTile8M (int x, int y, int tile);\r
-void VWB_DrawTile16 (int x, int y, int tile);\r
-void VWB_DrawTile16M (int x, int y, int tile);\r
-void VWB_DrawPic (int x, int y, int chunknum);\r
-void VWB_DrawMPic(int x, int y, int chunknum);\r
-void VWB_Bar (int x, int y, int width, int height, int color);\r
-\r
-void VWB_DrawPropString (char far *string);\r
-void VWB_DrawMPropString (char far *string);\r
-void VWB_DrawSprite (int x, int y, int chunknum);\r
-void VWB_Plot (int x, int y, int color);\r
-void VWB_Hlin (int x1, int x2, int y, int color);\r
-void VWB_Vlin (int y1, int y2, int x, int color);\r
-\r
-//===========================================================================\r
+++ /dev/null
-; Catacomb 3-D Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-; ID_VW_A.ASM\r
-\r
-IDEAL\r
-MODEL MEDIUM,C\r
-\r
-INCLUDE "ID_ASM.EQU"\r
-\r
-WAITFORVBL = 1 ; setting to 0 causes setscreen and waitvbl\r
- ; to skip waiting for VBL (for timing things)\r
-\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-EXTRN screenseg :WORD\r
-EXTRN drawofs :WORD\r
-EXTRN bufferofs :WORD\r
-EXTRN displayofs :WORD\r
-EXTRN drawofs :WORD\r
-EXTRN panadjust :WORD\r
-EXTRN ylookup :WORD\r
-EXTRN linewidth :WORD\r
-EXTRN grsegs :WORD\r
-EXTRN updateptr :WORD\r
-EXTRN blockstarts :WORD ;offsets from drawofs for each update block\r
-EXTRN fontspace :WORD\r
-EXTRN fontnumber :WORD\r
-\r
-\r
-planemask db ?\r
-planenum db ?\r
-screendest dw ?\r
-linedelta dw ?\r
-\r
-LABEL shiftdata0 WORD\r
- dw 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13\r
- dw 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27\r
- dw 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41\r
- dw 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55\r
- dw 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69\r
- dw 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83\r
- dw 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97\r
- dw 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111\r
- dw 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125\r
- dw 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139\r
- dw 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153\r
- dw 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167\r
- dw 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181\r
- dw 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195\r
- dw 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209\r
- dw 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223\r
- dw 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237\r
- dw 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251\r
- dw 252, 253, 254, 255\r
-\r
-LABEL shiftdata1 WORD\r
- dw 0,32768, 1,32769, 2,32770, 3,32771, 4,32772, 5,32773, 6,32774\r
- dw 7,32775, 8,32776, 9,32777, 10,32778, 11,32779, 12,32780, 13,32781\r
- dw 14,32782, 15,32783, 16,32784, 17,32785, 18,32786, 19,32787, 20,32788\r
- dw 21,32789, 22,32790, 23,32791, 24,32792, 25,32793, 26,32794, 27,32795\r
- dw 28,32796, 29,32797, 30,32798, 31,32799, 32,32800, 33,32801, 34,32802\r
- dw 35,32803, 36,32804, 37,32805, 38,32806, 39,32807, 40,32808, 41,32809\r
- dw 42,32810, 43,32811, 44,32812, 45,32813, 46,32814, 47,32815, 48,32816\r
- dw 49,32817, 50,32818, 51,32819, 52,32820, 53,32821, 54,32822, 55,32823\r
- dw 56,32824, 57,32825, 58,32826, 59,32827, 60,32828, 61,32829, 62,32830\r
- dw 63,32831, 64,32832, 65,32833, 66,32834, 67,32835, 68,32836, 69,32837\r
- dw 70,32838, 71,32839, 72,32840, 73,32841, 74,32842, 75,32843, 76,32844\r
- dw 77,32845, 78,32846, 79,32847, 80,32848, 81,32849, 82,32850, 83,32851\r
- dw 84,32852, 85,32853, 86,32854, 87,32855, 88,32856, 89,32857, 90,32858\r
- dw 91,32859, 92,32860, 93,32861, 94,32862, 95,32863, 96,32864, 97,32865\r
- dw 98,32866, 99,32867, 100,32868, 101,32869, 102,32870, 103,32871, 104,32872\r
- dw 105,32873, 106,32874, 107,32875, 108,32876, 109,32877, 110,32878, 111,32879\r
- dw 112,32880, 113,32881, 114,32882, 115,32883, 116,32884, 117,32885, 118,32886\r
- dw 119,32887, 120,32888, 121,32889, 122,32890, 123,32891, 124,32892, 125,32893\r
- dw 126,32894, 127,32895\r
-\r
-LABEL shiftdata2 WORD\r
- dw 0,16384,32768,49152, 1,16385,32769,49153, 2,16386,32770,49154, 3,16387\r
- dw 32771,49155, 4,16388,32772,49156, 5,16389,32773,49157, 6,16390,32774,49158\r
- dw 7,16391,32775,49159, 8,16392,32776,49160, 9,16393,32777,49161, 10,16394\r
- dw 32778,49162, 11,16395,32779,49163, 12,16396,32780,49164, 13,16397,32781,49165\r
- dw 14,16398,32782,49166, 15,16399,32783,49167, 16,16400,32784,49168, 17,16401\r
- dw 32785,49169, 18,16402,32786,49170, 19,16403,32787,49171, 20,16404,32788,49172\r
- dw 21,16405,32789,49173, 22,16406,32790,49174, 23,16407,32791,49175, 24,16408\r
- dw 32792,49176, 25,16409,32793,49177, 26,16410,32794,49178, 27,16411,32795,49179\r
- dw 28,16412,32796,49180, 29,16413,32797,49181, 30,16414,32798,49182, 31,16415\r
- dw 32799,49183, 32,16416,32800,49184, 33,16417,32801,49185, 34,16418,32802,49186\r
- dw 35,16419,32803,49187, 36,16420,32804,49188, 37,16421,32805,49189, 38,16422\r
- dw 32806,49190, 39,16423,32807,49191, 40,16424,32808,49192, 41,16425,32809,49193\r
- dw 42,16426,32810,49194, 43,16427,32811,49195, 44,16428,32812,49196, 45,16429\r
- dw 32813,49197, 46,16430,32814,49198, 47,16431,32815,49199, 48,16432,32816,49200\r
- dw 49,16433,32817,49201, 50,16434,32818,49202, 51,16435,32819,49203, 52,16436\r
- dw 32820,49204, 53,16437,32821,49205, 54,16438,32822,49206, 55,16439,32823,49207\r
- dw 56,16440,32824,49208, 57,16441,32825,49209, 58,16442,32826,49210, 59,16443\r
- dw 32827,49211, 60,16444,32828,49212, 61,16445,32829,49213, 62,16446,32830,49214\r
- dw 63,16447,32831,49215\r
-\r
-LABEL shiftdata3 WORD\r
- dw 0, 8192,16384,24576,32768,40960,49152,57344, 1, 8193,16385,24577,32769,40961\r
- dw 49153,57345, 2, 8194,16386,24578,32770,40962,49154,57346, 3, 8195,16387,24579\r
- dw 32771,40963,49155,57347, 4, 8196,16388,24580,32772,40964,49156,57348, 5, 8197\r
- dw 16389,24581,32773,40965,49157,57349, 6, 8198,16390,24582,32774,40966,49158,57350\r
- dw 7, 8199,16391,24583,32775,40967,49159,57351, 8, 8200,16392,24584,32776,40968\r
- dw 49160,57352, 9, 8201,16393,24585,32777,40969,49161,57353, 10, 8202,16394,24586\r
- dw 32778,40970,49162,57354, 11, 8203,16395,24587,32779,40971,49163,57355, 12, 8204\r
- dw 16396,24588,32780,40972,49164,57356, 13, 8205,16397,24589,32781,40973,49165,57357\r
- dw 14, 8206,16398,24590,32782,40974,49166,57358, 15, 8207,16399,24591,32783,40975\r
- dw 49167,57359, 16, 8208,16400,24592,32784,40976,49168,57360, 17, 8209,16401,24593\r
- dw 32785,40977,49169,57361, 18, 8210,16402,24594,32786,40978,49170,57362, 19, 8211\r
- dw 16403,24595,32787,40979,49171,57363, 20, 8212,16404,24596,32788,40980,49172,57364\r
- dw 21, 8213,16405,24597,32789,40981,49173,57365, 22, 8214,16406,24598,32790,40982\r
- dw 49174,57366, 23, 8215,16407,24599,32791,40983,49175,57367, 24, 8216,16408,24600\r
- dw 32792,40984,49176,57368, 25, 8217,16409,24601,32793,40985,49177,57369, 26, 8218\r
- dw 16410,24602,32794,40986,49178,57370, 27, 8219,16411,24603,32795,40987,49179,57371\r
- dw 28, 8220,16412,24604,32796,40988,49180,57372, 29, 8221,16413,24605,32797,40989\r
- dw 49181,57373, 30, 8222,16414,24606,32798,40990,49182,57374, 31, 8223,16415,24607\r
- dw 32799,40991,49183,57375\r
-\r
-LABEL shiftdata4 WORD\r
- dw 0, 4096, 8192,12288,16384,20480,24576,28672,32768,36864,40960,45056,49152,53248\r
- dw 57344,61440, 1, 4097, 8193,12289,16385,20481,24577,28673,32769,36865,40961,45057\r
- dw 49153,53249,57345,61441, 2, 4098, 8194,12290,16386,20482,24578,28674,32770,36866\r
- dw 40962,45058,49154,53250,57346,61442, 3, 4099, 8195,12291,16387,20483,24579,28675\r
- dw 32771,36867,40963,45059,49155,53251,57347,61443, 4, 4100, 8196,12292,16388,20484\r
- dw 24580,28676,32772,36868,40964,45060,49156,53252,57348,61444, 5, 4101, 8197,12293\r
- dw 16389,20485,24581,28677,32773,36869,40965,45061,49157,53253,57349,61445, 6, 4102\r
- dw 8198,12294,16390,20486,24582,28678,32774,36870,40966,45062,49158,53254,57350,61446\r
- dw 7, 4103, 8199,12295,16391,20487,24583,28679,32775,36871,40967,45063,49159,53255\r
- dw 57351,61447, 8, 4104, 8200,12296,16392,20488,24584,28680,32776,36872,40968,45064\r
- dw 49160,53256,57352,61448, 9, 4105, 8201,12297,16393,20489,24585,28681,32777,36873\r
- dw 40969,45065,49161,53257,57353,61449, 10, 4106, 8202,12298,16394,20490,24586,28682\r
- dw 32778,36874,40970,45066,49162,53258,57354,61450, 11, 4107, 8203,12299,16395,20491\r
- dw 24587,28683,32779,36875,40971,45067,49163,53259,57355,61451, 12, 4108, 8204,12300\r
- dw 16396,20492,24588,28684,32780,36876,40972,45068,49164,53260,57356,61452, 13, 4109\r
- dw 8205,12301,16397,20493,24589,28685,32781,36877,40973,45069,49165,53261,57357,61453\r
- dw 14, 4110, 8206,12302,16398,20494,24590,28686,32782,36878,40974,45070,49166,53262\r
- dw 57358,61454, 15, 4111, 8207,12303,16399,20495,24591,28687,32783,36879,40975,45071\r
- dw 49167,53263,57359,61455\r
-\r
-LABEL shiftdata5 WORD\r
- dw 0, 2048, 4096, 6144, 8192,10240,12288,14336,16384,18432,20480,22528,24576,26624\r
- dw 28672,30720,32768,34816,36864,38912,40960,43008,45056,47104,49152,51200,53248,55296\r
- dw 57344,59392,61440,63488, 1, 2049, 4097, 6145, 8193,10241,12289,14337,16385,18433\r
- dw 20481,22529,24577,26625,28673,30721,32769,34817,36865,38913,40961,43009,45057,47105\r
- dw 49153,51201,53249,55297,57345,59393,61441,63489, 2, 2050, 4098, 6146, 8194,10242\r
- dw 12290,14338,16386,18434,20482,22530,24578,26626,28674,30722,32770,34818,36866,38914\r
- dw 40962,43010,45058,47106,49154,51202,53250,55298,57346,59394,61442,63490, 3, 2051\r
- dw 4099, 6147, 8195,10243,12291,14339,16387,18435,20483,22531,24579,26627,28675,30723\r
- dw 32771,34819,36867,38915,40963,43011,45059,47107,49155,51203,53251,55299,57347,59395\r
- dw 61443,63491, 4, 2052, 4100, 6148, 8196,10244,12292,14340,16388,18436,20484,22532\r
- dw 24580,26628,28676,30724,32772,34820,36868,38916,40964,43012,45060,47108,49156,51204\r
- dw 53252,55300,57348,59396,61444,63492, 5, 2053, 4101, 6149, 8197,10245,12293,14341\r
- dw 16389,18437,20485,22533,24581,26629,28677,30725,32773,34821,36869,38917,40965,43013\r
- dw 45061,47109,49157,51205,53253,55301,57349,59397,61445,63493, 6, 2054, 4102, 6150\r
- dw 8198,10246,12294,14342,16390,18438,20486,22534,24582,26630,28678,30726,32774,34822\r
- dw 36870,38918,40966,43014,45062,47110,49158,51206,53254,55302,57350,59398,61446,63494\r
- dw 7, 2055, 4103, 6151, 8199,10247,12295,14343,16391,18439,20487,22535,24583,26631\r
- dw 28679,30727,32775,34823,36871,38919,40967,43015,45063,47111,49159,51207,53255,55303\r
- dw 57351,59399,61447,63495\r
-\r
-LABEL shiftdata6 WORD\r
- dw 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216,10240,11264,12288,13312\r
- dw 14336,15360,16384,17408,18432,19456,20480,21504,22528,23552,24576,25600,26624,27648\r
- dw 28672,29696,30720,31744,32768,33792,34816,35840,36864,37888,38912,39936,40960,41984\r
- dw 43008,44032,45056,46080,47104,48128,49152,50176,51200,52224,53248,54272,55296,56320\r
- dw 57344,58368,59392,60416,61440,62464,63488,64512, 1, 1025, 2049, 3073, 4097, 5121\r
- dw 6145, 7169, 8193, 9217,10241,11265,12289,13313,14337,15361,16385,17409,18433,19457\r
- dw 20481,21505,22529,23553,24577,25601,26625,27649,28673,29697,30721,31745,32769,33793\r
- dw 34817,35841,36865,37889,38913,39937,40961,41985,43009,44033,45057,46081,47105,48129\r
- dw 49153,50177,51201,52225,53249,54273,55297,56321,57345,58369,59393,60417,61441,62465\r
- dw 63489,64513, 2, 1026, 2050, 3074, 4098, 5122, 6146, 7170, 8194, 9218,10242,11266\r
- dw 12290,13314,14338,15362,16386,17410,18434,19458,20482,21506,22530,23554,24578,25602\r
- dw 26626,27650,28674,29698,30722,31746,32770,33794,34818,35842,36866,37890,38914,39938\r
- dw 40962,41986,43010,44034,45058,46082,47106,48130,49154,50178,51202,52226,53250,54274\r
- dw 55298,56322,57346,58370,59394,60418,61442,62466,63490,64514, 3, 1027, 2051, 3075\r
- dw 4099, 5123, 6147, 7171, 8195, 9219,10243,11267,12291,13315,14339,15363,16387,17411\r
- dw 18435,19459,20483,21507,22531,23555,24579,25603,26627,27651,28675,29699,30723,31747\r
- dw 32771,33795,34819,35843,36867,37891,38915,39939,40963,41987,43011,44035,45059,46083\r
- dw 47107,48131,49155,50179,51203,52227,53251,54275,55299,56323,57347,58371,59395,60419\r
- dw 61443,62467,63491,64515\r
-\r
-LABEL shiftdata7 WORD\r
- dw 0, 512, 1024, 1536, 2048, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656\r
- dw 7168, 7680, 8192, 8704, 9216, 9728,10240,10752,11264,11776,12288,12800,13312,13824\r
- dw 14336,14848,15360,15872,16384,16896,17408,17920,18432,18944,19456,19968,20480,20992\r
- dw 21504,22016,22528,23040,23552,24064,24576,25088,25600,26112,26624,27136,27648,28160\r
- dw 28672,29184,29696,30208,30720,31232,31744,32256,32768,33280,33792,34304,34816,35328\r
- dw 35840,36352,36864,37376,37888,38400,38912,39424,39936,40448,40960,41472,41984,42496\r
- dw 43008,43520,44032,44544,45056,45568,46080,46592,47104,47616,48128,48640,49152,49664\r
- dw 50176,50688,51200,51712,52224,52736,53248,53760,54272,54784,55296,55808,56320,56832\r
- dw 57344,57856,58368,58880,59392,59904,60416,60928,61440,61952,62464,62976,63488,64000\r
- dw 64512,65024, 1, 513, 1025, 1537, 2049, 2561, 3073, 3585, 4097, 4609, 5121, 5633\r
- dw 6145, 6657, 7169, 7681, 8193, 8705, 9217, 9729,10241,10753,11265,11777,12289,12801\r
- dw 13313,13825,14337,14849,15361,15873,16385,16897,17409,17921,18433,18945,19457,19969\r
- dw 20481,20993,21505,22017,22529,23041,23553,24065,24577,25089,25601,26113,26625,27137\r
- dw 27649,28161,28673,29185,29697,30209,30721,31233,31745,32257,32769,33281,33793,34305\r
- dw 34817,35329,35841,36353,36865,37377,37889,38401,38913,39425,39937,40449,40961,41473\r
- dw 41985,42497,43009,43521,44033,44545,45057,45569,46081,46593,47105,47617,48129,48641\r
- dw 49153,49665,50177,50689,51201,51713,52225,52737,53249,53761,54273,54785,55297,55809\r
- dw 56321,56833,57345,57857,58369,58881,59393,59905,60417,60929,61441,61953,62465,62977\r
- dw 63489,64001,64513,65025\r
-\r
-shifttabletable dw shiftdata0,shiftdata1,shiftdata2,shiftdata3\r
- dw shiftdata4,shiftdata5,shiftdata6,shiftdata7\r
-\r
-PUBLIC shifttabletable\r
-\r
-\r
-;============================================================================\r
-\r
-CODESEG\r
-\r
-IFE GRMODE-CGAGR\r
-INCLUDE "ID_VW_AC.ASM"\r
-ENDIF\r
-\r
-IFE GRMODE-EGAGR\r
-INCLUDE "ID_VW_AE.ASM"\r
-ENDIF\r
-\r
-IFE GRMODE-VGAGR\r
-INCLUDE "ID_VW_AV.ASM"\r
-ENDIF\r
-\r
-;============================================================================\r
-;\r
-; MISC VIDEO ROUTINES\r
-;\r
-;============================================================================\r
-\r
-;========\r
-;\r
-; VW_WaitVBL (int number)\r
-;\r
-;========\r
-\r
-PROC VW_WaitVBL number:WORD\r
-PUBLIC VW_WaitVBL\r
-\r
-if WAITFORVBL ; skip wait if profiling\r
-\r
- mov dx,STATUS_REGISTER_1\r
-\r
- mov cx,[number]\r
-\r
-waitvbl1:\r
- in al,dx\r
- test al,00001000b ;look for vbl\r
- jnz waitvbl1\r
-\r
-waitvbl2:\r
- in al,dx\r
- test al,00001000b ;look for vbl\r
- jz waitvbl2\r
-\r
- loop waitvbl1\r
-\r
-endif\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-\r
-\r
- MASM\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-;\r
-; Name: VW_VideoID\r
-;\r
-; Function: Detects the presence of various video subsystems\r
-;\r
-; int VideoID;\r
-;\r
-; Subsystem ID values:\r
-; 0 = (none)\r
-; 1 = MDA\r
-; 2 = CGA\r
-; 3 = EGA\r
-; 4 = MCGA\r
-; 5 = VGA\r
-; 80h = HGC\r
-; 81h = HGC+\r
-; 82h = Hercules InColor\r
-;\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-;\r
-; Equates\r
-;\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-VIDstruct STRUC ; corresponds to C data structure\r
-\r
-Video0Type DB ? ; first subsystem type\r
-Display0Type DB ? ; display attached to first subsystem\r
-\r
-Video1Type DB ? ; second subsystem type\r
-Display1Type DB ? ; display attached to second subsystem\r
-\r
-VIDstruct ENDS\r
-\r
-\r
-Device0 EQU word ptr Video0Type[di]\r
-Device1 EQU word ptr Video1Type[di]\r
-\r
-\r
-MDA EQU 1 ; subsystem types\r
-CGA EQU 2\r
-EGA EQU 3\r
-MCGA EQU 4\r
-VGA EQU 5\r
-HGC EQU 80h\r
-HGCPlus EQU 81h\r
-InColor EQU 82h\r
-\r
-MDADisplay EQU 1 ; display types\r
-CGADisplay EQU 2\r
-EGAColorDisplay EQU 3\r
-PS2MonoDisplay EQU 4\r
-PS2ColorDisplay EQU 5\r
-\r
-TRUE EQU 1\r
-FALSE EQU 0\r
-\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-;\r
-; Program\r
-;\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-\r
-Results VIDstruct <> ;results go here!\r
-\r
-EGADisplays DB CGADisplay ; 0000b, 0001b (EGA switch values)\r
- DB EGAColorDisplay ; 0010b, 0011b\r
- DB MDADisplay ; 0100b, 0101b\r
- DB CGADisplay ; 0110b, 0111b\r
- DB EGAColorDisplay ; 1000b, 1001b\r
- DB MDADisplay ; 1010b, 1011b\r
-\r
-DCCtable DB 0,0 ; translate table for INT 10h func 1Ah\r
- DB MDA,MDADisplay\r
- DB CGA,CGADisplay\r
- DB 0,0\r
- DB EGA,EGAColorDisplay\r
- DB EGA,MDADisplay\r
- DB 0,0\r
- DB VGA,PS2MonoDisplay\r
- DB VGA,PS2ColorDisplay\r
- DB 0,0\r
- DB MCGA,EGAColorDisplay\r
- DB MCGA,PS2MonoDisplay\r
- DB MCGA,PS2ColorDisplay\r
-\r
-TestSequence DB TRUE ; this list of flags and addresses\r
- DW FindPS2 ; determines the order in which this\r
- ; program looks for the various\r
-EGAflag DB ? ; subsystems\r
- DW FindEGA\r
-\r
-CGAflag DB ?\r
- DW FindCGA\r
-\r
-Monoflag DB ?\r
- DW FindMono\r
-\r
-NumberOfTests EQU ($-TestSequence)/3\r
-\r
-\r
-PUBLIC VW_VideoID\r
-VW_VideoID PROC\r
-\r
- push bp ; preserve caller registers\r
- mov bp,sp\r
- push ds\r
- push si\r
- push di\r
-\r
- push cs\r
- pop ds\r
- ASSUME DS:@Code\r
-\r
-; initialize the data structure that will contain the results\r
-\r
- lea di,Results ; DS:DI -> start of data structure\r
-\r
- mov Device0,0 ; zero these variables\r
- mov Device1,0\r
-\r
-; look for the various subsystems using the subroutines whose addresses are\r
-; tabulated in TestSequence; each subroutine sets flags in TestSequence\r
-; to indicate whether subsequent subroutines need to be called\r
-\r
- mov byte ptr CGAflag,TRUE\r
- mov byte ptr EGAflag,TRUE\r
- mov byte ptr Monoflag,TRUE\r
-\r
- mov cx,NumberOfTests\r
- mov si,offset TestSequence\r
-\r
-@@L01: lodsb ; AL := flag\r
- test al,al\r
- lodsw ; AX := subroutine address\r
- jz @@L02 ; skip subroutine if flag is false\r
-\r
- push si\r
- push cx\r
- call ax ; call subroutine to detect subsystem\r
- pop cx\r
- pop si\r
-\r
-@@L02: loop @@L01\r
-\r
-; determine which subsystem is active\r
-\r
- call FindActive\r
-\r
- mov al,Results.Video0Type\r
- mov ah,0 ; was: Results.Display0Type\r
-\r
- pop di ; restore caller registers and return\r
- pop si\r
- pop ds\r
- mov sp,bp\r
- pop bp\r
- ret\r
-\r
-VW_VideoID ENDP\r
-\r
-\r
-;\r
-; FindPS2\r
-;\r
-; This subroutine uses INT 10H function 1Ah to determine the video BIOS\r
-; Display Combination Code (DCC) for each video subsystem present.\r
-;\r
-\r
-FindPS2 PROC near\r
-\r
- mov ax,1A00h\r
- int 10h ; call video BIOS for info\r
-\r
- cmp al,1Ah\r
- jne @@L13 ; exit if function not supported (i.e.,\r
- ; no MCGA or VGA in system)\r
-\r
-; convert BIOS DCCs into specific subsystems & displays\r
-\r
- mov cx,bx\r
- xor bh,bh ; BX := DCC for active subsystem\r
-\r
- or ch,ch\r
- jz @@L11 ; jump if only one subsystem present\r
-\r
- mov bl,ch ; BX := inactive DCC\r
- add bx,bx\r
- mov ax,[bx+offset DCCtable]\r
-\r
- mov Device1,ax\r
-\r
- mov bl,cl\r
- xor bh,bh ; BX := active DCC\r
-\r
-@@L11: add bx,bx\r
- mov ax,[bx+offset DCCtable]\r
-\r
- mov Device0,ax\r
-\r
-; reset flags for subsystems that have been ruled out\r
-\r
- mov byte ptr CGAflag,FALSE\r
- mov byte ptr EGAflag,FALSE\r
- mov byte ptr Monoflag,FALSE\r
-\r
- lea bx,Video0Type[di] ; if the BIOS reported an MDA ...\r
- cmp byte ptr [bx],MDA\r
- je @@L12\r
-\r
- lea bx,Video1Type[di]\r
- cmp byte ptr [bx],MDA\r
- jne @@L13\r
-\r
-@@L12: mov word ptr [bx],0 ; ... Hercules can't be ruled out\r
- mov byte ptr Monoflag,TRUE\r
-\r
-@@L13: ret\r
-\r
-FindPS2 ENDP\r
-\r
-\r
-;\r
-; FindEGA\r
-;\r
-; Look for an EGA. This is done by making a call to an EGA BIOS function\r
-; which doesn't exist in the default (MDA, CGA) BIOS.\r
-\r
-FindEGA PROC near ; Caller: AH = flags\r
- ; Returns: AH = flags\r
- ; Video0Type and\r
- ; Display0Type updated\r
-\r
- mov bl,10h ; BL := 10h (return EGA info)\r
- mov ah,12h ; AH := INT 10H function number\r
- int 10h ; call EGA BIOS for info\r
- ; if EGA BIOS is present,\r
- ; BL <> 10H\r
- ; CL = switch setting\r
- cmp bl,10h\r
- je @@L22 ; jump if EGA BIOS not present\r
-\r
- mov al,cl\r
- shr al,1 ; AL := switches/2\r
- mov bx,offset EGADisplays\r
- xlat ; determine display type from switches\r
- mov ah,al ; AH := display type\r
- mov al,EGA ; AL := subystem type\r
- call FoundDevice\r
-\r
- cmp ah,MDADisplay\r
- je @@L21 ; jump if EGA has a monochrome display\r
-\r
- mov CGAflag,FALSE ; no CGA if EGA has color display\r
- jmp short @@L22\r
-\r
-@@L21: mov Monoflag,FALSE ; EGA has a mono display, so MDA and\r
- ; Hercules are ruled out\r
-@@L22: ret\r
-\r
-FindEGA ENDP\r
-\r
-;\r
-; FindCGA\r
-;\r
-; This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H.\r
-;\r
-FindCGA PROC near ; Returns: VIDstruct updated\r
-\r
- mov dx,3D4h ; DX := CRTC address port\r
- call Find6845\r
- jc @@L31 ; jump if not present\r
-\r
- mov al,CGA\r
- mov ah,CGADisplay\r
- call FoundDevice\r
-\r
-@@L31: ret\r
-\r
-FindCGA ENDP\r
-\r
-;\r
-; FindMono\r
-;\r
-; This is done by looking for the MDA's 6845 CRTC at I/O port 3B4H. If\r
-; a 6845 is found, the subroutine distinguishes between an MDA\r
-; and a Hercules adapter by monitoring bit 7 of the CRT Status byte.\r
-; This bit changes on Hercules adapters but does not change on an MDA.\r
-;\r
-; The various Hercules adapters are identified by bits 4 through 6 of\r
-; the CRT Status value:\r
-;\r
-; 000b = HGC\r
-; 001b = HGC+\r
-; 101b = InColor card\r
-;\r
-\r
-FindMono PROC near ; Returns: VIDstruct updated\r
-\r
- mov dx,3B4h ; DX := CRTC address port\r
- call Find6845\r
- jc @@L44 ; jump if not present\r
-\r
- mov dl,0BAh ; DX := 3BAh (status port)\r
- in al,dx\r
- and al,80h\r
- mov ah,al ; AH := bit 7 (vertical sync on HGC)\r
-\r
- mov cx,8000h ; do this 32768 times\r
-@@L41: in al,dx\r
- and al,80h ; isolate bit 7\r
- cmp ah,al\r
- loope @@L41 ; wait for bit 7 to change\r
- jne @@L42 ; if bit 7 changed, it's a Hercules\r
-\r
- mov al,MDA ; if bit 7 didn't change, it's an MDA\r
- mov ah,MDADisplay\r
- call FoundDevice\r
- jmp short @@L44\r
-\r
-@@L42: in al,dx\r
- mov dl,al ; DL := value from status port\r
- and dl,01110000b ; mask bits 4 thru 6\r
-\r
- mov ah,MDADisplay ; assume it's a monochrome display\r
-\r
- mov al,HGCPlus ; look for an HGC+\r
- cmp dl,00010000b\r
- je @@L43 ; jump if it's an HGC+\r
-\r
- mov al,HGC ; look for an InColor card or HGC\r
- cmp dl,01010000b\r
- jne @@L43 ; jump if it's not an InColor card\r
-\r
- mov al,InColor ; it's an InColor card\r
- mov ah,EGAColorDisplay\r
-\r
-@@L43: call FoundDevice\r
-\r
-@@L44: ret\r
-\r
-FindMono ENDP\r
-\r
-;\r
-; Find6845\r
-;\r
-; This routine detects the presence of the CRTC on a MDA, CGA or HGC.\r
-; The technique is to write and read register 0Fh of the chip (cursor\r
-; low). If the same value is read as written, assume the chip is\r
-; present at the specified port addr.\r
-;\r
-\r
-Find6845 PROC near ; Caller: DX = port addr\r
- ; Returns: cf set if not present\r
- mov al,0Fh\r
- out dx,al ; select 6845 reg 0Fh (Cursor Low)\r
- inc dx\r
- in al,dx ; AL := current Cursor Low value\r
- mov ah,al ; preserve in AH\r
- mov al,66h ; AL := arbitrary value\r
- out dx,al ; try to write to 6845\r
-\r
- mov cx,100h\r
-@@L51: loop @@L51 ; wait for 6845 to respond\r
-\r
- in al,dx\r
- xchg ah,al ; AH := returned value\r
- ; AL := original value\r
- out dx,al ; restore original value\r
-\r
- cmp ah,66h ; test whether 6845 responded\r
- je @@L52 ; jump if it did (cf is reset)\r
-\r
- stc ; set carry flag if no 6845 present\r
-\r
-@@L52: ret\r
-\r
-Find6845 ENDP\r
-\r
-\r
-;\r
-; FindActive\r
-;\r
-; This subroutine stores the currently active device as Device0. The\r
-; current video mode determines which subsystem is active.\r
-;\r
-\r
-FindActive PROC near\r
-\r
- cmp word ptr Device1,0\r
- je @@L63 ; exit if only one subsystem\r
-\r
- cmp Video0Type[di],4 ; exit if MCGA or VGA present\r
- jge @@L63 ; (INT 10H function 1AH\r
- cmp Video1Type[di],4 ; already did the work)\r
- jge @@L63\r
-\r
- mov ah,0Fh\r
- int 10h ; AL := current BIOS video mode\r
-\r
- and al,7\r
- cmp al,7 ; jump if monochrome\r
- je @@L61 ; (mode 7 or 0Fh)\r
-\r
- cmp Display0Type[di],MDADisplay\r
- jne @@L63 ; exit if Display0 is color\r
- jmp short @@L62\r
-\r
-@@L61: cmp Display0Type[di],MDADisplay\r
- je @@L63 ; exit if Display0 is monochrome\r
-\r
-@@L62: mov ax,Device0 ; make Device0 currently active\r
- xchg ax,Device1\r
- mov Device0,ax\r
-\r
-@@L63: ret\r
-\r
-FindActive ENDP\r
-\r
-\r
-;\r
-; FoundDevice\r
-;\r
-; This routine updates the list of subsystems.\r
-;\r
-\r
-FoundDevice PROC near ; Caller: AH = display #\r
- ; AL = subsystem #\r
- ; Destroys: BX\r
- lea bx,Video0Type[di]\r
- cmp byte ptr [bx],0\r
- je @@L71 ; jump if 1st subsystem\r
-\r
- lea bx,Video1Type[di] ; must be 2nd subsystem\r
-\r
-@@L71: mov [bx],ax ; update list entry\r
- ret\r
-\r
-FoundDevice ENDP\r
-\r
-IDEAL\r
-\r
-\r
-\r
-END\r
+++ /dev/null
-; Reconstructed Commander Keen 4-6 Source Code\r
-; Copyright (C) 2021 K1n9_Duk3\r
-;\r
-; This file is primarily based on:\r
-; Catacomb 3-D Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-;=================================\r
-;\r
-; CGA view manager routines\r
-;\r
-;=================================\r
-\r
-;============================================================================\r
-;\r
-; All of these routines draw into a floating virtual screen segment in main\r
-; memory. bufferofs points to the origin of the drawing page in screenseg.\r
-; The routines that write out words must take into account buffer wrapping\r
-; and not write a word at 0xffff (which causes an exception on 386s).\r
-;\r
-; The direction flag should be clear\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-plotpixels db 0c0h,030h,0ch,03h\r
-colorbyte db 000000b,01010101b,10101010b,11111111b\r
-colorword dw 0,5555h,0aaaah,0ffffh\r
-\r
-CODESEG\r
-\r
-;============================================================================\r
-;\r
-; VW_Plot (int x,y,color)\r
-;\r
-;============================================================================\r
-\r
-\r
-PROC VW_Plot x:WORD, y:WORD, color:WORD\r
-PUBLIC VW_Plot\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- mov bx,[y]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,3\r
- mov ah,[plotpixels+bx]\r
- mov bx,[color]\r
- mov cl,[colorbyte+bx]\r
- and cl,ah\r
- not ah\r
-\r
- mov al,[es:di]\r
- and al,ah ; mask off other pixels\r
- or al,cl\r
- stosb\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Vlin (int yl,yh,x,color)\r
-;\r
-;============================================================================\r
-\r
-PROC VW_Vlin yl:WORD, yh:WORD, x:WORD, color:WORD\r
-PUBLIC VW_Vlin\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- mov bx,[yl]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,3\r
- mov ah,[plotpixels+bx]\r
- mov bx,[color]\r
- mov bl,[colorbyte+bx]\r
- and bl,ah\r
- not ah\r
-\r
- mov cx,[yh]\r
- sub cx,[yl]\r
- inc cx ;number of pixels to plot\r
-\r
- mov dx,[linewidth]\r
-\r
-@@plot:\r
- mov al,[es:di]\r
- and al,ah ; mask off other pixels\r
- or al,bl\r
- mov [es:di],al\r
- add di,dx\r
- loop @@plot\r
-\r
- ret\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;===================\r
-;\r
-; VW_DrawTile8\r
-;\r
-; xcoord in bytes (8 pixels), ycoord in pixels\r
-; All Tile8s are in one grseg, so an offset is calculated inside it\r
-;\r
-; DONE\r
-;\r
-;===================\r
-\r
-PROC VW_DrawTile8 xcoord:WORD, ycoord:WORD, tile:WORD\r
-PUBLIC VW_DrawTile8\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- add di,[xcoord]\r
- mov bx,[ycoord]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
-\r
- mov bx,[linewidth]\r
- sub bx,2\r
-\r
- mov si,[tile]\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
-\r
- mov ds,[grsegs+STARTTILE8*2] ; segment for all tile8s\r
-\r
-;\r
-; start drawing\r
-;\r
-\r
-REPT 7\r
- movsb ;no word moves because of segment wrapping\r
- movsb\r
- add di,bx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MaskBlock\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then the data. Seperate unwound routines are used\r
-; to speed drawing.\r
-;\r
-; Mask blocks will allways be an even width because of the way IGRAB works\r
-;\r
-; DONE\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-UNWOUNDMASKS = 18\r
-\r
-\r
-maskroutines dw mask0,mask0,mask2E,mask2O,mask4E,mask4O\r
- dw mask6E,mask6O,mask8E,mask8O,mask10E,mask10O\r
- dw mask12E,mask12O,mask14E,mask14O,mask16E,mask16O\r
- dw mask18E,mask18O\r
-\r
-\r
-routinetouse dw ?\r
-\r
-CODESEG\r
-\r
-PROC VW_MaskBlock segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD, planesize:WORD\r
-PUBLIC VW_MaskBlock\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[wide]\r
- mov dx,[linewidth]\r
- sub dx,di ;dx = delta to start of next line\r
-\r
- mov bx,[planesize] ; si+bx = data location\r
-\r
- cmp di,UNWOUNDMASKS\r
- jbe @@unwoundroutine\r
-\r
-;==============\r
-;\r
-; General purpose masked block drawing. This could be optimised into\r
-; four routines to use words, but few play loop sprites should be this big!\r
-;\r
-;==============\r
-\r
- mov [ss:linedelta],dx\r
- mov ds,[segm]\r
- mov si,[ofs]\r
- mov di,[dest]\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopgen:\r
- mov cx,[wide]\r
-@@byteloop:\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
- loop @@byteloop\r
-\r
- add di,[ss:linedelta]\r
- dec dx\r
- jnz @@lineloopgen\r
-\r
-mask0:\r
- mov ax,ss\r
- mov ds,ax\r
- ret ;width of 0 = no drawing\r
-\r
-\r
-;=================\r
-;\r
-; use the unwound routines\r
-;\r
-;=================\r
-\r
-@@unwoundroutine:\r
- shr di,1 ;we only have even width unwound routines\r
- mov cx,[dest]\r
- shr cx,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1\r
- mov ax,[maskroutines+di] ;call the right routine\r
-\r
- mov ds,[segm]\r
- mov si,[ofs]\r
- mov di,[dest]\r
- mov cx,[height] ;scan lines to draw\r
-\r
- jmp ax ;draw it\r
-\r
-;=================\r
-;\r
-; Horizontally unwound routines to draw certain masked blocks faster\r
-;\r
-;=================\r
-\r
-MACRO MASKBYTE\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
-ENDM\r
-\r
-MACRO MASKWORD\r
- mov ax,[es:di]\r
- and ax,[si]\r
- or ax,[bx+si]\r
- inc si\r
- inc si\r
- stosw\r
-ENDM\r
-\r
-MACRO SPRITELOOP addr\r
- add di,dx\r
- loop addr\r
- mov ax,ss\r
- mov ds,ax\r
- ret\r
-ENDM\r
-\r
-\r
-EVEN\r
-mask2E:\r
- MASKWORD\r
- SPRITELOOP mask2E\r
-\r
-EVEN\r
-mask2O:\r
- MASKBYTE\r
- MASKBYTE\r
- SPRITELOOP mask2O\r
-\r
-EVEN\r
-mask4E:\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask4E\r
-\r
-EVEN\r
-mask4O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask4O\r
-\r
-EVEN\r
-mask6E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask6E\r
-\r
-EVEN\r
-mask6O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask6O\r
-\r
-EVEN\r
-mask8E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask8E\r
-\r
-EVEN\r
-mask8O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask8O\r
-\r
-EVEN\r
-mask10E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask10E\r
-\r
-EVEN\r
-mask10O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask10O\r
-\r
-EVEN\r
-mask12E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask12E\r
-\r
-EVEN\r
-mask12O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask12O\r
-\r
-EVEN\r
-mask14E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask14E\r
-\r
-EVEN\r
-mask14O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask14O\r
-\r
-EVEN\r
-mask16E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask16E\r
-\r
-EVEN\r
-mask16O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask16O\r
-\r
-EVEN\r
-mask18E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask18E\r
-\r
-EVEN\r
-mask18O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask18O\r
-\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_InverseMask\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then the data.\r
-;\r
-; Mask blocks will allways be an even width because of the way IGRAB works\r
-;\r
-;============================================================================\r
-\r
-PROC VW_InverseMask segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_InverseMask\r
-USES SI,DI\r
-\r
- mov es, [screenseg]\r
- mov ax, [wide]\r
- mov dx, [linewidth]\r
- sub dx, ax;\r
- mov ds, [segm]\r
- mov si, [ofs]\r
- mov di, [dest]\r
- mov bx, [height]\r
- shr [wide], 1\r
-@@yloop:\r
- mov cx, [wide]\r
-@@xloop:\r
- lodsw\r
- not ax\r
- or [es:di], ax\r
- inc di\r
- inc di\r
- loop @@xloop\r
- add di, dx\r
- dec bx\r
- jnz @@yloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_ScreenToScreen\r
-;\r
-; Basic block copy routine. Copies one block of screen memory to another,\r
-; bufferofs is NOT accounted for.\r
-;\r
-; DONE\r
-;\r
-;============================================================================\r
-\r
-PROC VW_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToScreen\r
-USES SI,DI\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ax,[screenseg]\r
- mov es,ax\r
- mov ds,ax\r
-\r
- mov si,[source]\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
-;\r
-; if the width, source, and dest are all even, use word moves\r
-; This is allways the case in the CGA refresh\r
-;\r
- test ax,1\r
- jnz @@bytelineloop\r
- test si,1\r
- jnz @@bytelineloop\r
- test di,1\r
- jnz @@bytelineloop\r
-\r
- shr ax,1\r
-@@wordlineloop:\r
- mov cx,ax\r
- rep movsw\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@wordlineloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-@@bytelineloop:\r
- mov cx,ax\r
- rep movsb\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@bytelineloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MemToScreen\r
-;\r
-; Basic block drawing routine. Takes a block shape at segment pointer source\r
-; of width by height data, and draws it to dest in the virtual screen,\r
-; based on linewidth. bufferofs is NOT accounted for.\r
-; There are four drawing routines to provide the best optimized code while\r
-; accounting for odd segment wrappings due to the floating screens.\r
-;\r
-; DONE\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-memtoscreentable dw eventoeven,eventoodd,oddtoeven,oddtoodd\r
-\r
-CODESEG\r
-\r
-\r
-PROC VW_MemToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_MemToScreen\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[source]\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- xor di,di\r
- shr [wide],1 ;change wide to words, and see if carry is set\r
- rcl di,1 ;1 if wide is odd\r
- mov ax,[dest]\r
- shr ax,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
- jmp [ss:memtoscreentable+di] ;call the right routine\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an even destination address\r
-;\r
-;==============\r
-\r
-eventoeven:\r
- mov di,[dest] ;start at same place in all planes\r
-EVEN\r
-@@lineloopEE:\r
- mov cx,ax\r
- rep movsw\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopEE\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an even video address\r
-;\r
-;==============\r
-\r
-oddtoeven:\r
- mov di,[dest] ;start at same place in all planes\r
-EVEN\r
-@@lineloopOE:\r
- mov cx,ax\r
- rep movsw\r
- movsb ;copy the last byte\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopOE\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an odd video address\r
-;\r
-;==============\r
-\r
-eventoodd:\r
- mov di,[dest] ;start at same place in all planes\r
- dec ax ;one word has to be handled seperately\r
-EVEN\r
-@@lineloopEO:\r
- movsb\r
- mov cx,ax\r
- rep movsw\r
- movsb\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopEO\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an odd video address\r
-;\r
-;==============\r
-\r
-oddtoodd:\r
- mov di,[dest] ;start at same place in all planes\r
-EVEN\r
-@@lineloopOO:\r
- movsb\r
- mov cx,ax\r
- rep movsw\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopOO\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;===========================================================================\r
-;\r
-; VW_ScreenToMem\r
-;\r
-; Copies a block of video memory to main memory, in order from planes 0-3.\r
-; This could be optimized along the lines of VW_MemToScreen to take advantage\r
-; of word copies, but this is an infrequently called routine.\r
-;\r
-; DONE\r
-;\r
-;===========================================================================\r
-\r
-PROC VW_ScreenToMem source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToMem\r
-USES SI,DI\r
-\r
- mov es,[dest]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[screenseg]\r
-\r
- xor di,di\r
-\r
- mov si,[source]\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloop:\r
- mov cx,[wide]\r
- rep movsb\r
-\r
- add si,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-;\r
-; MISC CGA ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-;==============\r
-;\r
-; VW_SetScreen\r
-;\r
-; DONE\r
-;\r
-;==============\r
-\r
-PROC VW_SetScreen crtc:WORD\r
-PUBLIC VW_SetScreen\r
-\r
-;\r
-; for some reason, my XT's EGA card doesn't like word outs to the CRTC\r
-; index...\r
-;\r
- cli\r
-\r
- mov cx,[crtc]\r
- mov dx,CRTC_INDEX\r
- mov al,0ch ;start address high register\r
- out dx,al\r
- inc dx\r
- mov al,ch\r
- out dx,al\r
- dec dx\r
- mov al,0dh ;start address low register\r
- out dx,al\r
- mov al,cl\r
- inc dx\r
- out dx,al\r
-\r
- sti\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-if NUMFONT+NUMFONTM\r
-\r
-;===========================================================================\r
-;\r
-; GENERAL FONT DRAWING ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-DATASEG\r
-\r
-px dw ? ; proportional character drawing coordinates\r
-py dw ?\r
-pdrawmode db 11000b ; 8 = OR, 24 = XOR, put in GC_DATAROTATE\r
-fontcolor db 15 ;0-15 mapmask value\r
-\r
-PUBLIC px,py,pdrawmode,fontcolor\r
-\r
-;\r
-; offsets in font structure\r
-;\r
-pcharheight = 0 ;lines high\r
-charloc = 2 ;pointers to every character\r
-charwidth = 514 ;every character's width in pixels\r
-\r
-\r
-propchar dw ? ; the character number to shift\r
-stringptr dw ?,?\r
-\r
-fontcolormask dw ? ; font color expands into this\r
-\r
-BUFFWIDTH = 100\r
-BUFFHEIGHT = 32 ; must be twice as high as font for masked fonts\r
-\r
-databuffer db BUFFWIDTH*BUFFHEIGHT dup (?)\r
-\r
-bufferwidth dw ? ; bytes with valid info / line\r
-bufferheight dw ? ; number of lines currently used\r
-\r
-bufferbyte dw ?\r
-bufferbit dw ?\r
-PUBLIC bufferwidth,bufferheight,bufferbyte,bufferbit\r
-\r
-screenspot dw ? ; where the buffer is going\r
-\r
-bufferextra dw ? ; add at end of a line copy\r
-screenextra dw ?\r
-\r
-CODESEG\r
-\r
-;======================\r
-;\r
-; Macros to table shift a byte of font\r
-;\r
-;======================\r
-\r
-MACRO SHIFTNOXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- or [di],al ; or with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-MACRO SHIFTWITHXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- not ax\r
- and [di],al ; and with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-\r
-;=======================\r
-;\r
-; VWL_XORBuffer\r
-;\r
-; Pass buffer start in SI (somewhere in databuffer)\r
-; Draws the buffer to the screen buffer\r
-;\r
-;========================\r
-\r
-PROC VWL_XORBuffer NEAR\r
-USES BP\r
- mov bl,[fontcolor]\r
- xor bh,bh\r
- shl bx,1\r
- mov ax,[colorword+bx]\r
- mov [fontcolormask],ax\r
-\r
- mov es,[screenseg]\r
- mov di,[screenspot]\r
-\r
- mov bx,[bufferwidth] ;calculate offsets for end of each line\r
- mov [bufferwidth],bx\r
-\r
- or bx,bx\r
- jnz @@isthere\r
- ret ;nothing to draw\r
-\r
-@@isthere:\r
- test bx,1\r
- jnz @@odd\r
- jmp @@even\r
-;\r
-; clear the last byte so word draws can be used\r
-;\r
-@@odd:\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line+bx],al\r
-line = line+1\r
-ENDM\r
-\r
- inc bx\r
-@@even:\r
- mov ax,[linewidth]\r
- sub ax,bx\r
- mov [screenextra],ax\r
- mov ax,BUFFWIDTH\r
- sub ax,bx\r
- mov [bufferextra],ax\r
- mov dx,bx\r
-\r
- mov bx,[bufferheight] ;lines to copy\r
- mov bp,[fontcolormask]\r
-@@lineloop:\r
- mov cx,dx\r
-@@byteloop:\r
- lodsb ;get a word from the buffer\r
- and ax,bp\r
- xor [es:di],al ;draw it\r
- inc di\r
- loop @@byteloop\r
-\r
- add si,[bufferextra]\r
- add di,[screenextra]\r
-\r
- dec bx\r
- jnz @@lineloop\r
-\r
- ret\r
-ENDP\r
-\r
-\r
-DATASEG\r
-\r
-;============================================================================\r
-;\r
-; NON MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfont\r
-\r
-DATASEG\r
-\r
-shiftdrawtable dw 0,shift1wide,shift2wide,shift3wide,shift4wide\r
- dw shift5wide,shift6wide\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
- mov cx,[bufferbit]\r
- add cx,si ;add twice because pixel == two bits\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,3\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:shiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-shift1wide:\r
- dec dx\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-shift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-shift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-;\r
-; four byte character\r
-;\r
-shift4wide:\r
- sub dx,4\r
-EVEN\r
-@@loop4:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop4\r
-\r
- ret\r
-\r
-\r
-;\r
-; five byte character\r
-;\r
-shift5wide:\r
- sub dx,5\r
-EVEN\r
-@@loop5:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop5\r
-\r
- ret\r
-\r
-;\r
-; six byte character\r
-;\r
-shift6wide:\r
- sub dx,6\r
-EVEN\r
-@@loop6:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop6\r
-\r
- ret\r
-\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-;==================\r
-\r
-CODESEG\r
-\r
-PROC VW_DrawPropString string:DWORD\r
-PUBLIC VW_DrawPropString\r
-USES SI,DI\r
-\r
-;\r
-; proportional spaceing, which clears the buffer ahead of it, so only\r
-; clear the first collumn\r
-;\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line],al\r
-line = line+1\r
-ENDM\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
-@@shiftchars:\r
- mov ax,[px]\r
- and ax,3\r
- shl ax,1 ;one pixel == two bits\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- mov bx,[bufferbit]\r
- shr bx,1 ;two bits == one pixel\r
- or ax,bx\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call VWL_XORBuffer\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ;numfont\r
-\r
-;============================================================================\r
-;\r
-; MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfontm\r
-\r
-DATASEG\r
-\r
-mshiftdrawtable dw 0,mshift1wide,mshift2wide,mshift3wide\r
-\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftMPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftMPropChar NEAR\r
-\r
- mov es,[grsegs+STARTFONTM*2] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
-;\r
-; advance position by character width\r
-;\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:mshiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-mshift1wide:\r
- dec dx\r
-\r
-EVEN\r
-@@loop1m:\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-mshift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-mshift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawMPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-;==================\r
-\r
-\r
-\r
-PROC VW_DrawMPropString string:DWORD\r
-PUBLIC VW_DrawMPropString\r
-USES SI,DI\r
-\r
-;\r
-; clear out the first byte of the buffer, the rest will automatically be\r
-; cleared as characters are drawn into it\r
-;\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov dx,[es:pcharheight]\r
- mov di,OFFSET databuffer\r
- mov ax,ds\r
- mov es,ax\r
- mov bx,BUFFWIDTH-1\r
-\r
- mov cx,dx\r
- mov al,0ffh\r
-@@maskfill:\r
- stosb ; fill the mask part with $ff\r
- add di,bx\r
- loop @@maskfill\r
-\r
- mov cx,dx\r
- xor al,al\r
-@@datafill:\r
- stosb ; fill the data part with $0\r
- add di,bx\r
- loop @@datafill\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftMPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen ; cut out mask\r
- ; or in data\r
- call BufferToScreen ; SI is still in the right position in buffer\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ; if numfontm\r
-\r
-endif ; if fonts\r
+++ /dev/null
-; Reconstructed Commander Keen 4-6 Source Code\r
-; Copyright (C) 2021 K1n9_Duk3\r
-;\r
-; This file is primarily based on:\r
-; Catacomb 3-D Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-;=================================\r
-;\r
-; EGA view manager routines\r
-;\r
-;=================================\r
-\r
-;============================================================================\r
-;\r
-; All EGA drawing routines that write out words need to have alternate forms\r
-; for starting on even and odd addresses, because writing a word at segment\r
-; offset 0xffff causes an exception! To work around this, write a single\r
-; byte out to make the address even, so it wraps cleanly at the end.\r
-;\r
-; All of these routines assume read/write mode 0, and will allways return\r
-; in that state.\r
-; The direction flag should be clear\r
-; readmap/writemask is left in an undefined state\r
-;\r
-;============================================================================\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Plot (int x,y,color)\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-plotpixels db 128,64,32,16,8,4,2,1\r
-\r
-CODESEG\r
-\r
-PROC VW_Plot x:WORD, y:WORD, color:WORD\r
-PUBLIC VW_Plot\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[y]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov bl,[BYTE color]\r
- xchg bl,[es:di] ; load latches and write pixel\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Vlin (int yl,yh,x,color)\r
-;\r
-;============================================================================\r
-\r
-PROC VW_Vlin yl:WORD, yh:WORD, x:WORD, color:WORD\r
-PUBLIC VW_Vlin\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[yl]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov cx,[yh]\r
- sub cx,[yl]\r
- inc cx ;number of pixels to plot\r
-\r
- mov bh,[BYTE color]\r
- mov dx,[linewidth]\r
-\r
-@@plot:\r
- mov bl,bh\r
- xchg bl,[es:di] ; load latches and write pixel\r
- add di,dx\r
-\r
- loop @@plot\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;===================\r
-;\r
-; VW_DrawTile8\r
-;\r
-; xcoord in bytes (8 pixels), ycoord in pixels\r
-; All Tile8s are in one grseg, so an offset is calculated inside it\r
-;\r
-;===================\r
-\r
-PROC VW_DrawTile8 xcoord:WORD, ycoord:WORD, tile:WORD\r
-PUBLIC VW_DrawTile8\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- add di,[xcoord]\r
- mov bx,[ycoord]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov [ss:screendest],di ;screen destination\r
-\r
- mov bx,[linewidth]\r
- dec bx\r
-\r
- mov si,[tile]\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
-\r
- mov ds,[grsegs+STARTTILE8*2] ; segment for all tile8s\r
-\r
- mov cx,4 ;planes to draw\r
- mov ah,0001b ;map mask\r
-\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
-\r
-;\r
-; start drawing\r
-;\r
-\r
-@@planeloop:\r
- WORDOUT\r
- shl ah,1 ;shift plane mask over for next plane\r
-\r
- mov di,[ss:screendest] ;start at same place in all planes\r
-\r
-REPT 7\r
- movsb\r
- add di,bx\r
-ENDM\r
- movsb\r
-\r
- loop @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MaskBlock\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then four planes of data.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-UNWOUNDMASKS = 10\r
-\r
-\r
-maskroutines dw mask0,mask0,mask1E,mask1E,mask2E,mask2O,mask3E,mask3O\r
- dw mask4E,mask4O,mask5E,mask5O,mask6E,mask6O\r
- dw mask7E,mask7O,mask8E,mask8O,mask9E,mask9O\r
- dw mask10E,mask10O\r
-\r
-\r
-routinetouse dw ?\r
-\r
-CODESEG\r
-\r
-PROC VW_MaskBlock segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD, planesize:WORD\r
-PUBLIC VW_MaskBlock\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov [BYTE planemask],1\r
- mov [BYTE planenum],0\r
-\r
- mov di,[wide]\r
- mov dx,[linewidth]\r
- sub dx,[wide]\r
- mov [linedelta],dx ;amount to add after drawing each line\r
-\r
- mov bx,[planesize] ; si+bx = data location\r
-\r
- cmp di,UNWOUNDMASKS\r
- jbe @@unwoundroutine\r
- mov [routinetouse],OFFSET generalmask\r
- jmp NEAR @@startloop\r
-\r
-;=================\r
-;\r
-; use the unwound routines\r
-;\r
-;=================\r
-\r
-@@unwoundroutine:\r
- mov cx,[dest]\r
- shr cx,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,[maskroutines+di] ;call the right routine\r
- mov [routinetouse],ax\r
-\r
-@@startloop:\r
- mov ds,[segm]\r
-\r
-@@drawplane:\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[ss:planemask]\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov al,GC_READMAP\r
- mov ah,[ss:planenum]\r
- WORDOUT\r
-\r
- mov si,[ofs] ;start back at the top of the mask\r
- mov di,[dest] ;start at same place in all planes\r
- mov cx,[height] ;scan lines to draw\r
- mov dx,[ss:linedelta]\r
-\r
- jmp [ss:routinetouse] ;draw one plane\r
-planereturn: ;routine jmps back here\r
-\r
- add bx,[ss:planesize] ;start of mask = start of next plane\r
-\r
- inc [ss:planenum]\r
- shl [ss:planemask],1 ;shift plane mask over for next plane\r
- cmp [ss:planemask],10000b ;done all four planes?\r
- jne @@drawplane\r
-\r
-mask0:\r
- mov ax,ss\r
- mov ds,ax\r
- ret ;width of 0 = no drawing\r
-\r
-;==============\r
-;\r
-; General purpose masked block drawing. This could be optimised into\r
-; four routines to use words, but few play loop sprites should be this big!\r
-;\r
-;==============\r
-\r
-generalmask:\r
- mov dx,cx\r
-\r
-@@lineloopgen:\r
- mov cx,[wide]\r
-@@byteloop:\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
- loop @@byteloop\r
-\r
- add di,[ss:linedelta]\r
- dec dx\r
- jnz @@lineloopgen\r
- jmp planereturn\r
-\r
-;=================\r
-;\r
-; Horizontally unwound routines to draw certain masked blocks faster\r
-;\r
-;=================\r
-\r
-MACRO MASKBYTE\r
- lodsb\r
- and al,[es:di]\r
- or al,[bx+si-1]\r
- stosb\r
-ENDM\r
-\r
-MACRO MASKWORD\r
- lodsw\r
- and ax,[es:di]\r
- or ax,[bx+si-2]\r
- stosw\r
-ENDM\r
-\r
-MACRO SPRITELOOP addr\r
- add di,dx\r
- loop addr\r
- jmp planereturn\r
-ENDM\r
-\r
-\r
-EVEN\r
-mask1E:\r
- MASKBYTE\r
- SPRITELOOP mask1E\r
-\r
-EVEN\r
-mask2E:\r
- MASKWORD\r
- SPRITELOOP mask2E\r
-\r
-EVEN\r
-mask2O:\r
- MASKBYTE\r
- MASKBYTE\r
- SPRITELOOP mask2O\r
-\r
-EVEN\r
-mask3E:\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask3E\r
-\r
-EVEN\r
-mask3O:\r
- MASKBYTE\r
- MASKWORD\r
- SPRITELOOP mask3O\r
-\r
-EVEN\r
-mask4E:\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask4E\r
-\r
-EVEN\r
-mask4O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask4O\r
-\r
-EVEN\r
-mask5E:\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask5E\r
-\r
-EVEN\r
-mask5O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask5O\r
-\r
-EVEN\r
-mask6E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask6E\r
-\r
-EVEN\r
-mask6O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask6O\r
-\r
-EVEN\r
-mask7E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask7E\r
-\r
-EVEN\r
-mask7O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask7O\r
-\r
-EVEN\r
-mask8E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask8E\r
-\r
-EVEN\r
-mask8O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask8O\r
-\r
-EVEN\r
-mask9E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask9E\r
-\r
-EVEN\r
-mask9O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask9O\r
-\r
-EVEN\r
-mask10E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask10E\r
-\r
-EVEN\r
-mask10O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask10O\r
-\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_InverseMask\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then four planes of data.\r
-;\r
-;============================================================================\r
-\r
-PROC VW_InverseMask segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_InverseMask\r
-USES SI,DI\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE+16*256 ;set function = OR\r
- WORDOUT\r
-\r
- mov es, [screenseg]\r
- mov ax, [wide]\r
- mov dx, [linewidth]\r
- sub dx, ax;\r
- mov ds, [segm]\r
- mov si, [ofs]\r
- mov di, [dest]\r
- mov bx, [height]\r
-@@yloop:\r
- mov cx, [wide]\r
-@@xloop:\r
- lodsb\r
- not al\r
- xchg al, [es:di]\r
- inc di\r
- loop @@xloop\r
- add di, dx\r
- dec bx\r
- jnz @@yloop\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE+0*256 ;set function = no change\r
- WORDOUT\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-;\r
-; VW_ScreenToScreen\r
-;\r
-; Basic block copy routine. Copies one block of screen memory to another,\r
-; using write mode 1 (sets it and returns with write mode 0). bufferofs is\r
-; NOT accounted for.\r
-;\r
-;============================================================================\r
-\r
-PROC VW_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToScreen\r
-USES SI,DI\r
-\r
- pushf\r
- cli\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- popf\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ax,[screenseg]\r
- mov es,ax\r
- mov ds,ax\r
-\r
- mov si,[source]\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
-\r
-@@lineloop:\r
- mov cx,ax\r
- rep movsb\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MemToScreen\r
-;\r
-; Basic block drawing routine. Takes a block shape at segment pointer source\r
-; with four planes of width by height data, and draws it to dest in the\r
-; virtual screen, based on linewidth. bufferofs is NOT accounted for.\r
-; There are four drawing routines to provide the best optimized code while\r
-; accounting for odd segment wrappings due to the floating screens.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-memtoscreentable dw eventoeven,eventoodd,oddtoeven,oddtoodd\r
-\r
-CODESEG\r
-\r
-\r
-PROC VW_MemToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_MemToScreen\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[source]\r
-\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- xor di,di\r
- shr [wide],1 ;change wide to words, and see if carry is set\r
- rcl di,1 ;1 if wide is odd\r
- mov ax,[dest]\r
- shr ax,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
- jmp [ss:memtoscreentable+di] ;call the right routine\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an even video address\r
-;\r
-;==============\r
-\r
-eventoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEE:\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne eventoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an even video address\r
-;\r
-;==============\r
-\r
-oddtoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOE:\r
- mov cx,[wide]\r
- rep movsw\r
- movsb ;copy the last byte\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an odd video address\r
-;\r
-;==============\r
-\r
-eventoodd:\r
- dec [wide] ;one word has to be handled seperately\r
-EOplaneloop:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
- movsb\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne EOplaneloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an odd video address\r
-;\r
-;==============\r
-\r
-oddtoodd:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoodd\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;===========================================================================\r
-;\r
-; VW_ScreenToMem\r
-;\r
-; Copies a block of video memory to main memory, in order from planes 0-3.\r
-; This could be optimized along the lines of VW_MemToScreen to take advantage\r
-; of word copies, but this is an infrequently called routine.\r
-;\r
-;===========================================================================\r
-\r
-PROC VW_ScreenToMem source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToMem\r
-USES SI,DI\r
-\r
- mov es,[dest]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[screenseg]\r
-\r
- mov ax,GC_READMAP ;read map for plane 0\r
-\r
- xor di,di\r
-\r
-@@planeloop:\r
- mov dx,GC_INDEX\r
- WORDOUT\r
-\r
- mov si,[source] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloop:\r
- mov cx,[wide]\r
- rep movsb\r
-\r
- add si,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- inc ah\r
- cmp ah,4 ;done all four planes?\r
- jne @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VWL_UpdateScreenBlocks\r
-;\r
-; Scans through the update matrix and copies any areas that have changed\r
-; to the visable screen, then zeros the update array\r
-;\r
-;============================================================================\r
-\r
-\r
-\r
-; AX 0/1 for scasb, temp for segment register transfers\r
-; BX width for block copies\r
-; CX REP counter\r
-; DX line width deltas\r
-; SI source for copies\r
-; DI scas dest / movsb dest\r
-; BP pointer to end of bufferblocks\r
-\r
-PROC VWL_UpdateScreenBlocks\r
-PUBLIC VWL_UpdateScreenBlocks\r
-USES SI,DI,BP\r
-\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- mov dx,GC_INDEX ; restore write mode 0\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- xor ax,ax ; clear out the update matrix\r
- mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-\r
- mov di,[updateptr]\r
- rep stosw\r
-\r
- ret\r
-\r
-@@realstart:\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- mov di,[updateptr] ; start of floating update screen\r
- mov bp,di\r
- add bp,UPDATEWIDE*UPDATEHIGH+1 ; when di = bp, all tiles have been scanned\r
-\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-\r
-;\r
-; scan for a 1 in the update list, meaning a tile needs to be copied\r
-; from the master screen to the current screen\r
-;\r
-@@findtile:\r
- pop di ; place to continue scaning from\r
- mov ax,ss\r
- mov es,ax ; search in the data segment\r
- mov ds,ax\r
- mov al,1\r
- repne scasb\r
- cmp di,bp\r
- jae @@done\r
-\r
- cmp [BYTE di],al\r
- jne @@singletile\r
- jmp @@tileblock\r
-\r
-;============\r
-;\r
-; copy a single tile\r
-;\r
-;============\r
-@@singletile:\r
- inc di ; we know the next tile is nothing\r
- push di ; save off the spot being scanned\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-4+di] ; start of tile location on screen\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,2\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- movsb\r
- movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
- jmp @@findtile\r
-\r
-;============\r
-;\r
-; more than one tile in a row needs to be updated, so do it as a group\r
-;\r
-;============\r
-EVEN\r
-@@tileblock:\r
- mov dx,di ; hold starting position + 1 in dx\r
- inc di ; we know the next tile also gets updated\r
- repe scasb ; see how many more in a row\r
- push di ; save off the spot being scanned\r
-\r
- mov bx,di\r
- sub bx,dx ; number of tiles in a row\r
- shl bx,1 ; number of bytes / row\r
-\r
- mov di,dx ; lookup position of start tile\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-2+di] ; start of tile location\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,bx ; offset to next line on screen\r
-\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- mov cx,bx\r
- rep movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- mov cx,bx\r
- rep movsb\r
-\r
- dec cx ; was 0 from last rep movsb, now $ffff for scasb\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-;\r
-; MISC EGA ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-;=================\r
-;\r
-; SyncVBL\r
-;\r
-;=================\r
-\r
-DATASEG\r
-\r
-EXTRN TimeCount :DWORD\r
-EXTRN jerk :WORD\r
-EXTRN nopan :WORD\r
-\r
-CODESEG\r
-\r
-PROC SyncVBL\r
- mov dx,STATUS_REGISTER_1\r
- mov bx,[WORD TimeCount]\r
- add bx,3\r
-@@waitloop:\r
- sti\r
- jmp $+2\r
- cli\r
- cmp [WORD TimeCount],bx\r
- je @@done\r
-@@waitnovert:\r
- in al,dx\r
- test al,1\r
- jnz @@waitnovert\r
-@@waitvert:\r
- in al,dx\r
- test al,1\r
- jz @@waitvert\r
-\r
-REPT 5\r
- in al,dx\r
- test al,8\r
- jnz @@waitloop\r
- test al,1\r
- jz @@waitloop\r
-ENDM\r
-\r
- test [jerk],1\r
- jz @@done\r
-\r
-REPT 5\r
- in al,dx\r
- test al,8\r
- jnz @@waitloop\r
- test al,1\r
- jz @@waitloop\r
-ENDM\r
-\r
-@@done:\r
- ret\r
-ENDP\r
-\r
-\r
-;==============\r
-;\r
-; VW_SetScreen\r
-;\r
-;==============\r
-\r
-PROC VW_SetScreen crtc:WORD, pel:WORD\r
-PUBLIC VW_SetScreen\r
-\r
- call SyncVBL\r
-;\r
-; set CRTC start\r
-;\r
-; for some reason, my XT's EGA card doesn't like word outs to the CRTC\r
-; index...\r
-;\r
- mov cx,[crtc]\r
- mov dx,CRTC_INDEX\r
- mov al,0ch ;start address high register\r
- out dx,al\r
- inc dx\r
- mov al,ch\r
- out dx,al\r
- dec dx\r
- mov al,0dh ;start address low register\r
- out dx,al\r
- mov al,cl\r
- inc dx\r
- out dx,al\r
-\r
- test [nopan],1\r
- jnz @@done\r
-;\r
-; set horizontal panning\r
-;\r
-\r
- mov dx,ATR_INDEX\r
- mov al,ATR_PELPAN or 20h\r
- out dx,al\r
- jmp $+2\r
- mov al,[BYTE pel] ;pel pan value\r
- out dx,al\r
-\r
-@@done:\r
- sti\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-if NUMFONT+NUMFONTM\r
-\r
-;===========================================================================\r
-;\r
-; GENERAL FONT DRAWING ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-DATASEG\r
-\r
-px dw ? ; proportional character drawing coordinates\r
-py dw ?\r
-pdrawmode db 11000b ; 8 = OR, 24 = XOR, put in GC_DATAROTATE\r
-fontcolor db 15 ;0-15 mapmask value\r
-\r
-PUBLIC px,py,pdrawmode,fontcolor\r
-\r
-;\r
-; offsets in font structure\r
-;\r
-pcharheight = 0 ;lines high\r
-charloc = 2 ;pointers to every character\r
-charwidth = 514 ;every character's width in pixels\r
-\r
-\r
-propchar dw ? ; the character number to shift\r
-stringptr dw ?,?\r
-\r
-\r
-BUFFWIDTH = 50\r
-BUFFHEIGHT = 32 ; must be twice as high as font for masked fonts\r
-\r
-databuffer db BUFFWIDTH*BUFFHEIGHT dup (?)\r
-\r
-bufferwidth dw ? ; bytes with valid info / line\r
-bufferheight dw ? ; number of lines currently used\r
-\r
-bufferbyte dw ?\r
-bufferbit dw ?\r
-\r
-screenspot dw ? ; where the buffer is going\r
-\r
-bufferextra dw ? ; add at end of a line copy\r
-screenextra dw ?\r
-\r
-PUBLIC bufferwidth,bufferheight,screenspot\r
-\r
-CODESEG\r
-\r
-;======================\r
-;\r
-; Macros to table shift a byte of font\r
-;\r
-;======================\r
-\r
-MACRO SHIFTNOXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- or [di],al ; or with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-MACRO SHIFTWITHXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- not ax\r
- and [di],al ; and with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-\r
-;=======================\r
-;\r
-; BufferToScreen\r
-;\r
-; Pass buffer start in SI (somewhere in databuffer)\r
-; Draws the buffer to the EGA screen in the current write mode\r
-;\r
-;========================\r
-\r
-PROC BufferToScreen NEAR\r
-\r
- mov es,[screenseg]\r
- mov di,[screenspot]\r
-\r
- mov bx,[bufferwidth] ;calculate offsets for end of each line\r
- or bx,bx\r
- jnz @@isthere\r
- ret ;nothing to draw\r
-\r
-@@isthere:\r
- mov ax,[linewidth]\r
- sub ax,bx\r
- mov [screenextra],ax\r
- mov ax,BUFFWIDTH\r
- sub ax,bx\r
- mov [bufferextra],ax\r
-\r
- mov bx,[bufferheight] ;lines to copy\r
-@@lineloop:\r
- mov cx,[bufferwidth] ;bytes to copy\r
-@@byteloop:\r
- lodsb ;get a byte from the buffer\r
- xchg [es:di],al ;load latches and store back to screen\r
- inc di\r
-\r
- loop @@byteloop\r
-\r
- add si,[bufferextra]\r
- add di,[screenextra]\r
-\r
- dec bx\r
- jnz @@lineloop\r
-\r
- ret\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; NON MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfont\r
-\r
-DATASEG\r
-\r
-shiftdrawtable dw 0,shift1wide,shift2wide,shift3wide,shift4wide\r
- dw shift5wide\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
-;\r
-; advance position by character width\r
-;\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:shiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-shift1wide:\r
- dec dx\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-shift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-shift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
- ret\r
-\r
-;\r
-; four byte character\r
-;\r
-shift4wide:\r
- sub dx,4\r
-EVEN\r
-@@loop4:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop4\r
- ret\r
-\r
-;\r
-; five byte character\r
-;\r
-shift5wide:\r
- sub dx,5\r
-EVEN\r
-@@loop5:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop5\r
- ret\r
-\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-CODESEG\r
-\r
-PROC VW_DrawPropString string:DWORD\r
-PUBLIC VW_DrawPropString\r
-USES SI,DI\r
-\r
-;\r
-; proportional spaceing, which clears the buffer ahead of it, so only\r
-; clear the first collumn\r
-;\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line],al\r
-line = line+1\r
-ENDM\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
-@@shiftchars:\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
-\r
-; set xor/or mode\r
- mov dx,GC_INDEX\r
- mov al,GC_DATAROTATE\r
- mov ah,[pdrawmode]\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ;numfont\r
-\r
-;============================================================================\r
-;\r
-; MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfontm\r
-\r
-DATASEG\r
-\r
-mshiftdrawtable dw 0,mshift1wide,mshift2wide,mshift3wide\r
-\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftMPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftMPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:mshiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-mshift1wide:\r
- dec dx\r
-\r
-EVEN\r
-@@loop1m:\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-mshift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-mshift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawMPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-\r
-\r
-PROC VW_DrawMPropString string:DWORD\r
-PUBLIC VW_DrawMPropString\r
-USES SI,DI\r
-\r
-;\r
-; clear out the first byte of the buffer, the rest will automatically be\r
-; cleared as characters are drawn into it\r
-;\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si]\r
- mov dx,[es:pcharheight]\r
- mov di,OFFSET databuffer\r
- mov ax,ds\r
- mov es,ax\r
- mov bx,BUFFWIDTH-1\r
-\r
- mov cx,dx\r
- mov al,0ffh\r
-@@maskfill:\r
- stosb ; fill the mask part with $ff\r
- add di,bx\r
- loop @@maskfill\r
-\r
- mov cx,dx\r
- xor al,al\r
-@@datafill:\r
- stosb ; fill the data part with $0\r
- add di,bx\r
- loop @@datafill\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftMPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
-; set AND mode to punch out the mask\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 8*256\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set OR mode to fill in the color\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 16*256\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- call BufferToScreen ; SI is still in the right position in buffer\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ; if numfontm\r
-\r
-endif ; if fonts\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __AUDIO_H__\r
-#define __AUDIO_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// MUSE Header for .CK4\r
-//\r
-/////////////////////////////////////////////////\r
-\r
-#define NUMSOUNDS LASTSOUND\r
-#define NUMSNDCHUNKS ((3*LASTSOUND)+LASTMUSIC)\r
-\r
-//\r
-// Sound names & indexes\r
-//\r
-typedef enum {\r
- SND_WORLDWALK1,\r
- SND_WORLDWALK2,\r
- SND_JUMP,\r
- SND_LAND,\r
- SND_KEENFIRE,\r
- SND_WORMOUTHATTACK,\r
- SND_6,\r
- SND_POGOBOUNCE,\r
- SND_GETPOINTS,\r
- SND_GETAMMO,\r
- SND_GETWATER,\r
- SND_11,\r
- SND_ENTERLEVEL,\r
- SND_LEVELDONE,\r
- SND_NOWAY,\r
- SND_HELMETHIT,\r
- SND_BOUNCE2,\r
- SND_EXTRAKEEN,\r
- SND_OPENDOOR,\r
- SND_GETKEY,\r
- SND_PLUMMET,\r
- SND_USESWITCH,\r
- SND_SQUISH,\r
- SND_KEENDEAD,\r
- SND_24,\r
- SND_SHOTEXPLODE,\r
- SND_SWIM1,\r
- SND_SWIM2,\r
- SND_BOUNCE1,\r
- SND_EATBONUS,\r
- SND_TREASUREEATERVANISH,\r
- SND_LINDSEY,\r
- SND_LICKATTACK,\r
- SND_BERKELOIDATTACK,\r
- SND_SHOWSTATUS,\r
- SND_HIDESTATUS,\r
- SND_BLUB,\r
- SND_MINEEXPLODE,\r
- SND_SPRITEFIRE,\r
- SND_THUNDER,\r
- SND_FIREBALLLAND,\r
- SND_SHOOTDART,\r
- SND_BURP,\r
- SND_FLAGSPIN,\r
- SND_FLAGLAND,\r
- SND_MAKEFOOT,\r
- SND_SLUGPOO,\r
- KEENPADDLESND,\r
- BALLBOUNCESND,\r
- COMPPADDLESND,\r
- COMPSCOREDSND,\r
- KEENSCOREDSND,\r
- LASTSOUND\r
-} soundnames;\r
-\r
-#if LASTSOUND != 52\r
-#error bad sound enum!\r
-#endif\r
-\r
-#define NOWAYSND SND_NOWAY\r
-\r
-//\r
-// Base offsets\r
-//\r
-#define STARTPCSOUNDS 0\r
-#define STARTADLIBSOUNDS (STARTPCSOUNDS+NUMSOUNDS)\r
-#define STARTDIGISOUNDS (STARTADLIBSOUNDS+NUMSOUNDS)\r
-#define STARTMUSIC (STARTDIGISOUNDS+NUMSOUNDS)\r
-\r
-//\r
-// Music names & indexes\r
-//\r
-typedef enum {\r
- SHADOWS_MUS,\r
- VEGGIES_MUS,\r
- TOOHOT_MUS,\r
- OASIS_MUS,\r
- KICKPANT_MUS,\r
- WONDER_MUS,\r
- LASTMUSIC\r
-} musicnames;\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// Thanks for playing with MUSE!\r
-//\r
-/////////////////////////////////////////////////\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-;=====================================\r
-;\r
-; Graphics .EQU file for .CK4\r
-; not IGRAB-ed :)\r
-;\r
-;=====================================\r
-\r
-;INCLUDE "VERSION.EQU"\r
-\r
-;\r
-; Amount of each data item\r
-;\r
-NUMFONT = 3\r
-NUMFONTM = 0\r
-NUMPICM = 3\r
-NUMTILE8 = 108\r
-NUMTILE8M = 36\r
-NUMTILE32 = 0\r
-NUMTILE32M = 0\r
-\r
-;\r
-; Amount of each item in episode 4\r
-;\r
-NUMPICS = 115\r
-NUMSPRITES = 397\r
-NUMTILE16 = 1296\r
-NUMTILE16M = 2916\r
-NUMEXTERN = 16\r
-\r
-\r
-;\r
-; File offsets for data items\r
-;\r
-STRUCTPIC = 0\r
-STRUCTPICM = 1\r
-STRUCTSPRITE = 2\r
-\r
-STARTFONT = 3\r
-STARTFONTM = (STARTFONT+NUMFONT)\r
-STARTPICS = (STARTFONTM+NUMFONTM)\r
-STARTPICM = (STARTPICS+NUMPICS)\r
-STARTSPRITES = (STARTPICM+NUMPICM)\r
-STARTTILE8 = (STARTSPRITES+NUMSPRITES)\r
-STARTTILE8M = (STARTTILE8+1)\r
-STARTTILE16 = (STARTTILE8M+1)\r
-STARTTILE16M = (STARTTILE16+NUMTILE16)\r
-STARTTILE32 = (STARTTILE16M+NUMTILE16M)\r
-STARTTILE32M = (STARTTILE32+NUMTILE32)\r
-STARTEXTERN = (STARTTILE32M+NUMTILE32M)\r
-\r
-NUMCHUNKS = (STARTEXTERN+NUMEXTERN)\r
-\r
-;\r
-; Thank you for using IGRAB!\r
-;\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __GFX_H__\r
-#define __GFX_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-//////////////////////////////////////\r
-//\r
-// Graphics .H file for .CK4\r
-// not IGRAB-ed :)\r
-//\r
-//////////////////////////////////////\r
-\r
-//\r
-// Lump creation macros\r
-//\r
-\r
-#define START_LUMP(actualname, dummyname) actualname, dummyname=actualname-1,\r
-#define END_LUMP(actualname, dummyname) dummyname, actualname=dummyname-1,\r
-\r
-//\r
-// Amount of each data item\r
-//\r
-\r
-//common numbers:\r
-#define NUMCHUNKS NUMGRCHUNKS\r
-#define NUMFONT 3\r
-#define NUMFONTM 0\r
-#define NUMPICM 3\r
-#define NUMTILE8 108 // BUG: only 104 tiles exist in EGAGRAPH!\r
-#define NUMTILE8M 36 // BUG: only 20 tiles exist in EGAGRAPH!\r
-#define NUMTILE32 0\r
-#define NUMTILE32M 0\r
-\r
-//episode-specific numbers:\r
-#define NUMPICS 115\r
-#define NUMSPRITES 397\r
-#define NUMTILE16 1296\r
-#define NUMTILE16M 2916\r
-#define NUMEXTERNS 16\r
-\r
-//\r
-// File offsets for data items\r
-//\r
-#define STRUCTPIC 0\r
-#define STRUCTPICM 1\r
-#define STRUCTSPRITE 2\r
-\r
-#define STARTFONT 3\r
-#define STARTFONTM (STARTFONT+NUMFONT)\r
-#define STARTPICS (STARTFONTM+NUMFONTM)\r
-#define STARTPICM (STARTPICS+NUMPICS)\r
-#define STARTSPRITES (STARTPICM+NUMPICM)\r
-#define STARTTILE8 (STARTSPRITES+NUMSPRITES)\r
-#define STARTTILE8M (STARTTILE8+1)\r
-#define STARTTILE16 (STARTTILE8M+1)\r
-#define STARTTILE16M (STARTTILE16+NUMTILE16)\r
-#define STARTTILE32 (STARTTILE16M+NUMTILE16M)\r
-#define STARTTILE32M (STARTTILE32+NUMTILE32)\r
-#define STARTEXTERNS (STARTTILE32M+NUMTILE32M)\r
-\r
-typedef enum {\r
- LASTFONT=STARTPICS-1,\r
-\r
- //\r
- // PICS\r
- //\r
-\r
- H_HELPPIC, // 6\r
- H_LARROWPIC, // 7\r
- H_RARROWPIC, // 8\r
- H_ESCPIC, // 9\r
- H_ENTERPIC, // 10\r
- DUMMYPIC, // 11\r
- H_STORY1PIC, // 12\r
- H_STORY2PIC, // 13\r
- H_STORY3PIC, // 14\r
- H_STORY4PIC, // 15\r
- STORY5PIC, // 16\r
- STORY6PIC, // 17\r
- STORY7PIC, // 18\r
- STORY8PIC, // 19\r
- ITEM1PIC, // 20\r
- ITEM2PIC, // 21\r
- ITEM3PIC, // 22\r
- ITEM4PIC, // 23\r
- ITEM5PIC, // 24\r
- ITEM6PIC, // 25\r
- ITEM7PIC, // 26\r
- ITEM8PIC, // 27\r
- ITEM9PIC, // 28\r
- ARACHNUTPIC, // 29\r
- BERKELOISPIC, // 30\r
- BOUNDERPIC, // 31\r
- COUNCILMEMBERPIC, // 32\r
- DOPEFISHPIC, // 33\r
- INCHWORMPIC, // 34\r
- LICKPIC, // 35\r
- MADMUSHROOMPIC, // 36\r
- POISONSLIGPIC, // 37\r
- PRINCESSLINDSEYPIC, // 38\r
- SCHOOLFISHPIC, // 39\r
- SKYPESTPIC, // 40\r
- SPRITEPIC, // 41\r
- WORMOUTHPIC, // 42\r
- ENDOFTEXTPIC, // 43\r
- H_MCPIC, // 44\r
- H_HANDPIC, // 45\r
- H_VISAPIC, // 46\r
- H_FLASHARROW1PIC, // 47\r
- H_FLASHARROW2PIC, // 48\r
- ENDINDG1PIC, // 49\r
- ENDINDG2PIC, // 50\r
- ENDINDG3PIC, // 51\r
- ENDINDG4PIC, // 52\r
- ENDINDG5PIC, // 53\r
- ENDINDG6PIC, // 54\r
- ENDINDG7PIC, // 55\r
- ENDINDG8PIC, // 56\r
- ENDINDG9PIC, // 57\r
- ENDINDG10PIC, // 58\r
- ENDINDG11PIC, // 59\r
- ENDINDG12PIC, // 60\r
- ENDINDG13PIC, // 61\r
- ENDINDG14PIC, // 62\r
- ENDINDG15PIC, // 63\r
- ENDINDG16PIC, // 64\r
- ENDINDG17PIC, // 65\r
- ENDINDG18PIC, // 66\r
- ENDINDG19PIC, // 67\r
- ENDINDG20PIC, // 68\r
- ENDINDG21PIC, // 69\r
- ENDINDG22PIC, // 70\r
- ENDINDG23PIC, // 71\r
- ENDINDG24PIC, // 72\r
- ENDINDG25PIC, // 73\r
- ENDINDG26PIC, // 74\r
- ENDINDG27PIC, // 75\r
- ENDINDG28PIC, // 76\r
- ENDINDG29PIC, // 77\r
- ENDINDG30PIC, // 78\r
- H_IDLOGOPIC, // 79\r
- H_TOPWINDOWPIC, // 80\r
- H_LEFTWINDOWPIC, // 81\r
- H_RIGHTWINDOWPIC, // 82\r
- H_BOTTOMINFOPIC, // 83\r
- H_BOTTOMWINDOWPIC, // 84\r
- H_BARPIC, // 85\r
- H_KEEN5PIC, // 86\r
- H_KEEN6PIC, // 87\r
-\r
- START_LUMP(CONTROLS_LUMP_START, __CONTROLSSTART)\r
- CP_MAINMENUPIC, // 88\r
- CP_NEWGAMEMENUPIC, // 89\r
- CP_LOADMENUPIC, // 90\r
- CP_SAVEMENUPIC, // 91\r
- CP_CONFIGMENUPIC, // 92\r
- CP_SOUNDMENUPIC, // 93\r
- CP_MUSICMENUPIC, // 94\r
- CP_KEYBOARDMENUPIC, // 95\r
- CP_KEYMOVEMENTPIC, // 96\r
- CP_KEYBUTTONPIC, // 97\r
- CP_JOYSTICKMENUPIC, // 98\r
- CP_OPTIONSMENUPIC, // 99\r
- CP_PADDLEWARPIC, // 100\r
- CP_QUITPIC, // 101\r
- CP_JOYSTICKPIC, // 102\r
- CP_MENUSCREENPIC, // 103\r
- END_LUMP(CONTROLS_LUMP_END, __CONTROLSEND)\r
-\r
- IDSOFTPIC, // 104\r
- PROGTEAMPIC, // 105\r
- ARTISTPIC, // 106\r
- DIRECTORPIC, // 107\r
- SW_BACKGROUNDPIC, // 108\r
- TITLEPICPIC, // 109\r
- ORACLEPIC, // 110\r
- KEENTALK1PIC, // 111\r
- KEENTALK2PIC, // 112\r
- KEENMADPIC, // 113\r
- LINDSEYPIC, // 114\r
- KEENCOUNT1PIC, // 115\r
- KEENCOUNT2PIC, // 116\r
- KEENCOUNT3PIC, // 117\r
- KEENCOUNT4PIC, // 118\r
- KEENCOUNT5PIC, // 119\r
- KEENCOUNT6PIC, // 120\r
-\r
- //\r
- // MASKED PICS\r
- //\r
-\r
- CP_MENUMASKPICM, // 121\r
- CORDPICM, // 122\r
- METALPOLEPICM, // 123\r
-\r
- //\r
- // SPRITES\r
- //\r
-\r
- START_LUMP(PADDLE_LUMP_START, __PADDLESTART)\r
- PADDLESPR, // 124\r
- BALLSPR, // 125\r
- BALL1PIXELTOTHERIGHTSPR, // 126\r
- BALL2PIXELSTOTHERIGHTSPR, // 127\r
- BALL3PIXELSTOTHERIGHTSPR, // 128\r
- END_LUMP(PADDLE_LUMP_END, __PADDLEEND)\r
-\r
- DEMOPLAQUESPR, // 129\r
-\r
- //player lump:\r
- START_LUMP(KEEN_LUMP_START, __KEENSTART)\r
- KEENSTANDRSPR, // 130\r
- KEENRUNR1SPR, // 131\r
- KEENRUNR2SPR, // 132\r
- KEENRUNR3SPR, // 133\r
- KEENRUNR4SPR, // 134\r
- KEENJUMPR1SPR, // 135\r
- KEENJUMPR2SPR, // 136\r
- KEENJUMPR3SPR, // 137\r
- KEENSTANDLSPR, // 138\r
- KEENRUNL1SPR, // 139\r
- KEENRUNL2SPR, // 140\r
- KEENRUNL3SPR, // 141\r
- KEENRUNL4SPR, // 142\r
- KEENJUMPL1SPR, // 143\r
- KEENJUMPL2SPR, // 144\r
- KEENJUMPL3SPR, // 145\r
- KEENLOOKUSPR, // 146\r
- KEENWAITR1SPR, // 147\r
- KEENWAITR2SPR, // 148\r
- KEENWAITR3SPR, // 149\r
- KEENSITREAD1SPR, // 150\r
- KEENSITREAD2SPR, // 151\r
- KEENSITREAD3SPR, // 152\r
- KEENSITREAD4SPR, // 153\r
- KEENREAD1SPR, // 154\r
- KEENREAD2SPR, // 155\r
- KEENREAD3SPR, // 156\r
- KEENSTOPREAD1SPR, // 157\r
- KEENSTOPREAD2SPR, // 158\r
- KEENWATCHSPR, // 159\r
- KEENLOOKD1SPR, // 160\r
- KEENLOOKD2SPR, // 161\r
- KEENDIE1SPR, // 162\r
- KEENDIE2SPR, // 163\r
- STUNSTARS1SPR, // 164\r
- STUNSTARS2SPR, // 165\r
- STUNSTARS3SPR, // 166\r
- KEENSHOOTLSPR, // 167\r
- KEENJLSHOOTLSPR, // 168\r
- KEENJSHOOTDSPR, // 169\r
- KEENJSHOOTUSPR, // 170\r
- KEENSHOOTUSPR, // 171\r
- KEENSHOOTRSPR, // 172\r
- KEENJRSHOOTRSPR, // 173\r
- STUN1SPR, // 174\r
- STUN2SPR, // 175\r
- STUN3SPR, // 176\r
- STUN4SPR, // 177\r
- STUNHIT1SPR, // 178\r
- STUNHIT2SPR, // 179\r
- KEENSHINNYR1SPR, // 180\r
- KEENSHINNYR2SPR, // 181\r
- KEENSHINNYR3SPR, // 182\r
- KEENSLIDED1SPR, // 183\r
- KEENSLIDED2SPR, // 184\r
- KEENSLIDED3SPR, // 185\r
- KEENSLIDED4SPR, // 186\r
- KEENSHINNYL1SPR, // 187\r
- KEENSHINNYL2SPR, // 188\r
- KEENSHINNYL3SPR, // 189\r
- KEENPLSHOOTUSPR, // 190\r
- KEENPRSHOOTUSPR, // 191\r
- KEENPRSHOOTDSPR, // 192\r
- KEENPLSHOOTDSPR, // 193\r
- KEENPSHOOTLSPR, // 194\r
- KEENPSHOOTRSPR, // 195\r
- KEENENTER1SPR, // 196\r
- KEENENTER2SPR, // 197\r
- KEENENTER3SPR, // 198\r
- KEENENTER4SPR, // 199\r
- KEENENTER5SPR, // 200\r
- KEENHANGLSPR, // 201\r
- KEENHANGRSPR, // 202\r
- KEENCLIMBEDGEL1SPR, // 203\r
- KEENCLIMBEDGEL2SPR, // 204\r
- KEENCLIMBEDGEL3SPR, // 205\r
- KEENCLIMBEDGEL4SPR, // 206\r
- KEENCLIMBEDGER1SPR, // 207\r
- KEENCLIMBEDGER2SPR, // 208\r
- KEENCLIMBEDGER3SPR, // 209\r
- KEENCLIMBEDGER4SPR, // 210\r
- KEENPOGOR1SPR, // 211\r
- KEENPOGOR2SPR, // 212\r
- KEENPOGOL1SPR, // 213\r
- KEENPOGOL2SPR, // 214\r
- DROPSPLASH1SPR, // 215\r
- DROPSPLASH2SPR, // 216\r
- DROPSPLASH3SPR, // 217\r
- BONUS100UPSPR, // 218\r
- BONUS100SPR, // 219\r
- BONUS200SPR, // 220\r
- BONUS500SPR, // 221\r
- BONUS1000SPR, // 222\r
- BONUS2000SPR, // 223\r
- BONUS5000SPR, // 224\r
- BONUS1UPSPR, // 225\r
- BONUSCLIPSPR, // 226\r
- END_LUMP(KEEN_LUMP_END, __KEENEND)\r
-\r
- START_LUMP(SUGAR1_LUMP_START, __SUGAR1START)\r
- SUGAR1ASPR, // 227\r
- SUGAR1BSPR, // 228\r
- END_LUMP(SUGAR1_LUMP_END, __SUGAR1END)\r
-\r
- START_LUMP(SUGAR2_LUMP_START, __SUGAR2START)\r
- SUGAR2ASPR, // 229\r
- SUGAR2BSPR, // 230\r
- END_LUMP(SUGAR2_LUMP_END, __SUGAR2END)\r
-\r
- START_LUMP(SUGAR3_LUMP_START, __SUGAR3START)\r
- SUGAR3ASPR, // 231\r
- SUGAR3BSPR, // 232\r
- END_LUMP(SUGAR3_LUMP_END, __SUGAR3END)\r
-\r
- START_LUMP(SUGAR4_LUMP_START, __SUGAR4START)\r
- SUGAR4ASPR, // 233\r
- SUGAR4BSPR, // 234\r
- END_LUMP(SUGAR4_LUMP_END, __SUGAR4END)\r
-\r
- START_LUMP(SUGAR5_LUMP_START, __SUGAR5START)\r
- SUGAR5ASPR, // 235\r
- SUGAR5BSPR, // 236\r
- END_LUMP(SUGAR5_LUMP_END, __SUGAR5END)\r
-\r
- START_LUMP(SUGAR6_LUMP_START, __SUGAR6START)\r
- SUGAR6ASPR, // 237\r
- SUGAR6BSPR, // 238\r
- END_LUMP(SUGAR6_LUMP_END, __SUGAR6END)\r
-\r
- START_LUMP(ONEUP_LUMP_START, __ONEUPSTART)\r
- ONEUPASPR, // 239\r
- ONEUPBSPR, // 240\r
- END_LUMP(ONEUP_LUMP_END, __ONEUPEND)\r
-\r
- DOORSPR, // 241\r
-\r
- START_LUMP(KEYGEM_LUMP_START, __KEYGEMSTART)\r
- REDGEM1SPR, // 242\r
- REDGEM2SPR, // 243\r
- YELLOWGEM1SPR, // 244\r
- YELLOWGEM2SPR, // 245\r
- BLUEGEM1SPR, // 246\r
- BLUEGEM2SPR, // 247\r
- GREENGEM1SPR, // 248\r
- GREENGEM2SPR, // 249\r
- BONUSGEMSPR, // 250\r
- END_LUMP(KEYGEM_LUMP_END, __KEYGEMEND)\r
-\r
- START_LUMP(AMMO_LUMP_START, __AMMOSTART)\r
- STUNCLIP1SPR, // 251\r
- STUNCLIP2SPR, // 252\r
- END_LUMP(AMMO_LUMP_END, __AMMOEND)\r
-\r
- SCOREBOXSPR, // 253\r
-\r
- START_LUMP(WORLDKEEN_LUMP_START, __WORLDKEENSTART)\r
- WORLDKEENL1SPR, // 254\r
- WORLDKEENL2SPR, // 255\r
- WORLDKEENL3SPR, // 256\r
- WORLDKEENR1SPR, // 257\r
- WORLDKEENR2SPR, // 258\r
- WORLDKEENR3SPR, // 259\r
- WORLDKEENU1SPR, // 260\r
- WORLDKEENU2SPR, // 261\r
- WORLDKEENU3SPR, // 262\r
- WORLDKEEND1SPR, // 263\r
- WORLDKEEND2SPR, // 264\r
- WORLDKEEND3SPR, // 265\r
- WORLDKEENDR1SPR, // 266\r
- WORLDKEENDR2SPR, // 267\r
- WORLDKEENDR3SPR, // 268\r
- WORLDKEENDL1SPR, // 269\r
- WORLDKEENDL2SPR, // 270\r
- WORLDKEENDL3SPR, // 271\r
- WORLDKEENUL1SPR, // 272\r
- WORLDKEENUL2SPR, // 273\r
- WORLDKEENUL3SPR, // 274\r
- WORLDKEENUR1SPR, // 275\r
- WORLDKEENUR2SPR, // 276\r
- WORLDKEENUR3SPR, // 277\r
- WORLDKEENWAVE1SPR, // 278\r
- WORLDKEENWAVE2SPR, // 279\r
- WORLDKEENSWIMU1SPR, // 280\r
- WORLDKEENSWIMU2SPR, // 281\r
- WORLDKEENSWIMR1SPR, // 282\r
- WORLDKEENSWIMR2SPR, // 283\r
- WORLDKEENSWIMD1SPR, // 284\r
- WORLDKEENSWIMD2SPR, // 285\r
- WORLDKEENSWIML1SPR, // 286\r
- WORLDKEENSWIML2SPR, // 287\r
- WORLDKEENSWIMUR1SPR, // 288\r
- WORLDKEENSWIMUR2SPR, // 289\r
- WORLDKEENSWIMDR1SPR, // 290\r
- WORLDKEENSWIMDR2SPR, // 291\r
- WORLDKEENSWIMDL1SPR, // 292\r
- WORLDKEENSWIMDL2SPR, // 293\r
- WORLDKEENSWIMUL1SPR, // 294\r
- WORLDKEENSWIMUL2SPR, // 295\r
- WOLRDKEENRIDE1SPR, // 296\r
- WOLRDKEENRIDE2SPR, // 297\r
- FLAGFLIP1SPR, // 298\r
- FLAGFLIP2SPR, // 299\r
- FLAGFLIP3SPR, // 300\r
- FLAGFLIP4SPR, // 301\r
- FLAGFLIP5SPR, // 302\r
- FLAGFALL1SPR, // 303\r
- FLAGFALL2SPR, // 304\r
- FLAGFLAP1SPR, // 305\r
- FLAGFLAP2SPR, // 306\r
- FLAGFLAP3SPR, // 307\r
- FLAGFLAP4SPR, // 308\r
- END_LUMP(WORLDKEEN_LUMP_END, __WORLDKEENEND)\r
-\r
- START_LUMP(SCUBAKEEN_LUMP_START, __SCUBAKEENSTART)\r
- SCUBAKEENL1SPR, // 309\r
- SCUBAKEENL2SPR, // 310\r
- SCUBAKEENR1SPR, // 311\r
- SCUBAKEENR2SPR, // 312\r
- SCUBAKEENDEAD1SPR, // 313\r
- SCUBAKEENDEAD2SPR, // 314\r
- END_LUMP(SCUBAKEEN_LUMP_END, __SCUBAKEENEND)\r
-\r
- START_LUMP(SLUG_LUMP_START, __SLUGSTART)\r
- SLUGWALKR1SPR, // 315\r
- SLUGWALKR2SPR, // 316\r
- SLUGPISSRSPR, // 317\r
- SLUGSTUN1SPR, // 318\r
- SLUGSTUN2SPR, // 319\r
- SLUGWALKL1SPR, // 320\r
- SLUGWALKL2SPR, // 321\r
- SLUGPISSLSPR, // 322\r
- SLUGSLIME1SPR, // 323\r
- SLUGSLIME2SPR, // 324\r
- END_LUMP(SLUG_LUMP_END, __SLUGEND)\r
-\r
- START_LUMP(MADMUSHROOM_LUMP_START, __MADMUSHROOMSTART)\r
- MADMUSHROOML1SPR, // 325\r
- MADMUSHROOML2SPR, // 326\r
- MADMUSHROOMR1SPR, // 327\r
- MADMUSHROOMR2SPR, // 328\r
- END_LUMP(MADMUSHROOM_LUMP_END, __MADMUSHROOMEND)\r
-\r
- START_LUMP(LINDSEY_LUMP_START, __LINDSEYSTART)\r
- LINDSEY1SPR, // 329\r
- LINDSEY2SPR, // 330\r
- LINDSEY3SPR, // 331\r
- LINDSEY4SPR, // 332\r
- END_LUMP(LINDSEY_LUMP_END, __LINDSEYEND)\r
-\r
- START_LUMP(INCHWORM_LUMP_START, __INCHWORMSTART)\r
- INCHWORMR1SPR, // 333\r
- INCHWORMR2SPR, // 334\r
- INCHWORML1SPR, // 335\r
- INCHWORML2SPR, // 336\r
- FOOTSPR, // 337\r
- END_LUMP(INCHWORM_LUMP_END, __INCHWORMEND)\r
-\r
- START_LUMP(EATER_LUMP_START, __EATERSTART)\r
- EATERSTAND1SPR, // 338\r
- EATERSTAND2SPR, // 339\r
- EATERJUMPR1SPR, // 340\r
- EATERJUMPR2SPR, // 341\r
- EATERJUMPR3SPR, // 342\r
- EATERJUMPL1SPR, // 343\r
- EATERJUMPL2SPR, // 344\r
- EATERJUMPL3SPR, // 345\r
- EATENBONUS1SPR, // 346\r
- EATENBONUS2SPR, // 347\r
- EATENBONUS3SPR, // 348\r
- EATENBONUS4SPR, // 349\r
- SMOKE1SPR, // 350\r
- SMOKE2SPR, // 351\r
- SMOKE3SPR, // 352\r
- SMOKE4SPR, // 353\r
- SMOKE5SPR, // 354\r
- EATERSTUNSPR, // 355\r
- END_LUMP(EATER_LUMP_END, __EATEREND)\r
-\r
- START_LUMP(COUNCIL_LUMP_START, __COUINCILSTART)\r
- COUNCILWALKR1SPR, // 356\r
- COUNCILWALKR2SPR, // 357\r
- COUNCILWALKL1SPR, // 358\r
- COUNCILWALKL2SPR, // 359\r
- COUNCILTHINKLSPR, // 360\r
- COUNCILTHINKRSPR, // 361\r
- END_LUMP(COUNCIL_LUMP_END, __COUNCILEND)\r
-\r
- START_LUMP(EGG_LUMP_START, __EGGSTART)\r
- EGGSPR, // 362\r
- EGGBROKESPR, // 363\r
- EGGCHIP1SPR, // 364\r
- EGGCHIP2SPR, // 365\r
- EGGCHIP3SPR, // 366\r
- END_LUMP(EGG_LUMP_END, __EGGEND)\r
-\r
- START_LUMP(EGGBIRD_LUMP_START, __EGGBIRDSTART)\r
- BIRDWALKR1SPR, // 367\r
- BIRDWALKR2SPR, // 368\r
- BIRDWALKR3SPR, // 369\r
- BIRDWALKR4SPR, // 370\r
- BIRDWALKL1SPR, // 371\r
- BIRDWALKL2SPR, // 372\r
- BIRDWALKL3SPR, // 373\r
- BIRDWALKL4SPR, // 374\r
- BIRDFLY1SPR, // 375\r
- BIRDFLY2SPR, // 376\r
- BIRDFLY3SPR, // 377\r
- BIRDFLY4SPR, // 378\r
- BIRDSTUNSPR, // 379\r
- END_LUMP(EGGBIRD_LUMP_END, __EGGBIRDEND)\r
-\r
- START_LUMP(DARTS_LUMP_START, __DARTSSTART)\r
- DARTU1SPR, // 380\r
- DARTU2SPR, // 381\r
- DARTD1SPR, // 382\r
- DARTD2SPR, // 383\r
- DARTR1SPR, // 384\r
- DARTR2SPR, // 385\r
- DARTL1SPR, // 386\r
- DARTL2SPR, // 387\r
- END_LUMP(DARTS_LUMP_END, __DARTSEND)\r
-\r
- START_LUMP(MIMROCK_LUMP_START, __MIMROCKSTART)\r
- MIMROCKSPR, // 388\r
- MIMROCKWALKL1SPR, // 389\r
- MIMROCKWALKL2SPR, // 390\r
- MIMROCKWALKL3SPR, // 391\r
- MIMROCKWALKL4SPR, // 392\r
- MIMROCKWALKR1SPR, // 393\r
- MIMROCKWALKR2SPR, // 394\r
- MIMROCKWALKR3SPR, // 395\r
- MIMROCKWALKR4SPR, // 396\r
- MIMROCKJUMPR1SPR, // 397\r
- MIMROCKJUMPR2SPR, // 398\r
- MIMROCKJUMPR3SPR, // 399\r
- MIMROCKJUMPL1SPR, // 400\r
- MIMROCKJUMPL2SPR, // 401\r
- MIMROCKJUMPL3SPR, // 402\r
- MINROCKSTUNSPR, // 403\r
- END_LUMP(MIMROCK_LUMP_END, __MIMROCKEND)\r
-\r
- START_LUMP(DOPEFISH_LUMP_START, __DOPEFISHSTART)\r
- DOPEFISHSWIMR1SPR, // 404\r
- DOPEFISHSWIMR2SPR, // 405\r
- DOPEFISHHUNGRYRSPR, // 406\r
- DOPEFISHBURP1SPR, // 407\r
- DOPEFISHBURP2SPR, // 408\r
- BIGBUBBLE1SPR, // 409\r
- BIGBUBBLE2SPR, // 410\r
- BIGBUBBLE3SPR, // 411\r
- BIGBUBBLE4SPR, // 412\r
- SMALLBUBBLE1SPR, // 413\r
- SMALLBUBBLE2SPR, // 414\r
- SMALLBUBBLE3SPR, // 415\r
- SMALLBUBBLE4SPR, // 416\r
- MEDIUMBUBBLESPR, // 417\r
- DOPEFISHSWIML1SPR, // 418\r
- DOPEFISHSWIML2SPR, // 419\r
- DOPEFISHHUNGRYLSPR, // 420\r
- END_LUMP(DOPEFISH_LUMP_END, __DOPEFISHEND)\r
-\r
- START_LUMP(SCHOOLFISH_LUMP_START, __SCHOOLFISHSTART)\r
- SCHOOLFISHL1SPR, // 421\r
- SCHOOLFISHL2SPR, // 422\r
- SCHOOLFISHR1SPR, // 423\r
- SCHOOLFISHR2SPR, // 424\r
- END_LUMP(SCHOOLFISH_LUMP_END, __SCHOOLFISHEND)\r
-\r
- START_LUMP(ARACHNUT_LUMP_START, __ARACHNUTSTART)\r
- ARACHNUTWALK1SPR, // 425\r
- ARACHNUTWALK2SPR, // 426\r
- ARACHNUTWALK3SPR, // 427\r
- ARACHNUTWALK4SPR, // 428\r
- ARACHNUTSTUNSPR, // 429\r
- END_LUMP(ARACHNUT_LUMP_END, __ARACHNUTEND)\r
-\r
- SCUBASPR, // 430\r
-\r
- START_LUMP(SPRITE_LUMP_START, __SPRITESTART)\r
- SPRITEFLOATSPR, // 431\r
- SPRITEAIMLSPR, // 432\r
- SPRITESHOOTLSPR, // 433\r
- SPRITEAIMRSPR, // 434\r
- SPRITESHOOTRSPR, // 435\r
- SPRITESHOT1SPR, // 436\r
- SPRITESHOT2SPR, // 437\r
- SPRITESHOT3SPR, // 438\r
- SPRITESHOT4SPR, // 439\r
- END_LUMP(SPRITE_LUMP_END, __SPRITEEND)\r
-\r
- START_LUMP(MINE_LUMP_START, __MINESTART)\r
- MINESPR, // 440\r
- MINEEXPLODE1SPR, // 441\r
- MINEEXPLODE2SPR, // 442\r
- END_LUMP(MINE_LUMP_END, __MINEEND)\r
-\r
- START_LUMP(SKYPEST_LUMP_START, __SKYPESTSTART)\r
- SKYPESTFLYL1SPR, // 443\r
- SKYPESTFLYL2SPR, // 444\r
- SKYPESTFLYR1SPR, // 445\r
- SKYPESTFLYR2SPR, // 446\r
- SKYPESTSIT1SPR, // 447\r
- SKYPESTSIT2SPR, // 448\r
- SKYPESTSIT3SPR, // 449\r
- SKYPESTSIT4SPR, // 450\r
- SKYPESTSIT5SPR, // 451\r
- SKYPESTSIT6SPR, // 452\r
- SKYPESTSIT7SPR, // 453\r
- SKYPESTSIT8SPR, // 454\r
- SKYPESTSIT9SPR, // 455\r
- SKYPESTSQUASHEDSPR, // 456\r
- END_LUMP(SKYPEST_LUMP_END, __SKYPESTEND)\r
-\r
- START_LUMP(WORMOUTH_LUMP_START, __WORMOUTHSTART)\r
- WORMOUTHSPR, // 457\r
- WORMOUTHPEEKR1SPR, // 458\r
- WORMOUTHPEEKR2SPR, // 459\r
- WORMOUTHPEEKL1SPR, // 460\r
- WORMOUTHPEEKL2SPR, // 461\r
- WORMOUTHBITER1SPR, // 462\r
- WORMOUTHBITER2SPR, // 463\r
- WORMOUTHBITER3SPR, // 464\r
- WORMOUTHBITEL1SPR, // 465\r
- WORMOUTHBITEL2SPR, // 466\r
- WORMOUTHBITEL3SPR, // 467\r
- WORMOUTHSTUNSPR, // 468\r
- END_LUMP(WORMOUTH_LUMP_END, __WORMOUTHEND)\r
-\r
- START_LUMP(LICK_LUMP_START, __LICKSTART)\r
- LICKMOVER1SPR, // 469\r
- LICKMOVER2SPR, // 470\r
- LICKMOVER3SPR, // 471\r
- LICKMOVER4SPR, // 472\r
- LICKMOVEL1SPR, // 473\r
- LICKMOVEL2SPR, // 474\r
- LICKMOVEL3SPR, // 475\r
- LICKMOVEL4SPR, // 476\r
- LICKATTACKR1SPR, // 477\r
- LICKATTACKR2SPR, // 478\r
- LICKATTACKR3SPR, // 479\r
- LICKATTACKL1SPR, // 480\r
- LICKATTACKL2SPR, // 481\r
- LICKATTACKL3SPR, // 482\r
- LICKSTUNSPR, // 483\r
- END_LUMP(LICK_LUMP_END, __LICKEND)\r
-\r
- START_LUMP(PLATFORM_LUMP_START, __PLATFORMSTART)\r
- PLATFORMSPR, // 484\r
- PLATSIDETHRUST1SPR, // 485\r
- PLATSIDETHRUST2SPR, // 486\r
- PLATRTHRUST1SPR, // 487\r
- PLATRTHRUST2SPR, // 488\r
- PLATLTHRUST1SPR, // 489\r
- PLATLTHRUST2SPR, // 490\r
- END_LUMP(PLATFORM_LUMP_END, __PLATFORMEND)\r
-\r
- START_LUMP(BOUNDER_LUMP_START, __BOUNDERSTART)\r
- BOUNDERL1SPR, // 491\r
- BOUNDERL2SPR, // 492\r
- BOUNDERR1SPR, // 493\r
- BOUNDERR2SPR, // 494\r
- BOUNDERC1SPR, // 495\r
- BOUNDERC2SPR, // 496\r
- BOUNDERSTUNSPR, // 497\r
- END_LUMP(BOUNDER_LUMP_END, __BOUNDEREND)\r
-\r
- START_LUMP(THUNDERCLOUD_LUMP_START, __THUNDERCLOUDSTART)\r
- CLOUDSPR, // 498\r
- CLOUDACTIVESPR, // 499\r
- CLOUDCHARGESPR, // 500\r
- BOLT1SPR, // 501\r
- BOLT2SPR, // 502\r
- END_LUMP(THUNDERCLOUD_LUMP_END, __THUNDERCLOUDEND)\r
-\r
- START_LUMP(BERKELOID_LUMP_START, __BERKELOIDSTART)\r
- BERKEWALKL1SPR, // 503\r
- BERKEWALKL2SPR, // 504\r
- BERKEWALKL3SPR, // 505\r
- BERKEWALKL4SPR, // 506\r
- BERKEWALKR1SPR, // 507\r
- BERKEWALKR2SPR, // 508\r
- BERKEWALKR3SPR, // 509\r
- BERKEWALKR4SPR, // 510\r
- BERKETHROWL1SPR, // 511\r
- BERKETHROWL2SPR, // 512\r
- BERKETHROWR1SPR, // 513\r
- BERKETHROWR2SPR, // 514\r
- FIREBALL1SPR, // 515\r
- FIREBALL2SPR, // 516\r
- FIREBALL3SPR, // 517\r
- FIREBALL4SPR, // 518\r
- END_LUMP(BERKELOID_LUMP_END, __BERKELOIDEND)\r
-\r
- START_LUMP(MOON_LUMP_START, __MOONSTART)\r
- KEENMOON1SPR, // 519\r
- KEENMOON2SPR, // 520\r
- END_LUMP(MOON_LUMP_END, __MOONEND)\r
-\r
- //\r
- // TILES (these don't need names)\r
- //\r
-\r
- LASTTILE=STARTEXTERNS-1,\r
-\r
- //\r
- // EXTERNS\r
- //\r
-\r
- ORDERSCREEN, // 4735\r
- BIGCOMMANDER, // 4736\r
- BIGKEEN, // 4737\r
- OUTOFMEM, // 4738\r
-\r
- //texts\r
- T_HELPART, // 4739\r
- T_STORYART, // 4740\r
- T_CONTRART, // 4741\r
- T_IDART, // 4742\r
- T_ENDART, // 4743\r
- T_DEMOART, // 4744\r
- T_ORDERART, // 4745\r
-\r
- //demos\r
- DEMO0, // 4746\r
- DEMO1, // 4747\r
- DEMO2, // 4748\r
- DEMO3, // 4749\r
- DEMO4, // 4750\r
-\r
- NUMGRCHUNKS\r
-} graphicnums;\r
-\r
-#undef START_LUMP\r
-#undef END_LUMP\r
-\r
-#endif //__GFX_H__
\ No newline at end of file
+++ /dev/null
-;\r
-; Equates for all .ASM files\r
-;\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-INCLUDE "GFXE_CK4.EQU"\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-CGAGR = 1\r
-EGAGR = 2\r
-VGAGR = 3\r
-\r
-GRMODE = EGAGR\r
-PROFILE = 0 ; 1=keep stats on tile drawing\r
-\r
-SC_INDEX = 03C4h\r
-SC_RESET = 0\r
-SC_CLOCK = 1\r
-SC_MAPMASK = 2\r
-SC_CHARMAP = 3\r
-SC_MEMMODE = 4\r
-\r
-CRTC_INDEX = 03D4h\r
-CRTC_H_TOTAL = 0\r
-CRTC_H_DISPEND = 1\r
-CRTC_H_BLANK = 2\r
-CRTC_H_ENDBLANK = 3\r
-CRTC_H_RETRACE = 4\r
-CRTC_H_ENDRETRACE = 5\r
-CRTC_V_TOTAL = 6\r
-CRTC_OVERFLOW = 7\r
-CRTC_ROWSCAN = 8\r
-CRTC_MAXSCANLINE = 9\r
-CRTC_CURSORSTART = 10\r
-CRTC_CURSOREND = 11\r
-CRTC_STARTHIGH = 12\r
-CRTC_STARTLOW = 13\r
-CRTC_CURSORHIGH = 14\r
-CRTC_CURSORLOW = 15\r
-CRTC_V_RETRACE = 16\r
-CRTC_V_ENDRETRACE = 17\r
-CRTC_V_DISPEND = 18\r
-CRTC_OFFSET = 19\r
-CRTC_UNDERLINE = 20\r
-CRTC_V_BLANK = 21\r
-CRTC_V_ENDBLANK = 22\r
-CRTC_MODE = 23\r
-CRTC_LINECOMPARE = 24\r
-\r
-\r
-GC_INDEX = 03CEh\r
-GC_SETRESET = 0\r
-GC_ENABLESETRESET = 1\r
-GC_COLORCOMPARE = 2\r
-GC_DATAROTATE = 3\r
-GC_READMAP = 4\r
-GC_MODE = 5\r
-GC_MISCELLANEOUS = 6\r
-GC_COLORDONTCARE = 7\r
-GC_BITMASK = 8\r
-\r
-ATR_INDEX = 03c0h\r
-ATR_MODE = 16\r
-ATR_OVERSCAN = 17\r
-ATR_COLORPLANEENABLE = 18\r
-ATR_PELPAN = 19\r
-ATR_COLORSELECT = 20\r
-\r
-STATUS_REGISTER_1 = 03dah\r
-\r
-\r
-MACRO WORDOUT\r
- out dx,ax\r
-ENDM\r
-\r
-if 0\r
-\r
-MACRO WORDOUT\r
- out dx,al\r
- inc dx\r
- xchg al,ah\r
- out dx,al\r
- dec dx\r
- xchg al,ah\r
-ENDM\r
-\r
-endif\r
-\r
-UPDATEWIDE = 22\r
-UPDATEHIGH = 14\r
-\r
-;\r
-; tile info offsets from segment tinf\r
-;\r
-\r
-ANIM = 402\r
-SPEED = (ANIM+NUMTILE16)\r
-\r
-NORTHWALL = (SPEED+NUMTILE16)\r
-EASTWALL = (NORTHWALL+NUMTILE16M)\r
-SOUTHWALL = (EASTWALL+NUMTILE16M)\r
-WESTWALL = (SOUTHWALL+NUMTILE16M)\r
-MANIM = (WESTWALL+NUMTILE16M)\r
-INTILE = (MANIM+NUMTILE16M)\r
-MSPEED = (INTILE+NUMTILE16M)\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-SCREENWIDTH = 64\r
-ENDIF\r
-IFE GRMODE-CGAGR\r
-SCREENWIDTH = 128\r
-ENDIF\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_GLOB.H\r
-\r
-\r
-#include <ALLOC.H>\r
-#include <CTYPE.H>\r
-#include <DOS.H>\r
-#include <ERRNO.H>\r
-#include <FCNTL.H>\r
-#include <IO.H>\r
-#include <MEM.H>\r
-#include <PROCESS.H>\r
-#include <STDIO.H>\r
-#include <STDLIB.H>\r
-#include <STRING.H>\r
-#include <SYS\STAT.H>\r
-\r
-#define __ID_GLOB__\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define KEEN\r
-#define KEEN4\r
-\r
-#define EXTENSION "CK4"\r
-\r
-extern char far introscn;\r
-\r
-#include "GFXE_CK4.H"\r
-#include "AUDIOCK4.H"\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define TEXTGR 0\r
-#define CGAGR 1\r
-#define EGAGR 2\r
-#define VGAGR 3\r
-\r
-#define GRMODE EGAGR\r
-\r
-#if GRMODE == EGAGR\r
-#define GREXT "EGA"\r
-#endif\r
-#if GRMODE == CGAGR\r
-#define GREXT "CGA"\r
-#endif\r
-\r
-//#define PROFILE\r
-\r
-//\r
-// ID Engine\r
-// Types.h - Generic types, #defines, etc.\r
-// v1.0d1\r
-//\r
-\r
-#ifndef __TYPES__\r
-#define __TYPES__\r
-\r
-typedef enum {false,true} boolean;\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long longword;\r
-typedef byte * Ptr;\r
-\r
-typedef struct\r
- {\r
- int x,y;\r
- } Point;\r
-typedef struct\r
- {\r
- Point ul,lr;\r
- } Rect;\r
-\r
-#define nil ((void *)0)\r
-\r
-#endif\r
-\r
-#include "ID_MM.H"\r
-#include "ID_CA.H"\r
-#include "ID_VW.H"\r
-#include "ID_RF.H"\r
-#include "ID_IN.H"\r
-#include "ID_SD.H"\r
-#include "ID_US.H"\r
-\r
-\r
-void Quit (char *error); // defined in user program\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K4_ACT1.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Miragia (world map)\r
-- Bonus Items\r
-- Council Member\r
-- Poison Slug\r
-- Mad Mushroom\r
-- Egg & Eggbird\r
-- Arachnut\r
-- Skypest\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- MIRAGIA\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_miragia0 = {0, 0, step, false, false, 300, 0, 0, T_Miragia0, NULL, NULL, &s_miragia1};\r
-statetype s_miragia1 = {0, 0, step, false, false, 30, 0, 0, T_Miragia1, NULL, NULL, &s_miragia2};\r
-statetype s_miragia2 = {0, 0, step, false, false, 30, 0, 0, T_Miragia2, NULL, NULL, &s_miragia3};\r
-statetype s_miragia3 = {0, 0, step, false, false, 30, 0, 0, T_Miragia3, NULL, NULL, &s_miragia4};\r
-statetype s_miragia4 = {0, 0, step, false, false, 300, 0, 0, T_Miragia4, NULL, NULL, &s_miragia5};\r
-statetype s_miragia5 = {0, 0, step, false, false, 30, 0, 0, T_Miragia5, NULL, NULL, &s_miragia6};\r
-statetype s_miragia6 = {0, 0, step, false, false, 30, 0, 0, T_Miragia6, NULL, NULL, &s_miragia7};\r
-statetype s_miragia7 = {0, 0, step, false, false, 30, 0, 0, T_Miragia7, NULL, NULL, &s_miragia0};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnMiragia\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnMiragia(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = inertobj;\r
- new->active = ac_allways;\r
- new->x = x;\r
- new->y = y;\r
- new->state = &s_miragia0;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia0\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia0(objtype *ob)\r
-{\r
- if (player->tileright >= ob->x && player->tileleft <= ob->x+5\r
- && player->tiletop >= ob->y && player->tilebottom <= ob->y+4)\r
- {\r
- //don't let miragia appear if player is in the area, so player won't get stuck\r
- ob->state = &s_miragia7;\r
- }\r
- else\r
- {\r
- RF_MapToMap(8, 60, ob->x, ob->y, 6, 4);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia1\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia1(objtype *ob)\r
-{\r
- RF_MapToMap(14, 60, ob->x, ob->y, 6, 4);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia2\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia2(objtype *ob)\r
-{\r
- RF_MapToMap(20, 60, ob->x, ob->y, 6, 4);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia3\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia3(objtype *ob)\r
-{\r
- RF_MapToMap(26, 60, ob->x, ob->y, 6, 4);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia4\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia4(objtype *ob)\r
-{\r
- RF_MapToMap(20, 60, ob->x, ob->y, 6, 4);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia5\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia5(objtype *ob)\r
-{\r
- RF_MapToMap(14, 60, ob->x, ob->y, 6, 4);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia6\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia6(objtype *ob)\r
-{\r
- RF_MapToMap(8, 60, ob->x, ob->y, 6, 4);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Miragia7\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Miragia7(objtype *ob)\r
-{\r
- RF_MapToMap(2, 60, ob->x, ob->y, 6, 4);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BONUS ITEMS\r
-\r
-temp1 = bonus type\r
-temp2 = base shape number\r
-temp3 = last animated shape number +1\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bonus1 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus2};\r
-statetype s_bonus2 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus1};\r
-statetype s_bonusrise = {0, 0, slide, false, false, 40, 0, 8, NULL, NULL, R_Draw, NULL};\r
-\r
-statetype s_splash1 = {DROPSPLASH1SPR, DROPSPLASH1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_splash2};\r
-statetype s_splash2 = {DROPSPLASH2SPR, DROPSPLASH2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_splash3};\r
-statetype s_splash3 = {DROPSPLASH3SPR, DROPSPLASH3SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-Uint16 bonusshape[] = {REDGEM1SPR, YELLOWGEM1SPR, BLUEGEM1SPR, GREENGEM1SPR, SUGAR1ASPR, SUGAR2ASPR, SUGAR3ASPR, SUGAR4ASPR, SUGAR5ASPR, SUGAR6ASPR, ONEUPASPR, STUNCLIP1SPR};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBonus\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBonus(Sint16 x, Sint16 y, Sint16 type)\r
-{\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = bonusobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- new->ydir = -1;\r
- new->temp1 = type;\r
- new->temp2 = new->shapenum = bonusshape[type];\r
- new->temp3 = new->temp2 + 2;\r
- NewState(new, &s_bonus1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSplash\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSplash(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(true);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 3;\r
- new->obclass = inertobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- NewState(new, &s_splash1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Bonus\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Bonus(objtype *ob)\r
-{\r
- ob->shapenum++;\r
- if (ob->shapenum == ob->temp3)\r
- ob->shapenum = ob->temp2;\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- COUNCIL MEMBER\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_councilwalk1 = {COUNCILWALKL1SPR, COUNCILWALKR1SPR, step, false, true, 10, 64, 0, T_Council, NULL, R_Walk, &s_councilwalk2};\r
-statetype s_councilwalk2 = {COUNCILWALKL2SPR, COUNCILWALKR2SPR, step, false, true, 10, 64, 0, T_Council, NULL, R_Walk, &s_councilwalk1};\r
-statetype s_councilstand = {COUNCILTHINKLSPR, COUNCILTHINKRSPR, step, false, false, 120, 128, 0, NULL, NULL, R_Draw, &s_councilwalk1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnCouncil\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnCouncil(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = oracleobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) -0x171; //TODO: wierd\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_councilwalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Council\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Council(objtype *ob)\r
-{\r
- Uint16 randnum;\r
-\r
- randnum = US_RndT();\r
- if (tics*8 > randnum)\r
- {\r
- // BUG: might be about to move off a ledge, causing it to get stuck\r
- // after standing (the stand state doesn't use R_Walk)!\r
- // To avoid that, set xtry to 0 here.\r
- ob->state = &s_councilstand;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- POINSON SLUG\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_slugwalk1 = {SLUGWALKL1SPR, SLUGWALKR1SPR, step, false, true, 8, 64, 0, NULL, C_Slug, R_WalkNormal, &s_slugwalk2};\r
-statetype s_slugwalk2 = {SLUGWALKL2SPR, SLUGWALKR2SPR, step, false, true, 8, 64, 0, T_Slug, C_Slug, R_WalkNormal, &s_slugwalk1};\r
-statetype s_slugpiss1 = {SLUGPISSLSPR, SLUGPISSRSPR, step, false, true, 60, 64, 0, T_SlugPiss, C_Slug, R_WalkNormal, &s_slugwalk1};\r
-statetype s_slugstun = {SLUGSTUN1SPR, SLUGSTUN1SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-statetype s_slugstunalt = {SLUGSTUN2SPR, SLUGSTUN2SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-statetype s_slugslime = {SLUGSLIME1SPR, SLUGSLIME1SPR, step, false, false, 300, 0, 0, NULL, C_Lethal, R_Draw, &s_slugslime2};\r
-statetype s_slugslime2 = {SLUGSLIME2SPR, SLUGSLIME2SPR, step, false, false, 60, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSlug\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSlug(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = slugobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x71;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_slugwalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Slug\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Slug(objtype *ob)\r
-{\r
- if (US_RndT() < 16)\r
- {\r
- if (ob->x < player->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- ob->state = &s_slugpiss1;\r
- SD_PlaySound(SND_SLUGPOO);\r
- // Note: might be a good idea to set xtry to 0 here\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SlugPiss\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SlugPiss(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->active = ac_removable;\r
- new->priority = 0;\r
- new->x = ob->x;\r
- new->y = ob->bottom - 8*PIXGLOBAL;\r
- NewState(new, &s_slugslime);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Slug\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Slug(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- if (US_RndT() < 0x80)\r
- {\r
- StunObj(ob, hit, &s_slugstun);\r
- }\r
- else\r
- {\r
- StunObj(ob, hit, &s_slugstunalt);\r
- }\r
- ob->yspeed = -24;\r
- ob->xspeed = ob->xdir*8;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- MAD MUSHROOM\r
-\r
-temp1 = jump counter\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_mushroom1 = {MADMUSHROOML1SPR, MADMUSHROOMR1SPR, stepthink, false, false, 8, 0, 0, T_Mushroom, C_Mushroom, R_Mushroom, &s_mushroom2};\r
-statetype s_mushroom2 = {MADMUSHROOML2SPR, MADMUSHROOMR2SPR, stepthink, false, false, 8, 0, 0, T_Mushroom, C_Mushroom, R_Mushroom, &s_mushroom1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnMadMushroom\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnMadMushroom(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = madmushroomobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) - 0xF1;\r
- new->xdir = 1;\r
- new->ydir = 1;\r
- NewState(new, &s_mushroom1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Mushroom\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Mushroom(objtype *ob)\r
-{\r
- if (player->x < ob->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
-\r
- // BUG: this might be executed twice during the same frame if the\r
- // object's animation/state changed during that frame, causing the\r
- // object to move at twice the speed during that frame!\r
- // To avoid that, return if ytry is not 0.\r
- DoWeakGravity(ob);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Mushroom\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Mushroom(objtype *ob, objtype *hit)\r
-{\r
- ob++; // shut up compiler\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Mushroom\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Mushroom(objtype *ob)\r
-{\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->yspeed = 0;\r
- if (++ob->temp1 == 3)\r
- {\r
- ob->temp1 = 0;\r
- ob->yspeed = -68;\r
- SD_PlaySound(SND_BOUNCE2);\r
- }\r
- else\r
- {\r
- SD_PlaySound(SND_BOUNCE1);\r
- ob->yspeed = -40;\r
- }\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- EGGBIRD\r
-\r
-temp1 = blocked flag for flying eggbird (cannot change xdir to chase Keen\r
- while this is non-zero)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_egg = {EGGSPR, EGGSPR, think, false, true, 8, 0, 0, NULL, C_Egg, R_Draw, NULL};\r
-statetype s_eggbroke = {EGGBROKESPR, EGGBROKESPR, step, false, false, 30000, 0, 0, NULL, NULL, R_Draw, NULL};\r
-statetype s_eggchip1 = {EGGCHIP1SPR, EGGCHIP1SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Chip, NULL};\r
-statetype s_eggchip2 = {EGGCHIP2SPR, EGGCHIP2SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Chip, NULL};\r
-statetype s_eggchip3 = {EGGCHIP3SPR, EGGCHIP3SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Chip, NULL};\r
-\r
-statetype s_eggbirdpause = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 120, 128, 0, NULL, C_EggbirdStun, R_Eggbird, &s_eggbirdwalk2};\r
-statetype s_eggbirdwalk1 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk2};\r
-statetype s_eggbirdwalk2 = {BIRDWALKL2SPR, BIRDWALKR2SPR, step, false, true, 7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk3};\r
-statetype s_eggbirdwalk3 = {BIRDWALKL3SPR, BIRDWALKR3SPR, step, false, true, 7, 128, 0, NULL, C_Eggbird, R_Eggbird, &s_eggbirdwalk4};\r
-statetype s_eggbirdwalk4 = {BIRDWALKL4SPR, BIRDWALKR4SPR, step, false, true, 7, 128, 0, T_Eggbird, C_Eggbird, R_Eggbird, &s_eggbirdwalk1};\r
-statetype s_eggbirdfly1 = {BIRDFLY1SPR, BIRDFLY1SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly2};\r
-statetype s_eggbirdfly2 = {BIRDFLY2SPR, BIRDFLY2SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly3};\r
-statetype s_eggbirdfly3 = {BIRDFLY3SPR, BIRDFLY3SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly4};\r
-statetype s_eggbirdfly4 = {BIRDFLY4SPR, BIRDFLY4SPR, slidethink, false, false, 8, 0, 0, T_EggbirdFly, C_Eggbird, R_Eggbirdfly, &s_eggbirdfly1};\r
-statetype s_eggbirddrop = {BIRDFLY4SPR, BIRDFLY4SPR, think, false, false, 8, 128, 0, T_WeakProjectile, C_Eggbird, R_EggbirdDrop, NULL};\r
-statetype s_eggbirdstun = {BIRDSTUNSPR, BIRDSTUNSPR, stepthink, false, false, 240, 0, 0, T_Projectile, C_EggbirdStun, R_Draw, &s_eggbirdstun2};\r
-statetype s_eggbirdstun2 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 20, 0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun3};\r
-statetype s_eggbirdstun3 = {BIRDSTUNSPR, BIRDSTUNSPR, step, false, true, 20, 0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun4};\r
-statetype s_eggbirdstun4 = {BIRDWALKL1SPR, BIRDWALKR1SPR, step, false, true, 20, 0, 0, NULL, C_EggbirdStun, R_Draw, &s_eggbirdstun5};\r
-statetype s_eggbirdstun5 = {BIRDSTUNSPR, BIRDSTUNSPR, step, false, true, 20, 0, 0, T_EggUnstun, C_EggbirdStun, R_Draw, &s_eggbirdwalk1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnEggbird\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnEggbird(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = eggobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x71;\r
- new->xdir = 1;\r
- new->ydir = 1;\r
- NewState(new, &s_egg);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_EggUnstun\r
-=\r
-===========================\r
-*/\r
-\r
-void T_EggUnstun(objtype *ob)\r
-{\r
- ob->obclass = eggbirdobj;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnEggbirdOut\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnEggbirdOut(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(true);\r
- new->obclass = eggbirdobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) - 0xF1;\r
- if (new->x < player->x)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_eggbirdpause);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Egg\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Egg(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj || hit->obclass == keenobj)\r
- {\r
- if (hit->obclass == stunshotobj)\r
- ExplodeShot(hit);\r
-\r
- ob->obclass = inertobj;\r
- ob->active = ac_removable;\r
- ChangeState(ob, &s_eggbroke);\r
-\r
- GetNewObj(true);\r
- new->obclass = eggbirdobj;\r
- new->active = ac_yes;\r
- new->x = ob->x;\r
- new->y = ob->y - 8*PIXGLOBAL;\r
- if (ob->x < player->x)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_eggbirdpause);\r
-\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->active = ac_removable;\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = -28;\r
- new->yspeed = -40;\r
- NewState(new, &s_eggchip1);\r
-\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->active = ac_removable;\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = 28;\r
- new->yspeed = -40;\r
- NewState(new, &s_eggchip2);\r
-\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->active = ac_removable;\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = 0;\r
- new->yspeed = -56;\r
- NewState(new, &s_eggchip3);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Eggbird\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Eggbird(objtype *ob)\r
-{\r
- if (ob->x < player->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- if (ob->bottom >= player->bottom + 3*TILEGLOBAL && player->hitnorth\r
- && StatePositionOk(ob, &s_eggbirdfly1)) // BUG: StatePositionOk() only works for normal clipping, not for full clipping\r
- {\r
- // Note: might be a good idea to set xtry to 0 here\r
- ob->state = &s_eggbirdfly1;\r
- ob->needtoclip = cl_fullclip;\r
- ob->yspeed = -8;\r
- ob->temp1 = 0;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_EggbirdFly\r
-=\r
-===========================\r
-*/\r
-\r
-void T_EggbirdFly(objtype *ob)\r
-{\r
- if (ob->temp1 == 0)\r
- {\r
- if (ob->x < player->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- }\r
- AccelerateXv(ob, ob->xdir, 16);\r
- if (ob->y < player->y)\r
- {\r
- AccelerateY(ob, 1, 16);\r
- }\r
- else\r
- {\r
- AccelerateY(ob, -1, 16);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Eggbird\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Eggbird(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ob->xspeed = 0;\r
- ob->needtoclip = cl_midclip;\r
- StunObj(ob, hit, &s_eggbirdstun);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_EggbirdStun\r
-=\r
-===========================\r
-*/\r
-\r
-void C_EggbirdStun(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ob->xspeed = 0;\r
- StunObj(ob, hit, &s_eggbirdstun);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Eggbird\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Eggbird(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- if (!ob->hitnorth)\r
- {\r
- ob->yspeed = -16;\r
- ob->needtoclip = cl_fullclip;\r
- ChangeState(ob, &s_eggbirdfly1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_EggbirdDrop\r
-=\r
-===========================\r
-*/\r
-\r
-void R_EggbirdDrop(objtype *ob) //never actually used\r
-{\r
- if (ob->hitnorth)\r
- {\r
- ChangeState(ob, &s_eggbirdwalk1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Chip\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Chip(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- ob->xspeed = ob->yspeed = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Eggbirdfly\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Eggbirdfly(objtype *ob)\r
-{\r
- statetype *oldstate;\r
-\r
- if ((ob->hitsouth || ob->hitnorth) && !ob->temp1)\r
- ob->temp1++;\r
-\r
- if (ob->hiteast && ob->xspeed < 0 || ob->hitwest && ob->xspeed > 0)\r
- {\r
- ob->xspeed = 0;\r
- ob->xdir = -ob->xdir;\r
- }\r
- if (ob->hitnorth == 1 && player->bottom - ob->bottom < 8*PIXGLOBAL) // BUG? unsigned comparison!\r
- {\r
- oldstate = ob->state;\r
- ob->needtoclip = cl_midclip;\r
- ChangeState(ob, &s_eggbirdwalk1);\r
- xtry = 0;\r
- ytry = 8*PIXGLOBAL;\r
- PushObj(ob);\r
- if (!ob->hitnorth)\r
- {\r
- ob->needtoclip = cl_fullclip;\r
- ChangeState(ob, oldstate);\r
- }\r
- return; // BUG: sprite isn't updated\r
- }\r
-\r
- if (!ob->hitsouth && !ob->hitnorth)\r
- ob->temp1 = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- ARACHNUT\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_arach1 = {ARACHNUTWALK1SPR, ARACHNUTWALK4SPR, step, false, true, 6, 128, 0, NULL, C_Arach, R_Walk, &s_arach2};\r
-statetype s_arach2 = {ARACHNUTWALK2SPR, ARACHNUTWALK3SPR, step, false, true, 6, 128, 0, NULL, C_Arach, R_Walk, &s_arach3};\r
-statetype s_arach3 = {ARACHNUTWALK3SPR, ARACHNUTWALK2SPR, step, false, true, 6, 128, 0, NULL, C_Arach, R_Walk, &s_arach4};\r
-statetype s_arach4 = {ARACHNUTWALK4SPR, ARACHNUTWALK1SPR, step, false, true, 6, 128, 0, T_Arach, C_Arach, R_Walk, &s_arach1};\r
-statetype s_arachstun = {ARACHNUTSTUNSPR, ARACHNUTSTUNSPR, step, false, true, 240, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun2};\r
-statetype s_arachstun2 = {ARACHNUTWALK1SPR, ARACHNUTWALK1SPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun3};\r
-statetype s_arachstun3 = {ARACHNUTSTUNSPR, ARACHNUTSTUNSPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun4};\r
-statetype s_arachstun4 = {ARACHNUTWALK1SPR, ARACHNUTWALK1SPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arachstun5};\r
-statetype s_arachstun5 = {ARACHNUTSTUNSPR, ARACHNUTSTUNSPR, step, false, true, 20, 0, 0, NULL, C_ArachStun, R_Draw, &s_arach1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnArachnut\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnArachnut(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = arachnutobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) - 0x171;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_arach1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Arach\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Arach(objtype *ob)\r
-{\r
- if (ob->x > player->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Arach\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Arach(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_arachstun);\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_ArachStun\r
-=\r
-===========================\r
-*/\r
-\r
-void C_ArachStun(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_arachstun);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SKYPEST\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_pestfly1 = {SKYPESTFLYL1SPR, SKYPESTFLYR1SPR, stepthink, true, false, 5, 0, 0, T_PestFly, C_PestFly, R_Pest, &s_pestfly2};\r
-statetype s_pestfly2 = {SKYPESTFLYL2SPR, SKYPESTFLYR2SPR, stepthink, true, false, 5, 0, 0, T_PestFly, C_PestFly, R_Pest, &s_pestfly1};\r
-statetype s_squashedpest = {SKYPESTSQUASHEDSPR, SKYPESTSQUASHEDSPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, &s_squashedpest};\r
-statetype s_pestrest1 = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 100, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest2};\r
-statetype s_pestrest2 = {SKYPESTSIT1SPR, SKYPESTSIT1SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest3};\r
-statetype s_pestrest3 = {SKYPESTSIT2SPR, SKYPESTSIT2SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest4};\r
-statetype s_pestrest4 = {SKYPESTSIT3SPR, SKYPESTSIT3SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest5};\r
-statetype s_pestrest5 = {SKYPESTSIT4SPR, SKYPESTSIT4SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest6};\r
-statetype s_pestrest6 = {SKYPESTSIT3SPR, SKYPESTSIT3SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest7};\r
-statetype s_pestrest7 = {SKYPESTSIT2SPR, SKYPESTSIT2SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest8};\r
-statetype s_pestrest8 = {SKYPESTSIT1SPR, SKYPESTSIT1SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest9};\r
-statetype s_pestrest9 = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 60, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest10};\r
-statetype s_pestrest10 = {SKYPESTSIT5SPR, SKYPESTSIT5SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest11};\r
-statetype s_pestrest11 = {SKYPESTSIT6SPR, SKYPESTSIT6SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest12};\r
-statetype s_pestrest12 = {SKYPESTSIT7SPR, SKYPESTSIT7SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest13};\r
-statetype s_pestrest13 = {SKYPESTSIT8SPR, SKYPESTSIT8SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest14};\r
-statetype s_pestrest14 = {SKYPESTSIT7SPR, SKYPESTSIT7SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest15};\r
-statetype s_pestrest15 = {SKYPESTSIT6SPR, SKYPESTSIT6SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest16};\r
-statetype s_pestrest16 = {SKYPESTSIT5SPR, SKYPESTSIT5SPR, step, false, false, 10, 0, 0, NULL, C_Squashable, R_Draw, &s_pestrest17};\r
-statetype s_pestrest17 = {SKYPESTSIT9SPR, SKYPESTSIT9SPR, step, false, false, 100, 0, 0, T_PestRest, C_Squashable, R_Draw, &s_pestfly1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSkypest\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSkypest(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = skypestobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- if (US_RndT() < 0x80)\r
- {\r
- new->ydir = 1;\r
- }\r
- else\r
- {\r
- new->ydir = -1;\r
- }\r
- NewState(new, &s_pestfly1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PestFly\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PestFly(objtype *ob)\r
-{\r
- // BUG: this might be executed twice during the same frame if the\r
- // object's animation/state changed during that frame, causing the\r
- // object to move at twice the speed during that frame!\r
- // To avoid that, return if xtry is not 0 or ytry is not 0.\r
-\r
- if (US_RndT() < tics)\r
- ob->xdir = -ob->xdir;\r
-\r
- if (ob->ydir == -1 && US_RndT() < tics)\r
- ob->ydir = 1;\r
-\r
- if (ob->ydir == 1 && US_RndT() < tics*2)\r
- ob->ydir = -ob->ydir;\r
-\r
- AccelerateX(ob, ob->xdir, 20);\r
- AccelerateY(ob, ob->ydir, 20);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_PestFly\r
-=\r
-===========================\r
-*/\r
-\r
-void C_PestFly(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- KillKeen();\r
-\r
- if (hit->obclass == stunshotobj)\r
- {\r
- if (hit->xdir == 1)\r
- {\r
- ob->xspeed = 20;\r
- }\r
- else if (hit->xdir == -1)\r
- {\r
- ob->xspeed = -20;\r
- }\r
- else if (hit->ydir == 1)\r
- {\r
- ob->yspeed = 20;\r
- }\r
- else if (hit->ydir == -1)\r
- {\r
- ob->yspeed = -20;\r
- }\r
- ExplodeShot(hit);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Squashable\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Squashable(objtype *ob, objtype *hit)\r
-{\r
- if (hit->state == &s_keenpogodown || hit->state == &s_keenpogo || hit->state == &s_keenpogo2)\r
- {\r
- ChangeState(ob, &s_squashedpest);\r
- SD_PlaySound(SND_SQUISH);\r
- ob->obclass = inertobj;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PestRest\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PestRest(objtype *ob)\r
-{\r
- ob->ydir = -1;\r
- ob->yspeed = -16;\r
- ytry = -144;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Pest\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Pest(objtype *ob)\r
-{\r
- if (ob->hitsouth)\r
- {\r
- ob->yspeed = 8;\r
- ob->ydir = 1;\r
- }\r
- if (ob->hitnorth && !ob->hiteast && !ob->hitwest)\r
- {\r
- ob->y += 8*PIXGLOBAL;\r
- ChangeState(ob, &s_pestrest1);\r
- }\r
- if (ob->hitwest)\r
- {\r
- ob->xspeed = 0;\r
- ob->xdir = -1;\r
- }\r
- if (ob->hiteast)\r
- {\r
- ob->xspeed = 0;\r
- ob->xdir = 1;\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K4_ACT2.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Wormouth\r
-- Thundercloud & Lightning\r
-- Berkeloid & Fireball\r
-- Inchworm & Foot (in-level)\r
-- Bounder\r
-- Lick\r
-- Platform\r
-- Dropping Platform\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- WORMOUTH\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_worm = {WORMOUTHSPR, WORMOUTHSPR, slide, true, true, 4, 16, 0, T_Worm, NULL, R_Walk, &s_worm};\r
-statetype s_wormpeek1 = {WORMOUTHPEEKL1SPR, WORMOUTHPEEKL1SPR, step, false, false, 20, 0, 0, NULL, C_Worm, R_Draw, &s_wormpeek2};\r
-statetype s_wormpeek2 = {WORMOUTHPEEKL2SPR, WORMOUTHPEEKL2SPR, step, false, false, 8, 0, 0, NULL, C_Worm, R_Draw, &s_wormpeek3};\r
-statetype s_wormpeek3 = {WORMOUTHPEEKL1SPR, WORMOUTHPEEKL1SPR, step, false, false, 20, 0, 0, T_WormLookLeft, C_Worm, R_Draw, &s_wormpeek4};\r
-statetype s_wormpeek4 = {WORMOUTHSPR, WORMOUTHSPR, step, false, false, 8, 0, 0, NULL, C_Worm, R_Draw, &s_wormpeek5};\r
-statetype s_wormpeek5 = {WORMOUTHPEEKR1SPR, WORMOUTHPEEKR1SPR, step, false, false, 20, 0, 0, NULL, C_Worm, R_Draw, &s_wormpeek6};\r
-statetype s_wormpeek6 = {WORMOUTHPEEKR2SPR, WORMOUTHPEEKR2SPR, step, false, false, 8, 0, 0, NULL, C_Worm, R_Draw, &s_wormpeek7};\r
-statetype s_wormpeek7 = {WORMOUTHPEEKR1SPR, WORMOUTHPEEKR1SPR, step, false, false, 20, 0, 0, T_WormLookRight, C_Worm, R_Draw, &s_wormpeek8};\r
-statetype s_wormpeek8 = {WORMOUTHSPR, WORMOUTHSPR, step, false, false, 8, 0, 0, T_WormLook, NULL, R_Draw, &s_worm};\r
-statetype s_wormbite1 = {WORMOUTHBITEL1SPR, WORMOUTHBITER1SPR, step, false, false, 8, 0, 0, NULL, C_WormKill, R_Draw, &s_wormbite2};\r
-statetype s_wormbite2 = {WORMOUTHBITEL2SPR, WORMOUTHBITER2SPR, step, false, false, 8, 0, 0, NULL, C_WormKill, R_Draw, &s_wormbite3};\r
-statetype s_wormbite3 = {WORMOUTHBITEL3SPR, WORMOUTHBITER3SPR, step, false, false, 16, 0, 0, NULL, C_WormKill, R_Draw, &s_wormbite4};\r
-statetype s_wormbite4 = {WORMOUTHBITEL2SPR, WORMOUTHBITER2SPR, step, false, false, 8, 0, 0, NULL, C_WormKill, R_Draw, &s_wormbite5};\r
-statetype s_wormbite5 = {WORMOUTHBITEL1SPR, WORMOUTHBITER1SPR, step, false, false, 8, 0, 0, NULL, C_WormKill, R_Draw, &s_worm};\r
-statetype s_wormstun = {WORMOUTHSTUNSPR, WORMOUTHSTUNSPR, think, false, false, 10, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnWormMouth\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnWormMouth(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = wormouthobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + 0x8F;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_worm);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_WormLookRight\r
-=\r
-===========================\r
-*/\r
-\r
-void T_WormLookRight(objtype *ob)\r
-{\r
- if (player->x > ob->x)\r
- {\r
- ob->xdir = 1;\r
- ob->state = &s_worm;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_WormLook\r
-=\r
-===========================\r
-*/\r
-\r
-void T_WormLook(objtype *ob)\r
-{\r
- if (player->x > ob->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_WormLookLeft\r
-=\r
-===========================\r
-*/\r
-\r
-void T_WormLookLeft(objtype *ob)\r
-{\r
- if (player->x < ob->x)\r
- {\r
- ob->xdir = -1;\r
- ob->state = &s_worm;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Worm\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Worm(objtype *ob)\r
-{\r
- Sint16 xdist, ydist;\r
-\r
- xdist = player->x - ob->x;\r
- ydist = player->bottom - ob->bottom;\r
- if ((xdist < -3*TILEGLOBAL || xdist > 3*TILEGLOBAL) && US_RndT() < 6)\r
- {\r
- ob->state = &s_wormpeek1;\r
- }\r
- else if (ydist >= -TILEGLOBAL && ydist <= TILEGLOBAL)\r
- {\r
- if (ob->xdir == 1 && xdist > 8*PIXGLOBAL && xdist < 24*PIXGLOBAL\r
- || ob->xdir == -1 && xdist < -8*PIXGLOBAL && xdist > -32*PIXGLOBAL)\r
- {\r
- SD_PlaySound(SND_WORMOUTHATTACK);\r
- ob->state = &s_wormbite1;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Worm\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Worm(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_wormstun);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_WormKill\r
-=\r
-===========================\r
-*/\r
-\r
-void C_WormKill(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- if (!(ob->xdir == 1 && ob->x > hit->x || ob->xdir == -1 && ob->x < hit->x))\r
- {\r
- KillKeen();\r
- }\r
- return;\r
- }\r
- else\r
- {\r
- C_Worm(ob, hit);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- THUNDERCLOUD\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_cloudsleep = {CLOUDSPR, CLOUDSPR, think, false, false, 20, 0, 0, NULL, C_CloudSleep, R_Draw, NULL};\r
-statetype s_cloudwake = {CLOUDACTIVESPR, CLOUDACTIVESPR, step, false, false, 100, 0, 0, NULL, NULL, R_Cloud, &s_cloud};\r
-statetype s_cloud = {CLOUDACTIVESPR, CLOUDACTIVESPR, think, false, false, 20, 0, 0, T_Cloud, NULL, R_Cloud, NULL};\r
-statetype s_cloudalign = {CLOUDACTIVESPR, CLOUDACTIVESPR, think, false, false, 20, 0, 0, T_CloudAlign, NULL, R_Cloud, NULL};\r
-statetype s_cloudcharge = {CLOUDACTIVESPR, CLOUDACTIVESPR, stepthink, false, false, 60, 0, 0, T_Velocity, NULL, R_Cloud, &s_cloud};\r
-statetype s_cloudattack1 = {CLOUDCHARGESPR, CLOUDCHARGESPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cloudattack2};\r
-statetype s_cloudattack2 = {CLOUDACTIVESPR, CLOUDACTIVESPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cloudattack3};\r
-statetype s_cloudattack3 = {CLOUDCHARGESPR, CLOUDCHARGESPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cloudattack4};\r
-statetype s_cloudattack4 = {CLOUDACTIVESPR, CLOUDACTIVESPR, step, false, false, 10, 0, 0, T_CloudShoot, NULL, R_Draw, &s_cloudattack5};\r
-statetype s_cloudattack5 = {CLOUDCHARGESPR, CLOUDCHARGESPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cloudattack6};\r
-statetype s_cloudattack6 = {CLOUDACTIVESPR, CLOUDACTIVESPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cloudattack7};\r
-statetype s_cloudattack7 = {CLOUDCHARGESPR, CLOUDCHARGESPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cloudattack8};\r
-statetype s_cloudattack8 = {CLOUDACTIVESPR, CLOUDACTIVESPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cloudattack9};\r
-statetype s_cloudattack9 = {CLOUDCHARGESPR, CLOUDCHARGESPR, step, false, false, 48, 0, 0, NULL, NULL, R_Draw, &s_cloudcharge};\r
-\r
-statetype s_bolt1 = {BOLT1SPR, BOLT1SPR, step, false, false, 8, 0, 0, NULL, C_Lethal, R_Draw, &s_bolt2};\r
-statetype s_bolt2 = {BOLT2SPR, BOLT2SPR, step, false, false, 8, 0, 0, NULL, C_Lethal, R_Draw, &s_bolt3};\r
-statetype s_bolt3 = {BOLT1SPR, BOLT1SPR, step, false, false, 8, 0, 0, NULL, C_Lethal, R_Draw, &s_bolt4};\r
-statetype s_bolt4 = {BOLT2SPR, BOLT2SPR, step, false, false, 8, 0, 0, NULL, C_Lethal, R_Draw, &s_bolt5};\r
-statetype s_bolt5 = {BOLT1SPR, BOLT1SPR, step, false, false, 8, 0, 0, NULL, C_Lethal, R_Draw, &s_bolt6};\r
-statetype s_bolt6 = {BOLT2SPR, BOLT2SPR, step, false, false, 8, 0, 0, NULL, C_Lethal, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnCloudster\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnCloudster(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = thundercloudobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- new->ydir = new->xdir = 1;\r
- NewState(new, &s_cloudsleep);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Cloud\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Cloud(objtype *ob)\r
-{\r
- if (US_RndT() < tics)\r
- ob->xdir = ob->x > player->x? -1 : 1;\r
-\r
- AccelerateX(ob, ob->xdir, 10);\r
- if (player->bottom < ob->bottom || (Sint16)(player->top - ob->bottom) > 64*PIXGLOBAL)\r
- return;\r
- if (ob->left < player->right && ob->right > player->left)\r
- {\r
- ob->state = &s_cloudalign;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_CloudAlign\r
-=\r
-===========================\r
-*/\r
-\r
-void T_CloudAlign(objtype *ob)\r
-{\r
- AccelerateX(ob, ob->xdir, 10);\r
- if (xtry < 0 && (Sint16)((ob->x & 0x7F) + xtry) <= 0)\r
- {\r
- xtry = -(ob->x & 0x7F);\r
- ob->state = &s_cloudattack1;\r
- }\r
- if (xtry > 0 && (ob->x & 0x7F) + xtry >= 8*PIXGLOBAL)\r
- {\r
- xtry = 8*PIXGLOBAL - (ob->x & 0x7F);\r
- ob->state = &s_cloudattack1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Cloud\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Cloud(objtype *ob)\r
-{\r
- if (ob->hitwest)\r
- {\r
- ob->xspeed = 0;\r
- ob->xdir = -1;\r
- }\r
- else if (ob->hiteast)\r
- {\r
- ob->xspeed = 0;\r
- ob->xdir = 1;\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_CloudShoot\r
-=\r
-===========================\r
-*/\r
-\r
-void T_CloudShoot(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->obclass = lightningobj;\r
- new->active = ac_removable;\r
- new->needtoclip = cl_noclip;\r
- new->x = ob->x + TILEGLOBAL;\r
- new->y = ob->y + TILEGLOBAL;\r
- NewState(new, &s_bolt1);\r
- SD_PlaySound(SND_THUNDER);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_CloudSleep\r
-=\r
-===========================\r
-*/\r
-\r
-void C_CloudSleep(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- ChangeState(ob, &s_cloudwake);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BERKELOID\r
-\r
-temp1 = float offset, in global units (added to ob->y when drawing the sprite)\r
-temp2 = float speed, in global units per tic (added to temp1 for every tic)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_berkefloat1 = {BERKEWALKL1SPR, BERKEWALKR1SPR, slide, false, true, 6, 8, 0, BerkeThink, C_Berke, BerkeWalkReact, &s_berkefloat2};\r
-statetype s_berkefloat2 = {BERKEWALKL2SPR, BERKEWALKR2SPR, slide, false, true, 6, 8, 0, BerkeThink, C_Berke, BerkeWalkReact, &s_berkefloat3};\r
-statetype s_berkefloat3 = {BERKEWALKL3SPR, BERKEWALKR3SPR, slide, false, true, 6, 8, 0, BerkeThink, C_Berke, BerkeWalkReact, &s_berkefloat4};\r
-statetype s_berkefloat4 = {BERKEWALKL4SPR, BERKEWALKR4SPR, slide, false, true, 6, 8, 0, BerkeThink, C_Berke, BerkeWalkReact, &s_berkefloat1};\r
-statetype s_berkethrow1 = {BERKETHROWL1SPR, BERKETHROWR1SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow2};\r
-statetype s_berkethrow2 = {BERKETHROWL1SPR, BERKETHROWR1SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow3};\r
-statetype s_berkethrow3 = {BERKETHROWL1SPR, BERKETHROWR1SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow4};\r
-statetype s_berkethrow4 = {BERKETHROWL1SPR, BERKETHROWR1SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow5};\r
-statetype s_berkethrow5 = {BERKETHROWL1SPR, BERKETHROWR1SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow6};\r
-statetype s_berkethrow6 = {BERKETHROWL1SPR, BERKETHROWR1SPR, step, false, false, 6, 0, 0, BerkeThrowThink, C_Berke, BerkeDrawReact, &s_berkethrow7};\r
-statetype s_berkethrow7 = {BERKETHROWL2SPR, BERKETHROWR2SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow8};\r
-statetype s_berkethrow8 = {BERKETHROWL2SPR, BERKETHROWR2SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow9};\r
-statetype s_berkethrow9 = {BERKETHROWL2SPR, BERKETHROWR2SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow10};\r
-statetype s_berkethrow10 = {BERKETHROWL2SPR, BERKETHROWR2SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow11};\r
-statetype s_berkethrow11 = {BERKETHROWL2SPR, BERKETHROWR2SPR, step, false, false, 6, 0, 0, SetReactThink, C_Berke, BerkeDrawReact, &s_berkethrow12};\r
-statetype s_berkethrow12 = {BERKETHROWL2SPR, BERKETHROWR2SPR, step, false, false, 6, 0, 0, BerkeThrowDone, C_Berke, BerkeDrawReact, &s_berkefloat1};\r
-\r
-statetype s_fire1 = {FIREBALL1SPR, FIREBALL1SPR, stepthink, false, false, 6, 0, 0, T_WeakProjectile, C_Lethal, FireReact, &s_fire2};\r
-statetype s_fire2 = {FIREBALL2SPR, FIREBALL2SPR, stepthink, false, false, 6, 0, 0, T_WeakProjectile, C_Lethal, FireReact, &s_fire1};\r
-statetype s_fireland1 = {FIREBALL1SPR, FIREBALL1SPR, step, false, false, 6, 0, 0, NULL, C_Berke, R_Draw, &s_fireland2};\r
-statetype s_fireland2 = {FIREBALL3SPR, FIREBALL3SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, &s_fireland3};\r
-statetype s_fireland3 = {FIREBALL4SPR, FIREBALL4SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, &s_fireland4};\r
-statetype s_fireland4 = {FIREBALL3SPR, FIREBALL3SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, &s_fireland5};\r
-statetype s_fireland5 = {FIREBALL4SPR, FIREBALL4SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, &s_fireland6};\r
-statetype s_fireland6 = {FIREBALL1SPR, FIREBALL1SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, &s_fireland7};\r
-statetype s_fireland7 = {FIREBALL2SPR, FIREBALL2SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, &s_fireland8};\r
-statetype s_fireland8 = {FIREBALL1SPR, FIREBALL1SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, &s_fireland9};\r
-statetype s_fireland9 = {FIREBALL2SPR, FIREBALL2SPR, step, false, false, 12, 0, 0, NULL, C_Berke, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBerkeloid\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBerkeloid(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = berkeloidobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -2*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- new->temp2 = 8;\r
- NewState(new, &s_berkefloat1);\r
-}\r
-\r
-\r
-/*\r
-===========================\r
-=\r
-= BerkeThink\r
-=\r
-===========================\r
-*/\r
-\r
-void BerkeThink(objtype *ob)\r
-{\r
- Sint16 xdist, ydist;\r
-\r
- if (US_RndT() < 0x20)\r
- ob->xdir = player->x < ob->x? -1 : 1;\r
-\r
- if (US_RndT() < 8)\r
- {\r
- // BUG: might be about to move off a ledge, causing it to get stuck\r
- // after throwing (the throw states don't use BerkeWalkReact)!\r
- // To avoid that, set xtry to 0 here.\r
-\r
- ob->state = &s_berkethrow1;\r
- // BUG? this doesn't play the attack sound\r
- }\r
- else if (US_RndT() <= 0x40)\r
- {\r
- xdist = player->x - ob->x;\r
- ydist = player->y - ob->y;\r
- if (ydist >= -TILEGLOBAL && ydist <= TILEGLOBAL\r
- && (ob->xdir == 1 && xdist > 0 || ob->xdir == -1 && xdist < 0))\r
- {\r
- // BUG: might be about to move off a ledge, causing it to get stuck\r
- // after throwing (the throw states don't use BerkeWalkReact)!\r
- // To avoid that, set xtry to 0 here.\r
-\r
- ob->state = &s_berkethrow1;\r
- SD_PlaySound(SND_BERKELOIDATTACK);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= BerkeThrowThink\r
-=\r
-===========================\r
-*/\r
-\r
-void BerkeThrowThink(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->active = ac_removable;\r
- new->obclass = berkeloidobj;\r
- new->y = ob->y + 8*PIXGLOBAL;\r
- new->yspeed = -8;\r
- if (ob->xdir == 1)\r
- {\r
- new->xspeed = 48;\r
- new->x = ob->x + 32*PIXGLOBAL;\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xspeed = -48;\r
- new->x = ob->x - 16*PIXGLOBAL;\r
- new->xdir = -1;\r
- }\r
- NewState(new, &s_fire1);\r
- ob->needtoreact = true;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= BerkeThrowDone\r
-=\r
-===========================\r
-*/\r
-\r
-void BerkeThrowDone(objtype *ob)\r
-{\r
- ob->nothink = 4;\r
- ob->needtoreact = true;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Berke\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Berke(objtype *ob, objtype *hit)\r
-{\r
- ob++; // shut up compiler\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= FireReact\r
-=\r
-===========================\r
-*/\r
-\r
-void FireReact(objtype *ob)\r
-{\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- SD_PlaySound(SND_FIREBALLLAND);\r
- ChangeState(ob, &s_fireland1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= BerkeDrawReact\r
-=\r
-===========================\r
-*/\r
-\r
-void BerkeDrawReact(objtype *ob)\r
-{\r
- //float up & down:\r
- ob->temp1 = ob->temp1 + ob->temp2 * tics;\r
- if (ob->temp1 > 0)\r
- {\r
- ob->temp1 = 0;\r
- ob->temp2 = -8;\r
- }\r
- else if (ob->temp1 < -TILEGLOBAL)\r
- {\r
- ob->temp1 = -TILEGLOBAL;\r
- ob->temp2 = 8;\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y+ob->temp1, ob->shapenum, spritedraw, 0);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= BerkeWalkReact\r
-=\r
-===========================\r
-*/\r
-\r
-void BerkeWalkReact(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove*2;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- BerkeDrawReact(ob);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- INCHWORM & FOOT\r
-\r
-temp1 = last lasttimecount (for resetting the touch counter after each frame)\r
-temp2 = touch counter\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_footsmoke1 = {SMOKE1SPR, SMOKE1SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_footsmoke2};\r
-statetype s_footsmoke2 = {SMOKE2SPR, SMOKE2SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_footsmoke3};\r
-statetype s_footsmoke3 = {SMOKE3SPR, SMOKE3SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_footsmoke4};\r
-statetype s_footsmoke4 = {SMOKE4SPR, SMOKE4SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, NULL};\r
-statetype s_inch1 = {INCHWORML1SPR, INCHWORMR1SPR, step, false, true, 30, 128, 0, InchThink, InchContact, R_Walk, &s_inch2};\r
-statetype s_inch2 = {INCHWORML2SPR, INCHWORMR2SPR, step, false, true, 30, 128, 0, InchThink, InchContact, R_Walk, &s_inch1};\r
-statetype s_footchange = { -1, -1, step, false, false, 48, 0, 0, NULL, NULL, R_Draw, &s_footwait}; //never used!\r
-statetype s_footwait = {FOOTSPR, FOOTSPR, think, false, false, 30000, 0, 0, NULL, FootContact, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnInchworm\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnInchworm(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = inchwormobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_inch1);\r
- new->ticcount = US_RndT() / 32;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnFoot\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnFoot(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = footobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y-3);\r
- NewState(new, &s_footwait);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= InchThink\r
-=\r
-===========================\r
-*/\r
-\r
-void InchThink(objtype *ob)\r
-{\r
- if (ob->x > player->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= InchContact\r
-=\r
-===========================\r
-*/\r
-\r
-void InchContact(objtype *ob, objtype *hit)\r
-{\r
- objtype *ob2;\r
-\r
- if (hit->obclass != inchwormobj)\r
- return;\r
-\r
- if (ob->temp1 != (Sint16)lasttimecount)\r
- {\r
- ob->temp1 = (Sint16)lasttimecount;\r
- ob->temp2 = 0;\r
- }\r
-\r
- if (++ob->temp2 != 11) //11 instead of 12 since the object can't contact itself\r
- return;\r
-\r
- //change current inchworm into a foot:\r
- SD_PlaySound(SND_MAKEFOOT);\r
- ob->y -= 5*TILEGLOBAL;\r
- ob->obclass = footobj;\r
- ChangeState(ob, &s_footwait);\r
-\r
- //Note: It would make more sense to remove the remaining inchworm BEFORE\r
- //spawning the smoke, just in case there are not enough free spots in the\r
- //objarray to spawn the smoke. The game won't crash either way, though.\r
-\r
- //spawn smoke:\r
- GetNewObj(true);\r
- new->x = ob->x - 8*PIXGLOBAL;\r
- new->y = ob->y + 16*PIXGLOBAL;\r
- new->priority = 3;\r
- NewState(new, &s_footsmoke1);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x + 16*PIXGLOBAL;\r
- new->y = ob->y + 24*PIXGLOBAL;\r
- new->priority = 3;\r
- NewState(new, &s_footsmoke1);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x + 40*PIXGLOBAL;\r
- new->y = ob->y + 16*PIXGLOBAL;\r
- new->priority = 3;\r
- NewState(new, &s_footsmoke1);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y - 8*PIXGLOBAL;\r
- new->priority = 3;\r
- NewState(new, &s_footsmoke1);\r
-\r
- //remove ALL inchworm from the level:\r
- for (ob2 = player->next; ob2; ob2=ob2->next)\r
- {\r
- if (ob2->obclass == inchwormobj)\r
- RemoveObj(ob2);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= FootContact\r
-=\r
-===========================\r
-*/\r
-\r
-void FootContact(objtype *ob, objtype *hit) //completely useless\r
-{\r
- ob++; // shut up compiler\r
- hit++; // shut up compiler\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BOUNDER\r
-\r
-temp1 = if non-zero, pick a new (random) direction when hitting the ground\r
- Makes the Bounder jump straight up at least once after having jumped\r
- left/right (unless Keen is riding the Bounder)\r
-temp2 = jump counter to make the Bounder jump straight up at least twice\r
- after Keen has fallen/jumped off\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bounderup1 = {BOUNDERC1SPR, BOUNDERC1SPR, stepthink, false, false, 20, 0, 0, T_Projectile, C_Bounder, R_Bounder, &s_bounderup2};\r
-statetype s_bounderup2 = {BOUNDERC2SPR, BOUNDERC2SPR, stepthink, false, false, 20, 0, 0, T_Projectile, C_Bounder, R_Bounder, &s_bounderup1};\r
-statetype s_bounderside1 = {BOUNDERL1SPR, BOUNDERR1SPR, stepthink, false, false, 20, 0, 0, T_Projectile, C_Bounder, R_Bounder, &s_bounderside2};\r
-statetype s_bounderside2 = {BOUNDERL2SPR, BOUNDERR2SPR, stepthink, false, false, 20, 0, 0, T_Projectile, C_Bounder, R_Bounder, &s_bounderside1};\r
-statetype s_bounderstun = {BOUNDERC1SPR, BOUNDERC1SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_bounderstun2};\r
-statetype s_bounderstun2 = {BOUNDERSTUNSPR, BOUNDERSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBounder\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBounder(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = bounderobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -8*PIXGLOBAL;\r
- new->ydir = 1;\r
- new->xdir = 0;\r
- NewState(new, &s_bounderup1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Bounder\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Bounder(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- //basically StunObj(), but in different order:\r
- ob->temp1 = 0;\r
- ob->temp2 = 0;\r
- ob->temp3 = 0;\r
- ob->temp4 = ob->obclass;\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_bounderstun);\r
- ob->obclass = stunnedobj;\r
-\r
- ob->yspeed -= 32;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Bounder\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Bounder(objtype *ob)\r
-{\r
- Sint16 randnum;\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->temp2++;\r
- if (OnScreen(ob))\r
- SD_PlaySound(SND_BOUNCE2);\r
-\r
- ob->yspeed = -50;\r
- if (gamestate.riding == ob)\r
- {\r
- ob->temp2 = 0;\r
- if (player->left < ob->left-4*PIXGLOBAL)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else if (player->right > ob->right+4*PIXGLOBAL)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = 0;\r
- }\r
- ob->xspeed = ob->xdir * 24;\r
- }\r
- else if (ob->temp2 <= 2 || ob->temp1 == 0)\r
- {\r
- ob->temp1 = 1;\r
- ob->xdir = ob->xspeed = 0;\r
- ChangeState(ob, &s_bounderup1);\r
- }\r
- else\r
- {\r
- ob->temp1 = 0;\r
- randnum = US_RndT();\r
- if (randnum < 100)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else if (randnum < 200)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = 0;\r
- }\r
- ob->xspeed = ob->xdir * 24;\r
- }\r
-\r
- if (ob->xdir)\r
- {\r
- ChangeState(ob, &s_bounderside1);\r
- }\r
- else\r
- {\r
- ChangeState(ob, &s_bounderup1);\r
- }\r
- }\r
-\r
- if (ob->hiteast || ob->hitwest)\r
- {\r
- ob->xdir = -ob->xdir;\r
- ob->xspeed = -ob->xspeed;\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- LICK\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_lick1 = {LICKMOVEL1SPR, LICKMOVER1SPR, step, false, false, 10, 0, 0, LickJumpThink, LickContact, R_Draw, &s_lick2};\r
-statetype s_lick2 = {LICKMOVEL2SPR, LICKMOVER2SPR, think, false, false, 0, 0, 0, T_Projectile, LickContact, LickAirReact, &s_lick3};\r
-statetype s_lick3 = {LICKMOVEL3SPR, LICKMOVER3SPR, think, false, false, 0, 0, 0, T_Projectile, LickContact, LickAirReact, NULL};\r
-statetype s_lick4 = {LICKMOVEL4SPR, LICKMOVER4SPR, step, false, false, 10, 0, 0, NULL, LickContact, R_Draw, &s_lick1};\r
-statetype s_licklick1 = {LICKATTACKL1SPR, LICKATTACKR1SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_licklick2};\r
-statetype s_licklick2 = {LICKATTACKL2SPR, LICKATTACKR2SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_licklick3};\r
-statetype s_licklick3 = {LICKATTACKL3SPR, LICKATTACKR3SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_licklick4};\r
-statetype s_licklick4 = {LICKATTACKL2SPR, LICKATTACKR2SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_licklick5};\r
-statetype s_licklick5 = {LICKATTACKL1SPR, LICKATTACKR1SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_licklick6};\r
-statetype s_licklick6 = {LICKATTACKL2SPR, LICKATTACKR2SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_licklick7};\r
-statetype s_licklick7 = {LICKATTACKL3SPR, LICKATTACKR3SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_licklick8};\r
-statetype s_licklick8 = {LICKATTACKL2SPR, LICKATTACKR2SPR, step, true, false, 4, 0, 0, NULL, LickKillContact, R_Draw, &s_lick3};\r
-statetype s_lickstun = {LICKSTUNSPR, LICKSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_lickstun2};\r
-statetype s_lickstun2 = {LICKSTUNSPR, LICKSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnLick\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnLick(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = lickobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- new->nothink = US_RndT() / 64;\r
- NewState(new, &s_lick3);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= LickJumpThink\r
-=\r
-===========================\r
-*/\r
-\r
-void LickJumpThink(objtype *ob)\r
-{\r
- Sint16 xdist, ydist;\r
-\r
- if (ob->x > player->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
-\r
- xdist = player->x - ob->x;\r
- ydist = player->y - ob->y;\r
-\r
- if (ydist >= -TILEGLOBAL && ydist <= TILEGLOBAL && \r
- ( ob->xdir == 1 && xdist > -2*PIXGLOBAL && xdist < 24*PIXGLOBAL\r
- || ob->xdir == -1 && xdist < 2*PIXGLOBAL && xdist > -32*PIXGLOBAL ) )\r
- {\r
- SD_PlaySound(SND_LICKATTACK);\r
- ob->state = &s_licklick1;\r
- }\r
- else if (abs(xdist) > 3*TILEGLOBAL)\r
- {\r
- ob->xspeed = ob->xdir * 32;\r
- ob->yspeed = -32;\r
- }\r
- else\r
- {\r
- ob->xspeed = (ob->xdir * 32)/2;\r
- ob->yspeed = -16;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= LickContact\r
-=\r
-===========================\r
-*/\r
-\r
-void LickContact(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_lickstun);\r
- ob->yspeed -= 16;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= LickKillContact\r
-=\r
-===========================\r
-*/\r
-\r
-void LickKillContact(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- if (ob->xdir == 1 && player->x > ob->x \r
- || ob->xdir == -1 && player->x < ob->x)\r
- {\r
- KillKeen();\r
- }\r
- }\r
- else\r
- {\r
- LickContact(ob, hit);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= LickAirReact\r
-=\r
-===========================\r
-*/\r
-\r
-void LickAirReact(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- ChangeState(ob, &s_lick4);\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- PLATFORM\r
-\r
-temp2 = additional sprite pointer for thruster sprites\r
-temp3 = additional sprite pointer for thruster sprites\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_platform = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_Platform, NULL, R_Platform, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnPlatform\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnPlatform(Sint16 x, Sint16 y, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- switch (dir)\r
- {\r
- case 0:\r
- new->xdir = 0;\r
- new->ydir = -1;\r
- break;\r
- case 1:\r
- new->xdir = 1;\r
- new->ydir = 0;\r
- break;\r
- case 2:\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- break;\r
- case 3:\r
- new->xdir = -1;\r
- new->ydir = 0;\r
- break;\r
- }\r
- NewState(new, &s_platform);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Platform\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Platform(objtype *ob)\r
-{\r
- Uint16 newpos, newtile;\r
-\r
- xtry = ob->xdir * 12 * tics;\r
- ytry = ob->ydir * 12 * tics;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- newpos = ob->right + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileright != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2+newtile) == 31)\r
- {\r
- ob->xdir = -1;\r
- xtry = xtry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- else if (ob->xdir == -1)\r
- {\r
- newpos = ob->left + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileleft != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2+newtile) == 31)\r
- {\r
- ob->xdir = 1;\r
- xtry = xtry + (0x100 - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- else if (ob->ydir == 1)\r
- {\r
- newpos = ob->bottom + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tilebottom != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2+ob->tileleft) == 31)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile-2]/2+ob->tileleft) == 31)\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = -1;\r
- ytry = ytry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- }\r
- else if (ob->ydir == -1)\r
- {\r
- newpos = ob->top + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tiletop != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2+ob->tileleft) == 31)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile+2]/2+ob->tileleft) == 31)\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = 1;\r
- ytry = ytry + (0x100 - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Platform\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Platform(objtype *ob)\r
-{\r
- Uint16 frame;\r
-\r
- //place platform sprite:\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- \r
- //place (or remove) thruster sprites:\r
- frame = (lasttimecount >> 2) & 1;\r
- if (ob->xdir == 1)\r
- {\r
- RF_PlaceSprite((void**)&ob->temp2, ob->x-1*PIXGLOBAL, ob->y+3*PIXGLOBAL, frame+PLATSIDETHRUST1SPR, spritedraw, 0);\r
- if (ob->temp3)\r
- RF_RemoveSprite((void**)&ob->temp3);\r
- }\r
- else if (ob->xdir == -1)\r
- {\r
- if (ob->temp2)\r
- RF_RemoveSprite((void**)&ob->temp2);\r
- RF_PlaceSprite((void**)&ob->temp3, ob->x+48*PIXGLOBAL, ob->y+5*PIXGLOBAL, frame+PLATSIDETHRUST1SPR, spritedraw, 1);\r
- }\r
- else if (ob->ydir == -1)\r
- {\r
- RF_PlaceSprite((void**)&ob->temp2, ob->x+2*PIXGLOBAL, ob->y+9*PIXGLOBAL, frame+PLATLTHRUST1SPR, spritedraw, 0);\r
- RF_PlaceSprite((void**)&ob->temp3, ob->x+46*PIXGLOBAL, ob->y+8*PIXGLOBAL, frame+PLATRTHRUST1SPR, spritedraw, 0);\r
- }\r
- else if (ob->ydir == 1)\r
- {\r
- if (frame)\r
- {\r
- RF_PlaceSprite((void**)&ob->temp2, ob->x+2*PIXGLOBAL, ob->y+9*PIXGLOBAL, frame+PLATLTHRUST1SPR, spritedraw, 0);\r
- RF_PlaceSprite((void**)&ob->temp3, ob->x+46*PIXGLOBAL, ob->y+8*PIXGLOBAL, frame+PLATRTHRUST1SPR, spritedraw, 0);\r
- }\r
- else\r
- {\r
- if (ob->temp2)\r
- RF_RemoveSprite((void**)&ob->temp2);\r
- if (ob->temp3)\r
- RF_RemoveSprite((void**)&ob->temp3);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- DROPPING PLATFORM\r
-\r
-temp1 = initial y position\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_dropplatsit = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatSit, NULL, R_Draw, NULL};\r
-statetype s_dropplatfall = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatFall, NULL, R_Draw, NULL};\r
-statetype s_dropplatrise = {PLATFORMSPR, PLATFORMSPR, slidethink, false, false, 0, 0, -32, T_DropPlatRise, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnDropPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnDropPlat(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = new->temp1 = CONVERT_TILE_TO_GLOBAL(y);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_dropplatsit);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatSit\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatSit(objtype *ob)\r
-{\r
- if (gamestate.riding == ob)\r
- {\r
- ytry = tics * 16;\r
- ob->yspeed = 0;\r
- if (ob->y + ytry - ob->temp1 >= 8*PIXGLOBAL)\r
- ob->state = &s_dropplatfall;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatFall\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatFall(objtype *ob)\r
-{\r
- Uint16 newy, ty;\r
-\r
- DoGravity(ob);\r
-\r
- if (ytry >= 15*PIXGLOBAL)\r
- ytry = 15*PIXGLOBAL;\r
-\r
- newy = ob->bottom + ytry;\r
- ty = CONVERT_GLOBAL_TO_TILE(newy);\r
- if (ob->tilebottom != ty)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ty]/2+ob->tileleft) == 31)\r
- {\r
- ytry = 0xFF - (ob->bottom & 0xFF);\r
- if (gamestate.riding != ob)\r
- ob->state = &s_dropplatrise;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatRise\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatRise(objtype *ob)\r
-{\r
- if (gamestate.riding == ob)\r
- {\r
- ob->yspeed = 0;\r
- ob->state = &s_dropplatfall;\r
- }\r
- else if (ob->y <= ob->temp1)\r
- {\r
- ytry = ob->temp1 - ob->y;\r
- ob->state = &s_dropplatsit;\r
- }\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K4_ACT3.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Treasure Eater\r
-- Mimrock\r
-- Dopefish\r
-- Schoolfish\r
-- Sprite\r
-- Mine\r
-- Lindsey\r
-- Dart Shooter & Dart\r
-- Wetsuit\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- TREASURE EATER\r
-\r
-temp1 = turn counter\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_eaterstand1 = {EATERSTAND1SPR, EATERSTAND1SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eaterstand2};\r
-statetype s_eaterstand2 = {EATERSTAND2SPR, EATERSTAND2SPR, step, false, false, 20, 0, 0, T_EaterJump, C_Eater, R_Draw, NULL};\r
-statetype s_eatertport1 = {SMOKE1SPR, SMOKE1SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eatertport2};\r
-statetype s_eatertport2 = {SMOKE2SPR, SMOKE2SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eatertport3};\r
-statetype s_eatertport3 = {SMOKE3SPR, SMOKE3SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eatertport4};\r
-statetype s_eatertport4 = {SMOKE4SPR, SMOKE4SPR, step, false, false, 20, 0, 0, T_EaterTeleport, C_Eater, R_Draw, &s_eatertport5};\r
-statetype s_eatertport5 = {SMOKE4SPR, SMOKE4SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eatertport6};\r
-statetype s_eatertport6 = {SMOKE3SPR, SMOKE3SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eatertport7};\r
-statetype s_eatertport7 = {SMOKE2SPR, SMOKE2SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eatertport8};\r
-statetype s_eatertport8 = {SMOKE1SPR, SMOKE1SPR, step, false, false, 20, 0, 0, NULL, C_Eater, R_Draw, &s_eaterjump1};\r
-statetype s_eaterjump1 = {EATERJUMPL1SPR, EATERJUMPR1SPR, stepthink, false, false, 6, 0, 0, T_WeakProjectile, C_Eater, R_EaterAir, &s_eaterjump2};\r
-statetype s_eaterjump2 = {EATERJUMPL2SPR, EATERJUMPR2SPR, stepthink, false, false, 6, 0, 0, T_WeakProjectile, C_Eater, R_EaterAir, &s_eaterjump3};\r
-statetype s_eaterjump3 = {EATERJUMPL3SPR, EATERJUMPR3SPR, stepthink, false, false, 6, 0, 0, T_WeakProjectile, C_Eater, R_EaterAir, &s_eaterjump4};\r
-statetype s_eaterjump4 = {EATERJUMPL2SPR, EATERJUMPR2SPR, stepthink, false, false, 6, 0, 0, T_WeakProjectile, C_Eater, R_EaterAir, &s_eaterjump1};\r
-statetype s_eaterstun = {EATERJUMPL1SPR, EATERJUMPL1SPR, think, false, false, 0, 0, 0, T_Projectile, 0, R_Stunned, &s_eaterstun2};\r
-statetype s_eaterstun2 = {EATERSTUNSPR, EATERSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, 0, R_Stunned, NULL};\r
-\r
-statetype s_eatenbonus1 = {EATENBONUS1SPR, EATENBONUS1SPR, slide, false, false, 10, 0, 8, NULL, NULL, R_Draw, &s_eatenbonus2};\r
-statetype s_eatenbonus2 = {EATENBONUS2SPR, EATENBONUS2SPR, slide, false, false, 10, 0, 8, NULL, NULL, R_Draw, &s_eatenbonus3};\r
-statetype s_eatenbonus3 = {EATENBONUS3SPR, EATENBONUS3SPR, slide, false, false, 10, 0, 8, NULL, NULL, R_Draw, &s_eatenbonus4};\r
-statetype s_eatenbonus4 = {EATENBONUS4SPR, EATENBONUS4SPR, slide, false, false, 10, 0, 8, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnEater\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnEater(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = treasureeaterobj;\r
- new->active = ac_yes;\r
- new->priority = 3;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) - 24*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_eaterstand1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_EaterJump\r
-=\r
-===========================\r
-*/\r
-\r
-void T_EaterJump(objtype *ob)\r
-{\r
- objtype *ob2;\r
- Uint16 x;\r
- Sint16 y;\r
- Uint16 far *map;\r
- Uint16 intile, rowdiff, width;\r
-\r
- ob->state = &s_eaterjump1;\r
-\r
- //jump straight up if below bonus object:\r
- for (ob2 = player->next; ob2; ob2 = ob2->next)\r
- {\r
- if (ob2->obclass == bonusobj && ob2->active == ac_yes\r
- && ob2->right > ob->left && ob2->left < ob->right\r
- && ob2->bottom < ob->top && ob2->bottom + 3*TILEGLOBAL > ob->top)\r
- {\r
- ob->xspeed = 0;\r
- ob->yspeed = -48;\r
- return;\r
- }\r
- }\r
-\r
- //jump straight up if below bonus tile:\r
- map = mapsegs[1] + mapbwidthtable[ob->tiletop-3]/2 + ob->tileleft;\r
- width = ob->tileright-ob->tileleft+1;\r
- rowdiff = mapwidth-width;\r
- for (y=0; y<3; y++, map+=rowdiff)\r
- {\r
- for (x=0; x<width; x++, map++)\r
- {\r
- intile = tinf[INTILE+*map];\r
- if (intile == INTILE_DROP || intile >= INTILE_BONUS100 && intile <= INTILE_AMMO)\r
- {\r
- ob->xspeed = 0;\r
- ob->yspeed = -48;\r
- return;\r
- }\r
- }\r
- }\r
-\r
- //vanish after having checked both directions:\r
- if (ob->temp1 >= 2)\r
- {\r
- // BUG? this doesn't play a sound\r
- ob->state = &s_eatertport1;\r
- return;\r
- }\r
-\r
- //jump in current direction if there is a floor in that direction:\r
- map = mapsegs[1] + mapbwidthtable[ob->tilebottom-2]/2 + ob->tilemidx;\r
- map += ob->xdir * 4;\r
- for (y=0; y<4; y++, map+=mapwidth)\r
- {\r
- if (tinf[NORTHWALL+*map])\r
- {\r
- ob->xspeed = ob->xdir * 20;\r
- ob->yspeed = -24;\r
- return;\r
- }\r
- }\r
-\r
- //couldn't jump in current direction, so turn around:\r
- if (++ob->temp1 == 2)\r
- {\r
- SD_PlaySound(SND_TREASUREEATERVANISH);\r
- ob->state = &s_eatertport1;\r
- return;\r
- }\r
-\r
- //jump in opposite direction:\r
- ob->xdir = -ob->xdir;\r
- ob->xspeed = ob->xdir * 20;\r
- ob->yspeed = -24;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_EaterTeleport\r
-=\r
-===========================\r
-*/\r
-\r
-void T_EaterTeleport(objtype *ob)\r
-{\r
- objtype *ob2;\r
-\r
- ob->temp1 = 0;\r
- for (ob2=player->next; ob2; ob2=ob2->next)\r
- {\r
- if (ob2->obclass == bonusobj)\r
- {\r
- ob->x = ob2->x - 8*PIXGLOBAL;\r
- ob->y = ob2->y;\r
- NewState(ob, &s_eatertport5);\r
- return;\r
- }\r
- }\r
- RemoveObj(ob);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Eater\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Eater(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == bonusobj)\r
- {\r
- //BUG? bonus object might be a key, and eating a key makes a level unwinnable\r
- hit->obclass = inertobj;\r
- hit->priority = 3;\r
- ChangeState(hit, &s_eatenbonus1);\r
- SD_PlaySound(SND_EATBONUS);\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- //basically StunObj(), but in different order:\r
- ob->temp1 = 0;\r
- ob->temp2 = 0;\r
- ob->temp3 = 0;\r
- ob->temp4 = ob->obclass;\r
- ob->obclass = stunnedobj;\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_eaterstun);\r
-\r
- ob->yspeed -= 16;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= EaterInTile\r
-=\r
-===========================\r
-*/\r
-\r
-void EaterInTile(objtype *ob)\r
-{\r
- Uint16 x, y;\r
- Uint16 far *map;\r
- Uint16 rowdiff, intile;\r
-\r
- map = mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft;\r
- rowdiff = mapwidth-(ob->tileright-ob->tileleft+1);\r
- for (y=ob->tiletop; y<=ob->tilebottom; y++, map+=rowdiff)\r
- {\r
- for (x=ob->tileleft; x<=ob->tileright; x++, map++)\r
- {\r
- intile = tinf[INTILE + *map] & INTILE_TYPEMASK;\r
- if (intile == INTILE_DROP || intile >= INTILE_BONUS100 && intile <= INTILE_AMMO)\r
- {\r
- RF_MemToMap(&zeromap, 1, x, y, 1, 1);\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->priority = 3;\r
- new->needtoclip = cl_noclip;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- new->active = ac_removable;\r
- ChangeState(new, &s_eatenbonus1); //using ChangeState and not NewState is fine for noclipping objects\r
- //BUG? this doesn't play a sound\r
- break;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_EaterAir\r
-=\r
-===========================\r
-*/\r
-\r
-void R_EaterAir(objtype *ob)\r
-{\r
- EaterInTile(ob);\r
-\r
- if (ob->hitnorth)\r
- ChangeState(ob, &s_eaterstand1);\r
-\r
- if (ob->hiteast || ob->hitwest)\r
- {\r
- ob->temp1++;\r
- ob->xdir = -ob->xdir;\r
- ob->xspeed = 0;\r
- }\r
-\r
- if (ob->hitnorth) //BUG? maybe this was supposed to check hitsouth as well?\r
- ob->yspeed = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- MIMROCK\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_mimrock = {MIMROCKSPR, MIMROCKSPR, step, false, true, 20, 0, 0, T_MimrockWait, NULL, R_Walk, &s_mimrock};\r
-statetype s_mimsneak1 = {MIMROCKWALKR1SPR, MIMROCKWALKL1SPR, step, false, true, 6, 64, 0, T_MimrockSneak, C_Mimrock, R_Walk, &s_mimsneak2};\r
-statetype s_mimsneak2 = {MIMROCKWALKR2SPR, MIMROCKWALKL2SPR, step, false, true, 6, 64, 0, T_MimrockSneak, C_Mimrock, R_Walk, &s_mimsneak3};\r
-statetype s_mimsneak3 = {MIMROCKWALKR3SPR, MIMROCKWALKL3SPR, step, false, true, 6, 64, 0, T_MimrockSneak, C_Mimrock, R_Walk, &s_mimsneak4};\r
-statetype s_mimsneak4 = {MIMROCKWALKR4SPR, MIMROCKWALKL4SPR, step, false, true, 6, 64, 0, T_MimrockSneak, C_Mimrock, R_Walk, &s_mimsneak5};\r
-statetype s_mimsneak5 = {MIMROCKWALKR1SPR, MIMROCKWALKL1SPR, step, false, true, 6, 64, 0, T_MimrockSneak, C_Mimrock, R_Walk, &s_mimsneak6};\r
-statetype s_mimsneak6 = {MIMROCKWALKR2SPR, MIMROCKWALKL2SPR, step, false, true, 6, 64, 0, T_MimrockSneak, C_Mimrock, R_Walk, &s_mimrock};\r
-statetype s_mimbonk1 = {MIMROCKJUMPL1SPR, MIMROCKJUMPR1SPR, stepthink, false, false, 24, 0, 0, T_WeakProjectile, C_MimLethal, R_MimAir, &s_mimbonk2};\r
-statetype s_mimbonk2 = {MIMROCKJUMPL2SPR, MIMROCKJUMPR2SPR, stepthink, false, false, 10, 0, 0, T_WeakProjectile, C_MimLethal, R_MimAir, &s_mimbonk3};\r
-statetype s_mimbonk3 = {MIMROCKJUMPL3SPR, MIMROCKJUMPR3SPR, think, false, false, 10, 0, 0, T_WeakProjectile, C_MimLethal, R_MimAir, &s_mimbonk2};\r
-statetype s_mimbounce = {MIMROCKJUMPL3SPR, MIMROCKJUMPR3SPR, think, false, false, 10, 0, 0, T_Projectile, C_Mimrock, R_MimBounce, NULL};\r
-statetype s_mimstun = {MIMROCKJUMPL3SPR, MIMROCKJUMPL3SPR, think, false, false, 12, 0, 0, T_Projectile, NULL, R_Stunned, &s_mimstun2};\r
-statetype s_mimstun2 = {MINROCKSTUNSPR, MINROCKSTUNSPR, think, false, false, 12, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnMimrock\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnMimrock(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = mimrockobj;\r
- new->active = ac_yes;\r
- new->priority = 3;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y)+ -13*PIXGLOBAL;\r
- new->ydir = new->xdir = 1;\r
- NewState(new, &s_mimrock);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_MimrockWait\r
-=\r
-===========================\r
-*/\r
-\r
-void T_MimrockWait(objtype *ob)\r
-{\r
- if (abs(ob->bottom - player->bottom) > 5*TILEGLOBAL)\r
- return;\r
-\r
- if (abs(ob->x - player->x) > 3*TILEGLOBAL)\r
- {\r
- if (player->x < ob->x)\r
- {\r
- if (player->xdir == -1)\r
- {\r
- ob->xdir = -1;\r
- ob->state = &s_mimsneak1;\r
- }\r
- }\r
- else\r
- {\r
- if (player->xdir == 1)\r
- {\r
- ob->xdir = 1;\r
- ob->state = &s_mimsneak1;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_MimrockSneak\r
-=\r
-===========================\r
-*/\r
-\r
-void T_MimrockSneak(objtype *ob)\r
-{\r
- if (abs(ob->bottom - player->bottom) > 5*TILEGLOBAL\r
- || ob->xdir != player->xdir)\r
- {\r
- ob->state = &s_mimrock;\r
- }\r
- else if (abs(ob->x - player->x) < 4*TILEGLOBAL)\r
- {\r
- ob->xspeed = ob->xdir * 20;\r
- ob->yspeed = -40;\r
- ytry = ob->yspeed * tics;\r
- ob->state = &s_mimbonk1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Mimrock\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Mimrock(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- //basically StunObj(), but in different order:\r
- ob->temp1 = 0;\r
- ob->temp2 = 0;\r
- ob->temp3 = 0;\r
- ob->temp4 = ob->obclass;\r
- ob->obclass = stunnedobj;\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_mimstun);\r
-\r
- ob->yspeed -= 16;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_MimLethal\r
-=\r
-===========================\r
-*/\r
-\r
-void C_MimLethal(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else\r
- {\r
- C_Mimrock(ob, hit);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_MimAir\r
-=\r
-===========================\r
-*/\r
-\r
-void R_MimAir(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- {\r
- SD_PlaySound(SND_HELMETHIT);\r
- ob->yspeed = -20;\r
- ChangeState(ob, &s_mimbounce);\r
- }\r
-\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitnorth || ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_MimBounce\r
-=\r
-===========================\r
-*/\r
-\r
-void R_MimBounce(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- {\r
- SD_PlaySound(SND_HELMETHIT);\r
- ChangeState(ob, &s_mimrock);\r
- }\r
-\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- ob->yspeed = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- DOPEFISH\r
-\r
-temp1 = blocked (cannot change xdir to chase Keen while this is non-zero)\r
-temp2 = old x position\r
-temp3 = old y position\r
-temp4 = pointer to object being eaten\r
- (BUG: pointer may be invalid after loading a saved game!)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_dopefish1 = {DOPEFISHSWIML1SPR, DOPEFISHSWIMR1SPR, stepthink, false, false, 20, 0, 0, T_Dope, C_Dope, R_Fish, &s_dopefish2};\r
-statetype s_dopefish2 = {DOPEFISHSWIML2SPR, DOPEFISHSWIMR2SPR, stepthink, false, false, 20, 0, 0, T_Dope, C_Dope, R_Fish, &s_dopefish1};\r
-statetype s_dopeattack = {DOPEFISHHUNGRYLSPR, DOPEFISHHUNGRYRSPR, think, false, false, 0, 0, 0, T_DopeHunt, NULL, R_Draw, NULL};\r
-statetype s_dopeeat = {DOPEFISHSWIML1SPR, DOPEFISHSWIMR1SPR, step, false, false, 60, 0, 0, NULL, NULL, R_Draw, &s_dopeburp1};\r
-statetype s_dopeburp1 = {DOPEFISHBURP1SPR, DOPEFISHBURP1SPR, step, false, false, 60, 0, 0, T_Burp, NULL, R_Draw, &s_dopeburp2};\r
-statetype s_dopeburp2 = {DOPEFISHBURP2SPR, DOPEFISHBURP2SPR, step, false, false, 60, 0, 0, NULL, NULL, R_Draw, &s_dopereturn};\r
-statetype s_dopereturn = {DOPEFISHSWIML1SPR, DOPEFISHSWIMR1SPR, think, false, false, 0, 0, 0, T_DopeReturn, NULL, R_Draw, &s_dopefish1};\r
-\r
-statetype s_dopefood = {SCHOOLFISHL1SPR, SCHOOLFISHR1SPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, NULL};\r
-statetype s_keendopefood = {SCUBAKEENDEAD1SPR, SCUBAKEENDEAD1SPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, &s_keendieslow};\r
-statetype s_keendieslow = {-1, -1, step, false, false, 180, 0, 0, T_EatenKeen, NULL, R_Draw, &s_keendieslow};\r
-\r
-statetype s_bubble1 = {BIGBUBBLE1SPR, BIGBUBBLE1SPR, think, false, false, 20, 0, 20, T_Bubble, NULL, R_Draw, &s_bubble2};\r
-statetype s_bubble2 = {BIGBUBBLE2SPR, BIGBUBBLE2SPR, think, false, false, 20, 0, 20, T_Bubble, NULL, R_Draw, &s_bubble3};\r
-statetype s_bubble3 = {BIGBUBBLE3SPR, BIGBUBBLE3SPR, think, false, false, 20, 0, 20, T_Bubble, NULL, R_Draw, &s_bubble4};\r
-statetype s_bubble4 = {BIGBUBBLE4SPR, BIGBUBBLE4SPR, think, false, false, 20, 0, 20, T_Bubble, NULL, R_Draw, &s_bubble1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnDopefish\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnDopefish(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = dopefishobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->needtoclip = cl_fullclip;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -3*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_dopefish1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_EatenKeen\r
-=\r
-===========================\r
-*/\r
-\r
-void T_EatenKeen(objtype *ob)\r
-{\r
- ob++; // shut up compiler\r
- playstate = ex_died;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Dope\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Dope(objtype *ob)\r
-{\r
- if (ob->temp1 == 0)\r
- {\r
- if (ob->x < player->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- }\r
- AccelerateXv(ob, ob->xdir, 10);\r
-\r
- if (ob->y < player->y)\r
- {\r
- AccelerateY(ob, 1, 10);\r
- }\r
- else\r
- {\r
- AccelerateY(ob, -1, 10);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DopeHunt\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DopeHunt(objtype *ob)\r
-{\r
- objtype *target;\r
- Sint16 xdist, ydist;\r
-\r
- target = (objtype *)(ob->temp4);\r
- ydist = target->y - TILEGLOBAL - ob->y;\r
- if (ob->xdir == 1)\r
- {\r
- xdist = target->right + 2*PIXGLOBAL - ob->right;\r
- }\r
- else\r
- {\r
- xdist = target->left - 2*PIXGLOBAL - ob->left;\r
- }\r
-\r
- if (xdist < 0)\r
- {\r
- xtry = tics * -32;\r
- if (xtry < xdist)\r
- xtry = xdist;\r
- }\r
- else\r
- {\r
- xtry = tics * 32;\r
- if (xtry > xdist)\r
- xtry = xdist;\r
- }\r
-\r
- if (ydist < 0)\r
- {\r
- ytry = tics * -32;\r
- if (ytry < ydist)\r
- ytry = ydist;\r
- }\r
- else\r
- {\r
- ytry = tics * 32;\r
- if (ytry > ydist)\r
- ytry = ydist;\r
- }\r
-\r
- if (xtry == xdist && ytry == ydist)\r
- {\r
- if (target == player)\r
- {\r
- ChangeState(target, &s_keendieslow);\r
- }\r
- else if (target->state->nextstate)\r
- {\r
- ChangeState(target, target->state->nextstate);\r
- }\r
- else\r
- {\r
- RemoveObj(target);\r
- }\r
- ob->state = &s_dopeeat;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DopeReturn\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DopeReturn(objtype *ob)\r
-{\r
- Sint16 xdist, ydist;\r
-\r
- ydist = ob->temp3 - ob->y;\r
- xdist = ob->temp2 - ob->x;\r
-\r
- if (xdist < 0)\r
- {\r
- xtry = tics * -32;\r
- if (xtry < xdist)\r
- xtry = xdist;\r
- }\r
- else\r
- {\r
- xtry = tics * 32;\r
- if (xtry > xdist)\r
- xtry = xdist;\r
- }\r
-\r
- if (ydist < 0)\r
- {\r
- ytry = tics * -32;\r
- if (ytry < ydist)\r
- ytry = ydist;\r
- }\r
- else\r
- {\r
- ytry = tics * 32;\r
- if (ytry > ydist)\r
- ytry = ydist;\r
- }\r
-\r
- if (xtry == xdist && ytry == ydist)\r
- {\r
- ob->state = ob->state->nextstate;\r
- ob->needtoclip = cl_fullclip;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Burp\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Burp(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->x = ob->x + 56*PIXGLOBAL;\r
- new->y = ob->y + 32*PIXGLOBAL;\r
- new->obclass = inertobj;\r
- new->priority = 3;\r
- new->active = ac_removable;\r
- new->needtoclip = cl_noclip;\r
- new->yspeed = -20;\r
- new->xspeed = 4;\r
- NewState(new, &s_bubble1);\r
- SD_PlaySound(SND_BURP);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Bubble\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Bubble(objtype *ob)\r
-{\r
- T_Velocity(ob);\r
- if (US_RndT() < tics * 16)\r
- ob->xspeed = -ob->xspeed;\r
-\r
- if (ob->y < 3*TILEGLOBAL)\r
- RemoveObj(ob);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Dope\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Dope(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == schoolfishobj)\r
- {\r
- ChangeState(hit, &s_dopefood);\r
- }\r
- else if (hit->obclass == keenobj && !godmode)\r
- {\r
- hit->obclass = inertobj; //prevents other objects from killing Keen before he is fully swallowed\r
- hit->needtoclip = cl_noclip;\r
- SD_PlaySound(SND_KEENDEAD);\r
- ChangeState(hit, &s_keendopefood);\r
- }\r
- else\r
- {\r
- return;\r
- }\r
-\r
- ob->temp2 = ob->x;\r
- ob->temp3 = ob->y;\r
- ob->temp4 = (Sint16)hit;\r
- if (hit->midx < ob->midx)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
- ChangeState(ob, &s_dopeattack);\r
- ob->needtoclip = cl_noclip;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Fish\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Fish(objtype *ob) //for Dopefish and Schoolfish\r
-{\r
- if ((ob->hitsouth || ob->hitnorth) && ob->temp1 == 0)\r
- ob->temp1++;\r
-\r
- if (ob->hiteast || ob->hitwest)\r
- {\r
- ob->xspeed = 0;\r
- ob->xdir = -ob->xdir;\r
- ob->temp1 = 1;\r
- }\r
-\r
- if (!ob->hitsouth && !ob->hitnorth)\r
- ob->temp1 = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SCHOOLFISH\r
-\r
-temp1 = blocked (cannot change xdir to chase Keen while this is non-zero)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_schoolfish1 = {SCHOOLFISHL1SPR, SCHOOLFISHR1SPR, stepthink, false, false, 20, 0, 0, T_SchoolFish, NULL, R_Fish, &s_schoolfish2};\r
-statetype s_schoolfish2 = {SCHOOLFISHL2SPR, SCHOOLFISHR2SPR, stepthink, false, false, 20, 0, 0, T_SchoolFish, NULL, R_Fish, &s_schoolfish1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSchoolfish\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSchoolfish(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = schoolfishobj;\r
- new->active = ac_yes;\r
- new->needtoclip = cl_fullclip;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- new->ydir = new->xdir = 1;\r
- NewState(new, &s_schoolfish1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SchoolFish\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SchoolFish(objtype *ob)\r
-{\r
- if (ob->temp1 == 0)\r
- {\r
- if (ob->x < player->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- }\r
- AccelerateXv(ob, ob->xdir, 10);\r
-\r
- if (ob->y < player->y)\r
- {\r
- AccelerateY(ob, 1, 10);\r
- }\r
- else\r
- {\r
- AccelerateY(ob, -1, 10);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- PIXIE (a.k.a. SPRITE)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_pixie = {SPRITEFLOATSPR, SPRITEFLOATSPR, think, false, false, 10, 0, 0, T_Pixie, C_Lethal, R_Draw, &s_pixie};\r
-statetype s_pixielook = {SPRITEAIMLSPR, SPRITEAIMRSPR, step, false, false, 40, 0, 0, T_PixieCheck, C_Lethal, R_Draw, &s_pixie};\r
-statetype s_pixieshoot = {SPRITESHOOTLSPR, SPRITESHOOTRSPR, step, false, false, 40, 0, 0, T_PixieShoot, C_Lethal, R_Draw, &s_pixieshoot2};\r
-statetype s_pixieshoot2 = {SPRITESHOOTLSPR, SPRITESHOOTRSPR, step, false, false, 30, 0, 0, NULL, C_Lethal, R_Draw, &s_pixie};\r
-statetype s_pixiefire1 = {SPRITESHOT1SPR, SPRITESHOT1SPR, slide, false, false, 10, 64, 0, NULL, C_Lethal, R_Mshot, &s_pixiefire2};\r
-statetype s_pixiefire2 = {SPRITESHOT2SPR, SPRITESHOT2SPR, slide, false, false, 10, 64, 0, NULL, C_Lethal, R_Mshot, &s_pixiefire3};\r
-statetype s_pixiefire3 = {SPRITESHOT3SPR, SPRITESHOT3SPR, slide, false, false, 10, 64, 0, NULL, C_Lethal, R_Mshot, &s_pixiefire4};\r
-statetype s_pixiefire4 = {SPRITESHOT4SPR, SPRITESHOT4SPR, slide, false, false, 10, 64, 0, NULL, C_Lethal, R_Mshot, &s_pixiefire1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnPixie\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnPixie(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = pixieobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->needtoclip = cl_noclip;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = new->temp1 = CONVERT_TILE_TO_GLOBAL(y);\r
- new->ydir = new->xdir = 1;\r
- NewState(new, &s_pixie);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Pixie\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Pixie(objtype *ob)\r
-{\r
- AccelerateY(ob, ob->ydir, 8);\r
- if ((Sint16)(ob->temp1 - ob->y) > 2*PIXGLOBAL)\r
- {\r
- ob->ydir = 1;\r
- }\r
- if ((Sint16)(ob->y - ob->temp1) > 2*PIXGLOBAL)\r
- {\r
- ob->ydir = -1;\r
- }\r
-\r
- if (player->top < ob->bottom && player->bottom > ob->top)\r
- {\r
- if (player->x < ob->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
- ob->state = &s_pixielook;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PixieCheck\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PixieCheck(objtype *ob)\r
-{\r
- if (player->top < ob->bottom && player->bottom > ob->top)\r
- ob->state = &s_pixieshoot;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PixieShoot\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PixieShoot(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y + 8*PIXGLOBAL;\r
- new->priority = 0;\r
- new->obclass = mshotobj;\r
- new->active = ac_removable;\r
- SD_PlaySound(SND_KEENFIRE); //BUG?\r
- new->xdir = ob->xdir;\r
- NewState(new, &s_pixiefire1);\r
- SD_PlaySound(SND_SPRITEFIRE);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Mshot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Mshot(objtype *ob)\r
-{\r
- if (ob->hitnorth || ob->hiteast || ob->hitsouth || ob->hitwest)\r
- {\r
- RemoveObj(ob);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- MINE\r
-\r
-=============================================================================\r
-*/\r
-statetype s_mine = {MINESPR, MINESPR, think, false, false, 10, 0, 0, T_Platform, C_Mine, R_Draw, &s_mine};\r
-statetype s_mineboom1 = {MINEEXPLODE1SPR, MINEEXPLODE1SPR, step, false, false, 30, 0, 0, NULL, NULL, R_Draw, &s_mineboom2};\r
-statetype s_mineboom2 = {MINEEXPLODE2SPR, MINEEXPLODE2SPR, step, false, false, 30, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnMine\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnMine(Sint16 x, Sint16 y, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = mineobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- switch (dir)\r
- {\r
- case 0:\r
- new->xdir = 0;\r
- new->ydir = -1;\r
- break;\r
- case 1:\r
- new->xdir = 1;\r
- new->ydir = 0;\r
- break;\r
- case 2:\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- break;\r
- case 3:\r
- new->xdir = -1;\r
- new->ydir = 0;\r
- break;\r
- }\r
- NewState(new, &s_mine);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Mine\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Mine(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- ChangeState(ob, &s_mineboom1);\r
- SD_PlaySound(SND_MINEEXPLODE);\r
- KillKeen();\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- PRINCESS LINDSEY\r
-\r
-temp1 = initial y position\r
-\r
-=============================================================================\r
-*/\r
-statetype s_lindsey1 = {LINDSEY1SPR, LINDSEY1SPR, stepthink, false, false, 20, 0, 0, T_Lindsey, NULL, R_Draw, &s_lindsey2};\r
-statetype s_lindsey2 = {LINDSEY2SPR, LINDSEY2SPR, stepthink, false, false, 20, 0, 0, T_Lindsey, NULL, R_Draw, &s_lindsey3};\r
-statetype s_lindsey3 = {LINDSEY3SPR, LINDSEY3SPR, stepthink, false, false, 20, 0, 0, T_Lindsey, NULL, R_Draw, &s_lindsey4};\r
-statetype s_lindsey4 = {LINDSEY4SPR, LINDSEY4SPR, stepthink, false, false, 20, 0, 0, T_Lindsey, NULL, R_Draw, &s_lindsey1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnLindsey\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnLindsey(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = lindseyobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = new->temp1 = CONVERT_TILE_TO_GLOBAL(y) - TILEGLOBAL;\r
- new->ydir = 1;\r
- NewState(new, &s_lindsey1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Lindsey\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Lindsey(objtype *ob)\r
-{\r
- AccelerateY(ob, ob->ydir, 8);\r
- if (ob->temp1 - (Sint16)ob->y > 2*PIXGLOBAL)\r
- {\r
- ob->ydir = 1;\r
- }\r
- if ((Sint16)ob->y - ob->temp1 > 2*PIXGLOBAL)\r
- {\r
- ob->ydir = -1;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- DARTS\r
-\r
-temp1 = direction\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_dartthrower = {0, 0, step, false, false, 150, 0, 0, T_DartShoot, NULL, NULL, &s_dartthrower};\r
-statetype s_dart1 = {DARTL1SPR, DARTR1SPR, slide, false, false, 6, 64, 0, NULL, C_Lethal, R_Mshot, &s_dart2};\r
-statetype s_dart2 = {DARTL2SPR, DARTR2SPR, slide, false, false, 6, 64, 0, NULL, C_Lethal, R_Mshot, &s_dart1};\r
-statetype s_dartup1 = {DARTU1SPR, DARTU1SPR, slide, false, false, 6, 0, 64, NULL, C_Lethal, R_Mshot, &s_dartup2};\r
-statetype s_dartup2 = {DARTU2SPR, DARTU2SPR, slide, false, false, 6, 0, 64, NULL, C_Lethal, R_Mshot, &s_dartup1};\r
-statetype s_dartdown1 = {DARTD1SPR, DARTD1SPR, slide, false, false, 6, 0, 64, NULL, C_Lethal, R_Mshot, &s_dartdown2};\r
-statetype s_dartdown2 = {DARTD2SPR, DARTD2SPR, slide, false, false, 6, 0, 64, NULL, C_Lethal, R_Mshot, &s_dartdown1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnDartShooter\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnDartShooter(Sint16 x, Sint16 y, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = inertobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->needtoclip = cl_noclip;\r
- new->y = CONVERT_TILE_TO_GLOBAL(y);\r
- new->temp1 = dir;\r
- switch (dir)\r
- {\r
- case 0:\r
- new->y -= 3*PIXGLOBAL;\r
- new->x += 9*PIXGLOBAL;\r
- new->shapenum = DARTU1SPR;\r
- break;\r
- case 1:\r
- new->x += 8*PIXGLOBAL;\r
- new->y += 5*PIXGLOBAL;\r
- new->shapenum = DARTR1SPR;\r
- break;\r
- case 2:\r
- new->x += 9*PIXGLOBAL;\r
- new->shapenum = DARTD1SPR;\r
- break;\r
- case 3:\r
- new->y += 7*PIXGLOBAL;\r
- new->x -= 3*PIXGLOBAL;\r
- new->shapenum = DARTL1SPR;\r
- break;\r
- }\r
- NewState(new, &s_dartthrower);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DartShoot\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DartShoot(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->obclass = mshotobj;\r
- new->active = ac_removable;\r
- switch (ob->temp1)\r
- {\r
- case 0:\r
- new->xdir = 0;\r
- new->ydir = -1;\r
- NewState(new, &s_dartup1);\r
- break;\r
- case 1:\r
- new->xdir = 1;\r
- new->ydir = 0;\r
- NewState(new, &s_dart1);\r
- break;\r
- case 2:\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- NewState(new, &s_dartdown1);\r
- break;\r
- case 3:\r
- new->xdir = -1;\r
- new->ydir = 0;\r
- NewState(new, &s_dart1);\r
- break;\r
- }\r
- SD_PlaySound(SND_SHOOTDART);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_DartThrower\r
-=\r
-===========================\r
-*/\r
-\r
-void R_DartThrower(objtype *ob) //never used\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SCUBA GEAR\r
-\r
-=============================================================================\r
-*/\r
-statetype s_scuba = {SCUBASPR, SCUBASPR, step, false, false, 30000, 0, 0, NULL, C_Scuba, R_Draw, &s_scuba};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnScuba\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnScuba(Sint16 x, Sint16 y)\r
-{\r
- GetNewObj(false);\r
- new->obclass = scubaobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(x);\r
- new->y = CONVERT_TILE_TO_GLOBAL(y) + -TILEGLOBAL;\r
- NewState(new, &s_scuba);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Scuba\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Scuba(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj && hit->hitnorth)\r
- {\r
- gamestate.wetsuit = true;\r
- SD_PlaySound(SND_MAKEFOOT);\r
- GotScuba();\r
- RF_ForceRefresh();\r
- playstate = ex_completed;\r
- ob++; // shut up compiler\r
- }\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __K4_DEF__\r
-#define __K4_DEF__\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-#define MINMEMORY 280000l\r
-#else\r
-#define MINMEMORY 310000l\r
-#endif\r
-\r
-#define STARPALETTE {0, 1, 2, 3, 4, 16, 6, 7, 31, 31, 31, 31, 31, 31, 31, 31, 0}\r
-#define INTROPALETTE {0, 24, 24, 7, 1, 1, 1, 1, 17, 17, 17, 17, 19, 19, 19, 19, 0}\r
-#define SHRINKPALETTE {0, 24, 24, 7, 1, 1, 1, 1, 17, 17, 17, 17, 19, 19, 19, 24, 0}\r
-\r
-#define HIGHSCORE_LEFT 24\r
-#define HIGHSCORE_TOP 51\r
-#define HIGHSCORE_RIGHT 296\r
-#define HIGHSCORE_MAP 19\r
-\r
-#define STATUS_PRESSKEY_X 160\r
-\r
-#define WORLDMAPNAME "Shadowlands"\r
-#define DROPSNAME "DROPS"\r
-\r
-#define STARWARSMUSIC 12\r
-#define ENDINGMUSIC 7\r
-\r
-// levels in this range can NOT be re-entered (BWB level should be > MAXDONELEVEL)\r
-#define MINDONELEVEL 1\r
-#define MAXDONELEVEL 17\r
-\r
-#define INACTIVATEDIST 4\r
-\r
-/*\r
-=============================================================================\r
-\r
- K4_SPEC DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern char far swtext[];\r
-extern char far *levelnames[GAMELEVELS];\r
-extern char far *levelenter[GAMELEVELS];\r
-\r
-void ScanInfoPlane(void);\r
-void PrincessLindsey(void);\r
-void RescueJanitor(void);\r
-void CantSwim(void);\r
-void GotScuba(void);\r
-void RescuedMember(void);\r
-\r
-extern statetype s_keenswimslow1;\r
-extern statetype s_keenswimslow2;\r
-extern statetype s_keenswim1;\r
-extern statetype s_keenswim2;\r
-extern statetype s_kbubble1;\r
-extern statetype s_kbubble2;\r
-extern statetype s_kbubble3;\r
-extern statetype s_kbubble4;\r
-void SpawnSwimKeen(Sint16 x, Sint16 y);\r
-void SpawnKbubble(objtype *ob);\r
-void T_KeenSwimSlow(objtype *ob);\r
-void T_KeenSwim(objtype *ob);\r
-void C_KeenSwim(objtype *ob, objtype *hit);\r
-void R_KeenSwim(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K4_ACT1 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_miragia0;\r
-extern statetype s_miragia1;\r
-extern statetype s_miragia2;\r
-extern statetype s_miragia3;\r
-extern statetype s_miragia4;\r
-extern statetype s_miragia5;\r
-extern statetype s_miragia6;\r
-extern statetype s_miragia7;\r
-void SpawnMiragia(Sint16 x, Sint16 y);\r
-void T_Miragia0(objtype *ob);\r
-void T_Miragia1(objtype *ob);\r
-void T_Miragia2(objtype *ob);\r
-void T_Miragia3(objtype *ob);\r
-void T_Miragia4(objtype *ob);\r
-void T_Miragia5(objtype *ob);\r
-void T_Miragia6(objtype *ob);\r
-void T_Miragia7(objtype *ob);\r
-\r
-extern statetype s_bonus1;\r
-extern statetype s_bonus2;\r
-extern statetype s_bonusrise;\r
-extern statetype s_splash1;\r
-extern statetype s_splash2;\r
-extern statetype s_splash3;\r
-extern Uint16 bonusshape[];\r
-void SpawnBonus(Sint16 x, Sint16 y, Sint16 type);\r
-void SpawnSplash(Sint16 x, Sint16 y);\r
-void T_Bonus(objtype *ob);\r
-\r
-extern statetype s_councilwalk1;\r
-extern statetype s_councilwalk2;\r
-extern statetype s_councilstand;\r
-void SpawnCouncil(Sint16 x, Sint16 y);\r
-void T_Council(objtype *ob);\r
-\r
-extern statetype s_slugwalk1;\r
-extern statetype s_slugwalk2;\r
-extern statetype s_slugpiss1;\r
-extern statetype s_slugstun;\r
-extern statetype s_slugstunalt;\r
-extern statetype s_slugslime;\r
-extern statetype s_slugslime2;\r
-void SpawnSlug(Sint16 x, Sint16 y);\r
-void T_Slug(objtype *ob);\r
-void T_SlugPiss(objtype *ob);\r
-void C_Slug(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_mushroom1;\r
-extern statetype s_mushroom2;\r
-void SpawnMadMushroom(Sint16 x, Sint16 y);\r
-void T_Mushroom(objtype *ob);\r
-void C_Mushroom(objtype *ob, objtype *hit);\r
-void R_Mushroom(objtype *ob);\r
-\r
-extern statetype s_egg;\r
-extern statetype s_eggbroke;\r
-extern statetype s_eggchip1;\r
-extern statetype s_eggchip2;\r
-extern statetype s_eggchip3;\r
-extern statetype s_eggbirdpause;\r
-extern statetype s_eggbirdwalk1;\r
-extern statetype s_eggbirdwalk2;\r
-extern statetype s_eggbirdwalk3;\r
-extern statetype s_eggbirdwalk4;\r
-extern statetype s_eggbirdfly1;\r
-extern statetype s_eggbirdfly2;\r
-extern statetype s_eggbirdfly3;\r
-extern statetype s_eggbirdfly4;\r
-extern statetype s_eggbirddrop;\r
-extern statetype s_eggbirdstun;\r
-extern statetype s_eggbirdstun2;\r
-extern statetype s_eggbirdstun3;\r
-extern statetype s_eggbirdstun4;\r
-extern statetype s_eggbirdstun5;\r
-void SpawnEggbird(Sint16 x, Sint16 y);\r
-void T_EggUnstun(objtype *ob);\r
-void SpawnEggbirdOut(Sint16 x, Sint16 y);\r
-void C_Egg(objtype *ob, objtype *hit);\r
-void T_Eggbird(objtype *ob);\r
-void T_EggbirdFly(objtype *ob);\r
-void C_Eggbird(objtype *ob, objtype *hit);\r
-void C_EggbirdStun(objtype *ob, objtype *hit);\r
-void R_Eggbird(objtype *ob);\r
-void R_EggbirdDrop(objtype *ob);\r
-void R_Chip(objtype *ob);\r
-void R_Eggbirdfly(objtype *ob);\r
-\r
-extern statetype s_arach1;\r
-extern statetype s_arach2;\r
-extern statetype s_arach3;\r
-extern statetype s_arach4;\r
-extern statetype s_arachstun;\r
-extern statetype s_arachstun2;\r
-extern statetype s_arachstun3;\r
-extern statetype s_arachstun4;\r
-extern statetype s_arachstun5;\r
-void SpawnArachnut(Sint16 x, Sint16 y);\r
-void T_Arach(objtype *ob);\r
-void C_Arach(objtype *ob, objtype *hit);\r
-void C_ArachStun(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_pestfly1;\r
-extern statetype s_pestfly2;\r
-extern statetype s_squashedpest;\r
-extern statetype s_pestrest1;\r
-extern statetype s_pestrest2;\r
-extern statetype s_pestrest3;\r
-extern statetype s_pestrest4;\r
-extern statetype s_pestrest5;\r
-extern statetype s_pestrest6;\r
-extern statetype s_pestrest7;\r
-extern statetype s_pestrest8;\r
-extern statetype s_pestrest9;\r
-extern statetype s_pestrest10;\r
-extern statetype s_pestrest11;\r
-extern statetype s_pestrest12;\r
-extern statetype s_pestrest13;\r
-extern statetype s_pestrest14;\r
-extern statetype s_pestrest15;\r
-extern statetype s_pestrest16;\r
-extern statetype s_pestrest17;\r
-void SpawnSkypest(Sint16 x, Sint16 y);\r
-void T_PestFly(objtype *ob);\r
-void C_PestFly(objtype *ob, objtype *hit);\r
-void C_Squashable(objtype *ob, objtype *hit);\r
-void T_PestRest(objtype *ob);\r
-void R_Pest(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K4_ACT2 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_worm;\r
-extern statetype s_wormpeek1;\r
-extern statetype s_wormpeek2;\r
-extern statetype s_wormpeek3;\r
-extern statetype s_wormpeek4;\r
-extern statetype s_wormpeek5;\r
-extern statetype s_wormpeek6;\r
-extern statetype s_wormpeek7;\r
-extern statetype s_wormpeek8;\r
-extern statetype s_wormbite1;\r
-extern statetype s_wormbite2;\r
-extern statetype s_wormbite3;\r
-extern statetype s_wormbite4;\r
-extern statetype s_wormbite5;\r
-extern statetype s_wormstun;\r
-void SpawnWormMouth(Sint16 x, Sint16 y);\r
-void T_WormLookRight(objtype *ob);\r
-void T_WormLook(objtype *ob);\r
-void T_WormLookLeft(objtype *ob);\r
-void T_Worm(objtype *ob);\r
-void C_Worm(objtype *ob, objtype *hit);\r
-void C_WormKill(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_cloudsleep;\r
-extern statetype s_cloudwake;\r
-extern statetype s_cloud;\r
-extern statetype s_cloudalign;\r
-extern statetype s_cloudcharge;\r
-extern statetype s_cloudattack1;\r
-extern statetype s_cloudattack2;\r
-extern statetype s_cloudattack3;\r
-extern statetype s_cloudattack4;\r
-extern statetype s_cloudattack5;\r
-extern statetype s_cloudattack6;\r
-extern statetype s_cloudattack7;\r
-extern statetype s_cloudattack8;\r
-extern statetype s_cloudattack9;\r
-extern statetype s_bolt1;\r
-extern statetype s_bolt2;\r
-extern statetype s_bolt3;\r
-extern statetype s_bolt4;\r
-extern statetype s_bolt5;\r
-extern statetype s_bolt6;\r
-void SpawnCloudster(Sint16 x, Sint16 y);\r
-void T_Cloud(objtype *ob);\r
-void T_CloudAlign(objtype *ob);\r
-void R_Cloud(objtype *ob);\r
-void T_CloudShoot(objtype *ob);\r
-void C_CloudSleep(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_berkefloat1;\r
-extern statetype s_berkefloat2;\r
-extern statetype s_berkefloat3;\r
-extern statetype s_berkefloat4;\r
-extern statetype s_berkethrow1;\r
-extern statetype s_berkethrow2;\r
-extern statetype s_berkethrow3;\r
-extern statetype s_berkethrow4;\r
-extern statetype s_berkethrow5;\r
-extern statetype s_berkethrow6;\r
-extern statetype s_berkethrow7;\r
-extern statetype s_berkethrow8;\r
-extern statetype s_berkethrow9;\r
-extern statetype s_berkethrow10;\r
-extern statetype s_berkethrow11;\r
-extern statetype s_berkethrow12;\r
-extern statetype s_fire1;\r
-extern statetype s_fire2;\r
-extern statetype s_fireland1;\r
-extern statetype s_fireland2;\r
-extern statetype s_fireland3;\r
-extern statetype s_fireland4;\r
-extern statetype s_fireland5;\r
-extern statetype s_fireland6;\r
-extern statetype s_fireland7;\r
-extern statetype s_fireland8;\r
-extern statetype s_fireland9;\r
-void SpawnBerkeloid(Sint16 x, Sint16 y);\r
-void BerkeThink(objtype *ob);\r
-void BerkeThrowThink(objtype *ob);\r
-void BerkeThrowDone(objtype *ob);\r
-void C_Berke(objtype *ob, objtype *hit);\r
-void FireReact(objtype *ob);\r
-void BerkeDrawReact(objtype *ob);\r
-void BerkeWalkReact(objtype *ob);\r
-\r
-extern statetype s_footsmoke1;\r
-extern statetype s_footsmoke2;\r
-extern statetype s_footsmoke3;\r
-extern statetype s_footsmoke4;\r
-extern statetype s_inch1;\r
-extern statetype s_inch2;\r
-extern statetype s_footchange; //never used!\r
-extern statetype s_footwait;\r
-void SpawnInchworm(Sint16 x, Sint16 y);\r
-void SpawnFoot(Sint16 x, Sint16 y);\r
-void InchThink(objtype *ob);\r
-void InchContact(objtype *ob, objtype *hit);\r
-void FootContact(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_bounderup1;\r
-extern statetype s_bounderup2;\r
-extern statetype s_bounderside1;\r
-extern statetype s_bounderside2;\r
-extern statetype s_bounderstun;\r
-extern statetype s_bounderstun2;\r
-void SpawnBounder(Sint16 x, Sint16 y);\r
-void C_Bounder(objtype *ob, objtype *hit);\r
-void R_Bounder(objtype *ob);\r
-\r
-extern statetype s_lick1;\r
-extern statetype s_lick2;\r
-extern statetype s_lick3;\r
-extern statetype s_lick4;\r
-extern statetype s_licklick1;\r
-extern statetype s_licklick2;\r
-extern statetype s_licklick3;\r
-extern statetype s_licklick4;\r
-extern statetype s_licklick5;\r
-extern statetype s_licklick6;\r
-extern statetype s_licklick7;\r
-extern statetype s_licklick8;\r
-extern statetype s_lickstun;\r
-extern statetype s_lickstun2;\r
-void SpawnLick(Sint16 x, Sint16 y);\r
-void LickJumpThink(objtype *ob);\r
-void LickContact(objtype *ob, objtype *hit);\r
-void LickKillContact(objtype *ob, objtype *hit);\r
-void LickAirReact(objtype *ob);\r
-\r
-extern statetype s_platform;\r
-void SpawnPlatform(Sint16 x, Sint16 y, Sint16 dir);\r
-void T_Platform(objtype *ob);\r
-void R_Platform(objtype *ob);\r
-\r
-extern statetype s_dropplatsit;\r
-extern statetype s_dropplatfall;\r
-extern statetype s_dropplatrise;\r
-void SpawnDropPlat(Sint16 x, Sint16 y);\r
-void T_DropPlatSit(objtype *ob);\r
-void T_DropPlatFall(objtype *ob);\r
-void T_DropPlatRise(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K4_ACT3 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_eaterstand1;\r
-extern statetype s_eaterstand2;\r
-extern statetype s_eatertport1;\r
-extern statetype s_eatertport2;\r
-extern statetype s_eatertport3;\r
-extern statetype s_eatertport4;\r
-extern statetype s_eatertport5;\r
-extern statetype s_eatertport6;\r
-extern statetype s_eatertport7;\r
-extern statetype s_eatertport8;\r
-extern statetype s_eaterjump1;\r
-extern statetype s_eaterjump2;\r
-extern statetype s_eaterjump3;\r
-extern statetype s_eaterjump4;\r
-extern statetype s_eaterstun;\r
-extern statetype s_eaterstun2;\r
-extern statetype s_eatenbonus1;\r
-extern statetype s_eatenbonus2;\r
-extern statetype s_eatenbonus3;\r
-extern statetype s_eatenbonus4;\r
-void SpawnEater(Sint16 x, Sint16 y);\r
-void T_EaterJump(objtype *ob);\r
-void T_EaterTeleport(objtype *ob);\r
-void C_Eater(objtype *ob, objtype *hit);\r
-void EaterInTile(objtype *ob);\r
-void R_EaterAir(objtype *ob);\r
-\r
-extern statetype s_mimrock;\r
-extern statetype s_mimsneak1;\r
-extern statetype s_mimsneak2;\r
-extern statetype s_mimsneak3;\r
-extern statetype s_mimsneak4;\r
-extern statetype s_mimsneak5;\r
-extern statetype s_mimsneak6;\r
-extern statetype s_mimbonk1;\r
-extern statetype s_mimbonk2;\r
-extern statetype s_mimbonk3;\r
-extern statetype s_mimbounce;\r
-extern statetype s_mimstun;\r
-extern statetype s_mimstun2;\r
-void SpawnMimrock(Sint16 x, Sint16 y);\r
-void T_MimrockWait(objtype *ob);\r
-void T_MimrockSneak(objtype *ob);\r
-void C_Mimrock(objtype *ob, objtype *hit);\r
-void C_MimLethal(objtype *ob, objtype *hit);\r
-void R_MimAir(objtype *ob);\r
-void R_MimBounce(objtype *ob);\r
-\r
-extern statetype s_dopefish1;\r
-extern statetype s_dopefish2;\r
-extern statetype s_dopeattack;\r
-extern statetype s_dopeeat;\r
-extern statetype s_dopeburp1;\r
-extern statetype s_dopeburp2;\r
-extern statetype s_dopereturn;\r
-extern statetype s_dopefood;\r
-extern statetype s_keendopefood;\r
-extern statetype s_keendieslow;\r
-extern statetype s_bubble1;\r
-extern statetype s_bubble2;\r
-extern statetype s_bubble3;\r
-extern statetype s_bubble4;\r
-void SpawnDopefish(Sint16 x, Sint16 y);\r
-void T_EatenKeen(objtype *ob);\r
-void T_Dope(objtype *ob);\r
-void T_DopeHunt(objtype *ob);\r
-void T_DopeReturn(objtype *ob);\r
-void T_Burp(objtype *ob);\r
-void T_Bubble(objtype *ob);\r
-void C_Dope(objtype *ob, objtype *hit);\r
-void R_Fish(objtype *ob);\r
-\r
-extern statetype s_schoolfish1;\r
-extern statetype s_schoolfish2;\r
-void SpawnSchoolfish(Sint16 x, Sint16 y);\r
-void T_SchoolFish(objtype *ob);\r
-\r
-extern statetype s_pixie;\r
-extern statetype s_pixielook;\r
-extern statetype s_pixieshoot;\r
-extern statetype s_pixieshoot2;\r
-extern statetype s_pixiefire1;\r
-extern statetype s_pixiefire2;\r
-extern statetype s_pixiefire3;\r
-extern statetype s_pixiefire4;\r
-void SpawnPixie(Sint16 x, Sint16 y);\r
-void T_Pixie(objtype *ob);\r
-void T_PixieCheck(objtype *ob);\r
-void T_PixieShoot(objtype *ob);\r
-void R_Mshot(objtype *ob);\r
-\r
-extern statetype s_mine;\r
-extern statetype s_mineboom1;\r
-extern statetype s_mineboom2;\r
-void SpawnMine(Sint16 x, Sint16 y, Sint16 dir);\r
-void C_Mine(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_lindsey1;\r
-extern statetype s_lindsey2;\r
-extern statetype s_lindsey3;\r
-extern statetype s_lindsey4;\r
-void SpawnLindsey(Sint16 x, Sint16 y);\r
-void T_Lindsey(objtype *ob);\r
-\r
-extern statetype s_dartthrower;\r
-extern statetype s_dart1;\r
-extern statetype s_dart2;\r
-extern statetype s_dartup1;\r
-extern statetype s_dartup2;\r
-extern statetype s_dartdown1;\r
-extern statetype s_dartdown2;\r
-void SpawnDartShooter(Sint16 x, Sint16 y, Sint16 dir);\r
-void T_DartShoot(objtype *ob);\r
-void R_DartThrower(objtype *ob);\r
-\r
-extern statetype s_scuba;\r
-void SpawnScuba(Sint16 x, Sint16 y);\r
-void C_Scuba(objtype *ob, objtype *hit);\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K4_SPEC.C\r
-=========\r
-\r
-Contains (in this order):\r
-\r
-- lump definition\r
-- "Star Wars" crawl text\r
-- level names & messages\r
-- ScanInfoPlane() - for spawning the level objects and marking required sprites\r
-- messages for Lindsey, Janitor, Oracle Members and more\r
-\r
-- actor states & implementation for swimming Keen\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-enum {\r
- CONTROLS_LUMP, // 0\r
- KEEN_LUMP, // 1\r
- SUGAR1_LUMP, // 2\r
- SUGAR2_LUMP, // 3\r
- SUGAR3_LUMP, // 4\r
- SUGAR4_LUMP, // 5\r
- SUGAR5_LUMP, // 6\r
- SUGAR6_LUMP, // 7\r
- ONEUP_LUMP, // 8\r
- AMMO_LUMP, // 9\r
- WOLRDKEEN_LUMP, // 10\r
- SLUG_LUMP, // 11\r
- MADMUSHROOM_LUMP, // 12\r
- UNUSED1_LUMP, // 13\r
- LINDSEY_LUMP, // 14\r
- INCHWORM_LUMP, // 15\r
- EATER_LUMP, // 16\r
- COUNCIL_LUMP, // 17\r
- EGGBIRD_LUMP, // 18\r
- MIMROCK_LUMP, // 19\r
- DOPEFISH_LUMP, // 20\r
- SCHOOLFISH_LUMP, // 21\r
- ARACHNUT_LUMP, // 22\r
- SKYPEST_LUMP, // 23\r
- WORMOUTH_LUMP, // 24\r
- LICK_LUMP, // 25\r
- PLATFORM_LUMP, // 26\r
- BOUNDER_LUMP, // 27\r
- THUNDERCLOUD_LUMP, // 28\r
- BERKELOID_LUMP, // 29\r
- KEYGEM_LUMP, // 30\r
- DARTS_LUMP, // 31\r
- SCUBAKEEN_LUMP, // 32\r
- SPRITE_LUMP, // 33\r
- MINE_LUMP, // 34\r
- MOON_LUMP, // 35\r
- EGG_LUMP, // 36\r
- NUMLUMPS // 37\r
-};\r
-\r
-Uint16 lumpstart[NUMLUMPS] = {\r
- CONTROLS_LUMP_START,\r
- KEEN_LUMP_START,\r
- SUGAR1_LUMP_START,\r
- SUGAR2_LUMP_START,\r
- SUGAR3_LUMP_START,\r
- SUGAR4_LUMP_START,\r
- SUGAR5_LUMP_START,\r
- SUGAR6_LUMP_START,\r
- ONEUP_LUMP_START,\r
- AMMO_LUMP_START,\r
- WORLDKEEN_LUMP_START,\r
- SLUG_LUMP_START,\r
- MADMUSHROOM_LUMP_START,\r
- 0,\r
- LINDSEY_LUMP_START,\r
- INCHWORM_LUMP_START,\r
- EATER_LUMP_START,\r
- COUNCIL_LUMP_START,\r
- EGGBIRD_LUMP_START,\r
- MIMROCK_LUMP_START,\r
- DOPEFISH_LUMP_START,\r
- SCHOOLFISH_LUMP_START,\r
- ARACHNUT_LUMP_START,\r
- SKYPEST_LUMP_START,\r
- WORMOUTH_LUMP_START,\r
- LICK_LUMP_START,\r
- PLATFORM_LUMP_START,\r
- BOUNDER_LUMP_START,\r
- THUNDERCLOUD_LUMP_START,\r
- BERKELOID_LUMP_START,\r
- KEYGEM_LUMP_START,\r
- DARTS_LUMP_START,\r
- SCUBAKEEN_LUMP_START,\r
- SPRITE_LUMP_START,\r
- MINE_LUMP_START,\r
- MOON_LUMP_START,\r
- EGG_LUMP_START\r
-};\r
-\r
-Uint16 lumpend[NUMLUMPS] = {\r
- CONTROLS_LUMP_END,\r
- KEEN_LUMP_END,\r
- SUGAR1_LUMP_END,\r
- SUGAR2_LUMP_END,\r
- SUGAR3_LUMP_END,\r
- SUGAR4_LUMP_END,\r
- SUGAR5_LUMP_END,\r
- SUGAR6_LUMP_END,\r
- ONEUP_LUMP_END,\r
- AMMO_LUMP_END,\r
- WORLDKEEN_LUMP_END,\r
- SLUG_LUMP_END,\r
- MADMUSHROOM_LUMP_END,\r
- 0,\r
- LINDSEY_LUMP_END,\r
- INCHWORM_LUMP_END,\r
- EATER_LUMP_END,\r
- COUNCIL_LUMP_END,\r
- EGGBIRD_LUMP_END,\r
- MIMROCK_LUMP_END,\r
- DOPEFISH_LUMP_END,\r
- SCHOOLFISH_LUMP_END,\r
- ARACHNUT_LUMP_END,\r
- SKYPEST_LUMP_END,\r
- WORMOUTH_LUMP_END,\r
- LICK_LUMP_END,\r
- PLATFORM_LUMP_END,\r
- BOUNDER_LUMP_END,\r
- THUNDERCLOUD_LUMP_END,\r
- BERKELOID_LUMP_END,\r
- KEYGEM_LUMP_END,\r
- DARTS_LUMP_END,\r
- SCUBAKEEN_LUMP_END,\r
- SPRITE_LUMP_END,\r
- MINE_LUMP_END,\r
- MOON_LUMP_END,\r
- EGG_LUMP_END\r
-};\r
-\r
-boolean lumpneeded[NUMLUMPS];\r
-\r
-#if GRMODE == EGAGR\r
-\r
-char far swtext[] =\r
- "Episode Four\n"\r
- "\n"\r
- "Secret of the Oracle\n"\r
- "\n"\r
- "After delivering a\n"\r
- "crippling blow to the\n"\r
- "plans of Mortimer\n"\r
- "McMire and receiving\n"\r
- "the praise of the\n"\r
- "Vorticon race,\n"\r
- "Commander Keen\n"\r
- "returned to his home in\n"\r
- "the suburbs.\n"\r
- "\n"\r
- "Here he was forced to\n"\r
- "go to bed at an early\n"\r
- "hour, and to eat mashed\n"\r
- "potatoes.\n"\r
- "\n"\r
- "Months later, Billy\n"\r
- "tinkered around with\n"\r
- "his latest invention,\n"\r
- "the Photachyon\n"\r
- "Transceiver, or faster-\n"\r
- "than-light radio. After\n"\r
- "picking up a lot of bad\n"\r
- "alien sitcoms, he\n"\r
- "stumbled upon a strange\n"\r
- "message of terrible\n"\r
- "importance....\n";\r
-\r
-#endif\r
-\r
-char far l0n[] = "Shadowlands";\r
-char far l1n[] = "Border Village";\r
-char far l2n[] = "Slug Village";\r
-char far l3n[] = "The Perilous Pit";\r
-char far l4n[] = "Cave of the Descendents";\r
-char far l5n[] = "Chasm of Chills";\r
-char far l6n[] = "Crystalus";\r
-char far l7n[] = "Hillville";\r
-char far l8n[] = "Sand Yego";\r
-char far l9n[] = "Miragia";\r
-char far l10n[] = "Lifewater Oasis";\r
-char far l11n[] = "Pyramid of the Moons";\r
-char far l12n[] = "Pyramid of Shadows";\r
-char far l13n[] = "Pyramid of the\nGnosticene Ancients";\r
-char far l14n[] = "Pyramid of the Forbidden";\r
-char far l15n[] = "Isle of Tar";\r
-char far l16n[] = "Isle of Fire";\r
-char far l17n[] = "Well of Wishes";\r
-char far l18n[] = "Bean-with-Bacon\nMegarocket";\r
-\r
-char far l0e[] = "Keen enters the\nShadowlands";\r
-char far l1e[] = "Keen makes a run for\nthe Border Village";\r
-char far l2e[] = "Keen slips into\nSlug Village";\r
-char far l3e[] = "Keen plummets into\nthe The Perilous Pit"; // sic!\r
-char far l4e[] = "Keen plods down into\nthe Cave of the\nDescendents";\r
-char far l5e[] = "Keen shivers along\nthe Chasm of Chills";\r
-char far l6e[] = "Keen reflects upon\nentering Crystalus";\r
-char far l7e[] = "Keen stumbles upon\nHillville";\r
-char far l8e[] = "Keen grits his teeth\nand enters Sand Yego";\r
-char far l9e[] = "Keen disappears into\nMiragia";\r
-char far l10e[] = "Keen crawls into\nLifewater Oasis";\r
-char far l11e[] = "Keen backs into the\nPyramid of the Moons";\r
-char far l12e[] = "Keen move silently in\nthe Pyramid of Shadows"; // sic!\r
-char far l13e[] = "Keen reverently enters\nthe Pyramid of the\nGnosticene Ancients";\r
-char far l14e[] = "Keen hesitantly crosses\ninto the Pyramid of the\nForbidden";\r
-char far l15e[] = "Keen mucks along the\nIsle of Tar";\r
-char far l16e[] = "Keen blazes across the\nIsle of Fire";\r
-char far l17e[] = "Keen hopefully enters\nthe Well of Wishes";\r
-char far l18e[] = "Keen launches into the\nBean-with-Bacon\nMegarocket";\r
-\r
-char far *levelnames[GAMELEVELS] = {\r
- l0n,\r
- l1n,\r
- l2n,\r
- l3n,\r
- l4n,\r
- l5n,\r
- l6n,\r
- l7n,\r
- l8n,\r
- l9n,\r
- l10n,\r
- l11n,\r
- l12n,\r
- l13n,\r
- l14n,\r
- l15n,\r
- l16n,\r
- l17n,\r
- l18n\r
-};\r
-\r
-char far *levelenter[GAMELEVELS] = {\r
- l0e,\r
- l1e,\r
- l2e,\r
- l3e,\r
- l4e,\r
- l5e,\r
- l6e,\r
- l7e,\r
- l8e,\r
- l9e,\r
- l10e,\r
- l11e,\r
- l12e,\r
- l13e,\r
- l14e,\r
- l15e,\r
- l16e,\r
- l17e,\r
- l18e\r
-};\r
-\r
-Uint16 bonuslump[] = {\r
- KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP,\r
- SUGAR1_LUMP, SUGAR2_LUMP, SUGAR3_LUMP,\r
- SUGAR4_LUMP, SUGAR5_LUMP, SUGAR6_LUMP,\r
- ONEUP_LUMP, AMMO_LUMP\r
-};\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= ScanInfoPlane\r
-=\r
-= Spawn all actors and mark down special places\r
-=\r
-==========================\r
-*/\r
-\r
-void ScanInfoPlane(void)\r
-{\r
- objtype *ob;\r
- Uint16 i, x, y, chunk;\r
- Sint16 info;\r
- Uint16 far *map;\r
-\r
- InitObjArray(); // start spawning things with a clean slate\r
-\r
- memset(lumpneeded, 0, sizeof(lumpneeded));\r
- map = mapsegs[2];\r
-\r
- for (y=0; y<mapheight; y++)\r
- {\r
- for (x=0; x<mapwidth; x++)\r
- {\r
- info = *map++;\r
-\r
- if (info == 0)\r
- continue;\r
-\r
- switch (info)\r
- {\r
- case 1:\r
- SpawnKeen(x, y, 1);\r
- SpawnScore();\r
- lumpneeded[KEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 2:\r
- SpawnKeen(x, y, -1);\r
- SpawnScore();\r
- lumpneeded[KEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 3:\r
- SpawnWorldKeen(x, y);\r
- SpawnScore();\r
- lumpneeded[WOLRDKEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 4:\r
- SpawnCouncil(x, y);\r
- lumpneeded[COUNCIL_LUMP] = true;\r
- break;\r
-\r
- case 50:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 49:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 5:\r
- SpawnBerkeloid(x, y);\r
- lumpneeded[BERKELOID_LUMP] = true;\r
- break;\r
-\r
- case 6:\r
- SpawnLindsey(x, y);\r
- lumpneeded[LINDSEY_LUMP] = true;\r
- break;\r
-\r
- case 52:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 51:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 7:\r
- SpawnWormMouth(x, y);\r
- lumpneeded[WORMOUTH_LUMP] = true;\r
- break;\r
-\r
- case 46:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 45:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 8:\r
- SpawnSkypest(x, y);\r
- lumpneeded[SKYPEST_LUMP] = true;\r
- break;\r
-\r
- case 9:\r
- SpawnCloudster(x, y);\r
- lumpneeded[THUNDERCLOUD_LUMP] = true;\r
- break;\r
-\r
- case 10:\r
- SpawnFoot(x, y);\r
- lumpneeded[INCHWORM_LUMP] = true; // lump includes the foot sprite\r
- // Note: The smoke sprites aren't actually required for the foot!\r
- for (i=SMOKE1SPR; i<=SMOKE4SPR; i++)\r
- {\r
- CA_MarkGrChunk(i);\r
- }\r
- break;\r
-\r
- case 11:\r
- SpawnInchworm(x, y);\r
- lumpneeded[INCHWORM_LUMP] = true;\r
- for (i=SMOKE1SPR; i<=SMOKE4SPR; i++)\r
- {\r
- CA_MarkGrChunk(i);\r
- }\r
- break;\r
-\r
- case 12:\r
- SpawnBounder(x, y);\r
- lumpneeded[BOUNDER_LUMP] = true;\r
- break;\r
-\r
- case 13:\r
- SpawnEggbird(x, y);\r
- lumpneeded[EGGBIRD_LUMP] = true;\r
- lumpneeded[EGG_LUMP] = true;\r
- break;\r
-\r
- case 48:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 47:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 14:\r
- SpawnLick(x, y);\r
- lumpneeded[LICK_LUMP] = true;\r
- break;\r
-\r
- case 88:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 87:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 15:\r
- SpawnDopefish(x, y);\r
- lumpneeded[DOPEFISH_LUMP] = true;\r
- break;\r
-\r
- case 16:\r
- SpawnSchoolfish(x, y);\r
- lumpneeded[SCHOOLFISH_LUMP] = true;\r
- break;\r
-\r
- case 24:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 23:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 17:\r
- SpawnPixie(x, y);\r
- lumpneeded[SPRITE_LUMP] = true;\r
- break;\r
-\r
- case 18:\r
- SpawnEater(x, y);\r
- lumpneeded[EATER_LUMP] = true;\r
- break;\r
-\r
- case 19:\r
- SpawnMimrock(x, y);\r
- lumpneeded[MIMROCK_LUMP] = true;\r
- break;\r
-\r
- case 74:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 73:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 20:\r
- SpawnArachnut(x, y);\r
- lumpneeded[ARACHNUT_LUMP] = true;\r
- break;\r
-\r
- case 21:\r
- SpawnMadMushroom(x, y);\r
- lumpneeded[MADMUSHROOM_LUMP] = true;\r
- break;\r
-\r
- case 44:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 43:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 22:\r
- SpawnSlug(x, y);\r
- lumpneeded[SLUG_LUMP] = true;\r
- break;\r
-\r
- case 25:\r
- RF_SetScrollBlock(x, y, 1);\r
- break;\r
-\r
- case 26:\r
- RF_SetScrollBlock(x, y, 0);\r
- break;\r
-\r
- case 27:\r
- case 28:\r
- case 29:\r
- case 30:\r
- SpawnPlatform(x, y, info-27);\r
- lumpneeded[PLATFORM_LUMP] = true;;\r
- break;\r
-\r
- case 32:\r
- SpawnDropPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 33:\r
- SpawnMiragia(x, y);\r
- break;\r
-\r
- case 34:\r
- if (gamestate.ammo < 5)\r
- {\r
- SpawnBonus(x, y, 11);\r
- lumpneeded[bonuslump[11]] = true;\r
- }\r
- break;\r
-\r
- case 35:\r
- SpawnScuba(x, y);\r
- CA_MarkGrChunk(SCUBASPR);\r
- break;\r
-\r
- case 42:\r
- SpawnSwimKeen(x, y);\r
- SpawnScore();\r
- lumpneeded[SCUBAKEEN_LUMP] = true;\r
- //mark pickup shapes:\r
- for (i=BONUS100SPR; i<=BONUSCLIPSPR; i++)\r
- {\r
- CA_MarkGrChunk(i);\r
- }\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 83:\r
- case 84:\r
- case 85:\r
- case 86:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- SpawnDartShooter(x, y, info-83);\r
- lumpneeded[DARTS_LUMP] = true;\r
- break;\r
-\r
- case 79:\r
- case 80:\r
- case 81:\r
- case 82:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- SpawnDartShooter(x, y, info-79);\r
- lumpneeded[DARTS_LUMP] = true;\r
- break;\r
-\r
- case 53:\r
- case 54:\r
- case 55:\r
- case 56:\r
- SpawnDartShooter(x, y, info-53);\r
- lumpneeded[DARTS_LUMP] = true;\r
- break;\r
-\r
- case 57:\r
- case 58:\r
- case 59:\r
- case 60:\r
- case 61:\r
- case 62:\r
- case 63:\r
- case 64:\r
- case 65:\r
- case 66:\r
- case 67:\r
- case 68:\r
- SpawnBonus(x, y, info-57);\r
- lumpneeded[bonuslump[info-57]] = true;\r
- break;\r
-\r
- case 69:\r
- case 70:\r
- case 71:\r
- case 72:\r
- SpawnMine(x, y, info-69);\r
- lumpneeded[MINE_LUMP] = true;\r
- break;\r
-\r
- case 75:\r
- lumpneeded[MOON_LUMP] = true;\r
- break;\r
-\r
- case 78:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 77:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 76:\r
- SpawnEggbirdOut(x, y);\r
- lumpneeded[EGGBIRD_LUMP] = true;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- for (ob = player; ob; ob = ob->next)\r
- {\r
- if (ob->active != ac_allways)\r
- ob->active = ac_no;\r
- }\r
-\r
- for (i = 0; i < NUMLUMPS; i++)\r
- {\r
- if (lumpneeded[i])\r
- {\r
- for (chunk = lumpstart[i]; chunk <= lumpend[i]; chunk++)\r
- {\r
- CA_MarkGrChunk(chunk);\r
- }\r
- }\r
- }\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= PrincessLindsey\r
-=\r
-===========================\r
-*/\r
-\r
-char *lindseytext[2] =\r
-{\r
- "There's gear to help\n"\r
- "you swim in Three-Tooth\n"\r
- "Lake. It is hidden in\n"\r
- "Miragia.\n"\r
- ,\r
- "The way to the Pyramid\n"\r
- "of the Forbidden lies\n"\r
- "under the Pyramid of\n"\r
- "Moons.\n"\r
-};\r
-\r
-char *klindseytext[2] =\r
-{\r
- "Thanks, your Highness!"\r
- ,\r
- "Thanks for the\n"\r
- "mysterious clue,\n"\r
- "Princess!\n"\r
-};\r
-\r
-void PrincessLindsey(void)\r
-{\r
- SD_WaitSoundDone();\r
- StopMusic();\r
- CA_UpLevel();\r
- CA_MarkGrChunk(LINDSEYPIC);\r
- CA_MarkGrChunk(KEENTALK1PIC);\r
- CA_MarkGrChunk(KEENTALK2PIC);\r
- CA_CacheMarks(NULL);\r
- VW_FixRefreshBuffer();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX, WindowY, LINDSEYPIC);\r
- PrintY += 6;\r
- WindowW -= 48;\r
- WindowX += 48;\r
- US_CPrint("Princess Lindsey says:\n");\r
- if (mapon == 7)\r
- {\r
- US_CPrint(lindseytext[0]);\r
- }\r
- else\r
- {\r
- US_CPrint(lindseytext[1]);\r
- }\r
- VW_UpdateScreen();\r
- SD_PlaySound(SND_MAKEFOOT);\r
- VW_WaitVBL(60);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 12;\r
- if (mapon == 7)\r
- {\r
- US_CPrint(klindseytext[0]);\r
- }\r
- else\r
- {\r
- US_CPrint(klindseytext[1]);\r
- }\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- VWB_DrawPic(WindowX+WindowW, WindowY, KEENTALK2PIC);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- CA_DownLevel();\r
- StartMusic(gamestate.mapon);\r
-\r
- //reset scorebox (sprite may have been re-cached by CA_DownLevel)\r
- scoreobj->temp2 = -1;\r
- scoreobj->temp1 = -1;\r
- scoreobj->temp3 = -1;\r
- scoreobj->temp4 = -1;\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= RescueJanitor\r
-=\r
-===========================\r
-*/\r
-\r
-char far jantext1[] =\r
- "Thanks for going to all\n"\r
- "that trouble, but I'm\n"\r
- "just the janitor for the\n"\r
- "High Council.";\r
-\r
-char far jantext2[] =\r
- "I tried to tell the\n"\r
- "Shikadi that but they\n"\r
- "just wouldn't listen...";\r
-\r
-char far keenjantext[] =\r
- "This had better\n"\r
- "be a joke.";\r
-\r
-char far jantext3[] =\r
- "Sorry. You aren't\n"\r
- "mad, are you?";\r
-\r
-void RescueJanitor(void)\r
-{\r
- char str[200];\r
-\r
- SD_WaitSoundDone();\r
- CA_UpLevel();\r
- CA_MarkGrChunk(ORACLEPIC);\r
- CA_MarkGrChunk(KEENTALK1PIC);\r
- CA_MarkGrChunk(KEENMADPIC);\r
- CA_CacheMarks(NULL);\r
- VW_FixRefreshBuffer();\r
- StartMusic(-1);\r
- \r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX, WindowY, ORACLEPIC);\r
- PrintY += 6;\r
- WindowW -= 48;\r
- WindowX += 48;\r
- _fstrcpy(str, jantext1);\r
- US_CPrint(str);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(60);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX, WindowY, ORACLEPIC);\r
- PrintY += 6;\r
- WindowW -= 48;\r
- WindowX += 48;\r
- _fstrcpy(str, jantext2);\r
- US_CPrint(str);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(60);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 12;\r
- _fstrcpy(str, keenjantext);\r
- US_CPrint(str);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(60);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX, WindowY, ORACLEPIC);\r
- PrintY += 6;\r
- WindowW -= 48;\r
- WindowX += 48;\r
- _fstrcpy(str, jantext3);\r
- US_CPrint(str);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(60);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- VWB_DrawPic(WindowX+WindowW-40, WindowY+24, KEENMADPIC);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- StopMusic();\r
- CA_DownLevel();\r
- StartMusic(gamestate.mapon);\r
-\r
- //BUG: scorebox needs to be reset here (sprite may have been re-cached by CA_DownLevel)\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= CanitSwim\r
-=\r
-===========================\r
-*/\r
-\r
-void CantSwim(void)\r
-{\r
- SD_WaitSoundDone();\r
- CA_UpLevel(); // kinda useless without CA_CacheMarks or CA_SetGrPurge\r
- // BUG: haven't made anything purgable here, caching the pic may cause an "out of memory" crash\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 12;\r
- US_CPrint("I can't swim!");\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- CA_DownLevel();\r
-\r
- //Note: scorebox sprite has not been re-cached here (didn't use CA_CacheMarks or anything else that would have made the sprite purgable)\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= GotScuba\r
-=\r
-===========================\r
-*/\r
-\r
-void GotScuba(void)\r
-{\r
- SD_WaitSoundDone();\r
- CA_UpLevel();\r
- CA_MarkGrChunk(KEENTALK1PIC);\r
- CA_MarkGrChunk(KEENTALK2PIC);\r
- CA_CacheMarks(NULL);\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 12;\r
- US_CPrint(\r
- "Cool! I can breathe\n"\r
- "under water now!"\r
- );\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- VWB_DrawPic(WindowX+WindowW, WindowY, KEENTALK2PIC);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- CA_DownLevel();\r
-\r
- //Note: scorebox sprite may have been re-cached by CA_DownLevel, but the level ends after this anyway\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= RescuedMember\r
-=\r
-===========================\r
-*/\r
-\r
-char *keentext[] = {\r
- "No sweat, oh guardian\n"\r
- "of wisdom!"\r
- ,\r
- "Sounds like a plan,\n"\r
- "bearded one!"\r
- ,\r
- "No problemo."\r
- ,\r
- "Great. You know, you\n"\r
- "look a lot like the\n"\r
- "last guy I rescued..."\r
- ,\r
- "Good idea, Gramps."\r
- ,\r
- "May the road rise\n"\r
- "to meet your feet,\n"\r
- "Mr. Member."\r
- ,\r
- "Wise plan of action,\n"\r
- "your ancientness."\r
- ,\r
- "You're the last one,\n"\r
- "fella. Let's both\n"\r
- "get back to the\n"\r
- "Oracle chamber!"\r
-};\r
-\r
-void RescuedMember(void)\r
-{\r
- SD_WaitSoundDone();\r
- CA_UpLevel();\r
- CA_MarkGrChunk(ORACLEPIC);\r
- CA_MarkGrChunk(KEENTALK1PIC);\r
- CA_MarkGrChunk(KEENTALK2PIC);\r
- CA_CacheMarks(NULL);\r
- StartMusic(-1);\r
- VW_FixRefreshBuffer();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX, WindowY, ORACLEPIC);\r
- PrintY += 6;\r
- WindowW -= 48;\r
- WindowX += 48;\r
- if (mapon == 17)\r
- {\r
- US_CPrint(\r
- "Ggoh thig you sogh mg\n"\r
- "fgor regscuing mgge!\n"\r
- "I'gll regur tgo the\n"\r
- "Goracle chagber\n"\r
- "igmediatggely. Blub."\r
- );\r
- }\r
- else\r
- {\r
- US_CPrint(\r
- "Oh thank you so much\n"\r
- "for rescuing me!\n"\r
- "I'll return to the\n"\r
- "Oracle chamber\n"\r
- "immediately."\r
- );\r
- }\r
- VW_UpdateScreen();\r
- VW_WaitVBL(60);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 12;\r
- US_CPrint(keentext[gamestate.rescued]);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- VWB_DrawPic(WindowX+WindowW, WindowY, KEENTALK2PIC);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- gamestate.rescued++;\r
- CA_DownLevel();\r
- StopMusic();\r
-\r
- //Note: scorebox sprite may have been re-cached by CA_DownLevel, but the level ends after this anyway\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SWIMMING KEEN\r
-\r
-temp4 = counter for spawning bubbles\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_keenswimslow1 = {SCUBAKEENL1SPR, SCUBAKEENR1SPR, stepthink, false, false, 50, 0, 0, T_KeenSwimSlow, C_KeenSwim, R_KeenSwim, &s_keenswimslow2};\r
-statetype s_keenswimslow2 = {SCUBAKEENL2SPR, SCUBAKEENR2SPR, stepthink, false, false, 50, 0, 0, T_KeenSwimSlow, C_KeenSwim, R_KeenSwim, &s_keenswimslow1};\r
-statetype s_keenswim1 = {SCUBAKEENL1SPR, SCUBAKEENR1SPR, stepthink, false, false, 50, 0, 0, T_KeenSwim, C_KeenSwim, R_KeenSwim, &s_keenswimslow2};\r
-statetype s_keenswim2 = {SCUBAKEENL2SPR, SCUBAKEENR2SPR, stepthink, false, false, 50, 0, 0, T_KeenSwim, C_KeenSwim, R_KeenSwim, &s_keenswimslow1};\r
-//Note: the die states for swimming Keen are in CK_KEEN.C and K4_ACT3.C (dopefish section)\r
-\r
-statetype s_kbubble1 = {SMALLBUBBLE1SPR, SMALLBUBBLE1SPR, think, false, false, 20, 0, 24, T_Bubble, NULL, R_Draw, &s_kbubble1};\r
-statetype s_kbubble2 = {SMALLBUBBLE2SPR, SMALLBUBBLE2SPR, think, false, false, 20, 0, 24, T_Bubble, NULL, R_Draw, &s_kbubble2};\r
-statetype s_kbubble3 = {SMALLBUBBLE3SPR, SMALLBUBBLE3SPR, think, false, false, 20, 0, 24, T_Bubble, NULL, R_Draw, &s_kbubble3};\r
-statetype s_kbubble4 = {SMALLBUBBLE4SPR, SMALLBUBBLE4SPR, think, false, false, 20, 0, 24, T_Bubble, NULL, R_Draw, &s_kbubble4};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSwimKeen\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSwimKeen(Sint16 x, Sint16 y)\r
-{\r
- player->obclass = keenobj;\r
- player->active = ac_allways;\r
- player->priority = 1;\r
- player->x = CONVERT_TILE_TO_GLOBAL(x);\r
- player->y = CONVERT_TILE_TO_GLOBAL(y);\r
- player->xdir = 1;\r
- player->ydir = 1;\r
- player->needtoclip = cl_fullclip;\r
- NewState(player, &s_keenswimslow1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnKbubble\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnKbubble(objtype *ob)\r
-{\r
- ob->temp4 = 0;\r
- GetNewObj(true);\r
- if (ob->xdir == -1)\r
- {\r
- new->x = ob->x;\r
- }\r
- else\r
- {\r
- new->x = ob->x + 24*PIXGLOBAL;\r
- }\r
- new->y = ob->y;\r
- new->obclass = inertobj;\r
- new->priority = 3;\r
- new->active = ac_removable;\r
- new->needtoclip = cl_noclip;\r
- new->yspeed = -24;\r
- new->xspeed = 4;\r
- switch (US_RndT() / 64)\r
- {\r
- case 0:\r
- NewState(new, &s_kbubble1);\r
- break;\r
- case 1:\r
- NewState(new, &s_kbubble2);\r
- break;\r
- case 2:\r
- NewState(new, &s_kbubble3);\r
- break;\r
- case 3:\r
- NewState(new, &s_kbubble4);\r
- break;\r
- }\r
- SD_PlaySound(SND_BLUB);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_KeenSwimSlow\r
-=\r
-===========================\r
-*/\r
-\r
-void T_KeenSwimSlow(objtype *ob)\r
-{\r
- Sint32 i;\r
- Sint16 vx, vy, xc, yc;\r
-\r
- xc = ob->xspeed < 0;\r
- yc = ob->yspeed < 4;\r
-\r
- ob->temp4 = ob->temp4 + tics;\r
- if (ob->temp4 > 60)\r
- SpawnKbubble(ob);\r
-\r
- if (jumpbutton && !jumpheld)\r
- {\r
- jumpheld = true;\r
- if (c.xaxis)\r
- ob->xspeed = c.xaxis * 18;\r
- if (c.yaxis)\r
- ob->yspeed = c.yaxis * 18;\r
- ob->state = ob->state->nextstate;\r
- }\r
- if (c.xaxis)\r
- ob->xdir = c.xaxis;\r
-\r
- for (i = lasttimecount-tics; i < lasttimecount; i++)\r
- {\r
- if ((i & 7) == 0)\r
- {\r
- if (ob->xspeed > 12)\r
- {\r
- vx = -3;\r
- }\r
- else if (ob->xspeed > 0)\r
- {\r
- vx = -1;\r
- }\r
- else if (ob->xspeed > -12)\r
- {\r
- vx = 1;\r
- }\r
- else\r
- {\r
- vx = 3;\r
- }\r
- vx += c.xaxis;\r
- vx += c.xaxis;\r
- ob->xspeed += vx;\r
-\r
- if (c.xaxis == 0 && (ob->xspeed < 0) != xc)\r
- ob->xspeed = 0;\r
-\r
- if (ob->yspeed > 12)\r
- {\r
- vy = -3;\r
- }\r
- else if (ob->yspeed > 4)\r
- {\r
- vy = -1;\r
- }\r
- else if (ob->yspeed > -12)\r
- {\r
- vy = 1;\r
- }\r
- else\r
- {\r
- vy = 3;\r
- }\r
- vy += c.yaxis;\r
- vy += c.yaxis;\r
- ob->yspeed += vy;\r
-\r
- if (c.yaxis == 0 && ob->yspeed > 4 && yc)\r
- ob->yspeed = 0;\r
- }\r
- xtry += ob->xspeed;\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_KeenSwim\r
-=\r
-===========================\r
-*/\r
-\r
-void T_KeenSwim(objtype *ob) //never actually used\r
-{\r
- ob->temp4 = ob->temp4 + tics;\r
- if (ob->temp4 > 60)\r
- SpawnKbubble(ob);\r
-\r
- if (jumpbutton && !jumpheld)\r
- {\r
- jumpheld = true;\r
- ob->xspeed = c.xaxis * 18;\r
- if (c.yaxis)\r
- ob->yspeed = c.yaxis * 18;\r
-\r
- if (ob->state == &s_keenswim1)\r
- {\r
- ob->state = &s_keenswim2;\r
- }\r
- else\r
- {\r
- ob->state = &s_keenswim1;\r
- }\r
- }\r
-\r
- xtry = xtry + ob->xspeed * tics;\r
- ytry = ytry + ob->yspeed * tics;\r
- if (xtry > 0)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else if (xtry < 0)\r
- {\r
- ob->xdir = -1;\r
- }\r
-\r
- ytry = ytry + tics*4;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_KeenSwim\r
-=\r
-===========================\r
-*/\r
-\r
-void C_KeenSwim(objtype *ob, objtype *hit)\r
-{\r
- switch (hit->obclass)\r
- {\r
- case bonusobj:\r
- switch (hit->temp1)\r
- {\r
- case 0:\r
- case 1:\r
- case 2:\r
- case 3:\r
- case 4:\r
- case 5:\r
- case 6:\r
- case 7:\r
- case 8:\r
- case 9:\r
- case 10:\r
- case 11:\r
- SD_PlaySound(bonussound[hit->temp1]);\r
- hit->obclass = inertobj;\r
- hit->priority = 3;\r
- hit->shapenum = bonussprite[hit->temp1];\r
- GivePoints(bonuspoints[hit->temp1]);\r
- if (hit->temp1 < 4)\r
- {\r
- gamestate.keys[hit->temp1]++;\r
- }\r
- else if (hit->temp1 == 10)\r
- {\r
- gamestate.lives++;\r
- }\r
- else if (hit->temp1 == 11)\r
- {\r
- gamestate.ammo += shotsinclip[gamestate.difficulty];\r
- }\r
- ChangeState(hit, &s_bonusrise);\r
- break;\r
- }\r
- break;\r
-\r
- case oracleobj:\r
- playstate = ex_rescued;\r
- break;\r
- }\r
- ob++; // shut up compiler\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_KeenSwim\r
-=\r
-===========================\r
-*/\r
-\r
-void R_KeenSwim(objtype *ob)\r
-{\r
- if (ob->hiteast && ob->xspeed < 0 || ob->hitwest && ob->xspeed > 0)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitnorth && ob->yspeed > 0 || ob->hitsouth && ob->yspeed < 0)\r
- ob->yspeed = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
+++ /dev/null
-;=====================================\r
-;\r
-; Graphics .EQU file for .CK4\r
-; not IGRAB-ed :)\r
-;\r
-;=====================================\r
-\r
-;INCLUDE "VERSION.EQU"\r
-\r
-;\r
-; Amount of each data item\r
-;\r
-NUMFONT = 2\r
-NUMFONTM = 0\r
-NUMPICM = 3\r
-NUMTILE8 = 108\r
-NUMTILE8M = 36\r
-NUMTILE32 = 0\r
-NUMTILE32M = 0\r
-\r
-;\r
-; Amount of each item in episode 4\r
-;\r
-NUMPICS = 116\r
-NUMSPRITES = 397\r
-NUMTILE16 = 1296\r
-NUMTILE16M = 2916\r
-NUMEXTERN = 16\r
-\r
-\r
-;\r
-; File offsets for data items\r
-;\r
-STRUCTPIC = 0\r
-STRUCTPICM = 1\r
-STRUCTSPRITE = 2\r
-\r
-STARTFONT = 3\r
-STARTFONTM = (STARTFONT+NUMFONT)\r
-STARTPICS = (STARTFONTM+NUMFONTM)\r
-STARTPICM = (STARTPICS+NUMPICS)\r
-STARTSPRITES = (STARTPICM+NUMPICM)\r
-STARTTILE8 = (STARTSPRITES+NUMSPRITES)\r
-STARTTILE8M = (STARTTILE8+1)\r
-STARTTILE16 = (STARTTILE8M+1)\r
-STARTTILE16M = (STARTTILE16+NUMTILE16)\r
-STARTTILE32 = (STARTTILE16M+NUMTILE16M)\r
-STARTTILE32M = (STARTTILE32+NUMTILE32)\r
-STARTEXTERN = (STARTTILE32M+NUMTILE32M)\r
-\r
-NUMCHUNKS = (STARTEXTERN+NUMEXTERN)\r
-\r
-;\r
-; Thank you for using IGRAB!\r
-;\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __GFX_H__\r
-#define __GFX_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-//////////////////////////////////////\r
-//\r
-// Graphics .H file for .CK4\r
-// not IGRAB-ed :)\r
-//\r
-//////////////////////////////////////\r
-\r
-//\r
-// Lump creation macros\r
-//\r
-\r
-#define START_LUMP(actualname, dummyname) actualname, dummyname=actualname-1,\r
-#define END_LUMP(actualname, dummyname) dummyname, actualname=dummyname-1,\r
-\r
-//\r
-// Amount of each data item\r
-//\r
-\r
-//common numbers:\r
-#define NUMCHUNKS NUMGRCHUNKS\r
-#define NUMFONT 2\r
-#define NUMFONTM 0\r
-#define NUMPICM 3\r
-#define NUMTILE8 108 // BUG: only 104 tiles exist in EGAGRAPH!\r
-#define NUMTILE8M 36 // BUG: only 20 tiles exist in EGAGRAPH!\r
-#define NUMTILE32 0\r
-#define NUMTILE32M 0\r
-\r
-//episode-specific numbers:\r
-#define NUMPICS 116\r
-#define NUMSPRITES 397\r
-#define NUMTILE16 1296\r
-#define NUMTILE16M 2916\r
-#define NUMEXTERNS 16\r
-\r
-//\r
-// File offsets for data items\r
-//\r
-#define STRUCTPIC 0\r
-#define STRUCTPICM 1\r
-#define STRUCTSPRITE 2\r
-\r
-#define STARTFONT 3\r
-#define STARTFONTM (STARTFONT+NUMFONT)\r
-#define STARTPICS (STARTFONTM+NUMFONTM)\r
-#define STARTPICM (STARTPICS+NUMPICS)\r
-#define STARTSPRITES (STARTPICM+NUMPICM)\r
-#define STARTTILE8 (STARTSPRITES+NUMSPRITES)\r
-#define STARTTILE8M (STARTTILE8+1)\r
-#define STARTTILE16 (STARTTILE8M+1)\r
-#define STARTTILE16M (STARTTILE16+NUMTILE16)\r
-#define STARTTILE32 (STARTTILE16M+NUMTILE16M)\r
-#define STARTTILE32M (STARTTILE32+NUMTILE32)\r
-#define STARTEXTERNS (STARTTILE32M+NUMTILE32M)\r
-\r
-typedef enum {\r
- LASTFONT=STARTPICS-1,\r
-\r
- //\r
- // PICS\r
- //\r
-\r
- PADDINGPIC, // 5 (compensate for the missing Star Wars font to give the other pics the correct chunk numbers)\r
-\r
- H_HELPPIC, // 6\r
- H_LARROWPIC, // 7\r
- H_RARROWPIC, // 8\r
- H_ESCPIC, // 9\r
- H_ENTERPIC, // 10\r
- DUMMYPIC, // 11\r
- H_STORY1PIC, // 12\r
- H_STORY2PIC, // 13\r
- H_STORY3PIC, // 14\r
- H_STORY4PIC, // 15\r
- STORY5PIC, // 16\r
- STORY6PIC, // 17\r
- STORY7PIC, // 18\r
- STORY8PIC, // 19\r
- ITEM1PIC, // 20\r
- ITEM2PIC, // 21\r
- ITEM3PIC, // 22\r
- ITEM4PIC, // 23\r
- ITEM5PIC, // 24\r
- ITEM6PIC, // 25\r
- ITEM7PIC, // 26\r
- ITEM8PIC, // 27\r
- ITEM9PIC, // 28\r
- ARACHNUTPIC, // 29\r
- BERKELOISPIC, // 30\r
- BOUNDERPIC, // 31\r
- COUNCILMEMBERPIC, // 32\r
- DOPEFISHPIC, // 33\r
- INCHWORMPIC, // 34\r
- LICKPIC, // 35\r
- MADMUSHROOMPIC, // 36\r
- POISONSLIGPIC, // 37\r
- PRINCESSLINDSEYPIC, // 38\r
- SCHOOLFISHPIC, // 39\r
- SKYPESTPIC, // 40\r
- SPRITEPIC, // 41\r
- WORMOUTHPIC, // 42\r
- ENDOFTEXTPIC, // 43\r
- H_MCPIC, // 44\r
- H_HANDPIC, // 45\r
- H_VISAPIC, // 46\r
- H_FLASHARROW1PIC, // 47\r
- H_FLASHARROW2PIC, // 48\r
- ENDINDG1PIC, // 49\r
- ENDINDG2PIC, // 50\r
- ENDINDG3PIC, // 51\r
- ENDINDG4PIC, // 52\r
- ENDINDG5PIC, // 53\r
- ENDINDG6PIC, // 54\r
- ENDINDG7PIC, // 55\r
- ENDINDG8PIC, // 56\r
- ENDINDG9PIC, // 57\r
- ENDINDG10PIC, // 58\r
- ENDINDG11PIC, // 59\r
- ENDINDG12PIC, // 60\r
- ENDINDG13PIC, // 61\r
- ENDINDG14PIC, // 62\r
- ENDINDG15PIC, // 63\r
- ENDINDG16PIC, // 64\r
- ENDINDG17PIC, // 65\r
- ENDINDG18PIC, // 66\r
- ENDINDG19PIC, // 67\r
- ENDINDG20PIC, // 68\r
- ENDINDG21PIC, // 69\r
- ENDINDG22PIC, // 70\r
- ENDINDG23PIC, // 71\r
- ENDINDG24PIC, // 72\r
- ENDINDG25PIC, // 73\r
- ENDINDG26PIC, // 74\r
- ENDINDG27PIC, // 75\r
- ENDINDG28PIC, // 76\r
- ENDINDG29PIC, // 77\r
- ENDINDG30PIC, // 78\r
- H_IDLOGOPIC, // 79\r
- H_TOPWINDOWPIC, // 80\r
- H_LEFTWINDOWPIC, // 81\r
- H_RIGHTWINDOWPIC, // 82\r
- H_BOTTOMINFOPIC, // 83\r
- H_BOTTOMWINDOWPIC, // 84\r
- H_BARPIC, // 85\r
- H_KEEN5PIC, // 86\r
- H_KEEN6PIC, // 87\r
-\r
- START_LUMP(CONTROLS_LUMP_START, __CONTROLSSTART)\r
- CP_MAINMENUPIC, // 88\r
- CP_NEWGAMEMENUPIC, // 89\r
- CP_LOADMENUPIC, // 90\r
- CP_SAVEMENUPIC, // 91\r
- CP_CONFIGMENUPIC, // 92\r
- CP_SOUNDMENUPIC, // 93\r
- CP_MUSICMENUPIC, // 94\r
- CP_KEYBOARDMENUPIC, // 95\r
- CP_KEYMOVEMENTPIC, // 96\r
- CP_KEYBUTTONPIC, // 97\r
- CP_JOYSTICKMENUPIC, // 98\r
- CP_OPTIONSMENUPIC, // 99\r
- CP_PADDLEWARPIC, // 100\r
- CP_QUITPIC, // 101\r
- CP_JOYSTICKPIC, // 102\r
- CP_MENUSCREENPIC, // 103\r
- END_LUMP(CONTROLS_LUMP_END, __CONTROLSEND)\r
-\r
- IDSOFTPIC, // 104\r
- PROGTEAMPIC, // 105\r
- ARTISTPIC, // 106\r
- DIRECTORPIC, // 107\r
- SW_BACKGROUNDPIC, // 108\r
- TITLEPICPIC, // 109\r
- ORACLEPIC, // 110\r
- KEENTALK1PIC, // 111\r
- KEENTALK2PIC, // 112\r
- KEENMADPIC, // 113\r
- LINDSEYPIC, // 114\r
- KEENCOUNT1PIC, // 115\r
- KEENCOUNT2PIC, // 116\r
- KEENCOUNT3PIC, // 117\r
- KEENCOUNT4PIC, // 118\r
- KEENCOUNT5PIC, // 119\r
- KEENCOUNT6PIC, // 120\r
-\r
- //\r
- // MASKED PICS\r
- //\r
-\r
- CP_MENUMASKPICM, // 121\r
- CORDPICM, // 122\r
- METALPOLEPICM, // 123\r
-\r
- //\r
- // SPRITES\r
- //\r
-\r
- START_LUMP(PADDLE_LUMP_START, __PADDLESTART)\r
- PADDLESPR, // 124\r
- BALLSPR, // 125\r
- BALL1PIXELTOTHERIGHTSPR, // 126\r
- BALL2PIXELSTOTHERIGHTSPR, // 127\r
- BALL3PIXELSTOTHERIGHTSPR, // 128\r
- END_LUMP(PADDLE_LUMP_END, __PADDLEEND)\r
-\r
- DEMOPLAQUESPR, // 129\r
-\r
- //player lump:\r
- START_LUMP(KEEN_LUMP_START, __KEENSTART)\r
- KEENSTANDRSPR, // 130\r
- KEENRUNR1SPR, // 131\r
- KEENRUNR2SPR, // 132\r
- KEENRUNR3SPR, // 133\r
- KEENRUNR4SPR, // 134\r
- KEENJUMPR1SPR, // 135\r
- KEENJUMPR2SPR, // 136\r
- KEENJUMPR3SPR, // 137\r
- KEENSTANDLSPR, // 138\r
- KEENRUNL1SPR, // 139\r
- KEENRUNL2SPR, // 140\r
- KEENRUNL3SPR, // 141\r
- KEENRUNL4SPR, // 142\r
- KEENJUMPL1SPR, // 143\r
- KEENJUMPL2SPR, // 144\r
- KEENJUMPL3SPR, // 145\r
- KEENLOOKUSPR, // 146\r
- KEENWAITR1SPR, // 147\r
- KEENWAITR2SPR, // 148\r
- KEENWAITR3SPR, // 149\r
- KEENSITREAD1SPR, // 150\r
- KEENSITREAD2SPR, // 151\r
- KEENSITREAD3SPR, // 152\r
- KEENSITREAD4SPR, // 153\r
- KEENREAD1SPR, // 154\r
- KEENREAD2SPR, // 155\r
- KEENREAD3SPR, // 156\r
- KEENSTOPREAD1SPR, // 157\r
- KEENSTOPREAD2SPR, // 158\r
- KEENWATCHSPR, // 159\r
- KEENLOOKD1SPR, // 160\r
- KEENLOOKD2SPR, // 161\r
- KEENDIE1SPR, // 162\r
- KEENDIE2SPR, // 163\r
- STUNSTARS1SPR, // 164\r
- STUNSTARS2SPR, // 165\r
- STUNSTARS3SPR, // 166\r
- KEENSHOOTLSPR, // 167\r
- KEENJLSHOOTLSPR, // 168\r
- KEENJSHOOTDSPR, // 169\r
- KEENJSHOOTUSPR, // 170\r
- KEENSHOOTUSPR, // 171\r
- KEENSHOOTRSPR, // 172\r
- KEENJRSHOOTRSPR, // 173\r
- STUN1SPR, // 174\r
- STUN2SPR, // 175\r
- STUN3SPR, // 176\r
- STUN4SPR, // 177\r
- STUNHIT1SPR, // 178\r
- STUNHIT2SPR, // 179\r
- KEENSHINNYR1SPR, // 180\r
- KEENSHINNYR2SPR, // 181\r
- KEENSHINNYR3SPR, // 182\r
- KEENSLIDED1SPR, // 183\r
- KEENSLIDED2SPR, // 184\r
- KEENSLIDED3SPR, // 185\r
- KEENSLIDED4SPR, // 186\r
- KEENSHINNYL1SPR, // 187\r
- KEENSHINNYL2SPR, // 188\r
- KEENSHINNYL3SPR, // 189\r
- KEENPLSHOOTUSPR, // 190\r
- KEENPRSHOOTUSPR, // 191\r
- KEENPRSHOOTDSPR, // 192\r
- KEENPLSHOOTDSPR, // 193\r
- KEENPSHOOTLSPR, // 194\r
- KEENPSHOOTRSPR, // 195\r
- KEENENTER1SPR, // 196\r
- KEENENTER2SPR, // 197\r
- KEENENTER3SPR, // 198\r
- KEENENTER4SPR, // 199\r
- KEENENTER5SPR, // 200\r
- KEENHANGLSPR, // 201\r
- KEENHANGRSPR, // 202\r
- KEENCLIMBEDGEL1SPR, // 203\r
- KEENCLIMBEDGEL2SPR, // 204\r
- KEENCLIMBEDGEL3SPR, // 205\r
- KEENCLIMBEDGEL4SPR, // 206\r
- KEENCLIMBEDGER1SPR, // 207\r
- KEENCLIMBEDGER2SPR, // 208\r
- KEENCLIMBEDGER3SPR, // 209\r
- KEENCLIMBEDGER4SPR, // 210\r
- KEENPOGOR1SPR, // 211\r
- KEENPOGOR2SPR, // 212\r
- KEENPOGOL1SPR, // 213\r
- KEENPOGOL2SPR, // 214\r
- DROPSPLASH1SPR, // 215\r
- DROPSPLASH2SPR, // 216\r
- DROPSPLASH3SPR, // 217\r
- BONUS100UPSPR, // 218\r
- BONUS100SPR, // 219\r
- BONUS200SPR, // 220\r
- BONUS500SPR, // 221\r
- BONUS1000SPR, // 222\r
- BONUS2000SPR, // 223\r
- BONUS5000SPR, // 224\r
- BONUS1UPSPR, // 225\r
- BONUSCLIPSPR, // 226\r
- END_LUMP(KEEN_LUMP_END, __KEENEND)\r
-\r
- START_LUMP(SUGAR1_LUMP_START, __SUGAR1START)\r
- SUGAR1ASPR, // 227\r
- SUGAR1BSPR, // 228\r
- END_LUMP(SUGAR1_LUMP_END, __SUGAR1END)\r
-\r
- START_LUMP(SUGAR2_LUMP_START, __SUGAR2START)\r
- SUGAR2ASPR, // 229\r
- SUGAR2BSPR, // 230\r
- END_LUMP(SUGAR2_LUMP_END, __SUGAR2END)\r
-\r
- START_LUMP(SUGAR3_LUMP_START, __SUGAR3START)\r
- SUGAR3ASPR, // 231\r
- SUGAR3BSPR, // 232\r
- END_LUMP(SUGAR3_LUMP_END, __SUGAR3END)\r
-\r
- START_LUMP(SUGAR4_LUMP_START, __SUGAR4START)\r
- SUGAR4ASPR, // 233\r
- SUGAR4BSPR, // 234\r
- END_LUMP(SUGAR4_LUMP_END, __SUGAR4END)\r
-\r
- START_LUMP(SUGAR5_LUMP_START, __SUGAR5START)\r
- SUGAR5ASPR, // 235\r
- SUGAR5BSPR, // 236\r
- END_LUMP(SUGAR5_LUMP_END, __SUGAR5END)\r
-\r
- START_LUMP(SUGAR6_LUMP_START, __SUGAR6START)\r
- SUGAR6ASPR, // 237\r
- SUGAR6BSPR, // 238\r
- END_LUMP(SUGAR6_LUMP_END, __SUGAR6END)\r
-\r
- START_LUMP(ONEUP_LUMP_START, __ONEUPSTART)\r
- ONEUPASPR, // 239\r
- ONEUPBSPR, // 240\r
- END_LUMP(ONEUP_LUMP_END, __ONEUPEND)\r
-\r
- DOORSPR, // 241\r
-\r
- START_LUMP(KEYGEM_LUMP_START, __KEYGEMSTART)\r
- REDGEM1SPR, // 242\r
- REDGEM2SPR, // 243\r
- YELLOWGEM1SPR, // 244\r
- YELLOWGEM2SPR, // 245\r
- BLUEGEM1SPR, // 246\r
- BLUEGEM2SPR, // 247\r
- GREENGEM1SPR, // 248\r
- GREENGEM2SPR, // 249\r
- BONUSGEMSPR, // 250\r
- END_LUMP(KEYGEM_LUMP_END, __KEYGEMEND)\r
-\r
- START_LUMP(AMMO_LUMP_START, __AMMOSTART)\r
- STUNCLIP1SPR, // 251\r
- STUNCLIP2SPR, // 252\r
- END_LUMP(AMMO_LUMP_END, __AMMOEND)\r
-\r
- SCOREBOXSPR, // 253\r
-\r
- START_LUMP(WORLDKEEN_LUMP_START, __WORLDKEENSTART)\r
- WORLDKEENL1SPR, // 254\r
- WORLDKEENL2SPR, // 255\r
- WORLDKEENL3SPR, // 256\r
- WORLDKEENR1SPR, // 257\r
- WORLDKEENR2SPR, // 258\r
- WORLDKEENR3SPR, // 259\r
- WORLDKEENU1SPR, // 260\r
- WORLDKEENU2SPR, // 261\r
- WORLDKEENU3SPR, // 262\r
- WORLDKEEND1SPR, // 263\r
- WORLDKEEND2SPR, // 264\r
- WORLDKEEND3SPR, // 265\r
- WORLDKEENDR1SPR, // 266\r
- WORLDKEENDR2SPR, // 267\r
- WORLDKEENDR3SPR, // 268\r
- WORLDKEENDL1SPR, // 269\r
- WORLDKEENDL2SPR, // 270\r
- WORLDKEENDL3SPR, // 271\r
- WORLDKEENUL1SPR, // 272\r
- WORLDKEENUL2SPR, // 273\r
- WORLDKEENUL3SPR, // 274\r
- WORLDKEENUR1SPR, // 275\r
- WORLDKEENUR2SPR, // 276\r
- WORLDKEENUR3SPR, // 277\r
- WORLDKEENWAVE1SPR, // 278\r
- WORLDKEENWAVE2SPR, // 279\r
- WORLDKEENSWIMU1SPR, // 280\r
- WORLDKEENSWIMU2SPR, // 281\r
- WORLDKEENSWIMR1SPR, // 282\r
- WORLDKEENSWIMR2SPR, // 283\r
- WORLDKEENSWIMD1SPR, // 284\r
- WORLDKEENSWIMD2SPR, // 285\r
- WORLDKEENSWIML1SPR, // 286\r
- WORLDKEENSWIML2SPR, // 287\r
- WORLDKEENSWIMUR1SPR, // 288\r
- WORLDKEENSWIMUR2SPR, // 289\r
- WORLDKEENSWIMDR1SPR, // 290\r
- WORLDKEENSWIMDR2SPR, // 291\r
- WORLDKEENSWIMDL1SPR, // 292\r
- WORLDKEENSWIMDL2SPR, // 293\r
- WORLDKEENSWIMUL1SPR, // 294\r
- WORLDKEENSWIMUL2SPR, // 295\r
- WOLRDKEENRIDE1SPR, // 296\r
- WOLRDKEENRIDE2SPR, // 297\r
- FLAGFLIP1SPR, // 298\r
- FLAGFLIP2SPR, // 299\r
- FLAGFLIP3SPR, // 300\r
- FLAGFLIP4SPR, // 301\r
- FLAGFLIP5SPR, // 302\r
- FLAGFALL1SPR, // 303\r
- FLAGFALL2SPR, // 304\r
- FLAGFLAP1SPR, // 305\r
- FLAGFLAP2SPR, // 306\r
- FLAGFLAP3SPR, // 307\r
- FLAGFLAP4SPR, // 308\r
- END_LUMP(WORLDKEEN_LUMP_END, __WORLDKEENEND)\r
-\r
- START_LUMP(SCUBAKEEN_LUMP_START, __SCUBAKEENSTART)\r
- SCUBAKEENL1SPR, // 309\r
- SCUBAKEENL2SPR, // 310\r
- SCUBAKEENR1SPR, // 311\r
- SCUBAKEENR2SPR, // 312\r
- SCUBAKEENDEAD1SPR, // 313\r
- SCUBAKEENDEAD2SPR, // 314\r
- END_LUMP(SCUBAKEEN_LUMP_END, __SCUBAKEENEND)\r
-\r
- START_LUMP(SLUG_LUMP_START, __SLUGSTART)\r
- SLUGWALKR1SPR, // 315\r
- SLUGWALKR2SPR, // 316\r
- SLUGPISSRSPR, // 317\r
- SLUGSTUN1SPR, // 318\r
- SLUGSTUN2SPR, // 319\r
- SLUGWALKL1SPR, // 320\r
- SLUGWALKL2SPR, // 321\r
- SLUGPISSLSPR, // 322\r
- SLUGSLIME1SPR, // 323\r
- SLUGSLIME2SPR, // 324\r
- END_LUMP(SLUG_LUMP_END, __SLUGEND)\r
-\r
- START_LUMP(MADMUSHROOM_LUMP_START, __MADMUSHROOMSTART)\r
- MADMUSHROOML1SPR, // 325\r
- MADMUSHROOML2SPR, // 326\r
- MADMUSHROOMR1SPR, // 327\r
- MADMUSHROOMR2SPR, // 328\r
- END_LUMP(MADMUSHROOM_LUMP_END, __MADMUSHROOMEND)\r
-\r
- START_LUMP(LINDSEY_LUMP_START, __LINDSEYSTART)\r
- LINDSEY1SPR, // 329\r
- LINDSEY2SPR, // 330\r
- LINDSEY3SPR, // 331\r
- LINDSEY4SPR, // 332\r
- END_LUMP(LINDSEY_LUMP_END, __LINDSEYEND)\r
-\r
- START_LUMP(INCHWORM_LUMP_START, __INCHWORMSTART)\r
- INCHWORMR1SPR, // 333\r
- INCHWORMR2SPR, // 334\r
- INCHWORML1SPR, // 335\r
- INCHWORML2SPR, // 336\r
- FOOTSPR, // 337\r
- END_LUMP(INCHWORM_LUMP_END, __INCHWORMEND)\r
-\r
- START_LUMP(EATER_LUMP_START, __EATERSTART)\r
- EATERSTAND1SPR, // 338\r
- EATERSTAND2SPR, // 339\r
- EATERJUMPR1SPR, // 340\r
- EATERJUMPR2SPR, // 341\r
- EATERJUMPR3SPR, // 342\r
- EATERJUMPL1SPR, // 343\r
- EATERJUMPL2SPR, // 344\r
- EATERJUMPL3SPR, // 345\r
- EATENBONUS1SPR, // 346\r
- EATENBONUS2SPR, // 347\r
- EATENBONUS3SPR, // 348\r
- EATENBONUS4SPR, // 349\r
- SMOKE1SPR, // 350\r
- SMOKE2SPR, // 351\r
- SMOKE3SPR, // 352\r
- SMOKE4SPR, // 353\r
- SMOKE5SPR, // 354\r
- EATERSTUNSPR, // 355\r
- END_LUMP(EATER_LUMP_END, __EATEREND)\r
-\r
- START_LUMP(COUNCIL_LUMP_START, __COUINCILSTART)\r
- COUNCILWALKR1SPR, // 356\r
- COUNCILWALKR2SPR, // 357\r
- COUNCILWALKL1SPR, // 358\r
- COUNCILWALKL2SPR, // 359\r
- COUNCILTHINKLSPR, // 360\r
- COUNCILTHINKRSPR, // 361\r
- END_LUMP(COUNCIL_LUMP_END, __COUNCILEND)\r
-\r
- START_LUMP(EGG_LUMP_START, __EGGSTART)\r
- EGGSPR, // 362\r
- EGGBROKESPR, // 363\r
- EGGCHIP1SPR, // 364\r
- EGGCHIP2SPR, // 365\r
- EGGCHIP3SPR, // 366\r
- END_LUMP(EGG_LUMP_END, __EGGEND)\r
-\r
- START_LUMP(EGGBIRD_LUMP_START, __EGGBIRDSTART)\r
- BIRDWALKR1SPR, // 367\r
- BIRDWALKR2SPR, // 368\r
- BIRDWALKR3SPR, // 369\r
- BIRDWALKR4SPR, // 370\r
- BIRDWALKL1SPR, // 371\r
- BIRDWALKL2SPR, // 372\r
- BIRDWALKL3SPR, // 373\r
- BIRDWALKL4SPR, // 374\r
- BIRDFLY1SPR, // 375\r
- BIRDFLY2SPR, // 376\r
- BIRDFLY3SPR, // 377\r
- BIRDFLY4SPR, // 378\r
- BIRDSTUNSPR, // 379\r
- END_LUMP(EGGBIRD_LUMP_END, __EGGBIRDEND)\r
-\r
- START_LUMP(DARTS_LUMP_START, __DARTSSTART)\r
- DARTU1SPR, // 380\r
- DARTU2SPR, // 381\r
- DARTD1SPR, // 382\r
- DARTD2SPR, // 383\r
- DARTR1SPR, // 384\r
- DARTR2SPR, // 385\r
- DARTL1SPR, // 386\r
- DARTL2SPR, // 387\r
- END_LUMP(DARTS_LUMP_END, __DARTSEND)\r
-\r
- START_LUMP(MIMROCK_LUMP_START, __MIMROCKSTART)\r
- MIMROCKSPR, // 388\r
- MIMROCKWALKL1SPR, // 389\r
- MIMROCKWALKL2SPR, // 390\r
- MIMROCKWALKL3SPR, // 391\r
- MIMROCKWALKL4SPR, // 392\r
- MIMROCKWALKR1SPR, // 393\r
- MIMROCKWALKR2SPR, // 394\r
- MIMROCKWALKR3SPR, // 395\r
- MIMROCKWALKR4SPR, // 396\r
- MIMROCKJUMPR1SPR, // 397\r
- MIMROCKJUMPR2SPR, // 398\r
- MIMROCKJUMPR3SPR, // 399\r
- MIMROCKJUMPL1SPR, // 400\r
- MIMROCKJUMPL2SPR, // 401\r
- MIMROCKJUMPL3SPR, // 402\r
- MINROCKSTUNSPR, // 403\r
- END_LUMP(MIMROCK_LUMP_END, __MIMROCKEND)\r
-\r
- START_LUMP(DOPEFISH_LUMP_START, __DOPEFISHSTART)\r
- DOPEFISHSWIMR1SPR, // 404\r
- DOPEFISHSWIMR2SPR, // 405\r
- DOPEFISHHUNGRYRSPR, // 406\r
- DOPEFISHBURP1SPR, // 407\r
- DOPEFISHBURP2SPR, // 408\r
- BIGBUBBLE1SPR, // 409\r
- BIGBUBBLE2SPR, // 410\r
- BIGBUBBLE3SPR, // 411\r
- BIGBUBBLE4SPR, // 412\r
- SMALLBUBBLE1SPR, // 413\r
- SMALLBUBBLE2SPR, // 414\r
- SMALLBUBBLE3SPR, // 415\r
- SMALLBUBBLE4SPR, // 416\r
- MEDIUMBUBBLESPR, // 417\r
- DOPEFISHSWIML1SPR, // 418\r
- DOPEFISHSWIML2SPR, // 419\r
- DOPEFISHHUNGRYLSPR, // 420\r
- END_LUMP(DOPEFISH_LUMP_END, __DOPEFISHEND)\r
-\r
- START_LUMP(SCHOOLFISH_LUMP_START, __SCHOOLFISHSTART)\r
- SCHOOLFISHL1SPR, // 421\r
- SCHOOLFISHL2SPR, // 422\r
- SCHOOLFISHR1SPR, // 423\r
- SCHOOLFISHR2SPR, // 424\r
- END_LUMP(SCHOOLFISH_LUMP_END, __SCHOOLFISHEND)\r
-\r
- START_LUMP(ARACHNUT_LUMP_START, __ARACHNUTSTART)\r
- ARACHNUTWALK1SPR, // 425\r
- ARACHNUTWALK2SPR, // 426\r
- ARACHNUTWALK3SPR, // 427\r
- ARACHNUTWALK4SPR, // 428\r
- ARACHNUTSTUNSPR, // 429\r
- END_LUMP(ARACHNUT_LUMP_END, __ARACHNUTEND)\r
-\r
- SCUBASPR, // 430\r
-\r
- START_LUMP(SPRITE_LUMP_START, __SPRITESTART)\r
- SPRITEFLOATSPR, // 431\r
- SPRITEAIMLSPR, // 432\r
- SPRITESHOOTLSPR, // 433\r
- SPRITEAIMRSPR, // 434\r
- SPRITESHOOTRSPR, // 435\r
- SPRITESHOT1SPR, // 436\r
- SPRITESHOT2SPR, // 437\r
- SPRITESHOT3SPR, // 438\r
- SPRITESHOT4SPR, // 439\r
- END_LUMP(SPRITE_LUMP_END, __SPRITEEND)\r
-\r
- START_LUMP(MINE_LUMP_START, __MINESTART)\r
- MINESPR, // 440\r
- MINEEXPLODE1SPR, // 441\r
- MINEEXPLODE2SPR, // 442\r
- END_LUMP(MINE_LUMP_END, __MINEEND)\r
-\r
- START_LUMP(SKYPEST_LUMP_START, __SKYPESTSTART)\r
- SKYPESTFLYL1SPR, // 443\r
- SKYPESTFLYL2SPR, // 444\r
- SKYPESTFLYR1SPR, // 445\r
- SKYPESTFLYR2SPR, // 446\r
- SKYPESTSIT1SPR, // 447\r
- SKYPESTSIT2SPR, // 448\r
- SKYPESTSIT3SPR, // 449\r
- SKYPESTSIT4SPR, // 450\r
- SKYPESTSIT5SPR, // 451\r
- SKYPESTSIT6SPR, // 452\r
- SKYPESTSIT7SPR, // 453\r
- SKYPESTSIT8SPR, // 454\r
- SKYPESTSIT9SPR, // 455\r
- SKYPESTSQUASHEDSPR, // 456\r
- END_LUMP(SKYPEST_LUMP_END, __SKYPESTEND)\r
-\r
- START_LUMP(WORMOUTH_LUMP_START, __WORMOUTHSTART)\r
- WORMOUTHSPR, // 457\r
- WORMOUTHPEEKR1SPR, // 458\r
- WORMOUTHPEEKR2SPR, // 459\r
- WORMOUTHPEEKL1SPR, // 460\r
- WORMOUTHPEEKL2SPR, // 461\r
- WORMOUTHBITER1SPR, // 462\r
- WORMOUTHBITER2SPR, // 463\r
- WORMOUTHBITER3SPR, // 464\r
- WORMOUTHBITEL1SPR, // 465\r
- WORMOUTHBITEL2SPR, // 466\r
- WORMOUTHBITEL3SPR, // 467\r
- WORMOUTHSTUNSPR, // 468\r
- END_LUMP(WORMOUTH_LUMP_END, __WORMOUTHEND)\r
-\r
- START_LUMP(LICK_LUMP_START, __LICKSTART)\r
- LICKMOVER1SPR, // 469\r
- LICKMOVER2SPR, // 470\r
- LICKMOVER3SPR, // 471\r
- LICKMOVER4SPR, // 472\r
- LICKMOVEL1SPR, // 473\r
- LICKMOVEL2SPR, // 474\r
- LICKMOVEL3SPR, // 475\r
- LICKMOVEL4SPR, // 476\r
- LICKATTACKR1SPR, // 477\r
- LICKATTACKR2SPR, // 478\r
- LICKATTACKR3SPR, // 479\r
- LICKATTACKL1SPR, // 480\r
- LICKATTACKL2SPR, // 481\r
- LICKATTACKL3SPR, // 482\r
- LICKSTUNSPR, // 483\r
- END_LUMP(LICK_LUMP_END, __LICKEND)\r
-\r
- START_LUMP(PLATFORM_LUMP_START, __PLATFORMSTART)\r
- PLATFORMSPR, // 484\r
- PLATSIDETHRUST1SPR, // 485\r
- PLATSIDETHRUST2SPR, // 486\r
- PLATRTHRUST1SPR, // 487\r
- PLATRTHRUST2SPR, // 488\r
- PLATLTHRUST1SPR, // 489\r
- PLATLTHRUST2SPR, // 490\r
- END_LUMP(PLATFORM_LUMP_END, __PLATFORMEND)\r
-\r
- START_LUMP(BOUNDER_LUMP_START, __BOUNDERSTART)\r
- BOUNDERL1SPR, // 491\r
- BOUNDERL2SPR, // 492\r
- BOUNDERR1SPR, // 493\r
- BOUNDERR2SPR, // 494\r
- BOUNDERC1SPR, // 495\r
- BOUNDERC2SPR, // 496\r
- BOUNDERSTUNSPR, // 497\r
- END_LUMP(BOUNDER_LUMP_END, __BOUNDEREND)\r
-\r
- START_LUMP(THUNDERCLOUD_LUMP_START, __THUNDERCLOUDSTART)\r
- CLOUDSPR, // 498\r
- CLOUDACTIVESPR, // 499\r
- CLOUDCHARGESPR, // 500\r
- BOLT1SPR, // 501\r
- BOLT2SPR, // 502\r
- END_LUMP(THUNDERCLOUD_LUMP_END, __THUNDERCLOUDEND)\r
-\r
- START_LUMP(BERKELOID_LUMP_START, __BERKELOIDSTART)\r
- BERKEWALKL1SPR, // 503\r
- BERKEWALKL2SPR, // 504\r
- BERKEWALKL3SPR, // 505\r
- BERKEWALKL4SPR, // 506\r
- BERKEWALKR1SPR, // 507\r
- BERKEWALKR2SPR, // 508\r
- BERKEWALKR3SPR, // 509\r
- BERKEWALKR4SPR, // 510\r
- BERKETHROWL1SPR, // 511\r
- BERKETHROWL2SPR, // 512\r
- BERKETHROWR1SPR, // 513\r
- BERKETHROWR2SPR, // 514\r
- FIREBALL1SPR, // 515\r
- FIREBALL2SPR, // 516\r
- FIREBALL3SPR, // 517\r
- FIREBALL4SPR, // 518\r
- END_LUMP(BERKELOID_LUMP_END, __BERKELOIDEND)\r
-\r
- START_LUMP(MOON_LUMP_START, __MOONSTART)\r
- KEENMOON1SPR, // 519\r
- KEENMOON2SPR, // 520\r
- END_LUMP(MOON_LUMP_END, __MOONEND)\r
-\r
- //\r
- // TILES (these don't need names)\r
- //\r
-\r
- LASTTILE=STARTEXTERNS-1,\r
-\r
- //\r
- // EXTERNS\r
- //\r
-\r
- ORDERSCREEN, // 4735\r
- BIGCOMMANDER, // 4736\r
- BIGKEEN, // 4737\r
- OUTOFMEM, // 4738\r
-\r
- //texts\r
- T_HELPART, // 4739\r
- T_STORYART, // 4740\r
- T_CONTRART, // 4741\r
- T_IDART, // 4742\r
- T_ENDART, // 4743\r
- T_DEMOART, // 4744\r
- T_ORDERART, // 4745\r
-\r
- //demos\r
- DEMO0, // 4746\r
- DEMO1, // 4747\r
- DEMO2, // 4748\r
- DEMO3, // 4749\r
- DEMO4, // 4750\r
-\r
- NUMGRCHUNKS\r
-} graphicnums;\r
-\r
-#undef START_LUMP\r
-#undef END_LUMP\r
-\r
-#endif //__GFX_H__
\ No newline at end of file
+++ /dev/null
-;\r
-; Equates for all .ASM files\r
-;\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-INCLUDE "GFXC_CK4.EQU"\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-CGAGR = 1\r
-EGAGR = 2\r
-VGAGR = 3\r
-\r
-GRMODE = CGAGR\r
-PROFILE = 0 ; 1=keep stats on tile drawing\r
-\r
-SC_INDEX = 03C4h\r
-SC_RESET = 0\r
-SC_CLOCK = 1\r
-SC_MAPMASK = 2\r
-SC_CHARMAP = 3\r
-SC_MEMMODE = 4\r
-\r
-CRTC_INDEX = 03D4h\r
-CRTC_H_TOTAL = 0\r
-CRTC_H_DISPEND = 1\r
-CRTC_H_BLANK = 2\r
-CRTC_H_ENDBLANK = 3\r
-CRTC_H_RETRACE = 4\r
-CRTC_H_ENDRETRACE = 5\r
-CRTC_V_TOTAL = 6\r
-CRTC_OVERFLOW = 7\r
-CRTC_ROWSCAN = 8\r
-CRTC_MAXSCANLINE = 9\r
-CRTC_CURSORSTART = 10\r
-CRTC_CURSOREND = 11\r
-CRTC_STARTHIGH = 12\r
-CRTC_STARTLOW = 13\r
-CRTC_CURSORHIGH = 14\r
-CRTC_CURSORLOW = 15\r
-CRTC_V_RETRACE = 16\r
-CRTC_V_ENDRETRACE = 17\r
-CRTC_V_DISPEND = 18\r
-CRTC_OFFSET = 19\r
-CRTC_UNDERLINE = 20\r
-CRTC_V_BLANK = 21\r
-CRTC_V_ENDBLANK = 22\r
-CRTC_MODE = 23\r
-CRTC_LINECOMPARE = 24\r
-\r
-\r
-GC_INDEX = 03CEh\r
-GC_SETRESET = 0\r
-GC_ENABLESETRESET = 1\r
-GC_COLORCOMPARE = 2\r
-GC_DATAROTATE = 3\r
-GC_READMAP = 4\r
-GC_MODE = 5\r
-GC_MISCELLANEOUS = 6\r
-GC_COLORDONTCARE = 7\r
-GC_BITMASK = 8\r
-\r
-ATR_INDEX = 03c0h\r
-ATR_MODE = 16\r
-ATR_OVERSCAN = 17\r
-ATR_COLORPLANEENABLE = 18\r
-ATR_PELPAN = 19\r
-ATR_COLORSELECT = 20\r
-\r
-STATUS_REGISTER_1 = 03dah\r
-\r
-\r
-MACRO WORDOUT\r
- out dx,ax\r
-ENDM\r
-\r
-if 0\r
-\r
-MACRO WORDOUT\r
- out dx,al\r
- inc dx\r
- xchg al,ah\r
- out dx,al\r
- dec dx\r
- xchg al,ah\r
-ENDM\r
-\r
-endif\r
-\r
-UPDATEWIDE = 22\r
-UPDATEHIGH = 14\r
-\r
-;\r
-; tile info offsets from segment tinf\r
-;\r
-\r
-ANIM = 402\r
-SPEED = (ANIM+NUMTILE16)\r
-\r
-NORTHWALL = (SPEED+NUMTILE16)\r
-EASTWALL = (NORTHWALL+NUMTILE16M)\r
-SOUTHWALL = (EASTWALL+NUMTILE16M)\r
-WESTWALL = (SOUTHWALL+NUMTILE16M)\r
-MANIM = (WESTWALL+NUMTILE16M)\r
-INTILE = (MANIM+NUMTILE16M)\r
-MSPEED = (INTILE+NUMTILE16M)\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-SCREENWIDTH = 64\r
-ENDIF\r
-IFE GRMODE-CGAGR\r
-SCREENWIDTH = 128\r
-ENDIF\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_GLOB.H\r
-\r
-\r
-#include <ALLOC.H>\r
-#include <CTYPE.H>\r
-#include <DOS.H>\r
-#include <ERRNO.H>\r
-#include <FCNTL.H>\r
-#include <IO.H>\r
-#include <MEM.H>\r
-#include <PROCESS.H>\r
-#include <STDIO.H>\r
-#include <STDLIB.H>\r
-#include <STRING.H>\r
-#include <SYS\STAT.H>\r
-\r
-#define __ID_GLOB__\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define KEEN\r
-#define KEEN4\r
-\r
-#define EXTENSION "CK4"\r
-\r
-extern char far introscn;\r
-\r
-#include "GFXC_CK4.H"\r
-#include "AUDIOCK4.H"\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define TEXTGR 0\r
-#define CGAGR 1\r
-#define EGAGR 2\r
-#define VGAGR 3\r
-\r
-#define GRMODE CGAGR\r
-\r
-#if GRMODE == EGAGR\r
-#define GREXT "EGA"\r
-#endif\r
-#if GRMODE == CGAGR\r
-#define GREXT "CGA"\r
-#endif\r
-\r
-//#define PROFILE\r
-\r
-//\r
-// ID Engine\r
-// Types.h - Generic types, #defines, etc.\r
-// v1.0d1\r
-//\r
-\r
-#ifndef __TYPES__\r
-#define __TYPES__\r
-\r
-typedef enum {false,true} boolean;\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long longword;\r
-typedef byte * Ptr;\r
-\r
-typedef struct\r
- {\r
- int x,y;\r
- } Point;\r
-typedef struct\r
- {\r
- Point ul,lr;\r
- } Rect;\r
-\r
-#define nil ((void *)0)\r
-\r
-#endif\r
-\r
-#include "ID_MM.H"\r
-#include "ID_CA.H"\r
-#include "ID_VW.H"\r
-#include "ID_RF.H"\r
-#include "ID_IN.H"\r
-#include "ID_SD.H"\r
-#include "ID_US.H"\r
-\r
-\r
-void Quit (char *error); // defined in user program\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __AUDIO_H__\r
-#define __AUDIO_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// MUSE Header for .CK5\r
-//\r
-/////////////////////////////////////////////////\r
-\r
-#define NUMSOUNDS LASTSOUND\r
-#define NUMSNDCHUNKS ((3*LASTSOUND)+LASTMUSIC)\r
-\r
-//\r
-// Sound names & indexes\r
-//\r
-typedef enum {\r
- SND_WORLDWALK1, // 0\r
- SND_WORLDWALK2, // 1\r
- SND_JUMP, // 2\r
- SND_LAND, // 3\r
- SND_KEENFIRE, // 4\r
- SND_MINEEXPLODE, // 5\r
- SND_SLICESTARBOUNCE, // 6\r
- SND_POGOBOUNCE, // 7\r
- SND_GETPOINTS, // 8\r
- SND_GETAMMO, // 9\r
- SND_GETWATER, // 10\r
- SND_11, // 11\r
- SND_ENTERLEVEL, // 12\r
- SND_LEVELDONE, // 13\r
- SND_NOWAY, // 14\r
- SND_HELMETHIT, // 15\r
- SND_BOUNCE, // 16\r
- SND_EXTRAKEEN, // 17\r
- SND_OPENCARDDOOR, // 18\r
- SND_GETKEY, // 19\r
- SND_PLUMMET, // 20\r
- SND_USESWITCH, // 21\r
- SND_22, // 22\r
- SND_KEENDEAD, // 23\r
- SND_24, // 24\r
- SND_SHOTEXPLODE, // 25\r
- SND_26, // 26\r
- SND_SPIROGRAB, // 27\r
- SND_SPINDREDBOUNCE, // 28\r
- SND_ENEMYSHOT, // 29\r
- SND_ENEMYSHOTEXPLODE, // 30\r
- SND_AMPTONWALK1, // 31\r
- SND_AMPTONWALK2, // 32\r
- SND_AMPTONDIE, // 33\r
- SND_SHOWSTATUS, // 34\r
- SND_HIDESTATUS, // 35\r
- SND_SHELLEYEXPLODE, // 36\r
- SND_SPINDREDFLIP, // 37\r
- SND_MASTERATTACK, // 38\r
- SND_MASTERBLAST, // 39\r
- SND_SHIKADIATTACK, // 40\r
- SND_TELEPORT, // 41\r
- SND_SHOCKSHUNDBARK, // 42\r
- SND_FLAGSPIN, // 43\r
- SND_FLAGLAND, // 44\r
- SND_SHOCKBALLEXPLODE, // 45\r
- KEENPADDLESND, // 46\r
- BALLBOUNCESND, // 47\r
- COMPPADDLESND, // 48\r
- COMPSCOREDSND, // 49\r
- KEENSCOREDSND, // 50\r
- SND_51, // 51\r
- SND_BIGSPARK, // 52\r
- SND_GAMEOVER1, // 53\r
- SND_GAMEOVER2, // 54\r
- SND_GETKEYCARD, // 55\r
- SND_56, // 56\r
- SND_LANDONFUSE, // 57\r
- SND_SPARKYCHARGE, // 58\r
- SND_SPHEREFULBOUNCE, // 59\r
- SND_OPENDOOR, // 60\r
- SND_SPIROFLY, // 61\r
- SND_62, // 62\r
- SND_ELEVATORDOOR, // 63\r
- LASTSOUND\r
-} soundnames;\r
-\r
-#if LASTSOUND != 64\r
-#error bad sound enum!\r
-#endif\r
-\r
-#define NOWAYSND SND_NOWAY\r
-\r
-//\r
-// Base offsets\r
-//\r
-#define STARTPCSOUNDS 0\r
-#define STARTADLIBSOUNDS (STARTPCSOUNDS+NUMSOUNDS)\r
-#define STARTDIGISOUNDS (STARTADLIBSOUNDS+NUMSOUNDS)\r
-#define STARTMUSIC (STARTDIGISOUNDS+NUMSOUNDS)\r
-\r
-//\r
-// Music names & indexes\r
-//\r
-typedef enum {\r
- CAMEIN_MUS,\r
- HAVING_T_MUS,\r
- SKATING_MUS,\r
- SNOOPING_MUS,\r
- BAGPIPES_MUS,\r
- WEDNESDY_MUS,\r
- ROCK_ME_MUS,\r
- BREATHE_MUS,\r
- SHIKAIRE_MUS,\r
- SPHEREFUL_MUS,\r
- TIGHTER_MUS,\r
- ROBOROCK_MUS,\r
- FANFARE_MUS,\r
- FEARSOME_MUS,\r
- LASTMUSIC\r
-} musicnames;\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// Thanks for playing with MUSE!\r
-//\r
-/////////////////////////////////////////////////\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-;=====================================\r
-;\r
-; Graphics .EQU file for .CK5\r
-; not IGRAB-ed :)\r
-;\r
-;=====================================\r
-\r
-;INCLUDE "VERSION.EQU"\r
-\r
-;\r
-; Amount of each data item\r
-;\r
-NUMFONT = 3\r
-NUMFONTM = 0\r
-NUMPICM = 3\r
-NUMTILE8 = 108\r
-NUMTILE8M = 36\r
-NUMTILE32 = 0\r
-NUMTILE32M = 0\r
-\r
-;\r
-; Amount of each item in episode 5\r
-;\r
-NUMPICS = 93\r
-NUMSPRITES = 346\r
-NUMTILE16 = 1512\r
-NUMTILE16M = 2952\r
-NUMEXTERN = 15\r
-\r
-\r
-;\r
-; File offsets for data items\r
-;\r
-STRUCTPIC = 0\r
-STRUCTPICM = 1\r
-STRUCTSPRITE = 2\r
-\r
-STARTFONT = 3\r
-STARTFONTM = (STARTFONT+NUMFONT)\r
-STARTPICS = (STARTFONTM+NUMFONTM)\r
-STARTPICM = (STARTPICS+NUMPICS)\r
-STARTSPRITES = (STARTPICM+NUMPICM)\r
-STARTTILE8 = (STARTSPRITES+NUMSPRITES)\r
-STARTTILE8M = (STARTTILE8+1)\r
-STARTTILE16 = (STARTTILE8M+1)\r
-STARTTILE16M = (STARTTILE16+NUMTILE16)\r
-STARTTILE32 = (STARTTILE16M+NUMTILE16M)\r
-STARTTILE32M = (STARTTILE32+NUMTILE32)\r
-STARTEXTERN = (STARTTILE32M+NUMTILE32M)\r
-\r
-NUMCHUNKS = (STARTEXTERN+NUMEXTERN)\r
-\r
-;\r
-; Thank you for using IGRAB!\r
-;\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __GFX_H__\r
-#define __GFX_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-//////////////////////////////////////\r
-//\r
-// Graphics .H file for .CK5\r
-// not IGRAB-ed :)\r
-//\r
-//////////////////////////////////////\r
-\r
-//\r
-// Lump creation macros\r
-//\r
-\r
-#define START_LUMP(actualname, dummyname) actualname, dummyname=actualname-1,\r
-#define END_LUMP(actualname, dummyname) dummyname, actualname=dummyname-1,\r
-\r
-//\r
-// Amount of each data item\r
-//\r
-\r
-//common numbers:\r
-#define NUMCHUNKS NUMGRCHUNKS\r
-#define NUMFONT 3\r
-#define NUMFONTM 0\r
-#define NUMPICM 3\r
-#define NUMTILE8 108 // BUG: only 104 tiles exist in EGAGRAPH!\r
-#define NUMTILE8M 36 // BUG: only 20 tiles exist in EGAGRAPH!\r
-#define NUMTILE32 0\r
-#define NUMTILE32M 0\r
-\r
-//episode-specific numbers:\r
-#define NUMPICS 93\r
-#define NUMSPRITES 346\r
-#define NUMTILE16 1512\r
-#define NUMTILE16M 2952\r
-#define NUMEXTERNS 17\r
-\r
-//\r
-// File offsets for data items\r
-//\r
-#define STRUCTPIC 0\r
-#define STRUCTPICM 1\r
-#define STRUCTSPRITE 2\r
-\r
-#define STARTFONT 3\r
-#define STARTFONTM (STARTFONT+NUMFONT)\r
-#define STARTPICS (STARTFONTM+NUMFONTM)\r
-#define STARTPICM (STARTPICS+NUMPICS)\r
-#define STARTSPRITES (STARTPICM+NUMPICM)\r
-#define STARTTILE8 (STARTSPRITES+NUMSPRITES)\r
-#define STARTTILE8M (STARTTILE8+1)\r
-#define STARTTILE16 (STARTTILE8M+1)\r
-#define STARTTILE16M (STARTTILE16+NUMTILE16)\r
-#define STARTTILE32 (STARTTILE16M+NUMTILE16M)\r
-#define STARTTILE32M (STARTTILE32+NUMTILE32)\r
-#define STARTEXTERNS (STARTTILE32M+NUMTILE32M)\r
-\r
-typedef enum {\r
- // Lump Start\r
-\r
- LASTFONT=STARTPICS-1,\r
-\r
- START_LUMP(HELP_LUMP_START, __HELPSTART)\r
- H_HELPPIC, // 6\r
- H_LARROWPIC, // 7\r
- H_RARROWPIC, // 8\r
- H_ESCPIC, // 9\r
- H_ENTERPIC, // 10\r
- H_BOTTOMINSTRPIC, // 11\r
- H_GUMPIC, // 12\r
- H_MARSHMALLOWPIC, // 13\r
- H_CHOCMILKPIC, // 14\r
- H_TARTSTIXPIC, // 15\r
- H_STOOPIESPIC, // 16\r
- H_SUGARPIC, // 17\r
- H_VITALINPIC, // 18\r
- H_STUNNERPIC, // 19\r
- H_GEMPIC, // 20\r
- H_KEGPIC, // 21\r
- H_ENDOFTEXTPIC, // 22\r
- H_HELPMENUPIC, // 23\r
- H_HANDPIC, // 24\r
- H_ARROWSENTERESCPIC, // 25\r
- H_FLASHARROW1PIC, // 26\r
- H_FLASHARROW2PIC, // 27\r
- H_TOPWINDOWPIC, // 28\r
- H_LEFTWINDOWPIC, // 29\r
- H_RIGHTWINDOWPIC, // 30\r
- H_BOTTOMINFOPIC, // 31\r
- H_BOTTOMWINDOWPIC, // 32\r
- H_BARPIC, // 33\r
- H_SPARKYPIC, // 34\r
- H_AMPTONPIC, // 35\r
- H_SLICESTARPIC, // 36\r
- H_VOLTEFACEPIC, // 37\r
- H_ROBOREDPIC, // 38\r
- H_SHELLEYPIC, // 39\r
- H_SPIROGRIPPIC, // 40\r
- H_MINEPIC, // 41\r
- H_SPINDREDPIC, // 42\r
- H_SHIKADIPIC, // 43\r
- H_SPHEREFULPIC, // 44\r
- H_PETPIC, // 45\r
- H_MASTERPIC, // 46\r
- H_IDLOGOPIC, // 47\r
- H_STORY1PIC, // 48\r
- H_STORY2PIC, // 49\r
- H_STORY3PIC, // 50\r
- H_STORY4PIC, // 51\r
- H_VISAPIC, // 52\r
- H_MCPIC, // 53\r
- H_KEENTHUMBSUPPIC, // 54\r
- H_END1PIC, // 55\r
- H_END2PIC, // 56\r
- H_END3PIC, // 57\r
- H_END4PIC, // 58\r
- H_END5PIC, // 59\r
- H_END6PIC, // 60\r
- H_END7PIC, // 61\r
- H_END8PIC, // 62\r
- H_CONGRATSPIC, // 63\r
- H_KEENFEEDSPIC, // 64\r
- H_DOORCARDPIC, // 65\r
- H_KEEN6PIC, // 66\r
- END_LUMP(HELP_LUMP_END, __HELPEND)\r
-\r
- START_LUMP(CONTROLS_LUMP_START, __CONTROLSSTART)\r
- CP_MAINMENUPIC, // 67\r
- CP_NEWGAMEMENUPIC, // 68\r
- CP_LOADMENUPIC, // 69\r
- CP_SAVEMENUPIC, // 70\r
- CP_CONFIGMENUPIC, // 71\r
- CP_SOUNDMENUPIC, // 72\r
- CP_MUSICMENUPIC, // 73\r
- CP_KEYBOARDMENUPIC, // 74\r
- CP_KEYMOVEMENTPIC, // 75\r
- CP_KEYBUTTONPIC, // 76\r
- CP_JOYSTICKMENUPIC, // 77\r
- CP_OPTIONSMENUPIC, // 78\r
- CP_PADDLEWARPIC, // 79\r
- CP_QUITPIC, // 80\r
- CP_JOYSTICKPIC, // 81\r
- CP_MENUSCREENPIC, // 82\r
- END_LUMP(CONTROLS_LUMP_END, __COLTROLSEND)\r
-\r
- START_LUMP(_LUMP_START, __START)\r
- IDSOFTPIC, // 83\r
- PROGTEAMPIC, // 84\r
- ARTISTPIC, // 85\r
- DIRECTORPIC, // 86\r
- SW_BACKGROUNDPIC, // 87\r
- TITLEPICPIC, // 88\r
- MILKYWAYPIC, // 89\r
- END_LUMP(_LUMP_END, __END)\r
-\r
- START_LUMP(KEENTALK_LUMP_START, __KEENTALKSTART)\r
- KEENTALK1PIC, // 90\r
- KEENTALK2PIC, // 91\r
- END_LUMP(KEENTALK_LUMP_END, __KEENTALKEND)\r
-\r
- START_LUMP(LOADING_LUMP_START, __LOADINGSTART)\r
- KEENCOUNT1PIC, // 92\r
- KEENCOUNT2PIC, // 93\r
- KEENCOUNT3PIC, // 94\r
- KEENCOUNT4PIC, // 95\r
- KEENCOUNT5PIC, // 96\r
- KEENCOUNT6PIC, // 97\r
- END_LUMP(LOADING_LUMP_END, __LOADINGEND)\r
-\r
- GAMEOVERPIC, // 98\r
-\r
- CP_MENUMASKPICM, // 99\r
- CORDPICM, // 100\r
- METALPOLEPICM, // 101\r
-\r
- //\r
- // SPRITES\r
- //\r
-\r
- START_LUMP(PADDLE_LUMP_START, __PADDLESTART)\r
- PADDLESPR, // 102\r
- BALLSPR, // 103\r
- BALL1PIXELTOTHERIGHTSPR, // 104\r
- BALL2PIXELSTOTHERIGHTSPR, // 105\r
- BALL3PIXELSTOTHERIGHTSPR, // 106\r
- END_LUMP(PADDLE_LUMP_END, __PADDLEEND)\r
-\r
- DEMOPLAQUESPR, // 107\r
-\r
- START_LUMP(KEEN_LUMP_START, __KEENSTART)\r
- KEENSTANDRSPR, // 108\r
- KEENRUNR1SPR, // 109\r
- KEENRUNR2SPR, // 110\r
- KEENRUNR3SPR, // 111\r
- KEENRUNR4SPR, // 112\r
- KEENJUMPR1SPR, // 113\r
- KEENJUMPR2SPR, // 114\r
- KEENJUMPR3SPR, // 115\r
- KEENSTANDLSPR, // 116\r
- KEENRUNL1SPR, // 117\r
- KEENRUNL2SPR, // 118\r
- KEENRUNL3SPR, // 119\r
- KEENRUNL4SPR, // 120\r
- KEENJUMPL1SPR, // 121\r
- KEENJUMPL2SPR, // 122\r
- KEENJUMPL3SPR, // 123\r
- KEENLOOKUSPR, // 124\r
- KEENWAITR1SPR, // 125\r
- KEENWAITR2SPR, // 126\r
- KEENWAITR3SPR, // 127\r
- KEENSITREAD1SPR, // 128\r
- KEENSITREAD2SPR, // 129\r
- KEENSITREAD3SPR, // 130\r
- KEENSITREAD4SPR, // 131\r
- KEENREAD1SPR, // 132\r
- KEENREAD2SPR, // 133\r
- KEENREAD3SPR, // 134\r
- KEENSTOPREAD1SPR, // 135\r
- KEENSTOPREAD2SPR, // 136\r
- KEENLOOKD1SPR, // 137\r
- KEENLOOKD2SPR, // 138\r
- KEENONPLATSPR, // 139\r
- KEENDIE1SPR, // 140\r
- KEENDIE2SPR, // 141\r
- KEENSTUNSPR, // 142\r
- STUNSTARS1SPR, // 143\r
- STUNSTARS2SPR, // 144\r
- STUNSTARS3SPR, // 145\r
- KEENSHOOTLSPR, // 146\r
- KEENJLSHOOTLSPR, // 147\r
- KEENJSHOOTDSPR, // 148\r
- KEENJSHOOTUSPR, // 149\r
- KEENSHOOTUSPR, // 150\r
- KEENSHOOTRSPR, // 151\r
- KEENJRSHOOTRSPR, // 152\r
- STUN1SPR, // 153\r
- STUN2SPR, // 154\r
- STUN3SPR, // 155\r
- STUN4SPR, // 156\r
- STUNHIT1SPR, // 157\r
- STUNHIT2SPR, // 158\r
- KEENSHINNYR1SPR, // 159\r
- KEENSHINNYR2SPR, // 160\r
- KEENSHINNYR3SPR, // 161\r
- KEENSLIDED1SPR, // 162\r
- KEENSLIDED2SPR, // 163\r
- KEENSLIDED3SPR, // 164\r
- KEENSLIDED4SPR, // 165\r
- KEENSHINNYL1SPR, // 166\r
- KEENSHINNYL2SPR, // 167\r
- KEENSHINNYL3SPR, // 168\r
- KEENPLSHOOTUSPR, // 169\r
- KEENPRSHOOTUSPR, // 170\r
- KEENPRSHOOTDSPR, // 171\r
- KEENPLSHOOTDSPR, // 172\r
- KEENPSHOOTLSPR, // 173\r
- KEENPSHOOTRSPR, // 174\r
- KEENENTER1SPR, // 175\r
- KEENENTER2SPR, // 176\r
- KEENENTER3SPR, // 177\r
- KEENENTER4SPR, // 178\r
- KEENENTER5SPR, // 179\r
- KEENHANGLSPR, // 180\r
- KEENHANGRSPR, // 181\r
- KEENCLIMBEDGEL1SPR, // 182\r
- KEENCLIMBEDGEL2SPR, // 183\r
- KEENCLIMBEDGEL3SPR, // 184\r
- KEENCLIMBEDGEL4SPR, // 185\r
- KEENCLIMBEDGER1SPR, // 186\r
- KEENCLIMBEDGER2SPR, // 187\r
- KEENCLIMBEDGER3SPR, // 188\r
- KEENCLIMBEDGER4SPR, // 189\r
- KEENPOGOR1SPR, // 190\r
- KEENPOGOR2SPR, // 191\r
- KEENPOGOL1SPR, // 192\r
- KEENPOGOL2SPR, // 193\r
- BONUS100UPSPR, // 194\r
- BONUS100SPR, // 195\r
- BONUS200SPR, // 196\r
- BONUS500SPR, // 197\r
- BONUS1000SPR, // 198\r
- BONUS2000SPR, // 199\r
- BONUS5000SPR, // 200\r
- BONUS1UPSPR, // 201\r
- BONUSCLIPSPR, // 202\r
- VIVAPOOF1SPR, // 203\r
- VIVAPOOF2SPR, // 204\r
- VIVAPOOF3SPR, // 205\r
- VIVAPOOF4SPR, // 206\r
- END_LUMP(KEEN_LUMP_END, __KEENEND)\r
-\r
- START_LUMP(KEYCARD_LUMP_START, __KEYCARDSTART)\r
- DOORCARD1SPR, // 207\r
- DOORCARD2SPR, // 208\r
- BONUSCARDSPR, // 209\r
- END_LUMP(KEYCARD_LUMP_END, __KEYCARDEND)\r
-\r
- START_LUMP(SUGAR1_LUMP_START, __SUGAR1START)\r
- SUGAR1ASPR, // 210\r
- SUGAR1BSPR, // 211\r
- END_LUMP(SUGAR1_LUMP_END, __SUGAR1END)\r
-\r
- START_LUMP(SUGAR2_LUMP_START, __SUGAR2START)\r
- SUGAR2ASPR, // 212\r
- SUGAR2BSPR, // 213\r
- END_LUMP(SUGAR2_LUMP_END, __SUGAR2END)\r
-\r
- START_LUMP(SUGAR3_LUMP_START, __SUGAR3START)\r
- SUGAR3ASPR, // 214\r
- SUGAR3BSPR, // 215\r
- END_LUMP(SUGAR3_LUMP_END, __SUGAR3END)\r
-\r
- START_LUMP(SUGAR4_LUMP_START, __SUGAR4START)\r
- SUGAR4ASPR, // 216\r
- SUGAR4BSPR, // 217\r
- END_LUMP(SUGAR4_LUMP_END, __SUGAR4END)\r
-\r
- START_LUMP(SUGAR5_LUMP_START, __SUGAR5START)\r
- SUGAR5ASPR, // 218\r
- SUGAR5BSPR, // 219\r
- END_LUMP(SUGAR5_LUMP_END, __SUGAR5END)\r
-\r
- START_LUMP(SUGAR6_LUMP_START, __SUGAR6START)\r
- SUGAR6ASPR, // 220\r
- SUGAR6BSPR, // 221\r
- END_LUMP(SUGAR6_LUMP_END, __SUGAR6END)\r
-\r
- START_LUMP(ONEUP_LUMP_START, __ONEUPSTART)\r
- ONEUPASPR, // 222\r
- ONEUPBSPR, // 223\r
- END_LUMP(ONEUP_LUMP_END, __ONEUPEND)\r
-\r
- START_LUMP(KEYGEM_LUMP_START, __KEYGEMSTART)\r
- REDGEM1SPR, // 224\r
- REDGEM2SPR, // 225\r
- YELLOWGEM1SPR, // 226\r
- YELLOWGEM2SPR, // 227\r
- BLUEGEM1SPR, // 228\r
- BLUEGEM2SPR, // 229\r
- GREENGEM1SPR, // 230\r
- GREENGEM2SPR, // 231\r
- BONUSGEMSPR, // 232\r
- END_LUMP(KEYGEM_LUMP_END, __KEYGEMEND)\r
-\r
- START_LUMP(AMMO_LUMP_START, __AMMOSTART)\r
- STUNCLIP1SPR, // 233\r
- STUNCLIP2SPR, // 234\r
- END_LUMP(AMMO_LUMP_END, __AMMOEND)\r
-\r
- SCOREBOXSPR, // 235\r
-\r
- START_LUMP(LASER_LUMP_START, __LASERSTART)\r
- LASER1SPR, // 236\r
- LASER2SPR, // 237\r
- LASER3SPR, // 238\r
- LASER4SPR, // 239\r
- LASERHIT1SPR, // 240\r
- LASERHIT2SPR, // 241\r
- END_LUMP(LASER_LUMP_END, __LASEREND)\r
-\r
- START_LUMP(WORLDKEEN_LUMP_START, __WORLDKEENSTART)\r
- WORLDKEENL1SPR, // 242\r
- WORLDKEENL2SPR, // 243\r
- WORLDKEENL3SPR, // 244\r
- WORLDKEENR1SPR, // 245\r
- WORLDKEENR2SPR, // 246\r
- WORLDKEENR3SPR, // 247\r
- WORLDKEENU1SPR, // 248\r
- WORLDKEENU2SPR, // 249\r
- WORLDKEENU3SPR, // 250\r
- WORLDKEEND1SPR, // 251\r
- WORLDKEEND2SPR, // 252\r
- WORLDKEEND3SPR, // 253\r
- WORLDKEENDR1SPR, // 254\r
- WORLDKEENDR2SPR, // 255\r
- WORLDKEENDR3SPR, // 256\r
- WORLDKEENDL1SPR, // 257\r
- WORLDKEENDL2SPR, // 258\r
- WORLDKEENDL3SPR, // 259\r
- WORLDKEENUL1SPR, // 260\r
- WORLDKEENUL2SPR, // 261\r
- WORLDKEENUL3SPR, // 262\r
- WORLDKEENUR1SPR, // 263\r
- WORLDKEENUR2SPR, // 264\r
- WORLDKEENUR3SPR, // 265\r
- WORLDKEENWAVE1SPR, // 266\r
- WORLDKEENWAVE2SPR, // 267\r
- FLAGFLIP1SPR, // 268\r
- FLAGFLIP2SPR, // 269\r
- FLAGFLIP3SPR, // 270\r
- FLAGFLIP4SPR, // 271\r
- FLAGFLIP5SPR, // 272\r
- FLAGFALL1SPR, // 273\r
- FLAGFALL2SPR, // 274\r
- FLAGFLAP1SPR, // 275\r
- FLAGFLAP2SPR, // 276\r
- FLAGFLAP3SPR, // 277\r
- FLAGFLAP4SPR, // 278\r
- SHOOTINGSTAR1SPR, // 279\r
- SHOOTINGSTAR2SPR, // 280\r
- WORLDTELSPARK1SPR, // 281\r
- WORLDTELSPARK2SPR, // 282\r
- END_LUMP(WORLDKEEN_LUMP_END, __WORLDKEENEND)\r
-\r
- START_LUMP(FUSE_LUMP_START, __FUSESTART)\r
- FUSEFLASH1SPR, // 283\r
- FUSEFLASH2SPR, // 284\r
- FUSEFLASH3SPR, // 285\r
- END_LUMP(FUSE_LUMP_END, __FUSEEND)\r
-\r
- START_LUMP(STAREXPLODE_LUMP_START, __SMALLSPARKSTART)\r
- STAREXPLODE1SPR, // 286\r
- STAREXPLODE2SPR, // 287\r
- STAREXPLODE3SPR, // 288\r
- STAREXPLODE4SPR, // 289\r
- END_LUMP(STAREXPLODE_LUMP_END, __SMALLSPARKEND)\r
-\r
- START_LUMP(TELEPORT_LUMP_START, __TELEPORTSTART)\r
- TELEPORTSPARK1SPR, // 290\r
- TELEPORTSPARK2SPR, // 291\r
- TELEPORTZAP1SPR, // 292\r
- TELEPORTZAP2SPR, // 293\r
- END_LUMP(TELEPORT_LUMP_END, __TELEPORTEND)\r
-\r
- START_LUMP(SCOTTIE_LUMP_START, __KORATHSTART)\r
- SCOTTIEWALKL1SPR, // 294\r
- SCOTTIEWALKL2SPR, // 295\r
- SCOTTIEWALKL3SPR, // 296\r
- SCOTTIEWALKL4SPR, // 297\r
- SCOTTIEWALKR1SPR, // 298\r
- SCOTTIEWALKR2SPR, // 299\r
- SCOTTIEWALKR3SPR, // 300\r
- SCOTTIEWALKR4SPR, // 301\r
- SCOTTIEFACESPR, // 302\r
- SCOTTIESTUNSPR, // 303\r
- END_LUMP(SCOTTIE_LUMP_END, __KORATHEND)\r
-\r
- START_LUMP(MASTER_LUMP_START, __MASTERSTART)\r
- MASTER1SPR, // 304\r
- MASTER2SPR, // 305\r
- MASTER3SPR, // 306\r
- MASTER4SPR, // 307\r
- MASTERTELEPORT1SPR, // 308\r
- MASTERTELEPORT2SPR, // 309\r
- SHIKMASTERCASTRSPR, // 310\r
- SHIKMASTERCASTLSPR, // 311\r
- MASTERFLOORSPARK1SPR, // 312\r
- MASTERFLOORSPARK2SPR, // 313\r
- MASTERFLOORSPARK3SPR, // 314\r
- MASTERFLOORSPARK4SPR, // 315\r
- MASTERSHOT1SPR, // 316\r
- MASTERSHOT2SPR, // 317\r
- MASTERSHOT3SPR, // 318\r
- MASTERSHOT4SPR, // 319\r
- END_LUMP(MASTER_LUMP_END, __MASTEREND)\r
-\r
- START_LUMP(SHIKADI_LUMP_START, __SHIKADISTART)\r
- SHIKADI1SPR, // 320\r
- SHIKADI2SPR, // 321\r
- SHIKADI3SPR, // 322\r
- SHIKADI4SPR, // 323\r
- SHIKADIGRABRSPR, // 324\r
- SHIKADIGRABLSPR, // 325\r
- SHIKADIPOLESPARK1SPR, // 326\r
- SHIKADIPOLESPARK2SPR, // 327\r
- SHIKADIWALKR1SPR, // 328\r
- SHIKADIWALKR2SPR, // 329\r
- SHIKADIWALKR3SPR, // 330\r
- SHIKADIWALKR4SPR, // 331\r
- SHIKADIWALKL1SPR, // 332\r
- SHIKADIWALKL2SPR, // 333\r
- SHIKADIWALKL3SPR, // 334\r
- SHIKADIWALKL4SPR, // 335\r
- SHIKADISTUNSPR, // 336\r
- END_LUMP(SHIKADI_LUMP_END, __SHIKADIEND)\r
-\r
- START_LUMP(SHOCKSHUND_LUMP_START, __SHOCKSHUNDSTART)\r
- PETSIT1SPR, // 337\r
- PETSIT2SPR, // 338\r
- PETRUNR1SPR, // 339\r
- PETRUNR2SPR, // 340\r
- PETRUNR3SPR, // 341\r
- PETRUNR4SPR, // 342\r
- PETRUNL1SPR, // 343\r
- PETRUNL2SPR, // 344\r
- PETRUNL3SPR, // 345\r
- PETRUNL4SPR, // 346\r
- PETJUMPLSPR, // 347\r
- PETJUMPRSPR, // 348\r
- PETBARKR1SPR, // 349\r
- PETBARKR2SPR, // 350\r
- PETBARKL1SPR, // 351\r
- PETBARKL2SPR, // 352\r
- PETSTUNSPR, // 353\r
- PETSPARK1SPR, // 354\r
- PETSPARK2SPR, // 355\r
- PETSPARKHIT1SPR, // 356\r
- PETSPARKHIT2SPR, // 357\r
- END_LUMP(SHOCKSHUND_LUMP_END, __SHOCKSHUNDEND)\r
-\r
- START_LUMP(SPHEREFUL_LUMP_START, __SPHEREFULSTART)\r
- SPHEREFUL1SPR, // 358\r
- SPHEREFUL2SPR, // 359\r
- SPHEREFUL3SPR, // 360\r
- SPHEREFUL4SPR, // 361\r
- SPHEREGUARD1SPR, // 362\r
- SPHEREGUARD2SPR, // 363\r
- SPHEREGUARD3SPR, // 364\r
- SPHEREGUARD4SPR, // 365\r
- END_LUMP(SPHEREFUL_LUMP_END, __SPHEREFULEND)\r
-\r
- START_LUMP(SPARKY_LUMP_START, __SPARKYSTART)\r
- SPARKYWALKL1SPR, // 366\r
- SPARKYWALKL2SPR, // 367\r
- SPARKYWALKL3SPR, // 368\r
- SPARKYWALKL4SPR, // 369\r
- SPARKYTURN1SPR, // 370\r
- SPARKYTURN2SPR, // 371\r
- SPARKYTURN3SPR, // 372\r
- SPARKYWALKR1SPR, // 373\r
- SPARKYWALKR2SPR, // 374\r
- SPARKYWALKR3SPR, // 375\r
- SPARKYWALKR4SPR, // 376\r
- SPARKYSTUNSPR, // 377\r
- END_LUMP(SPARKY_LUMP_END, __SPARKYEND)\r
-\r
- START_LUMP(MINE_LUMP_START, __MINESTART)\r
- SHIKADIMINESPR, // 378\r
- SHIKADIMINEEYESPR, // 379\r
- SHIKADIMINEPULSE1SPR, // 380\r
- SHIKADIMINEPULSE2SPR, // 381\r
- SHIKADIMINEBOOM1SPR, // 382\r
- SHIKADIMINEBOOM2SPR, // 383\r
- SHIKADIMINEPIECESPR, // 384\r
- END_LUMP(MINE_LUMP_END, __MINEEND)\r
-\r
- START_LUMP(SLICESTAR_LUMP_START, __SLICESTARSTART)\r
- SLICESTARSPR, // 385\r
- SLICESTARBOOMSPR, // 386\r
- END_LUMP(SLICESTAR_LUMP_END, __SLICASTAREND)\r
-\r
- START_LUMP(ROBORED_LUMP_START, __ROBOREDSTART)\r
- ROBOREDRSPR, // 387\r
- ROBOREDLSPR, // 388\r
- ROBOSHOT1SPR, // 389\r
- ROBOSHOT2SPR, // 390\r
- ROBOSHOTHIT1SPR, // 391\r
- ROBOSHOTHIT2SPR, // 392\r
- END_LUMP(ROBORED_LUMP_END, __ROBOREDEND)\r
-\r
- START_LUMP(SPIRO_LUMP_START, __SPIROSTART)\r
- SPIROSITDSPR, // 393\r
- SPIROSITLSPR, // 394\r
- SPIROSITUSPR, // 395\r
- SPIROSITRSPR, // 396\r
- SPIROSPINULSPR, // 397\r
- SPIROSPINURSPR, // 398\r
- SPIROSPINDRSPR, // 399\r
- SPIROSPINDLSPR, // 400\r
- SPIROSPINDSPR, // 401\r
- SPIROSPINLSPR, // 402\r
- SPIROSPINUSPR, // 403\r
- SPIROSPINRSPR, // 404\r
- END_LUMP(SPIRO_LUMP_END, __SPIROEND)\r
-\r
- START_LUMP(AMPTON_LUMP_START, __AMPTONSTART)\r
- AMPTONWALKR1SPR, // 405\r
- AMPTONWALKR2SPR, // 406\r
- AMPTONWALKR3SPR, // 407\r
- AMPTONWALKR4SPR, // 408\r
- AMPTONFACESPR, // 409\r
- AMPTONGRAB1SPR, // 410\r
- AMPTONGRAB2SPR, // 411\r
- AMTONWALKL1SPR, // 412\r
- AMTONWALKL2SPR, // 413\r
- AMTONWALKL3SPR, // 414\r
- AMTONWALKL4SPR, // 415\r
- AMPTONSTUNSPR, // 416\r
- END_LUMP(AMPTON_LUMP_END, __AMPTONEND)\r
-\r
- START_LUMP(VOLTE_LUMP_START, __VOLTESTART)\r
- VOLTEFACE1SPR, // 417\r
- VOLTEFACE2SPR, // 418\r
- VOLTEFACE3SPR, // 419\r
- VOLTEFACE4SPR, // 420\r
- VOLTEFACESTUNSPR, // 421\r
- END_LUMP(VOLTE_LUMP_END, __VOLTEEND)\r
-\r
- START_LUMP(SLOTPLAT_LUMP_START, __PINKPLATSTART)\r
- SLOTPLAT1SPR, // 422\r
- SLOTPLAT2SPR, // 423\r
- END_LUMP(SLOTPLAT_LUMP_END, __PINKPLATEND)\r
-\r
- START_LUMP(SPINDRED_LUMP_START, __SPINDREDSTART)\r
- SPINDRED1SPR, // 424\r
- SPINDRED2SPR, // 425\r
- SPINDRED3SPR, // 426\r
- SPINDRED4SPR, // 427\r
- END_LUMP(SPINDRED_LUMP_END, __SPINDREDEND)\r
-\r
- START_LUMP(SHELLEY_LUMP_START, __SHELLEYSTART)\r
- SHELLEYR1SPR, // 428\r
- SHELLEYR2SPR, // 429\r
- SHELLEYR3SPR, // 430\r
- SHELLEYR4SPR, // 431\r
- SHELLEYL1SPR, // 432\r
- SHELLEYL2SPR, // 433\r
- SHELLEYL3SPR, // 434\r
- SHELLEYL4SPR, // 435\r
- SHELLEYJUMPRSPR, // 436\r
- SHELLEYFALLRSPR, // 437\r
- SHELLEYJUMPLSPR, // 438\r
- SHELLEYFALLLSPR, // 439\r
- SHELLEYBOOM1SPR, // 440\r
- SHELLEYBOOM2SPR, // 441\r
- SHELLEYBOOM3SPR, // 442\r
- SHELLEYBOOM4SPR, // 443\r
- SHELLEYPIECE1SPR, // 444\r
- SHELLEYPIECE2SPR, // 445\r
- END_LUMP(SHELLEY_LUMP_END, __SHELLEYEND)\r
-\r
- START_LUMP(PLATFORM_LUMP_START, __PLATFORMSTART)\r
- PLATFORMSPR, // 446\r
- END_LUMP(PLATFORM_LUMP_END, __PLATFORMEND)\r
-\r
- START_LUMP(MINIPLAT_LUMP_START, __MINIPLATSTART)\r
- MINIPLATSPR, // 447\r
- END_LUMP(MINIPLAT_LUMP_END, __MINIPLATEND)\r
-\r
-\r
- //\r
- // TILES (these don't need names)\r
- //\r
-\r
- LASTTILE=STARTEXTERNS-1,\r
-\r
- //\r
- // EXTERNS\r
- //\r
-\r
- //texts\r
- T_HELPART, // 4914\r
- T_CONTRART, // 4915\r
- T_STORYART, // 4916\r
- T_IDART, // 4917\r
- T_ENDART, // 4918\r
- T_ENDART2, // 4919\r
- T_ORDERART, // 4920\r
-\r
- ORDERSCREEN, // 4921\r
- BIGCOMMANDER, // 4922\r
- BIGKEEN, // 4923\r
- OUTOFMEM, // 4924\r
- GALAXY, // 4925\r
-\r
- //demos\r
- DEMO0, // 4926\r
- DEMO1, // 4927\r
- DEMO2, // 4928\r
- DEMO3, // 4929\r
- DEMO4, // 4930\r
-\r
- NUMGRCHUNKS\r
-} graphicnums;\r
-\r
-#undef START_LUMP\r
-#undef END_LUMP\r
-\r
-#endif //__GFX_H__
\ No newline at end of file
+++ /dev/null
-;\r
-; Equates for all .ASM files\r
-;\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-INCLUDE "GFXE_CK5.EQU"\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-CGAGR = 1\r
-EGAGR = 2\r
-VGAGR = 3\r
-\r
-GRMODE = EGAGR\r
-PROFILE = 0 ; 1=keep stats on tile drawing\r
-\r
-SC_INDEX = 03C4h\r
-SC_RESET = 0\r
-SC_CLOCK = 1\r
-SC_MAPMASK = 2\r
-SC_CHARMAP = 3\r
-SC_MEMMODE = 4\r
-\r
-CRTC_INDEX = 03D4h\r
-CRTC_H_TOTAL = 0\r
-CRTC_H_DISPEND = 1\r
-CRTC_H_BLANK = 2\r
-CRTC_H_ENDBLANK = 3\r
-CRTC_H_RETRACE = 4\r
-CRTC_H_ENDRETRACE = 5\r
-CRTC_V_TOTAL = 6\r
-CRTC_OVERFLOW = 7\r
-CRTC_ROWSCAN = 8\r
-CRTC_MAXSCANLINE = 9\r
-CRTC_CURSORSTART = 10\r
-CRTC_CURSOREND = 11\r
-CRTC_STARTHIGH = 12\r
-CRTC_STARTLOW = 13\r
-CRTC_CURSORHIGH = 14\r
-CRTC_CURSORLOW = 15\r
-CRTC_V_RETRACE = 16\r
-CRTC_V_ENDRETRACE = 17\r
-CRTC_V_DISPEND = 18\r
-CRTC_OFFSET = 19\r
-CRTC_UNDERLINE = 20\r
-CRTC_V_BLANK = 21\r
-CRTC_V_ENDBLANK = 22\r
-CRTC_MODE = 23\r
-CRTC_LINECOMPARE = 24\r
-\r
-\r
-GC_INDEX = 03CEh\r
-GC_SETRESET = 0\r
-GC_ENABLESETRESET = 1\r
-GC_COLORCOMPARE = 2\r
-GC_DATAROTATE = 3\r
-GC_READMAP = 4\r
-GC_MODE = 5\r
-GC_MISCELLANEOUS = 6\r
-GC_COLORDONTCARE = 7\r
-GC_BITMASK = 8\r
-\r
-ATR_INDEX = 03c0h\r
-ATR_MODE = 16\r
-ATR_OVERSCAN = 17\r
-ATR_COLORPLANEENABLE = 18\r
-ATR_PELPAN = 19\r
-ATR_COLORSELECT = 20\r
-\r
-STATUS_REGISTER_1 = 03dah\r
-\r
-\r
-MACRO WORDOUT\r
- out dx,ax\r
-ENDM\r
-\r
-if 0\r
-\r
-MACRO WORDOUT\r
- out dx,al\r
- inc dx\r
- xchg al,ah\r
- out dx,al\r
- dec dx\r
- xchg al,ah\r
-ENDM\r
-\r
-endif\r
-\r
-UPDATEWIDE = 22\r
-UPDATEHIGH = 14\r
-\r
-;\r
-; tile info offsets from segment tinf\r
-;\r
-\r
-ANIM = 402\r
-SPEED = (ANIM+NUMTILE16)\r
-\r
-NORTHWALL = (SPEED+NUMTILE16)\r
-EASTWALL = (NORTHWALL+NUMTILE16M)\r
-SOUTHWALL = (EASTWALL+NUMTILE16M)\r
-WESTWALL = (SOUTHWALL+NUMTILE16M)\r
-MANIM = (WESTWALL+NUMTILE16M)\r
-INTILE = (MANIM+NUMTILE16M)\r
-MSPEED = (INTILE+NUMTILE16M)\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-SCREENWIDTH = 64\r
-ENDIF\r
-IFE GRMODE-CGAGR\r
-SCREENWIDTH = 128\r
-ENDIF\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_GLOB.H\r
-\r
-\r
-#include <ALLOC.H>\r
-#include <CTYPE.H>\r
-#include <DOS.H>\r
-#include <ERRNO.H>\r
-#include <FCNTL.H>\r
-#include <IO.H>\r
-#include <MEM.H>\r
-#include <PROCESS.H>\r
-#include <STDIO.H>\r
-#include <STDLIB.H>\r
-#include <STRING.H>\r
-#include <SYS\STAT.H>\r
-\r
-#define __ID_GLOB__\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define KEEN\r
-#define KEEN5\r
-\r
-#define EXTENSION "CK5"\r
-\r
-extern char far introscn;\r
-\r
-#include "GFXE_CK5.H"\r
-#include "AUDIOCK5.H"\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define TEXTGR 0\r
-#define CGAGR 1\r
-#define EGAGR 2\r
-#define VGAGR 3\r
-\r
-#define GRMODE EGAGR\r
-\r
-#if GRMODE == EGAGR\r
-#define GREXT "EGA"\r
-#endif\r
-#if GRMODE == CGAGR\r
-#define GREXT "CGA"\r
-#endif\r
-\r
-//#define PROFILE\r
-\r
-//\r
-// ID Engine\r
-// Types.h - Generic types, #defines, etc.\r
-// v1.0d1\r
-//\r
-\r
-#ifndef __TYPES__\r
-#define __TYPES__\r
-\r
-typedef enum {false,true} boolean;\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long longword;\r
-typedef byte * Ptr;\r
-\r
-typedef struct\r
- {\r
- int x,y;\r
- } Point;\r
-typedef struct\r
- {\r
- Point ul,lr;\r
- } Rect;\r
-\r
-#define nil ((void *)0)\r
-\r
-#endif\r
-\r
-#include "ID_MM.H"\r
-#include "ID_CA.H"\r
-#include "ID_VW.H"\r
-#include "ID_RF.H"\r
-#include "ID_IN.H"\r
-#include "ID_SD.H"\r
-#include "ID_US.H"\r
-\r
-\r
-void Quit (char *error); // defined in user program\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K5_ACT1.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- some shared routines\r
-- Bonus Items\r
-- Teleport and Fuse effects\r
-- Platforms\r
-- falling platforms\r
-- static platforms\r
-- Goplat platforms\r
-- Volte Face\r
-- sneaky platforms\r
-- Turrets\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- SHARED STUFF\r
-\r
-=============================================================================\r
-*/\r
-\r
-Sint16 pdirx[] = {0, 1, 0, -1, 1, 1, -1, -1};\r
-Sint16 pdiry[] = {-1, 0, 1, 0, -1, 1, 1, -1};\r
-\r
-/*\r
-===========================\r
-=\r
-= CheckSpawnShot\r
-=\r
-===========================\r
-*/\r
-\r
-Sint16 CheckSpawnShot(Uint16 x, Uint16 y, statetype *state)\r
-{\r
- if (GetNewObj(true) == -1)\r
- return -1;\r
- new->x = x;\r
- new->y = y;\r
- new->obclass = mshotobj;\r
- new->active = ac_removable;\r
- NewState(new, state);\r
- if (!CheckPosition(new))\r
- {\r
- RemoveObj(new);\r
- return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_ClipSide\r
-=\r
-===========================\r
-*/\r
-\r
-void C_ClipSide(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- playerkludgeclipcancel = true;\r
- ClipToSpriteSide(hit, ob);\r
- playerkludgeclipcancel = false;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_ClipTop\r
-=\r
-===========================\r
-*/\r
-\r
-void C_ClipTop(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- ClipToSpriteTop(hit, ob);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Land\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Land(objtype *ob)\r
-{\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->yspeed = 0;\r
- if (ob->state->nextstate)\r
- {\r
- ChangeState(ob, ob->state->nextstate);\r
- }\r
- else\r
- {\r
- RemoveObj(ob);\r
- return;\r
- }\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Bounce\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Bounce(objtype *ob)\r
-{\r
- Uint16 wall,absx,absy,angle,newangle;\r
- Uint32 speed;\r
-\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = -ob->xspeed/2;\r
-\r
- if (ob->hitsouth)\r
- {\r
- ob->yspeed = -ob->yspeed/2;\r
- return;\r
- }\r
-\r
- wall = ob->hitnorth;\r
- if (wall)\r
- {\r
- if (ob->yspeed < 0)\r
- ob->yspeed = 0;\r
-\r
- absx = abs(ob->xspeed);\r
- absy = ob->yspeed;\r
- if (absx>absy)\r
- {\r
- if (absx>absy*2) // 22 degrees\r
- {\r
- angle = 0;\r
- speed = absx*286; // x*sqrt(5)/2\r
- }\r
- else // 45 degrees\r
- {\r
- angle = 1;\r
- speed = absx*362; // x*sqrt(2)\r
- }\r
- }\r
- else\r
- {\r
- if (absy>absx*2) // 90 degrees\r
- {\r
- angle = 3;\r
- speed = absy*256;\r
- }\r
- else\r
- {\r
- angle = 2; // 67 degrees\r
- speed = absy*286; // y*sqrt(5)/2\r
- }\r
- }\r
- if (ob->xspeed > 0)\r
- angle = 7-angle;\r
-\r
- speed >>= 1;\r
- newangle = bounceangle[ob->hitnorth][angle];\r
- switch (newangle)\r
- {\r
- case 0:\r
- ob->xspeed = speed / 286;\r
- ob->yspeed = -ob->xspeed / 2;\r
- break;\r
- case 1:\r
- ob->xspeed = speed / 362;\r
- ob->yspeed = -ob->xspeed;\r
- break;\r
- case 2:\r
- ob->yspeed = -(speed / 286);\r
- ob->xspeed = -ob->yspeed / 2;\r
- break;\r
- case 3:\r
-\r
- case 4:\r
- ob->xspeed = 0;\r
- ob->yspeed = -(speed / 256);\r
- break;\r
- case 5:\r
- ob->yspeed = -(speed / 286);\r
- ob->xspeed = ob->yspeed / 2;\r
- break;\r
- case 6:\r
- ob->xspeed = ob->yspeed = -(speed / 362);\r
- break;\r
- case 7:\r
- ob->xspeed = -(speed / 286);\r
- ob->yspeed = ob->xspeed / 2;\r
- break;\r
-\r
- case 8:\r
- ob->xspeed = -(speed / 286);\r
- ob->yspeed = -ob->xspeed / 2;\r
- break;\r
- case 9:\r
- ob->xspeed = -(speed / 362);\r
- ob->yspeed = -ob->xspeed;\r
- break;\r
- case 10:\r
- ob->yspeed = speed / 286;\r
- ob->xspeed = -ob->yspeed / 2;\r
- break;\r
- case 11:\r
-\r
- case 12:\r
- ob->xspeed = 0;\r
- ob->yspeed = -(speed / 256);\r
- break;\r
- case 13:\r
- ob->yspeed = speed / 286;\r
- ob->xspeed = ob->yspeed / 2;\r
- break;\r
- case 14:\r
- ob->xspeed = speed / 362;\r
- ob->yspeed = speed / 362;\r
- break;\r
- case 15:\r
- ob->xspeed = speed / 286;\r
- ob->yspeed = ob->xspeed / 2;\r
- break;\r
- }\r
-\r
- if (speed < 256*16)\r
- {\r
- ChangeState(ob, ob->state->nextstate);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BONUS ITEMS\r
-temp1 = bonus type\r
-temp2 = base shape number\r
-temp3 = last animated shape number +1\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bonus1 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus2};\r
-statetype s_bonus2 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus1};\r
-statetype s_bonusfly1 = {0, 0, stepthink, false, false, 20, 0, 0, T_FlyBonus, NULL, R_Draw, &s_bonusfly2};\r
-statetype s_bonusfly2 = {0, 0, stepthink, false, false, 20, 0, 0, T_FlyBonus, NULL, R_Draw, &s_bonusfly1};\r
-statetype s_bonusrise = {0, 0, slide, false, false, 40, 0, 8, NULL, NULL, R_Draw, NULL};\r
-statetype s_splash1 = {VIVAPOOF1SPR, VIVAPOOF1SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash2};\r
-statetype s_splash2 = {VIVAPOOF2SPR, VIVAPOOF2SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash3};\r
-statetype s_splash3 = {VIVAPOOF3SPR, VIVAPOOF3SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash4};\r
-statetype s_splash4 = {VIVAPOOF4SPR, VIVAPOOF4SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-Uint16 bonusshape[] = {\r
- REDGEM1SPR, YELLOWGEM1SPR, BLUEGEM1SPR, GREENGEM1SPR,\r
- SUGAR1ASPR, SUGAR2ASPR, SUGAR3ASPR,\r
- SUGAR4ASPR, SUGAR5ASPR, SUGAR6ASPR,\r
- ONEUPASPR, STUNCLIP1SPR, DOORCARD1SPR\r
-};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBonus\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBonus(Uint16 tileX, Uint16 tileY, Uint16 type)\r
-{\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = bonusobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->ydir = -1;\r
- new->temp1 = type;\r
- new->temp2=new->shapenum = bonusshape[type];\r
- new->temp3 = new->temp2+2;\r
- NewState(new, &s_bonus1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSplash\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSplash(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(true);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 3;\r
- new->obclass = inertobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- NewState(new, &s_splash1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Bonus\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Bonus(objtype *ob)\r
-{\r
- if (++ob->shapenum == ob->temp3)\r
- ob->shapenum = ob->temp2;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_FlyBonus\r
-=\r
-===========================\r
-*/\r
-\r
-void T_FlyBonus(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- ob->state = &s_bonus1;\r
-\r
- if (++ob->shapenum == ob->temp3)\r
- ob->shapenum = ob->temp2;\r
-\r
- DoGravity(ob);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- TELEPORT EFFECTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_teleport1 = {TELEPORTSPARK1SPR, TELEPORTSPARK1SPR, step, false, false, 6, 0, 0, NULL, NULL, R_Draw, &s_teleport2};\r
-statetype s_teleport2 = {TELEPORTSPARK2SPR, TELEPORTSPARK2SPR, step, false, false, 6, 0, 0, NULL, NULL, R_Draw, &s_teleport1};\r
-statetype s_teleportzap1 = {TELEPORTZAP1SPR, TELEPORTZAP1SPR, step, false, false, 6, 0, 0, NULL, NULL, R_Draw, &s_teleportzap2};\r
-statetype s_teleportzap2 = {TELEPORTZAP2SPR, TELEPORTZAP2SPR, step, false, false, 6, 0, 0, NULL, NULL, R_Draw, &s_teleportzap1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnTeleport\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnTeleport(void)\r
-{\r
- GetNewObj(true);\r
- new->priority = 3;\r
- new->needtoclip = cl_noclip;\r
- new->obclass = teleporterobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(player->tileleft) - 8*PIXGLOBAL;\r
- new->y = CONVERT_TILE_TO_GLOBAL(player->tilebottom) - 5*TILEGLOBAL;\r
- NewState(new, &s_teleport1);\r
-\r
- GetNewObj(true);\r
- new->priority = 3;\r
- new->needtoclip = cl_noclip;\r
- new->obclass = teleporterobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(player->tileleft);\r
- new->y = CONVERT_TILE_TO_GLOBAL(player->tiletop) - 8*PIXGLOBAL;\r
- NewState(new, &s_teleportzap1);\r
-\r
- SD_PlaySound(SND_TELEPORT);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- FUSE FLASH\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_fuseflash1 = {FUSEFLASH1SPR, FUSEFLASH1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_fuseflash2};\r
-statetype s_fuseflash2 = {FUSEFLASH2SPR, FUSEFLASH2SPR, step, false, false, 20, 0, 0, NULL, NULL, R_Draw, &s_fuseflash3};\r
-statetype s_fuseflash3 = {FUSEFLASH3SPR, FUSEFLASH3SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnFuseFlash\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnFuseFlash(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(true);\r
- new->priority = 3;\r
- new->needtoclip = cl_noclip;\r
- new->obclass = teleporterobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX-1);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- NewState(new, &s_fuseflash1);\r
- SD_PlaySound(SND_BIGSPARK);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- DEAD MACHINE\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_deadmachine = {-1, -1, step, false, false, 60, 0, 0, T_DeadMachine, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnDeadMachine\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnDeadMachine(void)\r
-{\r
- GetNewObj(false);\r
- new->active = ac_allways;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_deadmachine);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DeadMachine\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void T_DeadMachine(objtype *ob)\r
-{\r
- if (mapon == 12)\r
- {\r
- playstate = ex_qedbroke;\r
- }\r
- else\r
- {\r
- playstate = ex_fusebroke;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- PLATFORMS\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_platform = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_Platform, NULL, R_Draw, NULL};\r
-statetype s_slotplat1 = {SLOTPLAT1SPR, SLOTPLAT1SPR, stepthink, false, false, 0, 0, 0, T_Slotplat, NULL, R_Draw, &s_slotplat2};\r
-statetype s_slotplat2 = {SLOTPLAT2SPR, SLOTPLAT2SPR, stepthink, false, false, 0, 0, 0, T_Slotplat, NULL, R_Draw, &s_slotplat1};\r
-// BUG? the slotplat states have a tictime of 0, so they never transition to the next state\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnPlatform\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnPlatform(Uint16 tileX, Uint16 tileY, Sint16 dir, Sint16 type)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- switch (dir)\r
- {\r
- case 0:\r
- new->xdir = 0;\r
- new->ydir = -1;\r
- break;\r
- case 1:\r
- new->xdir = 1;\r
- new->ydir = 0;\r
- break;\r
- case 2:\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- break;\r
- case 3:\r
- new->xdir = -1;\r
- new->ydir = 0;\r
- }\r
- if (type)\r
- {\r
- new->x += 4*PIXGLOBAL;\r
- new->y += 4*PIXGLOBAL;\r
- NewState(new, &s_slotplat1);\r
- }\r
- else\r
- {\r
- NewState(new, &s_platform);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Platform\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Platform(objtype *ob)\r
-{\r
- Uint16 newpos, newtile;\r
-\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (!xtry && !ytry)\r
- {\r
- xtry = ob->xdir * 12 * tics;\r
- ytry = ob->ydir * 12 * tics;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- newpos = ob->right + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileright != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK)\r
- {\r
- ob->xdir = -1;\r
- xtry = xtry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- else if (ob->xdir == -1)\r
- {\r
- newpos = ob->left + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileleft != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK)\r
- {\r
- ob->xdir = 1;\r
- xtry = xtry + (TILEGLOBAL - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- else if (ob->ydir == 1)\r
- {\r
- newpos = ob->bottom + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tilebottom != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile-2]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = -1;\r
- ytry = ytry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- }\r
- else if (ob->ydir == -1)\r
- {\r
- newpos = ob->top + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tiletop != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile+2]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = 1;\r
- ytry = ytry + (TILEGLOBAL - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Slotplat\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Slotplat(objtype *ob)\r
-{\r
- Uint16 newpos, newtile;\r
-\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (!xtry && !ytry)\r
- {\r
- xtry = ob->xdir * 12 * tics;\r
- ytry = ob->ydir * 12 * tics;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- newpos = ob->right + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileright != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK)\r
- {\r
- ob->xdir = -1;\r
- xtry = xtry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- else if (ob->xdir == -1)\r
- {\r
- newpos = ob->left + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileleft != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK)\r
- {\r
- ob->xdir = 1;\r
- xtry = xtry + (TILEGLOBAL - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- else if (ob->ydir == 1)\r
- {\r
- newpos = ob->bottom + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tilebottom != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft + 1) == PLATFORMBLOCK)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile-2]/2 + ob->tileleft) == PLATFORMBLOCK) // BUG? '+ 1' is missing after 'tileleft'\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = -1;\r
- ytry = ytry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- }\r
- else if (ob->ydir == -1)\r
- {\r
- newpos = ob->top + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tiletop != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft + 1) == PLATFORMBLOCK)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile+2]/2 + ob->tileleft + 1) == PLATFORMBLOCK)\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = 1;\r
- ytry = ytry + (TILEGLOBAL - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- DROPPING PLATFORM\r
-\r
-temp1 = initial y position\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_dropplatsit = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatSit, NULL, R_Draw, NULL};\r
-statetype s_dropplatfall = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatFall, NULL, R_Draw, NULL};\r
-statetype s_dropplatrise = {PLATFORMSPR, PLATFORMSPR, slidethink, false, false, 0, 0, -32, T_DropPlatRise, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnDropPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnDropPlat(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_dropplatsit);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatSit\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatSit(objtype *ob)\r
-{\r
- if (gamestate.riding == ob)\r
- {\r
- ytry = tics << 4; //tics * 16;\r
- ob->yspeed = 0;\r
- if (ob->y + ytry - ob->temp1 >= 8*PIXGLOBAL)\r
- ob->state = &s_dropplatfall;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatFall\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatFall(objtype *ob)\r
-{\r
- Uint16 newpos, newtile;\r
-\r
- DoGravity(ob);\r
-\r
-#if 0\r
- // bugfix: don't skip a tile (this is present in Keen 4, but missing in 5 & 6)\r
- if (ytry >= 15*PIXGLOBAL)\r
- ytry = 15*PIXGLOBAL;\r
-#endif\r
-\r
- newpos = ob->bottom + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tilebottom != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- ytry = 0xFF - (ob->bottom & 0xFF);\r
- if (gamestate.riding != ob)\r
- ob->state = &s_dropplatrise;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatRise\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatRise(objtype *ob)\r
-{\r
- if (gamestate.riding == ob)\r
- {\r
- ob->yspeed = 0;\r
- ob->state = &s_dropplatfall;\r
- }\r
- else if (ob->y <= ob->temp1)\r
- {\r
- ytry = ob->temp1 - ob->y;\r
- ob->state = &s_dropplatsit;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- STATIC PLATFORM\r
-\r
-temp1 = initial y position (is set but never used)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_statplat = {PLATFORMSPR, PLATFORMSPR, step, false, false, 32000, 0, 0, NULL, NULL, R_Draw, &s_statplat};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnStaticPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnStaticPlat(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_statplat);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GO PLATFORMS\r
-\r
-temp1 = direction\r
-temp2 = countdown to next dir check\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_goplat = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_GoPlat, NULL, R_Draw, NULL};\r
-statetype s_slotgoplat1 = {SLOTPLAT1SPR, SLOTPLAT1SPR, stepthink, false, false, 0, 0, 0, T_GoSlotPlat, NULL, R_Draw, &s_slotgoplat2};\r
-statetype s_slotgoplat2 = {SLOTPLAT2SPR, SLOTPLAT2SPR, stepthink, false, false, 0, 0, 0, T_GoSlotPlat, NULL, R_Draw, &s_slotgoplat1};\r
-// BUG? the slotgoplat states have a tictime of 0, so they never transition to the next state\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnGoPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnGoPlat(Uint16 tileX, Uint16 tileY, Sint16 dir, Sint16 type)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- if (type)\r
- {\r
- new->x += 4*PIXGLOBAL;\r
- new->y += 4*PIXGLOBAL;\r
- NewState(new, &s_slotgoplat1);\r
- }\r
- else\r
- {\r
- NewState(new, &s_goplat);\r
- }\r
- *(mapsegs[2]+mapbwidthtable[tileY]/2 + tileX) = DIRARROWSTART + dir;\r
- new->temp1 = dir;\r
- new->temp2 = TILEGLOBAL;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_GoPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void T_GoPlat(objtype *ob)\r
-{\r
- Uint16 move;\r
- Uint16 tx, ty;\r
- Sint16 dir;\r
-\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (!xtry && !ytry)\r
- {\r
- move = tics * 12;\r
- if (ob->temp2 > move)\r
- {\r
- ob->temp2 = ob->temp2 - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry + -move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry + -move;\r
- }\r
- }\r
- else\r
- {\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry += -ob->temp2;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry += -ob->temp2;\r
- }\r
-\r
- tx = CONVERT_GLOBAL_TO_TILE(ob->x + xtry);\r
- ty = CONVERT_GLOBAL_TO_TILE(ob->y + ytry);\r
- ob->temp1 = *(mapsegs[2]+mapbwidthtable[ty]/2 + tx) - DIRARROWSTART;\r
- if (ob->temp1 < arrow_North || ob->temp1 > arrow_None)\r
- {\r
- char error[60] = "Goplat moved to a bad spot: ";\r
- char buf[5] = "";\r
-\r
- strcat(error, itoa(ob->x, buf, 16));\r
- strcat(error, ",");\r
- strcat(error, itoa(ob->y, buf, 16));\r
- Quit(error);\r
- }\r
-\r
- move -= ob->temp2;\r
- ob->temp2 = TILEGLOBAL - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry - move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry - move;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_GoSlotPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void T_GoSlotPlat(objtype *ob)\r
-{\r
- Uint16 move;\r
- Uint16 tx, ty;\r
- Sint16 dir;\r
-\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (!xtry && !ytry)\r
- {\r
- move = tics * 12;\r
- if (ob->temp2 > move)\r
- {\r
- ob->temp2 = ob->temp2 - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry + -move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry + -move;\r
- }\r
- }\r
- else\r
- {\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry += -ob->temp2;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry += -ob->temp2;\r
- }\r
-\r
- tx = CONVERT_GLOBAL_TO_TILE(ob->x + xtry + 4*PIXGLOBAL);\r
- ty = CONVERT_GLOBAL_TO_TILE(ob->y + ytry + 4*PIXGLOBAL);\r
- ob->temp1 = *(mapsegs[2]+mapbwidthtable[ty]/2 + tx) - DIRARROWSTART;\r
- if (ob->temp1 < arrow_North || ob->temp1 > arrow_None)\r
- {\r
- Quit("Goplat moved to a bad spot!");\r
- }\r
-\r
- move -= ob->temp2;\r
- ob->temp2 = TILEGLOBAL - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry - move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry - move;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- VOLTEFACE\r
-\r
-temp1 = direction\r
-temp2 = countdown to next dir check\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_volte1 = {VOLTEFACE1SPR, VOLTEFACE1SPR, stepthink, false, false, 6, 0, 0, T_Volte, C_Volte, R_Draw, &s_volte2};\r
-statetype s_volte2 = {VOLTEFACE2SPR, VOLTEFACE2SPR, stepthink, false, false, 6, 0, 0, T_Volte, C_Volte, R_Draw, &s_volte3};\r
-statetype s_volte3 = {VOLTEFACE3SPR, VOLTEFACE3SPR, stepthink, false, false, 6, 0, 0, T_Volte, C_Volte, R_Draw, &s_volte4};\r
-statetype s_volte4 = {VOLTEFACE4SPR, VOLTEFACE4SPR, stepthink, false, false, 6, 0, 0, T_Volte, C_Volte, R_Draw, &s_volte1};\r
-statetype s_voltestun = {VOLTEFACESTUNSPR, VOLTEFACESTUNSPR, step, false, false, 300, 0, 0, NULL, NULL, R_Draw, &s_volte1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnVolte\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnVolte(Uint16 tileX, Uint16 tileY)\r
-{\r
- Uint16 dir;\r
- Uint16 far *map;\r
-\r
- GetNewObj(false);\r
- new->obclass = volteobj;\r
- new->active = ac_allways;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_volte1);\r
- map = mapsegs[2] + mapbwidthtable[tileY]/2 + tileX;\r
- if (map[-1] == DIRARROWSTART + arrow_East)\r
- {\r
- dir = arrow_East;\r
- }\r
- else if (map[1] == DIRARROWSTART + arrow_West)\r
- {\r
- dir = arrow_West;\r
- }\r
- else if (*(map-mapwidth) == DIRARROWSTART + arrow_South)\r
- {\r
- dir = arrow_South;\r
- }\r
- else if (*(map+mapwidth) == DIRARROWSTART + arrow_North)\r
- {\r
- dir = arrow_North;\r
- }\r
- map[0] = dir + DIRARROWSTART;\r
- new->temp1 = dir;\r
- new->temp2 = TILEGLOBAL;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Volte\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Volte(objtype *ob)\r
-{\r
- Uint16 move;\r
- Uint16 tx, ty;\r
- Sint16 dir;\r
-\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (!xtry && !ytry)\r
- {\r
- move = tics << 5;\r
- if (ob->temp2 > move)\r
- {\r
- ob->temp2 = ob->temp2 - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry + -move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry + -move;\r
- }\r
- }\r
- else\r
- {\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry += -ob->temp2;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry += -ob->temp2;\r
- }\r
-\r
- tx = CONVERT_GLOBAL_TO_TILE(ob->x + xtry);\r
- ty = CONVERT_GLOBAL_TO_TILE(ob->y + ytry);\r
- ob->temp1 = *(mapsegs[2]+mapbwidthtable[ty]/2 + tx) - DIRARROWSTART;\r
- if (ob->temp1 < arrow_North || ob->temp1 > arrow_None)\r
- {\r
- char error[60] = "Volte moved to a bad spot: ";\r
- char buf[5] = "";\r
-\r
- strcat(error, itoa(ob->x, buf, 16));\r
- strcat(error, ",");\r
- strcat(error, itoa(ob->y, buf, 16));\r
- Quit(error);\r
- }\r
-\r
- move -= ob->temp2;\r
- ob->temp2 = TILEGLOBAL - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry - move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry - move;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Volte\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Volte(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_voltestun);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SNEAKY PLATFORM\r
-\r
-temp1 = initial x position (is set but never used)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_sneakplatsit = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_SneakPlat, NULL, R_Draw, NULL};\r
-statetype s_sneakplatdodge = {PLATFORMSPR, PLATFORMSPR, slide, false, false, 48, 32, 0, NULL, NULL, R_Draw, &s_sneakplatreturn};\r
-statetype s_sneakplatreturn = {PLATFORMSPR, PLATFORMSPR, slide, false, false, 96, -16, 0, NULL, NULL, R_Draw, &s_sneakplatsit};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSneakPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSneakPlat(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_sneakplatsit);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SneakPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SneakPlat(objtype *ob)\r
-{\r
- Sint16 dist;\r
-\r
- if (player->state != &s_keenjump1)\r
- return;\r
-\r
- if (player->xdir == 1)\r
- {\r
- dist = ob->left-player->right;\r
- if (dist > 4*TILEGLOBAL || dist < 0)\r
- return;\r
- }\r
- else\r
- {\r
- dist = player->left-ob->right;\r
- if (dist > 4*TILEGLOBAL || dist < 0)\r
- return;\r
- }\r
- dist = player->y - ob->y;\r
- if (dist < -6*TILEGLOBAL || dist > 6*TILEGLOBAL)\r
- return;\r
-\r
- ob->xdir = player->xdir;\r
- ob->state = &s_sneakplatdodge;\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- CANNON\r
-\r
-temp1 = direction\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_cannon = {0, 0, step, false, false, 120, 0, 0, NULL, NULL, R_Draw, &s_cannonfire};\r
-statetype s_cannonfire = {0, 0, step, true, false, 1, 0, 0, T_Cannon, NULL, R_Draw, &s_cannon};\r
-statetype s_cshot1 = {LASER1SPR, LASER1SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot2};\r
-statetype s_cshot2 = {LASER2SPR, LASER2SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot3};\r
-statetype s_cshot3 = {LASER3SPR, LASER3SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot4};\r
-statetype s_cshot4 = {LASER4SPR, LASER4SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot1};\r
-statetype s_cshothit1 = {LASERHIT1SPR, LASERHIT1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cshothit2};\r
-statetype s_cshothit2 = {LASERHIT2SPR, LASERHIT2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnCannon\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnCannon(Uint16 tileX, Uint16 tileY, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = cannonobj;\r
- new->active = ac_yes;\r
- new->tileright = new->tileleft = tileX;\r
- new->tiletop = new->tilebottom = tileY;\r
- new->x = new->left = new->right = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = new->top = new->bottom = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->temp1 = dir;\r
- NewState(new, &s_cannon);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Cannon\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Cannon(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->obclass = mshotobj;\r
- new->active = ac_removable;\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- switch (ob->temp1)\r
- {\r
- case 0:\r
- new->yspeed = -64;\r
- break;\r
- case 1:\r
- new->xspeed = 64;\r
- break;\r
- case 2:\r
- new->yspeed = 64;\r
- break;\r
- case 3:\r
- new->xspeed = -64;\r
- }\r
- NewState(new, &s_cshot1);\r
- SD_PlaySound(SND_ENEMYSHOT);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_CShot\r
-=\r
-===========================\r
-*/\r
-\r
-void C_CShot(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- ChangeState(ob, &s_cshothit1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_CShot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_CShot(objtype *ob)\r
-{\r
- if (ob->hitnorth || ob->hiteast || ob->hitsouth || ob->hitwest)\r
- {\r
- SD_PlaySound(SND_ENEMYSHOTEXPLODE);\r
- ChangeState(ob, &s_cshothit1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K5_ACT2.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Sparky\r
-- Little Ampton\r
-- Slicestar\r
-- Shelley\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- SPARKY\r
-\r
-temp1 = charge countdown\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_sparkywalk1 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, false, true, 8, 128, 0, T_Sparky, C_Sparky, R_Sparky, &s_sparkywalk2};\r
-statetype s_sparkywalk2 = {SPARKYWALKL2SPR, SPARKYWALKR2SPR, step, false, true, 8, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkywalk3};\r
-statetype s_sparkywalk3 = {SPARKYWALKL3SPR, SPARKYWALKR3SPR, step, false, true, 8, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkywalk4};\r
-statetype s_sparkywalk4 = {SPARKYWALKL4SPR, SPARKYWALKR4SPR, step, false, true, 8, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkywalk1};\r
-statetype s_sparkylook1 = {SPARKYTURN1SPR, SPARKYTURN1SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook2};\r
-statetype s_sparkylook2 = {SPARKYTURN2SPR, SPARKYTURN2SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook3};\r
-statetype s_sparkylook3 = {SPARKYTURN3SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook4};\r
-statetype s_sparkylook4 = {SPARKYWALKR1SPR, SPARKYWALKR1SPR, step, false, true, 6, 0, 0, T_SparkyLookL, C_Sparky, R_Sparky, &s_sparkylook5};\r
-statetype s_sparkylook5 = {SPARKYTURN3SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook6};\r
-statetype s_sparkylook6 = {SPARKYTURN2SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook7};\r
-statetype s_sparkylook7 = {SPARKYTURN1SPR, SPARKYTURN3SPR, step, false, true, 6, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkylook8};\r
-statetype s_sparkylook8 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, false, true, 6, 0, 0, T_SparkyLookR, C_Sparky, R_Sparky, &s_sparkywalk2};\r
-statetype s_sparkyspeed1 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, true, true, 4, 0, 0, NULL, C_Sparky, R_Sparky, &s_sparkyspeed2};\r
-statetype s_sparkyspeed2 = {SPARKYWALKL2SPR, SPARKYWALKR2SPR, step, true, true, 4, 0, 0, NULL, C_Sparky, R_Sparky, &s_sparkyspeed3};\r
-statetype s_sparkyspeed3 = {SPARKYWALKL3SPR, SPARKYWALKR3SPR, step, true, true, 4, 0, 0, NULL, C_Sparky, R_Sparky, &s_sparkyspeed4};\r
-statetype s_sparkyspeed4 = {SPARKYWALKL4SPR, SPARKYWALKR4SPR, step, true, true, 4, 0, 0, T_ChargeCount, C_Sparky, R_Sparky, &s_sparkyspeed1};\r
-statetype s_sparkycharge1 = {SPARKYWALKL1SPR, SPARKYWALKR1SPR, step, true, true, 4, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkycharge2};\r
-statetype s_sparkycharge2 = {SPARKYWALKL2SPR, SPARKYWALKR2SPR, step, true, true, 4, 128, 0, T_RunSnd1, C_Sparky, R_Sparky, &s_sparkycharge3};\r
-statetype s_sparkycharge3 = {SPARKYWALKL3SPR, SPARKYWALKR3SPR, step, true, true, 4, 128, 0, NULL, C_Sparky, R_Sparky, &s_sparkycharge4};\r
-statetype s_sparkycharge4 = {SPARKYWALKL4SPR, SPARKYWALKR4SPR, step, true, true, 4, 128, 0, T_RunSnd2, C_Sparky, R_Sparky, &s_sparkycharge1};\r
-statetype s_sparkyturn1 = {SPARKYTURN3SPR, SPARKYTURN1SPR, step, false, true, 8, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkyturn2};\r
-statetype s_sparkyturn2 = {SPARKYTURN2SPR, SPARKYTURN2SPR, step, false, true, 8, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkyturn3};\r
-statetype s_sparkyturn3 = {SPARKYTURN1SPR, SPARKYTURN3SPR, step, false, true, 8, 0, 0, NULL, C_Sparky, R_Draw, &s_sparkywalk1};\r
-statetype s_sparkystun = {SPARKYSTUNSPR, SPARKYSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSparky\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSparky(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = sparkyobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -1*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_sparkywalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Sparky\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Sparky(objtype *ob)\r
-{\r
- if (US_RndT() < 0x40)\r
- {\r
- ob->state = &s_sparkylook1;\r
- xtry = 0;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_ChargeCount\r
-=\r
-===========================\r
-*/\r
-\r
-void T_ChargeCount(objtype *ob)\r
-{\r
- if (--ob->temp1 == 0)\r
- ob->state = &s_sparkycharge1;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SparkyLookL\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SparkyLookL(objtype *ob)\r
-{\r
- Uint16 dist = player->bottom + TILEGLOBAL - ob->bottom;\r
- if (dist > 2*TILEGLOBAL)\r
- return;\r
-\r
- if (player->x < ob->x)\r
- { \r
- ob->xdir = -1;\r
- SD_PlaySound(SND_SPARKYCHARGE);\r
- ob->state = &s_sparkyspeed1;\r
- ob->temp1 = 3;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SparkyLookR\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SparkyLookR(objtype *ob)\r
-{\r
- Uint16 dist = player->bottom + TILEGLOBAL - ob->bottom;\r
- if (dist > 2*TILEGLOBAL)\r
- return;\r
-\r
- if (player->x > ob->x)\r
- {\r
- ob->xdir = 1;\r
- SD_PlaySound(SND_SPARKYCHARGE);\r
- ob->state = &s_sparkyspeed1;\r
- ob->temp1 = 3;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_RunSnd1\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void T_RunSnd1(objtype *ob)\r
-{\r
- SD_PlaySound(SND_WORLDWALK1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_RunSnd2\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void T_RunSnd2(objtype *ob)\r
-{\r
- SD_PlaySound(SND_WORLDWALK1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Sparky\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Sparky(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_sparkystun);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Sparky\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Sparky(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, &s_sparkyturn1);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, &s_sparkyturn1);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, &s_sparkyturn1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- LITTLE AMPTON\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_amptonwalk1 = {AMTONWALKL1SPR, AMPTONWALKR1SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk2};\r
-statetype s_amptonwalk2 = {AMTONWALKL2SPR, AMPTONWALKR2SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk3};\r
-statetype s_amptonwalk3 = {AMTONWALKL3SPR, AMPTONWALKR3SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk4};\r
-statetype s_amptonwalk4 = {AMTONWALKL4SPR, AMPTONWALKR4SPR, step, false, true, 8, 128, 0, T_Ampton, C_Ampton, R_Ampton, &s_amptonwalk1};\r
-statetype s_amptonturn = {AMPTONFACESPR, AMPTONFACESPR, step, false, true, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonwalk1};\r
-statetype s_amptongrab1 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptongrab2};\r
-statetype s_amptongrab2 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, true, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonclimb};\r
-statetype s_amptonclimb = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, slidethink, false, false, 0, 0, 32, T_AmptonClimb, C_Ampton, R_Draw, NULL};\r
-statetype s_amptonrelease1 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, false, 8, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonrelease2};\r
-statetype s_amptonrelease2 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, false, 8, 0, 0, T_SetNoThink, C_Ampton, R_Draw, &s_amptonwalk1};\r
-statetype s_amptonfiddle1 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle2};\r
-statetype s_amptonfiddle2 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle3};\r
-statetype s_amptonfiddle3 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle4};\r
-statetype s_amptonfiddle4 = {AMPTONGRAB2SPR, AMPTONGRAB2SPR, step, false, true, 12, 0, 0, NULL, C_Ampton, R_Draw, &s_amptonfiddle5};\r
-statetype s_amptonfiddle5 = {AMPTONGRAB1SPR, AMPTONGRAB1SPR, step, false, true, 12, 0, 0, T_SetNoThink, C_Ampton, R_Draw, &s_amptonwalk1};\r
-statetype s_amptonstun = {AMPTONSTUNSPR, AMPTONSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnAmpton\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnAmpton(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = amptonobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_amptonwalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Ampton\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Ampton(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 intile, var8;\r
- boolean poleup, poledown;\r
-\r
- if (ob->state == &s_amptonwalk1)\r
- {\r
- SD_PlaySound(SND_AMPTONWALK1);\r
- }\r
- else if (ob->state == &s_amptonwalk3)\r
- {\r
- SD_PlaySound(SND_AMPTONWALK2);\r
- }\r
- if (ob->x & 0xFF)\r
- {\r
- map = mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft + 1;\r
- intile = tinf[*map + INTILE] & INTILE_TYPEMASK;\r
- if (intile == INTILE_AMPTONCOMPUTER)\r
- {\r
- ob->state = &s_amptonfiddle1;\r
- }\r
- else if (intile == INTILE_POLE && US_RndT() < 196)\r
- {\r
- if ((tinf[*(map + mapwidth*2) + INTILE] & INTILE_TYPEMASK) == INTILE_POLE)\r
- {\r
- poledown = true;\r
- }\r
- else\r
- {\r
- poledown = false;\r
- }\r
- if ((tinf[*(map - mapwidth*2) + INTILE] & INTILE_TYPEMASK) == INTILE_POLE)\r
- {\r
- poleup = true;\r
- }\r
- else\r
- {\r
- poleup = false;\r
- }\r
- if (poleup && poledown)\r
- {\r
- if (US_RndT() < 0x80)\r
- poleup = false;\r
- else\r
- poledown = false;\r
- }\r
-\r
- if (poleup)\r
- {\r
- ob->ydir = -1;\r
- ob->state = &s_amptongrab1;\r
- ob->needtoclip = cl_noclip;\r
- ob->nothink = 6;\r
- xtry = 0;\r
- }\r
- else if (poledown)\r
- {\r
- ob->ydir = 1;\r
- ob->state = &s_amptongrab1;\r
- ob->needtoclip = cl_noclip;\r
- ob->nothink = 6;\r
- xtry = 0;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_AmptonClimb\r
-=\r
-===========================\r
-*/\r
-\r
-void T_AmptonClimb(objtype *ob)\r
-{\r
- Uint16 newtile;\r
- Uint16 far *map;\r
- Uint16 move;\r
-\r
- newtile = CONVERT_GLOBAL_TO_TILE(ob->bottom + ytry);\r
- if (ob->tilebottom != newtile)\r
- {\r
- if (ob->ydir == -1)\r
- {\r
- map = mapsegs[1] + mapbwidthtable[newtile]/2 + ob->tileleft + 1;\r
- if (!tinf[map[0] + NORTHWALL] && tinf[map[mapwidth]+NORTHWALL])\r
- {\r
- if ((tinf[*(map-4*mapwidth)+INTILE] & INTILE_TYPEMASK) == INTILE_POLE && US_RndT() < 0x80)\r
- return;\r
-\r
- move = (ob->bottom & 0xFF) + 1;\r
- ob->y -= move;\r
- ob->bottom -= move;\r
- ob->needtoclip = cl_midclip;\r
- ob->state = &s_amptonrelease1;\r
- ytry = PIXGLOBAL;\r
- ob->ydir = 1;\r
- ClipToWalls(ob);\r
- ob->nothink = 4;\r
- return;\r
- }\r
- if ((tinf[*(map-mapwidth)+INTILE] & INTILE_TYPEMASK) != INTILE_POLE)\r
- {\r
- ytry = 0;\r
- ob->ydir = 1;\r
- }\r
- }\r
- else\r
- {\r
- map = mapsegs[1] + mapbwidthtable[newtile]/2 + ob->tileleft + 1;\r
- if (tinf[map[0] + NORTHWALL] && !tinf[*(map-mapwidth)+NORTHWALL])\r
- {\r
- if ((tinf[map[2*mapwidth] + INTILE] & INTILE_TYPEMASK) == INTILE_POLE && US_RndT() < 0x80)\r
- return;\r
-\r
- move = 0xFF - (ob->bottom & 0xFF);\r
- ob->y += move;\r
- ob->bottom += move;\r
- ob->needtoclip = cl_midclip;\r
- ob->state = &s_amptonrelease1;\r
- ytry = PIXGLOBAL;\r
- ClipToWalls(ob);\r
- ob->nothink = 4;\r
- return;\r
- }\r
- if ((tinf[map[0] + INTILE] & INTILE_TYPEMASK) != INTILE_POLE)\r
- {\r
- ytry = 0;\r
- ob->ydir = -1;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SetNoThink\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SetNoThink(objtype *ob)\r
-{\r
- ob->nothink = 4;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Ampton\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Ampton(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- if (ob->state == &s_amptonclimb)\r
- {\r
- KillKeen();\r
- }\r
- else\r
- {\r
- ClipToSpriteSide(hit, ob);\r
- }\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ob->needtoclip = cl_midclip;\r
- ob->ydir = 1;\r
- ob->yspeed = 0;\r
- SD_PlaySound(SND_AMPTONDIE);\r
- StunObj(ob, hit, &s_amptonstun);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Ampton\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Ampton(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ChangeState(ob, &s_amptonturn);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ChangeState(ob, &s_amptonturn);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -ob->xdir;\r
- ChangeState(ob, &s_amptonturn);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SLICESTAR\r
-\r
-temp4 = health\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_slicestarslide = {SLICESTARSPR, SLICESTARSPR, think, false, false, 0, 0, 0, T_Platform, C_Slicestar, R_Draw, NULL};\r
-statetype s_slicestarbounce = {SLICESTARSPR, SLICESTARSPR, slide, false, false, 0, 24, 24, NULL, C_Slicestar, R_Slicestar, &s_slicestarbounce};\r
-statetype s_slicestarboom = {SLICESTARBOOMSPR, SLICESTARBOOMSPR, step, false, false, 20, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSlicestarSlide\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSlicestarSlide(Uint16 tileX, Uint16 tileY, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = slicestarobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->temp4 = 20; // health!\r
- switch (dir)\r
- {\r
- case 0:\r
- new->xdir = 0;\r
- new->ydir = -1;\r
- break;\r
- case 1:\r
- new->xdir = 1;\r
- new->ydir = 0;\r
- break;\r
- case 2:\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- break;\r
- case 3:\r
- new->xdir = -1;\r
- new->ydir = 0;\r
- }\r
- NewState(new, &s_slicestarslide);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSlicestarBounce\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSlicestarBounce(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = slicestarobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->needtoclip = cl_fullclip;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->temp4 = 50; // health!\r
- switch (US_RndT() / 0x40)\r
- {\r
- case 0:\r
- new->xdir = -1;\r
- new->ydir = -1;\r
- break;\r
- case 1:\r
- new->xdir = 1;\r
- new->ydir = 1;\r
- break;\r
- case 2:\r
- new->xdir = -1;\r
- new->ydir = 1;\r
- break;\r
- case 3:\r
- new->xdir = 1;\r
- new->ydir = -1;\r
- }\r
- NewState(new, &s_slicestarbounce);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Slicestar\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Slicestar(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- if (--ob->temp4 == 0)\r
- {\r
- ChangeState(ob, &s_slicestarboom);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Slicestar\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Slicestar(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- {\r
- ob->ydir = -1;\r
- SD_PlaySound(SND_SLICESTARBOUNCE);\r
- }\r
- else if (ob->hitsouth)\r
- {\r
- ob->ydir = 1;\r
- SD_PlaySound(SND_SLICESTARBOUNCE);\r
- }\r
- if (ob->hitwest)\r
- {\r
- ob->xdir = -1;\r
- SD_PlaySound(SND_SLICESTARBOUNCE);\r
- }\r
- else if (ob->hiteast)\r
- {\r
- ob->xdir = 1;\r
- SD_PlaySound(SND_SLICESTARBOUNCE);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SHELLEY\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_shellywalk1 = {SHELLEYL1SPR, SHELLEYR1SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk2};\r
-statetype s_shellywalk2 = {SHELLEYL2SPR, SHELLEYR2SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk3};\r
-statetype s_shellywalk3 = {SHELLEYL3SPR, SHELLEYR3SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk4};\r
-statetype s_shellywalk4 = {SHELLEYL4SPR, SHELLEYR4SPR, step, false, true, 8, 128, 0, NULL, C_Shelly, R_Shelly, &s_shellywalk1};\r
-statetype s_shellylook = {SHELLEYL2SPR, SHELLEYR2SPR, stepthink, false, true, 100, 0, 0, T_ShellyLook, C_Shelly, R_Draw, &s_shellylook2};\r
-statetype s_shellylook2 = {SHELLEYL2SPR, SHELLEYR2SPR, step, true, true, 1, 0, 0, T_Turn, C_Shelly, R_Draw, &s_shellywalk1};\r
-statetype s_shellyjump1 = {SHELLEYJUMPLSPR, SHELLEYJUMPRSPR, stepthink, false, false, 8, 0, 0, T_Projectile, C_Shelly, R_Shell, &s_shellyjump2};\r
-statetype s_shellyjump2 = {SHELLEYFALLLSPR, SHELLEYFALLRSPR, think, false, false, 8, 0, 0, T_Projectile, C_Shelly, R_Shell, NULL};\r
-statetype s_shellydie = {SHELLEYFALLLSPR, SHELLEYFALLRSPR, step, false, false, 8, 0, 0, T_ShellyFrag, NULL, R_Shell, NULL};\r
-statetype s_shellydieup = {SHELLEYL2SPR, SHELLEYR2SPR, step, false, false, 8, 0, 0, T_ShellyFrag, NULL, R_Shell, NULL};\r
-statetype s_shellyboom1 = {SHELLEYBOOM1SPR, SHELLEYBOOM1SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, &s_shellyboom2};\r
-statetype s_shellyboom2 = {SHELLEYBOOM2SPR, SHELLEYBOOM2SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, &s_shellyboom3};\r
-statetype s_shellyboom3 = {SHELLEYBOOM3SPR, SHELLEYBOOM3SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, &s_shellyboom4};\r
-statetype s_shellyboom4 = {SHELLEYBOOM4SPR, SHELLEYBOOM4SPR, step, false, false, 20, 0, 0, NULL, C_Lethal, R_Draw, NULL};\r
-statetype s_shellypiece1 = {SHELLEYPIECE1SPR, SHELLEYPIECE1SPR, think, false, false, 8, 0, 0, T_Projectile, C_Lethal, R_Bounce, NULL};\r
-statetype s_shellypiece2 = {SHELLEYPIECE2SPR, SHELLEYPIECE2SPR, think, false, false, 8, 0, 0, T_Projectile, C_Lethal, R_Bounce, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnShelly\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnShelly(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = sparkyobj; // BUG: should use shelleyobj\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_shellywalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_ShellyLook\r
-=\r
-===========================\r
-*/\r
-\r
-void T_ShellyLook(objtype *ob)\r
-{\r
- Sint16 xdist;\r
-\r
- if (player->top < ob->bottom)\r
- return;\r
-\r
- xdist = player->midx - ob->midx;\r
- if (ob->xdir == 1)\r
- {\r
- if (xdist > 1*TILEGLOBAL && xdist < 3*TILEGLOBAL)\r
- {\r
- ob->xspeed = 16;\r
- ob->yspeed = -24;\r
- ob->state = &s_shellyjump1;\r
- xtry = ytry = 0;\r
- }\r
- }\r
- else\r
- {\r
- if (xdist < -1*TILEGLOBAL && xdist > -3*TILEGLOBAL)\r
- {\r
- ob->xspeed = -16;\r
- ob->yspeed = -24;\r
- ob->state = &s_shellyjump1;\r
- xtry = ytry = 0;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Turn\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Turn(objtype *ob)\r
-{\r
- ob->xdir = -ob->xdir;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_ShellyFrag\r
-=\r
-===========================\r
-*/\r
-\r
-void T_ShellyFrag(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = 32;\r
- new->yspeed = -24;\r
- NewState(new, &s_shellypiece1);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = -32;\r
- new->yspeed = -24;\r
- NewState(new, &s_shellypiece2);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Shelly\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Shelly(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- ClipToSpriteSide(hit, ob);\r
- if (player->midx < ob->left || player->midx > ob->right)\r
- return;\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- }\r
- else if (hit->obclass == mshotobj)\r
- {\r
- RemoveObj(hit);\r
- }\r
- else\r
- return;\r
-\r
-explode:\r
- SD_PlaySound(SND_SHELLEYEXPLODE);\r
- if (ob->hitnorth)\r
- {\r
- ChangeState(ob, &s_shellydieup);\r
- }\r
- else\r
- {\r
- ChangeState(ob, &s_shellydie);\r
- }\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- NewState(new, &s_shellyboom1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Shelly\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Shelly(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove;\r
- ChangeState(ob, &s_shellylook);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Shell\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Shell(objtype *ob)\r
-{\r
- if (ob->hiteast || ob->hitwest)\r
- {\r
- ob->xspeed = 0;\r
- }\r
- if (ob->hitnorth)\r
- {\r
- SD_PlaySound(SND_SHELLEYEXPLODE);\r
- ChangeState(ob, &s_shellydie);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- NewState(new, &s_shellyboom1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K5_ACT3.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Shikadi Mine\r
-- Robo Red\r
-- Spirogrip\r
-- Spindred\r
-- Shikadi Master\r
-- Shikadi\r
-- Shockshund\r
-- Sphereful\r
-- Scottie\r
-- QED\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- SHIKADI MINE\r
-\r
-temp2 = x position of the "eye", in global units (relative to the mine sprite)\r
-temp3 = y position of the "eye", in global units (relative to the mine sprite)\r
-temp4 = sprite pointer for the "eye"\r
-\r
-=============================================================================\r
-*/\r
-\r
-static Uint16 dopposite[] = {2, 3, 0, 1, 6, 7, 4, 5, 8};\r
-\r
-statetype s_mine = {SHIKADIMINESPR, SHIKADIMINESPR, think, false, false, 8, 0, 0, T_Mine, C_Solid, R_Mine, NULL};\r
-statetype s_minecenter = {SHIKADIMINESPR, SHIKADIMINESPR, think, false, false, 0, 0, 0, T_MineCenter, C_Solid, R_Mine, &s_mineshift};\r
-statetype s_mineshift = {SHIKADIMINESPR, SHIKADIMINESPR, think, false, false, 0, 0, 0, T_MineShift, C_Solid, R_Mine, &s_mine};\r
-statetype s_mineboom1 = {SHIKADIMINEPULSE1SPR, SHIKADIMINEPULSE1SPR, step, false, false, 10, 0, 0, NULL, C_Solid, R_Draw, &s_mineboom2};\r
-statetype s_mineboom2 = {SHIKADIMINEPULSE2SPR, SHIKADIMINEPULSE2SPR, step, false, false, 10, 0, 0, NULL, C_Solid, R_Draw, &s_mineboom3};\r
-statetype s_mineboom3 = {SHIKADIMINEPULSE1SPR, SHIKADIMINEPULSE1SPR, step, false, false, 10, 0, 0, NULL, C_Solid, R_Draw, &s_mineboom4};\r
-statetype s_mineboom4 = {SHIKADIMINEPULSE2SPR, SHIKADIMINEPULSE2SPR, step, false, false, 10, 0, 0, T_MineFrag, C_Solid, R_Draw, &s_mineboom5};\r
-statetype s_mineboom5 = {SHIKADIMINEBOOM1SPR, SHIKADIMINEBOOM1SPR, step, false, false, 20, 0, 0, NULL, C_Spindread, R_Draw, &s_mineboom6};\r
-statetype s_mineboom6 = {SHIKADIMINEBOOM2SPR, SHIKADIMINEBOOM2SPR, step, false, false, 20, 0, 0, NULL, C_Spindread, R_Draw, NULL};\r
-statetype s_minepiece = {SHIKADIMINEPIECESPR, SHIKADIMINEPIECESPR, think, false, false, 8, 0, 0, T_Projectile, C_MineFrag, R_Bounce, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnMine\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnMine(Uint16 tileX, Uint16 tileY)\r
-{\r
- Sint16 i;\r
-\r
- GetNewObj(false);\r
- new->obclass = mineobj;\r
- new->active = ac_yes;\r
- new->needtoclip = cl_noclip;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -(31*PIXGLOBAL + 1);\r
- new->temp2 = 16*PIXGLOBAL;\r
- new->temp3 = 13*PIXGLOBAL;\r
- NewState(new, &s_mineshift);\r
- new->xspeed = TILEGLOBAL;\r
-\r
- for (i=0; i<=3; i++)\r
- {\r
- if (Walk(new, i))\r
- break;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= MinePosCheck\r
-=\r
-===========================\r
-*/\r
-\r
-boolean MinePosCheck(Uint16 tileX, Uint16 tileY)\r
-{\r
- Uint16 far *map;\r
- Uint16 x, y, tile;\r
-\r
- map = mapsegs[1] + mapbwidthtable[tileY]/2 + tileX;\r
- for (y=0; y<2; y++)\r
- {\r
- for (x=0; x<3; x++)\r
- {\r
- tile = *(map + y*mapwidth + x);\r
- if (tinf[tile+NORTHWALL] || tinf[tile+EASTWALL] || tinf[tile+SOUTHWALL] || tinf[tile+WESTWALL])\r
- return false;\r
- }\r
- }\r
- return true;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= Walk\r
-=\r
-===========================\r
-*/\r
-\r
-boolean Walk(objtype *ob, Sint16 dir)\r
-{\r
- Uint16 tileX, tileY;\r
-\r
- tileX = CONVERT_GLOBAL_TO_TILE(ob->x + xtry);\r
- tileY = CONVERT_GLOBAL_TO_TILE(ob->y + ytry);\r
-\r
- switch (dir)\r
- {\r
- case 0:\r
- if (MinePosCheck(tileX, tileY-1))\r
- {\r
- ob->xdir = 0;\r
- ob->ydir = -1;\r
- return true;\r
- }\r
- return false;\r
- case 1:\r
- if (MinePosCheck(tileX+1, tileY))\r
- {\r
- ob->xdir = 1;\r
- ob->ydir = 0;\r
- return true;\r
- }\r
- return false;\r
- case 2:\r
- if (MinePosCheck(tileX, tileY+1))\r
- {\r
- ob->xdir = 0;\r
- ob->ydir = 1;\r
- return true;\r
- }\r
- return false;\r
- case 3:\r
- if (MinePosCheck(tileX-1, tileY))\r
- {\r
- ob->xdir = -1;\r
- ob->ydir = 0;\r
- return true;\r
- }\r
- return false;\r
- default:\r
- Quit("Walk: Bad dir");\r
- }\r
- return false;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= ChaseThink\r
-=\r
-===========================\r
-*/\r
-\r
-void ChaseThink(objtype *ob)\r
-{\r
- Sint16 temp;\r
- Sint16 xdist, ydist, ydir, xdir;\r
- Sint16 olddir[2], oppdir;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- olddir[0] = 1;\r
- }\r
- else if (ob->xdir == -1)\r
- {\r
- olddir[0] = 3;\r
- }\r
- else if (ob->ydir == -1)\r
- {\r
- olddir[0] = 0;\r
- }\r
- else if (ob->ydir == 1)\r
- {\r
- olddir[0] = 2;\r
- }\r
- oppdir = dopposite[olddir[0]];\r
- xdist = player->x - (ob->x + xtry);\r
- ydist = player->y - (ob->y + ytry);\r
- xdir = 8;\r
- ydir = 8;\r
- if (xdist > 0)\r
- {\r
- xdir = 1;\r
- }\r
- if (xdist < 0)\r
- {\r
- xdir = 3;\r
- }\r
- if (ydist > 0)\r
- {\r
- ydir = 2;\r
- }\r
- if (ydist < 0)\r
- {\r
- ydir = 0;\r
- }\r
- if (abs(ydist) > abs(xdist))\r
- {\r
- temp = xdir;\r
- xdir = ydir;\r
- ydir = temp;\r
- }\r
- if (xdir == oppdir)\r
- {\r
- xdir = 8;\r
- }\r
- if (ydir == oppdir)\r
- {\r
- ydir = 8;\r
- }\r
- if (ydir != 8 && Walk(ob, ydir))\r
- {\r
- return;\r
- }\r
- if (xdir != 8 && Walk(ob, xdir))\r
- {\r
- return;\r
- }\r
- if (Walk(ob, olddir[0]))\r
- {\r
- return;\r
- }\r
- if (US_RndT() > 0x80)\r
- {\r
- for (temp=0; temp<=3; temp++)\r
- {\r
- if (temp != oppdir && Walk(ob, temp))\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- for (temp=3; temp>=0; temp--)\r
- {\r
- if (temp != oppdir && Walk(ob, temp))\r
- return;\r
- }\r
- }\r
- Walk(ob, oppdir);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Mine\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Mine(objtype *ob)\r
-{\r
- Sint16 oldxdir, oldydir;\r
- Sint16 xdist, ydist;\r
- Sint16 speed;\r
-\r
- xdist = ob->x - player->x;\r
- ydist = ob->y - player->y;\r
- if (xdist <= 2*TILEGLOBAL && xdist >= -5*TILEGLOBAL && ydist <= 3*TILEGLOBAL && ydist >= -5*PIXGLOBAL)\r
- {\r
- SD_PlaySound(SND_MINEEXPLODE);\r
- ob->state = &s_mineboom1;\r
- RF_RemoveSprite((void**)(&ob->temp4));\r
- }\r
- else\r
- {\r
- speed = tics * 10;\r
- if (ob->xspeed <= speed)\r
- {\r
- xtry = ob->xdir * ob->xspeed;\r
- ytry = ob->ydir * ob->xspeed; // yes, this uses xspeed!\r
- speed -= ob->xspeed;\r
- oldxdir = ob->xdir;\r
- oldydir = ob->ydir;\r
- ChaseThink(ob);\r
- ob->xspeed = TILEGLOBAL;\r
- if (ob->xdir != oldxdir || ob->ydir != oldydir)\r
- {\r
- ob->state = &s_minecenter;\r
- return;\r
- }\r
- }\r
- ob->xspeed -= speed;\r
- xtry += ob->xdir * speed;\r
- ytry += ob->ydir * speed;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Solid\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void C_Solid(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_MineFrag\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void C_MineFrag(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == qedobj)\r
- {\r
- SpawnFuseFlash(hit->tileleft, hit->tiletop);\r
- SpawnFuseFlash(hit->tileright, hit->tiletop);\r
- SpawnFuseFlash(hit->tileleft, hit->tilebottom);\r
- SpawnFuseFlash(hit->tileright, hit->tilebottom);\r
- RF_MapToMap(0, 0, 16, 11, 4, 2);\r
- RF_MapToMap(4, 0, 16, 13, 4, 2);\r
- SpawnDeadMachine();\r
- RemoveObj(hit);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_MineCenter\r
-=\r
-===========================\r
-*/\r
-\r
-void T_MineCenter(objtype *ob)\r
-{\r
- Sint16 px, py, xdist, ydist;\r
-\r
- xdist = ob->x - player->x;\r
- ydist = ob->y - player->y;\r
-\r
- if (xdist <= 2*TILEGLOBAL && xdist >= -3*TILEGLOBAL && ydist <= 3*TILEGLOBAL && ydist >= -3*TILEGLOBAL)\r
- {\r
- //BUG? this doesn't play a sound\r
- ob->state = &s_mineboom1;\r
- RF_RemoveSprite((void**)&ob->temp4);\r
- }\r
- else\r
- {\r
- ob->needtoreact = true;\r
-\r
- px = 16*PIXGLOBAL;\r
- py = 13*PIXGLOBAL;\r
-\r
- if (ob->temp2 < px)\r
- {\r
- ob->temp2 = ob->temp2 + tics*4;\r
- if (ob->temp2 >= px)\r
- {\r
- ob->temp2 = px;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- else if (ob->temp2 > px)\r
- {\r
- ob->temp2 = ob->temp2 - tics*4;\r
- if (ob->temp2 <= px)\r
- {\r
- ob->temp2 = px;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- if (ob->temp3 < py)\r
- {\r
- ob->temp3 = ob->temp3 + tics*4;\r
- if (ob->temp3 >= py)\r
- {\r
- ob->temp3 = py;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- else if (ob->temp3 > py)\r
- {\r
- ob->temp3 = ob->temp3 - tics*4;\r
- if (ob->temp3 <= py)\r
- {\r
- ob->temp3 = py;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_MineShift\r
-=\r
-===========================\r
-*/\r
-\r
-void T_MineShift(objtype *ob)\r
-{\r
- Sint16 px, py, xdist, ydist;\r
-\r
- xdist = ob->x - player->x;\r
- ydist = ob->y - player->y;\r
-\r
- if (xdist <= 2*TILEGLOBAL && xdist >= -3*TILEGLOBAL && ydist <= 3*TILEGLOBAL && ydist >= -3*TILEGLOBAL)\r
- {\r
- //BUG? this doesn't play a sound\r
- ob->state = &s_mineboom1;\r
- RF_RemoveSprite((void**)&ob->temp4);\r
- }\r
- else\r
- {\r
- ob->needtoreact = true;\r
-\r
- switch (ob->xdir)\r
- {\r
- case -1:\r
- px = 8*PIXGLOBAL;\r
- break;\r
- case 0:\r
- px = 16*PIXGLOBAL;\r
- break;\r
- case 1:\r
- px = 24*PIXGLOBAL;\r
- }\r
- switch (ob->ydir)\r
- {\r
- case -1:\r
- py = 5*PIXGLOBAL;\r
- break;\r
- case 0:\r
- py = 13*PIXGLOBAL;\r
- break;\r
- case 1:\r
- py = 21*PIXGLOBAL;\r
- }\r
-\r
- if (ob->temp2 < px)\r
- {\r
- ob->temp2 = ob->temp2 + tics*4;\r
- if (ob->temp2 >= px)\r
- {\r
- ob->temp2 = px;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- else if (ob->temp2 > px)\r
- {\r
- ob->temp2 = ob->temp2 - tics*4;\r
- if (ob->temp2 <= px)\r
- {\r
- ob->temp2 = px;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- if (ob->temp3 < py)\r
- {\r
- ob->temp3 = ob->temp3 + tics*4;\r
- if (ob->temp3 >= py)\r
- {\r
- ob->temp3 = py;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- else if (ob->temp3 > py)\r
- {\r
- ob->temp3 = ob->temp3 - tics*4;\r
- if (ob->temp3 <= py)\r
- {\r
- ob->temp3 = py;\r
- ob->state = ob->state->nextstate;\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_MineFrag\r
-=\r
-===========================\r
-*/\r
-\r
-void T_MineFrag(objtype *ob)\r
-{\r
- SD_PlaySound(SND_MINEEXPLODE);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = -(US_RndT()>>3);\r
- new->yspeed = -48;\r
- NewState(new, &s_minepiece);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x + TILEGLOBAL;\r
- new->y = ob->y;\r
- new->xspeed = (US_RndT()>>3);\r
- new->yspeed = -48;\r
- NewState(new, &s_minepiece);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = (US_RndT()>>4) + 40;\r
- new->yspeed = -24;\r
- NewState(new, &s_minepiece);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x + TILEGLOBAL;\r
- new->y = ob->y;\r
- new->xspeed = -40 - (US_RndT()>>4);\r
- new->yspeed = -24;\r
- NewState(new, &s_minepiece);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = 24;\r
- new->yspeed = 16;\r
- NewState(new, &s_minepiece);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x + TILEGLOBAL;\r
- new->y = ob->y;\r
- new->xspeed = 24;\r
- new->yspeed = 16;\r
- NewState(new, &s_minepiece);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Mine\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Mine(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- RF_PlaceSprite((void**)&ob->temp4, ob->x+ob->temp2, ob->y+ob->temp3, SHIKADIMINEEYESPR, spritedraw, 2);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- ROBO RED\r
-\r
-temp1 = number of shots to fire\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_robored = {ROBOREDLSPR, ROBOREDRSPR, step, false, true, 6, 64, 0, T_RoboRed, C_RoboRed, R_Walk, &s_robored};\r
-statetype s_roboredfire0 = {ROBOREDLSPR, ROBOREDRSPR, step, true, true, 40, 0, 0, NULL, C_Spindread, R_Draw, &s_roboredfire1};\r
-statetype s_roboredfire1 = {ROBOREDLSPR, ROBOREDRSPR, step, true, true, 4, 64, 0, NULL, C_Spindread, R_Draw, &s_roboredfire2};\r
-statetype s_roboredfire2 = {ROBOREDLSPR, ROBOREDRSPR, step, false, true, 6, 0, 0, T_RoboShoot, C_Spindread, R_Draw, &s_roboredfire1};\r
-statetype s_rshot1 = {ROBOSHOT1SPR, ROBOSHOT1SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_RShot, R_RShot, &s_rshot2};\r
-statetype s_rshot2 = {ROBOSHOT2SPR, ROBOSHOT2SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_RShot, R_RShot, &s_rshot1};\r
-statetype s_rshothit1 = {ROBOSHOTHIT1SPR, ROBOSHOTHIT1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_rshothit2};\r
-statetype s_rshothit2 = {ROBOSHOTHIT2SPR, ROBOSHOTHIT2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnRoboRed\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnRoboRed(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = roboredobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -4*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- NewState(new, &s_robored);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_RoboRed\r
-=\r
-===========================\r
-*/\r
-\r
-void T_RoboRed(objtype *ob)\r
-{\r
- if (!(ob->x & (4*PIXGLOBAL)) && player->bottom > ob->top && player->top < ob->bottom && US_RndT() < 16)\r
- {\r
- if (ob->x > player->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
- ob->temp1 = 10; // shoot 10 times\r
- ob->state = &s_roboredfire0;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_RoboRed\r
-=\r
-===========================\r
-*/\r
-\r
-void C_RoboRed(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- ob->xdir = (player->x > ob->x)? 1 : -1;\r
- ob->temp1 = 10; // shoot 10 times\r
- ChangeState(ob, &s_roboredfire0);\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_RoboShoot\r
-=\r
-===========================\r
-*/\r
-\r
-void T_RoboShoot(objtype *ob)\r
-{\r
- Uint16 x;\r
-\r
- if (--ob->temp1 == 0)\r
- {\r
- ob->state = &s_robored;\r
- }\r
- if (ob->xdir == 1)\r
- {\r
- x = ob->x + 56*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- x = ob->x;\r
- }\r
- if (CheckSpawnShot(x, ob->y + 32*PIXGLOBAL, &s_rshot1) != -1)\r
- {\r
- new->xspeed = ob->xdir * 60;\r
- if (ob->temp1 & 1)\r
- {\r
- new->yspeed = 8;\r
- }\r
- else\r
- {\r
- new->yspeed = -8;\r
- }\r
- SD_PlaySound(SND_ENEMYSHOT);\r
- xtry = (ob->xdir == 1)? -4*PIXGLOBAL : 4*PIXGLOBAL;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_RShot\r
-=\r
-===========================\r
-*/\r
-\r
-void C_RShot(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- ChangeState(ob, &s_rshothit1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_RShot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_RShot(objtype *ob)\r
-{\r
- if (ob->hitnorth || ob->hiteast || ob->hitsouth || ob->hitwest)\r
- {\r
- SD_PlaySound(SND_ENEMYSHOTEXPLODE);\r
- ChangeState(ob, &s_rshothit1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SPIROGRIP\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_gripsitd = {SPIROSITDSPR, SPIROSITDSPR, step, false, false, 150, 0, 0, NULL, C_Spindread, R_Draw, &s_gripjumpd};\r
-statetype s_gripjumpd = {SPIROSITDSPR, SPIROSITDSPR, slide, false, false, 64, 0, -16, NULL, C_Spindread, R_Draw, &s_gripspin7};\r
-statetype s_gripsitl = {SPIROSITLSPR, SPIROSITLSPR, step, false, false, 150, 0, 0, NULL, C_Spindread, R_Draw, &s_gripjumpl};\r
-statetype s_gripjumpl = {SPIROSITLSPR, SPIROSITLSPR, slide, false, false, 64, 16, 0, NULL, C_Spindread, R_Draw, &s_gripspin1};\r
-statetype s_gripsitr = {SPIROSITRSPR, SPIROSITRSPR, step, false, false, 150, 0, 0, NULL, C_Spindread, R_Draw, &s_gripjumpr};\r
-statetype s_gripjumpr = {SPIROSITRSPR, SPIROSITRSPR, slide, false, false, 64, -16, 0, NULL, C_Spindread, R_Draw, &s_gripspin5};\r
-statetype s_gripsitu = {SPIROSITUSPR, SPIROSITUSPR, step, false, false, 150, 0, 0, NULL, C_Spindread, R_Draw, &s_gripjumpu};\r
-statetype s_gripjumpu = {SPIROSITUSPR, SPIROSITUSPR, slide, false, false, 64, 0, 16, NULL, C_Spindread, R_Draw, &s_gripspin3};\r
-statetype s_gripspin1 = {SPIROSPINULSPR, SPIROSPINULSPR, step, false, false, 8, 0, 0, NULL, C_Spindread, R_Draw, &s_gripspin2};\r
-statetype s_gripspin2 = {SPIROSPINUSPR, SPIROSPINUSPR, step, false, false, 8, 0, 0, T_SpiroLaunch, C_Spindread, R_Draw, &s_gripspin3};\r
-statetype s_gripspin3 = {SPIROSPINURSPR, SPIROSPINURSPR, step, false, false, 8, 0, 0, NULL, C_Spindread, R_Draw, &s_gripspin4};\r
-statetype s_gripspin4 = {SPIROSPINRSPR, SPIROSPINRSPR, step, false, false, 8, 0, 0, T_SpiroLaunch, C_Spindread, R_Draw, &s_gripspin5};\r
-statetype s_gripspin5 = {SPIROSPINDRSPR, SPIROSPINDRSPR, step, false, false, 8, 0, 0, NULL, C_Spindread, R_Draw, &s_gripspin6};\r
-statetype s_gripspin6 = {SPIROSPINDSPR, SPIROSPINDSPR, step, false, false, 8, 0, 0, T_SpiroLaunch, C_Spindread, R_Draw, &s_gripspin7};\r
-statetype s_gripspin7 = {SPIROSPINDLSPR, SPIROSPINDLSPR, step, false, false, 8, 0, 0, NULL, C_Spindread, R_Draw, &s_gripspin8};\r
-statetype s_gripspin8 = {SPIROSPINLSPR, SPIROSPINLSPR, step, false, false, 8, 0, 0, T_SpiroLaunch, C_Spindread, R_Draw, &s_gripspin1};\r
-statetype s_gripflyd = {SPIROSITDSPR, SPIROSITDSPR, slide, false, false, 0, 0, 48, NULL, C_Spindread, R_SpiroFly, &s_gripsitd};\r
-statetype s_gripflyl = {SPIROSITLSPR, SPIROSITLSPR, slide, false, false, 0, -48, 0, NULL, C_Spindread, R_SpiroFly, &s_gripsitl};\r
-statetype s_gripflyr = {SPIROSITRSPR, SPIROSITRSPR, slide, false, false, 0, 48, 0, NULL, C_Spindread, R_SpiroFly, &s_gripsitr};\r
-statetype s_gripflyu = {SPIROSITUSPR, SPIROSITUSPR, slide, false, false, 0, 0, -48, NULL, C_Spindread, R_SpiroFly, &s_gripsitu};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSpirogrip\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSpirogrip(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = spirogripobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -1*TILEGLOBAL;\r
- new->xdir = 1;\r
- new->ydir = 1;\r
- NewState(new, &s_gripsitd);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SpiroLaunch\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SpiroLaunch(objtype *ob)\r
-{\r
- if (US_RndT() <= 20)\r
- {\r
- SD_PlaySound(SND_SPIROFLY);\r
- if (ob->state == &s_gripspin2)\r
- {\r
- ob->state = &s_gripflyu;\r
- }\r
- else if (ob->state == &s_gripspin4)\r
- {\r
- ob->state = &s_gripflyr;\r
- }\r
- else if (ob->state == &s_gripspin6)\r
- {\r
- ob->state = &s_gripflyd;\r
- }\r
- else if (ob->state == &s_gripspin8)\r
- {\r
- ob->state = &s_gripflyl;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_SpiroFly\r
-=\r
-===========================\r
-*/\r
-\r
-void R_SpiroFly(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- if (ob->hitnorth || ob->hiteast || ob->hitsouth || ob->hitwest)\r
- {\r
- ChangeState(ob, ob->state->nextstate);\r
- SD_PlaySound(SND_SPIROGRAB);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SPINDRED\r
-\r
-temp1 = bounce counter\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_spindred1 = {SPINDRED1SPR, SPINDRED1SPR, stepthink, false, false, 8, 0, 0, T_Spindread, C_Spindread, R_Spindread, &s_spindred2};\r
-statetype s_spindred2 = {SPINDRED2SPR, SPINDRED2SPR, stepthink, false, false, 8, 0, 0, T_Spindread, C_Spindread, R_Spindread, &s_spindred3};\r
-statetype s_spindred3 = {SPINDRED3SPR, SPINDRED3SPR, stepthink, false, false, 8, 0, 0, T_Spindread, C_Spindread, R_Spindread, &s_spindred4};\r
-statetype s_spindred4 = {SPINDRED4SPR, SPINDRED4SPR, stepthink, false, false, 8, 0, 0, T_Spindread, C_Spindread, R_Spindread, &s_spindred1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSpindread\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSpindread(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = spindredobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
- new->ydir = 1;\r
- NewState(new, &s_spindred1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Spindread\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Spindread(objtype *ob)\r
-{\r
- Sint32 i;\r
-\r
- // BUG: this might be executed twice during the same frame if the\r
- // object's animation/state changed during that frame, causing the\r
- // object to move at twice the speed during that frame!\r
- // To avoid that, return if ytry is not 0.\r
-\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- if (ob->ydir == 1)\r
- {\r
- if (ob->yspeed < 0 && ob->yspeed >= -3)\r
- {\r
- ytry += ob->yspeed;\r
- ob->yspeed = 0;\r
- return;\r
- }\r
- else\r
- {\r
- ob->yspeed += 3;\r
- if (ob->yspeed > 70)\r
- {\r
- ob->yspeed = 70;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- if (ob->yspeed > 0 && ob->yspeed <= 3)\r
- {\r
- ytry += ob->yspeed;\r
- ob->yspeed = 0;\r
- return;\r
- }\r
- else\r
- {\r
- ob->yspeed -= 3;\r
- if (ob->yspeed < -70)\r
- {\r
- ob->yspeed = -70;\r
- }\r
- }\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Spindread\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void C_Spindread(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Spindread\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Spindread(objtype *ob)\r
-{\r
- if (ob->hitsouth)\r
- {\r
- ob->yspeed = 0;\r
- if (ob->ydir == -1)\r
- {\r
- if (++ob->temp1 == 3)\r
- {\r
- ob->temp1 = 0;\r
- ob->yspeed = 68;\r
- ob->ydir = -ob->ydir;\r
- SD_PlaySound(SND_SPINDREDFLIP);\r
- }\r
- else\r
- {\r
- SD_PlaySound(SND_SPINDREDBOUNCE);\r
- ob->yspeed = 40;\r
- }\r
- }\r
- }\r
- if (ob->hitnorth)\r
- {\r
- ob->yspeed = 0;\r
- if (ob->ydir == 1)\r
- {\r
- if (++ob->temp1 == 3)\r
- {\r
- ob->temp1 = 0;\r
- ob->yspeed = -68;\r
- ob->ydir = -ob->ydir;\r
- SD_PlaySound(SND_BOUNCE);\r
- }\r
- else\r
- {\r
- SD_PlaySound(SND_SPINDREDBOUNCE);\r
- ob->yspeed = -40;\r
- }\r
- }\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SHIKADI MASTER\r
-\r
-temp1 = defines next action (0 = shoot, 1 = teleport)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_master1 = {MASTER1SPR, MASTER1SPR, step, false, false, 8, 0, 0, NULL, C_Master, R_Draw, &s_master2};\r
-statetype s_master2 = {MASTER2SPR, MASTER2SPR, step, false, false, 8, 0, 0, NULL, C_Master, R_Draw, &s_master3};\r
-statetype s_master3 = {MASTER3SPR, MASTER3SPR, step, false, false, 8, 0, 0, NULL, C_Master, R_Draw, &s_master4};\r
-statetype s_master4 = {MASTER4SPR, MASTER4SPR, step, false, false, 8, 0, 0, T_Master, C_Master, R_Draw, &s_master1};\r
-statetype s_mastershoot1 = {SHIKMASTERCASTLSPR, SHIKMASTERCASTRSPR, step, false, false, 30, 0, 0, T_MasterShoot, C_Spindread, R_Draw, &s_mastershoot2};\r
-statetype s_mastershoot2 = {SHIKMASTERCASTLSPR, SHIKMASTERCASTRSPR, step, false, false, 8, 0, 0, NULL, C_Spindread, R_Draw, &s_master1};\r
-statetype s_mastertport1 = {MASTERTELEPORT1SPR, MASTERTELEPORT1SPR, step, false, true, 20, 0, 0, NULL, C_Spindread, R_Draw, &s_mastertport2};\r
-statetype s_mastertport2 = {MASTERTELEPORT2SPR, MASTERTELEPORT2SPR, step, false, true, 20, 0, 0, T_MasterTPort, C_Spindread, R_Draw, &s_mastertport3};\r
-statetype s_mastertport3 = {MASTERTELEPORT2SPR, MASTERTELEPORT2SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Land, &s_mastertport4};\r
-statetype s_mastertport4 = {MASTERTELEPORT2SPR, MASTERTELEPORT2SPR, step, false, false, 60, 0, 0, NULL, C_Spindread, R_Draw, &s_master1};\r
-statetype s_mshot1 = {MASTERSHOT4SPR, MASTERSHOT1SPR, stepthink, false, false, 8, 0, 0, T_WeakProjectile, C_MShot, R_MShot, &s_mshot2};\r
-statetype s_mshot2 = {MASTERSHOT3SPR, MASTERSHOT2SPR, stepthink, false, false, 8, 0, 0, T_WeakProjectile, C_MShot, R_MShot, &s_mshot3};\r
-statetype s_mshot3 = {MASTERSHOT2SPR, MASTERSHOT3SPR, stepthink, false, false, 8, 0, 0, T_WeakProjectile, C_MShot, R_MShot, &s_mshot4};\r
-statetype s_mshot4 = {MASTERSHOT1SPR, MASTERSHOT4SPR, stepthink, false, false, 8, 0, 0, T_WeakProjectile, C_MShot, R_MShot, &s_mshot1};\r
-statetype s_mspray1 = {MASTERFLOORSPARK1SPR, MASTERFLOORSPARK1SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_MShot, R_MSpray, &s_mspray2};\r
-statetype s_mspray2 = {MASTERFLOORSPARK2SPR, MASTERFLOORSPARK2SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_MShot, R_MSpray, &s_mspray3};\r
-statetype s_mspray3 = {MASTERFLOORSPARK3SPR, MASTERFLOORSPARK3SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_MShot, R_MSpray, &s_mspray4};\r
-statetype s_mspray4 = {MASTERFLOORSPARK4SPR, MASTERFLOORSPARK4SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_MShot, R_MSpray, &s_mspray1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnMaster\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnMaster(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = shikadimasterobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -24*PIXGLOBAL;\r
- NewState(new, &s_master1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Master\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Master(objtype *ob)\r
-{\r
- Sint16 randval;\r
-\r
- randval = US_RndT();\r
- if (randval < 0x40)\r
- {\r
- if (ob->temp1)\r
- {\r
- ob->state = &s_mastertport1;\r
- ob->temp1 = 0;\r
- }\r
- else\r
- {\r
- ob->temp1 = 1;\r
- if (player->x > ob->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- ob->state = &s_mastershoot1;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_MasterShoot\r
-=\r
-===========================\r
-*/\r
-\r
-void T_MasterShoot(objtype *ob)\r
-{\r
- Uint16 x;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- x = ob->x + 16*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- x = ob->x;\r
- }\r
- if (CheckSpawnShot(x, ob->y+8*PIXGLOBAL, &s_mshot1) != -1)\r
- {\r
- new->xspeed = ob->xdir * 48;\r
- new->yspeed = -16;\r
- SD_PlaySound(SND_MASTERATTACK);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Master\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Master(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- ob->xdir = (player->x > ob->x)? 1 : -1;\r
- ob->temp1 = 1;\r
- ChangeState(ob, &s_mastershoot1);\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_MasterTPort\r
-=\r
-===========================\r
-*/\r
-\r
-void T_MasterTPort(objtype *ob)\r
-{\r
- Uint16 tile;\r
- Sint16 tx, ty, redos, oldx, oldy;\r
-\r
- oldx = ob->x;\r
- oldy = ob->y;\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = 48;\r
- NewState(new, &s_mspray1); // BUG? new object is not made removable\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = -48;\r
- NewState(new, &s_mspray1); // BUG? new object is not made removable\r
-\r
- SD_PlaySound(SND_MASTERBLAST);\r
-\r
- redos = 0;\r
-redo:\r
- if (++redos == 10)\r
- {\r
- US_RndT(); // call it, but ignore the result\r
- // probably to avoid repeatedly getting the same same "random" values\r
- // due to having an even number of US_RndT() calls in this routine and\r
- // an even number of elements in the random table.\r
-\r
- ob->state = &s_master1;\r
- ob->x = oldx - 1;\r
- ob->y = oldy;\r
- xtry = 1;\r
- ytry = 0;\r
- }\r
- else\r
- {\r
- tx = player->tilemidx - 16 + (US_RndT()>>3);\r
- ty = player->tilebottom - 16 + (US_RndT()>>3);\r
- if (tx < 2 || ty < 2 || tx > mapwidth-5 || ty > mapheight-5)\r
- goto redo;\r
-\r
-\r
- ob->x = CONVERT_TILE_TO_GLOBAL(tx);\r
- ob->y = CONVERT_TILE_TO_GLOBAL(ty);\r
- ob->tileleft = tx-1;\r
- ob->tileright = tx+4;\r
- ob->tiletop = ty-1;\r
- ob->tilebottom = ty+4;\r
-\r
- {\r
- Uint16 x, y;\r
- Uint16 far *map;\r
- Uint16 mapdelta;\r
-\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft;\r
- mapdelta = mapwidth - (ob->tileright - ob->tileleft + 1);\r
-\r
- for (y = ob->tiletop; ob->tilebottom >= y; y++, map+=mapdelta)\r
- {\r
- for (x = ob->tileleft; ob->tileright >= x; x++)\r
- {\r
- tile = *map++;\r
- if ((tinf[tile+INTILE] & INTILE_FOREGROUND) || tinf[tile+NORTHWALL] || tinf[tile+EASTWALL]\r
- || tinf[tile+SOUTHWALL] || tinf[tile+WESTWALL])\r
- {\r
- goto redo;\r
- }\r
- }\r
- }\r
- xtry = ytry = 0;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_MShot\r
-=\r
-===========================\r
-*/\r
-\r
-void C_MShot(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- RemoveObj(ob);\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- RemoveObj(ob);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_MShot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_MShot(objtype *ob)\r
-{\r
- if (ob->hiteast || ob->hitwest)\r
- {\r
- ob->xspeed = -ob->xspeed;\r
- }\r
- if (ob->hitsouth)\r
- {\r
- ob->yspeed = 0;\r
- }\r
- if (ob->hitnorth)\r
- {\r
- SD_PlaySound(SND_MASTERATTACK);\r
- ob->xspeed = 48;\r
- ChangeState(ob, &s_mspray1);\r
-\r
- GetNewObj(true);\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->xspeed = -48;\r
- NewState(new, &s_mspray1); // BUG? new object is not made removable\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_MSpray\r
-=\r
-===========================\r
-*/\r
-\r
-void R_MSpray(objtype *ob)\r
-{\r
- if (ob->hiteast || ob->hitwest)\r
- {\r
- RemoveObj(ob);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SHIKADI\r
-\r
-temp1 = x tile position of the pole being grabbed (is set but never used)\r
-temp2 = health\r
-temp3 = flash countdown\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_shikadi1 = {SHIKADI1SPR, SHIKADI1SPR, step, false, true, 8, 0, 0, NULL, C_Shikadi, R_Shikadi, &s_shikadi2};\r
-statetype s_shikadi2 = {SHIKADI2SPR, SHIKADI2SPR, step, false, true, 8, 0, 0, NULL, C_Shikadi, R_Shikadi, &s_shikadi3};\r
-statetype s_shikadi3 = {SHIKADI3SPR, SHIKADI3SPR, step, false, true, 8, 0, 0, NULL, C_Shikadi, R_Shikadi, &s_shikadi4};\r
-statetype s_shikadi4 = {SHIKADI4SPR, SHIKADI4SPR, step, false, true, 8, 0, 0, NULL, C_Shikadi, R_Shikadi, &s_shikadiwalk1};\r
-statetype s_shikadiwalk1 = {SHIKADIWALKL1SPR, SHIKADIWALKR1SPR, step, false, true, 8, 128, 0, T_Shikadi, C_Shikadi, R_Shikadi, &s_shikadiwalk2};\r
-statetype s_shikadiwalk2 = {SHIKADIWALKL2SPR, SHIKADIWALKR2SPR, step, false, true, 8, 128, 0, T_Shikadi, C_Shikadi, R_Shikadi, &s_shikadiwalk3};\r
-statetype s_shikadiwalk3 = {SHIKADIWALKL3SPR, SHIKADIWALKR3SPR, step, false, true, 8, 128, 0, T_Shikadi, C_Shikadi, R_Shikadi, &s_shikadiwalk4};\r
-statetype s_shikadiwalk4 = {SHIKADIWALKL4SPR, SHIKADIWALKR4SPR, step, false, true, 8, 128, 0, T_Shikadi, C_Shikadi, R_Shikadi, &s_shikadiwalk1};\r
-statetype s_shikadigrab = {SHIKADIGRABLSPR, SHIKADIGRABRSPR, step, false, true, 20, 0, 0, T_PoleShock, C_Shikadi, R_Shikadi, &s_shikadigrab2};\r
-statetype s_shikadigrab2 = {SHIKADIGRABLSPR, SHIKADIGRABRSPR, step, false, true, 20, 0, 0, NULL, C_Shikadi, R_Shikadi, &s_shikadiwalk1};\r
-statetype s_shikadistun = {SHIKADISTUNSPR, SHIKADISTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-statetype s_polespark1 = {SHIKADIPOLESPARK1SPR, SHIKADIPOLESPARK1SPR, stepthink, false, false, 0, 0, 0, T_PoleSpark, C_Lethal, R_Draw, &s_polespark2};\r
-statetype s_polespark2 = {SHIKADIPOLESPARK1SPR, SHIKADIPOLESPARK1SPR, stepthink, false, false, 0, 0, 0, T_PoleSpark, C_Lethal, R_Draw, &s_polespark1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnShikadi\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnShikadi(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = shikadiobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -1*TILEGLOBAL;\r
- new->temp2 = 4; // health\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- NewState(new, &s_shikadi1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Shikadi\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Shikadi(objtype *ob)\r
-{\r
- Uint16 tx, tile;\r
-\r
- if (player->state->contact == &KeenPosContact\r
- || ob->bottom - player->bottom + TILEGLOBAL <= 2*TILEGLOBAL)\r
- {\r
- if (ob->x > player->x + TILEGLOBAL)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else if (ob->x < player->x - TILEGLOBAL)\r
- {\r
- ob->xdir = 1;\r
- }\r
- if (ob->xdir == 1)\r
- {\r
- tx = ob->tileright;\r
- }\r
- else\r
- {\r
- tx = ob->tileleft;\r
- }\r
-\r
- if (player->tilemidx != tx)\r
- return;\r
- }\r
- else\r
- {\r
- if (US_RndT() < 0x10)\r
- {\r
- xtry = 0;\r
- ob->state = &s_shikadi1;\r
- return;\r
- }\r
- if ((ob->x & 0xFF) || !OnScreen(ob))\r
- return;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- tx = ob->tileright;\r
- }\r
- else\r
- {\r
- tx = ob->tileleft;\r
- }\r
- }\r
-\r
- tile = *(mapsegs[1]+mapbwidthtable[ob->tiletop]/2 + tx);\r
- if (tinf[tile+INTILE] == INTILE_POLE)\r
- {\r
- ob->temp1 = tx;\r
- ob->state = &s_shikadigrab;\r
- xtry = 0;\r
- SD_PlaySound(SND_SHIKADIATTACK);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Shikadi\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Shikadi(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- if (hit->obclass == stunshotobj)\r
- {\r
- if (--ob->temp2 == 0) // handle health\r
- {\r
- ob->xspeed = 0;\r
- ob->yspeed = 0;\r
- StunObj(ob, hit, &s_shikadistun);\r
- }\r
- else\r
- {\r
- ob->temp3 = 2; // draw white two times\r
- ob->needtoreact = true;\r
- ExplodeShot(hit);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PoleShock\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PoleShock(objtype *ob)\r
-{\r
- Uint16 x;\r
-\r
- ob->nothink = 2;\r
- if (ob->xdir == 1)\r
- {\r
- x = CONVERT_TILE_TO_GLOBAL(ob->tileright);\r
- }\r
- else\r
- {\r
- x = CONVERT_TILE_TO_GLOBAL(ob->tileleft);\r
- }\r
-\r
- GetNewObj(true);\r
- new->x = x;\r
- new->y = ob->y + 8*PIXGLOBAL;\r
- new->obclass = mshotobj;\r
- new->active = ac_removable;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_polespark1);\r
- if (ob->y < player->y)\r
- {\r
- new->ydir = 1;\r
- }\r
- else\r
- {\r
- new->ydir = -1;\r
- }\r
- SD_PlaySound(SND_SHIKADIATTACK);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PoleSpark\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PoleSpark(objtype *ob)\r
-{\r
- Uint16 tile;\r
-\r
- if (ytry == 0)\r
- {\r
- ytry = ob->ydir * 48;\r
- tile = *(mapsegs[1]+mapbwidthtable[ob->tiletop]/2 + ob->tilemidx);\r
- if (tinf[tile+INTILE] != INTILE_POLE)\r
- {\r
- ob->state = NULL;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Shikadi\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Shikadi(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- if (ob->temp3)\r
- {\r
- ob->temp3--;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, maskdraw, ob->priority);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- PET (a.k.a. SHOCKSHUND)\r
-\r
-temp1 = countdown for sit animation\r
-temp2 = health\r
-temp3 = flash countdown\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_petsit1 = {PETSIT1SPR, PETSIT1SPR, step, false, true, 8, 0, 0, NULL, C_Pet, R_Pet, &s_petsit2};\r
-statetype s_petsit2 = {PETSIT2SPR, PETSIT2SPR, step, false, true, 8, 0, 0, T_PetSit, C_Pet, R_Pet, &s_petsit1};\r
-statetype s_petbark1 = {PETBARKL1SPR, PETBARKR1SPR, step, false, true, 8, 0, 0, NULL, C_Pet, R_Pet, &s_petbark2};\r
-statetype s_petbark2 = {PETBARKL2SPR, PETBARKR2SPR, step, false, true, 8, 0, 0, T_PetBark, C_Pet, R_Pet, &s_pet1};\r
-statetype s_pet1 = {PETRUNL1SPR, PETRUNR1SPR, step, false, true, 8, 128, 0, NULL, C_Pet, R_Pet, &s_pet2};\r
-statetype s_pet2 = {PETRUNL2SPR, PETRUNR2SPR, step, false, true, 8, 128, 0, NULL, C_Pet, R_Pet, &s_pet3};\r
-statetype s_pet3 = {PETRUNL3SPR, PETRUNR3SPR, step, false, true, 8, 128, 0, NULL, C_Pet, R_Pet, &s_pet4};\r
-statetype s_pet4 = {PETRUNL4SPR, PETRUNR4SPR, step, false, true, 8, 128, 0, T_Pet, C_Pet, R_Pet, &s_pet1};\r
-statetype s_petjump = {PETJUMPLSPR, PETJUMPRSPR, think, false, false, 8, 128, 0, T_Projectile, C_Pet, R_PetJump, &s_pet2};\r
-statetype s_pshot1 = {PETSPARK1SPR, PETSPARK1SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_PShot, R_PShot, &s_pshot2};\r
-statetype s_pshot2 = {PETSPARK2SPR, PETSPARK2SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_PShot, R_PShot, &s_pshot1};\r
-statetype s_pshothot1 = {PETSPARKHIT1SPR, PETSPARKHIT1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_pshothot2};\r
-statetype s_pshothot2 = {PETSPARKHIT2SPR, PETSPARKHIT2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
-statetype s_petstun = {PETSTUNSPR, PETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnPet\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnPet(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = petobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
- new->temp2 = 2; // health\r
- new->xdir = new->ydir = 1;\r
- NewState(new, &s_pet1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Pet\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Pet(objtype *ob)\r
-{\r
- if (ob->x > player->x)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
- if (US_RndT() < 0x10)\r
- {\r
- xtry = 0;\r
- ob->state = &s_petsit1;\r
- ob->temp1 = 10; // repeat animation 10 times;\r
- }\r
- else\r
- {\r
- if (ob->bottom != player->bottom)\r
- {\r
- ob->state = &s_petjump;\r
- if (ob->xdir == 1)\r
- {\r
- ob->xspeed = 40;\r
- }\r
- else\r
- {\r
- ob->xspeed = -40;\r
- }\r
- ob->yspeed = -40;\r
- }\r
- if (US_RndT() < 0x80)\r
- {\r
- xtry = 0;\r
- ob->state = &s_petbark1;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PetSit\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PetSit(objtype *ob)\r
-{\r
- if (--ob->temp1 == 0)\r
- {\r
- ob->state = &s_pet1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_PetBark\r
-=\r
-===========================\r
-*/\r
-\r
-void T_PetBark(objtype *ob)\r
-{\r
- Uint16 x;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- x = ob->x + 7*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- x = ob->x;\r
- }\r
- if (CheckSpawnShot(x, ob->y+4*PIXGLOBAL, &s_pshot1) != -1)\r
- {\r
- new->xspeed = ob->xdir * 60;\r
- new->xdir = ob->xdir;\r
- SD_PlaySound(SND_SHOCKSHUNDBARK);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Pet\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Pet(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- if (hit->obclass == stunshotobj) // no 'else if' in the original code!\r
- {\r
- if (--ob->temp2 == 0) // handle health\r
- {\r
- ob->xspeed = 0;\r
- ob->yspeed = 0;\r
- StunObj(ob, hit, &s_petstun);\r
- }\r
- else\r
- {\r
- ob->temp3 = 2; // draw white two times\r
- ob->needtoreact = true;\r
- ExplodeShot(hit);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Pet\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Pet(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- if ((ob->xdir == 1 && player->x > ob->x) || (ob->xdir == -1 && player->x < ob->x))\r
- {\r
- ChangeState(ob, &s_petjump);\r
- if (ob->xdir == 1)\r
- {\r
- ob->xspeed = 40;\r
- }\r
- else\r
- {\r
- ob->xspeed = -40;\r
- }\r
- ob->yspeed = -40;\r
- }\r
- else\r
- {\r
- ob->x -= ob->xmove*2;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- }\r
- if (ob->temp3)\r
- {\r
- ob->temp3--;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, maskdraw, ob->priority);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_PetJump\r
-=\r
-===========================\r
-*/\r
-\r
-void R_PetJump(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- {\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, &s_pet1);\r
- }\r
- if (ob->temp3)\r
- {\r
- ob->temp3--;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, maskdraw, ob->priority);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_PShot\r
-=\r
-===========================\r
-*/\r
-\r
-void C_PShot(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- ChangeState(ob, &s_pshothot1);\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_pshothot1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_PShot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_PShot(objtype *ob)\r
-{\r
- if (ob->hitnorth || ob->hiteast || ob->hitsouth || ob->hitwest)\r
- {\r
- SD_PlaySound(SND_SHOCKBALLEXPLODE);\r
- ChangeState(ob, &s_pshothot1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SPHEREFUL\r
-\r
-temp1 ... temp4 = sprite pointers for the guards circling around the sphere\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_sphereful1 = {SPHEREFUL1SPR, SPHEREFUL1SPR, stepthink, false, false, 6, 0, 0, T_Sphereful, C_Spindread, R_Sphereful, &s_sphereful2};\r
-statetype s_sphereful2 = {SPHEREFUL2SPR, SPHEREFUL2SPR, stepthink, false, false, 6, 0, 0, T_Sphereful, C_Spindread, R_Sphereful, &s_sphereful3};\r
-statetype s_sphereful3 = {SPHEREFUL3SPR, SPHEREFUL3SPR, stepthink, false, false, 6, 0, 0, T_Sphereful, C_Spindread, R_Sphereful, &s_sphereful4};\r
-statetype s_sphereful4 = {SPHEREFUL4SPR, SPHEREFUL4SPR, stepthink, false, false, 6, 0, 0, T_Sphereful, C_Spindread, R_Sphereful, &s_sphereful1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSphereful\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSphereful(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = spherefulobj;\r
- new->needtoclip = cl_fullclip;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -1*TILEGLOBAL;\r
- new->priority = 1;\r
- NewState(new, &s_sphereful1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Sphereful\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Sphereful(objtype *ob)\r
-{\r
- Sint32 i;\r
- ob->needtoreact = true;\r
-\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (xtry == 0 && ytry == 0)\r
- {\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (!(i & 0xF))\r
- {\r
- if (ob->yspeed < 8)\r
- ob->yspeed++;\r
-\r
- if (ob->x < player->x && ob->xspeed < 8)\r
- ob->xspeed++;\r
-\r
- if (ob->x > player->x && ob->xspeed > -8)\r
- ob->xspeed--;\r
- }\r
- ytry += ob->yspeed;\r
- xtry += ob->xspeed;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Sphereful\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Sphereful(objtype *ob)\r
-{\r
- static Uint16 circle[16] = {\r
- 384, 369, 328, 265, 192, 119, 58, 15,\r
- 0, 15, 58, 119, 192, 265, 328, 369\r
- };\r
-\r
- Uint16 index, shapenum, priority;\r
-\r
- if (ob->hitwest || ob->hiteast)\r
- {\r
- ob->xspeed = -ob->xspeed;\r
- SD_PlaySound(SND_SPHEREFULBOUNCE);\r
- }\r
- if (ob->hitsouth)\r
- {\r
- ob->yspeed = -ob->yspeed;\r
- SD_PlaySound(SND_SPHEREFULBOUNCE);\r
- }\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->yspeed = -ob->yspeed;\r
- if (player->y < ob->y)\r
- {\r
- ob->yspeed--;\r
- }\r
- else\r
- {\r
- ob->yspeed++;\r
- }\r
- if (ob->yspeed > -4)\r
- {\r
- ob->yspeed = -4;\r
- }\r
- else if (ob->yspeed < -12)\r
- {\r
- ob->yspeed = -12;\r
- }\r
- SD_PlaySound(SND_BOUNCE);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- index = ((Uint16)lasttimecount / 8) & 0xF;\r
- shapenum = index / 4 + SPHEREGUARD1SPR;\r
- if (index >= 8)\r
- {\r
- priority = 2;\r
- }\r
- else\r
- {\r
- priority = 0;\r
- }\r
- RF_PlaceSprite((void**)&ob->temp1, ob->x+circle[index], ob->y+circle[index], shapenum, spritedraw, priority);\r
- RF_PlaceSprite((void**)&ob->temp2, ob->x+24*PIXGLOBAL-circle[index], ob->y+circle[index], shapenum, spritedraw, priority);\r
-\r
- index += 8;\r
- index &= 0xF;\r
- if (index >= 8)\r
- {\r
- priority = 2;\r
- }\r
- else\r
- {\r
- priority = 0;\r
- }\r
- RF_PlaceSprite((void**)&ob->temp3, ob->x+circle[index], ob->y+circle[index], shapenum, spritedraw, priority);\r
- RF_PlaceSprite((void**)&ob->temp4, ob->x+24*PIXGLOBAL-circle[index], ob->y+circle[index], shapenum, spritedraw, priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SCOTTIE\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_scottie1 = {SCOTTIEWALKL1SPR, SCOTTIEWALKR1SPR, step, false, true, 8, 128, 0, T_Scottie, C_Scottie, R_Walk, &s_scottie2};\r
-statetype s_scottie2 = {SCOTTIEWALKL2SPR, SCOTTIEWALKR2SPR, step, false, true, 8, 128, 0, T_Scottie, C_Scottie, R_Walk, &s_scottie3};\r
-statetype s_scottie3 = {SCOTTIEWALKL3SPR, SCOTTIEWALKR3SPR, step, false, true, 8, 128, 0, T_Scottie, C_Scottie, R_Walk, &s_scottie4};\r
-statetype s_scottie4 = {SCOTTIEWALKL4SPR, SCOTTIEWALKR4SPR, step, false, true, 8, 128, 0, T_Scottie, C_Scottie, R_Walk, &s_scottie1};\r
-statetype s_scottieface = {SCOTTIEFACESPR, SCOTTIEFACESPR, step, false, true, 30, 0, 0, NULL, C_Scottie, R_Walk, &s_scottie1};\r
-statetype s_scottiestun = {SCOTTIESTUNSPR, SCOTTIESTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnScottie\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnScottie(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = scottieobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- NewState(new, &s_scottie1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Scottie\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Scottie(objtype *ob)\r
-{\r
- if (US_RndT() < 0x10)\r
- {\r
- xtry = 0;\r
- if (US_RndT() < 0x80)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- ob->state = &s_scottieface;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Scottie\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Scottie(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj && hit->state->contact)\r
- {\r
- ClipToSpriteSide(hit, ob);\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_scottiestun);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- QED\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_qed = {-1, -1, step, false, true, 8, 128, 0, NULL, NULL, NULL, &s_qed};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnQed\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnQed(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = qedobj;\r
- new->active = ac_yes;\r
- new->tileleft = tileX;\r
- new->tiletop = tileY;\r
- new->tileright = new->tileleft + 1;\r
- new->tilebottom = new->tiletop + 1;\r
- new->x = new->left = CONVERT_TILE_TO_GLOBAL(tileX) + -1*PIXGLOBAL;\r
- new->y = new->top = CONVERT_TILE_TO_GLOBAL(tileY) + -1*PIXGLOBAL;\r
- new->right = new->left + 34*PIXGLOBAL;\r
- new->bottom = new->top + 34*PIXGLOBAL;\r
- NewState(new, &s_qed);\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __K5_DEF__\r
-#define __K5_DEF__\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-#define MINMEMORY 255000l\r
-#else\r
-#define MINMEMORY 310000l\r
-#endif\r
-\r
-#define STARPALETTE {0, 1, 24, 30, 31, 28, 6, 7, 19, 19, 19, 19, 19, 19, 19, 19, 0}\r
-#define INTROPALETTE {0, 4, 4, 28, 1, 1, 1, 1, 17, 17, 17, 17, 19, 19, 19, 19, 0}\r
-#define SHRINKPALETTE {0, 4, 4, 28, 1, 1, 1, 1, 17, 17, 17, 17, 19, 19, 19, 4, 0}\r
-\r
-#define HIGHSCORE_LEFT 40\r
-#define HIGHSCORE_TOP 35\r
-#define HIGHSCORE_RIGHT 280\r
-#define HIGHSCORE_MAP 15\r
-\r
-#define STATUS_PRESSKEY_X 120\r
-\r
-#define WORLDMAPNAME "Armageddon"\r
-#define DROPSNAME "VITALIN"\r
-\r
-#define STARWARSMUSIC 17\r
-#define ENDINGMUSIC 14\r
-\r
-// levels in this range can NOT be re-entered (BWB level should be > MAXDONELEVEL)\r
-#define MINDONELEVEL 1\r
-#define MAXDONELEVEL 17\r
-\r
-#define INACTIVATEDIST 6\r
-\r
-//\r
-// tiles for worldmap teleporters\r
-//\r
-#define TELEPORTERTILE1 2687 // tile animation for teleporting out\r
-#define TELEPORTERTILE2 1063 // tile after teleporting out\r
-#define TELEPORTERTILE3 TELEPORTERTILE1 // tile animation for teleporting in\r
-#define TELEPORTERTILE4 0 // tile after teleporting in\r
-\r
-#define TELEPORERTILEMASK 1 // animation has 2 frames\r
-\r
-/*\r
-=============================================================================\r
-\r
- K5_SPEC DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern char far swtext[];\r
-extern char far *levelnames[GAMELEVELS];\r
-extern char far *levelenter[GAMELEVELS];\r
-\r
-void OpenMapDoor(Sint16 tileX, Sint16 tileY);\r
-void CloseMapDoor(Sint16 tileX, Sint16 tileY);\r
-void ScanInfoPlane(void);\r
-void GameOver(void);\r
-\r
-void FinishedFuse(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K5_ACT1 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern Sint16 pdirx[];\r
-extern Sint16 pdiry[];\r
-\r
-Sint16 CheckSpawnShot(Uint16 x, Uint16 y, statetype *state);\r
-void C_ClipSide(objtype *ob, objtype *hit);\r
-void C_ClipTop(objtype *ob, objtype *hit);\r
-void R_Land(objtype *ob);\r
-void R_Bounce(objtype *ob);\r
-\r
-extern statetype s_bonus1;\r
-extern statetype s_bonus2;\r
-extern statetype s_bonusfly1;\r
-extern statetype s_bonusfly2;\r
-extern statetype s_bonusrise;\r
-extern statetype s_splash1;\r
-extern statetype s_splash2;\r
-extern statetype s_splash3;\r
-extern statetype s_splash4;\r
-\r
-extern Uint16 bonusshape[];\r
-\r
-void SpawnBonus(Uint16 tileX, Uint16 tileY, Uint16 type);\r
-void SpawnSplash(Uint16 tileX, Uint16 tileY);\r
-void T_Bonus(objtype *ob);\r
-void T_FlyBonus(objtype *ob);\r
-\r
-extern statetype s_teleport1;\r
-extern statetype s_teleport2;\r
-extern statetype s_teleportzap1;\r
-extern statetype s_teleportzap2;\r
-\r
-void SpawnTeleport(void);\r
-\r
-extern statetype s_fuseflash1;\r
-extern statetype s_fuseflash2;\r
-extern statetype s_fuseflash3;\r
-\r
-void SpawnFuseFlash(Uint16 tileX, Uint16 tileY);\r
-\r
-extern statetype s_deadmachine;\r
-\r
-void SpawnDeadMachine(void);\r
-void T_DeadMachine(objtype *ob);\r
-\r
-extern statetype s_platform;\r
-extern statetype s_slotplat1;\r
-extern statetype s_slotplat2;\r
-\r
-void SpawnPlatform(Uint16 tileX, Uint16 tileY, Sint16 dir, Sint16 type);\r
-void T_Platform(objtype *ob);\r
-void T_Slotplat(objtype *ob);\r
-\r
-extern statetype s_dropplatsit;\r
-extern statetype s_dropplatfall;\r
-extern statetype s_dropplatrise;\r
-\r
-void SpawnDropPlat(Uint16 tileX, Uint16 tileY);\r
-void T_DropPlatSit(objtype *ob);\r
-void T_DropPlatFall(objtype *ob);\r
-void T_DropPlatRise(objtype *ob);\r
-\r
-extern statetype s_statplat;\r
-\r
-void SpawnStaticPlat(Uint16 tileX, Uint16 tileY);\r
-\r
-extern statetype s_goplat;\r
-extern statetype s_slotgoplat1;\r
-extern statetype s_slotgoplat2;\r
-\r
-void SpawnGoPlat(Uint16 tileX, Uint16 tileY, Sint16 dir, Sint16 type);\r
-void T_GoPlat(objtype *ob);\r
-void T_GoSlotPlat(objtype *ob);\r
-\r
-extern statetype s_volte1;\r
-extern statetype s_volte2;\r
-extern statetype s_volte3;\r
-extern statetype s_volte4;\r
-extern statetype s_voltestun;\r
-\r
-void SpawnVolte(Uint16 tileX, Uint16 tileY);\r
-void T_Volte(objtype *ob);\r
-void C_Volte(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_sneakplatsit;\r
-extern statetype s_sneakplatdodge;\r
-extern statetype s_sneakplatreturn;\r
-\r
-void SpawnSneakPlat(Uint16 tileX, Uint16 tileY);\r
-void T_SneakPlat(objtype *ob);\r
-\r
-extern statetype s_cannon;\r
-extern statetype s_cannonfire;\r
-extern statetype s_cshot1;\r
-extern statetype s_cshot2;\r
-extern statetype s_cshot3;\r
-extern statetype s_cshot4;\r
-extern statetype s_cshothit1;\r
-extern statetype s_cshothit2;\r
-\r
-void SpawnCannon(Uint16 tileX, Uint16 tileY, Sint16 dir);\r
-void T_Cannon(objtype *ob);\r
-void C_CShot(objtype *ob, objtype *hit);\r
-void R_CShot(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K5_ACT2 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_sparkywalk1;\r
-extern statetype s_sparkywalk2;\r
-extern statetype s_sparkywalk3;\r
-extern statetype s_sparkywalk4;\r
-extern statetype s_sparkylook1;\r
-extern statetype s_sparkylook2;\r
-extern statetype s_sparkylook3;\r
-extern statetype s_sparkylook4;\r
-extern statetype s_sparkylook5;\r
-extern statetype s_sparkylook6;\r
-extern statetype s_sparkylook7;\r
-extern statetype s_sparkylook8;\r
-extern statetype s_sparkyspeed1;\r
-extern statetype s_sparkyspeed2;\r
-extern statetype s_sparkyspeed3;\r
-extern statetype s_sparkyspeed4;\r
-extern statetype s_sparkycharge1;\r
-extern statetype s_sparkycharge2;\r
-extern statetype s_sparkycharge3;\r
-extern statetype s_sparkycharge4;\r
-extern statetype s_sparkyturn1;\r
-extern statetype s_sparkyturn2;\r
-extern statetype s_sparkyturn3;\r
-extern statetype s_sparkystun;\r
-\r
-void SpawnSparky(Uint16 tileX, Uint16 tileY);\r
-void T_Sparky(objtype *ob);\r
-void T_ChargeCount(objtype *ob);\r
-void T_SparkyLookL(objtype *ob);\r
-void T_SparkyLookR(objtype *ob);\r
-void T_RunSnd1(objtype *ob);\r
-void T_RunSnd2(objtype *ob);\r
-void C_Sparky(objtype *ob, objtype *hit);\r
-void R_Sparky(objtype *ob);\r
-\r
-extern statetype s_amptonwalk1;\r
-extern statetype s_amptonwalk2;\r
-extern statetype s_amptonwalk3;\r
-extern statetype s_amptonwalk4;\r
-extern statetype s_amptonturn;\r
-extern statetype s_amptongrab1;\r
-extern statetype s_amptongrab2;\r
-extern statetype s_amptonclimb;\r
-extern statetype s_amptonrelease1;\r
-extern statetype s_amptonrelease2;\r
-extern statetype s_amptonfiddle1;\r
-extern statetype s_amptonfiddle2;\r
-extern statetype s_amptonfiddle3;\r
-extern statetype s_amptonfiddle4;\r
-extern statetype s_amptonfiddle5;\r
-extern statetype s_amptonstun;\r
-\r
-void SpawnAmpton(Uint16 tileX, Uint16 tileY);\r
-void T_Ampton(objtype *ob);\r
-void T_AmptonClimb(objtype *ob);\r
-void T_SetNoThink(objtype *ob);\r
-void C_Ampton(objtype *ob, objtype *hit);\r
-void R_Ampton(objtype *ob);\r
-\r
-extern statetype s_slicestarslide;\r
-extern statetype s_slicestarbounce;\r
-extern statetype s_slicestarboom;\r
-\r
-void SpawnSlicestarSlide(Uint16 tileX, Uint16 tileY, Sint16 dir);\r
-void SpawnSlicestarBounce(Uint16 tileX, Uint16 tileY);\r
-void C_Slicestar(objtype *ob, objtype *hit);\r
-void R_Slicestar(objtype *ob);\r
-\r
-extern statetype s_shellywalk1;\r
-extern statetype s_shellywalk2;\r
-extern statetype s_shellywalk3;\r
-extern statetype s_shellywalk4;\r
-extern statetype s_shellylook;\r
-extern statetype s_shellylook2;\r
-extern statetype s_shellyjump1;\r
-extern statetype s_shellyjump2;\r
-extern statetype s_shellydie;\r
-extern statetype s_shellydieup;\r
-extern statetype s_shellyboom1;\r
-extern statetype s_shellyboom2;\r
-extern statetype s_shellyboom3;\r
-extern statetype s_shellyboom4;\r
-extern statetype s_shellypiece1;\r
-extern statetype s_shellypiece2;\r
-\r
-void SpawnShelly(Uint16 tileX, Uint16 tileY);\r
-void T_ShellyLook(objtype *ob);\r
-void T_Turn(objtype *ob);\r
-void T_ShellyFrag(objtype *ob);\r
-void C_Shelly(objtype *ob, objtype *hit);\r
-void R_Shelly(objtype *ob);\r
-void R_Shell(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K5_ACT3 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_mine;\r
-extern statetype s_minecenter;\r
-extern statetype s_mineshift;\r
-extern statetype s_mineboom1;\r
-extern statetype s_mineboom2;\r
-extern statetype s_mineboom3;\r
-extern statetype s_mineboom4;\r
-extern statetype s_mineboom5;\r
-extern statetype s_mineboom6;\r
-extern statetype s_minepiece;\r
-\r
-void SpawnMine(Uint16 tileX, Uint16 tileY);\r
-boolean MinePosCheck(Uint16 tileX, Uint16 tileY);\r
-boolean Walk(objtype *ob, Sint16 dir);\r
-void ChaseThink(objtype *ob);\r
-void T_Mine(objtype *ob);\r
-void C_Solid(objtype *ob, objtype *hit);\r
-void C_MineFrag(objtype *ob, objtype *hit);\r
-void T_MineCenter(objtype *ob);\r
-void T_MineShift(objtype *ob);\r
-void T_MineFrag(objtype *ob);\r
-void R_Mine(objtype *ob);\r
-\r
-extern statetype s_robored;\r
-extern statetype s_roboredfire0;\r
-extern statetype s_roboredfire1;\r
-extern statetype s_roboredfire2;\r
-extern statetype s_rshot1;\r
-extern statetype s_rshot2;\r
-extern statetype s_rshothit1;\r
-extern statetype s_rshothit2;\r
-\r
-void SpawnRoboRed(Uint16 tileX, Uint16 tileY);\r
-void T_RoboRed(objtype *ob);\r
-void C_RoboRed(objtype *ob, objtype *hit);\r
-void T_RoboShoot(objtype *ob);\r
-void C_RShot(objtype *ob, objtype *hit);\r
-void R_RShot(objtype *ob);\r
-\r
-extern statetype s_gripsitd;\r
-extern statetype s_gripjumpd;\r
-extern statetype s_gripsitl;\r
-extern statetype s_gripjumpl;\r
-extern statetype s_gripsitr;\r
-extern statetype s_gripjumpr;\r
-extern statetype s_gripsitu;\r
-extern statetype s_gripjumpu;\r
-extern statetype s_gripspin1;\r
-extern statetype s_gripspin2;\r
-extern statetype s_gripspin3;\r
-extern statetype s_gripspin4;\r
-extern statetype s_gripspin5;\r
-extern statetype s_gripspin6;\r
-extern statetype s_gripspin7;\r
-extern statetype s_gripspin8;\r
-extern statetype s_gripflyd;\r
-extern statetype s_gripflyl;\r
-extern statetype s_gripflyr;\r
-extern statetype s_gripflyu;\r
-\r
-void SpawnSpirogrip(Uint16 tileX, Uint16 tileY);\r
-void T_SpiroLaunch(objtype *ob);\r
-void R_SpiroFly(objtype *ob);\r
-\r
-extern statetype s_spindred1;\r
-extern statetype s_spindred2;\r
-extern statetype s_spindred3;\r
-extern statetype s_spindred4;\r
-\r
-void SpawnSpindread(Uint16 tileX, Uint16 tileY);\r
-void T_Spindread(objtype *ob);\r
-void C_Spindread(objtype *ob, objtype *hit);\r
-void R_Spindread(objtype *ob);\r
-\r
-extern statetype s_master1;\r
-extern statetype s_master2;\r
-extern statetype s_master3;\r
-extern statetype s_master4;\r
-extern statetype s_mastershoot1;\r
-extern statetype s_mastershoot2;\r
-extern statetype s_mastertport1;\r
-extern statetype s_mastertport2;\r
-extern statetype s_mastertport3;\r
-extern statetype s_mastertport4;\r
-extern statetype s_mshot1;\r
-extern statetype s_mshot2;\r
-extern statetype s_mshot3;\r
-extern statetype s_mshot4;\r
-extern statetype s_mspray1;\r
-extern statetype s_mspray2;\r
-extern statetype s_mspray3;\r
-extern statetype s_mspray4;\r
-\r
-void SpawnMaster(Uint16 tileX, Uint16 tileY);\r
-void T_Master(objtype *ob);\r
-void T_MasterShoot(objtype *ob);\r
-void C_Master(objtype *ob, objtype *hit);\r
-void T_MasterTPort(objtype *ob);\r
-void C_MShot(objtype *ob, objtype *hit);\r
-void R_MShot(objtype *ob);\r
-void R_MSpray(objtype *ob);\r
-\r
-extern statetype s_shikadi1;\r
-extern statetype s_shikadi2;\r
-extern statetype s_shikadi3;\r
-extern statetype s_shikadi4;\r
-extern statetype s_shikadiwalk1;\r
-extern statetype s_shikadiwalk2;\r
-extern statetype s_shikadiwalk3;\r
-extern statetype s_shikadiwalk4;\r
-extern statetype s_shikadigrab;\r
-extern statetype s_shikadigrab2;\r
-extern statetype s_shikadistun;\r
-extern statetype s_polespark1;\r
-extern statetype s_polespark2;\r
-\r
-void SpawnShikadi(Uint16 tileX, Uint16 tileY);\r
-void T_Shikadi(objtype *ob);\r
-void C_Shikadi(objtype *ob, objtype *hit);\r
-void T_PoleShock(objtype *ob);\r
-void T_PoleSpark(objtype *ob);\r
-void R_Shikadi(objtype *ob);\r
-\r
-extern statetype s_petsit1;\r
-extern statetype s_petsit2;\r
-extern statetype s_petbark1;\r
-extern statetype s_petbark2;\r
-extern statetype s_pet1;\r
-extern statetype s_pet2;\r
-extern statetype s_pet3;\r
-extern statetype s_pet4;\r
-extern statetype s_petjump;\r
-extern statetype s_pshot1;\r
-extern statetype s_pshot2;\r
-extern statetype s_pshothot1;\r
-extern statetype s_pshothot2;\r
-extern statetype s_petstun;\r
-\r
-void SpawnPet(Uint16 tileX, Uint16 tileY);\r
-void T_Pet(objtype *ob);\r
-void T_PetSit(objtype *ob);\r
-void T_PetBark(objtype *ob);\r
-void C_Pet(objtype *ob, objtype *hit);\r
-void R_Pet(objtype *ob);\r
-void R_PetJump(objtype *ob);\r
-void C_PShot(objtype *ob, objtype *hit);\r
-void R_PShot(objtype *ob);\r
-\r
-extern statetype s_sphereful1;\r
-extern statetype s_sphereful2;\r
-extern statetype s_sphereful3;\r
-extern statetype s_sphereful4;\r
-\r
-void SpawnSphereful(Uint16 tileX, Uint16 tileY);\r
-void T_Sphereful(objtype *ob);\r
-void R_Sphereful(objtype *ob);\r
-\r
-extern statetype s_scottie1;\r
-extern statetype s_scottie2;\r
-extern statetype s_scottie3;\r
-extern statetype s_scottie4;\r
-extern statetype s_scottieface;\r
-extern statetype s_scottiestun;\r
-\r
-void SpawnScottie(Uint16 tileX, Uint16 tileY);\r
-void T_Scottie(objtype *ob);\r
-void C_Scottie(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_qed;\r
-\r
-void SpawnQed(Uint16 tileX, Uint16 tileY);\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K5_SPEC.C\r
-=========\r
-\r
-Contains (in this order):\r
-\r
-- lump definition\r
-- "Star Wars" crawl text\r
-- level names & messages\r
-- Airlock opening & closing code\r
-- ScanInfoPlane() - for spawning the level objects and marking required sprites\r
-- game over animation\r
-- messages for breaking fuses\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-enum {\r
- HELP_LUMP, // 0\r
- CONTROLS_LUMP, // 1\r
- KEENTALK_LUMP, // 2\r
- LOADING_LUMP, // 3\r
- PADDLE_LUMP, // 4\r
- KEEN_LUMP, // 5\r
- SUGAR1_LUMP, // 6\r
- SUGAR2_LUMP, // 7\r
- SUGAR3_LUMP, // 8\r
- SUGAR4_LUMP, // 9\r
- SUGAR5_LUMP, // 10\r
- SUGAR6_LUMP, // 11\r
- ONEUP_LUMP, // 12\r
- KEYGEM_LUMP, // 13\r
- AMMO_LUMP, // 14\r
- LASER_LUMP, // 15\r
- WORLDKEEN_LUMP, // 16\r
- MASTER_LUMP, // 17\r
- SHIKADI_LUMP, // 18\r
- SHOCKSHUND_LUMP, // 19\r
- SPHEREFUL_LUMP, // 20\r
- SPARKY_LUMP, // 21\r
- MINE_LUMP, // 22\r
- SLICESTAR_LUMP, // 23\r
- ROBORED_LUMP, // 24\r
- SPIRO_LUMP, // 25\r
- AMPTON_LUMP, // 26\r
- VOLTE_LUMP, // 27\r
- SLOTPLAT_LUMP, // 28\r
- SPINDRED_LUMP, // 29\r
- SHELLEY_LUMP, // 30\r
- PLATFORM_LUMP, // 31\r
- SMALLPLAT_LUMP, // 32\r
- KEYCARD_LUMP, // 33\r
- SCOTTIE_LUMP, // 34\r
- FUSE_LUMP, // 35\r
- STAREXPLODE_LUMP, // 36\r
- TELEPORT_LUMP, // 37\r
-\r
- NUMLUMPS=42 // Keen 5 has 4 unused lumps at the end\r
-};\r
-\r
-Uint16 lumpstart[NUMLUMPS] = {\r
- HELP_LUMP_START,\r
- CONTROLS_LUMP_START,\r
- KEENTALK_LUMP_START,\r
- LOADING_LUMP_START,\r
- PADDLE_LUMP_START,\r
- KEEN_LUMP_START,\r
- SUGAR1_LUMP_START,\r
- SUGAR2_LUMP_START,\r
- SUGAR3_LUMP_START,\r
- SUGAR4_LUMP_START,\r
- SUGAR5_LUMP_START,\r
- SUGAR6_LUMP_START,\r
- ONEUP_LUMP_START,\r
- KEYGEM_LUMP_START,\r
- AMMO_LUMP_START,\r
- LASER_LUMP_START,\r
- WORLDKEEN_LUMP_START,\r
- MASTER_LUMP_START,\r
- SHIKADI_LUMP_START,\r
- SHOCKSHUND_LUMP_START,\r
- SPHEREFUL_LUMP_START,\r
- SPARKY_LUMP_START,\r
- MINE_LUMP_START,\r
- SLICESTAR_LUMP_START,\r
- ROBORED_LUMP_START,\r
- SPIRO_LUMP_START,\r
- AMPTON_LUMP_START,\r
- VOLTE_LUMP_START,\r
- SLOTPLAT_LUMP_START,\r
- SPINDRED_LUMP_START,\r
- SHELLEY_LUMP_START,\r
- PLATFORM_LUMP_START,\r
- MINIPLAT_LUMP_START,\r
- KEYCARD_LUMP_START,\r
- SCOTTIE_LUMP_START,\r
- FUSE_LUMP_START,\r
- STAREXPLODE_LUMP_START,\r
- TELEPORT_LUMP_START\r
-};\r
-\r
-Uint16 lumpend[NUMLUMPS] = {\r
- HELP_LUMP_END,\r
- CONTROLS_LUMP_END,\r
- KEENTALK_LUMP_END,\r
- LOADING_LUMP_END,\r
- PADDLE_LUMP_END,\r
- KEEN_LUMP_END,\r
- SUGAR1_LUMP_END,\r
- SUGAR2_LUMP_END,\r
- SUGAR3_LUMP_END,\r
- SUGAR4_LUMP_END,\r
- SUGAR5_LUMP_END,\r
- SUGAR6_LUMP_END,\r
- ONEUP_LUMP_END,\r
- KEYGEM_LUMP_END,\r
- AMMO_LUMP_END,\r
- LASER_LUMP_END,\r
- WORLDKEEN_LUMP_END,\r
- MASTER_LUMP_END,\r
- SHIKADI_LUMP_END,\r
- SHOCKSHUND_LUMP_END,\r
- SPHEREFUL_LUMP_END,\r
- SPARKY_LUMP_END,\r
- MINE_LUMP_END,\r
- SLICESTAR_LUMP_END,\r
- ROBORED_LUMP_END,\r
- SPIRO_LUMP_END,\r
- AMPTON_LUMP_END,\r
- VOLTE_LUMP_END,\r
- SLOTPLAT_LUMP_END,\r
- SPINDRED_LUMP_END,\r
- SHELLEY_LUMP_END,\r
- PLATFORM_LUMP_END,\r
- MINIPLAT_LUMP_END,\r
- KEYCARD_LUMP_END,\r
- SCOTTIE_LUMP_END,\r
- FUSE_LUMP_END,\r
- STAREXPLODE_LUMP_END,\r
- TELEPORT_LUMP_END\r
-};\r
-\r
-boolean lumpneeded[NUMLUMPS];\r
-\r
-#if GRMODE == EGAGR\r
-\r
-char far swtext[] =\r
- "Episode Five\n"\r
- "\n"\r
- "The Armageddon Machine\n"\r
- "\n"\r
- "After learning the\n"\r
- "location of the secret\n"\r
- "Shikadi base, Keen\n"\r
- "jumped in the trusty\n"\r
- "Bean-with-Bacon\n"\r
- "Megarocket and blasted\n"\r
- "across interstellar\n"\r
- "space.\n"\r
- "\n"\r
- "Seventy-five furious\n"\r
- "games of Paddle War\n"\r
- "later, Keen dropped\n"\r
- "out of lightspeed near\n"\r
- " the Korath system.\n"\r
- "\n"\r
- "He flew toward the\n"\r
- "planet, keeping it\n"\r
- "between him and the\n"\r
- "base.\n"\r
- "\n"\r
- "Pulling up underside\n"\r
- "and docking at the\n"\r
- "Ion Ventilation System,\n"\r
- "Keen must destroy the\n"\r
- "Shikadi Armageddon\n"\r
- "Machine before it\n"\r
- "explodes and destroys\n"\r
- "the Milky Way! He\n"\r
- "steps into the dark\n"\r
- "ventilation duct and\n"\r
- "begins his most\n"\r
- "dangerous adventure\n"\r
- "yet...\n";\r
-\r
-#endif\r
-\r
-char far l0n[] = "Omegamatic";\r
-char far l1n[] = "Ion Ventilation System";\r
-char far l2n[] = "Security Center";\r
-char far l3n[] = "Defense Tunnel Vlook";\r
-char far l4n[] = "Energy Flow Systems";\r
-char far l5n[] = "Defense Tunnel Burrh";\r
-char far l6n[] = "Regulation\nControl Center";\r
-char far l7n[] = "Defense Tunnel Sorra";\r
-char far l8n[] = "Neutrino\nBurst Injector";\r
-char far l9n[] = "Defense Tunnel Teln";\r
-char far l10n[] = "Brownian\nMotion Inducer";\r
-char far l11n[] = "Gravitational\nDamping Hub";\r
-char far l12n[] = "Quantum\nExplosion Dynamo";\r
-char far l13n[] = "Korath III Base";\r
-char far l14n[] = "BWBMegarocket";\r
-char far l15n[] = "High Scores";\r
-\r
-char far l0e[] = "Keen purposefully\nwanders about the\nOmegamatic";\r
-char far l1e[] = "Keen investigates the\nIon Ventilation System";\r
-char far l2e[] = "Keen struts through\nthe Security Center";\r
-char far l3e[] = "Keen invades\nDefense Tunnel Vlook";\r
-char far l4e[] = "Keen engages\nEnergy Flow Systems";\r
-char far l5e[] = "Keen barrels into\nDefense Tunnel Burrh";\r
-char far l6e[] = "Keen goes nuts in\nthe Regulation\nControl Center";\r
-char far l7e[] = "Keen regrets entering\nDefense Tunnel Sorra";\r
-char far l8e[] = "Keen blows through\nthe Neutrino\nBurst Injector";\r
-char far l9e[] = "Keen trots through\nDefense Tunnel Teln";\r
-char far l10e[] = "Keen breaks into\nthe Brownian\nMotion Inducer";\r
-char far l11e[] = "Keen hurries through\nthe Gravitational\nDamping Hub";\r
-char far l12e[] = "Keen explodes into\nthe Quantum\nExplosion Dynamo";\r
-char far l13e[] = "Keen faces danger\nin the secret\nKorath III Base";\r
-char far l14e[] = "Keen will not be\nin the BWBMegarocket";\r
-char far l15e[] = "Keen unexplainedly\nfinds himself by\ntheHigh Scores"; // sic!\r
-\r
-char far *levelnames[GAMELEVELS] = {\r
- l0n,\r
- l1n,\r
- l2n,\r
- l3n,\r
- l4n,\r
- l5n,\r
- l6n,\r
- l7n,\r
- l8n,\r
- l9n,\r
- l10n,\r
- l11n,\r
- l12n,\r
- l13n,\r
- l14n,\r
- l15n\r
-};\r
-\r
-char far *levelenter[GAMELEVELS] = {\r
- l0e,\r
- l1e,\r
- l2e,\r
- l3e,\r
- l4e,\r
- l5e,\r
- l6e,\r
- l7e,\r
- l8e,\r
- l9e,\r
- l10e,\r
- l11e,\r
- l12e,\r
- l13e,\r
- l14e,\r
- l15e\r
-};\r
-\r
-Uint16 bonuslump[] = {\r
- KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP,\r
- SUGAR1_LUMP, SUGAR2_LUMP, SUGAR3_LUMP,\r
- SUGAR4_LUMP, SUGAR5_LUMP, SUGAR6_LUMP,\r
- ONEUP_LUMP, AMMO_LUMP, KEYCARD_LUMP, 0, 0\r
-};\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= OpenMapDoor\r
-=\r
-===========================\r
-*/\r
-\r
-void OpenMapDoor(Sint16 tileX, Sint16 tileY)\r
-{\r
- Sint16 x, y;\r
- Uint16 tiles[2][2];\r
-\r
- for (y=0; y<2; y++)\r
- {\r
- for (x=0; x<2; x++)\r
- {\r
- tiles[y][x] = *(mapsegs[1]+mapbwidthtable[y]/2 + x + 10);\r
- }\r
- }\r
- RF_MemToMap(&tiles[0][0], 1, tileX, tileY, 2, 2);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= CloseMapDoor\r
-=\r
-===========================\r
-*/\r
-\r
-void CloseMapDoor(Sint16 tileX, Sint16 tileY)\r
-{\r
- Sint16 x, y;\r
- Uint16 tiles[2][2];\r
-\r
- for (y=0; y<2; y++)\r
- {\r
- for (x=0; x<2; x++)\r
- {\r
- tiles[y][x] = *(mapsegs[1]+mapbwidthtable[y]/2 + x);\r
- }\r
- }\r
- RF_MemToMap(&tiles[0][0], 1, tileX, tileY, 2, 2);\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= ScanInfoPlane\r
-=\r
-= Spawn all actors and mark down special places\r
-=\r
-==========================\r
-*/\r
-\r
-void ScanInfoPlane(void)\r
-{\r
- Uint16 i, x, y, chunk;\r
- Sint16 info;\r
- Uint16 far *map;\r
- objtype *ob;\r
-\r
- InitObjArray(); // start spawning things with a clean slate\r
-\r
- memset(lumpneeded, 0, sizeof(lumpneeded));\r
- gamestate.numfuses = 0;\r
-\r
- map = mapsegs[2];\r
-\r
- for (y=0; y<mapheight; y++)\r
- {\r
- for (x=0; x<mapwidth; x++)\r
- {\r
- info = *map++;\r
-\r
- if (info == 0)\r
- continue;\r
-\r
- switch (info)\r
- {\r
- case 1:\r
- SpawnKeen(x, y, 1);\r
- SpawnScore();\r
- lumpneeded[KEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 2:\r
- SpawnKeen(x, y, -1);\r
- SpawnScore();\r
- lumpneeded[KEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 3:\r
- SpawnScore();\r
- lumpneeded[WORLDKEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- if (playstate == ex_portout)\r
- break;\r
- SpawnWorldKeen(x, y);\r
- break;\r
-\r
- case 26:\r
- if (playstate != ex_portout)\r
- break;\r
- SpawnWorldKeenPort(x, y);\r
- break;\r
-\r
- case 6:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 5:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 4:\r
- SpawnSparky(x, y);\r
- lumpneeded[SPARKY_LUMP] = true;\r
- break;\r
-\r
- case 9:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 8:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 7:\r
- SpawnMine(x, y);\r
- lumpneeded[MINE_LUMP] = true;\r
- break;\r
-\r
- case 12:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 11:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 10:\r
- SpawnSlicestarSlide(x, y, 0);\r
- lumpneeded[SLICESTAR_LUMP] = true;\r
- break;\r
-\r
- case 15:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 14:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 13:\r
- SpawnRoboRed(x, y);\r
- lumpneeded[ROBORED_LUMP] = true;\r
- break;\r
-\r
- case 18:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 17:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 16:\r
- SpawnSpirogrip(x, y);\r
- lumpneeded[SPIRO_LUMP] = true;\r
- break;\r
-\r
- case 21:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 20:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 19:\r
- SpawnSlicestarBounce(x, y);\r
- lumpneeded[SLICESTAR_LUMP] = true;\r
- break;\r
-\r
- case 24:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 23:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 22:\r
- SpawnSlicestarSlide(x, y, 1);\r
- lumpneeded[SLICESTAR_LUMP] = true;\r
- break;\r
-\r
- case 25:\r
- RF_SetScrollBlock(x, y, true);\r
- break;\r
-\r
- // case 26 (teleported map keen) is handled above\r
-\r
- case 27:\r
- case 28:\r
- case 29:\r
- case 30:\r
- SpawnPlatform(x, y, info-27, 0);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- // case 31 is the block icon\r
-\r
- case 32:\r
- SpawnDropPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 35:\r
- SpawnStaticPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
- case 34:\r
- if (gamestate.difficulty > gd_Normal)\r
- break;\r
- SpawnStaticPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
- case 33:\r
- if (gamestate.difficulty > gd_Easy)\r
- break;\r
- SpawnStaticPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 36:\r
- case 37:\r
- case 38:\r
- case 39:\r
- SpawnGoPlat(x, y, info-36, 0);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 40:\r
- SpawnSneakPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 41:\r
- if (gamestate.mapon == 12)\r
- {\r
- gamestate.numfuses = 4;\r
- SpawnQed(x, y);\r
- }\r
- else\r
- {\r
- gamestate.numfuses++;\r
- }\r
- lumpneeded[FUSE_LUMP] = true;\r
- break;\r
-\r
- case 44:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 43:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 42:\r
- SpawnAmpton(x, y);\r
- lumpneeded[AMPTON_LUMP] = true;\r
- break;\r
-\r
- case 53:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 49:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 45:\r
- SpawnCannon(x, y, 0);\r
- lumpneeded[LASER_LUMP] = true;\r
- break;\r
-\r
- case 54:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 50:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 46:\r
- SpawnCannon(x, y, 1);\r
- lumpneeded[LASER_LUMP] = true;\r
- break;\r
-\r
- case 55:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 51:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 47:\r
- SpawnCannon(x, y, 2);\r
- lumpneeded[LASER_LUMP] = true;\r
- break;\r
-\r
- case 56:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 52:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 48:\r
- SpawnCannon(x, y, 3);\r
- lumpneeded[LASER_LUMP] = true;\r
- break;\r
-\r
- case 69:\r
- if (gamestate.ammo >= 5)\r
- break;\r
- info = 68; // spawn ammo\r
- //no break here!\r
- case 57:\r
- case 58:\r
- case 59:\r
- case 60:\r
- case 61:\r
- case 62:\r
- case 63:\r
- case 64:\r
- case 65:\r
- case 66:\r
- case 67:\r
- case 68:\r
- SpawnBonus(x, y, info-57);\r
- lumpneeded[bonuslump[info-57]] = true;\r
- break;\r
- case 70:\r
- SpawnBonus(x, y, info-58);\r
- lumpneeded[bonuslump[info-58]] = true;\r
- break;\r
-\r
- case 73:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 72:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 71:\r
- SpawnVolte(x, y);\r
- lumpneeded[VOLTE_LUMP] = true;\r
- break;\r
-\r
- case 76:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 75:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 74:\r
- SpawnShelly(x, y);\r
- lumpneeded[SHELLEY_LUMP] = true;\r
- break;\r
-\r
- case 79:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 78:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 77:\r
- SpawnSpindread(x, y);\r
- lumpneeded[SPINDRED_LUMP] = true;\r
- break;\r
-\r
- case 80:\r
- case 81:\r
- case 82:\r
- case 83:\r
- SpawnGoPlat(x, y, info-80, 1);\r
- lumpneeded[SLOTPLAT_LUMP] = true;\r
- break;\r
-\r
- case 84:\r
- case 85:\r
- case 86:\r
- case 87:\r
- SpawnPlatform(x, y, info-84, 1);\r
- lumpneeded[SLOTPLAT_LUMP] = true;\r
- break;\r
-\r
- case 90:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 89:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 88:\r
- SpawnMaster(x, y);\r
- lumpneeded[MASTER_LUMP] = true;\r
- break;\r
-\r
- // cases 91 to 98 are direction arrows\r
-\r
- case 101:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 100:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 99:\r
- SpawnShikadi(x, y);\r
- lumpneeded[SHIKADI_LUMP] = true;\r
- break;\r
-\r
- case 104:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 103:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 102:\r
- SpawnPet(x, y);\r
- lumpneeded[SHOCKSHUND_LUMP] = true;\r
- break;\r
-\r
- case 107:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 106:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 105:\r
- SpawnSphereful(x, y);\r
- lumpneeded[SPHEREFUL_LUMP] = true;\r
- break;\r
-\r
- // cases 108 to 123 are wall collision icons for the WallDebug cheat\r
-\r
- case 124:\r
- SpawnScottie(x, y);\r
- lumpneeded[SCOTTIE_LUMP] = true;\r
- break;\r
-\r
- case 125:\r
- lumpneeded[TELEPORT_LUMP] = true;\r
-\r
- }\r
- }\r
- }\r
-\r
- for (ob = player; ob; ob = ob->next)\r
- {\r
- if (ob->active != ac_allways)\r
- ob->active = ac_no;\r
- }\r
-\r
- for (i = 0; i < NUMLUMPS; i++)\r
- {\r
- if (lumpneeded[i])\r
- {\r
- for (chunk = lumpstart[i]; chunk <= lumpend[i]; chunk++)\r
- {\r
- CA_MarkGrChunk(chunk);\r
- }\r
- }\r
- }\r
-\r
- // Keen 5 addition to PatchWorldMap (PatchWorldMap is shared across Keen 4-6)\r
- if (gamestate.mapon == 0)\r
- {\r
- info = CONVERT_GLOBAL_TO_TILE(player->y);\r
- if (info < 75 || info > 100)\r
- {\r
- CloseMapDoor(24, 76);\r
- OpenMapDoor(22, 55);\r
- }\r
- if (gamestate.leveldone[4] && gamestate.leveldone[6] && gamestate.leveldone[8] && gamestate.leveldone[10]\r
- && (info > 39 || info > 100) )\r
- {\r
- OpenMapDoor(26, 55);\r
- }\r
- if (info <= 39 || info > 100)\r
- {\r
- OpenMapDoor(24, 30);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GAME OVER SEQUENCE\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-------------------------------------------------------------------------------\r
-The galaxy explosion chunk contains data in the following format:\r
-\r
-struct {\r
- Uint16 posx[4000];\r
- Uint16 velx[4000];\r
- Uint16 posy[4000];\r
- Uint16 vely[4000];\r
-};\r
-\r
-The values are stored as "fixed point" numbers (divide each number by 128 to\r
-get the amount in pixel units). The code in MoveStars basically does the\r
-following:\r
-\r
-1. set all pixels on the screen to black\r
-\r
-2. for each of the 4000 entries do:\r
-\r
-2.1 x := posx[i] + velx[i]\r
-\r
-2.2 if x (in pixels) is < 0 or > 320 then go to 2.8\r
-\r
-2.3 posx[i] := x\r
-\r
-2.4 y := posy[i] + vely[i]\r
-\r
-2.5 if y (in pixels) is < 0 or > 200 then go to 2.8\r
-\r
-2.6 posy[i] := y\r
-\r
-2.7 draw a white pixel at position (x, y) on the screen\r
-\r
-2.8 continue with the next entry\r
-\r
-------------------------------------------------------------------------------\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-Uint8 plotpixels[8] = {0xC0, 0x30, 0x0C, 0x03};\r
-\r
-/*\r
-===========================\r
-=\r
-= MoveStars CGA\r
-=\r
-===========================\r
-*/\r
-\r
-void MoveStars(void)\r
-{\r
- asm {\r
- mov ax, screenseg;\r
- mov es, ax;\r
- mov ds, word ptr grsegs + 2*GALAXY;\r
- mov cx, 2000h;\r
- xor ax, ax;\r
- xor di, di;\r
- rep stosw;\r
- mov si, 7998;\r
- }\r
-l1:\r
- asm {\r
- mov ax, [si]; // get posx\r
- add ax, [si+8000]; // add velx\r
- cmp ax, 40960; // check if new posx is on screen\r
- ja l2;\r
- mov [si], ax; // set new posx\r
- mov bx, [si+16000]; // get posy\r
- add bx, [si+24000]; // add vely\r
- cmp bx, 25600; // check if new posy is on screen\r
- ja l2;\r
- mov [si+16000], bx; // set new posy\r
- mov cl, 7;\r
- shr bx, cl;\r
- shl bx, 1;\r
- mov di, word ptr ss:ylookup[bx];\r
- mov bx, ax;\r
- mov cl, 9;\r
- shr ax, cl;\r
- add di, ax;\r
- mov cl, 7;\r
- shr bx, cl;\r
- and bx, 3;\r
- mov al, BYTE PTR ss:plotpixels[bx];\r
- or es:[di], al; // draw the pixel\r
- }\r
-l2:\r
- asm {\r
- sub si, 2;\r
- jns l1;\r
- mov ax, ss;\r
- mov ds, ax;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= GameOver CGA\r
-=\r
-===========================\r
-*/\r
-\r
-void GameOver(void)\r
-{\r
- Sint16 i;\r
-\r
- FreeGraphics();\r
- CA_CacheGrChunk(MILKYWAYPIC);\r
- CA_CacheGrChunk(GALAXY);\r
- CA_CacheGrChunk(GAMEOVERPIC);\r
- RF_FixOfs();\r
- VW_ClearVideo(BLACK);\r
- VWB_DrawPic(0, 0, MILKYWAYPIC);\r
- VW_UpdateScreen();\r
-\r
- SD_WaitSoundDone();\r
- SD_PlaySound(SND_GAMEOVER2);\r
- SD_WaitSoundDone();\r
- SD_PlaySound(SND_GAMEOVER1);\r
-\r
- IN_ClearKeysDown();\r
- VW_SetLineWidth(80);\r
-\r
- for (i=0; i<60; i++)\r
- {\r
- lasttimecount = TimeCount;\r
- MoveStars();\r
- VW_UpdateScreen();\r
-\r
- do {} while (TimeCount-lasttimecount < 4);\r
-\r
- if (LastScan)\r
- break;\r
- }\r
-\r
- VW_SetLineWidth(SCREENWIDTH);\r
- VW_ClearVideo(BLACK);\r
- StartMusic(18);\r
- VWB_DrawPic(32, 80, GAMEOVERPIC);\r
- VW_UpdateScreen();\r
- IN_UserInput(24*TickBase, false);\r
- StopMusic();\r
-}\r
-\r
-//============================================================================\r
-\r
-#else\r
-\r
-Uint16 dim[18] = {8, 8, 7, 15, 7, 8, 0, 8, 7, 15, 7, 8, 0, 0, 0, 0, 0, 0};\r
-Uint16 bright[18] = {7, 7, 7, 7, 7, 15, 7, 8, 0, 7, 15, 7, 8, 0, 0, 0, 0, 0};\r
-Uint8 galaxycolors[17] = {0, 1, 2, 3, 4, 5, 6, 7, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 3};\r
-Uint8 plotpixels[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};\r
-\r
-/*\r
-===========================\r
-=\r
-= MoveStars EGA\r
-=\r
-===========================\r
-*/\r
-\r
-void MoveStars(Uint16 dest)\r
-{\r
- asm {\r
- mov dx, GC_INDEX;\r
- mov al, GC_BITMASK;\r
- out dx, al;\r
- inc dx;\r
- mov ds, word ptr grsegs + 2*GALAXY;\r
- mov ax, 0A000h;\r
- mov es, ax;\r
- mov cx, 1000h;\r
- xor ax, ax;\r
- mov di, dest;\r
- rep stosw;\r
- mov si, 7998;\r
- }\r
-l1:\r
- asm {\r
- mov ax, [si]; // get posx\r
- add ax, [si+8000]; // add velx\r
- cmp ax, 40960; // check if new posx is on screen\r
- ja l2;\r
- mov [si], ax; // set new posx\r
- mov bx, [si+16000]; // get posy\r
- add bx, [si+24000]; // add vely\r
- cmp bx, 25600; // check if new posy is on screen\r
- ja l2;\r
- mov [si+16000], bx; // set new posy\r
- mov cl, 7;\r
- shr bx, cl;\r
- shl bx, 1;\r
- mov di, word ptr ss:ylookup[bx];\r
- add di, dest;\r
- mov bx, ax;\r
- mov cl, 10;\r
- shr ax, cl;\r
- add di, ax;\r
- mov cl, 7;\r
- shr bx, cl;\r
- and bx, 7;\r
- mov al, BYTE PTR ss:plotpixels[bx];\r
- out dx, al;\r
- mov al, 0Fh;\r
- xchg al, es:[di]; // draw the pixel\r
- }\r
-l2:\r
- asm {\r
- sub si, 2;\r
- jns l1;\r
- mov ax, ss;\r
- mov ds, ax;\r
- mov al, 0FFh;\r
- out dx, al;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SetCrtc EGA\r
-=\r
-===========================\r
-*/\r
-\r
-void SetCrtc(Uint16 addr)\r
-{\r
- asm {\r
- cli;\r
- mov cx, addr;\r
- mov dx, CRTC_INDEX;\r
- mov al, CRTC_STARTHIGH;\r
- out dx, al;\r
- inc dx;\r
- mov al, ch;\r
- out dx, al;\r
- dec dx;\r
- mov al, CRTC_STARTLOW;\r
- out dx, al;\r
- inc dx;\r
- mov al, cl;\r
- out dx, al;\r
- sti;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= GameOver EGA\r
-=\r
-===========================\r
-*/\r
-\r
-void GameOver(void)\r
-{\r
- Sint16 i;\r
-\r
- FreeGraphics();\r
- VW_FadeOut();\r
- CA_CacheGrChunk(MILKYWAYPIC);\r
- CA_CacheGrChunk(GALAXY);\r
- CA_CacheGrChunk(GAMEOVERPIC);\r
- VW_SetLineWidth(40);\r
- VW_SetScreen(0, 0);\r
- bufferofs = 0;\r
- VW_ClearVideo(0);\r
- VW_DrawPic(0, 0, MILKYWAYPIC);\r
- VW_ScreenToScreen(0, 0x2000, 40, 200);\r
- VW_FadeIn();\r
- IN_ClearKeysDown();\r
- SD_PlaySound(SND_GAMEOVER2);\r
-\r
- for (i=0; i<18; i++)\r
- {\r
- galaxycolors[8] = dim[i];\r
- galaxycolors[7] = bright[i];\r
-\r
- SetPalette(galaxycolors);\r
-\r
- VW_WaitVBL(10);\r
- if (LastScan)\r
- goto gameover;\r
- }\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
- SD_PlaySound(SND_GAMEOVER1);\r
-\r
- for (i=0; i<30; i++)\r
- {\r
- lasttimecount = TimeCount;\r
- MoveStars(0x2000);\r
- SetCrtc(0x2000);\r
- do {} while (TimeCount-lasttimecount < 4);\r
-\r
- lasttimecount = TimeCount;\r
- MoveStars(0);\r
- SetCrtc(0);\r
- do {} while (TimeCount-lasttimecount < 4);\r
-\r
- if (LastScan)\r
- goto gameover;\r
- }\r
-\r
-gameover:\r
- EGAWRITEMODE(0);\r
- VW_ClearVideo(BLACK);\r
- VW_SetLineWidth(SCREENWIDTH);\r
- VW_SetDefaultColors();\r
- RF_FixOfs();\r
- StartMusic(18);\r
- VWB_DrawPic(32, 80, GAMEOVERPIC);\r
- VW_UpdateScreen();\r
- IN_UserInput(24*TickBase, false);\r
- StopMusic();\r
-}\r
-\r
-#endif\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= FinishedFuse\r
-=\r
-===========================\r
-*/\r
-\r
-void FinishedFuse(void)\r
-{\r
- SD_WaitSoundDone();\r
- CA_UpLevel();\r
-#if 0\r
- // bugfix:\r
- CA_ClearMarks(); // don't cache more than we actually need here\r
-#endif\r
- CA_MarkGrChunk(KEENTALK1PIC);\r
- CA_MarkGrChunk(KEENTALK2PIC);\r
- CA_CacheMarks(NULL);\r
-\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(26, 8);\r
- WindowW -= 48;\r
- VWB_DrawPic(WindowX+WindowW, WindowY, KEENTALK1PIC);\r
- PrintY += 12;\r
- if (gamestate.mapon == 13)\r
- {\r
- US_CPrint(\r
- "I wonder what that\n"\r
- "fuse was for....\n"\r
- );\r
- }\r
- else\r
- {\r
- US_CPrint(\r
- "One of the four\n"\r
- "machines protecting the\n"\r
- "main elevator shaft--\n"\r
- "toast!\n"\r
- );\r
- }\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- VWB_DrawPic(WindowX+WindowW, WindowY, KEENTALK2PIC);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- CA_DownLevel();\r
- StopMusic();\r
-}
\ No newline at end of file
+++ /dev/null
-;=====================================\r
-;\r
-; Graphics .EQU file for .CK5\r
-; not IGRAB-ed :)\r
-;\r
-;=====================================\r
-\r
-;INCLUDE "VERSION.EQU"\r
-\r
-;\r
-; Amount of each data item\r
-;\r
-NUMFONT = 2\r
-NUMFONTM = 0\r
-NUMPICM = 3\r
-NUMTILE8 = 108\r
-NUMTILE8M = 36\r
-NUMTILE32 = 0\r
-NUMTILE32M = 0\r
-\r
-;\r
-; Amount of each item in episode 5\r
-;\r
-NUMPICS = 94\r
-NUMSPRITES = 346\r
-NUMTILE16 = 1512\r
-NUMTILE16M = 2952\r
-NUMEXTERN = 17\r
-\r
-\r
-;\r
-; File offsets for data items\r
-;\r
-STRUCTPIC = 0\r
-STRUCTPICM = 1\r
-STRUCTSPRITE = 2\r
-\r
-STARTFONT = 3\r
-STARTFONTM = (STARTFONT+NUMFONT)\r
-STARTPICS = (STARTFONTM+NUMFONTM)\r
-STARTPICM = (STARTPICS+NUMPICS)\r
-STARTSPRITES = (STARTPICM+NUMPICM)\r
-STARTTILE8 = (STARTSPRITES+NUMSPRITES)\r
-STARTTILE8M = (STARTTILE8+1)\r
-STARTTILE16 = (STARTTILE8M+1)\r
-STARTTILE16M = (STARTTILE16+NUMTILE16)\r
-STARTTILE32 = (STARTTILE16M+NUMTILE16M)\r
-STARTTILE32M = (STARTTILE32+NUMTILE32)\r
-STARTEXTERN = (STARTTILE32M+NUMTILE32M)\r
-\r
-NUMCHUNKS = (STARTEXTERN+NUMEXTERN)\r
-\r
-;\r
-; Thank you for using IGRAB!\r
-;\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __GFX_H__\r
-#define __GFX_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-//////////////////////////////////////\r
-//\r
-// Graphics .H file for .CK5\r
-// not IGRAB-ed :)\r
-//\r
-//////////////////////////////////////\r
-\r
-//\r
-// Lump creation macros\r
-//\r
-\r
-#define START_LUMP(actualname, dummyname) actualname, dummyname=actualname-1,\r
-#define END_LUMP(actualname, dummyname) dummyname, actualname=dummyname-1,\r
-\r
-//\r
-// Amount of each data item\r
-//\r
-\r
-//common numbers:\r
-#define NUMCHUNKS NUMGRCHUNKS\r
-#define NUMFONT 2\r
-#define NUMFONTM 0\r
-#define NUMPICM 3\r
-#define NUMTILE8 108 // BUG: only 104 tiles exist in EGAGRAPH!\r
-#define NUMTILE8M 36 // BUG: only 20 tiles exist in EGAGRAPH!\r
-#define NUMTILE32 0\r
-#define NUMTILE32M 0\r
-\r
-//episode-specific numbers:\r
-#define NUMPICS 94\r
-#define NUMSPRITES 346\r
-#define NUMTILE16 1512\r
-#define NUMTILE16M 2952\r
-#define NUMEXTERNS 15\r
-\r
-//\r
-// File offsets for data items\r
-//\r
-#define STRUCTPIC 0\r
-#define STRUCTPICM 1\r
-#define STRUCTSPRITE 2\r
-\r
-#define STARTFONT 3\r
-#define STARTFONTM (STARTFONT+NUMFONT)\r
-#define STARTPICS (STARTFONTM+NUMFONTM)\r
-#define STARTPICM (STARTPICS+NUMPICS)\r
-#define STARTSPRITES (STARTPICM+NUMPICM)\r
-#define STARTTILE8 (STARTSPRITES+NUMSPRITES)\r
-#define STARTTILE8M (STARTTILE8+1)\r
-#define STARTTILE16 (STARTTILE8M+1)\r
-#define STARTTILE16M (STARTTILE16+NUMTILE16)\r
-#define STARTTILE32 (STARTTILE16M+NUMTILE16M)\r
-#define STARTTILE32M (STARTTILE32+NUMTILE32)\r
-#define STARTEXTERNS (STARTTILE32M+NUMTILE32M)\r
-\r
-typedef enum {\r
- // Lump Start\r
-\r
- LASTFONT=STARTPICS-1,\r
-\r
- PADDINGPIC, // 5 (compensate for the missing Star Wars font to give the other pics the correct chunk numbers)\r
-\r
- START_LUMP(HELP_LUMP_START, __HELPSTART)\r
- H_HELPPIC, // 6\r
- H_LARROWPIC, // 7\r
- H_RARROWPIC, // 8\r
- H_ESCPIC, // 9\r
- H_ENTERPIC, // 10\r
- H_BOTTOMINSTRPIC, // 11\r
- H_GUMPIC, // 12\r
- H_MARSHMALLOWPIC, // 13\r
- H_CHOCMILKPIC, // 14\r
- H_TARTSTIXPIC, // 15\r
- H_STOOPIESPIC, // 16\r
- H_SUGARPIC, // 17\r
- H_VITALINPIC, // 18\r
- H_STUNNERPIC, // 19\r
- H_GEMPIC, // 20\r
- H_KEGPIC, // 21\r
- H_ENDOFTEXTPIC, // 22\r
- H_HELPMENUPIC, // 23\r
- H_HANDPIC, // 24\r
- H_ARROWSENTERESCPIC, // 25\r
- H_FLASHARROW1PIC, // 26\r
- H_FLASHARROW2PIC, // 27\r
- H_TOPWINDOWPIC, // 28\r
- H_LEFTWINDOWPIC, // 29\r
- H_RIGHTWINDOWPIC, // 30\r
- H_BOTTOMINFOPIC, // 31\r
- H_BOTTOMWINDOWPIC, // 32\r
- H_BARPIC, // 33\r
- H_SPARKYPIC, // 34\r
- H_AMPTONPIC, // 35\r
- H_SLICESTARPIC, // 36\r
- H_VOLTEFACEPIC, // 37\r
- H_ROBOREDPIC, // 38\r
- H_SHELLEYPIC, // 39\r
- H_SPIROGRIPPIC, // 40\r
- H_MINEPIC, // 41\r
- H_SPINDREDPIC, // 42\r
- H_SHIKADIPIC, // 43\r
- H_SPHEREFULPIC, // 44\r
- H_PETPIC, // 45\r
- H_MASTERPIC, // 46\r
- H_IDLOGOPIC, // 47\r
- H_STORY1PIC, // 48\r
- H_STORY2PIC, // 49\r
- H_STORY3PIC, // 50\r
- H_STORY4PIC, // 51\r
- H_VISAPIC, // 52\r
- H_MCPIC, // 53\r
- H_KEENTHUMBSUPPIC, // 54\r
- H_END1PIC, // 55\r
- H_END2PIC, // 56\r
- H_END3PIC, // 57\r
- H_END4PIC, // 58\r
- H_END5PIC, // 59\r
- H_END6PIC, // 60\r
- H_END7PIC, // 61\r
- H_END8PIC, // 62\r
- H_CONGRATSPIC, // 63\r
- H_KEENFEEDSPIC, // 64\r
- H_DOORCARDPIC, // 65\r
- H_KEEN6PIC, // 66\r
- END_LUMP(HELP_LUMP_END, __HELPEND)\r
-\r
- START_LUMP(CONTROLS_LUMP_START, __CONTROLSSTART)\r
- CP_MAINMENUPIC, // 67\r
- CP_NEWGAMEMENUPIC, // 68\r
- CP_LOADMENUPIC, // 69\r
- CP_SAVEMENUPIC, // 70\r
- CP_CONFIGMENUPIC, // 71\r
- CP_SOUNDMENUPIC, // 72\r
- CP_MUSICMENUPIC, // 73\r
- CP_KEYBOARDMENUPIC, // 74\r
- CP_KEYMOVEMENTPIC, // 75\r
- CP_KEYBUTTONPIC, // 76\r
- CP_JOYSTICKMENUPIC, // 77\r
- CP_OPTIONSMENUPIC, // 78\r
- CP_PADDLEWARPIC, // 79\r
- CP_QUITPIC, // 80\r
- CP_JOYSTICKPIC, // 81\r
- CP_MENUSCREENPIC, // 82\r
- END_LUMP(CONTROLS_LUMP_END, __COLTROLSEND)\r
-\r
- START_LUMP(_LUMP_START, __START)\r
- IDSOFTPIC, // 83\r
- PROGTEAMPIC, // 84\r
- ARTISTPIC, // 85\r
- DIRECTORPIC, // 86\r
- SW_BACKGROUNDPIC, // 87\r
- TITLEPICPIC, // 88\r
- MILKYWAYPIC, // 89\r
- END_LUMP(_LUMP_END, __END)\r
-\r
- START_LUMP(KEENTALK_LUMP_START, __KEENTALKSTART)\r
- KEENTALK1PIC, // 90\r
- KEENTALK2PIC, // 91\r
- END_LUMP(KEENTALK_LUMP_END, __KEENTALKEND)\r
-\r
- START_LUMP(LOADING_LUMP_START, __LOADINGSTART)\r
- KEENCOUNT1PIC, // 92\r
- KEENCOUNT2PIC, // 93\r
- KEENCOUNT3PIC, // 94\r
- KEENCOUNT4PIC, // 95\r
- KEENCOUNT5PIC, // 96\r
- KEENCOUNT6PIC, // 97\r
- END_LUMP(LOADING_LUMP_END, __LOADINGEND)\r
-\r
- GAMEOVERPIC, // 98\r
-\r
- CP_MENUMASKPICM, // 99\r
- CORDPICM, // 100\r
- METALPOLEPICM, // 101\r
-\r
- //\r
- // SPRITES\r
- //\r
-\r
- START_LUMP(PADDLE_LUMP_START, __PADDLESTART)\r
- PADDLESPR, // 102\r
- BALLSPR, // 103\r
- BALL1PIXELTOTHERIGHTSPR, // 104\r
- BALL2PIXELSTOTHERIGHTSPR, // 105\r
- BALL3PIXELSTOTHERIGHTSPR, // 106\r
- END_LUMP(PADDLE_LUMP_END, __PADDLEEND)\r
-\r
- DEMOPLAQUESPR, // 107\r
-\r
- START_LUMP(KEEN_LUMP_START, __KEENSTART)\r
- KEENSTANDRSPR, // 108\r
- KEENRUNR1SPR, // 109\r
- KEENRUNR2SPR, // 110\r
- KEENRUNR3SPR, // 111\r
- KEENRUNR4SPR, // 112\r
- KEENJUMPR1SPR, // 113\r
- KEENJUMPR2SPR, // 114\r
- KEENJUMPR3SPR, // 115\r
- KEENSTANDLSPR, // 116\r
- KEENRUNL1SPR, // 117\r
- KEENRUNL2SPR, // 118\r
- KEENRUNL3SPR, // 119\r
- KEENRUNL4SPR, // 120\r
- KEENJUMPL1SPR, // 121\r
- KEENJUMPL2SPR, // 122\r
- KEENJUMPL3SPR, // 123\r
- KEENLOOKUSPR, // 124\r
- KEENWAITR1SPR, // 125\r
- KEENWAITR2SPR, // 126\r
- KEENWAITR3SPR, // 127\r
- KEENSITREAD1SPR, // 128\r
- KEENSITREAD2SPR, // 129\r
- KEENSITREAD3SPR, // 130\r
- KEENSITREAD4SPR, // 131\r
- KEENREAD1SPR, // 132\r
- KEENREAD2SPR, // 133\r
- KEENREAD3SPR, // 134\r
- KEENSTOPREAD1SPR, // 135\r
- KEENSTOPREAD2SPR, // 136\r
- KEENLOOKD1SPR, // 137\r
- KEENLOOKD2SPR, // 138\r
- KEENONPLATSPR, // 139\r
- KEENDIE1SPR, // 140\r
- KEENDIE2SPR, // 141\r
- KEENSTUNSPR, // 142\r
- STUNSTARS1SPR, // 143\r
- STUNSTARS2SPR, // 144\r
- STUNSTARS3SPR, // 145\r
- KEENSHOOTLSPR, // 146\r
- KEENJLSHOOTLSPR, // 147\r
- KEENJSHOOTDSPR, // 148\r
- KEENJSHOOTUSPR, // 149\r
- KEENSHOOTUSPR, // 150\r
- KEENSHOOTRSPR, // 151\r
- KEENJRSHOOTRSPR, // 152\r
- STUN1SPR, // 153\r
- STUN2SPR, // 154\r
- STUN3SPR, // 155\r
- STUN4SPR, // 156\r
- STUNHIT1SPR, // 157\r
- STUNHIT2SPR, // 158\r
- KEENSHINNYR1SPR, // 159\r
- KEENSHINNYR2SPR, // 160\r
- KEENSHINNYR3SPR, // 161\r
- KEENSLIDED1SPR, // 162\r
- KEENSLIDED2SPR, // 163\r
- KEENSLIDED3SPR, // 164\r
- KEENSLIDED4SPR, // 165\r
- KEENSHINNYL1SPR, // 166\r
- KEENSHINNYL2SPR, // 167\r
- KEENSHINNYL3SPR, // 168\r
- KEENPLSHOOTUSPR, // 169\r
- KEENPRSHOOTUSPR, // 170\r
- KEENPRSHOOTDSPR, // 171\r
- KEENPLSHOOTDSPR, // 172\r
- KEENPSHOOTLSPR, // 173\r
- KEENPSHOOTRSPR, // 174\r
- KEENENTER1SPR, // 175\r
- KEENENTER2SPR, // 176\r
- KEENENTER3SPR, // 177\r
- KEENENTER4SPR, // 178\r
- KEENENTER5SPR, // 179\r
- KEENHANGLSPR, // 180\r
- KEENHANGRSPR, // 181\r
- KEENCLIMBEDGEL1SPR, // 182\r
- KEENCLIMBEDGEL2SPR, // 183\r
- KEENCLIMBEDGEL3SPR, // 184\r
- KEENCLIMBEDGEL4SPR, // 185\r
- KEENCLIMBEDGER1SPR, // 186\r
- KEENCLIMBEDGER2SPR, // 187\r
- KEENCLIMBEDGER3SPR, // 188\r
- KEENCLIMBEDGER4SPR, // 189\r
- KEENPOGOR1SPR, // 190\r
- KEENPOGOR2SPR, // 191\r
- KEENPOGOL1SPR, // 192\r
- KEENPOGOL2SPR, // 193\r
- BONUS100UPSPR, // 194\r
- BONUS100SPR, // 195\r
- BONUS200SPR, // 196\r
- BONUS500SPR, // 197\r
- BONUS1000SPR, // 198\r
- BONUS2000SPR, // 199\r
- BONUS5000SPR, // 200\r
- BONUS1UPSPR, // 201\r
- BONUSCLIPSPR, // 202\r
- VIVAPOOF1SPR, // 203\r
- VIVAPOOF2SPR, // 204\r
- VIVAPOOF3SPR, // 205\r
- VIVAPOOF4SPR, // 206\r
- END_LUMP(KEEN_LUMP_END, __KEENEND)\r
-\r
- START_LUMP(KEYCARD_LUMP_START, __KEYCARDSTART)\r
- DOORCARD1SPR, // 207\r
- DOORCARD2SPR, // 208\r
- BONUSCARDSPR, // 209\r
- END_LUMP(KEYCARD_LUMP_END, __KEYCARDEND)\r
-\r
- START_LUMP(SUGAR1_LUMP_START, __SUGAR1START)\r
- SUGAR1ASPR, // 210\r
- SUGAR1BSPR, // 211\r
- END_LUMP(SUGAR1_LUMP_END, __SUGAR1END)\r
-\r
- START_LUMP(SUGAR2_LUMP_START, __SUGAR2START)\r
- SUGAR2ASPR, // 212\r
- SUGAR2BSPR, // 213\r
- END_LUMP(SUGAR2_LUMP_END, __SUGAR2END)\r
-\r
- START_LUMP(SUGAR3_LUMP_START, __SUGAR3START)\r
- SUGAR3ASPR, // 214\r
- SUGAR3BSPR, // 215\r
- END_LUMP(SUGAR3_LUMP_END, __SUGAR3END)\r
-\r
- START_LUMP(SUGAR4_LUMP_START, __SUGAR4START)\r
- SUGAR4ASPR, // 216\r
- SUGAR4BSPR, // 217\r
- END_LUMP(SUGAR4_LUMP_END, __SUGAR4END)\r
-\r
- START_LUMP(SUGAR5_LUMP_START, __SUGAR5START)\r
- SUGAR5ASPR, // 218\r
- SUGAR5BSPR, // 219\r
- END_LUMP(SUGAR5_LUMP_END, __SUGAR5END)\r
-\r
- START_LUMP(SUGAR6_LUMP_START, __SUGAR6START)\r
- SUGAR6ASPR, // 220\r
- SUGAR6BSPR, // 221\r
- END_LUMP(SUGAR6_LUMP_END, __SUGAR6END)\r
-\r
- START_LUMP(ONEUP_LUMP_START, __ONEUPSTART)\r
- ONEUPASPR, // 222\r
- ONEUPBSPR, // 223\r
- END_LUMP(ONEUP_LUMP_END, __ONEUPEND)\r
-\r
- START_LUMP(KEYGEM_LUMP_START, __KEYGEMSTART)\r
- REDGEM1SPR, // 224\r
- REDGEM2SPR, // 225\r
- YELLOWGEM1SPR, // 226\r
- YELLOWGEM2SPR, // 227\r
- BLUEGEM1SPR, // 228\r
- BLUEGEM2SPR, // 229\r
- GREENGEM1SPR, // 230\r
- GREENGEM2SPR, // 231\r
- BONUSGEMSPR, // 232\r
- END_LUMP(KEYGEM_LUMP_END, __KEYGEMEND)\r
-\r
- START_LUMP(AMMO_LUMP_START, __AMMOSTART)\r
- STUNCLIP1SPR, // 233\r
- STUNCLIP2SPR, // 234\r
- END_LUMP(AMMO_LUMP_END, __AMMOEND)\r
-\r
- SCOREBOXSPR, // 235\r
-\r
- START_LUMP(LASER_LUMP_START, __LASERSTART)\r
- LASER1SPR, // 236\r
- LASER2SPR, // 237\r
- LASER3SPR, // 238\r
- LASER4SPR, // 239\r
- LASERHIT1SPR, // 240\r
- LASERHIT2SPR, // 241\r
- END_LUMP(LASER_LUMP_END, __LASEREND)\r
-\r
- START_LUMP(WORLDKEEN_LUMP_START, __WORLDKEENSTART)\r
- WORLDKEENL1SPR, // 242\r
- WORLDKEENL2SPR, // 243\r
- WORLDKEENL3SPR, // 244\r
- WORLDKEENR1SPR, // 245\r
- WORLDKEENR2SPR, // 246\r
- WORLDKEENR3SPR, // 247\r
- WORLDKEENU1SPR, // 248\r
- WORLDKEENU2SPR, // 249\r
- WORLDKEENU3SPR, // 250\r
- WORLDKEEND1SPR, // 251\r
- WORLDKEEND2SPR, // 252\r
- WORLDKEEND3SPR, // 253\r
- WORLDKEENDR1SPR, // 254\r
- WORLDKEENDR2SPR, // 255\r
- WORLDKEENDR3SPR, // 256\r
- WORLDKEENDL1SPR, // 257\r
- WORLDKEENDL2SPR, // 258\r
- WORLDKEENDL3SPR, // 259\r
- WORLDKEENUL1SPR, // 260\r
- WORLDKEENUL2SPR, // 261\r
- WORLDKEENUL3SPR, // 262\r
- WORLDKEENUR1SPR, // 263\r
- WORLDKEENUR2SPR, // 264\r
- WORLDKEENUR3SPR, // 265\r
- WORLDKEENWAVE1SPR, // 266\r
- WORLDKEENWAVE2SPR, // 267\r
- FLAGFLIP1SPR, // 268\r
- FLAGFLIP2SPR, // 269\r
- FLAGFLIP3SPR, // 270\r
- FLAGFLIP4SPR, // 271\r
- FLAGFLIP5SPR, // 272\r
- FLAGFALL1SPR, // 273\r
- FLAGFALL2SPR, // 274\r
- FLAGFLAP1SPR, // 275\r
- FLAGFLAP2SPR, // 276\r
- FLAGFLAP3SPR, // 277\r
- FLAGFLAP4SPR, // 278\r
- SHOOTINGSTAR1SPR, // 279\r
- SHOOTINGSTAR2SPR, // 280\r
- WORLDTELSPARK1SPR, // 281\r
- WORLDTELSPARK2SPR, // 282\r
- END_LUMP(WORLDKEEN_LUMP_END, __WORLDKEENEND)\r
-\r
- START_LUMP(FUSE_LUMP_START, __FUSESTART)\r
- FUSEFLASH1SPR, // 283\r
- FUSEFLASH2SPR, // 284\r
- FUSEFLASH3SPR, // 285\r
- END_LUMP(FUSE_LUMP_END, __FUSEEND)\r
-\r
- START_LUMP(STAREXPLODE_LUMP_START, __SMALLSPARKSTART)\r
- STAREXPLODE1SPR, // 286\r
- STAREXPLODE2SPR, // 287\r
- STAREXPLODE3SPR, // 288\r
- STAREXPLODE4SPR, // 289\r
- END_LUMP(STAREXPLODE_LUMP_END, __SMALLSPARKEND)\r
-\r
- START_LUMP(TELEPORT_LUMP_START, __TELEPORTSTART)\r
- TELEPORTSPARK1SPR, // 290\r
- TELEPORTSPARK2SPR, // 291\r
- TELEPORTZAP1SPR, // 292\r
- TELEPORTZAP2SPR, // 293\r
- END_LUMP(TELEPORT_LUMP_END, __TELEPORTEND)\r
-\r
- START_LUMP(SCOTTIE_LUMP_START, __KORATHSTART)\r
- SCOTTIEWALKL1SPR, // 294\r
- SCOTTIEWALKL2SPR, // 295\r
- SCOTTIEWALKL3SPR, // 296\r
- SCOTTIEWALKL4SPR, // 297\r
- SCOTTIEWALKR1SPR, // 298\r
- SCOTTIEWALKR2SPR, // 299\r
- SCOTTIEWALKR3SPR, // 300\r
- SCOTTIEWALKR4SPR, // 301\r
- SCOTTIEFACESPR, // 302\r
- SCOTTIESTUNSPR, // 303\r
- END_LUMP(SCOTTIE_LUMP_END, __KORATHEND)\r
-\r
- START_LUMP(MASTER_LUMP_START, __MASTERSTART)\r
- MASTER1SPR, // 304\r
- MASTER2SPR, // 305\r
- MASTER3SPR, // 306\r
- MASTER4SPR, // 307\r
- MASTERTELEPORT1SPR, // 308\r
- MASTERTELEPORT2SPR, // 309\r
- SHIKMASTERCASTRSPR, // 310\r
- SHIKMASTERCASTLSPR, // 311\r
- MASTERFLOORSPARK1SPR, // 312\r
- MASTERFLOORSPARK2SPR, // 313\r
- MASTERFLOORSPARK3SPR, // 314\r
- MASTERFLOORSPARK4SPR, // 315\r
- MASTERSHOT1SPR, // 316\r
- MASTERSHOT2SPR, // 317\r
- MASTERSHOT3SPR, // 318\r
- MASTERSHOT4SPR, // 319\r
- END_LUMP(MASTER_LUMP_END, __MASTEREND)\r
-\r
- START_LUMP(SHIKADI_LUMP_START, __SHIKADISTART)\r
- SHIKADI1SPR, // 320\r
- SHIKADI2SPR, // 321\r
- SHIKADI3SPR, // 322\r
- SHIKADI4SPR, // 323\r
- SHIKADIGRABRSPR, // 324\r
- SHIKADIGRABLSPR, // 325\r
- SHIKADIPOLESPARK1SPR, // 326\r
- SHIKADIPOLESPARK2SPR, // 327\r
- SHIKADIWALKR1SPR, // 328\r
- SHIKADIWALKR2SPR, // 329\r
- SHIKADIWALKR3SPR, // 330\r
- SHIKADIWALKR4SPR, // 331\r
- SHIKADIWALKL1SPR, // 332\r
- SHIKADIWALKL2SPR, // 333\r
- SHIKADIWALKL3SPR, // 334\r
- SHIKADIWALKL4SPR, // 335\r
- SHIKADISTUNSPR, // 336\r
- END_LUMP(SHIKADI_LUMP_END, __SHIKADIEND)\r
-\r
- START_LUMP(SHOCKSHUND_LUMP_START, __SHOCKSHUNDSTART)\r
- PETSIT1SPR, // 337\r
- PETSIT2SPR, // 338\r
- PETRUNR1SPR, // 339\r
- PETRUNR2SPR, // 340\r
- PETRUNR3SPR, // 341\r
- PETRUNR4SPR, // 342\r
- PETRUNL1SPR, // 343\r
- PETRUNL2SPR, // 344\r
- PETRUNL3SPR, // 345\r
- PETRUNL4SPR, // 346\r
- PETJUMPLSPR, // 347\r
- PETJUMPRSPR, // 348\r
- PETBARKR1SPR, // 349\r
- PETBARKR2SPR, // 350\r
- PETBARKL1SPR, // 351\r
- PETBARKL2SPR, // 352\r
- PETSTUNSPR, // 353\r
- PETSPARK1SPR, // 354\r
- PETSPARK2SPR, // 355\r
- PETSPARKHIT1SPR, // 356\r
- PETSPARKHIT2SPR, // 357\r
- END_LUMP(SHOCKSHUND_LUMP_END, __SHOCKSHUNDEND)\r
-\r
- START_LUMP(SPHEREFUL_LUMP_START, __SPHEREFULSTART)\r
- SPHEREFUL1SPR, // 358\r
- SPHEREFUL2SPR, // 359\r
- SPHEREFUL3SPR, // 360\r
- SPHEREFUL4SPR, // 361\r
- SPHEREGUARD1SPR, // 362\r
- SPHEREGUARD2SPR, // 363\r
- SPHEREGUARD3SPR, // 364\r
- SPHEREGUARD4SPR, // 365\r
- END_LUMP(SPHEREFUL_LUMP_END, __SPHEREFULEND)\r
-\r
- START_LUMP(SPARKY_LUMP_START, __SPARKYSTART)\r
- SPARKYWALKL1SPR, // 366\r
- SPARKYWALKL2SPR, // 367\r
- SPARKYWALKL3SPR, // 368\r
- SPARKYWALKL4SPR, // 369\r
- SPARKYTURN1SPR, // 370\r
- SPARKYTURN2SPR, // 371\r
- SPARKYTURN3SPR, // 372\r
- SPARKYWALKR1SPR, // 373\r
- SPARKYWALKR2SPR, // 374\r
- SPARKYWALKR3SPR, // 375\r
- SPARKYWALKR4SPR, // 376\r
- SPARKYSTUNSPR, // 377\r
- END_LUMP(SPARKY_LUMP_END, __SPARKYEND)\r
-\r
- START_LUMP(MINE_LUMP_START, __MINESTART)\r
- SHIKADIMINESPR, // 378\r
- SHIKADIMINEEYESPR, // 379\r
- SHIKADIMINEPULSE1SPR, // 380\r
- SHIKADIMINEPULSE2SPR, // 381\r
- SHIKADIMINEBOOM1SPR, // 382\r
- SHIKADIMINEBOOM2SPR, // 383\r
- SHIKADIMINEPIECESPR, // 384\r
- END_LUMP(MINE_LUMP_END, __MINEEND)\r
-\r
- START_LUMP(SLICESTAR_LUMP_START, __SLICESTARSTART)\r
- SLICESTARSPR, // 385\r
- SLICESTARBOOMSPR, // 386\r
- END_LUMP(SLICESTAR_LUMP_END, __SLICASTAREND)\r
-\r
- START_LUMP(ROBORED_LUMP_START, __ROBOREDSTART)\r
- ROBOREDRSPR, // 387\r
- ROBOREDLSPR, // 388\r
- ROBOSHOT1SPR, // 389\r
- ROBOSHOT2SPR, // 390\r
- ROBOSHOTHIT1SPR, // 391\r
- ROBOSHOTHIT2SPR, // 392\r
- END_LUMP(ROBORED_LUMP_END, __ROBOREDEND)\r
-\r
- START_LUMP(SPIRO_LUMP_START, __SPIROSTART)\r
- SPIROSITDSPR, // 393\r
- SPIROSITLSPR, // 394\r
- SPIROSITUSPR, // 395\r
- SPIROSITRSPR, // 396\r
- SPIROSPINULSPR, // 397\r
- SPIROSPINURSPR, // 398\r
- SPIROSPINDRSPR, // 399\r
- SPIROSPINDLSPR, // 400\r
- SPIROSPINDSPR, // 401\r
- SPIROSPINLSPR, // 402\r
- SPIROSPINUSPR, // 403\r
- SPIROSPINRSPR, // 404\r
- END_LUMP(SPIRO_LUMP_END, __SPIROEND)\r
-\r
- START_LUMP(AMPTON_LUMP_START, __AMPTONSTART)\r
- AMPTONWALKR1SPR, // 405\r
- AMPTONWALKR2SPR, // 406\r
- AMPTONWALKR3SPR, // 407\r
- AMPTONWALKR4SPR, // 408\r
- AMPTONFACESPR, // 409\r
- AMPTONGRAB1SPR, // 410\r
- AMPTONGRAB2SPR, // 411\r
- AMTONWALKL1SPR, // 412\r
- AMTONWALKL2SPR, // 413\r
- AMTONWALKL3SPR, // 414\r
- AMTONWALKL4SPR, // 415\r
- AMPTONSTUNSPR, // 416\r
- END_LUMP(AMPTON_LUMP_END, __AMPTONEND)\r
-\r
- START_LUMP(VOLTE_LUMP_START, __VOLTESTART)\r
- VOLTEFACE1SPR, // 417\r
- VOLTEFACE2SPR, // 418\r
- VOLTEFACE3SPR, // 419\r
- VOLTEFACE4SPR, // 420\r
- VOLTEFACESTUNSPR, // 421\r
- END_LUMP(VOLTE_LUMP_END, __VOLTEEND)\r
-\r
- START_LUMP(SLOTPLAT_LUMP_START, __PINKPLATSTART)\r
- SLOTPLAT1SPR, // 422\r
- SLOTPLAT2SPR, // 423\r
- END_LUMP(SLOTPLAT_LUMP_END, __PINKPLATEND)\r
-\r
- START_LUMP(SPINDRED_LUMP_START, __SPINDREDSTART)\r
- SPINDRED1SPR, // 424\r
- SPINDRED2SPR, // 425\r
- SPINDRED3SPR, // 426\r
- SPINDRED4SPR, // 427\r
- END_LUMP(SPINDRED_LUMP_END, __SPINDREDEND)\r
-\r
- START_LUMP(SHELLEY_LUMP_START, __SHELLEYSTART)\r
- SHELLEYR1SPR, // 428\r
- SHELLEYR2SPR, // 429\r
- SHELLEYR3SPR, // 430\r
- SHELLEYR4SPR, // 431\r
- SHELLEYL1SPR, // 432\r
- SHELLEYL2SPR, // 433\r
- SHELLEYL3SPR, // 434\r
- SHELLEYL4SPR, // 435\r
- SHELLEYJUMPRSPR, // 436\r
- SHELLEYFALLRSPR, // 437\r
- SHELLEYJUMPLSPR, // 438\r
- SHELLEYFALLLSPR, // 439\r
- SHELLEYBOOM1SPR, // 440\r
- SHELLEYBOOM2SPR, // 441\r
- SHELLEYBOOM3SPR, // 442\r
- SHELLEYBOOM4SPR, // 443\r
- SHELLEYPIECE1SPR, // 444\r
- SHELLEYPIECE2SPR, // 445\r
- END_LUMP(SHELLEY_LUMP_END, __SHELLEYEND)\r
-\r
- START_LUMP(PLATFORM_LUMP_START, __PLATFORMSTART)\r
- PLATFORMSPR, // 446\r
- END_LUMP(PLATFORM_LUMP_END, __PLATFORMEND)\r
-\r
- START_LUMP(MINIPLAT_LUMP_START, __MINIPLATSTART)\r
- MINIPLATSPR, // 447\r
- END_LUMP(MINIPLAT_LUMP_END, __MINIPLATEND)\r
-\r
-\r
- //\r
- // TILES (these don't need names)\r
- //\r
-\r
- LASTTILE=STARTEXTERNS-1,\r
-\r
- //\r
- // EXTERNS\r
- //\r
-\r
- //texts\r
- T_HELPART, // 4914\r
- T_CONTRART, // 4915\r
- T_STORYART, // 4916\r
- T_IDART, // 4917\r
- T_ENDART, // 4918\r
- T_ENDART2, // 4919\r
- T_ORDERART, // 4920\r
-\r
- ORDERSCREEN, // 4921\r
- OUTOFMEM, // 4922\r
- GALAXY, // 4923\r
-\r
- //demos\r
- DEMO0, // 4924\r
- DEMO1, // 4925\r
- DEMO2, // 4926\r
- DEMO3, // 4927\r
- DEMO4, // 4928\r
-\r
- NUMGRCHUNKS\r
-} graphicnums;\r
-\r
-#undef START_LUMP\r
-#undef END_LUMP\r
-\r
-#endif //__GFX_H__
\ No newline at end of file
+++ /dev/null
-;\r
-; Equates for all .ASM files\r
-;\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-INCLUDE "GFXC_CK5.EQU"\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-CGAGR = 1\r
-EGAGR = 2\r
-VGAGR = 3\r
-\r
-GRMODE = CGAGR\r
-PROFILE = 0 ; 1=keep stats on tile drawing\r
-\r
-SC_INDEX = 03C4h\r
-SC_RESET = 0\r
-SC_CLOCK = 1\r
-SC_MAPMASK = 2\r
-SC_CHARMAP = 3\r
-SC_MEMMODE = 4\r
-\r
-CRTC_INDEX = 03D4h\r
-CRTC_H_TOTAL = 0\r
-CRTC_H_DISPEND = 1\r
-CRTC_H_BLANK = 2\r
-CRTC_H_ENDBLANK = 3\r
-CRTC_H_RETRACE = 4\r
-CRTC_H_ENDRETRACE = 5\r
-CRTC_V_TOTAL = 6\r
-CRTC_OVERFLOW = 7\r
-CRTC_ROWSCAN = 8\r
-CRTC_MAXSCANLINE = 9\r
-CRTC_CURSORSTART = 10\r
-CRTC_CURSOREND = 11\r
-CRTC_STARTHIGH = 12\r
-CRTC_STARTLOW = 13\r
-CRTC_CURSORHIGH = 14\r
-CRTC_CURSORLOW = 15\r
-CRTC_V_RETRACE = 16\r
-CRTC_V_ENDRETRACE = 17\r
-CRTC_V_DISPEND = 18\r
-CRTC_OFFSET = 19\r
-CRTC_UNDERLINE = 20\r
-CRTC_V_BLANK = 21\r
-CRTC_V_ENDBLANK = 22\r
-CRTC_MODE = 23\r
-CRTC_LINECOMPARE = 24\r
-\r
-\r
-GC_INDEX = 03CEh\r
-GC_SETRESET = 0\r
-GC_ENABLESETRESET = 1\r
-GC_COLORCOMPARE = 2\r
-GC_DATAROTATE = 3\r
-GC_READMAP = 4\r
-GC_MODE = 5\r
-GC_MISCELLANEOUS = 6\r
-GC_COLORDONTCARE = 7\r
-GC_BITMASK = 8\r
-\r
-ATR_INDEX = 03c0h\r
-ATR_MODE = 16\r
-ATR_OVERSCAN = 17\r
-ATR_COLORPLANEENABLE = 18\r
-ATR_PELPAN = 19\r
-ATR_COLORSELECT = 20\r
-\r
-STATUS_REGISTER_1 = 03dah\r
-\r
-\r
-MACRO WORDOUT\r
- out dx,ax\r
-ENDM\r
-\r
-if 0\r
-\r
-MACRO WORDOUT\r
- out dx,al\r
- inc dx\r
- xchg al,ah\r
- out dx,al\r
- dec dx\r
- xchg al,ah\r
-ENDM\r
-\r
-endif\r
-\r
-UPDATEWIDE = 22\r
-UPDATEHIGH = 14\r
-\r
-;\r
-; tile info offsets from segment tinf\r
-;\r
-\r
-ANIM = 402\r
-SPEED = (ANIM+NUMTILE16)\r
-\r
-NORTHWALL = (SPEED+NUMTILE16)\r
-EASTWALL = (NORTHWALL+NUMTILE16M)\r
-SOUTHWALL = (EASTWALL+NUMTILE16M)\r
-WESTWALL = (SOUTHWALL+NUMTILE16M)\r
-MANIM = (WESTWALL+NUMTILE16M)\r
-INTILE = (MANIM+NUMTILE16M)\r
-MSPEED = (INTILE+NUMTILE16M)\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-SCREENWIDTH = 64\r
-ENDIF\r
-IFE GRMODE-CGAGR\r
-SCREENWIDTH = 128\r
-ENDIF\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_GLOB.H\r
-\r
-\r
-#include <ALLOC.H>\r
-#include <CTYPE.H>\r
-#include <DOS.H>\r
-#include <ERRNO.H>\r
-#include <FCNTL.H>\r
-#include <IO.H>\r
-#include <MEM.H>\r
-#include <PROCESS.H>\r
-#include <STDIO.H>\r
-#include <STDLIB.H>\r
-#include <STRING.H>\r
-#include <SYS\STAT.H>\r
-\r
-#define __ID_GLOB__\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define KEEN\r
-#define KEEN5\r
-\r
-#define EXTENSION "CK5"\r
-\r
-extern char far introscn;\r
-\r
-#include "GFXC_CK5.H"\r
-#include "AUDIOCK5.H"\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define TEXTGR 0\r
-#define CGAGR 1\r
-#define EGAGR 2\r
-#define VGAGR 3\r
-\r
-#define GRMODE CGAGR\r
-\r
-#if GRMODE == EGAGR\r
-#define GREXT "EGA"\r
-#endif\r
-#if GRMODE == CGAGR\r
-#define GREXT "CGA"\r
-#endif\r
-\r
-//#define PROFILE\r
-\r
-//\r
-// ID Engine\r
-// Types.h - Generic types, #defines, etc.\r
-// v1.0d1\r
-//\r
-\r
-#ifndef __TYPES__\r
-#define __TYPES__\r
-\r
-typedef enum {false,true} boolean;\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long longword;\r
-typedef byte * Ptr;\r
-\r
-typedef struct\r
- {\r
- int x,y;\r
- } Point;\r
-typedef struct\r
- {\r
- Point ul,lr;\r
- } Rect;\r
-\r
-#define nil ((void *)0)\r
-\r
-#endif\r
-\r
-#include "ID_MM.H"\r
-#include "ID_CA.H"\r
-#include "ID_VW.H"\r
-#include "ID_RF.H"\r
-#include "ID_IN.H"\r
-#include "ID_SD.H"\r
-#include "ID_US.H"\r
-\r
-\r
-void Quit (char *error); // defined in user program\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __AUDIO_H__\r
-#define __AUDIO_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// MUSE Header for .CK6\r
-//\r
-/////////////////////////////////////////////////\r
-\r
-#define NUMSOUNDS LASTSOUND\r
-#define NUMSNDCHUNKS ((3*LASTSOUND)+LASTMUSIC)\r
-\r
-//\r
-// Sound names & indexes\r
-//\r
-typedef enum {\r
- SND_WORLDWALK1, // 0\r
- SND_WORLDWALK2, // 1\r
- SND_JUMP, // 2\r
- SND_LAND, // 3\r
- SND_KEENFIRE, // 4\r
- SND_DROPKEY, // 5\r
- SND_BLORBBOUNCE, // 6\r
- SND_POGOBOUNCE, // 7\r
- SND_GETPOINTS, // 8\r
- SND_GETAMMO, // 9\r
- SND_GETWATER, // 10\r
- SND_11, // 11\r
- SND_ENTERLEVEL, // 12\r
- SND_LEVELDONE, // 13\r
- SND_NOWAY, // 14\r
- SND_HELMETHIT, // 15\r
- SND_16, // 16\r
- SND_EXTRAKEEN, // 17\r
- SND_OPENDOOR, // 18\r
- SND_GETKEY, // 19\r
- SND_PLUMMET, // 20\r
- SND_USESWITCH, // 21\r
- SND_BIPSQUISH, // 22\r
- SND_KEENDEAD, // 23\r
- SND_BIPSHIPEXPLODE, // 24\r
- SND_SHOTEXPLODE, // 25\r
- SND_BOBBAJUMP, // 26\r
- SND_BOBBALAND, // 27\r
- SND_28, // 28\r
- SND_ENEMYSHOT, // 29\r
- SND_ENEMYSHOTEXPLODE, // 30\r
- SND_BOBBASHOT, // 31\r
- SND_32, // 32\r
- SND_GRABSATELLITE, // 33\r
- SND_SHOWSTATUS, // 34\r
- SND_HIDESTATUS, // 35\r
- SND_GIKJUMP, // 36\r
- SND_GIKLAND, // 37\r
- SND_ORBATRIXBOUNCE, // 38\r
- SND_39, // 39\r
- SND_40, // 40\r
- SND_TELEPORT, // 41\r
- SND_SHOTBOUNCE, // 42\r
- SND_FLAGSPIN, // 43\r
- SND_FLAGLAND, // 44\r
- SND_QUESTITEM, // 45\r
- KEENPADDLESND, // 46\r
- BALLBOUNCESND, // 47\r
- COMPPADDLESND, // 48\r
- COMPSCOREDSND, // 49\r
- KEENSCOREDSND, // 50\r
- SND_CEILICKATTACK, // 51\r
- SND_SMASH, // 52\r
- SND_THROWROPE, // 53\r
- SND_ROCKETFLY, // 54\r
- SND_CEILICKLAUGH, // 55\r
- SND_ROCKETSTART, // 56\r
- SND_GRABBITER, // 57\r
- SND_STOMP, // 58\r
- SND_FLAME, // 59\r
- LASTSOUND\r
-} soundnames;\r
-\r
-#if LASTSOUND != 60\r
-#error bad sound enum!\r
-#endif\r
-\r
-#define NOWAYSND SND_NOWAY\r
-\r
-//\r
-// Base offsets\r
-//\r
-#define STARTPCSOUNDS 0\r
-#define STARTADLIBSOUNDS (STARTPCSOUNDS+NUMSOUNDS)\r
-#define STARTDIGISOUNDS (STARTADLIBSOUNDS+NUMSOUNDS)\r
-#define STARTMUSIC (STARTDIGISOUNDS+NUMSOUNDS)\r
-\r
-//\r
-// Music names & indexes\r
-//\r
-typedef enum {\r
- WONDER_MUS,\r
- BRERTAR_MUS,\r
- TOFUTURE_MUS,\r
- FASTER_MUS,\r
- SPACFUNK_MUS,\r
- ALIENATE_MUS,\r
- OMINOUS_MUS,\r
- METAL_MUS,\r
- MAMSNAKE_MUS,\r
- LASTMUSIC\r
-} musicnames;\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// Thanks for playing with MUSE!\r
-//\r
-/////////////////////////////////////////////////\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-;=====================================\r
-;\r
-; Graphics .EQU file for .CK6\r
-; not IGRAB-ed :)\r
-;\r
-;=====================================\r
-\r
-;INCLUDE "VERSION.EQU"\r
-\r
-;\r
-; Amount of each data item\r
-;\r
-NUMFONT = 3\r
-NUMFONTM = 0\r
-NUMPICM = 3\r
-NUMTILE8 = 108\r
-NUMTILE8M = 36\r
-NUMTILE32 = 0\r
-NUMTILE32M = 0\r
-\r
-;\r
-; Amount of each item in episode 6\r
-;\r
-NUMPICS = 37\r
-NUMSPRITES = 390\r
-NUMTILE16 = 2376\r
-NUMTILE16M = 2736\r
-NUMEXTERN = 11\r
-\r
-\r
-;\r
-; File offsets for data items\r
-;\r
-STRUCTPIC = 0\r
-STRUCTPICM = 1\r
-STRUCTSPRITE = 2\r
-\r
-STARTFONT = 3\r
-STARTFONTM = (STARTFONT+NUMFONT)\r
-STARTPICS = (STARTFONTM+NUMFONTM)\r
-STARTPICM = (STARTPICS+NUMPICS)\r
-STARTSPRITES = (STARTPICM+NUMPICM)\r
-STARTTILE8 = (STARTSPRITES+NUMSPRITES)\r
-STARTTILE8M = (STARTTILE8+1)\r
-STARTTILE16 = (STARTTILE8M+1)\r
-STARTTILE16M = (STARTTILE16+NUMTILE16)\r
-STARTTILE32 = (STARTTILE16M+NUMTILE16M)\r
-STARTTILE32M = (STARTTILE32+NUMTILE32)\r
-STARTEXTERN = (STARTTILE32M+NUMTILE32M)\r
-\r
-NUMCHUNKS = (STARTEXTERN+NUMEXTERN)\r
-\r
-;\r
-; Thank you for using IGRAB!\r
-;\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __GFX_H__\r
-#define __GFX_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-//////////////////////////////////////\r
-//\r
-// Graphics .H file for .CK6\r
-// not IGRAB-ed :)\r
-//\r
-//////////////////////////////////////\r
-\r
-//\r
-// Lump creation macros\r
-//\r
-\r
-#define START_LUMP(actualname, dummyname) actualname, dummyname=actualname-1,\r
-#define END_LUMP(actualname, dummyname) dummyname, actualname=dummyname-1,\r
-\r
-//\r
-// Amount of each data item\r
-//\r
-\r
-//common numbers:\r
-#define NUMCHUNKS NUMGRCHUNKS\r
-#define NUMFONT 3\r
-#define NUMFONTM 0\r
-#define NUMPICM 3\r
-#define NUMTILE8 108 // BUG: only 104 tiles exist in EGAGRAPH!\r
-#define NUMTILE8M 36 // BUG: only 12 tiles exist in EGAGRAPH!\r
-#define NUMTILE32 0\r
-#define NUMTILE32M 0\r
-\r
-//episode-specific numbers:\r
-#define NUMPICS 37\r
-#define NUMSPRITES 390\r
-#define NUMTILE16 2376\r
-#define NUMTILE16M 2736\r
-#define NUMEXTERNS 10\r
-\r
-//\r
-// File offsets for data items\r
-//\r
-#define STRUCTPIC 0\r
-#define STRUCTPICM 1\r
-#define STRUCTSPRITE 2\r
-\r
-#define STARTFONT 3\r
-#define STARTFONTM (STARTFONT+NUMFONT)\r
-#define STARTPICS (STARTFONTM+NUMFONTM)\r
-#define STARTPICM (STARTPICS+NUMPICS)\r
-#define STARTSPRITES (STARTPICM+NUMPICM)\r
-#define STARTTILE8 (STARTSPRITES+NUMSPRITES)\r
-#define STARTTILE8M (STARTTILE8+1)\r
-#define STARTTILE16 (STARTTILE8M+1)\r
-#define STARTTILE16M (STARTTILE16+NUMTILE16)\r
-#define STARTTILE32 (STARTTILE16M+NUMTILE16M)\r
-#define STARTTILE32M (STARTTILE32+NUMTILE32)\r
-#define STARTEXTERNS (STARTTILE32M+NUMTILE32M)\r
-\r
-typedef enum {\r
- LASTFONT=STARTPICS-1,\r
-\r
- //\r
- // PICS\r
- //\r
-\r
- H_END1PIC, // 6\r
- H_END2PIC, // 7\r
- H_END3PIC, // 8\r
- H_END4PIC, // 9\r
- H_END5PIC, // 10\r
-\r
- START_LUMP(CONTROLS_LUMP_START, __CONTROLSSTART)\r
- CP_MAINMENUPIC, // 11\r
- CP_NEWGAMEMENUPIC, // 12\r
- CP_LOADMENUPIC, // 13\r
- CP_SAVEMENUPIC, // 14\r
- CP_CONFIGMENUPIC, // 15\r
- CP_SOUNDMENUPIC, // 16\r
- CP_MUSICMENUPIC, // 17\r
- CP_KEYBOARDMENUPIC, // 18\r
- CP_KEYMOVEMENTPIC, // 19\r
- CP_KEYBUTTONPIC, // 20\r
- CP_JOYSTICKMENUPIC, // 21\r
- CP_OPTIONSMENUPIC, // 22\r
- CP_PADDLEWARPIC, // 23\r
- CP_QUITPIC, // 24\r
- CP_JOYSTICKPIC, // 25\r
- CP_MENUSCREENPIC, // 26\r
- END_LUMP(CONTROLS_LUMP_END, __CONTROLSEND)\r
-\r
- H_FLASHARROW1PIC, // 27\r
- H_FLASHARROW2PIC, // 28\r
- IDSOFTPIC, // 29\r
- PROGTEAMPIC, // 30\r
- ARTISTPIC, // 31\r
- DIRECTORPIC, // 32\r
- SW_BACKGROUNDPIC, // 33\r
- TITLEPICPIC, // 34\r
- KEENTALK1PIC, // 35\r
- KEENTALK2PIC, // 36\r
- KEENCOUNT1PIC, // 37\r
- KEENCOUNT2PIC, // 38\r
- KEENCOUNT3PIC, // 39\r
- KEENCOUNT4PIC, // 40\r
- KEENCOUNT5PIC, // 41\r
- KEENCOUNT6PIC, // 42\r
-\r
- //\r
- // MASKED PICS\r
- //\r
-\r
- CP_MENUMASKPICM, // 43\r
- CORDPICM, // 44\r
- METALPOLEPICM, // 45\r
-\r
- //\r
- // SPRITES\r
- //\r
-\r
- START_LUMP(PADDLE_LUMP_START, __PADDLESTART)\r
- PADDLESPR, // 46\r
- BALLSPR, // 47\r
- BALL1PIXELTOTHERIGHTSPR, // 48\r
- BALL2PIXELSTOTHERIGHTSPR, // 49\r
- BALL3PIXELSTOTHERIGHTSPR, // 50\r
- END_LUMP(PADDLE_LUMP_END, __PADDLEEND)\r
-\r
- DEMOPLAQUESPR, // 51\r
-\r
- START_LUMP(KEEN_LUMP_START, __KEENSTART)\r
- KEENSTANDRSPR, // 52\r
- KEENRUNR1SPR, // 53\r
- KEENRUNR2SPR, // 54\r
- KEENRUNR3SPR, // 55\r
- KEENRUNR4SPR, // 56\r
- KEENJUMPR1SPR, // 57\r
- KEENJUMPR2SPR, // 58\r
- KEENJUMPR3SPR, // 59\r
- KEENSTANDLSPR, // 60\r
- KEENRUNL1SPR, // 61\r
- KEENRUNL2SPR, // 62\r
- KEENRUNL3SPR, // 63\r
- KEENRUNL4SPR, // 64\r
- KEENJUMPL1SPR, // 65\r
- KEENJUMPL2SPR, // 66\r
- KEENJUMPL3SPR, // 67\r
- KEENLOOKUSPR, // 68\r
- KEENWAITR1SPR, // 69\r
- KEENWAITR2SPR, // 70\r
- KEENWAITR3SPR, // 71\r
- KEENSITREAD1SPR, // 72\r
- KEENSITREAD2SPR, // 73\r
- KEENSITREAD3SPR, // 74\r
- KEENSITREAD4SPR, // 75\r
- KEENREAD1SPR, // 76\r
- KEENREAD2SPR, // 77\r
- KEENREAD3SPR, // 78\r
- KEENSTOPREAD1SPR, // 79\r
- KEENSTOPREAD2SPR, // 80\r
- KEENLOOKD1SPR, // 81\r
- KEENLOOKD2SPR, // 82\r
- KEENDIE1SPR, // 83\r
- KEENDIE2SPR, // 84\r
- KEENSTUNSPR, // 85\r
- STUNSTARS1SPR, // 86\r
- STUNSTARS2SPR, // 87\r
- STUNSTARS3SPR, // 88\r
- KEENSHOOTLSPR, // 89\r
- KEENJLSHOOTLSPR, // 90\r
- KEENJSHOOTDSPR, // 91\r
- KEENJSHOOTUSPR, // 92\r
- KEENSHOOTUSPR, // 93\r
- KEENSHOOTRSPR, // 94\r
- KEENJRSHOOTRSPR, // 95\r
- STUN1SPR, // 96\r
- STUN2SPR, // 97\r
- STUN3SPR, // 98\r
- STUN4SPR, // 99\r
- STUNHIT1SPR, // 100\r
- STUNHIT2SPR, // 101\r
- KEENSHINNYR1SPR, // 102\r
- KEENSHINNYR2SPR, // 103\r
- KEENSHINNYR3SPR, // 104\r
- KEENSLIDED1SPR, // 105\r
- KEENSLIDED2SPR, // 106\r
- KEENSLIDED3SPR, // 107\r
- KEENSLIDED4SPR, // 108\r
- KEENSHINNYL1SPR, // 109\r
- KEENSHINNYL2SPR, // 110\r
- KEENSHINNYL3SPR, // 111\r
- KEENPLSHOOTUSPR, // 112\r
- KEENPRSHOOTUSPR, // 113\r
- KEENPRSHOOTDSPR, // 114\r
- KEENPLSHOOTDSPR, // 115\r
- KEENPSHOOTLSPR, // 116\r
- KEENPSHOOTRSPR, // 117\r
- KEENENTER1SPR, // 118\r
- KEENENTER2SPR, // 119\r
- KEENENTER3SPR, // 120\r
- KEENENTER4SPR, // 121\r
- KEENENTER5SPR, // 122\r
- KEENHANGLSPR, // 123\r
- KEENHANGRSPR, // 124\r
- KEENCLIMBEDGEL1SPR, // 125\r
- KEENCLIMBEDGEL2SPR, // 126\r
- KEENCLIMBEDGEL3SPR, // 127\r
- KEENCLIMBEDGEL4SPR, // 128\r
- KEENCLIMBEDGER1SPR, // 129\r
- KEENCLIMBEDGER2SPR, // 130\r
- KEENCLIMBEDGER3SPR, // 131\r
- KEENCLIMBEDGER4SPR, // 132\r
- KEENPOGOR1SPR, // 133\r
- KEENPOGOR2SPR, // 134\r
- KEENPOGOL1SPR, // 135\r
- KEENPOGOL2SPR, // 136\r
- BONUS100UPSPR, // 137\r
- BONUS100SPR, // 138\r
- BONUS200SPR, // 139\r
- BONUS500SPR, // 140\r
- BONUS1000SPR, // 141\r
- BONUS2000SPR, // 142\r
- BONUS5000SPR, // 143\r
- BONUS1UPSPR, // 144\r
- BONUSCLIPSPR, // 145\r
- VIVASPLASH1SPR, // 146\r
- VIVASPLASH2SPR, // 147\r
- VIVASPLASH3SPR, // 148\r
- VIVASPLASH4SPR, // 149\r
- END_LUMP(KEEN_LUMP_END, __KEENEND)\r
-\r
- START_LUMP(SUGAR1_LUMP_START, __SUGAR1START)\r
- SUGAR1ASPR, // 150\r
- SUGAR1BSPR, // 151\r
- END_LUMP(SUGAR1_LUMP_END, __SUGAR1END)\r
-\r
- START_LUMP(SUGAR2_LUMP_START, __SUGAR2START)\r
- SUGAR2ASPR, // 152\r
- SUGAR2BSPR, // 153\r
- END_LUMP(SUGAR2_LUMP_END, __SUGAR2END)\r
-\r
- START_LUMP(SUGAR3_LUMP_START, __SUGAR3START)\r
- SUGAR3ASPR, // 154\r
- SUGAR3BSPR, // 155\r
- END_LUMP(SUGAR3_LUMP_END, __SUGAR3END)\r
-\r
- START_LUMP(SUGAR4_LUMP_START, __SUGAR4START)\r
- SUGAR4ASPR, // 156\r
- SUGAR4BSPR, // 157\r
- END_LUMP(SUGAR4_LUMP_END, __SUGAR4END)\r
-\r
- START_LUMP(SUGAR5_LUMP_START, __SUGAR5START)\r
- SUGAR5ASPR, // 158\r
- SUGAR5BSPR, // 159\r
- END_LUMP(SUGAR5_LUMP_END, __SUGAR5END)\r
-\r
- START_LUMP(SUGAR6_LUMP_START, __SUGAR6START)\r
- SUGAR6ASPR, // 160\r
- SUGAR6BSPR, // 161\r
- END_LUMP(SUGAR6_LUMP_END, __SUGAR6END)\r
-\r
- START_LUMP(ONEUP_LUMP_START, __ONEUPSTART)\r
- ONEUPASPR, // 162\r
- ONEUPBSPR, // 163\r
- END_LUMP(ONEUP_LUMP_END, __ONEUPEND)\r
-\r
- START_LUMP(KEYGEM_LUMP_START, __KEYGEMSTART)\r
- REDGEM1SPR, // 164\r
- REDGEM2SPR, // 165\r
- YELLOWGEM1SPR, // 166\r
- YELLOWGEM2SPR, // 167\r
- BLUEGEM1SPR, // 168\r
- BLUEGEM2SPR, // 169\r
- GREENGEM1SPR, // 170\r
- GREENGEM2SPR, // 171\r
- BONUSGEMSPR, // 172\r
- END_LUMP(KEYGEM_LUMP_END, __KEYGEMEND)\r
-\r
- START_LUMP(AMMO_LUMP_START, __AMMOSTART)\r
- STUNCLIP1SPR, // 173\r
- STUNCLIP2SPR, // 174\r
- END_LUMP(AMMO_LUMP_END, __AMMOEND)\r
-\r
- SCOREBOXSPR, // 175\r
-\r
- START_LUMP(LASER_LUMP_START, __LASERSTART)\r
- LASER1SPR, // 176\r
- LASER2SPR, // 177\r
- LASER3SPR, // 178\r
- LASER4SPR, // 179\r
- LASERHIT1SPR, // 180\r
- LASERHIT2SPR, // 181\r
- END_LUMP(LASER_LUMP_END, __LASEREND)\r
-\r
- START_LUMP(SANDWICH_LUMP_START, __SANDWICHSTART)\r
- SANDWICHSPR, // 182\r
- END_LUMP(SANDWICH_LUMP_END, __SANDWICHEND)\r
-\r
- START_LUMP(HOOK_LUMP_START, __ROPESTART)\r
- HOOKSPR, // 183\r
- END_LUMP(HOOK_LUMP_END, __ROPEEND)\r
-\r
- START_LUMP(WORLDKEEN_LUMP_START, __WORLDKEENSTART)\r
- WORLDKEENL1SPR, // 184\r
- WORLDKEENL2SPR, // 185\r
- WORLDKEENL3SPR, // 186\r
- WORLDKEENR1SPR, // 187\r
- WORLDKEENR2SPR, // 188\r
- WORLDKEENR3SPR, // 189\r
- WORLDKEENU1SPR, // 190\r
- WORLDKEENU2SPR, // 191\r
- WORLDKEENU3SPR, // 192\r
- WORLDKEEND1SPR, // 193\r
- WORLDKEEND2SPR, // 194\r
- WORLDKEEND3SPR, // 195\r
- WORLDKEENDR1SPR, // 196\r
- WORLDKEENDR2SPR, // 197\r
- WORLDKEENDR3SPR, // 198\r
- WORLDKEENDL1SPR, // 199\r
- WORLDKEENDL2SPR, // 200\r
- WORLDKEENDL3SPR, // 201\r
- WORLDKEENUL1SPR, // 202\r
- WORLDKEENUL2SPR, // 203\r
- WORLDKEENUL3SPR, // 204\r
- WORLDKEENUR1SPR, // 205\r
- WORLDKEENUR2SPR, // 206\r
- WORLDKEENUR3SPR, // 207\r
- WORLDKEENWAVE1SPR, // 208\r
- WORLDKEENWAVE2SPR, // 209\r
- ROCKETSPR, // 210\r
- ROCKETFLY1SPR, // 211\r
- ROCKETFLY2SPR, // 212\r
- SATELLITE1SPR, // 213\r
- SATELLITE2SPR, // 214\r
- SATELLITE3SPR, // 215\r
- SATELLITE4SPR, // 216\r
- GRABBITER1SPR, // 217\r
- GRABBITER2SPR, // 218\r
- GRABBITERSLEEP1SPR, // 219\r
- GRABBITERSLEEP2SPR, // 220\r
- WORLDKEENTRHOW1SPR, // 221\r
- WORLDKEENTRHOW2SPR, // 222\r
- WORLDKEENCLIMB1SPR, // 223\r
- WORLDKEENCLIMB2SPR, // 224\r
- ROPETHROW1SPR, // 225\r
- ROPETHROW2SPR, // 226\r
- WORLDKEENHANGSPR, // 227\r
- FLAGFLIP1SPR, // 228\r
- FLAGFLIP2SPR, // 229\r
- FLAGFLIP3SPR, // 230\r
- FLAGFLIP4SPR, // 231\r
- FLAGFLIP5SPR, // 232\r
- FLAGFALL1SPR, // 233\r
- FLAGFALL2SPR, // 234\r
- FLAGFLAP1SPR, // 235\r
- FLAGFLAP2SPR, // 236\r
- FLAGFLAP3SPR, // 237\r
- FLAGFLAP4SPR, // 238\r
- END_LUMP(WORLDKEEN_LUMP_END, __WORLDKEENEND)\r
-\r
- START_LUMP(FLEEX_LUMP_START, __FLEEXSTART)\r
- FLEEXWALKR1SPR, // 239\r
- FLEEXWALKR2SPR, // 240\r
- FLEEXWALKL1SPR, // 241\r
- FLEEXWALKL2SPR, // 242\r
- FLEEXLOOK1SPR, // 243\r
- FLEEXLOOK2SPR, // 244\r
- FLEEXSTUNSPR, // 245\r
- END_LUMP(FLEEX_LUMP_END, __FLEEXEND)\r
-\r
- START_LUMP(CEILICK_LUMP_START, __CEILICKSTART)\r
- CEILICK1SPR, // 246\r
- CEILICK2SPR, // 247\r
- TONGUE1SPR, // 248\r
- TONGUE2SPR, // 249\r
- TONGUE3SPR, // 250\r
- TONGUE4SPR, // 251\r
- TONGUE5SPR, // 252\r
- CEILICKSTUNSPR, // 253\r
- END_LUMP(CEILICK_LUMP_END, __CEILICKEND)\r
-\r
- START_LUMP(BLOOGUARD_LUMP_START, __BLOOGUARDSTART)\r
- BLOOGUARDWALKL1SPR, // 254\r
- BLOOGUARDWALKL2SPR, // 255\r
- BLOOGUARDWALKL3SPR, // 256\r
- BLOOGUARDWALKL4SPR, // 257\r
- BLOOGUARDWALKR1SPR, // 258\r
- BLOOGUARDWALKR2SPR, // 259\r
- BLOOGUARDWALKR3SPR, // 260\r
- BLOOGUARDWALKR4SPR, // 261\r
- BLOOGUARDSWINGL1SPR, // 262\r
- BLOOGUARDSWINGL2SPR, // 263\r
- BLOOGUARDSWINGL3SPR, // 264\r
- BLOOGUARDSWINGR1SPR, // 265\r
- BLOOGUARDSWINGR2SPR, // 266\r
- BLOOGUARDSWINGR3SPR, // 267\r
- BLOOGUARDSTUNSPR, // 268\r
- END_LUMP(BLOOGUARD_LUMP_END, __BLOOGUARDEND)\r
-\r
- START_LUMP(BIPSHIP_LUMP_START, __BIPSHIPSTART)\r
- BIPSHIPRSPR, // 269\r
- BIPSHIPRTURN1SPR, // 270\r
- BIPSHIPRTURN2SPR, // 271\r
- BIPSHIPRTURN3SPR, // 272\r
- BIPSHIPRTURN4SPR, // 273\r
- BIPSHIPLSPR, // 274\r
- BIPSHIPLTURN1SPR, // 275\r
- BIPSHIPLTURN2SPR, // 276\r
- BIPSHIPLTURN3SPR, // 277\r
- BIPSHIPLTURN4SPR, // 278\r
- BIPSHIPEXPLODE1SPR, // 279\r
- BIPSHIPEXPLODE2SPR, // 280\r
- BIPSHIPEXPLODE3SPR, // 281\r
- BIPSHIPEXPLODE4SPR, // 282\r
- BIPSHIPEXPLODE5SPR, // 283\r
- BIPSHIPSHOTSPR, // 284\r
- END_LUMP(BIPSHIP_LUMP_END, __BIPSHIPEND)\r
-\r
- START_LUMP(BABOBBA_LUMP_START, __BABOBBASTART)\r
- BABOBBAL1SPR, // 285\r
- BABOBBAL2SPR, // 286\r
- BABOBBAL3SPR, // 287\r
- BABOBBAR1SPR, // 288\r
- BABOBBAR2SPR, // 289\r
- BABOBBAR3SPR, // 290\r
- BABOBBASHOT1SPR, // 291\r
- BABOBBASHOT2SPR, // 292\r
- BABOBBASTUNSPR, // 293\r
- BABOBBASLEEP1SPR, // 294\r
- BABOBBASLEEP2SPR, // 295\r
- BABOBBASLEEP3SPR, // 296\r
- BABOBBASLEEP4SPR, // 297\r
- END_LUMP(BABOBBA_LUMP_END, __BABOBBAEND)\r
-\r
- START_LUMP(NOSPIKE_LUMP_START, __NOSPIKESTART)\r
- NOSPIKESTANDSPR, // 298\r
- NOSPIKERUNR1SPR, // 299\r
- NOSPIKERUNR2SPR, // 300\r
- NOSPIKERUNR3SPR, // 301\r
- NOSPIKERUNR4SPR, // 302\r
- NOSPIKERUNL1SPR, // 303\r
- NOSPIKERUNL2SPR, // 304\r
- NOSPIKERUNL3SPR, // 305\r
- NOSPIKERUNL4SPR, // 306\r
- NOSPIKEWALKR1SPR, // 307\r
- NOSPIKEWALKR2SPR, // 308\r
- NOSPIKEWALKR3SPR, // 309\r
- NOSPIKEWALKR4SPR, // 310\r
- NOSPIKEWALKL1SPR, // 311\r
- NOSPIKEWALKL2SPR, // 312\r
- NOSPIKEWALKL3SPR, // 313\r
- NOSPIKEWALKL4SPR, // 314\r
- NOSPIKESTUNSPR, // 315\r
- QUESTIONMARKSPR, // 316\r
- END_LUMP(NOSPIKE_LUMP_END, __NOSPIKEEND)\r
-\r
- START_LUMP(FLECT_LUMP_START, __FLECTSTART)\r
- FLECTSTANDSPR, // 317\r
- FLECTSTANDRSPR, // 318\r
- FLECTWALKR1SPR, // 319\r
- FLECTWALKR2SPR, // 320\r
- FLECTWALKR3SPR, // 321\r
- FLECTWALKR4SPR, // 322\r
- FLECTSTANDLSPR, // 323\r
- FLECTWALKL1SPR, // 324\r
- FLECTWALKL2SPR, // 325\r
- FLECTWALKL3SPR, // 326\r
- FLECTWALKL4SPR, // 327\r
- FLECTSTUNSPR, // 328\r
- END_LUMP(FLECT_LUMP_END, __FLECTEND)\r
-\r
- START_LUMP(ORBATRIX_LUMP_START, __ORBATRIXSTART)\r
- ORBATRIX1SPR, // 329\r
- ORBATRIX2SPR, // 330\r
- ORBATRIX3SPR, // 331\r
- ORBATRIX4SPR, // 332\r
- ORBATRIXL1SPR, // 333\r
- ORBATRIXL2SPR, // 334\r
- ORBATRIXR1SPR, // 335\r
- ORBATRIXR2SPR, // 336\r
- ORBATRIXSPIN1SPR, // 337\r
- ORBATRIXSPIN2SPR, // 338\r
- ORBATRIXSPIN3SPR, // 339\r
- ORBATRIXSPIN4SPR, // 340\r
- ORBATRIXCURLSPR, // 341\r
- END_LUMP(ORBATRIX_LUMP_END, __ORBATRIXEND)\r
-\r
- START_LUMP(BLOOG_LUMP_START, __BLOOGSTART)\r
- BLOOGWALKR1SPR, // 342\r
- BLOOGWALKR2SPR, // 343\r
- BLOOGWALKR3SPR, // 344\r
- BLOOGWALKR4SPR, // 345\r
- BLOOGWALKL1SPR, // 346\r
- BLOOGWALKL2SPR, // 347\r
- BLOOGWALKL3SPR, // 348\r
- BLOOGWALKL4SPR, // 349\r
- BLOOGSTUNSPR, // 350\r
- END_LUMP(BLOOG_LUMP_END, __BLOOGEND)\r
-\r
- START_LUMP(RBLOOGLET_LUMP_START, __RBLOOGLETSTART)\r
- RBLOOGLETWALKR1SPR, // 351\r
- RBLOOGLETWALKR2SPR, // 352\r
- RBLOOGLETWALKR3SPR, // 353\r
- RBLOOGLETWALKR4SPR, // 354\r
- RBLOOGLETWALKL1SPR, // 355\r
- RBLOOGLETWALKL2SPR, // 356\r
- RBLOOGLETWALKL3SPR, // 357\r
- RBLOOGLETWALKL4SPR, // 358\r
- RBLOOGLETSTUNSPR, // 359\r
- END_LUMP(RBLOOGLET_LUMP_END, __RBLOOGLETEND)\r
-\r
- START_LUMP(YBLOOGLET_LUMP_START, __YBLOOGLETSTART)\r
- YBLOOGLETWALKR1SPR, // 360\r
- YBLOOGLETWALKR2SPR, // 361\r
- YBLOOGLETWALKR3SPR, // 362\r
- YBLOOGLETWALKR4SPR, // 363\r
- YBLOOGLETWALKL1SPR, // 364\r
- YBLOOGLETWALKL2SPR, // 365\r
- YBLOOGLETWALKL3SPR, // 366\r
- YBLOOGLETWALKL4SPR, // 367\r
- YBLOOGLETSTUNSPR, // 368\r
- END_LUMP(YBLOOGLET_LUMP_END, __YBLOOGLETEND)\r
-\r
- START_LUMP(BBLOOGLET_LUMP_START, __BBLOOGLETSTART)\r
- BBLOOGLETWALKR1SPR, // 369\r
- BBLOOGLETWALKR2SPR, // 370\r
- BBLOOGLETWALKR3SPR, // 371\r
- BBLOOGLETWALKR4SPR, // 372\r
- BBLOOGLETWALKL1SPR, // 373\r
- BBLOOGLETWALKL2SPR, // 374\r
- BBLOOGLETWALKL3SPR, // 375\r
- BBLOOGLETWALKL4SPR, // 376\r
- BBLOOGLETSTUNSPR, // 377\r
- END_LUMP(BBLOOGLET_LUMP_END, __BBLOOGLETEND)\r
-\r
- START_LUMP(GBLOOGLET_LUMP_START, __GBLOOGLETSTART)\r
- GBLOOGLETWALKR1SPR, // 378\r
- GBLOOGLETWALKR2SPR, // 379\r
- GBLOOGLETWALKR3SPR, // 380\r
- GBLOOGLETWALKR4SPR, // 381\r
- GBLOOGLETWALKL1SPR, // 382\r
- GBLOOGLETWALKL2SPR, // 383\r
- GBLOOGLETWALKL3SPR, // 384\r
- GBLOOGLETWALKL4SPR, // 385\r
- GBLOOGLETSTUNSPR, // 386\r
- END_LUMP(GBLOOGLET_LUMP_END, __GBLOOGLETEND)\r
-\r
- START_LUMP(GIK_LUMP_START, __GIKSTART)\r
- GIKWALKR1SPR, // 387\r
- GIKWALKR2SPR, // 388\r
- GIKWALKR3SPR, // 389\r
- GIKWALKL1SPR, // 390\r
- GIKWALKL2SPR, // 391\r
- GIKWALKL3SPR, // 392\r
- GIKJUMPLSPR, // 393\r
- GIKJUMPRSPR, // 394\r
- GIKSLIDER1SPR, // 395\r
- GIKSLIDER2SPR, // 396\r
- GIKSLIDEL1SPR, // 397\r
- GIKSLIDEL2SPR, // 398\r
- END_LUMP(GIK_LUMP_END, __GIKEND)\r
-\r
- START_LUMP(BLORB_LUMP_START, __BLORBSTART)\r
- BLORB1SPR, // 399\r
- BLORB2SPR, // 400\r
- BLORB3SPR, // 401\r
- END_LUMP(BLORB_LUMP_END, __BLORBEND)\r
-\r
- START_LUMP(BOBBA_LUMP_START, __BOBBASTART)\r
- BOBBAL1SPR, // 402\r
- BOBBAL2SPR, // 403\r
- BOBBAL3SPR, // 404\r
- BOBBAR1SPR, // 405\r
- BOBBAR2SPR, // 406\r
- BOBBAR3SPR, // 407\r
- BOBBASHOT1SPR, // 408\r
- BOBBASHOT2SPR, // 409\r
- BOBBASHOT3SPR, // 410\r
- BOBBASHOT4SPR, // 411\r
- BOBBASHOT5SPR, // 412\r
- BOBBASHOT6SPR, // 413\r
- END_LUMP(BOBBA_LUMP_END, __BOBBAEND)\r
-\r
- START_LUMP(BIP_LUMP_START, __BIPSTART)\r
- BIPSTANDSPR, // 414\r
- BIPWALKR1SPR, // 415\r
- BIPWALKR2SPR, // 416\r
- BIPWALKR3SPR, // 417\r
- BIPWALKR4SPR, // 418\r
- BIPWALKL1SPR, // 419\r
- BIPWALKL2SPR, // 420\r
- BIPWALKL3SPR, // 421\r
- BIPWALKL4SPR, // 422\r
- END_LUMP(BIP_LUMP_END, __BIPEND)\r
-\r
- START_LUMP(BIPSQUISHED_LUMP_START, __BIPSQUISHEDSTART)\r
- BIPSQUISHEDSPR, // 423\r
- END_LUMP(BIPSQUISHED_LUMP_END, __BIPSQUISHEDEND)\r
-\r
- START_LUMP(PLATFORM_LUMP_START, __PLATFORMSTART)\r
- PLATFORMSPR, // 424\r
- PLATBIP1SPR, // 425\r
- PLATBIP2SPR, // 426\r
- PLATBIP3SPR, // 427\r
- PLATBIP4SPR, // 428\r
- PLATBIP5SPR, // 429\r
- PLATBIP6SPR, // 430\r
- PLATBIP7SPR, // 431\r
- PLATBIP8SPR, // 432\r
- END_LUMP(PLATFORM_LUMP_END, __PLATFORMEND)\r
-\r
- START_LUMP(MOLLY_LUMP_START, __MOLLYSTART)\r
- MOLLY1SPR, // 433\r
- MOLLY2SPR, // 434\r
- END_LUMP(MOLLY_LUMP_END, __MOLLYEND)\r
-\r
- START_LUMP(PASSCARD_LUMP_START, __PASSCARDSTART)\r
- PASSCARDSPR, // 435\r
- END_LUMP(PASSCARD_LUMP_END, __PASSCARDEND)\r
-\r
- //\r
- // TILES (these don't need names)\r
- //\r
-\r
- LASTTILE=STARTEXTERNS-1,\r
-\r
- //\r
- // EXTERNS\r
- //\r
-\r
- T_ENDART, // 5550\r
-\r
- ORDERSCREEN, // 5551\r
- BIGCOMMANDER, // 5552\r
- BIGKEEN, // 5553\r
- OUTOFMEM, // 5554\r
-\r
- //demos\r
- DEMO0, // 5555\r
- DEMO1, // 5556\r
- DEMO2, // 5557\r
- DEMO3, // 5558\r
- DEMO4, // 5559\r
-\r
- NUMGRCHUNKS\r
-} graphicnums;\r
-\r
-#undef START_LUMP\r
-#undef END_LUMP\r
-\r
-#endif //__GFX_H__
\ No newline at end of file
+++ /dev/null
-;\r
-; Equates for all .ASM files\r
-;\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-INCLUDE "GFXE_CK6.EQU"\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-CGAGR = 1\r
-EGAGR = 2\r
-VGAGR = 3\r
-\r
-GRMODE = EGAGR\r
-PROFILE = 0 ; 1=keep stats on tile drawing\r
-\r
-SC_INDEX = 03C4h\r
-SC_RESET = 0\r
-SC_CLOCK = 1\r
-SC_MAPMASK = 2\r
-SC_CHARMAP = 3\r
-SC_MEMMODE = 4\r
-\r
-CRTC_INDEX = 03D4h\r
-CRTC_H_TOTAL = 0\r
-CRTC_H_DISPEND = 1\r
-CRTC_H_BLANK = 2\r
-CRTC_H_ENDBLANK = 3\r
-CRTC_H_RETRACE = 4\r
-CRTC_H_ENDRETRACE = 5\r
-CRTC_V_TOTAL = 6\r
-CRTC_OVERFLOW = 7\r
-CRTC_ROWSCAN = 8\r
-CRTC_MAXSCANLINE = 9\r
-CRTC_CURSORSTART = 10\r
-CRTC_CURSOREND = 11\r
-CRTC_STARTHIGH = 12\r
-CRTC_STARTLOW = 13\r
-CRTC_CURSORHIGH = 14\r
-CRTC_CURSORLOW = 15\r
-CRTC_V_RETRACE = 16\r
-CRTC_V_ENDRETRACE = 17\r
-CRTC_V_DISPEND = 18\r
-CRTC_OFFSET = 19\r
-CRTC_UNDERLINE = 20\r
-CRTC_V_BLANK = 21\r
-CRTC_V_ENDBLANK = 22\r
-CRTC_MODE = 23\r
-CRTC_LINECOMPARE = 24\r
-\r
-\r
-GC_INDEX = 03CEh\r
-GC_SETRESET = 0\r
-GC_ENABLESETRESET = 1\r
-GC_COLORCOMPARE = 2\r
-GC_DATAROTATE = 3\r
-GC_READMAP = 4\r
-GC_MODE = 5\r
-GC_MISCELLANEOUS = 6\r
-GC_COLORDONTCARE = 7\r
-GC_BITMASK = 8\r
-\r
-ATR_INDEX = 03c0h\r
-ATR_MODE = 16\r
-ATR_OVERSCAN = 17\r
-ATR_COLORPLANEENABLE = 18\r
-ATR_PELPAN = 19\r
-ATR_COLORSELECT = 20\r
-\r
-STATUS_REGISTER_1 = 03dah\r
-\r
-\r
-MACRO WORDOUT\r
- out dx,ax\r
-ENDM\r
-\r
-if 0\r
-\r
-MACRO WORDOUT\r
- out dx,al\r
- inc dx\r
- xchg al,ah\r
- out dx,al\r
- dec dx\r
- xchg al,ah\r
-ENDM\r
-\r
-endif\r
-\r
-UPDATEWIDE = 22\r
-UPDATEHIGH = 14\r
-\r
-;\r
-; tile info offsets from segment tinf\r
-;\r
-\r
-ANIM = 402\r
-SPEED = (ANIM+NUMTILE16)\r
-\r
-NORTHWALL = (SPEED+NUMTILE16)\r
-EASTWALL = (NORTHWALL+NUMTILE16M)\r
-SOUTHWALL = (EASTWALL+NUMTILE16M)\r
-WESTWALL = (SOUTHWALL+NUMTILE16M)\r
-MANIM = (WESTWALL+NUMTILE16M)\r
-INTILE = (MANIM+NUMTILE16M)\r
-MSPEED = (INTILE+NUMTILE16M)\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-SCREENWIDTH = 64\r
-ENDIF\r
-IFE GRMODE-CGAGR\r
-SCREENWIDTH = 128\r
-ENDIF\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_GLOB.H\r
-\r
-\r
-#include <ALLOC.H>\r
-#include <CTYPE.H>\r
-#include <DOS.H>\r
-#include <ERRNO.H>\r
-#include <FCNTL.H>\r
-#include <IO.H>\r
-#include <MEM.H>\r
-#include <PROCESS.H>\r
-#include <STDIO.H>\r
-#include <STDLIB.H>\r
-#include <STRING.H>\r
-#include <SYS\STAT.H>\r
-\r
-#define __ID_GLOB__\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define KEEN\r
-#define KEEN6\r
-\r
-#define EXTENSION "CK6"\r
-\r
-extern char far introscn;\r
-\r
-#include "GFXE_CK6.H"\r
-#include "AUDIOCK6.H"\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define TEXTGR 0\r
-#define CGAGR 1\r
-#define EGAGR 2\r
-#define VGAGR 3\r
-\r
-#define GRMODE EGAGR\r
-\r
-#if GRMODE == EGAGR\r
-#define GREXT "EGA"\r
-#endif\r
-#if GRMODE == CGAGR\r
-#define GREXT "CGA"\r
-#endif\r
-\r
-//#define PROFILE\r
-\r
-//\r
-// ID Engine\r
-// Types.h - Generic types, #defines, etc.\r
-// v1.0d1\r
-//\r
-\r
-#ifndef __TYPES__\r
-#define __TYPES__\r
-\r
-typedef enum {false,true} boolean;\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long longword;\r
-typedef byte * Ptr;\r
-\r
-typedef struct\r
- {\r
- int x,y;\r
- } Point;\r
-typedef struct\r
- {\r
- Point ul,lr;\r
- } Rect;\r
-\r
-#define nil ((void *)0)\r
-\r
-#endif\r
-\r
-#include "ID_MM.H"\r
-#include "ID_CA.H"\r
-#include "ID_VW.H"\r
-#include "ID_RF.H"\r
-#include "ID_IN.H"\r
-#include "ID_SD.H"\r
-#include "ID_US.H"\r
-\r
-\r
-void Quit (char *error); // defined in user program\r
-\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K6_ACT1.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- some shared routines\r
-- Bonus Items\r
-- Grabbiter\r
-- Rocket\r
-- Grapple spots\r
-- Satellite\r
-- Quest Items (Sandwich, Grappling Hook, Passcard, Molly)\r
-- Platforms\r
-- falling platforms\r
-- static platforms\r
-- Goplat platforms\r
-- Trick platforms\r
-- Bloog\r
-- Blooguard\r
-- Blooglet\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- SHARED STUFF\r
-\r
-=============================================================================\r
-*/\r
-\r
-Sint16 pdirx[] = {0, 1, 0, -1, 1, 1, -1, -1};\r
-Sint16 pdiry[] = {-1, 0, 1, 0, -1, 1, 1, -1};\r
-\r
-/*\r
-===========================\r
-=\r
-= C_ClipSide\r
-=\r
-===========================\r
-*/\r
-\r
-void C_ClipSide(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- playerkludgeclipcancel = true;\r
- ClipToSpriteSide(hit, ob);\r
- playerkludgeclipcancel = false;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_ClipTop\r
-=\r
-===========================\r
-*/\r
-\r
-void C_ClipTop(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- ClipToSpriteTop(hit, ob);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Land\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Land(objtype *ob)\r
-{\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->yspeed = 0;\r
- if (ob->state->nextstate)\r
- {\r
- ChangeState(ob, ob->state->nextstate);\r
- }\r
- else\r
- {\r
- RemoveObj(ob);\r
- return;\r
- }\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Bounce\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Bounce(objtype *ob)\r
-{\r
- Uint16 wall,absx,absy,angle,newangle;\r
- Uint32 speed;\r
-\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = -ob->xspeed/2;\r
-\r
- if (ob->hitsouth)\r
- {\r
- ob->yspeed = -ob->yspeed/2;\r
- return;\r
- }\r
-\r
- wall = ob->hitnorth;\r
-#ifdef KEEN6Ev15\r
- if (!wall)\r
- {\r
- return;\r
- }\r
- else\r
-#else\r
- if (wall)\r
-#endif\r
- {\r
- if (ob->yspeed < 0)\r
- ob->yspeed = 0;\r
-\r
- absx = abs(ob->xspeed);\r
- absy = ob->yspeed;\r
- if (absx>absy)\r
- {\r
- if (absx>absy*2) // 22 degrees\r
- {\r
- angle = 0;\r
- speed = absx*286; // x*sqrt(5)/2\r
- }\r
- else // 45 degrees\r
- {\r
- angle = 1;\r
- speed = absx*362; // x*sqrt(2)\r
- }\r
- }\r
- else\r
- {\r
- if (absy>absx*2) // 90 degrees\r
- {\r
- angle = 3;\r
- speed = absy*256;\r
- }\r
- else\r
- {\r
- angle = 2; // 67 degrees\r
- speed = absy*286; // y*sqrt(5)/2\r
- }\r
- }\r
- if (ob->xspeed > 0)\r
- angle = 7-angle;\r
-\r
- speed >>= 1;\r
- newangle = bounceangle[ob->hitnorth][angle];\r
- switch (newangle)\r
- {\r
- case 0:\r
- ob->xspeed = speed / 286;\r
- ob->yspeed = -ob->xspeed / 2;\r
- break;\r
- case 1:\r
- ob->xspeed = speed / 362;\r
- ob->yspeed = -ob->xspeed;\r
- break;\r
- case 2:\r
- ob->yspeed = -(speed / 286);\r
- ob->xspeed = -ob->yspeed / 2;\r
- break;\r
- case 3:\r
-\r
- case 4:\r
- ob->xspeed = 0;\r
- ob->yspeed = -(speed / 256);\r
- break;\r
- case 5:\r
- ob->yspeed = -(speed / 286);\r
- ob->xspeed = ob->yspeed / 2;\r
- break;\r
- case 6:\r
- ob->xspeed = ob->yspeed = -(speed / 362);\r
- break;\r
- case 7:\r
- ob->xspeed = -(speed / 286);\r
- ob->yspeed = ob->xspeed / 2;\r
- break;\r
-\r
- case 8:\r
- ob->xspeed = -(speed / 286);\r
- ob->yspeed = -ob->xspeed / 2;\r
- break;\r
- case 9:\r
- ob->xspeed = -(speed / 362);\r
- ob->yspeed = -ob->xspeed;\r
- break;\r
- case 10:\r
- ob->yspeed = speed / 286;\r
- ob->xspeed = -ob->yspeed / 2;\r
- break;\r
- case 11:\r
-\r
- case 12:\r
- ob->xspeed = 0;\r
- ob->yspeed = -(speed / 256);\r
- break;\r
- case 13:\r
- ob->yspeed = speed / 286;\r
- ob->xspeed = ob->yspeed / 2;\r
- break;\r
- case 14:\r
- ob->xspeed = speed / 362;\r
- ob->yspeed = speed / 362;\r
- break;\r
- case 15:\r
- ob->xspeed = speed / 286;\r
- ob->yspeed = ob->xspeed / 2;\r
- break;\r
- }\r
-\r
- if (speed < 256*16)\r
- {\r
- ChangeState(ob, ob->state->nextstate);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BONUS ITEMS\r
-\r
-temp1 = bonus type\r
-temp2 = base shape number\r
-temp3 = last animated shape number +1\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bonus1 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus2};\r
-statetype s_bonus2 = {0, 0, step, false, false, 20, 0, 0, T_Bonus, NULL, R_Draw, &s_bonus1};\r
-statetype s_bonusfly1 = {0, 0, stepthink, false, false, 20, 0, 0, T_FlyBonus, NULL, R_Draw, &s_bonusfly2};\r
-statetype s_bonusfly2 = {0, 0, stepthink, false, false, 20, 0, 0, T_FlyBonus, NULL, R_Draw, &s_bonusfly1};\r
-statetype s_bonusrise = {0, 0, slide, false, false, 40, 0, 8, NULL, NULL, R_Draw, NULL};\r
-\r
-statetype s_splash1 = {VIVASPLASH1SPR, VIVASPLASH1SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash2};\r
-statetype s_splash2 = {VIVASPLASH2SPR, VIVASPLASH2SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash3};\r
-statetype s_splash3 = {VIVASPLASH3SPR, VIVASPLASH3SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_splash4};\r
-statetype s_splash4 = {VIVASPLASH4SPR, VIVASPLASH4SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-Uint16 bonusshape[] = {\r
- REDGEM1SPR, YELLOWGEM1SPR, BLUEGEM1SPR, GREENGEM1SPR,\r
- SUGAR1ASPR, SUGAR2ASPR, SUGAR3ASPR,\r
- SUGAR4ASPR, SUGAR5ASPR, SUGAR6ASPR,\r
- ONEUPASPR, STUNCLIP1SPR\r
-};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBonus\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBonus(Uint16 tileX, Uint16 tileY, Uint16 type)\r
-{\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = bonusobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->ydir = -1;\r
- new->temp1 = type;\r
- new->temp2=new->shapenum = bonusshape[type];\r
- new->temp3 = new->temp2+2;\r
- NewState(new, &s_bonus1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSplash\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSplash(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(true);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 3;\r
- new->obclass = inertobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- NewState(new, &s_splash1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Bonus\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Bonus(objtype *ob)\r
-{\r
- if (++ob->shapenum == ob->temp3)\r
- ob->shapenum = ob->temp2;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_FlyBonus\r
-=\r
-===========================\r
-*/\r
-\r
-void T_FlyBonus(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- ob->state = &s_bonus1;\r
-\r
- if (++ob->shapenum == ob->temp3)\r
- ob->shapenum = ob->temp2;\r
-\r
- DoGravity(ob);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GRABBITER\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_grabbiter1 = {GRABBITER1SPR, GRABBITER1SPR, step, false, false, 12, 0, 0, NULL, C_Grabbiter, R_Draw, &s_grabbiter2};\r
-statetype s_grabbiter2 = {GRABBITER2SPR, GRABBITER2SPR, step, false, false, 12, 0, 0, NULL, C_Grabbiter, R_Draw, &s_grabbiter1};\r
-statetype s_grabbitersleep1 = {GRABBITERSLEEP1SPR, GRABBITERSLEEP1SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_grabbitersleep2};\r
-statetype s_grabbitersleep2 = {GRABBITERSLEEP2SPR, GRABBITERSLEEP2SPR, step, false, false, 12, 0, 0, NULL, NULL, R_Draw, &s_grabbitersleep1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnGrabbiter\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnGrabbiter(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->active = ac_yes;\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = grabbiterobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- if (gamestate.sandwichstate == 2)\r
- {\r
- NewState(new, &s_grabbitersleep1);\r
- }\r
- else\r
- {\r
- NewState(new, &s_grabbiter1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Grabbiter\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Grabbiter(objtype *ob, objtype *hit)\r
-{\r
- // BUG: this is executed for every object, not just (Map-)Keen!\r
- switch (gamestate.sandwichstate)\r
- {\r
- case 0:\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
- SD_PlaySound(SND_GRABBITER);\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 5;\r
- US_CPrint(\r
- "Oh, no!\n"\r
- "It's a slavering\n"\r
- "Grabbiter! He says,\n"\r
- "\"Get me lunch and\n"\r
- "I'll tell ya a secret!\""\r
- );\r
- VW_UpdateScreen();\r
- SD_PlaySound(SND_NOWAY);\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- RF_ForceRefresh();\r
-\r
- //push Keen back\r
- xtry = -hit->xmove;\r
- ytry = -hit->ymove;\r
- hit->xdir = hit->ydir = 0;\r
- ClipToWalls(hit);\r
- break;\r
-\r
- case 1:\r
- gamestate.sandwichstate++;\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 2;\r
- US_CPrint(\r
- "The Grabbiter grabs\n"\r
- "the gigantic sandwich,\n"\r
- "downs it in one bite,\n"\r
- "and says,\"Here's your\n"\r
- "secret. Big meals\n"\r
- "make me sleepy!\n" // BUG: quote is missing at the end\r
- );\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- ChangeState(ob, &s_grabbitersleep1);\r
- RF_ForceRefresh();\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- ROCKET\r
-\r
-temp1 = direction\r
-temp2 = countdown to next dir check\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_rocket = {ROCKETSPR, ROCKETSPR, think, false, false, 0, 0, 0, NULL, C_Rocket, R_Draw, NULL};\r
-statetype s_rocketfly1 = {ROCKETFLY1SPR, ROCKETFLY1SPR, stepthink, false, false, 8, 0, 0, T_RocketFly, C_RocketFly, R_Draw, &s_rocketfly2};\r
-statetype s_rocketfly2 = {ROCKETFLY2SPR, ROCKETFLY2SPR, stepthink, false, false, 8, 0, 0, T_RocketFly, C_RocketFly, R_Draw, &s_rocketfly1};\r
-statetype s_keenrocket = {0, 0, think, false, false, 0, 0, 0, T_Rocket, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnRocket\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnRocket(Uint16 tileX, Uint16 tileY, Uint16 state)\r
-{\r
- if (gamestate.rocketstate == state)\r
- {\r
- GetNewObj(false);\r
- new->active = ac_yes;\r
- new->needtoclip = cl_noclip;\r
- new->priority = 3;\r
- new->obclass = rocketobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- NewState(new, &s_rocket);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Rocket\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Rocket(objtype *ob)\r
-{\r
- ob->needtoreact = true;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Rocket\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Rocket(objtype *ob, objtype *hit)\r
-{\r
- // BUG: this is executed for every object, not just (Map-)Keen!\r
- switch (gamestate.passcardstate)\r
- {\r
- case 0:\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 5;\r
- US_CPrint(\r
- "The door makes a loud\n"\r
- "blooping noise.\n"\r
- "It says,\n"\r
- "\"Passcard required\n"\r
- "for entry.\""\r
- );\r
- VW_UpdateScreen();\r
- SD_PlaySound(SND_NOWAY);\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- RF_ForceRefresh();\r
-\r
- //push Keen back\r
- xtry = -hit->xmove;\r
- ytry = -hit->ymove;\r
- hit->xdir = hit->ydir = 0;\r
- ClipToWalls(hit);\r
- break;\r
-\r
- case 1:\r
- ob->temp1 = arrow_North;\r
- ob->temp2 = TILEGLOBAL;\r
- ChangeState(ob, &s_rocketfly1);\r
-\r
- hit->x = ob->x;\r
- hit->y = ob->y + TILEGLOBAL;\r
- hit->needtoclip = cl_noclip;\r
- ChangeState(hit, &s_keenrocket);\r
- SD_PlaySound(SND_ROCKETSTART);\r
- SD_WaitSoundDone();\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_RocketFly\r
-=\r
-===========================\r
-*/\r
-\r
-void C_RocketFly(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- hit->x = ob->x;\r
- hit->y = ob->y+TILEGLOBAL;\r
- ChangeState(hit, hit->state);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_RocketFly\r
-=\r
-===========================\r
-*/\r
-\r
-void T_RocketFly(objtype *ob)\r
-{\r
- Uint16 move, tx, ty;\r
- Sint16 dir;\r
-\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (xtry == 0 && ytry == 0)\r
- {\r
- if (!SD_SoundPlaying())\r
- SD_PlaySound(SND_ROCKETFLY);\r
-\r
- move = tics << 5;\r
- if (ob->temp2 > move)\r
- {\r
- ob->temp2 = ob->temp2 - move;\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = -move;\r
- }\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = move;\r
-\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = -move;\r
- }\r
- }\r
- else\r
- {\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = -ob->temp2;\r
- }\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = -ob->temp2;\r
- }\r
-\r
- tx = CONVERT_GLOBAL_TO_TILE(ob->x + xtry);\r
- ty = CONVERT_GLOBAL_TO_TILE(ob->y + ytry);\r
- ob->temp1 = *(mapsegs[2]+mapbwidthtable[ty]/2 + tx)-DIRARROWSTART;\r
- if (ob->temp1 < arrow_North || ob->temp1 > arrow_None)\r
- {\r
- ob->x += xtry;\r
- ob->y += ytry;\r
- ChangeState(ob, &s_rocket);\r
-\r
- player->x = CONVERT_TILE_TO_GLOBAL(tx+1) + 1*PIXGLOBAL;\r
- player->y = CONVERT_TILE_TO_GLOBAL(ty+1);\r
- player->obclass = keenobj;\r
- player->shapenum = WORLDKEENR3SPR;\r
- player->needtoclip = cl_midclip;\r
- NewState(player, &s_worldkeen);\r
- gamestate.rocketstate ^= 1;\r
- }\r
- else\r
- {\r
- move -= ob->temp2;\r
- ob->temp2 = TILEGLOBAL - move;\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry - move;\r
- }\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry - move;\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GRAPPLE SPOT\r
-\r
-temp1 = type (0 = top of cliff, 1 = bottom of cliff)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_grapplespot = {-1, -1, think, false, false, 0, 0, 0, NULL, C_GrappleSpot, R_Draw, NULL};\r
-statetype s_throwrope1 = {WORLDKEENTRHOW1SPR, WORLDKEENTRHOW1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_throwrope2};\r
-statetype s_throwrope2 = {WORLDKEENTRHOW2SPR, WORLDKEENTRHOW2SPR, step, false, false, 8, 0, 0, T_ThrowRope, NULL, R_Draw, &s_worldkeen};\r
-statetype s_climbrope1 = {WORLDKEENCLIMB1SPR, WORLDKEENCLIMB1SPR, slide, true, false, 4, 0, 16, NULL, NULL, R_Draw, &s_climbrope2};\r
-statetype s_climbrope2 = {WORLDKEENCLIMB2SPR, WORLDKEENCLIMB2SPR, slide, true, false, 4, 0, 16, T_ClimbRope, NULL, R_Draw, &s_climbrope1};\r
-statetype s_maprope = {ROPETHROW2SPR, ROPETHROW2SPR, think, false, false, 0, 0, 0, NULL, NULL, R_Draw, NULL};\r
-statetype s_mapropeshort = {ROPETHROW1SPR, ROPETHROW1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_mapropeshort};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnGrappleSpot\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnGrappleSpot(Uint16 tileX, Uint16 tileY, Uint16 type)\r
-{\r
- GetNewObj(false);\r
- new->active = ac_yes;\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = grapplespotobj;\r
- new->tileleft = new->tileright = tileX;\r
- new->tiletop = new->tilebottom = tileY;\r
- new->temp1 = type;\r
- new->x = new->left = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->right = new->left + TILEGLOBAL;\r
- if (type)\r
- {\r
- new->y = new->top = CONVERT_TILE_TO_GLOBAL(tileY+1)-1;\r
- }\r
- else\r
- {\r
- new->y = new->top = CONVERT_TILE_TO_GLOBAL(tileY);\r
- }\r
- new->bottom = new->top + 1;\r
- NewState(new, &s_grapplespot);\r
-\r
- if (gamestate.hookstate == 2 && type)\r
- {\r
- GetNewObj(false);\r
- new->active = ac_yes;\r
- new->needtoclip = cl_noclip;\r
- new->priority = 0;\r
- new->obclass = inertobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY+1);\r
- NewState(new, &s_maprope);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_ThrowRope\r
-=\r
-===========================\r
-*/\r
-\r
-void T_ThrowRope(objtype *ob)\r
-{\r
- GetNewObj(false);\r
- new->active = ac_yes;\r
- new->needtoclip = cl_noclip;\r
- new->priority = 0;\r
- new->obclass = inertobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(ob->tileright);\r
- new->y = ob->y - 2*TILEGLOBAL;\r
- NewState(new, &s_maprope);\r
-\r
- ob->obclass = keenobj;\r
- ob->shapenum = WORLDKEENU3SPR;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_ClimbRope\r
-=\r
-===========================\r
-*/\r
-\r
-void T_ClimbRope(objtype *ob)\r
-{\r
- if (--ob->temp4 == 0)\r
- {\r
- if (ob->ydir == 1)\r
- {\r
- ob->y += 3*PIXGLOBAL;\r
- ob->shapenum = WORLDKEEND3SPR;\r
- }\r
- else\r
- {\r
- ob->y -= 3*PIXGLOBAL;\r
- ob->shapenum = WORLDKEENU3SPR;\r
- }\r
- ob->obclass = keenobj;\r
- NewState(ob, &s_worldkeen);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_GrappleSpot\r
-=\r
-===========================\r
-*/\r
-\r
-void C_GrappleSpot(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- switch (gamestate.hookstate)\r
- {\r
- case 0:\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
- VW_FixRefreshBuffer();\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 15;\r
- US_CPrint(\r
- "What a tall cliff!\n"\r
- "Wish I had a rope\n"\r
- "and grappling hook.\n"\r
- );\r
- VW_UpdateScreen();\r
- SD_PlaySound(SND_NOWAY);\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- RF_ForceRefresh();\r
-\r
- //push Keen back\r
- xtry = -hit->xmove;\r
- ytry = -hit->ymove;\r
- hit->xdir = hit->ydir = 0;\r
- ClipToWalls(hit);\r
- break;\r
-\r
- case 1:\r
- gamestate.hookstate++;\r
- SD_PlaySound(SND_THROWROPE);\r
- ChangeState(hit, &s_throwrope1);\r
- hit->obclass = inertobj;\r
- break;\r
-\r
- case 2:\r
- if (ob->temp1)\r
- {\r
- hit->y += 4*PIXGLOBAL;\r
- hit->temp4 = 6;\r
- hit->ydir = 1;\r
- }\r
- else\r
- {\r
- hit->y -= 4*PIXGLOBAL;\r
- hit->temp4 = 6;\r
- hit->ydir = -1;\r
- }\r
- NewState(hit, &s_climbrope1);\r
- hit->obclass = inertobj;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SATELLITE\r
-\r
-temp1 = direction (satellite) / type (stop points)\r
-temp2 = countdown to next dir check\r
-temp3 = type of stop point touched (low byte: current; high byte: previous)\r
- is updated every frame and resets to 0 when no longer touching a spot\r
-temp4 = type of last stop point passed over (1 or 2, never 0)\r
- is updated when no longer touching the spot\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_satellitestopspot = {-1, -1, think, false, false, 0, 0, 0, NULL, NULL, NULL, NULL};\r
-statetype s_worldkeensatellite = {WORLDKEENHANGSPR, WORLDKEENHANGSPR, think, false, false, 0, 0, 0, NULL, NULL, R_WorldKeenSatellite, NULL};\r
-statetype s_satellite1 = {SATELLITE1SPR, SATELLITE1SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite2};\r
-statetype s_satellite2 = {SATELLITE2SPR, SATELLITE2SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite3};\r
-statetype s_satellite3 = {SATELLITE3SPR, SATELLITE3SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite4};\r
-statetype s_satellite4 = {SATELLITE4SPR, SATELLITE4SPR, stepthink, false, false, 10, 0, 0, T_Satellite, C_Satellite, R_Draw, &s_satellite1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSatelliteStop\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSatelliteStop(Uint16 tileX, Uint16 tileY, Uint16 type)\r
-{\r
- GetNewObj(false);\r
- new->active = ac_allways;\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = satellitestopobj;\r
- new->tileleft=new->tileright=tileX;\r
- new->tiletop=new->tilebottom=tileY;\r
- new->temp1 = (type ^ 1) + 1; // type is either 0 or 1, so this just maps 0 to 2 and 1 to 1\r
- new->x=new->left = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->right = new->left + TILEGLOBAL;\r
- new->y=new->top = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->bottom = new->top + TILEGLOBAL;\r
- NewState(new, &s_satellitestopspot);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSatellite\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSatellite(Uint16 tileX, Uint16 tileY)\r
-{\r
- Sint16 dir;\r
-\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->active = ac_allways;\r
- new->obclass = satelliteobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- NewState(new, &s_satellite1);\r
-\r
- dir = arrow_West;\r
- (mapsegs[2]+mapbwidthtable[tileY]/2)[tileX] = (dir+DIRARROWSTART);\r
- new->temp1 = dir;\r
- new->temp2 = TILEGLOBAL;\r
- new->temp4 = 2;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Satellite\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Satellite(objtype *ob)\r
-{\r
- //\r
- // this code could be executed twice during the same frame because the\r
- // object's animation/state changed during that frame, so don't update\r
- // anything if we already have movement for the current frame i.e. the\r
- // update code has already been executed this frame\r
- //\r
- if (xtry == 0 && ytry == 0)\r
- {\r
- //\r
- // if current stop spot type is 0 (not touching a spot), but previous\r
- // type is not 0, then set temp4 to the previous type\r
- //\r
- if (!(ob->temp3 & 0xFF) && (ob->temp3 & 0xFF00))\r
- {\r
- ob->temp4 = ob->temp3 >> 8;\r
- }\r
- //\r
- // move current type into previous type and set current stop type to 0\r
- //\r
- ob->temp3 <<= 8;\r
-\r
- //\r
- // follow the arrow path like a GoPlat\r
- //\r
- T_GoPlat(ob);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Satellite\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Satellite(objtype *ob, objtype *hit)\r
-{\r
- Sint16 temp;\r
- objtype *o;\r
-\r
- if (hit->state == &s_satellitestopspot)\r
- {\r
- ob->temp3 |= hit->temp1;\r
- }\r
- else if (hit->obclass == keenobj)\r
- {\r
- //\r
- // check if satellite has reaced a new stop spot\r
- //\r
- temp = ob->temp3 >> 8;\r
- if (temp && temp != ob->temp4)\r
- {\r
- SD_PlaySound(SND_GRABSATELLITE);\r
- //\r
- // update last spot value (don't grab or drop Keen until moved to the next spot)\r
- //\r
- ob->temp4 = temp;\r
- if (player->state == &s_worldkeensatellite)\r
- {\r
- //\r
- // drop Keen off at the current stop spot\r
- //\r
- for (o=player->next; o; o=o->next)\r
- {\r
- if (o->obclass == satellitestopobj && o->temp1 == temp)\r
- {\r
- hit->x = o->x;\r
- hit->y = o->y;\r
- hit->shapenum = WORLDKEENU3SPR;\r
- ChangeState(player, &s_worldkeen);\r
- hit->needtoclip = cl_midclip;\r
- return;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- //\r
- // grab and carry Keen\r
- //\r
- hit->x = ob->x + 12*PIXGLOBAL;\r
- hit->y = ob->y + 16*PIXGLOBAL;\r
- hit->needtoclip = cl_noclip;\r
- ChangeState(player, &s_worldkeensatellite);\r
- }\r
- }\r
- else if (hit->state == &s_worldkeensatellite)\r
- {\r
- //\r
- // move Keen along with the satellite\r
- //\r
- hit->x = ob->x + 12*PIXGLOBAL;\r
- hit->y = ob->y + 16*PIXGLOBAL;\r
- ChangeState(hit, hit->state);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_WorldKeenSatellite\r
-=\r
-===========================\r
-*/\r
-\r
-void R_WorldKeenSatellite(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x + 4*PIXGLOBAL, ob->y + 8*PIXGLOBAL, WORLDKEENHANGSPR, spritedraw, 1);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SANDWICH\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_sandwich = {SANDWICHSPR, SANDWICHSPR, think, false, false, 0, 0, 0, NULL, C_Molly, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSandwich\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSandwich(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = sandwichobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- NewState(new, &s_sandwich);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GRAPPLING HOOK\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_hook = {HOOKSPR, HOOKSPR, think, false, false, 0, 0, 0, NULL, C_Molly, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnHook\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnHook(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = hookobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- NewState(new, &s_hook);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- PASSCARD\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_passcard = {PASSCARDSPR, PASSCARDSPR, think, false, false, 0, 0, 0, NULL, C_Molly, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnPasscard\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnPasscard(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->needtoclip = cl_noclip;\r
- new->priority = 2;\r
- new->obclass = passcardobj;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- NewState(new, &s_passcard);\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Molly\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Molly(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- switch (ob->obclass)\r
- {\r
- case sandwichobj:\r
- playstate = ex_sandwich;\r
- break;\r
-\r
- case hookobj:\r
- playstate = ex_hook;\r
- break;\r
-\r
- case passcardobj:\r
- playstate = ex_card;\r
- break;\r
-\r
- case mollyobj:\r
- playstate = ex_molly;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- MOLLY\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_molly1 = {MOLLY1SPR, MOLLY1SPR, step, false, false, 20, 0, 0, NULL, C_Molly, R_Draw, &s_molly2};\r
-statetype s_molly2 = {MOLLY2SPR, MOLLY2SPR, step, false, false, 40, 0, 0, NULL, C_Molly, R_Draw, &s_molly3};\r
-statetype s_molly3 = {MOLLY1SPR, MOLLY1SPR, step, false, false, 40, 0, 0, NULL, C_Molly, R_Draw, &s_molly4};\r
-statetype s_molly4 = {MOLLY2SPR, MOLLY2SPR, step, false, false, 20, 0, 0, NULL, C_Molly, R_Draw, &s_molly1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnMolly\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnMolly(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = mollyobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_molly1);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- PLATFORM\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_platform = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_Platform, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnPlatform\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnPlatform(Uint16 tileX, Uint16 tileY, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- switch (dir)\r
- {\r
- case 0:\r
- new->xdir = 0;\r
- new->ydir = -1;\r
- break;\r
- case 1:\r
- new->xdir = 1;\r
- new->ydir = 0;\r
- break;\r
- case 2:\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- break;\r
- case 3:\r
- new->xdir = -1;\r
- new->ydir = 0;\r
- }\r
- NewState(new, &s_platform);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Platform\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Platform(objtype *ob)\r
-{\r
- Uint16 newpos, newtile;\r
-\r
- xtry = ob->xdir * 12 * tics;\r
- ytry = ob->ydir * 12 * tics;\r
-\r
- if (ob->xdir == 1)\r
- {\r
- newpos = ob->right + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileright != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK)\r
- {\r
- ob->xdir = -1;\r
- xtry = xtry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- else if (ob->xdir == -1)\r
- {\r
- newpos = ob->left + xtry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tileleft != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[ob->tiletop]/2 + newtile) == PLATFORMBLOCK)\r
- {\r
- ob->xdir = 1;\r
- xtry = xtry + (TILEGLOBAL - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- else if (ob->ydir == 1)\r
- {\r
- newpos = ob->bottom + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tilebottom != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile-2]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = -1;\r
- ytry = ytry - (newpos & 0xFF);\r
- }\r
- }\r
- }\r
- }\r
- else if (ob->ydir == -1)\r
- {\r
- newpos = ob->top + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tiletop != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile+2]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- ytry = 0;\r
- ob->needtoreact = true;\r
- }\r
- else\r
- {\r
- ob->ydir = 1;\r
- ytry = ytry + (TILEGLOBAL - (newpos & 0xFF));\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- DROPPING PLATFORM\r
-\r
-temp1 = initial y position\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_dropplatsit = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatSit, NULL, R_Draw, NULL};\r
-statetype s_fallplatfall = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_DropPlatFall, NULL, R_Draw, NULL};\r
-statetype s_fallplatrise = {PLATFORMSPR, PLATFORMSPR, slidethink, false, false, 0, 0, -32, T_DropPlatRise, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnDropPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnDropPlat(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_dropplatsit);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatSit\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatSit(objtype *ob)\r
-{\r
- if (gamestate.riding == ob)\r
- {\r
- ytry = tics << 4; //tics * 16;\r
- ob->yspeed = 0;\r
- if (ob->y + ytry - ob->temp1 >= 8*PIXGLOBAL)\r
- ob->state = &s_fallplatfall;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatFall\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatFall(objtype *ob)\r
-{\r
- Uint16 newpos, newtile;\r
-\r
- DoGravity(ob);\r
-\r
-#if 0\r
- // bugfix: don't skip a tile (this is present in Keen 4, but missing in 5 & 6)\r
- if (ytry >= 15*PIXGLOBAL)\r
- ytry = 15*PIXGLOBAL;\r
-#endif\r
-\r
- newpos = ob->bottom + ytry;\r
- newtile = CONVERT_GLOBAL_TO_TILE(newpos);\r
- if (ob->tilebottom != newtile)\r
- {\r
- if (*(mapsegs[2]+mapbwidthtable[newtile]/2 + ob->tileleft) == PLATFORMBLOCK)\r
- {\r
- ytry = 0xFF - (ob->bottom & 0xFF);\r
- if (gamestate.riding != ob)\r
- ob->state = &s_fallplatrise;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_DropPlatRise\r
-=\r
-===========================\r
-*/\r
-\r
-void T_DropPlatRise(objtype *ob)\r
-{\r
- if (gamestate.riding == ob)\r
- {\r
- ob->yspeed = 0;\r
- ob->state = &s_fallplatfall;\r
- }\r
- else if (ob->y <= ob->temp1)\r
- {\r
- ytry = ob->temp1 - ob->y;\r
- ob->state = &s_dropplatsit;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- STATIC PLATFORM\r
-\r
-temp1 = initial y position (is set but never used)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_staticplatform = {PLATFORMSPR, PLATFORMSPR, step, false, false, 32000, 0, 0, NULL, NULL, R_Draw, &s_staticplatform};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnStaticPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnStaticPlat(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_staticplatform);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GO PLATFORM\r
-\r
-temp1 = direction\r
-temp2 = countdown to next dir check\r
-temp3 = sprite pointer for the Bip sprite\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_goplat = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_GoPlat, NULL, R_GoPlat, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnGoPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnGoPlat(Uint16 tileX, Uint16 tileY, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_goplat);\r
- *(mapsegs[2]+mapbwidthtable[tileY]/2 + tileX) = dir + DIRARROWSTART;\r
- new->temp1 = dir;\r
- new->temp2 = TILEGLOBAL;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_GoPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void T_GoPlat(objtype *ob)\r
-{\r
- Uint16 move;\r
- Sint16 dir;\r
- Uint16 tx, ty;\r
-\r
- move = tics * 12;\r
- if (ob->temp2 > move)\r
- {\r
- ob->temp2 = ob->temp2 - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry + -move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry + -move;\r
- }\r
- }\r
- else\r
- {\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry += -ob->temp2;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry += ob->temp2;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry += -ob->temp2;\r
- }\r
-\r
- tx = CONVERT_GLOBAL_TO_TILE(ob->x + xtry);\r
- ty = CONVERT_GLOBAL_TO_TILE(ob->y + ytry);\r
- ob->temp1 = *(mapsegs[2]+mapbwidthtable[ty]/2 + tx) - DIRARROWSTART;\r
- if (ob->temp1 < arrow_North || ob->temp1 > arrow_None)\r
- {\r
- Quit("Goplat moved to a bad spot!");\r
- }\r
-\r
- move -= ob->temp2;\r
- ob->temp2 = TILEGLOBAL - move;\r
-\r
- dir = pdirx[ob->temp1];\r
- if (dir == 1)\r
- {\r
- xtry = xtry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- xtry = xtry - move;\r
- }\r
-\r
- dir = pdiry[ob->temp1];\r
- if (dir == 1)\r
- {\r
- ytry = ytry + move;\r
- }\r
- else if (dir == -1)\r
- {\r
- ytry = ytry - move;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_GoPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void R_GoPlat(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- RF_PlaceSprite((void**)&ob->temp3, ob->x+TILEGLOBAL, ob->y+TILEGLOBAL, ob->temp1+PLATBIP1SPR, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SNEAKY PLATFORM\r
-\r
-temp1 = initial x position (is set but never used)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_sneakplatsit = {PLATFORMSPR, PLATFORMSPR, think, false, false, 0, 0, 0, T_SneakPlat, NULL, R_Draw, NULL};\r
-statetype s_sneakplatdodge = {PLATFORMSPR, PLATFORMSPR, slide, false, false, 48, 32, 0, NULL, NULL, R_Draw, &s_sneakplatreturn};\r
-statetype s_sneakplatreturn = {PLATFORMSPR, PLATFORMSPR, slide, false, false, 96, -16, 0, NULL, NULL, R_Draw, &s_sneakplatsit};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnSneakPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnSneakPlat(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = platformobj;\r
- new->active = ac_allways;\r
- new->priority = 0;\r
- new->x=new->temp1 = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->xdir = 0;\r
- new->ydir = 1;\r
- new->needtoclip = cl_noclip;\r
- NewState(new, &s_sneakplatsit);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_SneakPlat\r
-=\r
-===========================\r
-*/\r
-\r
-void T_SneakPlat(objtype *ob)\r
-{\r
- Sint16 dist;\r
-\r
- if (player->state != &s_keenjump1)\r
- return;\r
-\r
- if (player->xdir == 1)\r
- {\r
- dist = ob->left-player->right;\r
- if (dist > 4*TILEGLOBAL || dist < 0)\r
- return;\r
- }\r
- else\r
- {\r
- dist = player->left-ob->right;\r
- if (dist > 4*TILEGLOBAL || dist < 0)\r
- return;\r
- }\r
-\r
- dist = player->y - ob->y;\r
- if (dist < -6*TILEGLOBAL || dist > 6*TILEGLOBAL)\r
- return;\r
-\r
- ob->xdir = player->xdir;\r
- ob->state = &s_sneakplatdodge;\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BLOOG\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bloogwalk1 = {BLOOGWALKL1SPR, BLOOGWALKR1SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk2};\r
-statetype s_bloogwalk2 = {BLOOGWALKL2SPR, BLOOGWALKR2SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk3};\r
-statetype s_bloogwalk3 = {BLOOGWALKL3SPR, BLOOGWALKR3SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk4};\r
-statetype s_bloogwalk4 = {BLOOGWALKL4SPR, BLOOGWALKR4SPR, step, false, true, 10, 128, 0, T_BloogWalk, C_Bloog, R_Walk, &s_bloogwalk1};\r
-statetype s_bloogstun = {BLOOGSTUNSPR, BLOOGSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_bloogstun};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBloog\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBloog(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = bloogobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_bloogwalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BloogWalk\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BloogWalk(objtype *ob)\r
-{\r
- if (US_RndT() < 0x20)\r
- {\r
- if (ob->x < player->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Bloog\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Bloog(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_bloogstun);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BLOOGUARD\r
-\r
-temp1 = flash countdown\r
-temp2 = health\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_blooguardwalk1 = {BLOOGUARDWALKL1SPR, BLOOGUARDWALKR1SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk2};\r
-statetype s_blooguardwalk2 = {BLOOGUARDWALKL2SPR, BLOOGUARDWALKR2SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk3};\r
-statetype s_blooguardwalk3 = {BLOOGUARDWALKL3SPR, BLOOGUARDWALKR3SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk4};\r
-statetype s_blooguardwalk4 = {BLOOGUARDWALKL4SPR, BLOOGUARDWALKR4SPR, step, false, true, 9, 128, 0, T_BlooguardWalk, C_Blooguard, R_Blooguard, &s_blooguardwalk1};\r
-statetype s_blooguardattack1 = {BLOOGUARDSWINGL1SPR, BLOOGUARDSWINGR1SPR, step, false, true, 30, 0, 0, NULL, C_Blooguard, R_Blooguard, &s_blooguardattack2};\r
-statetype s_blooguardattack2 = {BLOOGUARDSWINGL2SPR, BLOOGUARDSWINGR2SPR, step, false, true, 9, 0, 0, NULL, C_Blooguard, R_Blooguard, &s_blooguardattack3};\r
-statetype s_blooguardattack3 = {BLOOGUARDSWINGL3SPR, BLOOGUARDSWINGR3SPR, step, true, true, 1, 0, 0, T_BlooguardAttack, C_Blooguard, R_Blooguard, &s_blooguardattack4};\r
-statetype s_blooguardattack4 = {BLOOGUARDSWINGL3SPR, BLOOGUARDSWINGR3SPR, step, false, true, 9, 0, 0, NULL, C_Blooguard, R_Blooguard, &s_blooguardwalk1};\r
-statetype s_blooguardstun = {BLOOGUARDSTUNSPR, BLOOGUARDSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_blooguardstun};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBlooguard\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBlooguard(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = blooguardobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -40*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- new->temp2 = 3; // health\r
- NewState(new, &s_blooguardwalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BlooguardWalk\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BlooguardWalk(objtype *ob)\r
-{\r
- if (US_RndT() < 0x20)\r
- {\r
- if (ob->x < player->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- }\r
- if ( ((ob->xdir == 1 && ob->x < player->x) || (ob->xdir == -1 && ob->x > player->x))\r
- && ob->bottom == player->bottom && US_RndT() < 0x20)\r
- {\r
- ob->state = &s_blooguardattack1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BlooguardAttack\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void T_BlooguardAttack(objtype *ob)\r
-{\r
- SD_PlaySound(SND_SMASH);\r
- groundslam = 23;\r
- if (player->hitnorth)\r
- {\r
- ChangeState(player, &s_keenstun);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Blooguard\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Blooguard(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- if (hit->obclass == stunshotobj) // not 'else if' in the original code\r
- {\r
- if (--ob->temp2 == 0) // handle health\r
- {\r
- StunObj(ob, hit, &s_blooguardstun);\r
- }\r
- else\r
- {\r
- ob->temp1 = 2; // draw white twice\r
- ob->needtoreact = true;\r
- ExplodeShot(hit);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Blooguard\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Blooguard(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove*2;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- if (ob->temp1)\r
- {\r
- ob->temp1--;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, maskdraw, ob->priority);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BLOOGLET\r
-\r
-temp1 = type\r
-\r
-=============================================================================\r
-*/\r
-\r
-// red Blooglet:\r
-statetype s_rbloogletwalk1 = {RBLOOGLETWALKL1SPR, RBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk2};\r
-statetype s_rbloogletwalk2 = {RBLOOGLETWALKL2SPR, RBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk3};\r
-statetype s_rbloogletwalk3 = {RBLOOGLETWALKL3SPR, RBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk4};\r
-statetype s_rbloogletwalk4 = {RBLOOGLETWALKL4SPR, RBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_rbloogletwalk1};\r
-statetype s_rbloogletstun = {RBLOOGLETSTUNSPR, RBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-// yellow Blooglet:\r
-statetype s_ybloogletwalk1 = {YBLOOGLETWALKL1SPR, YBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk2};\r
-statetype s_ybloogletwalk2 = {YBLOOGLETWALKL2SPR, YBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk3};\r
-statetype s_ybloogletwalk3 = {YBLOOGLETWALKL3SPR, YBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk4};\r
-statetype s_ybloogletwalk4 = {YBLOOGLETWALKL4SPR, YBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_ybloogletwalk1};\r
-statetype s_ybloogletstun = {YBLOOGLETSTUNSPR, YBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-// blue Blooglet:\r
-statetype s_bbloogletwalk1 = {BBLOOGLETWALKL1SPR, BBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk2};\r
-statetype s_bbloogletwalk2 = {BBLOOGLETWALKL2SPR, BBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk3};\r
-statetype s_bbloogletwalk3 = {BBLOOGLETWALKL3SPR, BBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk4};\r
-statetype s_bbloogletwalk4 = {BBLOOGLETWALKL4SPR, BBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_bbloogletwalk1};\r
-statetype s_bbloogletstun = {BBLOOGLETSTUNSPR, BBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-// green Blooglet:\r
-statetype s_gbloogletwalk1 = {GBLOOGLETWALKL1SPR, GBLOOGLETWALKR1SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk2};\r
-statetype s_gbloogletwalk2 = {GBLOOGLETWALKL2SPR, GBLOOGLETWALKR2SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk3};\r
-statetype s_gbloogletwalk3 = {GBLOOGLETWALKL3SPR, GBLOOGLETWALKR3SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk4};\r
-statetype s_gbloogletwalk4 = {GBLOOGLETWALKL4SPR, GBLOOGLETWALKR4SPR, step, false, true, 5, 128, 0, T_BloogWalk, C_Blooglet, R_Walk, &s_gbloogletwalk1};\r
-statetype s_gbloogletstun = {GBLOOGLETSTUNSPR, GBLOOGLETSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBlooglet\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBlooglet(Uint16 tileX, Uint16 tileY, Sint16 type)\r
-{\r
- GetNewObj(false);\r
- new->obclass = bloogletobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- new->temp1 = type;\r
-\r
- switch (type % 4)\r
- {\r
- case 0:\r
- NewState(new, &s_rbloogletwalk1);\r
- break;\r
-\r
- case 1:\r
- NewState(new, &s_ybloogletwalk1);\r
- break;\r
-\r
- case 2:\r
- NewState(new, &s_bbloogletwalk1);\r
- break;\r
-\r
- case 3:\r
- NewState(new, &s_gbloogletwalk1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Blooglet\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Blooglet(objtype *ob, objtype *hit)\r
-{\r
- static statetype *stunnedstate[4] = {\r
- &s_rbloogletstun,\r
- &s_ybloogletstun,\r
- &s_bbloogletstun,\r
- &s_gbloogletstun\r
- };\r
- Sint16 color;\r
-\r
- if (hit->obclass == keenobj && hit->state->contact)\r
- {\r
- playerkludgeclipcancel = true;\r
- ClipToSpriteSide(hit, ob);\r
- playerkludgeclipcancel = false;\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- color = ob->temp1 & 3;\r
- if (ob->temp1 > 3)\r
- {\r
- //\r
- // spawn a key gem\r
- //\r
- GetNewObj(false);\r
- new->needtoclip = cl_midclip;\r
- new->priority = 2;\r
- new->obclass = bonusobj;\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- new->ydir = -1;\r
- new->yspeed = -40;\r
- new->temp1 = color;\r
- new->temp2=new->shapenum = bonusshape[color];\r
- new->temp3 = new->temp2 + 2;\r
- NewState(new, &s_bonusfly1);\r
- SD_PlaySound(SND_DROPKEY);\r
- }\r
- StunObj(ob, hit, stunnedstate[color]);\r
- }\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K6_ACT2.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Nospike\r
-- Gik\r
-- Turrets\r
-- Orbatrix\r
-- Bip & Bipship\r
-- Flect\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- NOSPIKE\r
-\r
-temp1 = step counter for running on thin air\r
-temp2 = low byte: running flag; high byte: flash countdown\r
-temp3 = sprite pointer for the question mark\r
-temp4 = health\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_nospikestand = {NOSPIKESTANDSPR, NOSPIKESTANDSPR, step, false, true, 90, 0, 0, NULL, C_Nospike, R_Walk, &s_nospikewalk1};\r
-statetype s_nospikewalk1 = {NOSPIKEWALKL1SPR, NOSPIKEWALKR1SPR, step, false, true, 10, 128, 0, T_NospikeWalk, C_Nospike, R_Walk, &s_nospikewalk2};\r
-statetype s_nospikewalk2 = {NOSPIKEWALKL2SPR, NOSPIKEWALKR2SPR, step, false, true, 10, 128, 0, T_NospikeWalk, C_Nospike, R_Walk, &s_nospikewalk3};\r
-statetype s_nospikewalk3 = {NOSPIKEWALKL3SPR, NOSPIKEWALKR3SPR, step, false, true, 10, 128, 0, T_NospikeWalk, C_Nospike, R_Walk, &s_nospikewalk4};\r
-statetype s_nospikewalk4 = {NOSPIKEWALKL4SPR, NOSPIKEWALKR4SPR, step, false, true, 10, 128, 0, T_NospikeWalk, C_Nospike, R_Walk, &s_nospikewalk1};\r
-statetype s_nospikerun1 = {NOSPIKERUNL1SPR, NOSPIKERUNR1SPR, step, false, true, 4, 128, 0, T_NospikeRun, C_Nospike, R_NospikeRun, &s_nospikerun2};\r
-statetype s_nospikerun2 = {NOSPIKERUNL2SPR, NOSPIKERUNR2SPR, step, false, true, 4, 128, 0, T_NospikeRun, C_Nospike, R_NospikeRun, &s_nospikerun3};\r
-statetype s_nospikerun3 = {NOSPIKERUNL3SPR, NOSPIKERUNR3SPR, step, false, true, 4, 128, 0, T_NospikeRun, C_Nospike, R_NospikeRun, &s_nospikerun4};\r
-statetype s_nospikerun4 = {NOSPIKERUNL4SPR, NOSPIKERUNR4SPR, step, false, true, 4, 128, 0, T_NospikeRun, C_Nospike, R_NospikeRun, &s_nospikerun1};\r
-statetype s_nospikeconfused1 = {NOSPIKESTANDSPR, NOSPIKESTANDSPR, step, false, false, 20, 0, 1, NULL, NULL, R_Draw, &s_nospikeconfused2};\r
-statetype s_nospikeconfused2 = {NOSPIKESTANDSPR, NOSPIKESTANDSPR, step, false, false, 90, 0, 0, T_NospikeConfused, NULL, R_NospikeConfused, &s_nospikeconfused3};\r
-statetype s_nospikeconfused3 = {NOSPIKESTANDSPR, NOSPIKESTANDSPR, step, false, false, 20, 0, 0, NULL, NULL, R_Draw, &s_nospikefall};\r
-statetype s_nospikefall = {NOSPIKESTANDSPR, NOSPIKESTANDSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_NospikeFall, NULL};\r
-statetype s_nospikestun = {NOSPIKESTUNSPR, NOSPIKESTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_nospikestun};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnNospike\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnNospike(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = nospikeobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -24*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_nospikestand);\r
- new->temp4 = 4; // health\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_NospikeWalk\r
-=\r
-===========================\r
-*/\r
-\r
-void T_NospikeWalk(objtype *ob)\r
-{\r
- if (US_RndT() < 0x10)\r
- {\r
- ob->state = &s_nospikestand;\r
- }\r
- else if (ob->bottom == player->bottom && US_RndT() <= 0x20)\r
- {\r
- //\r
- // start running towards player\r
- //\r
- if (player->x > ob->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- ob->temp1 = 0; // nospike is still on solid ground (should already be 0 anyway)\r
- ob->temp2 = 1; // nospike is running\r
- if (ob->state == &s_nospikewalk1)\r
- {\r
- ob->state = &s_nospikerun2;\r
- }\r
- else if (ob->state == &s_nospikewalk2)\r
- {\r
- ob->state = &s_nospikerun3;\r
- }\r
- else if (ob->state == &s_nospikewalk3)\r
- {\r
- ob->state = &s_nospikerun4;\r
- }\r
- else if (ob->state == &s_nospikewalk4)\r
- {\r
- ob->state = &s_nospikerun1;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_NospikeRun\r
-=\r
-===========================\r
-*/\r
-\r
-void T_NospikeRun(objtype *ob)\r
-{\r
- if (ob->temp1)\r
- return; // nospike is running on thin air, so we'd better not stop\r
-\r
- if ( ( ( player->bottom != ob->bottom // not on same ground level as Keen?\r
- || (ob->xdir == -1 && ob->x < player->x)\r
- || (ob->xdir == 1 && ob->x > player->x) ) // already ran past Keen?\r
- && US_RndT() < 8 )\r
- || !OnScreen(ob) ) // always stop running when off-screen\r
- {\r
- //\r
- // stop running\r
- //\r
- ob->temp2 = 0;\r
- if (ob->state == &s_nospikerun1)\r
- {\r
- ob->state = &s_nospikewalk2;\r
- }\r
- else if (ob->state == &s_nospikerun2)\r
- {\r
- ob->state = &s_nospikewalk3;\r
- }\r
- else if (ob->state == &s_nospikerun3)\r
- {\r
- ob->state = &s_nospikewalk4;\r
- }\r
- else if (ob->state == &s_nospikerun4)\r
- {\r
- ob->state = &s_nospikewalk1;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Nospike\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Nospike(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- if (--ob->temp4 == 0) // handle health\r
- {\r
- StunObj(ob, hit, &s_nospikestun);\r
- ob->yspeed = -24;\r
- }\r
- else\r
- {\r
- if (player->x > ob->x)\r
- {\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->xdir = -1;\r
- }\r
- ob->temp2 |= 0x400; // draw white 4 times\r
- ob->needtoreact = true;\r
- if (ob->state == &s_nospikestand || ob->state == &s_nospikewalk1)\r
- {\r
- ChangeState(ob, &s_nospikerun2);\r
- }\r
- else if (ob->state == &s_nospikewalk2)\r
- {\r
- ChangeState(ob, &s_nospikerun3);\r
- }\r
- else if (ob->state == &s_nospikewalk3)\r
- {\r
- ChangeState(ob, &s_nospikerun4);\r
- }\r
- else if (ob->state == &s_nospikewalk4)\r
- {\r
- ChangeState(ob, &s_nospikerun1);\r
- }\r
- ExplodeShot(hit);\r
- }\r
- }\r
- else if (hit->obclass == nospikeobj\r
- && (hit->temp2 & 0xFF) && (ob->temp2 & 0xFF) // both nospikes are running?\r
- && hit->xdir != ob->xdir) // running in opposite directions?\r
- {\r
- //\r
- // stun both nospikes\r
- //\r
- ob->temp1=ob->temp2=ob->temp3=hit->temp1=hit->temp2=hit->temp3 = 0;\r
- ob->temp4 = hit->temp4 = ob->obclass;\r
- ChangeState(ob, &s_nospikestun);\r
- ChangeState(hit, &s_nospikestun);\r
- SD_PlaySound(SND_SMASH);\r
- ob->obclass = hit->obclass = stunnedobj;\r
- ob->yspeed = hit->yspeed = -24;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_NospikeConfused\r
-=\r
-===========================\r
-*/\r
-\r
-void T_NospikeConfused(objtype* ob)\r
-{\r
- RF_RemoveSprite((void**)&ob->temp3);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_NospikeConfused\r
-=\r
-===========================\r
-*/\r
-\r
-void R_NospikeConfused(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- RF_PlaceSprite((void**)&ob->temp3, ob->x+TILEGLOBAL, ob->y-8*PIXGLOBAL, QUESTIONMARKSPR, spritedraw, 3);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_NospikeFall\r
-=\r
-===========================\r
-*/\r
-\r
-void R_NospikeFall(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- if (ob->hitnorth)\r
- {\r
- ob->temp1=ob->temp2=ob->temp3 = 0;\r
- ob->temp4 = ob->obclass;\r
- ChangeState(ob, &s_nospikestun);\r
- SD_PlaySound(SND_SMASH);\r
- ob->obclass = stunnedobj;\r
- ob->yspeed = -24;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_NospikeRun\r
-=\r
-===========================\r
-*/\r
-\r
-void R_NospikeRun(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- {\r
- ob->temp1 = 0; // on solid ground\r
- if (ob->hiteast || ob->hitwest)\r
- {\r
- ob->x -= ob->xdir << 7;\r
- NewState(ob, &s_nospikestand);\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- ob->temp2 = 0; // no longer running or flashing white\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- if (++ob->temp1 == 6) // not on solid ground for 6 steps?\r
- {\r
- ChangeState(ob, &s_nospikeconfused1);\r
-#if 0\r
- // bugfix:\r
- ob->nothink = 0; // to make sure T_NospikeConfused can remove the question mark sprite\r
-#endif\r
- }\r
- }\r
- if (ob->temp2 & 0xFF00)\r
- {\r
- ob->temp2 -= 0x100;\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, maskdraw, ob->priority);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GIK\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_gikwalk1 = {GIKWALKL1SPR, GIKWALKR1SPR, step, false, true, 10, 128, 0, T_GikWalk, C_ClipTop, R_Walk, &s_gikwalk2};\r
-statetype s_gikwalk2 = {GIKWALKL2SPR, GIKWALKR2SPR, step, false, true, 10, 128, 0, T_GikWalk, C_ClipTop, R_Walk, &s_gikwalk3};\r
-statetype s_gikwalk3 = {GIKWALKL3SPR, GIKWALKR3SPR, step, false, true, 10, 128, 0, T_GikWalk, C_ClipTop, R_Walk, &s_gikwalk1};\r
-statetype s_gikjump = {GIKJUMPLSPR, GIKJUMPRSPR, think, false, false, 0, 0, 0, T_Projectile, C_ClipSide, R_GikJump, &s_gikslide1};\r
-statetype s_gikslide1 = {GIKSLIDEL1SPR, GIKSLIDER1SPR, stepthink, false, false, 6, 0, 0, T_GikSlide, C_Lethal, R_GikSlide, &s_gikslide2};\r
-statetype s_gikslide2 = {GIKSLIDEL2SPR, GIKSLIDER2SPR, stepthink, false, false, 6, 0, 0, T_GikSlide, C_Lethal, R_GikSlide, &s_gikslide1};\r
-statetype s_gikstand = {GIKSLIDEL1SPR, GIKSLIDER1SPR, step, false, true, 20, 0, 0, NULL, C_Lethal, R_Walk, &s_gikwalk1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnGik\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnGik(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = gikobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY);\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_gikwalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_GikWalk\r
-=\r
-===========================\r
-*/\r
-\r
-void T_GikWalk(objtype *ob)\r
-{\r
- Sint16 xdist;\r
-\r
- if (ob->hitnorth != 9) // if NOT on flat ground that kills Keen\r
- {\r
- xdist = player->x - ob->x;\r
- if (player->bottom <= ob->bottom && ob->bottom - player->bottom <= 4*TILEGLOBAL)\r
- {\r
- if (xdist < 0)\r
- {\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->xdir = 1;\r
- }\r
- if (xdist >= -7*TILEGLOBAL && xdist <= 7*TILEGLOBAL\r
- && (xdist <= -TILEGLOBAL || xdist >= TILEGLOBAL) )\r
- {\r
- if (xdist < 0)\r
- {\r
- ob->xspeed = -40;\r
- }\r
- else\r
- {\r
- ob->xspeed = 40;\r
- }\r
- ob->yspeed = -28;\r
- ob->state = &s_gikjump;\r
- SD_PlaySound(SND_GIKJUMP);\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_GikSlide\r
-=\r
-===========================\r
-*/\r
-\r
-void T_GikSlide(objtype *ob)\r
-{\r
- // tic masks for friction, based on slope type and direction\r
- // 0 - no friction\r
- // 7 - lowest friction (speed decreases every 8 tics)\r
- // 3 - medium friction (speed decreases every 4 tics)\r
- // 1 - highest friction (speed decreases every 2 tics)\r
- static Sint16 rticmask[8] = {0, 7, 0, 0, 0, 3, 3, 1};\r
- static Sint16 lticmask[8] = {0, 7, 3, 3, 1, 0, 0, 0};\r
-\r
- Sint16 ticmask;\r
- Sint16 slope;\r
- Sint32 i;\r
-\r
- DoGravity(ob);\r
-\r
- slope = ob->hitnorth & 7;\r
- if (ob->xdir == 1)\r
- {\r
- ticmask = rticmask[slope];\r
- }\r
- else\r
- {\r
- ticmask = lticmask[slope];\r
- }\r
-\r
- if (ob->xspeed == 0 && ob->hitnorth)\r
- {\r
- ob->state = &s_gikstand;\r
- }\r
- else\r
- {\r
- for (i = lasttimecount-tics; i < lasttimecount; i++)\r
- {\r
- if (ticmask && !(i & ticmask))\r
- {\r
- if ((ob->xspeed < 0 && ++ob->xspeed == 0)\r
- || (ob-> xspeed > 0 && --ob->xspeed == 0))\r
- {\r
- ob->state = &s_gikstand;\r
- return;\r
- }\r
- }\r
- xtry += ob->xspeed;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_GikJump\r
-=\r
-===========================\r
-*/\r
-\r
-void R_GikJump(objtype *ob)\r
-{\r
- if (ob->hiteast || ob->hitwest)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->yspeed = 0;\r
- SD_PlaySound(SND_GIKLAND);\r
- ChangeState(ob, ob->state->nextstate);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_GikSlide\r
-=\r
-===========================\r
-*/\r
-\r
-void R_GikSlide(objtype *ob)\r
-{\r
- if ((ob->hiteast && ob->xspeed < 0) || (ob->hitwest && ob->xspeed > 0))\r
- ob->xspeed = 0;\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- CANNON\r
-\r
-temp1 = direction\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_cannon = {0, 0, step, false, false, 120, 0, 0, NULL, NULL, R_Draw, &s_cannonfire};\r
-statetype s_cannonfire = {0, 0, step, true, false, 1, 0, 0, T_Cannon, NULL, R_Draw, &s_cannon};\r
-statetype s_cshot1 = {LASER1SPR, LASER1SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot2};\r
-statetype s_cshot2 = {LASER2SPR, LASER2SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot3};\r
-statetype s_cshot3 = {LASER3SPR, LASER3SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot4};\r
-statetype s_cshot4 = {LASER4SPR, LASER4SPR, stepthink, false, false, 8, 0, 0, T_Velocity, C_CShot, R_CShot, &s_cshot1};\r
-statetype s_cshothit1 = {LASERHIT1SPR, LASERHIT1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_cshothit2};\r
-statetype s_cshothit2 = {LASERHIT2SPR, LASERHIT2SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnCannon\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnCannon(Uint16 tileX, Uint16 tileY, Sint16 dir)\r
-{\r
- GetNewObj(false);\r
- new->obclass = cannonobj;\r
- new->active = ac_yes;\r
- new->tileright = new->tileleft = tileX;\r
- new->tiletop = new->tilebottom = tileY;\r
- new->x = new->left = new->right = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = new->top = new->bottom = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->temp1 = dir;\r
- NewState(new, &s_cannon);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_Cannon\r
-=\r
-===========================\r
-*/\r
-\r
-void T_Cannon(objtype *ob)\r
-{\r
- GetNewObj(true);\r
- new->obclass = mshotobj;\r
- new->active = ac_yes; // BUG? NOT removable in Keen 6 (checked v1.0, v1.4 and v1.5)\r
- new->x = ob->x;\r
- new->y = ob->y;\r
- switch (ob->temp1)\r
- {\r
- case 0:\r
- new->yspeed = -64;\r
- break;\r
- case 1:\r
- new->xspeed = 64;\r
- break;\r
- case 2:\r
- new->yspeed = 64;\r
- break;\r
- case 3:\r
- new->xspeed = -64;\r
- }\r
- NewState(new, &s_cshot1);\r
- SD_PlaySound(SND_ENEMYSHOT);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_CShot\r
-=\r
-===========================\r
-*/\r
-\r
-void C_CShot(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- ChangeState(ob, &s_cshothit1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_CShot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_CShot(objtype *ob)\r
-{\r
- if (ob->hitnorth || ob->hiteast || ob->hitsouth || ob->hitwest)\r
- {\r
- SD_PlaySound(SND_ENEMYSHOTEXPLODE);\r
- ChangeState(ob, &s_cshothit1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- ORBATRIX\r
-\r
-temp1 = bounce counter\r
-temp2 = amount to move up during uncurl animation\r
-temp3 = float offset\r
-temp4 = float direction (up or down)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_orbatrix1 = {ORBATRIXL1SPR, ORBATRIXR1SPR, slide, false, true, 12, 16, 0, T_OrbatrixFly, C_Orbatrix, R_Orbatrix, &s_orbatrix2};\r
-statetype s_orbatrix2 = {ORBATRIXL2SPR, ORBATRIXR2SPR, slide, false, true, 12, 16, 0, T_OrbatrixFly, C_Orbatrix, R_Orbatrix, &s_orbatrix1};\r
-statetype s_orbatrixcurl1 = {ORBATRIX1SPR, ORBATRIX1SPR, stepthink, false, true, 12, 0, 0, NULL, C_Orbatrix, R_Orbatrix, &s_orbatrixcurl2};\r
-statetype s_orbatrixcurl2 = {ORBATRIXCURLSPR, ORBATRIXCURLSPR, stepthink, false, true, 12, 0, 0, NULL, C_Orbatrix, R_Orbatrix, &s_orbatrixcurl3};\r
-statetype s_orbatrixcurl3 = {ORBATRIXCURLSPR, ORBATRIXCURLSPR, think, false, true, 12, 0, 0, T_OrbatrixCurl, C_Orbatrix, R_Orbatrix, &s_orbatrixbounce1};\r
-statetype s_orbatrixuncurl1 = {ORBATRIXSPIN1SPR, ORBATRIXSPIN1SPR, think, false, false, 12, 0, 0, T_OrbatrixUncurl, C_OrbatrixBounce, R_Draw, &s_orbatrixuncurl2};\r
-statetype s_orbatrixuncurl2 = {ORBATRIXCURLSPR, ORBATRIXCURLSPR, step, false, false, 12, 0, 0, NULL, C_OrbatrixBounce, R_Draw, &s_orbatrixidle1};\r
-statetype s_orbatrixidle1 = {ORBATRIX1SPR, ORBATRIX1SPR, stepthink, false, true, 12, 0, 0, NULL, C_Orbatrix, R_Orbatrix, &s_orbatrixidle2};\r
-statetype s_orbatrixidle2 = {ORBATRIX2SPR, ORBATRIX2SPR, stepthink, false, true, 12, 0, 0, NULL, C_Orbatrix, R_Orbatrix, &s_orbatrixidle3};\r
-statetype s_orbatrixidle3 = {ORBATRIX3SPR, ORBATRIX3SPR, stepthink, false, true, 12, 0, 0, NULL, C_Orbatrix, R_Orbatrix, &s_orbatrixidle4};\r
-statetype s_orbatrixidle4 = {ORBATRIX4SPR, ORBATRIX4SPR, stepthink, false, true, 12, 0, 0, NULL, C_Orbatrix, R_Orbatrix, &s_orbatrix1};\r
-statetype s_orbatrixbounce1 = {ORBATRIXSPIN4SPR, ORBATRIXSPIN1SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_OrbatrixBounce, R_OrbatrixBounce, &s_orbatrixbounce2};\r
-statetype s_orbatrixbounce2 = {ORBATRIXSPIN3SPR, ORBATRIXSPIN2SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_OrbatrixBounce, R_OrbatrixBounce, &s_orbatrixbounce3};\r
-statetype s_orbatrixbounce3 = {ORBATRIXSPIN2SPR, ORBATRIXSPIN3SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_OrbatrixBounce, R_OrbatrixBounce, &s_orbatrixbounce4};\r
-statetype s_orbatrixbounce4 = {ORBATRIXSPIN1SPR, ORBATRIXSPIN4SPR, stepthink, false, false, 6, 0, 0, T_Projectile, C_OrbatrixBounce, R_OrbatrixBounce, &s_orbatrixbounce1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnOrbatrix\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnOrbatrix(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = orbatrixobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -24*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- new->temp4 = 1;\r
- NewState(new, &s_orbatrix1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_OrbatrixFly\r
-=\r
-===========================\r
-*/\r
-\r
-void T_OrbatrixFly(objtype *ob)\r
-{\r
- Sint16 dist;\r
-\r
- if (US_RndT() < 0x20)\r
- {\r
- ob->state = &s_orbatrixidle1;\r
- return;\r
- }\r
-\r
- if (ob->bottom != player->bottom)\r
- {\r
- return;\r
- }\r
-\r
- dist = player->x - ob->x;\r
- ob->xdir = (dist < 0)? -1 : 1;\r
- if (dist > -5*TILEGLOBAL && dist < 5*TILEGLOBAL)\r
- {\r
- ob->state = &s_orbatrixcurl1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Orbatrix\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Orbatrix(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_orbatrixidle1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Orbatrix\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Orbatrix(objtype *ob)\r
-{\r
- //\r
- // ugly hack: apply float offset before drawing the sprite\r
- // (it's ugly because the sprite moves up/down, but the hitbox doesn't)\r
- //\r
- ob->y -= ob->temp3;\r
- R_Walk(ob);\r
- ob->y += ob->temp3;\r
-\r
- //\r
- // update the float offset\r
- //\r
- ob->temp3 = ob->temp3 + ob->temp4 * tics * 4;\r
- if (ob->temp3 > 8*PIXGLOBAL)\r
- {\r
- ob->temp3 = 8*PIXGLOBAL;\r
- ob->temp4 = -1;\r
- }\r
- else if (ob->temp3 < -8*PIXGLOBAL)\r
- {\r
- ob->temp3 = -8*PIXGLOBAL;\r
- ob->temp4 = 1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_OrbatrixBounce\r
-=\r
-===========================\r
-*/\r
-\r
-void R_OrbatrixBounce(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->yspeed = -ob->yspeed;\r
- }\r
- if (ob->hitnorth || ob->hitwest || ob->hiteast)\r
- {\r
- ob->xspeed = -ob->xspeed;\r
- SD_PlaySound(SND_ORBATRIXBOUNCE);\r
- if (ob->hitnorth && --ob->temp1 == 0)\r
- {\r
- ChangeState(ob, &s_orbatrixuncurl1);\r
- ob->temp2 = 24*PIXGLOBAL;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_OrbatrixCurl\r
-=\r
-===========================\r
-*/\r
-\r
-void T_OrbatrixCurl(objtype *ob)\r
-{\r
- if (ob->temp3 >= 16)\r
- {\r
- ob->xspeed = ob->xdir * 60;\r
- ob->yspeed = -32;\r
- ob->y -= ob->temp3;\r
- ob->temp1 = 5; // bounce 5 times\r
- ob->state = ob->state->nextstate;\r
- }\r
- ob->needtoreact = true;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_OrbatrixUncurl\r
-=\r
-===========================\r
-*/\r
-\r
-void T_OrbatrixUncurl(objtype *ob)\r
-{\r
- ob->temp2 += (ytry = tics * -8);\r
- if (ob->temp2 <= 0)\r
- {\r
- ytry -= ob->temp2;\r
- ob->state = ob->state->nextstate;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_OrbatrixBounce\r
-=\r
-===========================\r
-*/\r
-\r
-void C_OrbatrixBounce(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- ob->xspeed = 0;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BIP\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bipstand = {BIPSTANDSPR, BIPSTANDSPR, step, false, true, 30, 0, 0, NULL, C_Bip, R_Walk, &s_bipwalk1};\r
-statetype s_bipwalk1 = {BIPWALKL1SPR, BIPWALKR1SPR, step, true, true, 4, 32, 0, T_BipWalk, C_Bip, R_Walk, &s_bipwalk2};\r
-statetype s_bipwalk2 = {BIPWALKL2SPR, BIPWALKR2SPR, step, true, true, 4, 32, 0, T_BipWalk, C_Bip, R_Walk, &s_bipwalk3};\r
-statetype s_bipwalk3 = {BIPWALKL3SPR, BIPWALKR3SPR, step, true, true, 4, 32, 0, T_BipWalk, C_Bip, R_Walk, &s_bipwalk4};\r
-statetype s_bipwalk4 = {BIPWALKL4SPR, BIPWALKR4SPR, step, true, true, 4, 32, 0, T_BipWalk, C_Bip, R_Walk, &s_bipwalk1};\r
-statetype s_bipsquished = {BIPSQUISHEDSPR, BIPSQUISHEDSPR, think, false, true, 0, 0, 0, T_Projectile, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BipWalk\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BipWalk(objtype *ob)\r
-{\r
- if (ob->bottom == player->bottom)\r
- {\r
- if (ob->right < player->left - 4*PIXGLOBAL)\r
- ob->xdir = 1;\r
-\r
- if (ob->left > player->right + 4*PIXGLOBAL)\r
- ob->xdir = -1;\r
- }\r
- else if (US_RndT() < 0x10)\r
- {\r
- ob->xdir = -ob->xdir;\r
- ob->state = &s_bipstand;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Bip\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Bip(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj && hit->ymove > 0)\r
- {\r
- SD_PlaySound(SND_BIPSQUISH);\r
- ob->obclass = inertobj;\r
- ChangeState(ob, &s_bipsquished);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BIPSHIP\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bipship = {BIPSHIPLSPR, BIPSHIPRSPR, think, false, true, 0, 0, 0, T_BipshipFly, C_Bipship, R_Draw, &s_bipship};\r
-statetype s_bipshipshot = {BIPSHIPSHOTSPR, BIPSHIPSHOTSPR, think, false, false, 0, 0, 0, T_Velocity, C_Lethal, R_BipShot, NULL};\r
-statetype s_bipshipturn1 = {BIPSHIPRTURN1SPR, BIPSHIPLTURN1SPR, stepthink, false, true, 10, 0, 0, T_BipshipTurn, C_Bipship, R_Draw, &s_bipshipturn2};\r
-statetype s_bipshipturn2 = {BIPSHIPRTURN2SPR, BIPSHIPLTURN2SPR, stepthink, false, true, 10, 0, 0, T_BipshipTurn, C_Bipship, R_Draw, &s_bipshipturn3};\r
-statetype s_bipshipturn3 = {BIPSHIPRTURN3SPR, BIPSHIPLTURN3SPR, stepthink, false, true, 10, 0, 0, T_BipshipTurn, C_Bipship, R_Draw, &s_bipshipturn4};\r
-statetype s_bipshipturn4 = {BIPSHIPRTURN4SPR, BIPSHIPLTURN4SPR, stepthink, false, true, 10, 0, 0, T_BipshipTurn, C_Bipship, R_Draw, &s_bipship};\r
-statetype s_bipshipexplode1 = {BIPSHIPEXPLODE2SPR, BIPSHIPEXPLODE1SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Land, &s_bipshipexplode2};\r
-statetype s_bipshipexplode2 = {BIPSHIPEXPLODE2SPR, BIPSHIPEXPLODE1SPR, step, true, false, 1, 0, 0, T_BipshipExplode, NULL, R_Land, &s_bipshipexplode3};\r
-statetype s_bipshipexplode3 = {BIPSHIPEXPLODE5SPR, BIPSHIPEXPLODE5SPR, step, true, false, 30000, 0, 0, NULL, NULL, R_Land, &s_bipshipexplode3};\r
-statetype s_bipshipsmoke1 = {BIPSHIPEXPLODE3SPR, BIPSHIPEXPLODE3SPR, step, true, false, 10, 0, 0, NULL, NULL, R_Draw, &s_bipshipsmoke2};\r
-statetype s_bipshipsmoke2 = {BIPSHIPEXPLODE4SPR, BIPSHIPEXPLODE4SPR, step, true, false, 10, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBipship\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBipship(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = bipshipobj;\r
- new->active = ac_yes;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY)+ -24*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->xspeed = new->xdir * 20;\r
- NewState(new, &s_bipship);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_BipShot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_BipShot(objtype *ob)\r
-{\r
- if (ob->hitnorth || ob->hitsouth || ob->hiteast || ob->hitwest)\r
- {\r
- RemoveObj(ob);\r
- }\r
- else\r
- {\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BipshipTurn\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BipshipTurn(objtype *ob)\r
-{\r
- AccelerateX(ob, ob->xdir, 20);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BipshipFly\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BipshipFly(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Sint16 dir;\r
- Uint16 tile, tx, ty;\r
-\r
- AccelerateX(ob, ob->xdir, 20);\r
- dir = ob->xdir;\r
- if (player->bottom + TILEGLOBAL - ob->bottom <= 2*TILEGLOBAL)\r
- {\r
- if (player->x < ob->x)\r
- {\r
- dir = -1;\r
- }\r
- else\r
- {\r
- dir = 1;\r
- }\r
- if (ob->xdir == dir && US_RndT() < tics*4)\r
- {\r
- SD_PlaySound(SND_KEENFIRE);\r
- GetNewObj(true);\r
- new->obclass = mshotobj;\r
- new->active = ac_removable;\r
- new->priority = 1;\r
- if (ob->xdir == 1)\r
- {\r
- new->x = ob->x + TILEGLOBAL;\r
- new->xspeed = 64;\r
- }\r
- else\r
- {\r
- new->x = ob->x;\r
- new->xspeed = -64;\r
- }\r
- new->y = ob->y + 10*PIXGLOBAL;\r
- new->yspeed = 16;\r
- NewState(new, &s_bipshipshot);\r
- }\r
- }\r
-\r
- tx = ob->tilemidx + dir*4;\r
- map = mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + tx;\r
-\r
- for (ty = ob->tiletop; ty <= ob->tilebottom; ty++, map += mapwidth)\r
- {\r
- tile = *map;\r
- if (tinf[tile+EASTWALL] || tinf[tile+WESTWALL])\r
- {\r
- dir = -dir;\r
- goto check_turn;\r
- }\r
- }\r
- tile = *map;\r
- if (!tinf[tile+NORTHWALL])\r
- {\r
- dir = -dir;\r
- }\r
-check_turn:\r
- if (dir != ob->xdir)\r
- {\r
- ob->xdir = dir;\r
- ChangeState(ob, &s_bipshipturn1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BipshipExplode\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BipshipExplode(objtype *ob)\r
-{\r
- SD_PlaySound(SND_BIPSHIPEXPLODE);\r
-\r
- GetNewObj(true);\r
- new->obclass = inertobj;\r
- new->active = ac_yes;\r
- new->priority = 2;\r
- new->x = ob->x;\r
- new->y = ob->y - 24*PIXGLOBAL;\r
- NewState(new, &s_bipshipsmoke1);\r
-\r
- GetNewObj(true);\r
- new->obclass = bipobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = ob->x;\r
- new->y = ob->y - 8*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- NewState(new, &s_bipstand);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Bipship\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Bipship(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- ChangeState(ob, &s_bipshipexplode1);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- FLECT\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_flectstand = {FLECTSTANDLSPR, FLECTSTANDRSPR, think, false, true, 60, 0, 0, T_FlectStand, C_Flect, R_Flect, &s_flectwalk1};\r
-statetype s_flectturn = {FLECTSTANDSPR, FLECTSTANDSPR, step, false, true, 8, 0, 0, NULL, C_Flect, R_Flect, &s_flectwalk1};\r
-statetype s_flectwalk1 = {FLECTWALKL1SPR, FLECTWALKR1SPR, step, false, true, 10, 128, 0, T_FlectWalk, C_Flect, R_Flect, &s_flectwalk2};\r
-statetype s_flectwalk2 = {FLECTWALKL2SPR, FLECTWALKR2SPR, step, false, true, 10, 128, 0, T_FlectWalk, C_Flect, R_Flect, &s_flectwalk3};\r
-statetype s_flectwalk3 = {FLECTWALKL3SPR, FLECTWALKR3SPR, step, false, true, 10, 128, 0, T_FlectWalk, C_Flect, R_Flect, &s_flectwalk4};\r
-statetype s_flectwalk4 = {FLECTWALKL4SPR, FLECTWALKR4SPR, step, false, true, 10, 128, 0, T_FlectWalk, C_Flect, R_Flect, &s_flectwalk1};\r
-statetype s_flectstun = {FLECTSTUNSPR, FLECTSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_flectstun};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnFlect\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnFlect(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = flectobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -1*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_flectwalk1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_FlectStand\r
-=\r
-===========================\r
-*/\r
-\r
-void T_FlectStand(objtype *ob)\r
-{\r
- if (player->x < ob->x)\r
- {\r
- if (ob->xdir != -1)\r
- {\r
- ob->state = &s_flectturn;\r
- ob->xdir = -1;\r
- }\r
- else\r
- {\r
- ob->state = &s_flectwalk1;\r
- }\r
- }\r
- else\r
- {\r
- if (ob->xdir != 1)\r
- {\r
- ob->state = &s_flectturn;\r
- ob->xdir = 1;\r
- }\r
- else\r
- {\r
- ob->state = &s_flectwalk1;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_FlectWalk\r
-=\r
-===========================\r
-*/\r
-\r
-void T_FlectWalk(objtype *ob)\r
-{\r
- if (player->x < ob->x && ob->xdir == 1)\r
- {\r
- if (ob->xdir != -1) // always true here!\r
- {\r
- ob->state = &s_flectturn;\r
- }\r
- ob->xdir = -1;\r
- }\r
-\r
- if (player->x > ob->x && ob->xdir == -1)\r
- {\r
- if (ob->xdir != 1) // always true here!\r
- {\r
- ob->state = &s_flectturn;\r
- }\r
- ob->xdir = 1;\r
- }\r
-\r
- if (US_RndT() < 0x20)\r
- {\r
- ob->state = &s_flectstand;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Flect\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Flect(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- ClipToSpriteSide(hit, ob);\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- if (hit->xdir == 0)\r
- {\r
- StunObj(ob, hit, &s_flectstun);\r
- }\r
- else if (hit->xdir != ob->xdir)\r
- {\r
- // reflect shot:\r
- hit->xdir = ob->xdir;\r
- hit->temp4 = true; // shot can now stun Keen\r
- SD_PlaySound(SND_SHOTBOUNCE);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Flect\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Flect(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -ob->xdir;\r
- ChangeState(ob, ob->state);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K6_ACT3.C\r
-=========\r
-\r
-Contains the following actor types (in this order):\r
-\r
-- Fleex\r
-- Bobba\r
-- Babobba\r
-- Blorb\r
-- Ceilick\r
-\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- FLEEX\r
-\r
-temp1 = flash countdown\r
-temp2 = health\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_fleexwalk1 = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step, false, true, 7, 128, 0, T_FleexWalk, C_Fleex, R_Blooguard, &s_fleexwalk2};\r
-statetype s_fleexwalk2 = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step, false, true, 7, 128, 0, T_FleexWalk, C_Fleex, R_Blooguard, &s_fleexwalk1};\r
-statetype s_fleexrun1 = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step, false, true, 7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun2};\r
-statetype s_fleexrun2 = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step, false, true, 7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun3};\r
-statetype s_fleexrun3 = {FLEEXWALKL1SPR, FLEEXWALKR1SPR, step, false, true, 7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexrun4};\r
-statetype s_fleexrun4 = {FLEEXWALKL2SPR, FLEEXWALKR2SPR, step, false, true, 7, 128, 0, NULL, C_Fleex, R_Blooguard, &s_fleexwalk1};\r
-statetype s_fleexlook1 = {FLEEXLOOK1SPR, FLEEXLOOK1SPR, step, false, true, 60, 0, 0, NULL, C_Fleex, R_Blooguard, &s_fleexlook2};\r
-statetype s_fleexlook2 = {FLEEXLOOK2SPR, FLEEXLOOK2SPR, step, false, true, 60, 0, 0, T_FleexLook, C_Fleex, R_Blooguard, &s_fleexrun1};\r
-statetype s_fleexstun = {FLEEXSTUNSPR, FLEEXSTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnFleex\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnFleex(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = fleexobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -40*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_fleexwalk1);\r
- new->temp2 = 4; // health\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_FleexWalk\r
-=\r
-===========================\r
-*/\r
-\r
-void T_FleexWalk(objtype *ob)\r
-{\r
- if (!player->xmove && !ob->temp1)\r
- {\r
- ob->state = &s_fleexlook1;\r
- }\r
- else\r
- {\r
- ob->xdir = (ob->x < player->x)? 1 : -1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_FleexLook\r
-=\r
-===========================\r
-*/\r
-\r
-void T_FleexLook(objtype *ob)\r
-{\r
- ob->xdir = (ob->x < player->x)? 1 : -1;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Fleex\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Fleex(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- if (hit->obclass == stunshotobj) // this is not 'else if' in the original code\r
- {\r
- if (--ob->temp2 == 0)\r
- {\r
- StunObj(ob, hit, &s_fleexstun);\r
- ob->yspeed = -20;\r
- }\r
- else\r
- {\r
- ob->temp1 = 2; // draw white twice\r
- ob->needtoreact = true;\r
- ExplodeShot(hit);\r
- if (ob->state == &s_fleexlook1 || ob->state == &s_fleexlook2)\r
- {\r
- ob->xdir = (ob->x < player->x)? 1 : -1;\r
- ChangeState(ob, &s_fleexwalk1);\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BOBBA\r
-\r
-temp1 = jump counter\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_bobbajump1 = {BOBBAL2SPR, BOBBAR2SPR, stepthink, false, false, 8, 0, 0, T_Projectile, C_Bobba, R_Bobba, &s_bobbajump2};\r
-statetype s_bobbajump2 = {BOBBAL3SPR, BOBBAR3SPR, think, false, false, 8, 0, 0, T_Projectile, C_Bobba, R_Bobba, &s_bobbajump2};\r
-statetype s_bobbastand = {BOBBAL1SPR, BOBBAR1SPR, step, false, false, 20, 0, 0, T_BobbaStand, C_Bobba, R_Draw, &s_bobbajump1};\r
-statetype s_bobbaattack = {BOBBAL1SPR, BOBBAR1SPR, step, false, false, 40, 0, 0, NULL, C_Bobba, R_Draw, &s_bobbajump1};\r
-statetype s_bobbashot1 = {BOBBASHOT1SPR, BOBBASHOT1SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_bobbashot2};\r
-statetype s_bobbashot2 = {BOBBASHOT2SPR, BOBBASHOT2SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_bobbashot3};\r
-statetype s_bobbashot3 = {BOBBASHOT1SPR, BOBBASHOT1SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_bobbashot4};\r
-statetype s_bobbashot4 = {BOBBASHOT2SPR, BOBBASHOT2SPR, step, false, false, 8, 0, 0, T_BobbaShot, NULL, R_Draw, &s_bobbashot5};\r
-statetype s_bobbashot5 = {BOBBASHOT3SPR, BOBBASHOT3SPR, slide, false, false, 8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot6};\r
-statetype s_bobbashot6 = {BOBBASHOT4SPR, BOBBASHOT4SPR, slide, false, false, 8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot7};\r
-statetype s_bobbashot7 = {BOBBASHOT5SPR, BOBBASHOT5SPR, slide, false, false, 8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot8};\r
-statetype s_bobbashot8 = {BOBBASHOT6SPR, BOBBASHOT6SPR, slide, false, false, 8, 48, 0, NULL, C_Lethal, R_BobbaShot, &s_bobbashot5};\r
-statetype s_bobbashotvanish1 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_bobbashotvanish2};\r
-statetype s_bobbashotvanish2 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_bobbashotvanish3};\r
-statetype s_bobbashotvanish3 = {BOBBASHOT6SPR, BOBBASHOT6SPR, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBobba\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBobba(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = bobbaobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_bobbajump1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BobbaShot\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void T_BobbaShot(objtype *ob)\r
-{\r
- SD_PlaySound(SND_BOBBASHOT);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BobbaStand\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BobbaStand(objtype *ob)\r
-{\r
- Sint16 i;\r
- Uint16 far *map;\r
-\r
- if (++ob->temp1 == 3)\r
- {\r
- ob->temp1 = 0;\r
- GetNewObj(true);\r
- new->active = ac_removable;\r
- new->obclass = mshotobj;\r
- new->y = ob->y + 11*PIXGLOBAL;\r
- new->xdir = ob->xdir;\r
- if (ob->xdir == 1)\r
- {\r
- new->x = ob->x + 16*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- new->x = ob->x + 11*PIXGLOBAL;\r
- }\r
- NewState(new, &s_bobbashot1);\r
- new->priority = 2;\r
- ob->state = &s_bobbaattack;\r
- }\r
- else\r
- {\r
- map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2 + ob->tilemidx;\r
- for (i=0; i<4; map += ob->xdir, i++)\r
- {\r
- if ( !tinf[*map+NORTHWALL]\r
- && !tinf[*(map-mapwidth)+NORTHWALL]\r
- && !tinf[*(map+mapwidth)+NORTHWALL] )\r
- {\r
- ob->xdir = -ob->xdir;\r
- break;\r
- }\r
- }\r
- ob->xspeed = ob->xdir << 5;\r
- ob->yspeed = -32;\r
- SD_PlaySound(SND_BOBBAJUMP);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Bobba\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Bobba(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- ExplodeShot(hit);\r
- if (hit->xdir != 0)\r
- {\r
- ob->xdir = -hit->xdir;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Bobba\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Bobba(objtype *ob)\r
-{\r
- if (ob->hiteast)\r
- {\r
- ob->xdir = 1;\r
- ob->xspeed = -ob->xspeed;\r
- }\r
- else if (ob->hitwest)\r
- {\r
- ob->xdir = -1;\r
- ob->xspeed = -ob->xspeed;\r
- }\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- SD_PlaySound(SND_BOBBALAND);\r
- ChangeState(ob, &s_bobbastand);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_BobbaShot\r
-=\r
-===========================\r
-*/\r
-\r
-void R_BobbaShot(objtype *ob)\r
-{\r
- if (ob->hitnorth || ob->hitsouth || ob->hiteast || ob->hitwest)\r
- {\r
- ChangeState(ob, &s_bobbashotvanish1);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BABOBBA\r
-\r
-temp1 = jump counter (Babobba) / animation counter (Shot)\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_babobbajump1 = {BABOBBAL2SPR, BABOBBAR2SPR, stepthink, false, false, 8, 0, 0, T_Projectile, C_Babobba, R_Babobba, &s_babobbajump2};\r
-statetype s_babobbajump2 = {BABOBBAL3SPR, BABOBBAR3SPR, think, false, false, 8, 0, 0, T_Projectile, C_Babobba, R_Babobba, &s_babobbajump2};\r
-statetype s_babobbastand = {BABOBBAL1SPR, BABOBBAR1SPR, step, false, false, 20, 0, 0, T_BabobbaStand, C_Babobba, R_Draw, &s_babobbajump1};\r
-statetype s_babobbaattack = {BABOBBAL1SPR, BABOBBAR1SPR, step, false, false, 70, 0, 0, NULL, C_Babobba, R_Draw, &s_babobbastand};\r
-statetype s_babobbastun1 = {BABOBBAL2SPR, BABOBBAR2SPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, &s_babobbastun2};\r
-statetype s_babobbastun2 = {BABOBBASTUNSPR, BABOBBASTUNSPR, think, false, false, 0, 0, 0, T_Projectile, NULL, R_Stunned, NULL};\r
-statetype s_babobbasleep1 = {BABOBBASLEEP1SPR, BABOBBASLEEP1SPR, step, false, false, 15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep2};\r
-statetype s_babobbasleep2 = {BABOBBASLEEP2SPR, BABOBBASLEEP2SPR, step, false, false, 15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep3};\r
-statetype s_babobbasleep3 = {BABOBBASLEEP3SPR, BABOBBASLEEP3SPR, step, false, false, 15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep4};\r
-statetype s_babobbasleep4 = {BABOBBASLEEP4SPR, BABOBBASLEEP4SPR, step, false, false, 500, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep5};\r
-statetype s_babobbasleep5 = {BABOBBASLEEP3SPR, BABOBBASLEEP3SPR, step, false, false, 15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep6};\r
-statetype s_babobbasleep6 = {BABOBBASLEEP2SPR, BABOBBASLEEP2SPR, step, false, false, 15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbasleep7};\r
-statetype s_babobbasleep7 = {BABOBBASLEEP1SPR, BABOBBASLEEP1SPR, step, false, false, 15, 0, 0, NULL, C_BabobbaSleep, R_Draw, &s_babobbastand};\r
-statetype s_babobbashot1 = {BABOBBASHOT1SPR, BABOBBASHOT1SPR, think, false, false, 0, 0, 0, T_Projectile, C_Lethal, R_Bounce, &s_babobbashot2};\r
-statetype s_babobbashot2 = {BABOBBASHOT2SPR, BABOBBASHOT2SPR, step, false, false, 8, 0, 0, T_BabobbaShot, C_Lethal, R_Draw, &s_babobbashot3};\r
-statetype s_babobbashot3 = {BABOBBASHOT1SPR, BABOBBASHOT1SPR, step, false, false, 8, 0, 0, NULL, C_Lethal, R_Draw, &s_babobbashot2};\r
-statetype s_babobbashotvanish1 = {BABOBBASHOT2SPR, BABOBBASHOT2SPR, step, false, false, 8, 0, 0, T_BabobbaShotVanish, C_Lethal, R_Draw, &s_babobbashotvanish2};\r
-statetype s_babobbashotvanish2 = {-1, -1, step, false, false, 8, 0, 0, NULL, NULL, R_Draw, &s_babobbashotvanish1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBabobba\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBabobba(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = babobbaobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -2*TILEGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- new->ydir = 1;\r
- NewState(new, &s_babobbajump1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BabobbaStand\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BabobbaStand(objtype *ob)\r
-{\r
- Sint16 i;\r
- Uint16 far *map;\r
-\r
- if (US_RndT() < 4)\r
- {\r
- ob->temp1 = 0;\r
- ob->state = &s_babobbasleep1;\r
- }\r
- else if (++ob->temp1 == 3)\r
- {\r
- ob->temp1 = 0;\r
-\r
- GetNewObj(true);\r
- new->active = ac_removable;\r
- new->obclass = mshotobj;\r
- new->y = ob->y + 4*PIXGLOBAL;\r
- new->xdir = ob->xdir;\r
- if (ob->xdir == 1)\r
- {\r
- new->x = ob->x + 16*PIXGLOBAL;\r
- }\r
- else\r
- {\r
- new->x = ob->x + 11*PIXGLOBAL;\r
- }\r
- new->xspeed = new->xdir << 5;\r
- NewState(new, &s_babobbashot1);\r
- new->priority = 2;\r
- ob->state = &s_babobbaattack;\r
- }\r
- else\r
- {\r
- map = mapsegs[1] + mapbwidthtable[ob->tilebottom+1]/2 + ob->tilemidx;\r
- for (i=0; i<4; map += ob->xdir, i++)\r
- {\r
- if ( !tinf[*map+NORTHWALL]\r
- && !tinf[*(map-mapwidth)+NORTHWALL]\r
- && !tinf[*(map+mapwidth)+NORTHWALL] )\r
- {\r
- ob->xdir = -ob->xdir;\r
- break;\r
- }\r
- }\r
- ob->xspeed = ob->xdir *24;\r
- ob->yspeed = -32;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Babobba\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Babobba(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
- else if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_babobbastun1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_BabobbaSleep\r
-=\r
-===========================\r
-*/\r
-\r
-void C_BabobbaSleep(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- StunObj(ob, hit, &s_babobbastun1);\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Babobba\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Babobba(objtype *ob)\r
-{\r
- if (ob->hiteast)\r
- {\r
- ob->xdir = 1;\r
- ob->xspeed = -ob->xspeed;\r
- }\r
- else if (ob->hitwest)\r
- {\r
- ob->xdir = -1;\r
- ob->xspeed = -ob->xspeed;\r
- }\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ChangeState(ob, &s_babobbastand);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BabobbaShot\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BabobbaShot(objtype *ob)\r
-{\r
- if (++ob->temp1 == 10)\r
- {\r
- ob->temp1 = 0;\r
- ob->state = &s_babobbashotvanish1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_BabobbaShotVanish\r
-=\r
-===========================\r
-*/\r
-\r
-void T_BabobbaShotVanish(objtype *ob)\r
-{\r
- if (++ob->temp1 == 5)\r
- {\r
- RemoveObj(ob);\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BLORB\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_blorb1 = {BLORB1SPR, BLORB1SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb2};\r
-statetype s_blorb2 = {BLORB2SPR, BLORB2SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb3};\r
-statetype s_blorb3 = {BLORB3SPR, BLORB3SPR, slide, false, false, 20, 8, 8, 0, C_Lethal, R_Blorb, &s_blorb1};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnBlorb\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnBlorb(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = blorbobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = CONVERT_TILE_TO_GLOBAL(tileY) + -8*PIXGLOBAL;\r
- if (US_RndT() < 0x80)\r
- {\r
- new->xdir = 1;\r
- }\r
- else\r
- {\r
- new->xdir = -1;\r
- }\r
- if (US_RndT() < 0x80)\r
- {\r
- new->ydir = 1;\r
- }\r
- else\r
- {\r
- new->ydir = -1;\r
- }\r
- new->needtoclip = cl_fullclip;\r
- NewState(new, &s_blorb1);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= R_Blorb\r
-=\r
-===========================\r
-*/\r
-\r
-void R_Blorb(objtype *ob)\r
-{\r
- if (ob->hitnorth)\r
- {\r
- ob->ydir = -1;\r
- SD_PlaySound(SND_BLORBBOUNCE);\r
- }\r
- else if (ob->hitsouth)\r
- {\r
- ob->ydir = 1;\r
- SD_PlaySound(SND_BLORBBOUNCE);\r
- }\r
- if (ob->hitwest)\r
- {\r
- ob->xdir = -1;\r
- SD_PlaySound(SND_BLORBBOUNCE);\r
- }\r
- else if (ob->hiteast)\r
- {\r
- ob->xdir = 1;\r
- SD_PlaySound(SND_BLORBBOUNCE);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- CEILICK\r
-\r
-temp1 = initial y position\r
-\r
-=============================================================================\r
-*/\r
-\r
-statetype s_ceilickhidden = {TONGUE1SPR, TONGUE1SPR, think, false, false, 20, 0, 0, T_CeilickHidden, NULL, R_Draw, NULL};\r
-statetype s_ceilickattack1 = {TONGUE1SPR, TONGUE1SPR, step, false, false, 6, 0, 0, NULL, NULL, R_Draw, &s_ceilickattack2};\r
-statetype s_ceilickattack2 = {TONGUE2SPR, TONGUE2SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack3};\r
-statetype s_ceilickattack3 = {TONGUE3SPR, TONGUE3SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack4};\r
-statetype s_ceilickattack4 = {TONGUE4SPR, TONGUE4SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack5};\r
-statetype s_ceilickattack5 = {TONGUE5SPR, TONGUE5SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack6};\r
-statetype s_ceilickattack6 = {TONGUE4SPR, TONGUE4SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack7};\r
-statetype s_ceilickattack7 = {TONGUE3SPR, TONGUE3SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack8};\r
-statetype s_ceilickattack8 = {TONGUE4SPR, TONGUE4SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack9};\r
-statetype s_ceilickattack9 = {TONGUE5SPR, TONGUE5SPR, step, false, false, 6, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack10};\r
-statetype s_ceilickattack10 = {TONGUE2SPR, TONGUE2SPR, step, false, false, 10, 0, 0, NULL, C_Lethal, R_Draw, &s_ceilickattack11};\r
-statetype s_ceilickattack11 = {TONGUE1SPR, TONGUE1SPR, step, false, false, 10, 0, 0, NULL, NULL, R_Draw, &s_ceilicklaugh1};\r
-statetype s_ceilicklaugh1 = {CEILICK1SPR, CEILICK1SPR, slide, true, false, 16, 0, 16, T_CeilickLaugh, C_Ceilick, R_Draw, &s_ceilicklaugh2};\r
-statetype s_ceilicklaugh2 = {CEILICK2SPR, CEILICK2SPR, step, true, false, 10, 0, 0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh3};\r
-statetype s_ceilicklaugh3 = {CEILICK1SPR, CEILICK1SPR, step, true, false, 10, 0, 0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh4};\r
-statetype s_ceilicklaugh4 = {CEILICK2SPR, CEILICK2SPR, step, true, false, 10, 0, 0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh5};\r
-statetype s_ceilicklaugh5 = {CEILICK1SPR, CEILICK1SPR, step, true, false, 10, 0, 0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh6};\r
-statetype s_ceilicklaugh6 = {CEILICK2SPR, CEILICK2SPR, step, true, false, 10, 0, 0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh7};\r
-statetype s_ceilicklaugh7 = {CEILICK1SPR, CEILICK1SPR, step, true, false, 10, 0, 0, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh8};\r
-statetype s_ceilicklaugh8 = {CEILICK1SPR, CEILICK1SPR, slide, true, false, 16, 0, -16, NULL, C_Ceilick, R_Draw, &s_ceilicklaugh9};\r
-statetype s_ceilicklaugh9 = {-1, -1, step, true, false, 60, 0, 0, NULL, C_Ceilick, R_Draw, &s_ceilickhidden};\r
-statetype s_ceilickstun = {CEILICKSTUNSPR, CEILICKSTUNSPR, think, true, false, 0, 0, 0, T_CeilickStunned, NULL, R_Stunned, NULL};\r
-\r
-/*\r
-===========================\r
-=\r
-= SpawnCeilick\r
-=\r
-===========================\r
-*/\r
-\r
-void SpawnCeilick(Uint16 tileX, Uint16 tileY)\r
-{\r
- GetNewObj(false);\r
- new->obclass = ceilickobj;\r
- new->active = ac_yes;\r
- new->priority = 0;\r
- new->needtoclip = cl_noclip;\r
- new->x = CONVERT_TILE_TO_GLOBAL(tileX);\r
- new->y = new->temp1 = CONVERT_TILE_TO_GLOBAL(tileY);\r
- new->ydir = 1;\r
- NewState(new, &s_ceilickhidden);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_CeilickHidden\r
-=\r
-===========================\r
-*/\r
-\r
-void T_CeilickHidden(objtype *ob)\r
-{\r
- if ( player->y - ob->y <= 40*PIXGLOBAL\r
- && player->left < ob->right+PIXGLOBAL\r
- && player->right > ob->left-PIXGLOBAL )\r
- {\r
- SD_PlaySound(SND_CEILICKATTACK);\r
- ob->state = &s_ceilickattack1;\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_CeilickLaugh\r
-=\r
-===========================\r
-*/\r
-\r
-#pragma argsused\r
-void T_CeilickLaugh(objtype *ob)\r
-{\r
- SD_PlaySound(SND_CEILICKLAUGH);\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= T_CeilickStunned\r
-=\r
-===========================\r
-*/\r
-\r
-void T_CeilickStunned(objtype *ob)\r
-{\r
- ob->needtoreact = true; // to make sure the stunned stars animate\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= C_Ceilick\r
-=\r
-===========================\r
-*/\r
-\r
-void C_Ceilick(objtype *ob, objtype *hit)\r
-{\r
- if (hit->obclass == stunshotobj)\r
- {\r
- ob->y = ob->temp1;\r
- ExplodeShot(hit);\r
- ob->temp1 = ob->temp2 = ob->temp3 = 0;\r
- ob->temp4 = ob->obclass;\r
- ChangeState(ob, &s_ceilickstun);\r
- ob->obclass = stunnedobj;\r
- }\r
-}
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __K6_DEF__\r
-#define __K6_DEF__\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-#define MINMEMORY 255000l\r
-#else\r
-#define MINMEMORY 300000l\r
-#endif\r
-\r
-#define STARPALETTE {0, 1, 24, 25, 4, 28, 6, 7, 31, 31, 31, 31, 31, 31, 31, 31, 0}\r
-#define INTROPALETTE {0, 5, 5, 21, 1, 1, 1, 1, 17, 17, 17, 17, 19, 19, 19, 19, 0}\r
-#define SHRINKPALETTE {0, 5, 5, 21, 1, 1, 1, 1, 17, 17, 17, 17, 19, 19, 19, 5, 0}\r
-\r
-#define HIGHSCORE_LEFT 40\r
-#define HIGHSCORE_TOP 51\r
-#define HIGHSCORE_RIGHT 280\r
-#define HIGHSCORE_MAP 18\r
-\r
-#define STATUS_PRESSKEY_X 120\r
-\r
-#define WORLDMAPNAME "Fribbulus Xax"\r
-#define DROPSNAME "VIVAS"\r
-\r
-#define STARWARSMUSIC 13\r
-#define ENDINGMUSIC 1\r
-\r
-// levels in this range can NOT be re-entered (BWB level should be > MAXDONELEVEL)\r
-#define MINDONELEVEL 1\r
-#define MAXDONELEVEL 16\r
-\r
-#define INACTIVATEDIST 4\r
-\r
-//\r
-// tiles for worldmap teleporters\r
-//\r
-#define TELEPORTERTILE1 2613 // tile animation for teleporting out\r
-#define TELEPORTERTILE2 2629 // tile after teleporting out\r
-#define TELEPORTERTILE3 TELEPORTERTILE1 // tile animation for teleporting in\r
-#define TELEPORTERTILE4 TELEPORTERTILE2 // tile after teleporting in\r
-\r
-#define TELEPORERTILEMASK 3 // animation has 4 frames\r
-\r
-extern Sint16 groundslam;\r
-\r
-//HACKs:\r
-//#define US_ManualCheck() true\r
-boolean US_ManualCheck(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K6_SPEC DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern char far swtext[];\r
-extern char far *levelnames[GAMELEVELS];\r
-extern char far *levelenter[GAMELEVELS];\r
-\r
-void ScanInfoPlane(void);\r
-\r
-extern statetype s_keenstun;\r
-\r
-void FlipBigSwitch(objtype *ob, boolean isup);\r
-void GotSandwich(void);\r
-void GotHook(void);\r
-void GotPasscard(void);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- K6_ACT1 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern Sint16 pdirx[];\r
-extern Sint16 pdiry[];\r
-\r
-void C_ClipSide(objtype *ob, objtype *hit);\r
-void C_ClipTop(objtype *ob, objtype *hit);\r
-void R_Land(objtype *ob);\r
-void R_Bounce(objtype *ob);\r
-\r
-extern statetype s_bonus1;\r
-extern statetype s_bonus2;\r
-extern statetype s_bonusfly1;\r
-extern statetype s_bonusfly2;\r
-extern statetype s_bonusrise;\r
-\r
-extern statetype s_splash1;\r
-extern statetype s_splash2;\r
-extern statetype s_splash3;\r
-extern statetype s_splash4;\r
-\r
-extern Uint16 bonusshape[];\r
-\r
-void SpawnBonus(Uint16 tileX, Uint16 tileY, Uint16 type);\r
-void SpawnSplash(Uint16 tileX, Uint16 tileY);\r
-void T_Bonus(objtype *ob);\r
-void T_FlyBonus(objtype *ob);\r
-\r
-extern statetype s_grabbiter1;\r
-extern statetype s_grabbiter2;\r
-extern statetype s_grabbitersleep1;\r
-extern statetype s_grabbitersleep2;\r
-\r
-void SpawnGrabbiter(Uint16 tileX, Uint16 tileY);\r
-void C_Grabbiter(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_rocket;\r
-extern statetype s_rocketfly1;\r
-extern statetype s_rocketfly2;\r
-extern statetype s_keenrocket;\r
-\r
-void SpawnRocket(Uint16 tileX, Uint16 tileY, Uint16 state);\r
-void T_Rocket(objtype *ob);\r
-void C_Rocket(objtype *ob, objtype *hit);\r
-void C_RocketFly(objtype *ob, objtype *hit);\r
-void T_RocketFly(objtype *ob);\r
-\r
-extern statetype s_grapplespot;\r
-extern statetype s_throwrope1;\r
-extern statetype s_throwrope2;\r
-extern statetype s_climbrope1;\r
-extern statetype s_climbrope2;\r
-extern statetype s_maprope;\r
-extern statetype s_mapropeshort;\r
-\r
-void SpawnGrappleSpot(Uint16 tileX, Uint16 tileY, Uint16 type);\r
-void T_ThrowRope(objtype *ob);\r
-void T_ClimbRope(objtype *ob);\r
-void C_GrappleSpot(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_satellitestopspot;\r
-extern statetype s_worldkeensatellite;\r
-extern statetype s_satellite1;\r
-extern statetype s_satellite2;\r
-extern statetype s_satellite3;\r
-extern statetype s_satellite4;\r
-\r
-void SpawnSatelliteStop(Uint16 tileX, Uint16 tileY, Uint16 type);\r
-void SpawnSatellite(Uint16 tileX, Uint16 tileY);\r
-void T_Satellite(objtype *ob);\r
-void C_Satellite(objtype *ob, objtype *hit);\r
-void R_WorldKeenSatellite(objtype *ob);\r
-\r
-extern statetype s_sandwich;\r
-\r
-void SpawnSandwich(Uint16 tileX, Uint16 tileY);\r
-\r
-extern statetype s_hook;\r
-\r
-void SpawnHook(Uint16 tileX, Uint16 tileY);\r
-\r
-extern statetype s_passcard;\r
-\r
-void SpawnPasscard(Uint16 tileX, Uint16 tileY);\r
-void C_Molly(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_molly1;\r
-extern statetype s_molly2;\r
-extern statetype s_molly3;\r
-extern statetype s_molly4;\r
-\r
-void SpawnMolly(Uint16 tileX, Uint16 tileY);\r
-\r
-extern statetype s_platform;\r
-\r
-void SpawnPlatform(Uint16 tileX, Uint16 tileY, Sint16 dir);\r
-void T_Platform(objtype *ob);\r
-\r
-extern statetype s_dropplatsit;\r
-extern statetype s_fallplatfall;\r
-extern statetype s_fallplatrise;\r
-\r
-void SpawnDropPlat(Uint16 tileX, Uint16 tileY);\r
-void T_DropPlatSit(objtype *ob);\r
-void T_DropPlatFall(objtype *ob);\r
-void T_DropPlatRise(objtype *ob);\r
-\r
-extern statetype s_staticplatform;\r
-\r
-void SpawnStaticPlat(Uint16 tileX, Uint16 tileY);\r
-\r
-extern statetype s_goplat;\r
-\r
-void SpawnGoPlat(Uint16 tileX, Uint16 tileY, Sint16 dir);\r
-void T_GoPlat(objtype *ob);\r
-void R_GoPlat(objtype *ob);\r
-\r
-extern statetype s_sneakplatsit;\r
-extern statetype s_sneakplatdodge;\r
-extern statetype s_sneakplatreturn;\r
-\r
-void SpawnSneakPlat(Uint16 tileX, Uint16 tileY);\r
-void T_SneakPlat(objtype *ob);\r
-\r
-extern statetype s_bloogwalk1;\r
-extern statetype s_bloogwalk2;\r
-extern statetype s_bloogwalk3;\r
-extern statetype s_bloogwalk4;\r
-extern statetype s_bloogstun;\r
-\r
-void SpawnBloog(Uint16 tileX, Uint16 tileY);\r
-void T_BloogWalk(objtype *ob);\r
-void C_Bloog(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_blooguardwalk1;\r
-extern statetype s_blooguardwalk2;\r
-extern statetype s_blooguardwalk3;\r
-extern statetype s_blooguardwalk4;\r
-extern statetype s_blooguardattack1;\r
-extern statetype s_blooguardattack2;\r
-extern statetype s_blooguardattack3;\r
-extern statetype s_blooguardattack4;\r
-extern statetype s_blooguardstun;\r
-\r
-void SpawnBlooguard(Uint16 tileX, Uint16 tileY);\r
-void T_BlooguardWalk(objtype *ob);\r
-void T_BlooguardAttack(objtype *ob);\r
-void C_Blooguard(objtype *ob, objtype *hit);\r
-void R_Blooguard(objtype *ob);\r
-\r
-extern statetype s_rbloogletwalk1;\r
-extern statetype s_rbloogletwalk2;\r
-extern statetype s_rbloogletwalk3;\r
-extern statetype s_rbloogletwalk4;\r
-extern statetype s_rbloogletstun;\r
-extern statetype s_ybloogletwalk1;\r
-extern statetype s_ybloogletwalk2;\r
-extern statetype s_ybloogletwalk3;\r
-extern statetype s_ybloogletwalk4;\r
-extern statetype s_ybloogletstun;\r
-extern statetype s_bbloogletwalk1;\r
-extern statetype s_bbloogletwalk2;\r
-extern statetype s_bbloogletwalk3;\r
-extern statetype s_bbloogletwalk4;\r
-extern statetype s_bbloogletstun;\r
-extern statetype s_gbloogletwalk1;\r
-extern statetype s_gbloogletwalk2;\r
-extern statetype s_gbloogletwalk3;\r
-extern statetype s_gbloogletwalk4;\r
-extern statetype s_gbloogletstun;\r
-\r
-void SpawnBlooglet(Uint16 tileX, Uint16 tileY, Sint16 type);\r
-void C_Blooglet(objtype *ob, objtype *hit);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K6_ACT2 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_nospikestand;\r
-extern statetype s_nospikewalk1;\r
-extern statetype s_nospikewalk2;\r
-extern statetype s_nospikewalk3;\r
-extern statetype s_nospikewalk4;\r
-extern statetype s_nospikerun1;\r
-extern statetype s_nospikerun2;\r
-extern statetype s_nospikerun3;\r
-extern statetype s_nospikerun4;\r
-extern statetype s_nospikeconfused1;\r
-extern statetype s_nospikeconfused2;\r
-extern statetype s_nospikeconfused3;\r
-extern statetype s_nospikefall;\r
-extern statetype s_nospikestun;\r
-\r
-void SpawnNospike(Uint16 tileX, Uint16 tileY);\r
-void T_NospikeWalk(objtype *ob);\r
-void T_NospikeRun(objtype *ob);\r
-void C_Nospike(objtype *ob, objtype *hit);\r
-void T_NospikeConfused(objtype* ob);\r
-void R_NospikeConfused(objtype *ob);\r
-void R_NospikeFall(objtype *ob);\r
-void R_NospikeRun(objtype *ob);\r
-\r
-extern statetype s_gikwalk1;\r
-extern statetype s_gikwalk2;\r
-extern statetype s_gikwalk3;\r
-extern statetype s_gikjump;\r
-extern statetype s_gikslide1;\r
-extern statetype s_gikslide2;\r
-extern statetype s_gikstand;\r
-\r
-void SpawnGik(Uint16 tileX, Uint16 tileY);\r
-void T_GikWalk(objtype *ob);\r
-void T_GikSlide(objtype *ob);\r
-void R_GikJump(objtype *ob);\r
-void R_GikSlide(objtype *ob);\r
-\r
-extern statetype s_cannon;\r
-extern statetype s_cannonfire;\r
-extern statetype s_cshot1;\r
-extern statetype s_cshot2;\r
-extern statetype s_cshot3;\r
-extern statetype s_cshot4;\r
-extern statetype s_cshothit1;\r
-extern statetype s_cshothit2;\r
-\r
-void SpawnCannon(Uint16 tileX, Uint16 tileY, Sint16 dir);\r
-void T_Cannon(objtype *ob);\r
-void C_CShot(objtype *ob, objtype *hit);\r
-void R_CShot(objtype *ob);\r
-\r
-extern statetype s_orbatrix1;\r
-extern statetype s_orbatrix2;\r
-extern statetype s_orbatrixcurl1;\r
-extern statetype s_orbatrixcurl2;\r
-extern statetype s_orbatrixcurl3;\r
-extern statetype s_orbatrixuncurl1;\r
-extern statetype s_orbatrixuncurl2;\r
-extern statetype s_orbatrixidle1;\r
-extern statetype s_orbatrixidle2;\r
-extern statetype s_orbatrixidle3;\r
-extern statetype s_orbatrixidle4;\r
-extern statetype s_orbatrixbounce1;\r
-extern statetype s_orbatrixbounce2;\r
-extern statetype s_orbatrixbounce3;\r
-extern statetype s_orbatrixbounce4;\r
-\r
-void SpawnOrbatrix(Uint16 tileX, Uint16 tileY);\r
-void T_OrbatrixFly(objtype *ob);\r
-void C_Orbatrix(objtype *ob, objtype *hit);\r
-void R_Orbatrix(objtype *ob);\r
-void R_OrbatrixBounce(objtype *ob);\r
-void T_OrbatrixCurl(objtype *ob);\r
-void T_OrbatrixUncurl(objtype *ob);\r
-void C_OrbatrixBounce(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_bipstand;\r
-extern statetype s_bipwalk1;\r
-extern statetype s_bipwalk2;\r
-extern statetype s_bipwalk3;\r
-extern statetype s_bipwalk4;\r
-extern statetype s_bipsquished;\r
-\r
-void T_BipWalk(objtype *ob);\r
-void C_Bip(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_bipship;\r
-extern statetype s_bipshipshot;\r
-extern statetype s_bipshipturn1;\r
-extern statetype s_bipshipturn2;\r
-extern statetype s_bipshipturn3;\r
-extern statetype s_bipshipturn4;\r
-extern statetype s_bipshipexplode1;\r
-extern statetype s_bipshipexplode2;\r
-extern statetype s_bipshipexplode3;\r
-extern statetype s_bipshipsmoke1;\r
-extern statetype s_bipshipsmoke2;\r
-\r
-void SpawnBipship(Uint16 tileX, Uint16 tileY);\r
-void R_BipShot(objtype *ob);\r
-void T_BipshipTurn(objtype *ob);\r
-void T_BipshipFly(objtype *ob);\r
-void T_BipshipExplode(objtype *ob);\r
-void C_Bipship(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_flectstand;\r
-extern statetype s_flectturn;\r
-extern statetype s_flectwalk1;\r
-extern statetype s_flectwalk2;\r
-extern statetype s_flectwalk3;\r
-extern statetype s_flectwalk4;\r
-extern statetype s_flectstun;\r
-\r
-void SpawnFlect(Uint16 tileX, Uint16 tileY);\r
-void T_FlectStand(objtype *ob);\r
-void T_FlectWalk(objtype *ob);\r
-void C_Flect(objtype *ob, objtype *hit);\r
-void R_Flect(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- K6_ACT3 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_fleexwalk1;\r
-extern statetype s_fleexwalk2;\r
-extern statetype s_fleexrun1;\r
-extern statetype s_fleexrun2;\r
-extern statetype s_fleexrun3;\r
-extern statetype s_fleexrun4;\r
-extern statetype s_fleexlook1;\r
-extern statetype s_fleexlook2;\r
-extern statetype s_fleexstun;\r
-\r
-void SpawnFleex(Uint16 tileX, Uint16 tileY);\r
-void T_FleexWalk(objtype *ob);\r
-void T_FleexLook(objtype *ob);\r
-void C_Fleex(objtype *ob, objtype *hit);\r
-\r
-extern statetype s_bobbajump1;\r
-extern statetype s_bobbajump2;\r
-extern statetype s_bobbastand;\r
-extern statetype s_bobbaattack;\r
-extern statetype s_bobbashot1;\r
-extern statetype s_bobbashot2;\r
-extern statetype s_bobbashot3;\r
-extern statetype s_bobbashot4;\r
-extern statetype s_bobbashot5;\r
-extern statetype s_bobbashot6;\r
-extern statetype s_bobbashot7;\r
-extern statetype s_bobbashot8;\r
-extern statetype s_bobbashotvanish1;\r
-extern statetype s_bobbashotvanish2;\r
-extern statetype s_bobbashotvanish3;\r
-\r
-void SpawnBobba(Uint16 tileX, Uint16 tileY);\r
-void T_BobbaShot(objtype *ob);\r
-void T_BobbaStand(objtype *ob);\r
-void C_Bobba(objtype *ob, objtype *hit);\r
-void R_Bobba(objtype *ob);\r
-void R_BobbaShot(objtype *ob);\r
-\r
-extern statetype s_babobbajump1;\r
-extern statetype s_babobbajump2;\r
-extern statetype s_babobbastand;\r
-extern statetype s_babobbaattack;\r
-extern statetype s_babobbastun1;\r
-extern statetype s_babobbastun2;\r
-extern statetype s_babobbasleep1;\r
-extern statetype s_babobbasleep2;\r
-extern statetype s_babobbasleep3;\r
-extern statetype s_babobbasleep4;\r
-extern statetype s_babobbasleep5;\r
-extern statetype s_babobbasleep6;\r
-extern statetype s_babobbasleep7;\r
-extern statetype s_babobbashot1;\r
-extern statetype s_babobbashot2;\r
-extern statetype s_babobbashot3;\r
-extern statetype s_babobbashotvanish1;\r
-extern statetype s_babobbashotvanish2;\r
-\r
-void SpawnBabobba(Uint16 tileX, Uint16 tileY);\r
-void T_BabobbaStand(objtype *ob);\r
-void C_Babobba(objtype *ob, objtype *hit);\r
-void C_BabobbaSleep(objtype *ob, objtype *hit);\r
-void R_Babobba(objtype *ob);\r
-void T_BabobbaShot(objtype *ob);\r
-void T_BabobbaShotVanish(objtype *ob);\r
-\r
-extern statetype s_blorb1;\r
-extern statetype s_blorb2;\r
-extern statetype s_blorb3;\r
-\r
-void SpawnBlorb(Uint16 tileX, Uint16 tileY);\r
-void R_Blorb(objtype *ob);\r
-\r
-extern statetype s_ceilickhidden;\r
-extern statetype s_ceilickattack1;\r
-extern statetype s_ceilickattack2;\r
-extern statetype s_ceilickattack3;\r
-extern statetype s_ceilickattack4;\r
-extern statetype s_ceilickattack5;\r
-extern statetype s_ceilickattack6;\r
-extern statetype s_ceilickattack7;\r
-extern statetype s_ceilickattack8;\r
-extern statetype s_ceilickattack9;\r
-extern statetype s_ceilickattack10;\r
-extern statetype s_ceilickattack11;\r
-extern statetype s_ceilicklaugh1;\r
-extern statetype s_ceilicklaugh2;\r
-extern statetype s_ceilicklaugh3;\r
-extern statetype s_ceilicklaugh4;\r
-extern statetype s_ceilicklaugh5;\r
-extern statetype s_ceilicklaugh6;\r
-extern statetype s_ceilicklaugh7;\r
-extern statetype s_ceilicklaugh8;\r
-extern statetype s_ceilicklaugh9;\r
-extern statetype s_ceilickstun;\r
-\r
-void SpawnCeilick(Uint16 tileX, Uint16 tileY);\r
-void T_CeilickHidden(objtype *ob);\r
-void T_CeilickLaugh(objtype *ob);\r
-void T_CeilickStunned(objtype *ob);\r
-void C_Ceilick(objtype *ob, objtype *hit);\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/*\r
-K6_SPEC.C\r
-=========\r
-\r
-Contains (in this order):\r
-\r
-- lump definition\r
-- "Star Wars" crawl text\r
-- level names & messages\r
-- ScanInfoPlane() - for spawning the level objects and marking required sprites\r
-- stunned state for Keen\r
-- code to flip the big yellow switches\r
-- messages for sandwich, rope and passcard\r
-*/\r
-\r
-#include "CK_DEF.H"\r
-\r
-enum {\r
- CONTROLS_LUMP, // 0\r
- KEEN_LUMP, // 1\r
- SUGAR1_LUMP, // 2\r
- SUGAR2_LUMP, // 3\r
- SUGAR3_LUMP, // 4\r
- SUGAR4_LUMP, // 5\r
- SUGAR5_LUMP, // 6\r
- SUGAR6_LUMP, // 7\r
- ONEUP_LUMP, // 8\r
- KEYGEM_LUMP, // 9\r
- AMMO_LUMP, // 10\r
- WORLDKEEN_LUMP, // 11\r
- UNUSED1_LUMP, // 12\r
- BLOOG_LUMP, // 13\r
- RBLOOGLET_LUMP, // 14\r
- YBLOOGLET_LUMP, // 15\r
- BBLOOGLET_LUMP, // 16\r
- GBLOOGLET_LUMP, // 17\r
- PLATFORM_LUMP, // 18\r
- GIK_LUMP, // 19\r
- BLORB_LUMP, // 20\r
- BOBBA_LUMP, // 21\r
- BABOBBA_LUMP, // 22\r
- BLOOGUARD_LUMP, // 23\r
- FLECT_LUMP, // 24\r
- BIP_LUMP, // 25\r
- BIPSQUISHED_LUMP, // 26\r
- BIPSHIP_LUMP, // 27\r
- NOSPIKE_LUMP, // 28\r
- ORBATRIX_LUMP, // 29\r
- CEILICK_LUMP, // 30\r
- FLEEX_LUMP, // 31\r
- HOOK_LUMP, // 32\r
- SANDWICH_LUMP, // 33\r
- LASER_LUMP, // 34\r
- PASSCARD_LUMP, // 35\r
- MOLLY_LUMP, // 36\r
-\r
- NUMLUMPS=40 // Keen 6 has 3 unused lumps at the end\r
-};\r
-\r
-Uint16 lumpstart[NUMLUMPS] = {\r
- CONTROLS_LUMP_START,\r
- KEEN_LUMP_START,\r
- SUGAR1_LUMP_START,\r
- SUGAR2_LUMP_START,\r
- SUGAR3_LUMP_START,\r
- SUGAR4_LUMP_START,\r
- SUGAR5_LUMP_START,\r
- SUGAR6_LUMP_START,\r
- ONEUP_LUMP_START,\r
- KEYGEM_LUMP_START,\r
- AMMO_LUMP_START,\r
- WORLDKEEN_LUMP_START,\r
- 0,\r
- BLOOG_LUMP_START,\r
- RBLOOGLET_LUMP_START,\r
- YBLOOGLET_LUMP_START,\r
- BBLOOGLET_LUMP_START,\r
- GBLOOGLET_LUMP_START,\r
- PLATFORM_LUMP_START,\r
- GIK_LUMP_START,\r
- BLORB_LUMP_START,\r
- BOBBA_LUMP_START,\r
- BABOBBA_LUMP_START,\r
- BLOOGUARD_LUMP_START,\r
- FLECT_LUMP_START,\r
- BIP_LUMP_START,\r
- BIPSQUISHED_LUMP_START,\r
- BIPSHIP_LUMP_START,\r
- NOSPIKE_LUMP_START,\r
- ORBATRIX_LUMP_START,\r
- CEILICK_LUMP_START,\r
- FLEEX_LUMP_START,\r
- HOOK_LUMP_START,\r
- SANDWICH_LUMP_START,\r
- LASER_LUMP_START,\r
- PASSCARD_LUMP_START,\r
- MOLLY_LUMP_START\r
-};\r
-\r
-Uint16 lumpend[NUMLUMPS] = {\r
- CONTROLS_LUMP_END,\r
- KEEN_LUMP_END,\r
- SUGAR1_LUMP_END,\r
- SUGAR2_LUMP_END,\r
- SUGAR3_LUMP_END,\r
- SUGAR4_LUMP_END,\r
- SUGAR5_LUMP_END,\r
- SUGAR6_LUMP_END,\r
- ONEUP_LUMP_END,\r
- KEYGEM_LUMP_END,\r
- AMMO_LUMP_END,\r
- WORLDKEEN_LUMP_END,\r
- 0,\r
- BLOOG_LUMP_END,\r
- RBLOOGLET_LUMP_END,\r
- YBLOOGLET_LUMP_END,\r
- BBLOOGLET_LUMP_END,\r
- GBLOOGLET_LUMP_END,\r
- PLATFORM_LUMP_END,\r
- GIK_LUMP_END,\r
- BLORB_LUMP_END,\r
- BOBBA_LUMP_END,\r
- BABOBBA_LUMP_END,\r
- BLOOGUARD_LUMP_END,\r
- FLECT_LUMP_END,\r
- BIP_LUMP_END,\r
- BIPSQUISHED_LUMP_END,\r
- BIPSHIP_LUMP_END,\r
- NOSPIKE_LUMP_END,\r
- ORBATRIX_LUMP_END,\r
- CEILICK_LUMP_END,\r
- FLEEX_LUMP_END,\r
- HOOK_LUMP_END,\r
- SANDWICH_LUMP_END,\r
- LASER_LUMP_END,\r
- PASSCARD_LUMP_END,\r
- MOLLY_LUMP_END\r
-};\r
-\r
-boolean lumpneeded[NUMLUMPS];\r
-\r
-#if GRMODE == EGAGR\r
-\r
-char far swtext[] =\r
- "Episode Six\n"\r
- "\n"\r
- "Aliens Ate My\n"\r
- "Baby Sitter!\n"\r
- "\n"\r
- "While out in his\n"\r
- "backyard clubhouse,\n"\r
- "Billy's baby sitter\n"\r
- "Molly calls him for\n"\r
- "dinner. He continues\n"\r
- "working on his new\n"\r
- "wrist computer.\n"\r
- "\n"\r
- "Suddenly, there is a\n"\r
- "loud noise outside.\n"\r
- "\n"\r
- "Rushing out, Keen finds\n"\r
- "his baby sitter gone\n"\r
- "and a note on a patch\n"\r
- "of scorched grass. The\n"\r
- "Bloogs of Fribbulus Xax\n"\r
- "are going to make a\n"\r
- "meal out of Molly!\n"\r
- "\n"\r
- "You've got to rescue\n"\r
- "her, because your\n"\r
- "parents will never\n"\r
- "believe you when you\n"\r
- "tell them...\n"\r
- "\n"\r
- "\"Aliens Ate My\n"\r
- "Baby Sitter!\"\n";\r
-\r
-#endif\r
-\r
-char far l0n[] = "Fribbulus Xax";\r
-char far l1n[] = "Bloogwaters\nCrossing";\r
-char far l2n[] = "Guard Post One";\r
-char far l3n[] = "First Dome\nof Darkness";\r
-char far l4n[] = "Second Dome\nof Darkness";\r
-char far l5n[] = "The Bloogdome";\r
-char far l6n[] = "Bloogton Mfg.,\nIncorporated";\r
-char far l7n[] = "Bloogton Tower";\r
-char far l8n[] = "Bloogfoods, Inc.";\r
-char far l9n[] = "Guard Post Two";\r
-char far l10n[] = "Bloogville";\r
-char far l11n[] = "BASA";\r
-char far l12n[] = "Guard Post Three";\r
-char far l13n[] = "Bloogbase Rec\nDistrict";\r
-char far l14n[] = "Bloogbase Mgmt.\nDistrict";\r
-char far l15n[] = "Bloog Control Center";\r
-char far l16n[] = "Blooglab";\r
-char far l17n[] = "Bean-with-Bacon\nMegarocket";\r
-char far l18n[] = "High Scores";\r
-\r
-char far l0e[] = "Keen attacks\nFribbulus Xax";\r
-char far l1e[] = "Keen hops across\nBloogwaters\nCrossing";\r
-char far l2e[] = "Keen fights his way\nthrough Guard Post One";\r
-char far l3e[] = "Keen crosses into the\nFirst Dome of Darkness";\r
-char far l4e[] = "Keen dares to enter the\nSecond Dome of Darkness";\r
-char far l5e[] = "Keen foolishly enters\nthe Bloogdome";\r
-char far l6e[] = "Keen makes his way\ninto Bloogton\nManufacturing";\r
-char far l7e[] = "Keen ascends\nBloogton Tower";\r
-char far l8e[] = "Keen hungrily enters\nBloogfoods, Inc.";\r
-char far l9e[] = "Keen smashes through\nGuard Post Two";\r
-char far l10e[] = "Keen seeks thrills\nin Bloogville";\r
-char far l11e[] = "Keen rockets into the\nBloog Aeronautics and\nSpace Administration";\r
-char far l12e[] = "Keen boldly assaults\nGuard Post Three";\r
-char far l13e[] = "Keen whoops it up in\nthe Bloogbae\nRecreational District"; // sic!\r
-char far l14e[] = "Keen purposefully struts\ninto the Bloogbase\nManagement District";\r
-char far l15e[] = "Keen bravely enters the\nBloog Control Center,\nlooking for Molly";\r
-char far l16e[] = "Keen warily enters\nBlooglab Space\nStation";\r
-char far l17e[] = "Keen returns to the\nBean-with-Bacon\nMegarocket";\r
-char far l18e[] = "Keen is in the High\nScore screen. Call Id!";\r
-\r
-char far *levelnames[GAMELEVELS] = {\r
- l0n,\r
- l1n,\r
- l2n,\r
- l3n,\r
- l4n,\r
- l5n,\r
- l6n,\r
- l7n,\r
- l8n,\r
- l9n,\r
- l10n,\r
- l11n,\r
- l12n,\r
- l13n,\r
- l14n,\r
- l15n,\r
- l16n,\r
- l17n,\r
- l18n\r
-};\r
-\r
-char far *levelenter[GAMELEVELS] = {\r
- l0e,\r
- l1e,\r
- l2e,\r
- l3e,\r
- l4e,\r
- l5e,\r
- l6e,\r
- l7e,\r
- l8e,\r
- l9e,\r
- l10e,\r
- l11e,\r
- l12e,\r
- l13e,\r
- l14e,\r
- l15e,\r
- l16e,\r
- l17e,\r
- l18e\r
-};\r
-\r
-Uint16 bonuslump[] = {\r
- KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP, KEYGEM_LUMP,\r
- SUGAR1_LUMP, SUGAR2_LUMP, SUGAR3_LUMP,\r
- SUGAR4_LUMP, SUGAR5_LUMP, SUGAR6_LUMP,\r
- ONEUP_LUMP, AMMO_LUMP, AMMO_LUMP, 0, 0\r
-};\r
-\r
-//============================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= ScanInfoPlane\r
-=\r
-= Spawn all actors and mark down special places\r
-=\r
-==========================\r
-*/\r
-\r
-void ScanInfoPlane(void)\r
-{\r
- Uint16 i, x, y, chunk;\r
- Sint16 info;\r
- Uint16 far *map;\r
- objtype *ob;\r
-\r
- InitObjArray(); // start spawning things with a clean slate\r
-\r
- memset(lumpneeded, 0, sizeof(lumpneeded));\r
- map = mapsegs[2];\r
-\r
- for (y=0; y<mapheight; y++)\r
- {\r
- for (x=0; x<mapwidth; x++)\r
- {\r
- info = *map++;\r
-\r
- if (info == 0)\r
- continue;\r
-\r
- switch (info)\r
- {\r
- case 1:\r
- SpawnKeen(x, y, 1);\r
- SpawnScore();\r
- lumpneeded[KEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 2:\r
- SpawnKeen(x, y, -1);\r
- SpawnScore();\r
- lumpneeded[KEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 3:\r
- SpawnWorldKeen(x, y);\r
- SpawnScore();\r
- lumpneeded[WORLDKEEN_LUMP] = true;\r
- CA_MarkGrChunk(SCOREBOXSPR);\r
- break;\r
-\r
- case 6:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 5:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 4:\r
- SpawnBloog(x, y);\r
- lumpneeded[BLOOG_LUMP] = true;\r
- break;\r
-\r
- case 7:\r
- case 8:\r
- case 9:\r
- case 10:\r
- case 11:\r
- case 12:\r
- case 13:\r
- case 14:\r
- SpawnBlooglet(x, y, info-7);\r
- lumpneeded[(info-7) % 4 + RBLOOGLET_LUMP] = true;\r
- if (info > 10)\r
- lumpneeded[KEYGEM_LUMP] = true;\r
- break;\r
-\r
- case 15:\r
- case 16:\r
- SpawnGrappleSpot(x, y, info-15);\r
- break;\r
-\r
- // case 17 is not used\r
-\r
- case 20:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 19:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 18:\r
- SpawnFleex(x, y);\r
- lumpneeded[FLEEX_LUMP] = true;\r
- break;\r
-\r
- case 21:\r
- case 22:\r
- case 23:\r
- case 24:\r
- SpawnMolly(x, y);\r
- lumpneeded[MOLLY_LUMP] = true;\r
- break;\r
-\r
- case 25:\r
- RF_SetScrollBlock(x, y, true);\r
- break;\r
-\r
- case 26:\r
- RF_SetScrollBlock(x, y, false);\r
- break;\r
-\r
- case 27:\r
- case 28:\r
- case 29:\r
- case 30:\r
- SpawnPlatform(x, y, info-27);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- // case 31 is the block icon\r
-\r
- case 32:\r
- SpawnDropPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 35:\r
- SpawnStaticPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
- case 34:\r
- if (gamestate.difficulty > gd_Normal)\r
- break;\r
- SpawnStaticPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
- case 33:\r
- if (gamestate.difficulty > gd_Easy)\r
- break;\r
- SpawnStaticPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 36:\r
- case 37:\r
- case 38:\r
- case 39:\r
- SpawnGoPlat(x, y, info-36);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- lumpneeded[BIPSQUISHED_LUMP] = true; // why?\r
- break;\r
-\r
- case 40:\r
- SpawnSneakPlat(x, y);\r
- lumpneeded[PLATFORM_LUMP] = true;\r
- break;\r
-\r
- case 43:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 42:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 41:\r
- SpawnBobba(x, y);\r
- lumpneeded[BOBBA_LUMP] = true;\r
- break;\r
-\r
- case 44:\r
- case 45:\r
- SpawnSatelliteStop(x, y, info-44);\r
- break;\r
-\r
- // case 46 is not used\r
-\r
- case 49:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 48:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 47:\r
- SpawnNospike(x, y);\r
- lumpneeded[NOSPIKE_LUMP] = true;\r
- break;\r
-\r
- case 52:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 51:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 50:\r
- SpawnGik(x, y);\r
- lumpneeded[GIK_LUMP] = true;\r
- break;\r
-\r
- case 53:\r
- case 54:\r
- case 55:\r
- case 56:\r
- SpawnCannon(x, y, info-53);\r
- lumpneeded[LASER_LUMP] = true;\r
- break;\r
-\r
- case 69:\r
- if (gamestate.ammo >= 5)\r
- break;\r
- info = 68;\r
- // no break here!\r
- case 57:\r
- case 58:\r
- case 59:\r
- case 60:\r
- case 61:\r
- case 62:\r
- case 63:\r
- case 64:\r
- case 65:\r
- case 66:\r
- case 67:\r
- case 68:\r
- SpawnBonus(x, y, info-57);\r
- lumpneeded[bonuslump[info-57]] = true;\r
- break;\r
-\r
- case 72:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 71:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 70:\r
- SpawnOrbatrix(x, y);\r
- lumpneeded[ORBATRIX_LUMP] = true;\r
- break;\r
-\r
- case 75:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 74:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 73:\r
- SpawnBipship(x, y);\r
- lumpneeded[BIP_LUMP]=lumpneeded[BIPSHIP_LUMP]=lumpneeded[BIPSQUISHED_LUMP] = true;\r
- break;\r
-\r
- case 78:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 77:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 76:\r
- SpawnFlect(x, y);\r
- lumpneeded[FLECT_LUMP] = true;\r
- break;\r
-\r
- case 81:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 80:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 79:\r
- SpawnBlorb(x, y);\r
- lumpneeded[BLORB_LUMP] = true;\r
- break;\r
-\r
- case 84:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 83:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 82:\r
- SpawnCeilick(x, y);\r
- lumpneeded[CEILICK_LUMP] = true;\r
- break;\r
-\r
- case 87:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 86:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 85:\r
- SpawnBlooguard(x, y);\r
- lumpneeded[BLOOGUARD_LUMP] = true;\r
- break;\r
-\r
- case 88:\r
- SpawnGrabbiter(x, y);\r
- // no additional lump needed - sprites are in WORLDKEEN_LUMP\r
- break;\r
-\r
- case 89:\r
- SpawnSatellite(x, y);\r
- // no additional lump needed - sprites are in WORLDKEEN_LUMP\r
- break;\r
-\r
- // case 90 is not used\r
- // cases 91 to 98 are direction arrows\r
-\r
- case 99:\r
- SpawnHook(x, y);\r
- lumpneeded[HOOK_LUMP] = true;\r
- break;\r
-\r
- case 100:\r
- SpawnSandwich(x, y);\r
- lumpneeded[SANDWICH_LUMP] = true;\r
- break;\r
-\r
- case 101:\r
- SpawnPasscard(x, y);\r
- lumpneeded[PASSCARD_LUMP] = true;\r
- break;\r
-\r
- case 104:\r
- if (gamestate.difficulty < gd_Hard)\r
- break;\r
- case 103:\r
- if (gamestate.difficulty < gd_Normal)\r
- break;\r
- case 102:\r
- SpawnBabobba(x, y);\r
- lumpneeded[BABOBBA_LUMP] = true;\r
- break;\r
-\r
- case 105:\r
- case 106:\r
- SpawnRocket(x, y, info-105);\r
- // no additional lump needed - sprites are in WORLDKEEN_LUMP\r
- break;\r
- }\r
- }\r
- }\r
-\r
- for (ob = player; ob; ob = ob->next)\r
- {\r
- if (ob->active != ac_allways)\r
- ob->active = ac_no;\r
- }\r
-\r
- for (i = 0; i < NUMLUMPS; i++)\r
- {\r
- if (lumpneeded[i])\r
- {\r
- for (chunk = lumpstart[i]; chunk <= lumpend[i]; chunk++)\r
- {\r
- CA_MarkGrChunk(chunk);\r
- }\r
- }\r
- }\r
-}\r
-\r
-//============================================================================\r
-\r
-statetype s_keenstun = {KEENSTUNSPR, KEENSTUNSPR, step, false, true, 60, 0, 0, T_Projectile, KeenContact, KeenStandReact, &s_keenstand};\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= FlipBigSwitch\r
-=\r
-===========================\r
-*/\r
-\r
-void FlipBigSwitch(objtype *ob, boolean isup)\r
-{\r
- Uint16 x, y;\r
- Uint16 far *map;\r
- Uint16 top, mid, bot;\r
- Uint16 *tileptr;\r
- Uint16 tile, tx, ty, xi, yi, offset, anim;\r
- Uint16 tiles[6];\r
-\r
- //\r
- // handle flipping the switch itself:\r
- //\r
- if (isup)\r
- {\r
- ty = ob->tilebottom;\r
- }\r
- else\r
- {\r
- ty = ob->tiletop - 2;\r
- }\r
- tx = ob->tileleft - 1;\r
- map = mapsegs[2] + mapbwidthtable[ty+1]/2 + tx + 1;\r
- while (*map == 0)\r
- {\r
- map++;\r
- tx++;\r
- }\r
- map = mapsegs[1] + mapbwidthtable[ty]/2 + tx;\r
- tileptr = tiles;\r
- for (y = 0; y < 3; y++, map += mapwidth)\r
- {\r
- for (x = 0; x < 2; tileptr++, x++)\r
- {\r
- tile = map[x];\r
- *tileptr = tile + (Sint8)tinf[tile+MANIM];\r
- }\r
- }\r
- RF_MemToMap(tiles, 1, tx, ty, 2, 3);\r
-\r
- tile = *(mapsegs[2]+mapbwidthtable[ty+1]/2 + tx + 1);\r
- x = tile >> 8;\r
- y = tile & 0xFF;\r
- SD_PlaySound(SND_USESWITCH);\r
-\r
- //\r
- // toggle whatever was linked to the switch (at tile x, y):\r
- //\r
- offset = mapbwidthtable[y]/2 + x;\r
- map = mapsegs[2] + offset;\r
- tile = *map;\r
-\r
- if (tile >= DIRARROWSTART && tile < DIRARROWEND)\r
- {\r
- // turn direction arrow:\r
- *map = arrowflip[tile-DIRARROWSTART] + DIRARROWSTART;\r
- }\r
- else\r
- {\r
- map = mapsegs[1] + offset;\r
- tile = *map;\r
- switch (tinf[tile+INTILE] & INTILE_TYPEMASK)\r
- {\r
- case INTILE_NOTHING: // no special tiles\r
- mapsegs[2][offset] ^= PLATFORMBLOCK;\r
- break;\r
-\r
- case INTILE_BRIDGE: // bridge\r
- for (yi=y; y+2 > yi; yi++)\r
- {\r
- map = mapsegs[1] + mapbwidthtable[yi]/2 + x - (yi != y);\r
- for (xi = x - (yi != y); xi < mapwidth; xi++)\r
- {\r
- tile = *map;\r
- map++;\r
- anim = tinf[tile + MANIM];\r
- if (!anim)\r
- break;\r
- tile += (Sint8)anim;\r
- RF_MemToMap(&tile, 1, xi, yi, 1, 1);\r
- }\r
- }\r
- break;\r
-\r
- case INTILE_FORCEFIELD: // active force field\r
- map = mapsegs[1];\r
- top = *map;\r
- mid = *++map;\r
- bot = *++map;\r
- map = mapsegs[1] + mapbwidthtable[y+1]/2 + x;\r
-\r
- RF_MemToMap(&top, 1, x, y++, 1, 1);\r
- while (tinf[*map+INTILE] == INTILE_DEADLY)\r
- {\r
- RF_MemToMap(&mid, 1, x, y++, 1, 1);\r
- map += mapwidth;\r
- }\r
- RF_MemToMap(&bot, 1, x, y, 1, 1);\r
- break;\r
-\r
- case INTILE_FORCEFIELDEND: // inactive force field\r
- map = mapsegs[1] + 3;\r
- top = *map;\r
- mid = *++map;\r
- bot = *++map;\r
- map = mapsegs[1] + mapbwidthtable[y+1]/2 + x;\r
-\r
- RF_MemToMap(&top, 1, x, y++, 1, 1);\r
- while (tinf[*map+INTILE] != INTILE_FORCEFIELDEND)\r
- {\r
- RF_MemToMap(&mid, 1, x, y++, 1, 1);\r
- map += mapwidth;\r
- }\r
- RF_MemToMap(&bot, 1, x, y, 1, 1);\r
- }\r
- }\r
-}\r
-\r
-//============================================================================\r
-\r
-/*\r
-===========================\r
-=\r
-= GotSandwich\r
-=\r
-===========================\r
-*/\r
-\r
-void GotSandwich(void)\r
-{\r
- SD_WaitSoundDone();\r
- SD_PlaySound(SND_QUESTITEM);\r
- CA_UpLevel(); // kinda useless without CA_CacheMarks or CA_SetGrPurge\r
- // BUG: haven't made anything purgable here, caching the pic may cause an "out of memory" crash\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 12;\r
- US_CPrint(\r
- "This is the second\n"\r
- "biggest sandwich\n"\r
- "I ever saw!\n"\r
- );\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- CA_DownLevel();\r
- gamestate.sandwichstate = 1;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= GotHook\r
-=\r
-===========================\r
-*/\r
-\r
-void GotHook(void)\r
-{\r
- SD_WaitSoundDone();\r
- SD_PlaySound(SND_QUESTITEM);\r
- CA_UpLevel(); // kinda useless without CA_CacheMarks or CA_SetGrPurge\r
- // BUG: haven't made anything purgable here, caching the pic may cause an "out of memory" crash\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 12;\r
- US_CPrint(\r
- "Wow! A rope and\n"\r
- "grappling hook!\n"\r
- "They look useful!\n"\r
- );\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- CA_DownLevel();\r
- gamestate.hookstate = 1;\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= GotPasscard\r
-=\r
-===========================\r
-*/\r
-\r
-void GotPasscard(void)\r
-{\r
- SD_WaitSoundDone();\r
- SD_PlaySound(SND_QUESTITEM);\r
- CA_UpLevel(); // kinda useless without CA_CacheMarks or CA_SetGrPurge\r
- // BUG: haven't made anything purgable here, caching the pic may cause an "out of memory" crash\r
- CA_CacheGrChunk(KEENTALK1PIC);\r
-\r
- US_CenterWindow(26, 8);\r
- VWB_DrawPic(WindowX+WindowW-48, WindowY, KEENTALK1PIC);\r
- WindowW -= 48;\r
- PrintY += 4;\r
- US_CPrint(\r
- "What's this? Cool!\n"\r
- "A passcard for\n"\r
- "the Bloogstar Rocket!\n"\r
- "(It can fly through\n"\r
- "their force field.)"\r
- );\r
- VW_UpdateScreen();\r
- VW_WaitVBL(30);\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- CA_DownLevel();\r
- gamestate.passcardstate = 1;\r
-}\r
+++ /dev/null
-%file RCK6E15.exe 109058\r
-%patch $1C 0 0 0 0\r
-%end
\ No newline at end of file
+++ /dev/null
-;=====================================\r
-;\r
-; Graphics .EQU file for .CK6\r
-; not IGRAB-ed :)\r
-;\r
-;=====================================\r
-\r
-;INCLUDE "VERSION.EQU"\r
-\r
-;\r
-; Amount of each data item\r
-;\r
-NUMFONT = 2\r
-NUMFONTM = 0\r
-NUMPICM = 3\r
-NUMTILE8 = 108\r
-NUMTILE8M = 36\r
-NUMTILE32 = 0\r
-NUMTILE32M = 0\r
-\r
-;\r
-; Amount of each item in episode 6\r
-;\r
-NUMPICS = 34\r
-NUMSPRITES = 390\r
-NUMTILE16 = 2376\r
-NUMTILE16M = 2736\r
-NUMEXTERN = 8\r
-\r
-\r
-;\r
-; File offsets for data items\r
-;\r
-STRUCTPIC = 0\r
-STRUCTPICM = 1\r
-STRUCTSPRITE = 2\r
-\r
-STARTFONT = 3\r
-STARTFONTM = (STARTFONT+NUMFONT)\r
-STARTPICS = (STARTFONTM+NUMFONTM)\r
-STARTPICM = (STARTPICS+NUMPICS)\r
-STARTSPRITES = (STARTPICM+NUMPICM)\r
-STARTTILE8 = (STARTSPRITES+NUMSPRITES)\r
-STARTTILE8M = (STARTTILE8+1)\r
-STARTTILE16 = (STARTTILE8M+1)\r
-STARTTILE16M = (STARTTILE16+NUMTILE16)\r
-STARTTILE32 = (STARTTILE16M+NUMTILE16M)\r
-STARTTILE32M = (STARTTILE32+NUMTILE32)\r
-STARTEXTERN = (STARTTILE32M+NUMTILE32M)\r
-\r
-NUMCHUNKS = (STARTEXTERN+NUMEXTERN)\r
-\r
-;\r
-; Thank you for using IGRAB!\r
-;\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef __GFX_H__\r
-#define __GFX_H__\r
-\r
-//#include "VERSION.H"\r
-\r
-//////////////////////////////////////\r
-//\r
-// Graphics .H file for .CK6\r
-// not IGRAB-ed :)\r
-//\r
-//////////////////////////////////////\r
-\r
-//\r
-// Lump creation macros\r
-//\r
-\r
-#define START_LUMP(actualname, dummyname) actualname, dummyname=actualname-1,\r
-#define END_LUMP(actualname, dummyname) dummyname, actualname=dummyname-1,\r
-\r
-//\r
-// Amount of each data item\r
-//\r
-\r
-//common numbers:\r
-#define NUMCHUNKS NUMGRCHUNKS\r
-#define NUMFONT 2\r
-#define NUMFONTM 0\r
-#define NUMPICM 3\r
-#define NUMTILE8 108 // BUG: only 104 tiles exist in EGAGRAPH!\r
-#define NUMTILE8M 36 // BUG: only 12 tiles exist in EGAGRAPH!\r
-#define NUMTILE32 0\r
-#define NUMTILE32M 0\r
-\r
-//episode-specific numbers:\r
-#define NUMPICS 34\r
-#define NUMSPRITES 390\r
-#define NUMTILE16 2376\r
-#define NUMTILE16M 2736\r
-#define NUMEXTERNS 8\r
-\r
-//\r
-// File offsets for data items\r
-//\r
-#define STRUCTPIC 0\r
-#define STRUCTPICM 1\r
-#define STRUCTSPRITE 2\r
-\r
-#define STARTFONT 3\r
-#define STARTFONTM (STARTFONT+NUMFONT)\r
-#define STARTPICS (STARTFONTM+NUMFONTM)\r
-#define STARTPICM (STARTPICS+NUMPICS)\r
-#define STARTSPRITES (STARTPICM+NUMPICM)\r
-#define STARTTILE8 (STARTSPRITES+NUMSPRITES)\r
-#define STARTTILE8M (STARTTILE8+1)\r
-#define STARTTILE16 (STARTTILE8M+1)\r
-#define STARTTILE16M (STARTTILE16+NUMTILE16)\r
-#define STARTTILE32 (STARTTILE16M+NUMTILE16M)\r
-#define STARTTILE32M (STARTTILE32+NUMTILE32)\r
-#define STARTEXTERNS (STARTTILE32M+NUMTILE32M)\r
-\r
-typedef enum {\r
- LASTFONT=STARTPICS-1,\r
-\r
- //\r
- // PICS\r
- //\r
-\r
- PADDINGPIC, // 5 (compensate for the missing Star Wars font to give the other pics the correct chunk numbers)\r
-\r
- H_END1PIC, // 6\r
- H_END2PIC, // 7\r
- H_END3PIC, // 8\r
- H_END4PIC, // 9\r
- H_END5PIC, // 10\r
-\r
- START_LUMP(CONTROLS_LUMP_START, __CONTROLSSTART)\r
- CP_MAINMENUPIC, // 11\r
- CP_NEWGAMEMENUPIC, // 12\r
- CP_LOADMENUPIC, // 13\r
- CP_SAVEMENUPIC, // 14\r
- CP_CONFIGMENUPIC, // 15\r
- CP_SOUNDMENUPIC, // 16\r
- CP_MUSICMENUPIC, // 17\r
- CP_KEYBOARDMENUPIC, // 18\r
- CP_KEYMOVEMENTPIC, // 19\r
- CP_KEYBUTTONPIC, // 20\r
- CP_JOYSTICKMENUPIC, // 21\r
- CP_OPTIONSMENUPIC, // 22\r
- CP_PADDLEWARPIC, // 23\r
- CP_QUITPIC, // 24\r
- CP_JOYSTICKPIC, // 25\r
- CP_MENUSCREENPIC, // 26\r
- END_LUMP(CONTROLS_LUMP_END, __CONTROLSEND)\r
-\r
- H_FLASHARROW1PIC, // 27\r
- H_FLASHARROW2PIC, // 28\r
-\r
- SW_BACKGROUNDPIC, // 33\r
- TITLEPICPIC, // 34\r
- KEENTALK1PIC, // 35\r
- KEENTALK2PIC, // 36\r
- KEENCOUNT1PIC, // 37\r
- KEENCOUNT2PIC, // 38\r
- KEENCOUNT3PIC, // 39\r
- KEENCOUNT4PIC, // 40\r
- KEENCOUNT5PIC, // 41\r
- KEENCOUNT6PIC, // 42\r
-\r
- //\r
- // MASKED PICS\r
- //\r
-\r
- CP_MENUMASKPICM, // 43\r
- CORDPICM, // 44\r
- METALPOLEPICM, // 45\r
-\r
- //\r
- // SPRITES\r
- //\r
-\r
- START_LUMP(PADDLE_LUMP_START, __PADDLESTART)\r
- PADDLESPR, // 46\r
- BALLSPR, // 47\r
- BALL1PIXELTOTHERIGHTSPR, // 48\r
- BALL2PIXELSTOTHERIGHTSPR, // 49\r
- BALL3PIXELSTOTHERIGHTSPR, // 50\r
- END_LUMP(PADDLE_LUMP_END, __PADDLEEND)\r
-\r
- DEMOPLAQUESPR, // 51\r
-\r
- START_LUMP(KEEN_LUMP_START, __KEENSTART)\r
- KEENSTANDRSPR, // 52\r
- KEENRUNR1SPR, // 53\r
- KEENRUNR2SPR, // 54\r
- KEENRUNR3SPR, // 55\r
- KEENRUNR4SPR, // 56\r
- KEENJUMPR1SPR, // 57\r
- KEENJUMPR2SPR, // 58\r
- KEENJUMPR3SPR, // 59\r
- KEENSTANDLSPR, // 60\r
- KEENRUNL1SPR, // 61\r
- KEENRUNL2SPR, // 62\r
- KEENRUNL3SPR, // 63\r
- KEENRUNL4SPR, // 64\r
- KEENJUMPL1SPR, // 65\r
- KEENJUMPL2SPR, // 66\r
- KEENJUMPL3SPR, // 67\r
- KEENLOOKUSPR, // 68\r
- KEENWAITR1SPR, // 69\r
- KEENWAITR2SPR, // 70\r
- KEENWAITR3SPR, // 71\r
- KEENSITREAD1SPR, // 72\r
- KEENSITREAD2SPR, // 73\r
- KEENSITREAD3SPR, // 74\r
- KEENSITREAD4SPR, // 75\r
- KEENREAD1SPR, // 76\r
- KEENREAD2SPR, // 77\r
- KEENREAD3SPR, // 78\r
- KEENSTOPREAD1SPR, // 79\r
- KEENSTOPREAD2SPR, // 80\r
- KEENLOOKD1SPR, // 81\r
- KEENLOOKD2SPR, // 82\r
- KEENDIE1SPR, // 83\r
- KEENDIE2SPR, // 84\r
- KEENSTUNSPR, // 85\r
- STUNSTARS1SPR, // 86\r
- STUNSTARS2SPR, // 87\r
- STUNSTARS3SPR, // 88\r
- KEENSHOOTLSPR, // 89\r
- KEENJLSHOOTLSPR, // 90\r
- KEENJSHOOTDSPR, // 91\r
- KEENJSHOOTUSPR, // 92\r
- KEENSHOOTUSPR, // 93\r
- KEENSHOOTRSPR, // 94\r
- KEENJRSHOOTRSPR, // 95\r
- STUN1SPR, // 96\r
- STUN2SPR, // 97\r
- STUN3SPR, // 98\r
- STUN4SPR, // 99\r
- STUNHIT1SPR, // 100\r
- STUNHIT2SPR, // 101\r
- KEENSHINNYR1SPR, // 102\r
- KEENSHINNYR2SPR, // 103\r
- KEENSHINNYR3SPR, // 104\r
- KEENSLIDED1SPR, // 105\r
- KEENSLIDED2SPR, // 106\r
- KEENSLIDED3SPR, // 107\r
- KEENSLIDED4SPR, // 108\r
- KEENSHINNYL1SPR, // 109\r
- KEENSHINNYL2SPR, // 110\r
- KEENSHINNYL3SPR, // 111\r
- KEENPLSHOOTUSPR, // 112\r
- KEENPRSHOOTUSPR, // 113\r
- KEENPRSHOOTDSPR, // 114\r
- KEENPLSHOOTDSPR, // 115\r
- KEENPSHOOTLSPR, // 116\r
- KEENPSHOOTRSPR, // 117\r
- KEENENTER1SPR, // 118\r
- KEENENTER2SPR, // 119\r
- KEENENTER3SPR, // 120\r
- KEENENTER4SPR, // 121\r
- KEENENTER5SPR, // 122\r
- KEENHANGLSPR, // 123\r
- KEENHANGRSPR, // 124\r
- KEENCLIMBEDGEL1SPR, // 125\r
- KEENCLIMBEDGEL2SPR, // 126\r
- KEENCLIMBEDGEL3SPR, // 127\r
- KEENCLIMBEDGEL4SPR, // 128\r
- KEENCLIMBEDGER1SPR, // 129\r
- KEENCLIMBEDGER2SPR, // 130\r
- KEENCLIMBEDGER3SPR, // 131\r
- KEENCLIMBEDGER4SPR, // 132\r
- KEENPOGOR1SPR, // 133\r
- KEENPOGOR2SPR, // 134\r
- KEENPOGOL1SPR, // 135\r
- KEENPOGOL2SPR, // 136\r
- BONUS100UPSPR, // 137\r
- BONUS100SPR, // 138\r
- BONUS200SPR, // 139\r
- BONUS500SPR, // 140\r
- BONUS1000SPR, // 141\r
- BONUS2000SPR, // 142\r
- BONUS5000SPR, // 143\r
- BONUS1UPSPR, // 144\r
- BONUSCLIPSPR, // 145\r
- VIVASPLASH1SPR, // 146\r
- VIVASPLASH2SPR, // 147\r
- VIVASPLASH3SPR, // 148\r
- VIVASPLASH4SPR, // 149\r
- END_LUMP(KEEN_LUMP_END, __KEENEND)\r
-\r
- START_LUMP(SUGAR1_LUMP_START, __SUGAR1START)\r
- SUGAR1ASPR, // 150\r
- SUGAR1BSPR, // 151\r
- END_LUMP(SUGAR1_LUMP_END, __SUGAR1END)\r
-\r
- START_LUMP(SUGAR2_LUMP_START, __SUGAR2START)\r
- SUGAR2ASPR, // 152\r
- SUGAR2BSPR, // 153\r
- END_LUMP(SUGAR2_LUMP_END, __SUGAR2END)\r
-\r
- START_LUMP(SUGAR3_LUMP_START, __SUGAR3START)\r
- SUGAR3ASPR, // 154\r
- SUGAR3BSPR, // 155\r
- END_LUMP(SUGAR3_LUMP_END, __SUGAR3END)\r
-\r
- START_LUMP(SUGAR4_LUMP_START, __SUGAR4START)\r
- SUGAR4ASPR, // 156\r
- SUGAR4BSPR, // 157\r
- END_LUMP(SUGAR4_LUMP_END, __SUGAR4END)\r
-\r
- START_LUMP(SUGAR5_LUMP_START, __SUGAR5START)\r
- SUGAR5ASPR, // 158\r
- SUGAR5BSPR, // 159\r
- END_LUMP(SUGAR5_LUMP_END, __SUGAR5END)\r
-\r
- START_LUMP(SUGAR6_LUMP_START, __SUGAR6START)\r
- SUGAR6ASPR, // 160\r
- SUGAR6BSPR, // 161\r
- END_LUMP(SUGAR6_LUMP_END, __SUGAR6END)\r
-\r
- START_LUMP(ONEUP_LUMP_START, __ONEUPSTART)\r
- ONEUPASPR, // 162\r
- ONEUPBSPR, // 163\r
- END_LUMP(ONEUP_LUMP_END, __ONEUPEND)\r
-\r
- START_LUMP(KEYGEM_LUMP_START, __KEYGEMSTART)\r
- REDGEM1SPR, // 164\r
- REDGEM2SPR, // 165\r
- YELLOWGEM1SPR, // 166\r
- YELLOWGEM2SPR, // 167\r
- BLUEGEM1SPR, // 168\r
- BLUEGEM2SPR, // 169\r
- GREENGEM1SPR, // 170\r
- GREENGEM2SPR, // 171\r
- BONUSGEMSPR, // 172\r
- END_LUMP(KEYGEM_LUMP_END, __KEYGEMEND)\r
-\r
- START_LUMP(AMMO_LUMP_START, __AMMOSTART)\r
- STUNCLIP1SPR, // 173\r
- STUNCLIP2SPR, // 174\r
- END_LUMP(AMMO_LUMP_END, __AMMOEND)\r
-\r
- SCOREBOXSPR, // 175\r
-\r
- START_LUMP(LASER_LUMP_START, __LASERSTART)\r
- LASER1SPR, // 176\r
- LASER2SPR, // 177\r
- LASER3SPR, // 178\r
- LASER4SPR, // 179\r
- LASERHIT1SPR, // 180\r
- LASERHIT2SPR, // 181\r
- END_LUMP(LASER_LUMP_END, __LASEREND)\r
-\r
- START_LUMP(SANDWICH_LUMP_START, __SANDWICHSTART)\r
- SANDWICHSPR, // 182\r
- END_LUMP(SANDWICH_LUMP_END, __SANDWICHEND)\r
-\r
- START_LUMP(HOOK_LUMP_START, __ROPESTART)\r
- HOOKSPR, // 183\r
- END_LUMP(HOOK_LUMP_END, __ROPEEND)\r
-\r
- START_LUMP(WORLDKEEN_LUMP_START, __WORLDKEENSTART)\r
- WORLDKEENL1SPR, // 184\r
- WORLDKEENL2SPR, // 185\r
- WORLDKEENL3SPR, // 186\r
- WORLDKEENR1SPR, // 187\r
- WORLDKEENR2SPR, // 188\r
- WORLDKEENR3SPR, // 189\r
- WORLDKEENU1SPR, // 190\r
- WORLDKEENU2SPR, // 191\r
- WORLDKEENU3SPR, // 192\r
- WORLDKEEND1SPR, // 193\r
- WORLDKEEND2SPR, // 194\r
- WORLDKEEND3SPR, // 195\r
- WORLDKEENDR1SPR, // 196\r
- WORLDKEENDR2SPR, // 197\r
- WORLDKEENDR3SPR, // 198\r
- WORLDKEENDL1SPR, // 199\r
- WORLDKEENDL2SPR, // 200\r
- WORLDKEENDL3SPR, // 201\r
- WORLDKEENUL1SPR, // 202\r
- WORLDKEENUL2SPR, // 203\r
- WORLDKEENUL3SPR, // 204\r
- WORLDKEENUR1SPR, // 205\r
- WORLDKEENUR2SPR, // 206\r
- WORLDKEENUR3SPR, // 207\r
- WORLDKEENWAVE1SPR, // 208\r
- WORLDKEENWAVE2SPR, // 209\r
- ROCKETSPR, // 210\r
- ROCKETFLY1SPR, // 211\r
- ROCKETFLY2SPR, // 212\r
- SATELLITE1SPR, // 213\r
- SATELLITE2SPR, // 214\r
- SATELLITE3SPR, // 215\r
- SATELLITE4SPR, // 216\r
- GRABBITER1SPR, // 217\r
- GRABBITER2SPR, // 218\r
- GRABBITERSLEEP1SPR, // 219\r
- GRABBITERSLEEP2SPR, // 220\r
- WORLDKEENTRHOW1SPR, // 221\r
- WORLDKEENTRHOW2SPR, // 222\r
- WORLDKEENCLIMB1SPR, // 223\r
- WORLDKEENCLIMB2SPR, // 224\r
- ROPETHROW1SPR, // 225\r
- ROPETHROW2SPR, // 226\r
- WORLDKEENHANGSPR, // 227\r
- FLAGFLIP1SPR, // 228\r
- FLAGFLIP2SPR, // 229\r
- FLAGFLIP3SPR, // 230\r
- FLAGFLIP4SPR, // 231\r
- FLAGFLIP5SPR, // 232\r
- FLAGFALL1SPR, // 233\r
- FLAGFALL2SPR, // 234\r
- FLAGFLAP1SPR, // 235\r
- FLAGFLAP2SPR, // 236\r
- FLAGFLAP3SPR, // 237\r
- FLAGFLAP4SPR, // 238\r
- END_LUMP(WORLDKEEN_LUMP_END, __WORLDKEENEND)\r
-\r
- START_LUMP(FLEEX_LUMP_START, __FLEEXSTART)\r
- FLEEXWALKR1SPR, // 239\r
- FLEEXWALKR2SPR, // 240\r
- FLEEXWALKL1SPR, // 241\r
- FLEEXWALKL2SPR, // 242\r
- FLEEXLOOK1SPR, // 243\r
- FLEEXLOOK2SPR, // 244\r
- FLEEXSTUNSPR, // 245\r
- END_LUMP(FLEEX_LUMP_END, __FLEEXEND)\r
-\r
- START_LUMP(CEILICK_LUMP_START, __CEILICKSTART)\r
- CEILICK1SPR, // 246\r
- CEILICK2SPR, // 247\r
- TONGUE1SPR, // 248\r
- TONGUE2SPR, // 249\r
- TONGUE3SPR, // 250\r
- TONGUE4SPR, // 251\r
- TONGUE5SPR, // 252\r
- CEILICKSTUNSPR, // 253\r
- END_LUMP(CEILICK_LUMP_END, __CEILICKEND)\r
-\r
- START_LUMP(BLOOGUARD_LUMP_START, __BLOOGUARDSTART)\r
- BLOOGUARDWALKL1SPR, // 254\r
- BLOOGUARDWALKL2SPR, // 255\r
- BLOOGUARDWALKL3SPR, // 256\r
- BLOOGUARDWALKL4SPR, // 257\r
- BLOOGUARDWALKR1SPR, // 258\r
- BLOOGUARDWALKR2SPR, // 259\r
- BLOOGUARDWALKR3SPR, // 260\r
- BLOOGUARDWALKR4SPR, // 261\r
- BLOOGUARDSWINGL1SPR, // 262\r
- BLOOGUARDSWINGL2SPR, // 263\r
- BLOOGUARDSWINGL3SPR, // 264\r
- BLOOGUARDSWINGR1SPR, // 265\r
- BLOOGUARDSWINGR2SPR, // 266\r
- BLOOGUARDSWINGR3SPR, // 267\r
- BLOOGUARDSTUNSPR, // 268\r
- END_LUMP(BLOOGUARD_LUMP_END, __BLOOGUARDEND)\r
-\r
- START_LUMP(BIPSHIP_LUMP_START, __BIPSHIPSTART)\r
- BIPSHIPRSPR, // 269\r
- BIPSHIPRTURN1SPR, // 270\r
- BIPSHIPRTURN2SPR, // 271\r
- BIPSHIPRTURN3SPR, // 272\r
- BIPSHIPRTURN4SPR, // 273\r
- BIPSHIPLSPR, // 274\r
- BIPSHIPLTURN1SPR, // 275\r
- BIPSHIPLTURN2SPR, // 276\r
- BIPSHIPLTURN3SPR, // 277\r
- BIPSHIPLTURN4SPR, // 278\r
- BIPSHIPEXPLODE1SPR, // 279\r
- BIPSHIPEXPLODE2SPR, // 280\r
- BIPSHIPEXPLODE3SPR, // 281\r
- BIPSHIPEXPLODE4SPR, // 282\r
- BIPSHIPEXPLODE5SPR, // 283\r
- BIPSHIPSHOTSPR, // 284\r
- END_LUMP(BIPSHIP_LUMP_END, __BIPSHIPEND)\r
-\r
- START_LUMP(BABOBBA_LUMP_START, __BABOBBASTART)\r
- BABOBBAL1SPR, // 285\r
- BABOBBAL2SPR, // 286\r
- BABOBBAL3SPR, // 287\r
- BABOBBAR1SPR, // 288\r
- BABOBBAR2SPR, // 289\r
- BABOBBAR3SPR, // 290\r
- BABOBBASHOT1SPR, // 291\r
- BABOBBASHOT2SPR, // 292\r
- BABOBBASTUNSPR, // 293\r
- BABOBBASLEEP1SPR, // 294\r
- BABOBBASLEEP2SPR, // 295\r
- BABOBBASLEEP3SPR, // 296\r
- BABOBBASLEEP4SPR, // 297\r
- END_LUMP(BABOBBA_LUMP_END, __BABOBBAEND)\r
-\r
- START_LUMP(NOSPIKE_LUMP_START, __NOSPIKESTART)\r
- NOSPIKESTANDSPR, // 298\r
- NOSPIKERUNR1SPR, // 299\r
- NOSPIKERUNR2SPR, // 300\r
- NOSPIKERUNR3SPR, // 301\r
- NOSPIKERUNR4SPR, // 302\r
- NOSPIKERUNL1SPR, // 303\r
- NOSPIKERUNL2SPR, // 304\r
- NOSPIKERUNL3SPR, // 305\r
- NOSPIKERUNL4SPR, // 306\r
- NOSPIKEWALKR1SPR, // 307\r
- NOSPIKEWALKR2SPR, // 308\r
- NOSPIKEWALKR3SPR, // 309\r
- NOSPIKEWALKR4SPR, // 310\r
- NOSPIKEWALKL1SPR, // 311\r
- NOSPIKEWALKL2SPR, // 312\r
- NOSPIKEWALKL3SPR, // 313\r
- NOSPIKEWALKL4SPR, // 314\r
- NOSPIKESTUNSPR, // 315\r
- QUESTIONMARKSPR, // 316\r
- END_LUMP(NOSPIKE_LUMP_END, __NOSPIKEEND)\r
-\r
- START_LUMP(FLECT_LUMP_START, __FLECTSTART)\r
- FLECTSTANDSPR, // 317\r
- FLECTSTANDRSPR, // 318\r
- FLECTWALKR1SPR, // 319\r
- FLECTWALKR2SPR, // 320\r
- FLECTWALKR3SPR, // 321\r
- FLECTWALKR4SPR, // 322\r
- FLECTSTANDLSPR, // 323\r
- FLECTWALKL1SPR, // 324\r
- FLECTWALKL2SPR, // 325\r
- FLECTWALKL3SPR, // 326\r
- FLECTWALKL4SPR, // 327\r
- FLECTSTUNSPR, // 328\r
- END_LUMP(FLECT_LUMP_END, __FLECTEND)\r
-\r
- START_LUMP(ORBATRIX_LUMP_START, __ORBATRIXSTART)\r
- ORBATRIX1SPR, // 329\r
- ORBATRIX2SPR, // 330\r
- ORBATRIX3SPR, // 331\r
- ORBATRIX4SPR, // 332\r
- ORBATRIXL1SPR, // 333\r
- ORBATRIXL2SPR, // 334\r
- ORBATRIXR1SPR, // 335\r
- ORBATRIXR2SPR, // 336\r
- ORBATRIXSPIN1SPR, // 337\r
- ORBATRIXSPIN2SPR, // 338\r
- ORBATRIXSPIN3SPR, // 339\r
- ORBATRIXSPIN4SPR, // 340\r
- ORBATRIXCURLSPR, // 341\r
- END_LUMP(ORBATRIX_LUMP_END, __ORBATRIXEND)\r
-\r
- START_LUMP(BLOOG_LUMP_START, __BLOOGSTART)\r
- BLOOGWALKR1SPR, // 342\r
- BLOOGWALKR2SPR, // 343\r
- BLOOGWALKR3SPR, // 344\r
- BLOOGWALKR4SPR, // 345\r
- BLOOGWALKL1SPR, // 346\r
- BLOOGWALKL2SPR, // 347\r
- BLOOGWALKL3SPR, // 348\r
- BLOOGWALKL4SPR, // 349\r
- BLOOGSTUNSPR, // 350\r
- END_LUMP(BLOOG_LUMP_END, __BLOOGEND)\r
-\r
- START_LUMP(RBLOOGLET_LUMP_START, __RBLOOGLETSTART)\r
- RBLOOGLETWALKR1SPR, // 351\r
- RBLOOGLETWALKR2SPR, // 352\r
- RBLOOGLETWALKR3SPR, // 353\r
- RBLOOGLETWALKR4SPR, // 354\r
- RBLOOGLETWALKL1SPR, // 355\r
- RBLOOGLETWALKL2SPR, // 356\r
- RBLOOGLETWALKL3SPR, // 357\r
- RBLOOGLETWALKL4SPR, // 358\r
- RBLOOGLETSTUNSPR, // 359\r
- END_LUMP(RBLOOGLET_LUMP_END, __RBLOOGLETEND)\r
-\r
- START_LUMP(YBLOOGLET_LUMP_START, __YBLOOGLETSTART)\r
- YBLOOGLETWALKR1SPR, // 360\r
- YBLOOGLETWALKR2SPR, // 361\r
- YBLOOGLETWALKR3SPR, // 362\r
- YBLOOGLETWALKR4SPR, // 363\r
- YBLOOGLETWALKL1SPR, // 364\r
- YBLOOGLETWALKL2SPR, // 365\r
- YBLOOGLETWALKL3SPR, // 366\r
- YBLOOGLETWALKL4SPR, // 367\r
- YBLOOGLETSTUNSPR, // 368\r
- END_LUMP(YBLOOGLET_LUMP_END, __YBLOOGLETEND)\r
-\r
- START_LUMP(BBLOOGLET_LUMP_START, __BBLOOGLETSTART)\r
- BBLOOGLETWALKR1SPR, // 369\r
- BBLOOGLETWALKR2SPR, // 370\r
- BBLOOGLETWALKR3SPR, // 371\r
- BBLOOGLETWALKR4SPR, // 372\r
- BBLOOGLETWALKL1SPR, // 373\r
- BBLOOGLETWALKL2SPR, // 374\r
- BBLOOGLETWALKL3SPR, // 375\r
- BBLOOGLETWALKL4SPR, // 376\r
- BBLOOGLETSTUNSPR, // 377\r
- END_LUMP(BBLOOGLET_LUMP_END, __BBLOOGLETEND)\r
-\r
- START_LUMP(GBLOOGLET_LUMP_START, __GBLOOGLETSTART)\r
- GBLOOGLETWALKR1SPR, // 378\r
- GBLOOGLETWALKR2SPR, // 379\r
- GBLOOGLETWALKR3SPR, // 380\r
- GBLOOGLETWALKR4SPR, // 381\r
- GBLOOGLETWALKL1SPR, // 382\r
- GBLOOGLETWALKL2SPR, // 383\r
- GBLOOGLETWALKL3SPR, // 384\r
- GBLOOGLETWALKL4SPR, // 385\r
- GBLOOGLETSTUNSPR, // 386\r
- END_LUMP(GBLOOGLET_LUMP_END, __GBLOOGLETEND)\r
-\r
- START_LUMP(GIK_LUMP_START, __GIKSTART)\r
- GIKWALKR1SPR, // 387\r
- GIKWALKR2SPR, // 388\r
- GIKWALKR3SPR, // 389\r
- GIKWALKL1SPR, // 390\r
- GIKWALKL2SPR, // 391\r
- GIKWALKL3SPR, // 392\r
- GIKJUMPLSPR, // 393\r
- GIKJUMPRSPR, // 394\r
- GIKSLIDER1SPR, // 395\r
- GIKSLIDER2SPR, // 396\r
- GIKSLIDEL1SPR, // 397\r
- GIKSLIDEL2SPR, // 398\r
- END_LUMP(GIK_LUMP_END, __GIKEND)\r
-\r
- START_LUMP(BLORB_LUMP_START, __BLORBSTART)\r
- BLORB1SPR, // 399\r
- BLORB2SPR, // 400\r
- BLORB3SPR, // 401\r
- END_LUMP(BLORB_LUMP_END, __BLORBEND)\r
-\r
- START_LUMP(BOBBA_LUMP_START, __BOBBASTART)\r
- BOBBAL1SPR, // 402\r
- BOBBAL2SPR, // 403\r
- BOBBAL3SPR, // 404\r
- BOBBAR1SPR, // 405\r
- BOBBAR2SPR, // 406\r
- BOBBAR3SPR, // 407\r
- BOBBASHOT1SPR, // 408\r
- BOBBASHOT2SPR, // 409\r
- BOBBASHOT3SPR, // 410\r
- BOBBASHOT4SPR, // 411\r
- BOBBASHOT5SPR, // 412\r
- BOBBASHOT6SPR, // 413\r
- END_LUMP(BOBBA_LUMP_END, __BOBBAEND)\r
-\r
- START_LUMP(BIP_LUMP_START, __BIPSTART)\r
- BIPSTANDSPR, // 414\r
- BIPWALKR1SPR, // 415\r
- BIPWALKR2SPR, // 416\r
- BIPWALKR3SPR, // 417\r
- BIPWALKR4SPR, // 418\r
- BIPWALKL1SPR, // 419\r
- BIPWALKL2SPR, // 420\r
- BIPWALKL3SPR, // 421\r
- BIPWALKL4SPR, // 422\r
- END_LUMP(BIP_LUMP_END, __BIPEND)\r
-\r
- START_LUMP(BIPSQUISHED_LUMP_START, __BIPSQUISHEDSTART)\r
- BIPSQUISHEDSPR, // 423\r
- END_LUMP(BIPSQUISHED_LUMP_END, __BIPSQUISHEDEND)\r
-\r
- START_LUMP(PLATFORM_LUMP_START, __PLATFORMSTART)\r
- PLATFORMSPR, // 424\r
- PLATBIP1SPR, // 425\r
- PLATBIP2SPR, // 426\r
- PLATBIP3SPR, // 427\r
- PLATBIP4SPR, // 428\r
- PLATBIP5SPR, // 429\r
- PLATBIP6SPR, // 430\r
- PLATBIP7SPR, // 431\r
- PLATBIP8SPR, // 432\r
- END_LUMP(PLATFORM_LUMP_END, __PLATFORMEND)\r
-\r
- START_LUMP(MOLLY_LUMP_START, __MOLLYSTART)\r
- MOLLY1SPR, // 433\r
- MOLLY2SPR, // 434\r
- END_LUMP(MOLLY_LUMP_END, __MOLLYEND)\r
-\r
- START_LUMP(PASSCARD_LUMP_START, __PASSCARDSTART)\r
- PASSCARDSPR, // 435\r
- END_LUMP(PASSCARD_LUMP_END, __PASSCARDEND)\r
-\r
- //\r
- // TILES (these don't need names)\r
- //\r
-\r
- LASTTILE=STARTEXTERNS-1,\r
-\r
- //\r
- // EXTERNS\r
- //\r
-\r
- T_ENDART, // 5550\r
-\r
- ORDERSCREEN, // 5551\r
- OUTOFMEM, // 5554\r
-\r
- //demos\r
- DEMO0, // 5555\r
- DEMO1, // 5556\r
- DEMO2, // 5557\r
- DEMO3, // 5558\r
- DEMO4, // 5559\r
-\r
- NUMGRCHUNKS\r
-} graphicnums;\r
-\r
-#undef START_LUMP\r
-#undef END_LUMP\r
-\r
-#endif //__GFX_H__
\ No newline at end of file
+++ /dev/null
-;\r
-; Equates for all .ASM files\r
-;\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-INCLUDE "GFXC_CK6.EQU"\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-CGAGR = 1\r
-EGAGR = 2\r
-VGAGR = 3\r
-\r
-GRMODE = CGAGR\r
-PROFILE = 0 ; 1=keep stats on tile drawing\r
-\r
-SC_INDEX = 03C4h\r
-SC_RESET = 0\r
-SC_CLOCK = 1\r
-SC_MAPMASK = 2\r
-SC_CHARMAP = 3\r
-SC_MEMMODE = 4\r
-\r
-CRTC_INDEX = 03D4h\r
-CRTC_H_TOTAL = 0\r
-CRTC_H_DISPEND = 1\r
-CRTC_H_BLANK = 2\r
-CRTC_H_ENDBLANK = 3\r
-CRTC_H_RETRACE = 4\r
-CRTC_H_ENDRETRACE = 5\r
-CRTC_V_TOTAL = 6\r
-CRTC_OVERFLOW = 7\r
-CRTC_ROWSCAN = 8\r
-CRTC_MAXSCANLINE = 9\r
-CRTC_CURSORSTART = 10\r
-CRTC_CURSOREND = 11\r
-CRTC_STARTHIGH = 12\r
-CRTC_STARTLOW = 13\r
-CRTC_CURSORHIGH = 14\r
-CRTC_CURSORLOW = 15\r
-CRTC_V_RETRACE = 16\r
-CRTC_V_ENDRETRACE = 17\r
-CRTC_V_DISPEND = 18\r
-CRTC_OFFSET = 19\r
-CRTC_UNDERLINE = 20\r
-CRTC_V_BLANK = 21\r
-CRTC_V_ENDBLANK = 22\r
-CRTC_MODE = 23\r
-CRTC_LINECOMPARE = 24\r
-\r
-\r
-GC_INDEX = 03CEh\r
-GC_SETRESET = 0\r
-GC_ENABLESETRESET = 1\r
-GC_COLORCOMPARE = 2\r
-GC_DATAROTATE = 3\r
-GC_READMAP = 4\r
-GC_MODE = 5\r
-GC_MISCELLANEOUS = 6\r
-GC_COLORDONTCARE = 7\r
-GC_BITMASK = 8\r
-\r
-ATR_INDEX = 03c0h\r
-ATR_MODE = 16\r
-ATR_OVERSCAN = 17\r
-ATR_COLORPLANEENABLE = 18\r
-ATR_PELPAN = 19\r
-ATR_COLORSELECT = 20\r
-\r
-STATUS_REGISTER_1 = 03dah\r
-\r
-\r
-MACRO WORDOUT\r
- out dx,ax\r
-ENDM\r
-\r
-if 0\r
-\r
-MACRO WORDOUT\r
- out dx,al\r
- inc dx\r
- xchg al,ah\r
- out dx,al\r
- dec dx\r
- xchg al,ah\r
-ENDM\r
-\r
-endif\r
-\r
-UPDATEWIDE = 22\r
-UPDATEHIGH = 14\r
-\r
-;\r
-; tile info offsets from segment tinf\r
-;\r
-\r
-ANIM = 402\r
-SPEED = (ANIM+NUMTILE16)\r
-\r
-NORTHWALL = (SPEED+NUMTILE16)\r
-EASTWALL = (NORTHWALL+NUMTILE16M)\r
-SOUTHWALL = (EASTWALL+NUMTILE16M)\r
-WESTWALL = (SOUTHWALL+NUMTILE16M)\r
-MANIM = (WESTWALL+NUMTILE16M)\r
-INTILE = (MANIM+NUMTILE16M)\r
-MSPEED = (INTILE+NUMTILE16M)\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-SCREENWIDTH = 64\r
-ENDIF\r
-IFE GRMODE-CGAGR\r
-SCREENWIDTH = 128\r
-ENDIF\r
+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_GLOB.H\r
-\r
-\r
-#include <ALLOC.H>\r
-#include <CTYPE.H>\r
-#include <DOS.H>\r
-#include <ERRNO.H>\r
-#include <FCNTL.H>\r
-#include <IO.H>\r
-#include <MEM.H>\r
-#include <PROCESS.H>\r
-#include <STDIO.H>\r
-#include <STDLIB.H>\r
-#include <STRING.H>\r
-#include <SYS\STAT.H>\r
-\r
-#define __ID_GLOB__\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define KEEN\r
-#define KEEN6\r
-\r
-#define EXTENSION "CK6"\r
-\r
-extern char far introscn;\r
-\r
-#include "GFXC_CK6.H"\r
-#include "AUDIOCK6.H"\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define TEXTGR 0\r
-#define CGAGR 1\r
-#define EGAGR 2\r
-#define VGAGR 3\r
-\r
-#define GRMODE CGAGR\r
-\r
-#if GRMODE == EGAGR\r
-#define GREXT "EGA"\r
-#endif\r
-#if GRMODE == CGAGR\r
-#define GREXT "CGA"\r
-#endif\r
-\r
-//#define PROFILE\r
-\r
-//\r
-// ID Engine\r
-// Types.h - Generic types, #defines, etc.\r
-// v1.0d1\r
-//\r
-\r
-#ifndef __TYPES__\r
-#define __TYPES__\r
-\r
-typedef enum {false,true} boolean;\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long longword;\r
-typedef byte * Ptr;\r
-\r
-typedef struct\r
- {\r
- int x,y;\r
- } Point;\r
-typedef struct\r
- {\r
- Point ul,lr;\r
- } Rect;\r
-\r
-#define nil ((void *)0)\r
-\r
-#endif\r
-\r
-#include "ID_MM.H"\r
-#include "ID_CA.H"\r
-#include "ID_VW.H"\r
-#include "ID_RF.H"\r
-#include "ID_IN.H"\r
-#include "ID_SD.H"\r
-#include "ID_US.H"\r
-\r
-\r
-void Quit (char *error); // defined in user program\r
-\r
+++ /dev/null
-%file RCK6C15.exe 102166\r
-%patch $1C 0 0 0 0\r
-%end
\ No newline at end of file
+++ /dev/null
-@echo off\r
-rem bcc makeobj.c\r
-\r
-makeobj c AUDIODCT.CK4 ..\keen4\ck4adict.obj _audiodict\r
-makeobj f AUDIOHED.CK4 ..\keen4\ck4ahead.obj _AudioHeader _audiohead\r
-makeobj c EGADICT.CK4 ..\keen4\ck4edict.obj _EGAdict\r
-makeobj f EGAHEAD.CK4 ..\keen4\ck4ehead.obj EGA_grafixheader _EGAhead\r
-makeobj c CGADICT.CK4 ..\keen4\ck4cdict.obj _CGAdict\r
-makeobj f CGAHEAD.CK4 ..\keen4\ck4chead.obj CGA_grafixheader _CGAhead\r
-makeobj f MAPHEAD.CK4 ..\keen4\ck4mhead.obj MapHeader _maphead\r
-makeobj f introscn.CK4 ..\keen4\ck4intro.obj _introscn\r
-\r
-makeobj c AUDIODCT.CK5 ..\keen5\ck5adict.obj _audiodict\r
-makeobj f AUDIOHED.CK5 ..\keen5\ck5ahead.obj _AudioHeader _audiohead\r
-makeobj c EGADICT.CK5 ..\keen5\ck5edict.obj _EGAdict\r
-makeobj f EGAHEAD.CK5 ..\keen5\ck5ehead.obj EGA_grafixheader _EGAhead\r
-makeobj c CGADICT.CK5 ..\keen5\ck5cdict.obj _CGAdict\r
-makeobj f CGAHEAD.CK5 ..\keen5\ck5chead.obj CGA_grafixheader _CGAhead\r
-makeobj f MAPHEAD.CK5 ..\keen5\ck5mhead.obj MapHeader _maphead\r
-makeobj f introscn.CK5 ..\keen5\ck5intro.obj _introscn\r
-\r
-makeobj c AUDIODCT.CK6 ..\keen6\ck6adict.obj _audiodict\r
-makeobj f AUDIOHED.CK6 ..\keen6\ck6ahead.obj _AudioHeader _audiohead\r
-makeobj c EGADICT.CK6 ..\keen6\ck6edict.obj _EGAdict\r
-makeobj f EGAHEAD.CK6 ..\keen6\ck6ehead.obj EGA_grafixheader _EGAhead\r
-makeobj c CGADICT.CK6 ..\keen6\ck6cdict.obj _CGAdict\r
-makeobj f CGAHEAD.CK6 ..\keen6\ck6chead.obj CGA_grafixheader _CGAhead\r
-makeobj f MAPHEAD.CK6 ..\keen6\ck6mhead.obj MapHeader _maphead\r
-makeobj f introscn.CK6 ..\keen6\ck6intro.obj _introscn\r
-makeobj f orderscn.CK6 ..\keen6\ck6order.obj _orderscn\r
+++ /dev/null
-/*\r
-** makeobj.c\r
-**\r
-**---------------------------------------------------------------------------\r
-** Copyright 2014 Braden Obrzut\r
-** All rights reserved.\r
-**\r
-** Redistribution and use in source and binary forms, with or without\r
-** modification, are permitted provided that the following conditions\r
-** are met:\r
-**\r
-** 1. Redistributions of source code must retain the above copyright\r
-** notice, this list of conditions and the following disclaimer.\r
-** 2. Redistributions in binary form must reproduce the above copyright\r
-** notice, this list of conditions and the following disclaimer in the\r
-** documentation and/or other materials provided with the distribution.\r
-** 3. The name of the author may not be used to endorse or promote products\r
-** derived from this software without specific prior written permission.\r
-**\r
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
-** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
-** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
-** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
-** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
-** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
-** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-**---------------------------------------------------------------------------\r
-**\r
-** This is a throwaway program to create OMF object files for DOS. It also\r
-** extracts the object files. It should be compatible with MakeOBJ by John\r
-** Romero except where we calculate the checksum correctly.\r
-**\r
-*/\r
-\r
-#include <stdio.h>\r
-#include <malloc.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <stdlib.h>\r
-\r
-#pragma pack(1)\r
-typedef struct\r
-{\r
- unsigned char type;\r
- unsigned short len;\r
-} SegHeader;\r
-\r
-typedef struct\r
-{\r
- unsigned short len;\r
- unsigned char name;\r
- unsigned char classname;\r
- unsigned char overlayname;\r
-} SegDef;\r
-#pragma pack()\r
-\r
-const char* ReadFile(const char* fn, int *size)\r
-{\r
- char* out;\r
-\r
- FILE* f = fopen(fn, "rb");\r
- fseek(f, 0, SEEK_END);\r
- *size = ftell(f);\r
- out = (char*)malloc(*size);\r
- fseek(f, 0, SEEK_SET);\r
-\r
- fread(out, *size, 1, f);\r
-\r
- fclose(f);\r
-\r
- return out;\r
-}\r
-\r
-void WriteFile(const char* fn, const char *data, int size)\r
-{\r
- FILE* f = fopen(fn, "wb");\r
- fwrite(data, size, 1, f);\r
- fclose(f);\r
-}\r
-\r
-void Extract(const char* infn)\r
-{\r
- const char* in;\r
- const char* start;\r
- const char* p;\r
- char outfn[16];\r
- char str[256];\r
- char *outdata;\r
- int outsize;\r
- int insize;\r
- SegHeader head;\r
-\r
- outdata = NULL;\r
-\r
- start = in = ReadFile(infn, &insize);\r
-\r
- while(in < start + insize)\r
- {\r
- head = *(SegHeader*)in;\r
-\r
- switch(head.type)\r
- {\r
- case 0x80: /* THEADR */\r
- memcpy(outfn, in+4, in[3]);\r
- outfn[in[3]] = 0;\r
- printf("Output: %s\n", outfn);\r
- {\r
- int i;\r
- for(i = 0;i < 16;++i)\r
- {\r
- if(outfn[i] == ' ')\r
- outfn[i] = 0;\r
- }\r
- }\r
- break;\r
- case 0x88: /* COMENT */\r
- switch(in[3])\r
- {\r
- case 0:\r
- memcpy(str, in+5, head.len-2);\r
- str[head.len-3] = 0;\r
- printf("Comment: %s\n", str);\r
- break;\r
- default:\r
- printf("Unknown comment type %X @ %x ignored.\n", (unsigned char)in[3], (unsigned int)(in - start));\r
- break;\r
- }\r
- break;\r
- case 0x96: /* LNAMES */\r
- p = in+3;\r
- while(p < in+head.len+2)\r
- {\r
- memcpy(str, p+1, (unsigned char)*p);\r
- str[(unsigned char)*p] = 0;\r
- printf("Name: %s\n", str);\r
-\r
- p += (unsigned char)*p+1;\r
- }\r
- break;\r
- case 0x98: /* SEGDEF */\r
- {\r
- SegDef *sd;\r
-\r
- sd = *(in+3) ? (SegDef*)(in+4) : (SegDef*)(in+7);\r
- printf("Segment Length: %d\n", sd->len);\r
-\r
- outdata = (char*)malloc(sd->len);\r
- outsize = sd->len;\r
- break;\r
- }\r
- case 0x90: /* PUBDEF */\r
- p = in+5;\r
- if(in[5] == 0)\r
- p += 2;\r
- while(p < in+head.len+2)\r
- {\r
- memcpy(str, p+1, (unsigned char)*p);\r
- str[(unsigned char)*p] = 0;\r
- printf("Public Name: %s\n", str);\r
-\r
- p += (unsigned char)*p+4;\r
- }\r
- break;\r
- case 0xA0: /* LEDATA */\r
- printf("Writing data at %d (%d)\n", *(unsigned short*)(in+4), head.len-4);\r
- memcpy(outdata+*(unsigned short*)(in+4), in+6, head.len-4);\r
- break;\r
- case 0x8A: /* MODEND */\r
- /* Ignore */\r
- break;\r
- default:\r
- printf("Unknown header type %X @ %x ignored.\n", head.type, (unsigned int)(in - start));\r
- break;\r
- }\r
-\r
- in += 3 + head.len;\r
- }\r
-\r
- WriteFile(outfn, outdata, outsize);\r
-\r
- free((char*)start);\r
- free(outdata);\r
-}\r
-\r
-void CheckSum(char *s, unsigned short len)\r
-{\r
- int sum;\r
-\r
- len += 3;\r
-\r
- sum = 0;\r
- while(len > 1)\r
- {\r
- sum += *(unsigned char*)s;\r
- ++s;\r
- --len;\r
- }\r
- *s = (unsigned char)(0x100-(sum&0xFF));\r
-}\r
-\r
-void MakeDataObj(const char* infn, const char* outfn, const char* segname, const char* symname, int altmode)\r
-{\r
-#define Flush() fwrite(d.buf, d.head.len+3, 1, f)\r
- union\r
- {\r
- char buf[4096];\r
- SegHeader head;\r
- } d;\r
- int i;\r
- FILE *f;\r
- int insize;\r
- const char *in;\r
- const char *infn_stripped = strrchr(infn, '/');\r
- if(strrchr(infn, '\\') > infn_stripped)\r
- infn_stripped = strrchr(infn, '\\');\r
- if(infn_stripped == NULL)\r
- infn_stripped = infn;\r
- else\r
- ++infn_stripped;\r
-\r
- f = fopen(outfn, "wb");\r
-\r
- in = ReadFile(infn, &insize);\r
-\r
- d.head.type = 0x80;\r
- d.head.len = 14;\r
- d.buf[3] = 12;\r
- if(d.buf[3] > 12)\r
- d.buf[3] = 12;\r
- sprintf(&d.buf[4], "%-12s", infn_stripped);\r
- for(i = 0;i < strlen(infn_stripped) && i < 12;++i)\r
- d.buf[4+i] = toupper(d.buf[4+i]);\r
- /* CheckSum(d.buf, d.head.len); */\r
- d.buf[17] = 0; /* For some reason this one isn't checksummed by MakeOBJ */\r
- Flush();\r
-\r
- d.head.type = 0x88;\r
- d.head.len = 15;\r
- d.buf[3] = 0;\r
- d.buf[4] = 0;\r
- /* We're not really MakeOBJ v1.1, but to allow us to verify with md5sums */\r
- memcpy(&d.buf[5], "MakeOBJ v1.1", 12);\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- d.head.type = 0x96;\r
- d.head.len = strlen(infn_stripped)+40;\r
- d.buf[3] = 6;\r
- memcpy(&d.buf[4], "DGROUP", 6);\r
- d.buf[10] = 5;\r
- memcpy(&d.buf[11], "_DATA", 5);\r
- d.buf[16] = 4;\r
- memcpy(&d.buf[17], "DATA", 4);\r
- d.buf[21] = 0;\r
- d.buf[22] = 5;\r
- memcpy(&d.buf[23], "_TEXT", 5);\r
- d.buf[28] = 4;\r
- memcpy(&d.buf[29], "CODE", 4);\r
- d.buf[33] = 8;\r
- memcpy(&d.buf[34], "FAR_DATA", 8);\r
- if(!segname)\r
- {\r
- if(!altmode)\r
- {\r
- d.buf[42] = strlen(infn_stripped)-1;\r
- for(i = 0;i < strlen(infn_stripped)-4;++i)\r
- {\r
- if(i == 0)\r
- d.buf[43] = toupper(infn_stripped[0]);\r
- else\r
- d.buf[43+i] = tolower(infn_stripped[i]);\r
- }\r
- memcpy(&d.buf[43+i], "Seg", 3);\r
- }\r
- else\r
- {\r
- d.head.len = 40;\r
- }\r
- }\r
- else\r
- {\r
- d.head.len = strlen(segname)+41;\r
- d.buf[42] = strlen(segname);\r
- strcpy(&d.buf[43], segname);\r
- }\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- d.head.type = 0x98;\r
- d.head.len = 7;\r
- *(unsigned short*)(d.buf+4) = insize;\r
- if(altmode == 0)\r
- {\r
- d.buf[3] = (char)((unsigned char)0x60);\r
- d.buf[6] = 8;\r
- d.buf[7] = 7;\r
- d.buf[8] = 4;\r
- }\r
- else\r
- {\r
- d.buf[3] = (char)((unsigned char)0x48);\r
- d.buf[6] = 2;\r
- d.buf[7] = 3;\r
- d.buf[8] = 4;\r
- }\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- if(altmode)\r
- {\r
- d.head.type = 0x9A;\r
- d.head.len = 4;\r
- d.buf[3] = 1;\r
- d.buf[4] = (char)((unsigned char)0xFF);\r
- d.buf[5] = 1;\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
- }\r
-\r
- d.head.type = 0x90;\r
- d.head.len = strlen(infn_stripped)+4;\r
- d.buf[3] = 1;\r
- d.buf[4] = 1;\r
- if(!symname)\r
- {\r
- d.buf[5] = strlen(infn_stripped)-3;\r
- d.buf[6] = '_';\r
- for(i = 0;i < strlen(infn_stripped)-4;++i)\r
- d.buf[7+i] = tolower(infn_stripped[i]);\r
- }\r
- else\r
- {\r
- d.head.len = strlen(symname)+7;\r
- d.buf[5] = strlen(symname);\r
- strcpy(&d.buf[6], symname);\r
- i = strlen(symname)-1;\r
- }\r
- d.buf[7+i] = 0;\r
- d.buf[8+i] = 0;\r
- d.buf[9+i] = 0;\r
- /* This checksum is calculated wrong in MakeOBJ, although I don't know in what way. */\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
-#define LEDATA_LEN 1024\r
- for(i = 0;i < insize;i += LEDATA_LEN)\r
- {\r
- d.head.type = 0xA0;\r
- d.head.len = insize - i > LEDATA_LEN ? LEDATA_LEN+4 : insize - i + 4;\r
- d.buf[3] = 1;\r
- *(unsigned short*)(d.buf+4) = i;\r
- memcpy(&d.buf[6], &in[i], d.head.len-4);\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
- }\r
-\r
- d.head.type = 0x8A;\r
- d.head.len = 2;\r
- d.buf[3] = 0;\r
- d.buf[4] = 0;\r
- CheckSum(d.buf, d.head.len);\r
- Flush();\r
-\r
- fclose(f);\r
- free((char*)in);\r
-}\r
-\r
-void DumpData(const char* infn, const char* outfn, int skip)\r
-{\r
- FILE *f;\r
- int i;\r
- int insize;\r
- char symname[9];\r
- const char *in;\r
- const char *infn_stripped = strrchr(infn, '/');\r
- if(strrchr(infn, '\\') > infn_stripped)\r
- infn_stripped = strrchr(infn, '\\');\r
- if(infn_stripped == NULL)\r
- infn_stripped = infn;\r
- else\r
- ++infn_stripped;\r
-\r
- f = fopen(outfn, "wb");\r
-\r
- memset(symname, 0, 9);\r
- memcpy(symname, infn_stripped, strlen(infn_stripped)-4);\r
- fprintf(f, "char far %s[] ={\r\n", symname);\r
-\r
- in = ReadFile(infn, &insize);\r
-\r
- for(i = skip;i < insize;++i)\r
- {\r
- fprintf(f, "%d", (unsigned char)in[i]);\r
- if(i != insize-1)\r
- fprintf(f, ",\r\n");\r
- }\r
- fprintf(f, " };\r\n");\r
-\r
- fclose(f);\r
- free((char*)in);\r
-}\r
-\r
-int main(int argc, char* argv[])\r
-{\r
- if(argc < 3)\r
- {\r
- printf("Converts file to OMF.\nUseage:\n ./makeobj [fx] <input> ...\n");\r
- return 0;\r
- }\r
-\r
- switch(argv[1][0])\r
- {\r
- case 'c':\r
- if(argc < 4)\r
- {\r
- printf("Need an output location. (Extra parms: <output> [<symbol>])\n");\r
- return 0;\r
- }\r
- else\r
- {\r
- const char *symname = NULL;\r
- if(argc >= 5)\r
- symname = argv[4];\r
- MakeDataObj(argv[2], argv[3], NULL, symname, 1);\r
- }\r
- break;\r
- default:\r
- case 'f':\r
- if(argc < 4)\r
- {\r
- printf("Need an output location. (Extra parms: <output> [<segname> <symbol>])\n");\r
- return 0;\r
- }\r
- else\r
- {\r
- const char *segname = NULL, *symname = NULL;\r
- if(argc >= 6)\r
- {\r
- segname = argv[4];\r
- symname = argv[5];\r
- }\r
- MakeDataObj(argv[2], argv[3], segname, symname, 0);\r
- }\r
- break;\r
- case 'x':\r
- Extract(argv[2]);\r
- break;\r
- case 's':\r
- if(argc < 4)\r
- {\r
- printf("Need an output location. (Extra parms: <output> [<skip>])\n");\r
- return 0;\r
- }\r
- else\r
- {\r
- int skip = 0;\r
- if(argc >= 5)\r
- {\r
- skip = atoi(argv[4]);\r
- }\r
- DumpData(argv[2], argv[3], skip);\r
- }\r
- break;\r
- break;\r
- }\r
- return 0;\r
-}\r
+++ /dev/null
-%ext ck4\r
-%version 1.4\r
-\r
-%dump audiodct.ck4 $354F6 1024\r
-%dump audiohed.ck4 $20DF0 652\r
-\r
-%dump egadict.ck4 $358F6 1024\r
-%dump egahead.ck4 $21080 14256\r
-\r
-%dump introscn.ck4 $1FE40 4008\r
-\r
-%dump maphead.ck4 $24830 23406\r
-\r
-\r
-%version cga-1.4\r
-\r
-%dump audiodct.ck4 $3335C 1024\r
-%dump audiohed.ck4 $1E7A0 652\r
-\r
-%dump cgadict.ck4 $3375C 1024\r
-%dump cgahead.ck4 $1EA30 14256\r
-\r
-%dump introscn.ck4 $1D7F0 4008\r
-\r
-%dump maphead.ck4 $221E0 23406\r
-\r
-\r
-%version 1.4gt # Note: not supported by CK4PATCH v0.11.3\r
-\r
-%dump audiodct.ck4 $359D6 1024\r
-%dump audiohed.ck4 $212D0 652\r
-\r
-%dump egadict.ck4 $35DD6 1024\r
-%dump egahead.ck4 $21560 14256\r
-\r
-%dump introscn.ck4 $20320 4008\r
-\r
-%dump maphead.ck4 $24D10 23406\r
-\r
-\r
-%version all\r
-\r
-%abort\r
-%end
\ No newline at end of file
+++ /dev/null
-%ext ck5\r
-%version 1.4\r
-\r
-%dump audiodct.ck5 $35EC4 1024\r
-%dump audiohed.ck5 $21C80 828\r
-\r
-%dump egadict.ck5 $362C4 1024\r
-%dump egahead.ck5 $21FC0 14796\r
-\r
-%dump introscn.ck5 $20CD0 4008\r
-\r
-%dump maphead.ck5 $25990 24090\r
-\r
-\r
-%version cga-1.4\r
-\r
-%dump audiodct.ck5 $33B88 1024\r
-%dump audiohed.ck5 $1F4C0 828\r
-\r
-%dump cgadict.ck5 $33F88 1024\r
-%dump cgahead.ck5 $1F800 14790\r
-\r
-%dump introscn.ck5 $1E510 4008\r
-\r
-%dump maphead.ck5 $231D0 24090\r
-\r
-\r
-%version 1.4gt # Note: not supported by CK4PATCH v0.11.3\r
-\r
-%dump audiodct.ck5 $36424 1024\r
-%dump audiohed.ck5 $221E0 828\r
-\r
-%dump egadict.ck5 $36824 1024\r
-%dump egahead.ck5 $22520 14796\r
-\r
-%dump introscn.ck5 $21230 4008\r
-\r
-%dump maphead.ck5 $25EF0 24090\r
-\r
-\r
-%version all\r
-\r
-%abort\r
-%end
\ No newline at end of file
+++ /dev/null
-%ext ck6\r
-%version 1.4\r
-\r
-%dump audiodct.ck6 $36EEE 1024\r
-%dump audiohed.ck6 $20C50 760\r
-\r
-%dump egadict.ck6 $372EE 1024\r
-%dump egahead.ck6 $20F50 16683\r
-\r
-%dump introscn.ck6 $1FCA0 4008\r
-\r
-%dump maphead.ck6 $25080 24306\r
-\r
-%dump orderscn.ck6 $2AF80 4008\r
-\r
-\r
-%version 1.5\r
-\r
-%dump audiodct.ck6 $36B4E 1024\r
-%dump audiohed.ck6 $256B0 760\r
-\r
-%dump egadict.ck6 $36F4E 1024\r
-%dump egahead.ck6 $259B0 16683\r
-\r
-%dump introscn.ck6 $24700 4008\r
-\r
-%dump maphead.ck6 $29AE0 24306\r
-\r
-%dump orderscn.ck6 $2F9E0 4008\r
-\r
-\r
-%version cga-1.4\r
-\r
-%dump audiodct.ck6 $35030 1024\r
-%dump audiohed.ck6 $1E830 760\r
-\r
-%dump cgadict.ck6 $35430 1024\r
-%dump cgahead.ck6 $1EB30 16665\r
-\r
-%dump introscn.ck6 $1D880 4008\r
-\r
-%dump maphead.ck6 $22C50 24306\r
-\r
-%dump orderscn.ck6 $28B50 4008\r
-\r
-\r
-%version cga-1.5\r
-\r
-%dump audiodct.ck6 $34DA0 1024\r
-%dump audiohed.ck6 $1E5A0 760\r
-\r
-%dump cgadict.ck6 $351A0 1024\r
-%dump cgahead.ck6 $1E8A0 16665\r
-\r
-%dump introscn.ck6 $1D5F0 4008\r
-\r
-%dump maphead.ck6 $229C0 24306\r
-\r
-%dump orderscn.ck6 $288C0 4008\r
-\r
-\r
-%version all\r
-\r
-%abort\r
-%end
\ No newline at end of file
+++ /dev/null
-KEEN 4 RECREATION TIMELINE:\r
----------------------------\r
-\r
-2019-02-16:\r
-\r
-- started implementation\r
-- started & finished CK_MAIN.C (except for variables)\r
-- started & finished CK_DEMO.C (except for variables and fancy intro stuff)\r
-- started CK_GAME.C, CK_PLAY.C, CK_TEXT.C, CK_STATE.C\r
-\r
-\r
-2019-02-17:\r
-\r
-- finished CK_GAME.C (except for variables)\r
-- finished CK_PLAY.C (except for variables)\r
-- finished CK_TEXT.C (except for variables)\r
-- finished CK_STATE.C (except for variables)\r
-- started CK_KEEN.C\r
-\r
-\r
-2019-02-18:\r
-\r
-- finished CK_KEEN.C (except for variables)\r
-- started & finished CK_KEEN2.C (except for variables)\r
-- started & finished K4_LEVEL.C (except for variables)\r
-- started K4_ACT1.C, K4_ACT2.C\r
-\r
-\r
-2019-02-19:\r
-\r
-- finished K4_ACT1.C (except for variables)\r
-- finished K4_ACT2.C (except for variables)\r
-- started & finished K4_ACT3.C (except for variables)\r
-- added crawl text in K4_LEVEL.C\r
-- added states in K4_ACT1.C\r
-\r
-\r
-2019-02-20:\r
-\r
-- added states in K4_LEVEL.C\r
-- added states and initialized variables in CK_KEEN.C\r
-- added states and initialized variables in CK_KEEN2.C\r
-- added states in K4_ACT2.C\r
-- added states in K4_ACT3.C\r
-\r
-\r
-2019-02-22:\r
-\r
-- added ID Engine (taken from Catacomb 3D)\r
-- started creating header files to put it all together\r
-- fixed tons of typos...\r
-\r
-\r
-2019-02-23:\r
-\r
-- finished header files\r
-- fixed remaining typos & compiler errors\r
-- code compiles, but linking fails because of missing data that needs to be\r
- included in EXE (AUDIOHED, AUDIODICT, EGAHEAD, EGADICT, MAPHEAD)\r
-- first builds - lots of memory(?) issues, quitting freezes DOSBox\r
-- fixed menu colors in ID_US_2.C\r
-- renamed "SKULL 'N' BONES" to "PADDLE WAR" (still need to fix speed issues in pong)\r
-- fixed error in GFXINFO (wrong number of tile16's) now help texts and quitting work\r
-- fixed memory issue by increasing number of memory block to 1200 (Cat3D used only 600)\r
-- first level loads now, but RF_Refresh() locks up/takes forever\r
-\r
-\r
-2019-02-27:\r
-\r
-- modified VW_ClearVideo to match Keen4 behavior (also adding in the bug)\r
-- modified USL_TearDownCtlPanel to use VW_ClearVideo instead of VW_Bar\r
-- fixed error in DrawCacheBox -> animation plays correctly now\r
- (but RF_Refresh still locks up/takes forever)\r
-- fixed error in ID_CA.H (Keen4 uses tile info order SPEED, ANIM, NORTHWALL, ...)\r
- -> RF_Refresh doesn't lock up anymore\r
-- fixed error in GameLoop -> can now enter sub-levels from world map\r
-- fixed error in KeenAirReact -> can now land\r
-- fixed bug in score box (used ammo number for lives)\r
-- status freezes the game\r
-- fixed signed/unsigned division bug in KeenStandThink\r
-- fixed spawn position for slugstain\r
-- fixed error in PlatformThink (platforms got stuck at the top/right end of the path)\r
-- added Keen4 Highscore defaults\r
-- fixed error in StatusWindow -> status window doesn't cause an endless loop anymore\r
-- fixed error in DrawStatus (bad positions for a few things)\r
-- fixed bug in CheckGrabPole -> can climb on poles now\r
-- fixed error in KeenAirReact -> grab edge with correct y position\r
-- fixed error in KeenClimbEdge1Think -> climbing left works correctly now\r
-- fixed bugs in SpawnFlag (darn typecasts...)\r
-- fixed error in ScrollScreenWorld\r
-- fixed error in KeenPoleTihink -> won't fall off when pressing left/right\r
-\r
-\r
-2019-02-28:\r
-\r
-- fixed lindsey floating bug (typecasts)\r
-- fixed mimrock walking\r
-- fixed arachnut contact\r
-- fixed riding the foot\r
-- fixed thundercloud not randomly turning towards player\r
-- fixed missing VW_UpdateScreen in LindseyDialog\r
-- fixed KeenAirReact\r
-- fixed EggContact\r
-- fixed controls for scuba keen\r
-\r
-\r
-2019-03-01:\r
-\r
-- fixed Sprite, Dopefish and Schoolfish\r
-- seems fully playable now...\r
-\r
-\r
-2019-03-16:\r
-\r
-- renamed PlayDemo to RunDemo, since that's the name that is used in the Keen 4 Demo\r
-- fixed Dopefish contact code (used to check 'ob' instead of 'hit' for a keenobj)\r
-\r
-\r
-2019-04-10:\r
-\r
-- fixed bug in PatchWorldMap (info layer value wasn't set to 0 for completed levels)\r
-\r
-\r
-2019-05-04:\r
-\r
-- replaced all sprite numbers with enum names\r
-- fixed error in WormouthLookLeftThink -> changes state to s_wormouth now\r
-\r
-\r
-2019-05-06:\r
-\r
-- replaced some more numbers with enum names\r
-\r
-\r
-2019-05-11:\r
-\r
-- fixed error in MergeTile16M\r
-\r
-\r
-2019-05-17:\r
-\r
-- fixed bug in WormouthThink (used PIXGLOBAL instead of TILEGLOBAL for xdist)\r
-\r
-\r
-2019-05-19:\r
-\r
-- actually moved all far strings into far memory\r
-\r
-\r
-2019-09-27:\r
-\r
-- fixed a minor error in PageLayout (skip anything <= space character, not just space char)\r
-\r
-\r
-2019-09-28:\r
-\r
-- fixed a bug in control panel (had to adjust indices because options menu was added back in)\r
-\r
-\r
-2019-11-26:\r
-\r
-- started implementation of Keen 5 stuff (K5_*.C)\r
-\r
-\r
-2019-11-28:\r
-\r
-- started implementation of Keen 6 stuff (K6_*.C)\r
-\r
-\r
-2019-11-30:\r
-\r
-- finished implementation of Keen 5 & 6 stuff\r
-\r
-\r
-2019-12-09:\r
-\r
-- reorganized KEEN4 project to add support for Keen 5 & 6 without too much redunancy\r
-- added code specific to Keen 5 and Keen 6 to the main codebase (CK_*.C)\r
-- excluded code specific to Keen 4 from the other builds (lots of #if & #ifdef)\r
-- Keen 4 still compiles fine, 5 & 6 still need some header files\r
-\r
-\r
-2019-12-10:\r
-\r
-- created header files for Keen 5 and Keen 6\r
-- all 3 projects compile, but still some bugfixing to do and features to add:\r
- - refresh manager constants must be adjusted\r
- - copy protection for Keen 6 isn't implemented\r
- - sounds for animated tiles (Keen 6) aren't implemented\r
-- fixed a few bugs, first couple of levels in Keen 6 are playable now\r
-\r
-\r
-2019-12-11:\r
-\r
-- adjusted refresh manager constants (now Keen 5 levels are playable, too)\r
-- adjusted position of the "PRESS A KEY" graphic in the status window \r
- (position in Keen 4 differs from 5 & 6 because of the wetsuit box)\r
-- added RF_MaskBlockWhite and a few other things\r
-- studied Terminator-related code in depth, trying to understand it all and\r
- find names for all those variables\r
-\r
-\r
-2019-12-12:\r
-\r
-- finally found and fixed a bug with the turret shots in Keen 5\r
-- fixed wrong pole shooting sprites (left and right sprites were swapped)\r
-- fixed demo-breaking bugs in Spindred and RoboRed (Keen 5)\r
-- fixed worldmap elevator door code (Keen 5)\r
-- fixed worldmap rope and rocket bugs (Keen 6)\r
-- still a demo-breaking bug somewhere (Nospike / Bloogdome, Keen 6 obviously)\r
-- fixed pole check for shikadi pole sparks\r
-\r
-\r
-2019-12-15:\r
-\r
-- FUCLING FINALLY found and fixed the demo-breaking bug in Keen 6\r
- (was in NospikeRunThink)\r
-- fixed bug in Shikadi Master spawn (y offset used tile units instead of pixels)\r
-- started implementation of the Terminator intro and the Star Wars text crawl\r
-\r
-\r
-2019-12-16:\r
-\r
-- finished implementation of the Terminator and Star Wars stuff, but now the\r
- compiler crashes...\r
-- found and fixed the issue that crashed the compiler\r
-- fixed all bugs in the Staw Wars text crawl\r
-- fixed all bugs in the Terminator intro\r
-\r
-2019-12-17:\r
-\r
-- added tile animation sounds for Keen 6\r
-\r
-\r
-2019-12-19:\r
-\r
-- implemented Keen 4-6 version of VW_SetScreen (in _ID_VW_AE.ASM) and my\r
- customized version of the routine (in ID_VW_AE.ASM). swap the files if you\r
- want to use the original code\r
-- added support for the NOPAN parameter\r
-- added US_CheckArg in ID_US_1.C\r
-- added Quiet AdLib mode\r
-- added Gravis Gamepad support\r
-\r
-\r
-2019-12-20:\r
-\r
-- fixed CheckHighScore bug (each episode uses a different map number)\r
-- fixed shockshund bugs (blast direction, stun jump)\r
-\r
-\r
-2019-12-21:\r
-\r
-- fixed EagleWalkThink (condition for starting to fly, Keen 4 obviously)\r
-- fixed tile-based item stealing for TreasureEater (Keen 4)\r
-- fixed force field toggling (Keen 6)\r
-\r
-\r
-2019-12-22:\r
-\r
-- fixed bug in EagleFlyReact (Keen 4)\r
-- changed ConfigVersion in ID_US_1.C for full compatibility with version 1.4\r
- (saved games are still incompatible, though)\r
-\r
-\r
-2020-01-05:\r
-\r
-- modified PaddleWar code to match the code from Keen 4-6\r
-\r
-\r
-2020-01-06:\r
-\r
-- moved minimum memory requirement into the episode headers\r
- (Keen 4 & 5 need 310,000 bytes, Keen 6 needs 300,000 bytes)\r
-- added missing code in SD_Default() (also marked the bug in there)\r
-\r
-\r
-2020-01-08:\r
-\r
-- fixed a minor issue in ID_RF.C related to the tile animation sounds in Keen 6\r
-\r
-\r
-2020-02-21:\r
-\r
-- fixed a bug in Bipship movement code (Keen 6)\r
-- modified sound engine to avoid SDL_Delay entirely and read port 0x388 instead\r
- (which is exactly how version 1.4 and above work)\r
-\r
-\r
-2020-03-05:\r
-\r
-- fixed bug in Ampton walk code\r
-\r
-\r
-2020-04-24:\r
-\r
-- added the title screen in DemoLoop() (after high scores)\r
-- replaced some chunk numbers with their enum names in K4_LEVEL.C (smoke sprites)\r
-\r
-\r
-2020-05-20:\r
-\r
-- SpawnEnemyShot now makes the object removable (KEEN5)\r
-\r
-\r
-2021-05-05:\r
-\r
-- fixed bug in PageLayout (negative top row index)\r
-\r
-\r
-2021-05-05:\r
-\r
-- fixed bug in JanitorDialog (bad picture position for KEENMADPIC)\r
-\r
-\r
-2021-06-06 to 2021-06-23:\r
-\r
-- renamed things in Keen 4 & 5 to what is believed to be the original naming\r
- scheme - Keen 6 stuff is still guesswork\r
-- adapted code to make it compile with Borland C++ 2.0 and 3.0\r
-- adjusted compiler settings and code to recreate the original executables as\r
- closely as possible (for automated comparison and verification)\r
-- found and fixed a few bugs along the way\r
-\r
-\r
-2021-06-24:\r
-\r
-- tracked down and fixed any remaining differences\r
-- compiling (with source debugging enabled) and then compressing the EXE files\r
- with LZEXE Version 0.91 creates EXACTLY the same files as the original v1.4\r
- releases shipped with\r
-- Mission accomplished, I guess...\r
-\r
-\r
-2021-07-01:\r
-\r
-- first public release of this source code\r
-\r
-\r
-2021-07-03:\r
-\r
-- Keen 6 EGA v1.5 can now be recreated with this source code thanks to NY00123\r
-- added some more comments to the source code, mostly explaining what the temp\r
- variables are used for in each actor's code\r
-- changed the function names in the Keen 6 code from ...Think, ...Contact and\r
- ...React to T_..., C_... and R_... for more consistency with the Keen 4 and\r
- Keen 5 code, also changed some state and sprite names for more consistency\r
-\r
-2021-07-08:\r
-- all CGA executables of versions 1.4 and 1.5 can now be recreated with this\r
- source code\r
-- added a few more comments\r
+++ /dev/null
-SET PATH=%PATH%;C:\BC30\BIN\r
-cd KEEN4-6\r
-BC RCK4.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC30\BIN\r
-cd KEEN4-6\r
-BC RCK4C.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC31\BIN\r
-cd KEEN4-6\r
-BC RCK4GT.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC30\BIN\r
-cd KEEN4-6\r
-BC RCK5.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC30\BIN\r
-cd KEEN4-6\r
-BC RCK5C.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC31\BIN\r
-cd KEEN4-6\r
-BC RCK5GT.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC30\BIN\r
-cd KEEN4-6\r
-BC RCK6.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC30\BIN\r
-cd KEEN4-6\r
-BC RCK6C.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC31\BIN\r
-cd KEEN4-6\r
-BC RCK6C15.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-SET PATH=%PATH%;C:\BC31\BIN\r
-cd KEEN4-6\r
-BC RCK6E15.PRJ\r
-cd ..
\ No newline at end of file
+++ /dev/null
-@echo off\r
-del KEEN4-6\KEEN4\OBJ\*.obj\r
-del KEEN4-6\KEEN4C\OBJ\*.obj\r
-del KEEN4-6\KEEN5\OBJ\*.obj\r
-del KEEN4-6\KEEN5C\OBJ\*.obj\r
-del KEEN4-6\KEEN6\OBJ\*.obj\r
-del KEEN4-6\KEEN6C\OBJ\*.obj
\ No newline at end of file
+++ /dev/null
-Reconstructed Commander Keen 4-6 Source Code\r
-Copyright (C) 2021 K1n9_Duk3\r
-===============================================================================\r
-\r
-This is an UNOFFICIAL reconstruction of the original Keen 4-6 source code. More\r
-specifically, it is a reconstruction of the version 1.4 (and 1.5) EGA and CGA\r
-releases.\r
-\r
-The code is primarily based on the Catacomb 3-D source code (ID Engine files).\r
-The text view code (CK_TEXT.C) is based on Wolfenstein 3-D, and the main game\r
-and actor code is loosely based on Keen Dreams.\r
-\r
-Catacomb 3-D Source Code\r
-Copyright (C) 1993-2014 Flat Rock Software\r
-\r
-Wolfenstein 3-D Source Code\r
-Copyright (C) 1992 id Software\r
-\r
-Keen Dreams Source Code\r
-Copyright (C) 2014 Javier M. Chavez\r
-\r
-This program is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-This program is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License along\r
-with this program; if not, write to the Free Software Foundation, Inc.,\r
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-\r
-Getting this code to compile\r
-============================\r
-\r
-You will need Borland C++ 2.0, 3.0 or 3.1 to compile this code. Newer versions\r
-may work, but have not been tested.\r
-\r
-In addition to the compiler and this source code, you will also need to extract\r
-some data files from the original executables. I have provided patch scripts to\r
-extract that data from the original executables. To use these patch scripts,\r
-you will need one of the following tools:\r
-\r
-CKPatch v0.11.3 (unofficial) - 16 bit DOS application\r
-http://ny.duke4.net/files.html\r
-\r
-K1n9_Duk3's Patching Utility v2.3 - Win32 application\r
-http://k1n9duk3.shikadi.net/patcher.html\r
-\r
-Copy the patching programs into the "static" subdirectory, along with copies of\r
-the original Keen 4-6 executables. The Keen 4-6 executables should be named\r
-KEEN4*.EXE, KEEN5*.EXE and KEEN6*.EXE respectively, otherwise the patching\r
-programs might have trouble recognizing the files.\r
-\r
-If you are going to use CKPatch, you should only copy one KEEN4*.EXE file, one\r
-KEEN5*.EXE and one KEEN6*.EXE file into the "static" directory. CKPatch will\r
-always use the first file matching this pattern, so if you have both KEEN4C.EXE\r
-and KEEN4E.EXE in that directory, for example, CK4PATCH will always operate on\r
-KEEN4C.EXE and ignore KEEN4E.EXE.\r
-\r
-These patches will only work on very specific versions of the original game's\r
-executables (v1.4/v1.5 CGA/EGA). The GT versions are not supported by CKPatch,\r
-so you will need K1n9_Duk3's Patching Utility to extract their data with the\r
-patch scripts included in the "static" directory. CKPatch may also be unable to\r
-open the FormGen release of Keen 4 (and Keen 5, if it exists). Decompressing\r
-the game's executable with UNLZEXE may fix that problem.\r
-\r
-If you are using K1n9_Duk3's Patching Utility, simply run it and open the patch\r
-file (*.PAT) you want to use. If K1n9_Duk3's Patching Utility found more than\r
-one supported version of the executables (or none at all), it will ask you to\r
-open the executable manually. Save the extracted files into the "static"\r
-directory using the suggested file names.\r
-\r
-If you are going to use CKPatch, just copy the files as described above, then\r
-use the provided batch files as described in the following section.\r
-\r
-\r
-Setting up a working environment in DOSBox\r
-------------------------------------------\r
-\r
-The Borland C++ compilers, as well as CKPATCH, MAKEOBJ and LZEXE, are all DOS\r
-programs, so you will need a system that is capable of running DOS programs or\r
-you will have to use an emulator like DOSBox to run these programs.\r
-\r
-If you are going to use DOSBox, start out by preparing a base directory on your\r
-system that you are going to mount as drive C: in DOSBox (mounting your real C:\r
-drive as C: in DOSBox is NOT recommended). Let's assume your base directory is\r
-"C:\BASE". Extract the contents of this package into that directory. Also copy\r
-the Borland C++ compiler(s) you are going to use into that directory,\r
-preferably into subdirectories named "BC20", "BC30" and "BC31" to make things\r
-easier for you. You can use different names, but then you will have to edit a\r
-couple of files and settings later on.\r
-\r
-You could just start DOSBox and manually mount your base directory as the C:\r
-drive in DOSBox, but this project comes with a couple of batch files that make\r
-the process much easier, as long as things are set up correctly.\r
-\r
-In case you didn't know, dragging and dropping a file onto DOSBox.exe will\r
-start DOSBox and mount the directory in which that file is located in as the C:\r
-drive in DOSBox, then it will try to execute that file in DOSBox.\r
-\r
-At this point, your base directory should have the following contents:\r
-\r
- BC20 - Borland C++ 2.0\r
- BC30 - Borland C++ 3.0\r
- BC31 - Borland C++ 3.1\r
- KEEN4-6 - main source directory\r
-\r
- lzexe.exe - for compressing executables\r
- rck4.bat - opens RCK4.PRJ with the correct compiler version\r
- rck4c.bat - opens RCK4C.PRJ with the correct compiler version\r
- rck5.bat - opens RCK5.PRJ with the correct compiler version\r
- rck5c.bat - opens RCK5C.PRJ with the correct compiler version\r
- rck6.bat - opens RCK6.PRJ with the correct compiler version\r
- rck6c.bat - opens RCK6C.PRJ with the correct compiler version\r
- rck4gt.bat - opens RCK4GT.PRJ with the correct compiler version\r
- rck5gt.bat - opens RCK5GT.PRJ with the correct compiler version\r
- rck6e15.bat - opens RCK6E15.PRJ with the correct compiler version\r
- rck6c15.bat - opens RCK6C15.PRJ with the correct compiler version\r
- ripnmake.bat - extracts data files and converts them into .OBJ files\r
- readme.txt - this file\r
-\r
-The first order of business is to drag and drop RIPNMAKE.BAT onto DOSBox.exe or\r
-onto a shortcut to DOSBox.exe. This will try to extract the required data files\r
-from the original executables via CKPatch and then convert the data files into\r
-.OBJ files that the compiler can include when generating the new executables.\r
-The .OBJ files will be created in the KEEN4, KEEN5 and KEEN6 subdirectories.\r
-\r
-Note that you should do this step even if you already extracted the data files\r
-using K1n9_Duk3's Patching Utility. The RIPNMAKE.BAT file may not be able to\r
-run the CKPatch programs in that case, but as long as the extracted data files\r
-are present in the "KEEN4-6\static" directory, it will still convert them into\r
-.OBJ files and place the .OBJ files into the correct directories.\r
-\r
-If you are using CKPatch and you want to extract the data for both the EGA and\r
-the CGA versions, you need to delete the KEEN*.EXE files from the "static"\r
-directory after running RIPNMAKE.BAT and then copy the other executables into\r
-that directory and run RIPNMAKE.BAT again.\r
-\r
-\r
-Check the KEEN4, KEEN5 and KEEN6 directories and make sure the following files\r
-are in them:\r
-\r
- CK?ADICT.OBJ\r
- CK?AHEAD.OBJ\r
- CK?CDICT.OBJ (for the CGA version)\r
- CK?CHEAD.OBJ (for the CGA version)\r
- CK?EDICT.OBJ (for the EGA version)\r
- CK?EHEAD.OBJ (for the EGA version)\r
- CK?INTRO.OBJ\r
- CK?MHEAD.OBJ\r
- CK6ORDER.OBJ (only for Keen 6)\r
-\r
-You can exit from DOSBox after this is done. Simply type "exit" at the prompt\r
-and hit Enter.\r
-\r
-\r
-Compiling the code:\r
--------------------\r
-\r
-The other batch files in your base directory (RCK*.BAT) are provided to make\r
-compiling the code easy. Simply drag and drop the batch file onto DOSBox.exe\r
-(or onto a shortcut to DOSBox.exe) and it will open the respective project in\r
-the correct version of the compiler.\r
-\r
- RCK4 - EGA version 1.4 - Apogee and FormGen release\r
- RCK5 - EGA version 1.4 - Apogee (and FormGen?) release)\r
- RCK6 - EGA version 1.4 - FormGen release\r
- RCK4C - CGA version 1.4 - Apogee and FormGen release\r
- RCK5C - CGA version 1.4 - Apogee (and FormGen?) release)\r
- RCK6C - CGA version 1.4 - FormGen release\r
-\r
- RCK4GT - EGA version 1.4 - GT release\r
- RCK5GT - EGA version 1.4 - GT release\r
- RCK6E15 - EGA version 1.5 - FormGen release\r
- RCK6C15 - CGA version 1.5 - FormGen release\r
-\r
-The first six are set up for use with Borland C++ 3.0 by default, the later\r
-four are set up for use with Borland C++ 3.1. If you want to compile them with\r
-a different version of the compiler, edit the batch file and change the\r
-compiler directory (in the "SET PATH=" line) to the one you wish to use. Then\r
-open the project (drag and drop the batch file onto DOSBox.exe) and then select\r
-"Options" -> "Directories" from the main menu. Make sure that the Include and\r
-Library directory settings point to a version that you actually have installed.\r
-\r
-Note that RCK4, RCK4C, RCK5, RCK5C, RCK6 and RCK6C are set up to compile with\r
-BC30, but using the Library directory from BC20. This is required for\r
-recreating the original executables, but if you don't have both of these\r
-versions and you don't care about creating 100% identical copies, you can just\r
-change the directory settings to point to the compiler you have.\r
-\r
-To actually compile the code, press F9 or select "Compile" -> "Make" from the\r
-menu.\r
-\r
-Compiling all of the files may take a while, depending on your CPU cycles\r
-settings in DOSBox. By default, DOSBox should automatically switch to maximum\r
-cycles mode when Borland C++ 3.0 or 3.1 are started, but not when Borland C++\r
-2.0 is started. You can simply enter the command "cycles max" at the DOSBox\r
-prompt (or add it to the batch files) to switch DOSBox into maximum cycles mode\r
-if the automatic switch doesn't work for you.\r
-\r
-With the current code base, it is completely normal to get 3 or 4 warnings as\r
-the code is compiled. One may come from CK_KEEN2.C ("Condition is always true")\r
-when compiling Keen 6 v1.5. The other three of them should come from ID_US_1.C\r
-(2x "Condition is always true" and 1x "Unreachable code"). You can ignore these\r
-warnings.\r
-\r
-Once the code has been compiled, simply press ALT+X or select "File" -> "Quit"\r
-from the menu. Don't just close DOSBox while Borland C++ is still running, you\r
-would just end up with lots of useless swap files in your project directory.\r
-\r
-Type "exit" at the DOS prompt to quit DOSBox.\r
-\r
-Please note that you should always quit DOSBox after compiling a project.\r
-Trying to compile a second project after the first one may cause issues with\r
-the provided batch files and the way they adjust the PATH environment variable.\r
-For example, DOSBox may end up starting the wrong version of the compiler.\r
-\r
-\r
-Recreating the original executables\r
-===================================\r
-\r
-Here's the TL;DR for advanced users:\r
-\r
-RCK4.PRJ, RCK5.PRJ, RCK6.PRJ, RCK4C.PRJ, RCK5C.PRJ, RCK6C.PRJ:\r
-- Use same compiler settings as in the provided RCK?.PRJ files\r
-- Use LIB directory from Borland C++ 2.0\r
-- Use INCLUDE directory from Borland C++ 3.0\r
-- Compile with Borland C++ 3.0\r
-- Compress compiled EXE file with LZEXE version 0.91\r
-\r
-RCK4GT.PJR, RCK5GT.PRJ, RCK6E15.PRJ, RCK6C15.PRJ:\r
-- Use same compiler settings as in the provided RCK?GT.PRJ/RCK6?15.PRJ files\r
-- Use LIB and INCLUDE directories from Borland C++ 3.1\r
-- Compile with Borland C++ 3.1\r
-- Compress compiled EXE file with LZEXE version 0.91\r
-\r
-To create 100% identical copies of the original v1.4 EGA executables, you will\r
-need a copy of Borland C++ 3.0 as well as a copy of Borland C++ 2.0 (or at\r
-least the LIB directory from Borland C++ 2.0).\r
-\r
-Make sure to start with the original project files included in this package.\r
-Those have all of the compiler options set to the correct values. Different\r
-settings may produce slightly different code and the whole point of this is\r
-to get code that's 100% identical to the original executables.\r
-\r
-Unlike Borland C++ 3.1, version 3.0 will not recompile every file when you\r
-select "Build all" from the "Compile" menu if neither that file nor the header\r
-files used by that file have changed since the last time that file was\r
-compiled. Therefore I recommend that you delete all *.OBJ files from the\r
-"KEEN*\OBJ" directory to make sure everything gets recompiled. The CLEANUP.BAT\r
-file will take care of that (can be run in Windows as well as in DOSBox).\r
-\r
-Open the project in BC30 and select "Options" -> "Directories" from the menu.\r
-Change the "Include Directories" path to the INCLUDE directory from BC30 and\r
-change the "Library Directories" path to the LIB directory from BC20.\r
-\r
-Compile the code (select either "Make" or "Build all" from the "Compile" menu)\r
-and once the compiler is done, quit to DOS(Box) and compress the new executable\r
-with LZEXE. To compress RCK4.EXE, you must type "LZEXE RCK4.EXE" and hit Enter.\r
-The program will display a message in French about additional information at\r
-the end of the executable that will be lost after compression and ask if you\r
-want to abort. Type "N" and hit Enter to compress the file.\r
-\r
-\r
-For reference, these are the results you should be getting after compression:\r
-\r
-Keen 4 EGA version 1.4 (Apogee) : size = 105108 bytes, CRC = 6646B983\r
-Keen 4 EGA version 1.4 (FormGen) : size = 105140 bytes, CRC = F91E558B\r
-Keen 4 EGA version 1.4 (GT) : size = 106178 bytes, CRC = 0A05442E\r
-Keen 4 CGA version 1.4 (Apogee) : size = 98007 bytes, CRC = F544DD41\r
-Keen 4 CGA version 1.4 (FormGen) : size = 98007 bytes, CRC = 018FA365\r
-\r
-Keen 5 EGA version 1.4 (Apogee) : size = 106417 bytes, CRC = 2A45589A\r
-(No FormGen release of Keen 5 EGA version 1.4 is known at this time.)\r
-Keen 5 EGA version 1.4 (GT) : size = 107611 bytes, CRC = 5E450B12\r
-Keen 5 CGA version 1.4 (Apogee) : size = 98880 bytes, CRC = FB9EB429\r
-(No FormGen release of Keen 5 CGA version 1.4 is known at this time.)\r
-\r
-Keen 6 EGA version 1.4 (FormGen) : size = 107719 bytes, CRC = 9CDACDAE\r
-Keen 6 EGA version 1.5 (FormGen) : size = 109058 bytes, CRC = 5B828EE2\r
-Keen 6 CGA version 1.4 (FormGen) : size = 100964 bytes, CRC = F36A4C51\r
-Keen 6 CGA version 1.5 (FormGen) : size = 102166 bytes, CRC = D2F379B8\r
-\r
-The GT versions appear to have been compiled with Borland C++ 3.1 and its LIB\r
-directory, but otherwise using the same compiler and optimization settings as\r
-in the earlier Apogee/FormGen versions.\r
-\r
-The only difference between the Apogee/FormGen and the GT versions of the Keen\r
-4 and 5 executables (obvious differences in the included OBJ files aside) is\r
-that the GT version has only four entries in the help menu instead of five\r
-(the Order Info section has been removed) and that the GT version has a\r
-different set of default high scores. You must have GOODTIMES defined to\r
-compile these versions (already set in the RCK?GT.PRJ files).\r
-\r
-Keen 6 EGA/CGA version 1.5 was also compiled with Borland C++ 3.1 and its LIB\r
-directory, but it uses completely different compiler and optimization settings\r
-and also has one new variable in CK_PLAY.C that is never used but still has to\r
-be present to recreate the original code. It appears that somebody just pressed\r
-the "Fastest code" button in the compiler optimizations window before version\r
-1.5 was compiled, which was a bad idea for this code. None of the variables in\r
-the ID Engine are marked as "volatile", not even the ones that may be changed\r
-by an interrupt. That means the optimizations may end up generating code that\r
-leads to endless loops, as is the case with the "while (!LastScan);" loop in\r
-the PicturePause() routine.\r
-\r
-To recreate the exact same files as the original Keen 6 v1.5 executables, you\r
-need to compress the generated executables with LZEXE and then hex-edit the\r
-compressed files to replace the "LZ91" signature at offset 0x1C in the EXE file\r
-with four 0 bytes. If you don't have a hex editor, you can use K1n9_Duk3's\r
-Patching Utility for that step. Simply open the "fix_RCK6_v15.pat" or the\r
-"fix_RCK6C_v15.pat" patch file (located in the KEEN4-6\KEEN6\OBJ and\r
-KEEN4-6\KEEN6C\OBJ directories, respectively) with K1n9_Duk3's Patching Utility\r
-and let it patch the compressed executable for you.\r
-\r
-\r
-Borland C++ 2.0 issues?\r
-=======================\r
-\r
-Any versions of Keen 4-6 prior to version 1.4 appear to have been compiled with\r
-Borland C++ 2.0. Version 1.4 is where they switched from 2.0 to 3.0 (without\r
-changing the Library directory to the one from 3.0 for some reason).\r
-\r
-The code in this package can be built with Borland C++ 2.0 and the compiled\r
-executables appear to be working perfectly fine. But when that version of the\r
-compiler was used to compile the "Return to the Shadowlands" source code (which\r
-is based on an earlier incarnation of this source code recreation), it caused\r
-problems. The code compiled without errors, but the compiled executable would\r
-always quit with the error message "Abnormal program termination".\r
-\r
-The reason for this error was that the compiler appeared to have forced the\r
-"grneeded" array (declared as "far" in ID_CA.C) into the main data segment\r
-instead of giving it its own far data segment. With this additional data in the\r
-main data segment, there was simply not enough space left for the stack and\r
-that is why the program aborted with an error message.\r
-\r
-It is unclear what caused this problem. The same source code compiles perfectly\r
-fine with Borland C++ 3.1 and produces an executable that actually works. If\r
-similar issues arise when working on mods based on this source code, try using\r
-Borland C++ 3.1 instead of whatever version you were using before.\r
-\r
-\r
-Special Thanks\r
-==============\r
-\r
-I would like to thank Jason Blochowiak, Adrian Carmack, John Carmack, Tom Hall,\r
-John Romero and Robert Prince for creating Commander Keen 4-6 in the first\r
-place.\r
-\r
-Special thanks to John Carmack (and the rest of id Software) for releasing the\r
-Wolfenstein 3-D and Spear of Destiny source code to the public in July 1995.\r
-\r
-Extra special thanks to the late Richard Mandel of Flat Rock Software and\r
-everybody else involved in the process of getting the source code of some of\r
-the games id Software made for Softdisk (Catacomb series, Hovertank, Keen\r
-Dreams) released to the public. I have learned a lot from the source code of\r
-these games and this project certainly would not have been possible without it.\r
-\r
-Thanks to PCKF user Multimania for supplying additional information regarding\r
-the names of functions and variables for Keen 4 and Keen 5.\r
-\r
-And last, but not least, I would like to thank NY00123 for figuring out how to\r
-get the compiler to recreate Keen 6 v1.5 and also for sharing a lot of valuable\r
-information about the "gamesrc-ver-recreation" project in various public posts\r
-on the RGB Classic Games Forum (among other places). That's where I first heard\r
-about the TDUMP utility, which is certainly a much better way to extract names\r
-from the debugging information that some executables came with. And using IDA\r
-to open executables and then make IDA generate ASM files that can be compared\r
-more easily using tools like FC in Windows/DOS is pretty much the best way to\r
-track down differences between those two executables without going insane.\r
-\r
-[END OF FILE]
\ No newline at end of file
+++ /dev/null
-@echo off\r
-\r
-cd keen4-6\static\r
-\r
-echo Trying to extract data from KEEN 4 ...\r
-ck4patch ripck4.pat\r
-echo.\r
-\r
-echo Trying to extract data from KEEN 5 ...\r
-ck5patch ripck5.pat\r
-echo.\r
-\r
-echo Trying to extract data from KEEN 6 ...\r
-ck6patch ripck6.pat\r
-echo.\r
-\r
-echo Converting data files to .OBJ ...\r
-call make.bat\r
-\r
-cd ..\..
\ No newline at end of file
@$(REMOVECOMMAND) -rf 16/dro2imf
@$(REMOVECOMMAND) -rf 16/vgmtools
@$(REMOVECOMMAND) -rf 16/abrash-black-book
+ @$(REMOVECOMMAND) -rf 16/keen4-6
@wmake -s -h initlibs
initlibs: .symbolic
@git clone https://github.com/Malvineous/dro2imf.git
@git clone https://github.com/vgmrips/vgmtools.git
@git clone https://github.com/jeffpar/abrash-black-book.git
+ @git clone https://github.com/sparky4/keen4-6.git
@cd $(BUILD_ROOT)
@$(COPYCOMMAND) $(DOSLIBDIR)/make-lowercase .