]> 4ch.mooo.com Git - 16.git/blob - 16/keen456/KEEN4-6/ID_VW_AC.ASM
extrcted keen code remake
[16.git] / 16 / keen456 / KEEN4-6 / ID_VW_AC.ASM
1 ; Reconstructed Commander Keen 4-6 Source Code\r
2 ; Copyright (C) 2021 K1n9_Duk3\r
3 ;\r
4 ; This file is primarily based on:\r
5 ; Catacomb 3-D Source Code\r
6 ; Copyright (C) 1993-2014 Flat Rock Software\r
7 ;\r
8 ; This program is free software; you can redistribute it and/or modify\r
9 ; it under the terms of the GNU General Public License as published by\r
10 ; the Free Software Foundation; either version 2 of the License, or\r
11 ; (at your option) any later version.\r
12 ;\r
13 ; This program is distributed in the hope that it will be useful,\r
14 ; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16 ; GNU General Public License for more details.\r
17 ;\r
18 ; You should have received a copy of the GNU General Public License along\r
19 ; with this program; if not, write to the Free Software Foundation, Inc.,\r
20 ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
21 \r
22 ;=================================\r
23 ;\r
24 ; CGA view manager routines\r
25 ;\r
26 ;=================================\r
27 \r
28 ;============================================================================\r
29 ;\r
30 ; All of these routines draw into a floating virtual screen segment in main\r
31 ; memory.  bufferofs points to the origin of the drawing page in screenseg.\r
32 ; The routines that write out words must take into account buffer wrapping\r
33 ; and not write a word at 0xffff (which causes an exception on 386s).\r
34 ;\r
35 ; The direction flag should be clear\r
36 ;\r
37 ;============================================================================\r
38 \r
39 DATASEG\r
40 \r
41 plotpixels      db      0c0h,030h,0ch,03h\r
42 colorbyte       db      000000b,01010101b,10101010b,11111111b\r
43 colorword       dw      0,5555h,0aaaah,0ffffh\r
44 \r
45 CODESEG\r
46 \r
47 ;============================================================================\r
48 ;\r
49 ; VW_Plot (int x,y,color)\r
50 ;\r
51 ;============================================================================\r
52 \r
53 \r
54 PROC    VW_Plot x:WORD, y:WORD, color:WORD\r
55 PUBLIC  VW_Plot\r
56 USES    SI,DI\r
57 \r
58         mov     es,[screenseg]\r
59 \r
60         mov     di,[bufferofs]\r
61         mov     bx,[y]\r
62         shl     bx,1\r
63         add     di,[ylookup+bx]\r
64         mov     bx,[x]\r
65         mov     ax,bx\r
66         shr     ax,1\r
67         shr     ax,1\r
68         add     di,ax                           ; di = byte on screen\r
69 \r
70         and     bx,3\r
71         mov     ah,[plotpixels+bx]\r
72         mov     bx,[color]\r
73         mov     cl,[colorbyte+bx]\r
74         and     cl,ah\r
75         not     ah\r
76 \r
77         mov     al,[es:di]\r
78         and     al,ah                           ; mask off other pixels\r
79         or      al,cl\r
80         stosb\r
81 \r
82         ret\r
83 \r
84 ENDP\r
85 \r
86 \r
87 ;============================================================================\r
88 ;\r
89 ; VW_Vlin (int yl,yh,x,color)\r
90 ;\r
91 ;============================================================================\r
92 \r
93 PROC    VW_Vlin yl:WORD, yh:WORD, x:WORD, color:WORD\r
94 PUBLIC  VW_Vlin\r
95 USES    SI,DI\r
96 \r
97         mov     es,[screenseg]\r
98 \r
99         mov     di,[bufferofs]\r
100         mov     bx,[yl]\r
101         shl     bx,1\r
102         add     di,[ylookup+bx]\r
103         mov     bx,[x]\r
104         mov     ax,bx\r
105         shr     ax,1\r
106         shr     ax,1\r
107         add     di,ax                           ; di = byte on screen\r
108 \r
109         and     bx,3\r
110         mov     ah,[plotpixels+bx]\r
111         mov     bx,[color]\r
112         mov     bl,[colorbyte+bx]\r
113         and     bl,ah\r
114         not     ah\r
115 \r
116         mov     cx,[yh]\r
117         sub     cx,[yl]\r
118         inc     cx                                      ;number of pixels to plot\r
119 \r
120         mov     dx,[linewidth]\r
121 \r
122 @@plot:\r
123         mov     al,[es:di]\r
124         and     al,ah                           ; mask off other pixels\r
125         or      al,bl\r
126         mov [es:di],al\r
127         add     di,dx\r
128         loop    @@plot\r
129 \r
130         ret\r
131 \r
132         ret\r
133 \r
134 ENDP\r
135 \r
136 \r
137 ;============================================================================\r
138 \r
139 \r
140 ;===================\r
141 ;\r
142 ; VW_DrawTile8\r
143 ;\r
144 ; xcoord in bytes (8 pixels), ycoord in pixels\r
145 ; All Tile8s are in one grseg, so an offset is calculated inside it\r
146 ;\r
147 ; DONE\r
148 ;\r
149 ;===================\r
150 \r
151 PROC    VW_DrawTile8    xcoord:WORD, ycoord:WORD, tile:WORD\r
152 PUBLIC  VW_DrawTile8\r
153 USES    SI,DI\r
154 \r
155         mov     es,[screenseg]\r
156 \r
157         mov     di,[bufferofs]\r
158         add     di,[xcoord]\r
159         mov     bx,[ycoord]\r
160         shl     bx,1\r
161         add     di,[ylookup+bx]\r
162 \r
163         mov     bx,[linewidth]\r
164         sub     bx,2\r
165 \r
166         mov     si,[tile]\r
167         shl     si,1\r
168         shl     si,1\r
169         shl     si,1\r
170         shl     si,1\r
171 \r
172         mov     ds,[grsegs+STARTTILE8*2] ; segment for all tile8s\r
173 \r
174 ;\r
175 ; start drawing\r
176 ;\r
177 \r
178 REPT    7\r
179         movsb                                           ;no word moves because of segment wrapping\r
180         movsb\r
181         add     di,bx\r
182 ENDM\r
183         movsb\r
184         movsb\r
185 \r
186         mov     ax,ss\r
187         mov     ds,ax                                   ;restore turbo's data segment\r
188 \r
189         ret\r
190 \r
191 ENDP\r
192 \r
193 \r
194 ;============================================================================\r
195 ;\r
196 ; VW_MaskBlock\r
197 ;\r
198 ; Draws a masked block shape to the screen.  bufferofs is NOT accounted for.\r
199 ; The mask comes first, then the data.  Seperate unwound routines are used\r
200 ; to speed drawing.\r
201 ;\r
202 ; Mask blocks will allways be an even width because of the way IGRAB works\r
203 ;\r
204 ; DONE\r
205 ;\r
206 ;============================================================================\r
207 \r
208 DATASEG\r
209 \r
210 UNWOUNDMASKS    =       18\r
211 \r
212 \r
213 maskroutines    dw      mask0,mask0,mask2E,mask2O,mask4E,mask4O\r
214                                 dw      mask6E,mask6O,mask8E,mask8O,mask10E,mask10O\r
215                                 dw      mask12E,mask12O,mask14E,mask14O,mask16E,mask16O\r
216                                 dw      mask18E,mask18O\r
217 \r
218 \r
219 routinetouse    dw      ?\r
220 \r
221 CODESEG\r
222 \r
223 PROC    VW_MaskBlock    segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD, planesize:WORD\r
224 PUBLIC  VW_MaskBlock\r
225 USES    SI,DI\r
226 \r
227         mov     es,[screenseg]\r
228 \r
229         mov     di,[wide]\r
230         mov     dx,[linewidth]\r
231         sub     dx,di                                   ;dx = delta to start of next line\r
232 \r
233         mov     bx,[planesize]                  ; si+bx = data location\r
234 \r
235         cmp     di,UNWOUNDMASKS\r
236         jbe     @@unwoundroutine\r
237 \r
238 ;==============\r
239 ;\r
240 ; General purpose masked block drawing.  This could be optimised into\r
241 ; four routines to use words, but few play loop sprites should be this big!\r
242 ;\r
243 ;==============\r
244 \r
245         mov     [ss:linedelta],dx\r
246         mov     ds,[segm]\r
247         mov     si,[ofs]\r
248         mov     di,[dest]\r
249         mov     dx,[height]                             ;scan lines to draw\r
250 \r
251 @@lineloopgen:\r
252         mov     cx,[wide]\r
253 @@byteloop:\r
254         mov     al,[es:di]\r
255         and     al,[si]\r
256         or      al,[bx+si]\r
257         inc     si\r
258         stosb\r
259         loop    @@byteloop\r
260 \r
261         add     di,[ss:linedelta]\r
262         dec     dx\r
263         jnz     @@lineloopgen\r
264 \r
265 mask0:\r
266         mov     ax,ss\r
267         mov     ds,ax\r
268         ret                                                     ;width of 0 = no drawing\r
269 \r
270 \r
271 ;=================\r
272 ;\r
273 ; use the unwound routines\r
274 ;\r
275 ;=================\r
276 \r
277 @@unwoundroutine:\r
278         shr     di,1                                    ;we only have even width unwound routines\r
279         mov     cx,[dest]\r
280         shr     cx,1\r
281         rcl     di,1                                    ;shift a 1 in if destination is odd\r
282         shl     di,1\r
283         mov     ax,[maskroutines+di]    ;call the right routine\r
284 \r
285         mov     ds,[segm]\r
286         mov     si,[ofs]\r
287         mov     di,[dest]\r
288         mov     cx,[height]                             ;scan lines to draw\r
289 \r
290         jmp ax                                          ;draw it\r
291 \r
292 ;=================\r
293 ;\r
294 ; Horizontally unwound routines to draw certain masked blocks faster\r
295 ;\r
296 ;=================\r
297 \r
298 MACRO   MASKBYTE\r
299         mov     al,[es:di]\r
300         and     al,[si]\r
301         or      al,[bx+si]\r
302         inc     si\r
303         stosb\r
304 ENDM\r
305 \r
306 MACRO   MASKWORD\r
307         mov     ax,[es:di]\r
308         and     ax,[si]\r
309         or      ax,[bx+si]\r
310         inc     si\r
311         inc     si\r
312         stosw\r
313 ENDM\r
314 \r
315 MACRO   SPRITELOOP      addr\r
316         add     di,dx\r
317         loop    addr\r
318         mov     ax,ss\r
319         mov     ds,ax\r
320         ret\r
321 ENDM\r
322 \r
323 \r
324 EVEN\r
325 mask2E:\r
326         MASKWORD\r
327         SPRITELOOP      mask2E\r
328 \r
329 EVEN\r
330 mask2O:\r
331         MASKBYTE\r
332         MASKBYTE\r
333         SPRITELOOP      mask2O\r
334 \r
335 EVEN\r
336 mask4E:\r
337         MASKWORD\r
338         MASKWORD\r
339         SPRITELOOP      mask4E\r
340 \r
341 EVEN\r
342 mask4O:\r
343         MASKBYTE\r
344         MASKWORD\r
345         MASKBYTE\r
346         SPRITELOOP      mask4O\r
347 \r
348 EVEN\r
349 mask6E:\r
350         MASKWORD\r
351         MASKWORD\r
352         MASKWORD\r
353         SPRITELOOP      mask6E\r
354 \r
355 EVEN\r
356 mask6O:\r
357         MASKBYTE\r
358         MASKWORD\r
359         MASKWORD\r
360         MASKBYTE\r
361         SPRITELOOP      mask6O\r
362 \r
363 EVEN\r
364 mask8E:\r
365         MASKWORD\r
366         MASKWORD\r
367         MASKWORD\r
368         MASKWORD\r
369         SPRITELOOP      mask8E\r
370 \r
371 EVEN\r
372 mask8O:\r
373         MASKBYTE\r
374         MASKWORD\r
375         MASKWORD\r
376         MASKWORD\r
377         MASKBYTE\r
378         SPRITELOOP      mask8O\r
379 \r
380 EVEN\r
381 mask10E:\r
382         MASKWORD\r
383         MASKWORD\r
384         MASKWORD\r
385         MASKWORD\r
386         MASKWORD\r
387         SPRITELOOP      mask10E\r
388 \r
389 EVEN\r
390 mask10O:\r
391         MASKBYTE\r
392         MASKWORD\r
393         MASKWORD\r
394         MASKWORD\r
395         MASKWORD\r
396         MASKBYTE\r
397         SPRITELOOP      mask10O\r
398 \r
399 EVEN\r
400 mask12E:\r
401         MASKWORD\r
402         MASKWORD\r
403         MASKWORD\r
404         MASKWORD\r
405         MASKWORD\r
406         MASKWORD\r
407         SPRITELOOP      mask12E\r
408 \r
409 EVEN\r
410 mask12O:\r
411         MASKBYTE\r
412         MASKWORD\r
413         MASKWORD\r
414         MASKWORD\r
415         MASKWORD\r
416         MASKWORD\r
417         MASKBYTE\r
418         SPRITELOOP      mask12O\r
419 \r
420 EVEN\r
421 mask14E:\r
422         MASKWORD\r
423         MASKWORD\r
424         MASKWORD\r
425         MASKWORD\r
426         MASKWORD\r
427         MASKWORD\r
428         MASKWORD\r
429         SPRITELOOP      mask14E\r
430 \r
431 EVEN\r
432 mask14O:\r
433         MASKBYTE\r
434         MASKWORD\r
435         MASKWORD\r
436         MASKWORD\r
437         MASKWORD\r
438         MASKWORD\r
439         MASKWORD\r
440         MASKBYTE\r
441         SPRITELOOP      mask14O\r
442 \r
443 EVEN\r
444 mask16E:\r
445         MASKWORD\r
446         MASKWORD\r
447         MASKWORD\r
448         MASKWORD\r
449         MASKWORD\r
450         MASKWORD\r
451         MASKWORD\r
452         MASKWORD\r
453         SPRITELOOP      mask16E\r
454 \r
455 EVEN\r
456 mask16O:\r
457         MASKBYTE\r
458         MASKWORD\r
459         MASKWORD\r
460         MASKWORD\r
461         MASKWORD\r
462         MASKWORD\r
463         MASKWORD\r
464         MASKWORD\r
465         MASKBYTE\r
466         SPRITELOOP      mask16O\r
467 \r
468 EVEN\r
469 mask18E:\r
470         MASKWORD\r
471         MASKWORD\r
472         MASKWORD\r
473         MASKWORD\r
474         MASKWORD\r
475         MASKWORD\r
476         MASKWORD\r
477         MASKWORD\r
478         MASKWORD\r
479         SPRITELOOP      mask18E\r
480 \r
481 EVEN\r
482 mask18O:\r
483         MASKBYTE\r
484         MASKWORD\r
485         MASKWORD\r
486         MASKWORD\r
487         MASKWORD\r
488         MASKWORD\r
489         MASKWORD\r
490         MASKWORD\r
491         MASKWORD\r
492         MASKBYTE\r
493         SPRITELOOP      mask18O\r
494 \r
495 \r
496 ENDP\r
497 \r
498 \r
499 ;============================================================================\r
500 ;\r
501 ; VW_InverseMask\r
502 ;\r
503 ; Draws a masked block shape to the screen.  bufferofs is NOT accounted for.\r
504 ; The mask comes first, then the data.\r
505 ;\r
506 ; Mask blocks will allways be an even width because of the way IGRAB works\r
507 ;\r
508 ;============================================================================\r
509 \r
510 PROC    VW_InverseMask  segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD\r
511 PUBLIC  VW_InverseMask\r
512 USES    SI,DI\r
513 \r
514         mov     es, [screenseg]\r
515         mov     ax, [wide]\r
516         mov     dx, [linewidth]\r
517         sub     dx, ax;\r
518         mov     ds, [segm]\r
519         mov     si, [ofs]\r
520         mov     di, [dest]\r
521         mov     bx, [height]\r
522         shr     [wide], 1\r
523 @@yloop:\r
524         mov     cx, [wide]\r
525 @@xloop:\r
526         lodsw\r
527         not     ax\r
528         or      [es:di], ax\r
529         inc     di\r
530         inc     di\r
531         loop    @@xloop\r
532         add     di, dx\r
533         dec     bx\r
534         jnz     @@yloop\r
535 \r
536         mov     ax,ss\r
537         mov     ds,ax                                   ;restore turbo's data segment\r
538 \r
539         ret\r
540 ENDP\r
541 \r
542 \r
543 ;============================================================================\r
544 ;\r
545 ; VW_ScreenToScreen\r
546 ;\r
547 ; Basic block copy routine.  Copies one block of screen memory to another,\r
548 ; bufferofs is NOT accounted for.\r
549 ;\r
550 ; DONE\r
551 ;\r
552 ;============================================================================\r
553 \r
554 PROC    VW_ScreenToScreen       source:WORD, dest:WORD, wide:WORD, height:WORD\r
555 PUBLIC  VW_ScreenToScreen\r
556 USES    SI,DI\r
557 \r
558         mov     bx,[linewidth]\r
559         sub     bx,[wide]\r
560 \r
561         mov     ax,[screenseg]\r
562         mov     es,ax\r
563         mov     ds,ax\r
564 \r
565         mov     si,[source]\r
566         mov     di,[dest]                               ;start at same place in all planes\r
567         mov     dx,[height]                             ;scan lines to draw\r
568         mov     ax,[wide]\r
569 ;\r
570 ; if the width, source, and dest are all even, use word moves\r
571 ; This is allways the case in the CGA refresh\r
572 ;\r
573         test    ax,1\r
574         jnz     @@bytelineloop\r
575         test    si,1\r
576         jnz     @@bytelineloop\r
577         test    di,1\r
578         jnz     @@bytelineloop\r
579 \r
580         shr     ax,1\r
581 @@wordlineloop:\r
582         mov     cx,ax\r
583         rep     movsw\r
584         add     si,bx\r
585         add     di,bx\r
586 \r
587         dec     dx\r
588         jnz     @@wordlineloop\r
589 \r
590         mov     ax,ss\r
591         mov     ds,ax                                   ;restore turbo's data segment\r
592 \r
593         ret\r
594 \r
595 @@bytelineloop:\r
596         mov     cx,ax\r
597         rep     movsb\r
598         add     si,bx\r
599         add     di,bx\r
600 \r
601         dec     dx\r
602         jnz     @@bytelineloop\r
603 \r
604         mov     ax,ss\r
605         mov     ds,ax                                   ;restore turbo's data segment\r
606 \r
607         ret\r
608 \r
609 ENDP\r
610 \r
611 \r
612 ;============================================================================\r
613 ;\r
614 ; VW_MemToScreen\r
615 ;\r
616 ; Basic block drawing routine. Takes a block shape at segment pointer source\r
617 ; of width by height data, and draws it to dest in the virtual screen,\r
618 ; based on linewidth.  bufferofs is NOT accounted for.\r
619 ; There are four drawing routines to provide the best optimized code while\r
620 ; accounting for odd segment wrappings due to the floating screens.\r
621 ;\r
622 ; DONE\r
623 ;\r
624 ;============================================================================\r
625 \r
626 DATASEG\r
627 \r
628 memtoscreentable        dw      eventoeven,eventoodd,oddtoeven,oddtoodd\r
629 \r
630 CODESEG\r
631 \r
632 \r
633 PROC    VW_MemToScreen  source:WORD, dest:WORD, wide:WORD, height:WORD\r
634 PUBLIC  VW_MemToScreen\r
635 USES    SI,DI\r
636 \r
637         mov     es,[screenseg]\r
638 \r
639         mov     bx,[linewidth]\r
640         sub     bx,[wide]\r
641 \r
642         mov     ds,[source]\r
643 \r
644         xor     si,si                                   ;block is segment aligned\r
645 \r
646         xor     di,di\r
647         shr     [wide],1                                ;change wide to words, and see if carry is set\r
648         rcl     di,1                                    ;1 if wide is odd\r
649         mov     ax,[dest]\r
650         shr     ax,1\r
651         rcl     di,1                                    ;shift a 1 in if destination is odd\r
652         shl     di,1                                    ;to index into a word width table\r
653         mov     dx,[height]                             ;scan lines to draw\r
654         mov     ax,[wide]\r
655         jmp     [ss:memtoscreentable+di]        ;call the right routine\r
656 \r
657 ;==============\r
658 ;\r
659 ; Copy an even width block to an even destination address\r
660 ;\r
661 ;==============\r
662 \r
663 eventoeven:\r
664         mov     di,[dest]                               ;start at same place in all planes\r
665 EVEN\r
666 @@lineloopEE:\r
667         mov     cx,ax\r
668         rep     movsw\r
669         add     di,bx\r
670         dec     dx\r
671         jnz     @@lineloopEE\r
672 \r
673         mov     ax,ss\r
674         mov     ds,ax                                   ;restore turbo's data segment\r
675 \r
676         ret\r
677 \r
678 ;==============\r
679 ;\r
680 ; Copy an odd width block to an even video address\r
681 ;\r
682 ;==============\r
683 \r
684 oddtoeven:\r
685         mov     di,[dest]                               ;start at same place in all planes\r
686 EVEN\r
687 @@lineloopOE:\r
688         mov     cx,ax\r
689         rep     movsw\r
690         movsb                                           ;copy the last byte\r
691         add     di,bx\r
692         dec     dx\r
693         jnz     @@lineloopOE\r
694 \r
695         mov     ax,ss\r
696         mov     ds,ax                                   ;restore turbo's data segment\r
697 \r
698         ret\r
699 \r
700 ;==============\r
701 ;\r
702 ; Copy an even width block to an odd video address\r
703 ;\r
704 ;==============\r
705 \r
706 eventoodd:\r
707         mov     di,[dest]                               ;start at same place in all planes\r
708         dec     ax                                              ;one word has to be handled seperately\r
709 EVEN\r
710 @@lineloopEO:\r
711         movsb\r
712         mov     cx,ax\r
713         rep     movsw\r
714         movsb\r
715         add     di,bx\r
716         dec     dx\r
717         jnz     @@lineloopEO\r
718 \r
719         mov     ax,ss\r
720         mov     ds,ax                                   ;restore turbo's data segment\r
721 \r
722         ret\r
723 \r
724 ;==============\r
725 ;\r
726 ; Copy an odd width block to an odd video address\r
727 ;\r
728 ;==============\r
729 \r
730 oddtoodd:\r
731         mov     di,[dest]                               ;start at same place in all planes\r
732 EVEN\r
733 @@lineloopOO:\r
734         movsb\r
735         mov     cx,ax\r
736         rep     movsw\r
737         add     di,bx\r
738         dec     dx\r
739         jnz     @@lineloopOO\r
740 \r
741         mov     ax,ss\r
742         mov     ds,ax                                   ;restore turbo's data segment\r
743         ret\r
744 \r
745 \r
746 ENDP\r
747 \r
748 ;===========================================================================\r
749 ;\r
750 ; VW_ScreenToMem\r
751 ;\r
752 ; Copies a block of video memory to main memory, in order from planes 0-3.\r
753 ; This could be optimized along the lines of VW_MemToScreen to take advantage\r
754 ; of word copies, but this is an infrequently called routine.\r
755 ;\r
756 ; DONE\r
757 ;\r
758 ;===========================================================================\r
759 \r
760 PROC    VW_ScreenToMem  source:WORD, dest:WORD, wide:WORD, height:WORD\r
761 PUBLIC  VW_ScreenToMem\r
762 USES    SI,DI\r
763 \r
764         mov     es,[dest]\r
765 \r
766         mov     bx,[linewidth]\r
767         sub     bx,[wide]\r
768 \r
769         mov     ds,[screenseg]\r
770 \r
771         xor     di,di\r
772 \r
773         mov     si,[source]\r
774         mov     dx,[height]                             ;scan lines to draw\r
775 \r
776 @@lineloop:\r
777         mov     cx,[wide]\r
778         rep     movsb\r
779 \r
780         add     si,bx\r
781 \r
782         dec     dx\r
783         jnz     @@lineloop\r
784 \r
785         mov     ax,ss\r
786         mov     ds,ax                                   ;restore turbo's data segment\r
787 \r
788         ret\r
789 \r
790 ENDP\r
791 \r
792 \r
793 ;===========================================================================\r
794 ;\r
795 ;                    MISC CGA ROUTINES\r
796 ;\r
797 ;===========================================================================\r
798 \r
799 ;==============\r
800 ;\r
801 ; VW_SetScreen\r
802 ;\r
803 ; DONE\r
804 ;\r
805 ;==============\r
806 \r
807 PROC    VW_SetScreen  crtc:WORD\r
808 PUBLIC  VW_SetScreen\r
809 \r
810 ;\r
811 ; for some reason, my XT's EGA card doesn't like word outs to the CRTC\r
812 ; index...\r
813 ;\r
814         cli\r
815 \r
816         mov     cx,[crtc]\r
817         mov     dx,CRTC_INDEX\r
818         mov     al,0ch          ;start address high register\r
819         out     dx,al\r
820         inc     dx\r
821         mov     al,ch\r
822         out     dx,al\r
823         dec     dx\r
824         mov     al,0dh          ;start address low register\r
825         out     dx,al\r
826         mov     al,cl\r
827         inc     dx\r
828         out     dx,al\r
829 \r
830         sti\r
831 \r
832         ret\r
833 \r
834 ENDP\r
835 \r
836 \r
837 if NUMFONT+NUMFONTM\r
838 \r
839 ;===========================================================================\r
840 ;\r
841 ; GENERAL FONT DRAWING ROUTINES\r
842 ;\r
843 ;===========================================================================\r
844 \r
845 DATASEG\r
846 \r
847 px      dw      ?                                       ; proportional character drawing coordinates\r
848 py      dw      ?\r
849 pdrawmode       db      11000b          ; 8 = OR, 24 = XOR, put in GC_DATAROTATE\r
850 fontcolor       db      15              ;0-15 mapmask value\r
851 \r
852 PUBLIC  px,py,pdrawmode,fontcolor\r
853 \r
854 ;\r
855 ; offsets in font structure\r
856 ;\r
857 pcharheight     =       0               ;lines high\r
858 charloc         =       2               ;pointers to every character\r
859 charwidth       =       514             ;every character's width in pixels\r
860 \r
861 \r
862 propchar        dw      ?                       ; the character number to shift\r
863 stringptr       dw      ?,?\r
864 \r
865 fontcolormask   dw      ?                       ; font color expands into this\r
866 \r
867 BUFFWIDTH       =       100\r
868 BUFFHEIGHT      =   32                  ; must be twice as high as font for masked fonts\r
869 \r
870 databuffer      db      BUFFWIDTH*BUFFHEIGHT dup (?)\r
871 \r
872 bufferwidth     dw      ?                                               ; bytes with valid info / line\r
873 bufferheight dw ?                                               ; number of lines currently used\r
874 \r
875 bufferbyte      dw      ?\r
876 bufferbit       dw      ?\r
877 PUBLIC  bufferwidth,bufferheight,bufferbyte,bufferbit\r
878 \r
879 screenspot      dw      ?                                               ; where the buffer is going\r
880 \r
881 bufferextra     dw      ?                                               ; add at end of a line copy\r
882 screenextra     dw      ?\r
883 \r
884 CODESEG\r
885 \r
886 ;======================\r
887 ;\r
888 ; Macros to table shift a byte of font\r
889 ;\r
890 ;======================\r
891 \r
892 MACRO   SHIFTNOXOR\r
893         mov     al,[es:bx]              ; source\r
894         xor     ah,ah\r
895         shl     ax,1\r
896         mov     si,ax\r
897         mov     ax,[bp+si]              ; table shift into two bytes\r
898         or      [di],al                 ; or with first byte\r
899         inc     di\r
900         mov     [di],ah                 ; replace next byte\r
901         inc     bx                              ; next source byte\r
902 ENDM\r
903 \r
904 MACRO   SHIFTWITHXOR\r
905         mov     al,[es:bx]              ; source\r
906         xor     ah,ah\r
907         shl     ax,1\r
908         mov     si,ax\r
909         mov     ax,[bp+si]              ; table shift into two bytes\r
910         not     ax\r
911         and     [di],al                 ; and with first byte\r
912         inc     di\r
913         mov     [di],ah                 ; replace next byte\r
914         inc     bx                              ; next source byte\r
915 ENDM\r
916 \r
917 \r
918 ;=======================\r
919 ;\r
920 ; VWL_XORBuffer\r
921 ;\r
922 ; Pass buffer start in SI (somewhere in databuffer)\r
923 ; Draws the buffer to the screen buffer\r
924 ;\r
925 ;========================\r
926 \r
927 PROC    VWL_XORBuffer   NEAR\r
928 USES    BP\r
929         mov     bl,[fontcolor]\r
930         xor     bh,bh\r
931         shl     bx,1\r
932         mov     ax,[colorword+bx]\r
933         mov     [fontcolormask],ax\r
934 \r
935         mov     es,[screenseg]\r
936         mov     di,[screenspot]\r
937 \r
938         mov     bx,[bufferwidth]                ;calculate offsets for end of each line\r
939         mov     [bufferwidth],bx\r
940 \r
941         or      bx,bx\r
942         jnz     @@isthere\r
943         ret                                                     ;nothing to draw\r
944 \r
945 @@isthere:\r
946         test    bx,1\r
947         jnz     @@odd\r
948         jmp     @@even\r
949 ;\r
950 ; clear the last byte so word draws can be used\r
951 ;\r
952 @@odd:\r
953         mov     al,0\r
954 line    =       0\r
955 REPT    BUFFHEIGHT\r
956         mov     [BYTE databuffer+BUFFWIDTH*line+bx],al\r
957 line    =       line+1\r
958 ENDM\r
959 \r
960         inc     bx\r
961 @@even:\r
962         mov     ax,[linewidth]\r
963         sub     ax,bx\r
964         mov     [screenextra],ax\r
965         mov     ax,BUFFWIDTH\r
966         sub     ax,bx\r
967         mov     [bufferextra],ax\r
968         mov     dx,bx\r
969 \r
970         mov     bx,[bufferheight]               ;lines to copy\r
971         mov     bp,[fontcolormask]\r
972 @@lineloop:\r
973         mov     cx,dx\r
974 @@byteloop:\r
975         lodsb                                           ;get a word from the buffer\r
976         and     ax,bp\r
977         xor     [es:di],al                              ;draw it\r
978         inc     di\r
979         loop    @@byteloop\r
980 \r
981         add     si,[bufferextra]\r
982         add     di,[screenextra]\r
983 \r
984         dec     bx\r
985         jnz     @@lineloop\r
986 \r
987         ret\r
988 ENDP\r
989 \r
990 \r
991 DATASEG\r
992 \r
993 ;============================================================================\r
994 ;\r
995 ; NON MASKED FONT DRAWING ROUTINES\r
996 ;\r
997 ;============================================================================\r
998 \r
999 if numfont\r
1000 \r
1001 DATASEG\r
1002 \r
1003 shiftdrawtable  dw      0,shift1wide,shift2wide,shift3wide,shift4wide\r
1004                                 dw              shift5wide,shift6wide\r
1005 \r
1006 CODESEG\r
1007 \r
1008 ;==================\r
1009 ;\r
1010 ; ShiftPropChar\r
1011 ;\r
1012 ; Call with BX = character number (0-255)\r
1013 ; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
1014 ; them to the new position\r
1015 ;\r
1016 ;==================\r
1017 \r
1018 PROC    ShiftPropChar   NEAR\r
1019 \r
1020         mov     si,[fontnumber]\r
1021         shl     si,1\r
1022         mov     es,[grsegs+STARTFONT*2+si]      ;segment of font to use\r
1023 \r
1024 ;\r
1025 ; find character location, width, and height\r
1026 ;\r
1027         mov     si,[es:charwidth+bx]\r
1028         and     si,0ffh                                 ;SI hold width in pixels\r
1029         shl     bx,1\r
1030         mov     bx,[es:charloc+bx]              ;BX holds pointer to character data\r
1031 \r
1032 ;\r
1033 ; look up which shift table to use, based on bufferbit\r
1034 ;\r
1035         mov     di,[bufferbit]\r
1036         shl     di,1\r
1037         mov     bp,[shifttabletable+di] ;BP holds pointer to shift table\r
1038 \r
1039         mov     di,OFFSET databuffer\r
1040         add     di,[bufferbyte]                 ;DI holds pointer to buffer\r
1041 \r
1042         mov     cx,[bufferbit]\r
1043         add     cx,si                                   ;add twice because pixel == two bits\r
1044         add     cx,si                                   ;new bit position\r
1045         mov     ax,cx\r
1046         and     ax,7\r
1047         mov     [bufferbit],ax                  ;new bit position\r
1048         mov     ax,cx\r
1049         shr     ax,1\r
1050         shr     ax,1\r
1051         shr     ax,1\r
1052         add     [bufferbyte],ax                 ;new byte position\r
1053 \r
1054         add     si,3\r
1055         shr     si,1\r
1056         shr     si,1                                    ;bytes the character is wide\r
1057         shl     si,1                    ;*2 to look up in shiftdrawtable\r
1058 \r
1059         mov     cx,[es:pcharheight]\r
1060         mov     dx,BUFFWIDTH\r
1061         jmp     [ss:shiftdrawtable+si]  ;procedure to draw this width\r
1062 \r
1063 ;\r
1064 ; one byte character\r
1065 ;\r
1066 shift1wide:\r
1067         dec     dx\r
1068 EVEN\r
1069 @@loop1:\r
1070         SHIFTNOXOR\r
1071         add     di,dx                   ; next line in buffer\r
1072 \r
1073         loop    @@loop1\r
1074 \r
1075         ret\r
1076 \r
1077 ;\r
1078 ; two byte character\r
1079 ;\r
1080 shift2wide:\r
1081         dec     dx\r
1082         dec     dx\r
1083 EVEN\r
1084 @@loop2:\r
1085         SHIFTNOXOR\r
1086         SHIFTNOXOR\r
1087         add     di,dx                   ; next line in buffer\r
1088 \r
1089         loop    @@loop2\r
1090 \r
1091         ret\r
1092 \r
1093 ;\r
1094 ; three byte character\r
1095 ;\r
1096 shift3wide:\r
1097         sub     dx,3\r
1098 EVEN\r
1099 @@loop3:\r
1100         SHIFTNOXOR\r
1101         SHIFTNOXOR\r
1102         SHIFTNOXOR\r
1103         add     di,dx                   ; next line in buffer\r
1104 \r
1105         loop    @@loop3\r
1106 \r
1107         ret\r
1108 \r
1109 \r
1110 ;\r
1111 ; four byte character\r
1112 ;\r
1113 shift4wide:\r
1114         sub     dx,4\r
1115 EVEN\r
1116 @@loop4:\r
1117         SHIFTNOXOR\r
1118         SHIFTNOXOR\r
1119         SHIFTNOXOR\r
1120         SHIFTNOXOR\r
1121         add     di,dx                   ; next line in buffer\r
1122 \r
1123         loop    @@loop4\r
1124 \r
1125         ret\r
1126 \r
1127 \r
1128 ;\r
1129 ; five byte character\r
1130 ;\r
1131 shift5wide:\r
1132         sub     dx,5\r
1133 EVEN\r
1134 @@loop5:\r
1135         SHIFTNOXOR\r
1136         SHIFTNOXOR\r
1137         SHIFTNOXOR\r
1138         SHIFTNOXOR\r
1139         SHIFTNOXOR\r
1140         add     di,dx                   ; next line in buffer\r
1141 \r
1142         loop    @@loop5\r
1143 \r
1144         ret\r
1145 \r
1146 ;\r
1147 ; six byte character\r
1148 ;\r
1149 shift6wide:\r
1150         sub     dx,6\r
1151 EVEN\r
1152 @@loop6:\r
1153         SHIFTNOXOR\r
1154         SHIFTNOXOR\r
1155         SHIFTNOXOR\r
1156         SHIFTNOXOR\r
1157         SHIFTNOXOR\r
1158         SHIFTNOXOR\r
1159         add     di,dx                   ; next line in buffer\r
1160 \r
1161         loop    @@loop6\r
1162 \r
1163         ret\r
1164 \r
1165 \r
1166 \r
1167 ENDP\r
1168 \r
1169 ;============================================================================\r
1170 \r
1171 ;==================\r
1172 ;\r
1173 ; VW_DrawPropString\r
1174 ;\r
1175 ; Draws a C string of characters at px/py and advances px\r
1176 ;\r
1177 ;==================\r
1178 \r
1179 CODESEG\r
1180 \r
1181 PROC    VW_DrawPropString       string:DWORD\r
1182 PUBLIC  VW_DrawPropString\r
1183 USES    SI,DI\r
1184 \r
1185 ;\r
1186 ; proportional spaceing, which clears the buffer ahead of it, so only\r
1187 ; clear the first collumn\r
1188 ;\r
1189         mov     al,0\r
1190 line    =       0\r
1191 REPT    BUFFHEIGHT\r
1192         mov     [BYTE databuffer+BUFFWIDTH*line],al\r
1193 line    =       line+1\r
1194 ENDM\r
1195 \r
1196 ;\r
1197 ; shift the characters into the buffer\r
1198 ;\r
1199 @@shiftchars:\r
1200         mov     ax,[px]\r
1201         and     ax,3\r
1202         shl     ax,1                    ;one pixel == two bits\r
1203         mov     [bufferbit],ax\r
1204         mov     [bufferbyte],0\r
1205 \r
1206         mov     ax,[WORD string]\r
1207         mov     [stringptr],ax\r
1208         mov     ax,[WORD string+2]\r
1209         mov     [stringptr+2],ax\r
1210 \r
1211 @@shiftone:\r
1212         mov     es,[stringptr+2]\r
1213         mov     bx,[stringptr]\r
1214         inc     [stringptr]\r
1215         mov     bx,[es:bx]\r
1216         xor     bh,bh\r
1217         or      bl,bl\r
1218         jz      @@allshifted\r
1219         call    ShiftPropChar\r
1220         jmp     @@shiftone\r
1221 \r
1222 @@allshifted:\r
1223 ;\r
1224 ; calculate position to draw buffer on screen\r
1225 ;\r
1226         mov     bx,[py]\r
1227         shl     bx,1\r
1228         mov     di,[ylookup+bx]\r
1229         add     di,[bufferofs]\r
1230         add     di,[panadjust]\r
1231 \r
1232         mov     ax,[px]\r
1233         shr     ax,1\r
1234         shr     ax,1            ;x location in bytes\r
1235         add     di,ax\r
1236         mov     [screenspot],di\r
1237 \r
1238 ;\r
1239 ; advance px\r
1240 ;\r
1241         mov     ax,[bufferbyte]\r
1242         shl     ax,1\r
1243         shl     ax,1\r
1244         mov     bx,[bufferbit]\r
1245         shr     bx,1                    ;two bits == one pixel\r
1246         or      ax,bx\r
1247         add     [px],ax\r
1248 \r
1249 ;\r
1250 ; draw it\r
1251 ;\r
1252         mov     ax,[bufferbyte]\r
1253         test    [bufferbit],7\r
1254         jz      @@go\r
1255         inc     ax                              ;so the partial byte also gets drawn\r
1256 @@go:\r
1257         mov     [bufferwidth],ax\r
1258         mov     si,[fontnumber]\r
1259         shl     si,1\r
1260         mov     es,[grsegs+STARTFONT*2+si]\r
1261         mov     ax,[es:pcharheight]\r
1262         mov     [bufferheight],ax\r
1263 \r
1264         mov     si,OFFSET databuffer\r
1265         call    VWL_XORBuffer\r
1266 \r
1267         ret\r
1268 \r
1269 ENDP\r
1270 \r
1271 endif   ;numfont\r
1272 \r
1273 ;============================================================================\r
1274 ;\r
1275 ; MASKED FONT DRAWING ROUTINES\r
1276 ;\r
1277 ;============================================================================\r
1278 \r
1279 if      numfontm\r
1280 \r
1281 DATASEG\r
1282 \r
1283 mshiftdrawtable dw      0,mshift1wide,mshift2wide,mshift3wide\r
1284 \r
1285 \r
1286 CODESEG\r
1287 \r
1288 ;==================\r
1289 ;\r
1290 ; ShiftMPropChar\r
1291 ;\r
1292 ; Call with BX = character number (0-255)\r
1293 ; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
1294 ; them to the new position\r
1295 ;\r
1296 ;==================\r
1297 \r
1298 PROC    ShiftMPropChar  NEAR\r
1299 \r
1300         mov     es,[grsegs+STARTFONTM*2]        ;segment of font to use\r
1301 \r
1302 ;\r
1303 ; find character location, width, and height\r
1304 ;\r
1305         mov     si,[es:charwidth+bx]\r
1306         and     si,0ffh                                 ;SI hold width in pixels\r
1307         shl     bx,1\r
1308         mov     bx,[es:charloc+bx]              ;BX holds pointer to character data\r
1309 \r
1310 ;\r
1311 ; look up which shift table to use, based on bufferbit\r
1312 ;\r
1313         mov     di,[bufferbit]\r
1314         shl     di,1\r
1315         mov     bp,[shifttabletable+di] ;BP holds pointer to shift table\r
1316 \r
1317         mov     di,OFFSET databuffer\r
1318         add     di,[bufferbyte]                 ;DI holds pointer to buffer\r
1319 \r
1320 ;\r
1321 ; advance position by character width\r
1322 ;\r
1323         mov     cx,[bufferbit]\r
1324         add     cx,si                                   ;new bit position\r
1325         mov     ax,cx\r
1326         and     ax,7\r
1327         mov     [bufferbit],ax                  ;new bit position\r
1328         mov     ax,cx\r
1329         shr     ax,1\r
1330         shr     ax,1\r
1331         shr     ax,1\r
1332         add     [bufferbyte],ax                 ;new byte position\r
1333 \r
1334         add     si,7\r
1335         shr     si,1\r
1336         shr     si,1\r
1337         shr     si,1                                    ;bytes the character is wide\r
1338         shl     si,1                    ;*2 to look up in shiftdrawtable\r
1339 \r
1340         mov     cx,[es:pcharheight]\r
1341         mov     dx,BUFFWIDTH\r
1342         jmp     [ss:mshiftdrawtable+si] ;procedure to draw this width\r
1343 \r
1344 ;\r
1345 ; one byte character\r
1346 ;\r
1347 mshift1wide:\r
1348         dec     dx\r
1349 \r
1350 EVEN\r
1351 @@loop1m:\r
1352         SHIFTWITHXOR\r
1353         add     di,dx                   ; next line in buffer\r
1354 \r
1355         loop    @@loop1m\r
1356 \r
1357         mov     cx,[es:pcharheight]\r
1358 \r
1359 EVEN\r
1360 @@loop1:\r
1361         SHIFTNOXOR\r
1362         add     di,dx                   ; next line in buffer\r
1363         loop    @@loop1\r
1364 \r
1365         ret\r
1366 \r
1367 ;\r
1368 ; two byte character\r
1369 ;\r
1370 mshift2wide:\r
1371         dec     dx\r
1372         dec     dx\r
1373 EVEN\r
1374 @@loop2m:\r
1375         SHIFTWITHXOR\r
1376         SHIFTWITHXOR\r
1377         add     di,dx                   ; next line in buffer\r
1378 \r
1379         loop    @@loop2m\r
1380 \r
1381         mov     cx,[es:pcharheight]\r
1382 \r
1383 EVEN\r
1384 @@loop2:\r
1385         SHIFTNOXOR\r
1386         SHIFTNOXOR\r
1387         add     di,dx                   ; next line in buffer\r
1388         loop    @@loop2\r
1389 \r
1390         ret\r
1391 \r
1392 ;\r
1393 ; three byte character\r
1394 ;\r
1395 mshift3wide:\r
1396         sub     dx,3\r
1397 EVEN\r
1398 @@loop3m:\r
1399         SHIFTWITHXOR\r
1400         SHIFTWITHXOR\r
1401         SHIFTWITHXOR\r
1402         add     di,dx                   ; next line in buffer\r
1403 \r
1404         loop    @@loop3m\r
1405 \r
1406         mov     cx,[es:pcharheight]\r
1407 \r
1408 EVEN\r
1409 @@loop3:\r
1410         SHIFTNOXOR\r
1411         SHIFTNOXOR\r
1412         SHIFTNOXOR\r
1413         add     di,dx                   ; next line in buffer\r
1414         loop    @@loop3\r
1415 \r
1416         ret\r
1417 \r
1418 \r
1419 ENDP\r
1420 \r
1421 ;============================================================================\r
1422 \r
1423 ;==================\r
1424 ;\r
1425 ; VW_DrawMPropString\r
1426 ;\r
1427 ; Draws a C string of characters at px/py and advances px\r
1428 ;\r
1429 ;==================\r
1430 \r
1431 \r
1432 \r
1433 PROC    VW_DrawMPropString      string:DWORD\r
1434 PUBLIC  VW_DrawMPropString\r
1435 USES    SI,DI\r
1436 \r
1437 ;\r
1438 ; clear out the first byte of the buffer, the rest will automatically be\r
1439 ; cleared as characters are drawn into it\r
1440 ;\r
1441         mov     es,[grsegs+STARTFONTM*2]\r
1442         mov     dx,[es:pcharheight]\r
1443         mov     di,OFFSET databuffer\r
1444         mov     ax,ds\r
1445         mov     es,ax\r
1446         mov     bx,BUFFWIDTH-1\r
1447 \r
1448         mov     cx,dx\r
1449         mov     al,0ffh\r
1450 @@maskfill:\r
1451         stosb                           ; fill the mask part with $ff\r
1452         add     di,bx\r
1453         loop    @@maskfill\r
1454 \r
1455         mov     cx,dx\r
1456         xor     al,al\r
1457 @@datafill:\r
1458         stosb                           ; fill the data part with $0\r
1459         add     di,bx\r
1460         loop    @@datafill\r
1461 \r
1462 ;\r
1463 ; shift the characters into the buffer\r
1464 ;\r
1465         mov     ax,[px]\r
1466         and     ax,7\r
1467         mov     [bufferbit],ax\r
1468         mov     [bufferbyte],0\r
1469 \r
1470         mov     ax,[WORD string]\r
1471         mov     [stringptr],ax\r
1472         mov     ax,[WORD string+2]\r
1473         mov     [stringptr+2],ax\r
1474 \r
1475 @@shiftone:\r
1476         mov     es,[stringptr+2]\r
1477         mov     bx,[stringptr]\r
1478         inc     [stringptr]\r
1479         mov     bx,[es:bx]\r
1480         xor     bh,bh\r
1481         or      bl,bl\r
1482         jz      @@allshifted\r
1483         call    ShiftMPropChar\r
1484         jmp     @@shiftone\r
1485 \r
1486 @@allshifted:\r
1487 ;\r
1488 ; calculate position to draw buffer on screen\r
1489 ;\r
1490         mov     bx,[py]\r
1491         shl     bx,1\r
1492         mov     di,[ylookup+bx]\r
1493         add     di,[bufferofs]\r
1494 \r
1495         mov     ax,[px]\r
1496         shr     ax,1\r
1497         shr     ax,1\r
1498         shr     ax,1            ;x location in bytes\r
1499         add     di,ax\r
1500         mov     [screenspot],di\r
1501 \r
1502 ;\r
1503 ; advance px\r
1504 ;\r
1505         mov     ax,[bufferbyte]\r
1506         shl     ax,1\r
1507         shl     ax,1\r
1508         shl     ax,1\r
1509         or      ax,[bufferbit]\r
1510         add     [px],ax\r
1511 \r
1512 ;\r
1513 ; draw it\r
1514 ;\r
1515         mov     ax,[bufferbyte]\r
1516         test    [bufferbit],7\r
1517         jz      @@go\r
1518         inc     ax                              ;so the partial byte also gets drawn\r
1519 @@go:\r
1520         mov     [bufferwidth],ax\r
1521         mov     es,[grsegs+STARTFONTM*2]\r
1522         mov     ax,[es:pcharheight]\r
1523         mov     [bufferheight],ax\r
1524 \r
1525         mov     si,OFFSET databuffer\r
1526         call    BufferToScreen          ; cut out mask\r
1527                                                                 ; or in data\r
1528         call    BufferToScreen          ; SI is still in the right position in buffer\r
1529 \r
1530         ret\r
1531 \r
1532 ENDP\r
1533 \r
1534 endif           ; if numfontm\r
1535 \r
1536 endif           ; if fonts\r