]> 4ch.mooo.com Git - 16.git/blob - 16/keen456/KEEN4-6/ID_RF_A.ASM
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / ID_RF_A.ASM
1 ; Catacomb 3-D Source Code\r
2 ; Copyright (C) 1993-2014 Flat Rock Software\r
3 ;\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
8 ;\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
13 ;\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
17 \r
18 ; ID_RF_A.ASM\r
19 \r
20 IDEAL\r
21 MODEL   MEDIUM,C\r
22 \r
23 INCLUDE "ID_ASM.EQU"\r
24 \r
25 ;============================================================================\r
26 \r
27 TILESWIDE       =       21\r
28 TILESHIGH       =       14\r
29 \r
30 UPDATESIZE      =       (TILESWIDE+1)*TILESHIGH+1\r
31 \r
32 DATASEG\r
33 \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
40 EXTRN   grsegs:WORD\r
41 EXTRN   mapsegs:WORD\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
46 \r
47 planemask       db      ?\r
48 planenum        db      ?\r
49 \r
50 CODESEG\r
51 \r
52 screenstartcs   dw      ?               ;in code segment for accesability\r
53 \r
54 \r
55 \r
56 \r
57 IFE GRMODE-CGAGR\r
58 ;============================================================================\r
59 ;\r
60 ; CGA refresh routines\r
61 ;\r
62 ;============================================================================\r
63 \r
64 TILEWIDTH       =       4\r
65 \r
66 ;=================\r
67 ;\r
68 ; RFL_NewTile\r
69 ;\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
73 ;\r
74 ; Called to draw newlly scrolled on strips and animating tiles\r
75 ;\r
76 ;=================\r
77 \r
78 PROC    RFL_NewTile     updateoffset:WORD\r
79 PUBLIC  RFL_NewTile\r
80 USES    SI,DI\r
81 \r
82 ;\r
83 ; mark both update lists at this spot\r
84 ;\r
85         mov     di,[updateoffset]\r
86 \r
87         mov     bx,[updateptr]                  ;start of update matrix\r
88         mov     [BYTE bx+di],1\r
89 \r
90         mov     dx,SCREENWIDTH-TILEWIDTH                ;add to get to start of next line\r
91 \r
92 ;\r
93 ; set di to the location in screenseg to draw the tile\r
94 ;\r
95         shl     di,1\r
96         mov     si,[updatemapofs+di]    ;offset in map from origin\r
97         add     si,[originmap]\r
98         mov     di,[blockstarts+di]             ;screen location for tile\r
99         add     di,[masterofs]\r
100 \r
101 ;\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
105 ;\r
106         mov     es,[mapsegs+2]                  ;foreground plane\r
107         mov     bx,[es:si]\r
108         mov     es,[mapsegs]                    ;background plane\r
109         mov     si,[es:si]\r
110 \r
111         mov     es,[screenseg]\r
112 \r
113         or      bx,bx\r
114         jz      @@singletile\r
115         jmp     @@maskeddraw                    ;draw both together\r
116 \r
117 ;=============\r
118 ;\r
119 ; Draw single background tile from main memory\r
120 ;\r
121 ;=============\r
122 \r
123 @@singletile:\r
124         shl     si,1\r
125         mov     ds,[grsegs+STARTTILE16*2+si]\r
126 \r
127         xor     si,si                                   ;block is segment aligned\r
128 \r
129 REPT    15\r
130         movsw\r
131         movsw\r
132         add     di,dx\r
133 ENDM\r
134         movsw\r
135         movsw\r
136 \r
137         mov     ax,ss\r
138         mov     ds,ax                                   ;restore turbo's data segment\r
139         ret\r
140 \r
141 \r
142 ;=========\r
143 ;\r
144 ; Draw a masked tile combo\r
145 ; Interupts are disabled and the stack segment is reassigned\r
146 ;\r
147 ;=========\r
148 @@maskeddraw:\r
149         cli                                                     ; don't allow ints when SS is set\r
150         shl     bx,1\r
151         mov     ss,[grsegs+STARTTILE16M*2+bx]\r
152         shl     si,1\r
153         mov     ds,[grsegs+STARTTILE16*2+si]\r
154 \r
155         xor     si,si                                   ;first word of tile data\r
156 \r
157 REPT    16\r
158         mov     ax,[si]                                 ;background tile\r
159         and     ax,[ss:si]                              ;mask\r
160         or      ax,[ss:si+64]                   ;masked data\r
161         stosw\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
165         stosw\r
166         add     si,4\r
167         add     di,dx\r
168 ENDM\r
169 \r
170         mov     ax,@DATA\r
171         mov     ss,ax\r
172         sti\r
173         mov     ds,ax\r
174         ret\r
175 ENDP\r
176 \r
177 ENDIF\r
178 \r
179 \r
180 \r
181 IFE GRMODE-EGAGR\r
182 ;===========================================================================\r
183 ;\r
184 ; EGA refresh routines\r
185 ;\r
186 ;===========================================================================\r
187 \r
188 TILEWIDTH       =       2\r
189 \r
190 ;=================\r
191 ;\r
192 ; RFL_NewTile\r
193 ;\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
197 ;\r
198 ; Called to draw newlly scrolled on strips and animating tiles\r
199 ;\r
200 ; Assumes write mode 0\r
201 ;\r
202 ;=================\r
203 \r
204 PROC    RFL_NewTile     updateoffset:WORD\r
205 PUBLIC  RFL_NewTile\r
206 USES    SI,DI\r
207 \r
208 ;\r
209 ; mark both update lists at this spot\r
210 ;\r
211         mov     di,[updateoffset]\r
212 \r
213         mov     bx,[updatestart]                ;page 0 pointer\r
214         mov     [BYTE bx+di],1\r
215         mov     bx,[updatestart+2]              ;page 1 pointer\r
216         mov     [BYTE bx+di],1\r
217 \r
218 ;\r
219 ; set screenstartcs to the location in screenseg to draw the tile\r
220 ;\r
221         shl     di,1\r
222         mov     si,[updatemapofs+di]    ;offset in map from origin\r
223         add     si,[originmap]\r
224         mov     di,[blockstarts+di]             ;screen location for tile\r
225         add     di,[masterofs]\r
226         mov     [cs:screenstartcs],di\r
227 \r
228 ;\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
232 ;\r
233         mov     es,[mapsegs+2]                  ;foreground plane\r
234         mov     bx,[es:si]\r
235         mov     es,[mapsegs]                    ;background plane\r
236         mov     si,[es:si]\r
237 \r
238         mov     es,[screenseg]\r
239         mov     dx,SC_INDEX                             ;for stepping through map mask planes\r
240 \r
241         or      bx,bx\r
242         jz      @@singletile\r
243         jmp     @@maskeddraw                    ;draw both together\r
244 \r
245 ;=========\r
246 ;\r
247 ; No foreground tile, so draw a single background tile.\r
248 ;\r
249 ;=========\r
250 @@singletile:\r
251 \r
252         mov     bx,SCREENWIDTH-2                ;add to get to start of next line\r
253         shl     si,1\r
254 \r
255         mov     ax,[cs:screenstartcs]\r
256         mov     ds,[grsegs+STARTTILE16*2+si]\r
257 \r
258         xor     si,si                                   ;block is segment aligned\r
259 \r
260         mov     ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
261 \r
262         mov     cx,4                                    ;draw four planes\r
263 @@planeloop:\r
264         mov     dx,SC_INDEX\r
265         WORDOUT\r
266 \r
267         mov     di,[cs:screenstartcs]   ;start at same place in all planes\r
268 \r
269 REPT    15\r
270         movsw\r
271         add     di,bx\r
272 ENDM\r
273         movsw\r
274 \r
275         shl     ah,1                                    ;shift plane mask over for next plane\r
276         loop    @@planeloop\r
277 \r
278         mov     ax,ss\r
279         mov     ds,ax                                   ;restore turbo's data segment\r
280         ret\r
281 \r
282 \r
283 ;=========\r
284 ;\r
285 ; Draw a masked tile combo\r
286 ; Interupts are disabled and the stack segment is reassigned\r
287 ;\r
288 ;=========\r
289 @@maskeddraw:\r
290         cli                                                     ; don't allow ints when SS is set\r
291         shl     bx,1\r
292         mov     ss,[grsegs+STARTTILE16M*2+bx]\r
293         shl     si,1\r
294         mov     ds,[grsegs+STARTTILE16*2+si]\r
295 \r
296         xor     si,si                                   ;first word of tile data\r
297 \r
298         mov     ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
299 \r
300         mov     di,[cs:screenstartcs]\r
301 @@planeloopm:\r
302         WORDOUT\r
303 tileofs         =       0\r
304 lineoffset      =       0\r
305 REPT    16\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
312 ENDM\r
313         add     si,32\r
314         shl     ah,1                                    ;shift plane mask over for next plane\r
315         cmp     ah,10000b\r
316         je      @@done                                  ;drawn all four planes\r
317         jmp     @@planeloopm\r
318 \r
319 @@done:\r
320         mov     ax,@DATA\r
321         mov     ss,ax\r
322         sti\r
323         mov     ds,ax\r
324         ret\r
325 ENDP\r
326 \r
327 ENDIF\r
328 \r
329 IFE GRMODE-VGAGR\r
330 ;============================================================================\r
331 ;\r
332 ; VGA refresh routines\r
333 ;\r
334 ;============================================================================\r
335 \r
336 \r
337 ENDIF\r
338 \r
339 \r
340 ;============================================================================\r
341 ;\r
342 ; reasonably common refresh routines\r
343 ;\r
344 ;============================================================================\r
345 \r
346 \r
347 ;=================\r
348 ;\r
349 ; RFL_UpdateTiles\r
350 ;\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
355 ;\r
356 ; Assumes write mode 1\r
357 ;\r
358 ;=================\r
359 \r
360 \r
361 ; AX    0/1 for scasb, temp for segment register transfers\r
362 ; BX    width for block copies\r
363 ; CX    REP counter\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
368 ;\r
369 ; DS\r
370 ; ES\r
371 ; SS\r
372 \r
373 PROC    RFL_UpdateTiles\r
374 PUBLIC  RFL_UpdateTiles\r
375 USES    SI,DI,BP\r
376 \r
377         jmp     SHORT @@realstart\r
378 @@done:\r
379 ;\r
380 ; all tiles have been scanned\r
381 ;\r
382         ret\r
383 \r
384 @@realstart:\r
385         mov     di,[updateptr]\r
386         mov     bp,(TILESWIDE+1)*TILESHIGH+1\r
387         add     bp,di                                   ; when di = bx, all tiles have been scanned\r
388         push    di\r
389         mov     cx,-1                                   ; definately scan the entire thing\r
390 \r
391 ;\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
394 ;\r
395 @@findtile:\r
396         pop     di                                              ; place to continue scaning from\r
397         mov     ax,ss\r
398         mov     es,ax                                   ; search in the data segment\r
399         mov     ds,ax\r
400         mov al,1\r
401         repne   scasb\r
402         cmp     di,bp\r
403         je      @@done\r
404 \r
405         cmp     [BYTE di],al\r
406         jne     @@singletile\r
407         jmp     @@tileblock\r
408 \r
409 ;============\r
410 ;\r
411 ; copy a single tile\r
412 ;\r
413 ;============\r
414 EVEN\r
415 @@singletile:\r
416         inc     di                                              ; we know the next tile is nothing\r
417         push    di                                      ; save off the spot being scanned\r
418         sub     di,[updateptr]\r
419         shl     di,1\r
420         mov     di,[blockstarts-4+di]   ; start of tile location on screen\r
421         mov     si,di\r
422         add     di,[bufferofs]                  ; dest in current screen\r
423         add     si,[masterofs]                  ; source in master screen\r
424 \r
425         mov     dx,SCREENWIDTH-TILEWIDTH\r
426         mov     ax,[screenseg]\r
427         mov     ds,ax\r
428         mov     es,ax\r
429 \r
430 ;--------------------------\r
431 \r
432 IFE GRMODE-CGAGR\r
433 \r
434 REPT    15\r
435         movsw\r
436         movsw\r
437         add     si,dx\r
438         add     di,dx\r
439 ENDM\r
440         movsw\r
441         movsw\r
442 \r
443 ENDIF\r
444 \r
445 ;--------------------------\r
446 \r
447 IFE GRMODE-EGAGR\r
448 \r
449 REPT    15\r
450         movsb\r
451         movsb\r
452         add     si,dx\r
453         add     di,dx\r
454 ENDM\r
455         movsb\r
456         movsb\r
457 \r
458 ENDIF\r
459 \r
460 ;--------------------------\r
461 \r
462         jmp     @@findtile\r
463 \r
464 ;============\r
465 ;\r
466 ; more than one tile in a row needs to be updated, so do it as a group\r
467 ;\r
468 ;============\r
469 EVEN\r
470 @@tileblock:\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
475 \r
476         mov     bx,di\r
477         sub     bx,dx                                   ; number of tiles in a row\r
478         shl     bx,1                                    ; number of bytes / row\r
479 \r
480         mov     di,dx                                   ; lookup position of start tile\r
481         sub     di,[updateptr]\r
482         shl     di,1\r
483         mov     di,[blockstarts-2+di]   ; start of tile location\r
484         mov     si,di\r
485         add     di,[bufferofs]                  ; dest in current screen\r
486         add     si,[masterofs]                  ; source in master screen\r
487 \r
488         mov     dx,SCREENWIDTH\r
489         sub     dx,bx                                   ; offset to next line on screen\r
490 IFE GRMODE-CGAGR\r
491         sub     dx,bx                                   ; bx is words wide in CGA tiles\r
492 ENDIF\r
493 \r
494         mov     ax,[screenseg]\r
495         mov     ds,ax\r
496         mov     es,ax\r
497 \r
498 REPT    15\r
499         mov     cx,bx\r
500 IFE GRMODE-CGAGR\r
501         rep     movsw\r
502 ENDIF\r
503 IFE GRMODE-EGAGR\r
504         rep     movsb\r
505 ENDIF\r
506         add     si,dx\r
507         add     di,dx\r
508 ENDM\r
509         mov     cx,bx\r
510 IFE GRMODE-CGAGR\r
511         rep     movsw\r
512 ENDIF\r
513 IFE GRMODE-EGAGR\r
514         rep     movsb\r
515 ENDIF\r
516 \r
517         dec     cx                                              ; was 0 from last rep movsb, now $ffff for scasb\r
518         jmp     @@findtile\r
519 \r
520 ENDP\r
521 \r
522 \r
523 ;============================================================================\r
524 \r
525 \r
526 ;=================\r
527 ;\r
528 ; RFL_MaskForegroundTiles\r
529 ;\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
532 ;\r
533 ;=================\r
534 \r
535 PROC    RFL_MaskForegroundTiles\r
536 PUBLIC  RFL_MaskForegroundTiles\r
537 USES    SI,DI,BP\r
538         jmp     SHORT @@realstart\r
539 @@done:\r
540 ;\r
541 ; all tiles have been scanned\r
542 ;\r
543         ret\r
544 \r
545 @@realstart:\r
546         mov     di,[updateptr]\r
547         mov     bp,(TILESWIDE+1)*TILESHIGH+2\r
548         add     bp,di                                   ; when di = bx, all tiles have been scanned\r
549         push    di\r
550         mov     cx,-1                                   ; definately scan the entire thing\r
551 ;\r
552 ; scan for a 3 in the update list\r
553 ;\r
554 @@findtile:\r
555         mov     ax,ss\r
556         mov     es,ax                                   ; scan in the data segment\r
557         mov     al,3\r
558         pop     di                                              ; place to continue scaning from\r
559         repne   scasb\r
560         cmp     di,bp\r
561         je      @@done\r
562 \r
563 ;============\r
564 ;\r
565 ; found a tile, see if it needs to be masked on\r
566 ;\r
567 ;============\r
568 \r
569         push    di\r
570 \r
571         sub     di,[updateptr]\r
572         shl     di,1\r
573         mov     si,[updatemapofs-2+di]  ; offset from originmap\r
574         add     si,[originmap]\r
575 \r
576         mov     es,[mapsegs+2]                  ; foreground map plane segment\r
577         mov     si,[es:si]                              ; foreground tile number\r
578 \r
579         or      si,si\r
580         jz      @@findtile                              ; 0 = no foreground tile\r
581 \r
582         mov     bx,si\r
583         add     bx,INTILE                               ;INTILE tile info table\r
584         mov     es,[tinf]\r
585         test    [BYTE PTR es:bx],80h            ;high bit = masked tile\r
586         jz      @@findtile\r
587 \r
588 ;-------------------\r
589 \r
590 IFE GRMODE-CGAGR\r
591 ;=================\r
592 ;\r
593 ; mask the tile CGA\r
594 ;\r
595 ;=================\r
596 \r
597         mov     di,[blockstarts-2+di]\r
598         add     di,[bufferofs]\r
599         mov     es,[screenseg]\r
600         shl     si,1\r
601         mov     ds,[grsegs+STARTTILE16M*2+si]\r
602 \r
603         mov     bx,64                                   ;data starts 64 bytes after mask\r
604 \r
605         xor     si,si\r
606 \r
607 lineoffset      =       0\r
608 REPT    16\r
609         mov     ax,[es:di+lineoffset]   ;background\r
610         and     ax,[si]                                 ;mask\r
611         or      ax,[si+bx]                              ;masked data\r
612         mov     [es:di+lineoffset],ax   ;background\r
613         inc     si\r
614         inc     si\r
615         mov     ax,[es:di+lineoffset+2] ;background\r
616         and     ax,[si]                                 ;mask\r
617         or      ax,[si+bx]                              ;masked data\r
618         mov     [es:di+lineoffset+2],ax ;background\r
619         inc     si\r
620         inc     si\r
621 lineoffset      =       lineoffset + SCREENWIDTH\r
622 ENDM\r
623 ENDIF\r
624 \r
625 ;-------------------\r
626 \r
627 IFE GRMODE-EGAGR\r
628 ;=================\r
629 ;\r
630 ; mask the tile\r
631 ;\r
632 ;=================\r
633 \r
634         mov     [BYTE planemask],1\r
635         mov     [BYTE planenum],0\r
636 \r
637         mov     di,[blockstarts-2+di]\r
638         add     di,[bufferofs]\r
639         mov     [cs:screenstartcs],di\r
640         mov     es,[screenseg]\r
641         shl     si,1\r
642         mov     ds,[grsegs+STARTTILE16M*2+si]\r
643 \r
644         mov     bx,32                                   ;data starts 32 bytes after mask\r
645 \r
646 @@planeloopm:\r
647         mov     dx,SC_INDEX\r
648         mov     al,SC_MAPMASK\r
649         mov     ah,[ss:planemask]\r
650         WORDOUT\r
651         mov     dx,GC_INDEX\r
652         mov     al,GC_READMAP\r
653         mov     ah,[ss:planenum]\r
654         WORDOUT\r
655 \r
656         xor     si,si\r
657         mov     di,[cs:screenstartcs]\r
658 lineoffset      =       0\r
659 REPT    16\r
660         mov     cx,[es:di+lineoffset]   ;background\r
661         and     cx,[si]                                 ;mask\r
662         or      cx,[si+bx]                              ;masked data\r
663         inc     si\r
664         inc     si\r
665         mov     [es:di+lineoffset],cx\r
666 lineoffset      =       lineoffset + SCREENWIDTH\r
667 ENDM\r
668         add     bx,32                                   ;the mask is now further away\r
669         inc     [ss:planenum]\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
673         jmp     @@planeloopm\r
674 \r
675 @@drawn:\r
676 ENDIF\r
677 \r
678 ;-------------------\r
679 \r
680         mov     ax,ss\r
681         mov     ds,ax\r
682         mov     cx,-1                                   ;definately scan the entire thing\r
683 \r
684         jmp     @@findtile\r
685 \r
686 ENDP\r
687 \r
688 \r
689 END\r
690 \r