1 ; Catacomb Armageddon Source Code
\r
2 ; Copyright (C) 1993-2014 Flat Rock Software
\r
4 ; This program is free software; you can redistribute it and/or modify
\r
5 ; it under the terms of the GNU General Public License as published by
\r
6 ; the Free Software Foundation; either version 2 of the License, or
\r
7 ; (at your option) any later version.
\r
9 ; This program is distributed in the hope that it will be useful,
\r
10 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 ; GNU General Public License for more details.
\r
14 ; You should have received a copy of the GNU General Public License along
\r
15 ; with this program; if not, write to the Free Software Foundation, Inc.,
\r
16 ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
23 INCLUDE "ID_ASM.EQU"
\r
25 ;============================================================================
\r
30 UPDATESIZE = (TILESWIDE+1)*TILESHIGH+1
\r
34 EXTRN screenseg:WORD
\r
35 EXTRN updateptr:WORD
\r
36 EXTRN updatestart:WORD
\r
37 EXTRN masterofs:WORD ;start of master tile port
\r
38 EXTRN bufferofs:WORD ;start of current buffer port
\r
39 EXTRN screenstart:WORD ;starts of three screens (0/1/master) in EGA mem
\r
42 EXTRN originmap:WORD
\r
43 EXTRN updatemapofs:WORD
\r
44 EXTRN tinf:WORD ;seg pointer to map header and tile info
\r
45 EXTRN blockstarts:WORD ;offsets from bufferofs for each update block
\r
52 screenstartcs dw ? ;in code segment for accesability
\r
58 ;============================================================================
\r
60 ; CGA refresh routines
\r
62 ;============================================================================
\r
70 ; Draws a composit two plane tile to the master screen and sets the update
\r
71 ; spot to 1 in both update pages, forcing the tile to be copied to the
\r
72 ; view pages the next two refreshes
\r
74 ; Called to draw newlly scrolled on strips and animating tiles
\r
78 PROC RFL_NewTile updateoffset:WORD
\r
83 ; mark both update lists at this spot
\r
85 mov di,[updateoffset]
\r
87 mov bx,[updateptr] ;start of update matrix
\r
90 mov dx,SCREENWIDTH-TILEWIDTH ;add to get to start of next line
\r
93 ; set di to the location in screenseg to draw the tile
\r
96 mov si,[updatemapofs+di] ;offset in map from origin
\r
98 mov di,[blockstarts+di] ;screen location for tile
\r
102 ; set BX to the foreground tile number and SI to the background number
\r
103 ; If either BX or SI = 0xFFFF, the tile does not need to be masked together
\r
104 ; as one of the planes totally eclipses the other
\r
106 mov es,[mapsegs+2] ;foreground plane
\r
108 mov es,[mapsegs] ;background plane
\r
115 jmp @@maskeddraw ;draw both together
\r
119 ; Draw single background tile from main memory
\r
125 mov ds,[grsegs+STARTTILE16*2+si]
\r
127 xor si,si ;block is segment aligned
\r
138 mov ds,ax ;restore turbo's data segment
\r
144 ; Draw a masked tile combo
\r
145 ; Interupts are disabled and the stack segment is reassigned
\r
149 cli ; don't allow ints when SS is set
\r
151 mov ss,[grsegs+STARTTILE16M*2+bx]
\r
153 mov ds,[grsegs+STARTTILE16*2+si]
\r
155 xor si,si ;first word of tile data
\r
158 mov ax,[si] ;background tile
\r
159 and ax,[ss:si] ;mask
\r
160 or ax,[ss:si+64] ;masked data
\r
162 mov ax,[si+2] ;background tile
\r
163 and ax,[ss:si+2] ;mask
\r
164 or ax,[ss:si+66] ;masked data
\r
182 ;===========================================================================
\r
184 ; EGA refresh routines
\r
186 ;===========================================================================
\r
194 ; Draws a composit two plane tile to the master screen and sets the update
\r
195 ; spot to 1 in both update pages, forcing the tile to be copied to the
\r
196 ; view pages the next two refreshes
\r
198 ; Called to draw newlly scrolled on strips and animating tiles
\r
200 ; Assumes write mode 0
\r
204 PROC RFL_NewTile updateoffset:WORD
\r
209 ; mark both update lists at this spot
\r
211 mov di,[updateoffset]
\r
213 mov bx,[updatestart] ;page 0 pointer
\r
215 mov bx,[updatestart+2] ;page 1 pointer
\r
219 ; set screenstartcs to the location in screenseg to draw the tile
\r
222 mov si,[updatemapofs+di] ;offset in map from origin
\r
224 mov di,[blockstarts+di] ;screen location for tile
\r
226 mov [cs:screenstartcs],di
\r
229 ; set BX to the foreground tile number and SI to the background number
\r
230 ; If either BX or SI = 0xFFFF, the tile does not need to be masked together
\r
231 ; as one of the planes totally eclipses the other
\r
233 mov es,[mapsegs+2] ;foreground plane
\r
235 mov es,[mapsegs] ;background plane
\r
239 mov dx,SC_INDEX ;for stepping through map mask planes
\r
243 jmp @@maskeddraw ;draw both together
\r
247 ; No foreground tile, so draw a single background tile.
\r
252 mov bx,SCREENWIDTH-2 ;add to get to start of next line
\r
255 mov ax,[cs:screenstartcs]
\r
256 mov ds,[grsegs+STARTTILE16*2+si]
\r
258 xor si,si ;block is segment aligned
\r
260 mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0
\r
262 mov cx,4 ;draw four planes
\r
267 mov di,[cs:screenstartcs] ;start at same place in all planes
\r
275 shl ah,1 ;shift plane mask over for next plane
\r
279 mov ds,ax ;restore turbo's data segment
\r
285 ; Draw a masked tile combo
\r
286 ; Interupts are disabled and the stack segment is reassigned
\r
290 cli ; don't allow ints when SS is set
\r
292 mov ss,[grsegs+STARTTILE16M*2+bx]
\r
294 mov ds,[grsegs+STARTTILE16*2+si]
\r
296 xor si,si ;first word of tile data
\r
298 mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0
\r
300 mov di,[cs:screenstartcs]
\r
306 mov bx,[si+tileofs] ;background tile
\r
307 and bx,[ss:tileofs] ;mask
\r
308 or bx,[ss:si+tileofs+32] ;masked data
\r
309 mov [es:di+lineoffset],bx
\r
310 tileofs = tileofs + 2
\r
311 lineoffset = lineoffset + SCREENWIDTH
\r
314 shl ah,1 ;shift plane mask over for next plane
\r
316 je @@done ;drawn all four planes
\r
330 ;============================================================================
\r
332 ; VGA refresh routines
\r
334 ;============================================================================
\r
340 ;============================================================================
\r
342 ; reasonably common refresh routines
\r
344 ;============================================================================
\r
351 ; Scans through the update matrix pointed to by updateptr, looking for 1s.
\r
352 ; A 1 represents a tile that needs to be copied from the master screen to the
\r
353 ; current screen (a new row or an animated tiled). If more than one adjacent
\r
354 ; tile in a horizontal row needs to be copied, they will be copied as a group.
\r
356 ; Assumes write mode 1
\r
361 ; AX 0/1 for scasb, temp for segment register transfers
\r
362 ; BX width for block copies
\r
364 ; DX line width deltas
\r
365 ; SI source for copies
\r
366 ; DI scas dest / movsb dest
\r
367 ; BP pointer to UPDATETERMINATE
\r
373 PROC RFL_UpdateTiles
\r
374 PUBLIC RFL_UpdateTiles
\r
377 jmp SHORT @@realstart
\r
380 ; all tiles have been scanned
\r
386 mov bp,(TILESWIDE+1)*TILESHIGH+1
\r
387 add bp,di ; when di = bx, all tiles have been scanned
\r
389 mov cx,-1 ; definately scan the entire thing
\r
392 ; scan for a 1 in the update list, meaning a tile needs to be copied
\r
393 ; from the master screen to the current screen
\r
396 pop di ; place to continue scaning from
\r
398 mov es,ax ; search in the data segment
\r
411 ; copy a single tile
\r
416 inc di ; we know the next tile is nothing
\r
417 push di ; save off the spot being scanned
\r
420 mov di,[blockstarts-4+di] ; start of tile location on screen
\r
422 add di,[bufferofs] ; dest in current screen
\r
423 add si,[masterofs] ; source in master screen
\r
425 mov dx,SCREENWIDTH-TILEWIDTH
\r
430 ;--------------------------
\r
445 ;--------------------------
\r
460 ;--------------------------
\r
466 ; more than one tile in a row needs to be updated, so do it as a group
\r
471 mov dx,di ; hold starting position + 1 in dx
\r
472 inc di ; we know the next tile also gets updated
\r
473 repe scasb ; see how many more in a row
\r
474 push di ; save off the spot being scanned
\r
477 sub bx,dx ; number of tiles in a row
\r
478 shl bx,1 ; number of bytes / row
\r
480 mov di,dx ; lookup position of start tile
\r
483 mov di,[blockstarts-2+di] ; start of tile location
\r
485 add di,[bufferofs] ; dest in current screen
\r
486 add si,[masterofs] ; source in master screen
\r
489 sub dx,bx ; offset to next line on screen
\r
491 sub dx,bx ; bx is words wide in CGA tiles
\r
517 dec cx ; was 0 from last rep movsb, now $ffff for scasb
\r
523 ;============================================================================
\r
528 ; RFL_MaskForegroundTiles
\r
530 ; Scan through update looking for 3's. If the foreground tile there is a
\r
531 ; masked foreground tile, draw it to the screen
\r
535 PROC RFL_MaskForegroundTiles
\r
536 PUBLIC RFL_MaskForegroundTiles
\r
538 jmp SHORT @@realstart
\r
541 ; all tiles have been scanned
\r
547 mov bp,(TILESWIDE+1)*TILESHIGH+2
\r
548 add bp,di ; when di = bx, all tiles have been scanned
\r
550 mov cx,-1 ; definately scan the entire thing
\r
552 ; scan for a 3 in the update list
\r
556 mov es,ax ; scan in the data segment
\r
558 pop di ; place to continue scaning from
\r
565 ; found a tile, see if it needs to be masked on
\r
573 mov si,[updatemapofs-2+di] ; offset from originmap
\r
576 mov es,[mapsegs+2] ; foreground map plane segment
\r
577 mov si,[es:si] ; foreground tile number
\r
580 jz @@findtile ; 0 = no foreground tile
\r
583 add bx,INTILE ;INTILE tile info table
\r
585 test [BYTE PTR es:bx],80h ;high bit = masked tile
\r
588 ;-------------------
\r
593 ; mask the tile CGA
\r
597 mov di,[blockstarts-2+di]
\r
601 mov ds,[grsegs+STARTTILE16M*2+si]
\r
603 mov bx,64 ;data starts 64 bytes after mask
\r
609 mov ax,[es:di+lineoffset] ;background
\r
611 or ax,[si+bx] ;masked data
\r
612 mov [es:di+lineoffset],ax ;background
\r
615 mov ax,[es:di+lineoffset+2] ;background
\r
617 or ax,[si+bx] ;masked data
\r
618 mov [es:di+lineoffset+2],ax ;background
\r
621 lineoffset = lineoffset + SCREENWIDTH
\r
625 ;-------------------
\r
634 mov [BYTE planemask],1
\r
635 mov [BYTE planenum],0
\r
637 mov di,[blockstarts-2+di]
\r
639 mov [cs:screenstartcs],di
\r
642 mov ds,[grsegs+STARTTILE16M*2+si]
\r
644 mov bx,32 ;data starts 32 bytes after mask
\r
649 mov ah,[ss:planemask]
\r
653 mov ah,[ss:planenum]
\r
657 mov di,[cs:screenstartcs]
\r
660 mov cx,[es:di+lineoffset] ;background
\r
662 or cx,[si+bx] ;masked data
\r
665 mov [es:di+lineoffset],cx
\r
666 lineoffset = lineoffset + SCREENWIDTH
\r
668 add bx,32 ;the mask is now further away
\r
670 shl [ss:planemask],1 ;shift plane mask over for next plane
\r
671 cmp [ss:planemask],10000b ;done all four planes?
\r
672 je @@drawn ;drawn all four planes
\r
678 ;-------------------
\r
682 mov cx,-1 ;definately scan the entire thing
\r