+++ /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