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