]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/modex.asm
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / arch / dos / modex.asm
1 ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
2 ;SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
3 ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
4 ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
5 ;IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
6 ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
7 ;FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
8 ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
9 ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
10 ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
11 ;
12 ;
13 ; Routines to access ModeX VGA memory
14 ;
15
16 ;
17 ;
18
19
20 [BITS 32]
21
22 section .data
23 %include "vgaregs.inc"
24 %include "tweak.inc"
25
26 extern _gr_var_bwidth
27 extern _gr_video_memory
28
29 global _modex_line_vertincr
30 global _modex_line_incr1
31 global _modex_line_incr2
32 global _modex_line_x1
33 global _modex_line_x2
34 global _modex_line_y1
35 global _modex_line_y2
36 global _modex_line_Color
37
38 _modex_line_vertincr dd 0
39 _modex_line_incr1    dd 0
40 _modex_line_incr2    dd 0
41 _modex_line_x1       dd 0
42 _modex_line_y1       dd 0
43 _modex_line_x2       dd 0
44 _modex_line_y2       dd 0
45 _modex_line_Color    db 0
46
47
48 _modex_line_routine     dd 0
49 SavedColor              db 0
50
51 %define LEFT_MASK1      1000b
52 %define LEFT_MASK2      1100b
53 %define LEFT_MASK3      1110b
54 %define RIGHT_MASK1     0001b
55 %define RIGHT_MASK2     0011b
56 %define RIGHT_MASK3     0111b
57 %define ALL_MASK        1111b
58
59 tmppal          times 768 db 0
60 fb_pal          dd 0
61 fb_add          dw 0
62 fb_count        dd 0
63
64 MaskTable1  db  ALL_MASK & RIGHT_MASK1
65             db                    ALL_MASK & RIGHT_MASK2
66             db                    ALL_MASK & RIGHT_MASK3
67             db                    ALL_MASK
68             db                    LEFT_MASK3 & RIGHT_MASK1
69             db                    LEFT_MASK3 & RIGHT_MASK2
70             db                    LEFT_MASK3 & RIGHT_MASK3
71             db                    LEFT_MASK3
72             db                    LEFT_MASK2 & RIGHT_MASK1
73             db                    LEFT_MASK2 & RIGHT_MASK2
74             db                    LEFT_MASK2 & RIGHT_MASK3
75             db                    LEFT_MASK2
76             db                    LEFT_MASK1 & RIGHT_MASK1
77             db                    LEFT_MASK1 & RIGHT_MASK2
78             db                    LEFT_MASK1 & RIGHT_MASK3
79             db                    LEFT_MASK1
80
81 MaskTable2  db  ALL_MASK,RIGHT_MASK1
82             db                    ALL_MASK,RIGHT_MASK2
83             db                    ALL_MASK,RIGHT_MASK3
84             db                    ALL_MASK,ALL_MASK
85             db                    LEFT_MASK3,RIGHT_MASK1
86             db                    LEFT_MASK3,RIGHT_MASK2
87             db                    LEFT_MASK3,RIGHT_MASK3
88             db                    LEFT_MASK3,ALL_MASK
89             db                    LEFT_MASK2,RIGHT_MASK1
90             db                    LEFT_MASK2,RIGHT_MASK2
91             db                    LEFT_MASK2,RIGHT_MASK3
92             db                    LEFT_MASK2,ALL_MASK
93             db                    LEFT_MASK1,RIGHT_MASK1
94             db                    LEFT_MASK1,RIGHT_MASK2
95             db                    LEFT_MASK1,RIGHT_MASK3
96             db                    LEFT_MASK1,ALL_MASK
97
98 DrawTable   dd  DrawMR
99             dd                    DrawMR
100             dd                    DrawMR
101             dd                    DrawM
102             dd                    DrawLMR
103             dd                    DrawLMR
104             dd                    DrawLMR
105             dd                    DrawLM
106             dd                    DrawLMR
107             dd                    DrawLMR
108             dd                    DrawLMR
109             dd                    DrawLM
110             dd                    DrawLMR
111             dd                    DrawLMR
112             dd                    DrawLMR
113             dd                    DrawLM
114
115 section .text
116
117 global  _gr_sync_display
118
119 _gr_sync_display:
120                 mov     dx, VERT_RESCAN
121 VS2A:           in      al, dx
122                 and     al, 08h
123                 jnz     VS2A        ; Loop until not in vertical retrace
124 VS2B:           in      al, dx
125                 and     al, 08h
126                 jz      VS2B        ; Loop until in vertical retrace
127                 ret
128
129
130 ; gr_modex_uscanline(int x1,int x2,int y,int color);
131 global  _gr_modex_uscanline
132
133 _gr_modex_uscanline:
134                 push    ebx
135                 mov     eax,[esp+8];x1
136                 mov     edx,[esp+12];x2
137                 mov     ebx,[esp+16];y
138                 mov     ecx,[esp+20];color
139                 push    edi
140
141                 ; EAX = X1  (X1 and X2 don't need to be sorted)
142                 ; EDX = X2
143                 ; EBX = Y
144                 ; ECX = Color
145
146                 mov     [SavedColor], cl
147
148                 ;mov     ebx, _RowOffset[ebx*4]
149                 mov     edi, [_gr_var_bwidth]
150                 imul    edi, ebx
151                 add     edi, [_gr_video_memory]
152                 cmp     eax, edx
153                 jle     @@f1
154                 xchg    eax, edx
155 @@f1:     mov     bl, al
156                 shl     bl, 2
157                 mov     bh, dl
158                 and     bh, 011b
159                 or      bl, bh
160                 and     ebx, 0fh
161                 ; BX = LeftRight switch command. (4bit)
162                 shr     eax, 2
163                 shr     edx, 2
164                 add     edi, eax
165                 ; EDI = Offset into video memory
166                 mov     ecx, edx
167                 sub     ecx, eax
168                 ; ECX = X2/4 - X1/4 - 1
169                 jnz     LargerThan4
170
171 ;======================= ONE GROUP OF 4 OR LESS TO DRAW ====================
172
173                 mov     dx, SC_INDEX
174                 mov     al, SC_MAP_MASK
175                 out     dx, al
176                 inc     dx
177                 mov     al, [MaskTable1+ebx]
178                 out     dx, al
179                 mov     al, [SavedColor]
180                 mov     [edi], al           ; Write the one pixel
181                 pop     edi
182                 pop     ebx
183                 ret
184
185 LargerThan4:
186                 dec     ecx
187                 jnz     LargerThan8
188
189 ;===================== TWO GROUPS OF 4 OR LESS TO DRAW ====================
190
191                 mov     cx, word [MaskTable2+ebx*2]
192                 mov     bl, [SavedColor]
193                 mov     dx, SC_INDEX
194                 mov     al, SC_MAP_MASK
195                 out     dx, al
196                 inc     dx
197                 mov     al, cl
198                 out     dx, al
199                 mov     [edi], bl           ; Write the left pixel
200                 mov     al, ch
201                 out     dx, al
202                 mov     [edi+1], bl         ; Write the right pixel
203                 pop     edi
204                 pop     ebx
205                 ret
206
207 ;========================= MANY GROUPS OF 4 TO DRAW ======================
208 LargerThan8:
209                 mov     dx, SC_INDEX
210                 mov     al, SC_MAP_MASK
211                 out     dx, al
212                 inc     dx
213                 ; DX = SC_INDEX
214                 mov     al, [SavedColor]
215                 mov     ah, al
216                 ; AL,AH = color of pixel
217                 jmp     dword [DrawTable+ebx*4]
218
219
220 DrawM:  ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
221                 mov     al, ALL_MASK
222                 out     dx, al
223                 mov     al, ah
224                 cld
225                 add     ecx, 2
226                 shr     ecx, 1
227                 rep     stosw       ; Write the middle pixels
228                 jnc     @@f2
229                 stosb               ; Write the middle odd pixel
230 @@f2:           pop     edi
231                 pop     ebx
232                 ret
233
234 DrawLM:
235                 ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
236                 mov     al, byte [MaskTable2+ebx*2]
237                 out     dx, al
238                 mov     [edi], ah       ; Write leftmost pixels
239                 inc     edi
240                 mov     al, ALL_MASK
241                 out     dx, al
242                 mov     al, ah
243                 cld
244                 inc     ecx
245                 shr     ecx, 1
246                 rep     stosw       ; Write the middle pixels
247                 jnc     @@f3
248                 stosb               ; Write the middle odd pixel
249 @@f3:           pop     edi
250                 pop     ebx
251                 ret
252
253
254 DrawLMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
255                 mov     bx, word [MaskTable2+ebx*2]
256                 mov     al, bl
257                 out     dx, al
258                 mov     [edi], ah       ; Write leftmost pixels
259                 inc     edi
260                 mov     al, ALL_MASK
261                 out     dx, al
262                 mov     al, ah
263                 cld
264                 shr     ecx, 1
265                 rep     stosw       ; Write the middle pixels
266                 jnc     @@f4
267                 stosb               ; Write the middle odd pixel
268 @@f4:           mov     al, bh
269                 out     dx, al
270                 mov     [edi], ah   ; Write the rightmost pixels
271                 pop     edi
272                 pop     ebx
273                 ret
274
275 DrawMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
276                 mov     bx, word [MaskTable2+ebx*2]
277                 mov     al, ALL_MASK
278                 out     dx, al
279                 mov     al, ah
280                 cld
281                 inc     ecx
282                 shr     ecx, 1
283                 rep     stosw       ; Write the middle pixels
284                 jnc     @@f5
285                 stosb               ; Write the middle odd pixel
286 @@f5:     mov     al, bh
287                 out     dx, al
288                 mov     [edi], ah   ; Write the rightmost pixels
289                 pop     edi
290                 pop     ebx
291                 ret
292
293
294 global _gr_modex_setmode
295
296 _gr_modex_setmode:
297         mov   eax,[esp+4]
298         push  ecx
299         push  edx
300         push  esi
301         push  edi
302
303         mov   ecx, eax
304         dec   ecx
305
306         cmp   ecx, LAST_X_MODE
307         jbe   @@f6
308         mov   ecx, 0
309 @@f6:
310
311         ;call  turn_screen_off
312
313         push  ecx                   ; some bios's dont preserve cx
314
315         ;mov ax, 1201h
316         ;mov bl, 31h     ; disable palette loading at mode switch
317         ;int 10h
318         mov   ax,13h                ; let the BIOS set standard 256-color
319         int   10h                   ;  mode (320x200 linear)
320         ;mov ax, 1200h
321         ;mov bl, 31h     ; enable palette loading at mode switch
322         ;int 10h
323
324         pop   ecx
325
326         mov   dx,SC_INDEX
327         mov   ax,0604h
328         out   dx,ax                 ; disable chain4 mode
329
330         mov   dx,SC_INDEX
331         mov   ax,0100h
332         out   dx,ax                 ; synchronous reset while setting Misc
333                                                                 ;  Output for safety, even though clock
334                                                                 ;  unchanged
335
336         mov   esi, dword [ModeTable+ecx*4]
337         lodsb
338
339         or    al,al
340         jz    DontSetDot
341
342         mov   dx,MISC_OUTPUT
343         out   dx,al               ; select the dot clock and Horiz
344                                                           ;  scanning rate
345
346         ;mov   dx,SC_INDEX
347         ;mov   al,01h
348         ;out   dx,al
349         ;inc   dx
350         ;in    al, dx
351         ;or    al, 1000b
352         ;out   dx, al
353
354 DontSetDot:
355         mov   dx,SC_INDEX
356         mov   ax,0300h
357         out   dx,ax        ; undo reset (restart sequencer)
358
359         mov   dx,CRTC_INDEX       ; reprogram the CRT Controller
360         mov   al,11h              ; VSync End reg contains register write
361         out   dx,al               ; protect bit
362         inc   dx                  ; CRT Controller Data register
363         in    al,dx               ; get current VSync End register setting
364         and   al,07fh             ; remove write protect on various
365         out   dx,al               ; CRTC registers
366         dec   dx                  ; CRT Controller Index
367         cld
368         xor   ecx,ecx
369         lodsb
370         mov   cl,al
371
372 SetCRTParmsLoop:
373         lodsw                     ; get the next CRT Index/Data pair
374         out   dx,ax               ; set the next CRT Index/Data pair
375         loop  SetCRTParmsLoop
376
377         mov   dx,SC_INDEX
378         mov   ax,0f02h
379         out   dx,ax       ; enable writes to all four planes
380         mov   edi, [_gr_video_memory]  ; point ES:DI to display memory
381         xor   eax,eax             ; clear to zero-value pixels
382         mov   ecx,4000h           ; # of dwords in display memory
383         rep   stosd               ; clear all of display memory
384
385         ;  Set pysical screen dimensions
386
387         xor   eax, eax
388         lodsw                               ; Load scrn pixel width
389         mov   cx, ax
390         shl   eax, 16
391
392         mov   dx,CRTC_INDEX
393         mov   al,CRTC_OFFSET
394         out   dx,al
395         inc   dx
396         mov   ax,cx
397         shr   ax,3
398         out   dx,al
399
400         ;mov     si, 360
401         ;@@:
402         ;mov     ax, 04f06h
403         ;mov     bl, 0
404         ;mov     cx, si
405         ;int     10h
406         ;cmp     cx, si
407         ;je      @f
408         ;inc     si
409         ;jmp     @B
410         ;@@:
411         ;movzx     eax, si
412
413         lodsw                               ; Load Screen Phys. Height
414
415         ;call  turn_screen_on
416
417         pop  edi
418         pop  esi
419         pop  edx
420         pop  ecx
421
422         ret
423
424 global _gr_modex_setplane
425
426 _gr_modex_setplane:
427         mov     eax,[esp+4]
428
429         mov     cl, al
430
431         ; SELECT WRITE PLANE
432         and     cl,011b             ;CL = plane
433         mov     ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg
434         shl     ah,cl               ;set only the bit for the required
435                                                                         ; plane to 1
436         mov     dx,SC_INDEX         ;set the Map Mask to enable only the
437         out     dx,ax               ; pixel's plane
438
439         ; SELECT READ PLANE
440         mov     ah,cl               ;AH = plane
441         mov     al,READ_MAP         ;AL = index in GC of the Read Map reg
442         mov     dx,GC_INDEX         ;set the Read Map to read the pixel's
443         out     dx,ax               ; plane
444         ret
445
446 global  _gr_modex_setstart
447
448 _gr_modex_setstart:
449         push    ebx
450         mov     eax,[esp+8]
451         mov     edx,[esp+12]
452         mov     ebx,[esp+16]
453         push    ebx
454
455         ; EAX = X
456         ; EDX = Y
457         ; EBX = Wait for retrace
458
459         mov     ecx, [_gr_var_bwidth]
460         imul    ecx, edx
461
462         shr     eax, 2
463         add     eax, ecx
464
465         mov     ch, ah
466         mov     bh, al
467
468         mov     bl, CC_START_LO
469         mov     cl, CC_START_HI
470
471         cli
472         mov     dx, VERT_RESCAN
473 WaitDE: in      al, dx
474         test    al, 01h
475         jnz     WaitDE
476
477         mov     dx, CRTC_INDEX
478         mov     ax, bx
479         out     dx, ax      ; Start address low
480         mov     ax, cx
481         out     dx, ax      ; Start address high
482         sti
483
484         pop     ebx
485         cmp     ebx, 0
486         je      NoWaitVS
487         mov     dx, VERT_RESCAN
488 WaitVS: in      al, dx
489         test    al, 08h
490         jz      WaitVS      ; Loop until in vertical retrace
491 NoWaitVS:
492
493         pop     ebx
494
495         ret
496
497
498
499
500 %macro ModeXAddr 0
501 ; given: ebx=x, eax=y, return cl=plane mask, ebx=address, trash eax
502         mov     cl, bl
503         and     cl, 3
504         shr     ebx, 2
505         imul    eax, [_gr_var_bwidth]
506         add     ebx, eax
507         add     ebx, [_gr_video_memory]
508 %endmacro
509
510
511 ;-----------------------------------------------------------------------
512 ;
513 ; Line drawing function for all MODE X 256 Color resolutions
514 ; Based on code from "PC and PS/2 Video Systems" by Richard Wilton.
515
516 global _gr_modex_line
517
518 _gr_modex_line:
519         pusha
520
521         mov     dx,SC_INDEX     ; setup for plane mask access
522
523 ; check for vertical line
524
525         mov     esi,[_gr_var_bwidth]
526         mov     ecx,[_modex_line_x2]
527         sub     ecx,[_modex_line_x1]
528         jz      near VertLine
529
530 ; force x1 < x2
531
532         jns     L01
533
534         neg     ecx
535
536         mov     ebx,[_modex_line_x2]
537         xchg    ebx,[_modex_line_x1]
538         mov     [_modex_line_x2],ebx
539
540         mov     ebx,[_modex_line_y2]
541         xchg    ebx,[_modex_line_y1]
542         mov     [_modex_line_y2],ebx
543
544 ; calc dy = abs(y2 - y1)
545
546 L01:
547         mov     ebx,[_modex_line_y2]
548         sub     ebx,[_modex_line_y1]
549         jnz     short skip
550         jmp     HorizLine
551 skip:           jns     L03
552
553         neg     ebx
554         neg     esi
555
556 ; select appropriate routine for slope of line
557
558 L03:
559         mov     [_modex_line_vertincr],esi
560         mov     dword [_modex_line_routine],LoSlopeLine
561         cmp     ebx,ecx
562         jle     L04
563         mov     dword [_modex_line_routine],HiSlopeLine
564         xchg    ebx,ecx
565
566 ; calc initial decision variable and increments
567
568 L04:
569         shl     ebx,1
570         mov     [_modex_line_incr1],ebx
571         sub     ebx,ecx
572         mov     esi,ebx
573         sub     ebx,ecx
574         mov     [_modex_line_incr2],ebx
575
576 ; calc first pixel address
577
578         push    ecx
579         mov     eax,[_modex_line_y1]
580         mov     ebx,[_modex_line_x1]
581         ModeXAddr
582         mov     edi,ebx
583         mov     al,1
584         shl     al,cl
585         mov     ah,al           ; duplicate nybble
586         shl     al,4
587         add     ah,al
588         mov     bl,ah
589         pop     ecx
590         inc     ecx
591         jmp     near dword [_modex_line_routine]
592
593 ; routine for verticle lines
594
595 VertLine:
596         mov     eax,[_modex_line_y1]
597         mov     ebx,[_modex_line_y2]
598         mov     ecx,ebx
599         sub     ecx,eax
600         jge     L31
601         neg     ecx
602         mov     eax,ebx
603
604 L31:
605         inc     ecx
606         mov     ebx,[_modex_line_x1]
607         push    ecx
608         ModeXAddr
609
610         mov     ah,1
611         shl     ah,cl
612         mov     al,MAP_MASK
613         out     dx,ax
614         pop     ecx
615         mov     ax, word [_modex_line_Color]
616
617 ; draw the line
618
619 L32:
620         mov     [ebx],al
621         add     ebx,esi
622         loop    L32
623         jmp     Lexit
624
625 ; routine for horizontal line
626
627 HorizLine:
628
629         mov     eax,[_modex_line_y1]
630         mov     ebx,[_modex_line_x1]
631         ModeXAddr
632
633         mov     edi,ebx     ; set dl = first byte mask
634         mov     dl,00fh
635         shl     dl,cl
636
637         mov     ecx,[_modex_line_x2] ; set dh = last byte mask
638         and     cl,3
639         mov     dh,00eh
640         shl     dh,cl
641         not     dh
642
643 ; determine byte offset of first and last pixel in line
644
645         mov     eax,[_modex_line_x2]
646         mov     ebx,[_modex_line_x1]
647
648         shr     eax,2     ; set ax = last byte column
649         shr     ebx,2    ; set bx = first byte column
650         mov     ecx,eax    ; cx = ax - bx
651         sub     ecx,ebx
652
653         mov     eax,edx    ; mov end byte masks to ax
654         mov     dx,SC_INDEX ; setup dx for VGA outs
655         mov     bl,[_modex_line_Color]
656
657 ; set pixels in leftmost byte of line
658
659         or      ecx,ecx      ; is start and end pt in same byte
660         jnz     L42        ; no !
661         and     ah,al      ; combine start and end masks
662         jmp     short L44
663
664 L42:            push    eax
665         mov     ah,al
666         mov     al,MAP_MASK
667         out     dx,ax
668         mov     al,bl
669         stosb
670         dec     ecx
671
672 ; draw remainder of the line
673
674 L43:
675         mov     ah,0Fh
676         mov     al,MAP_MASK
677         out     dx,ax
678         mov     al,bl
679         rep     stosb
680         pop     eax
681
682 ; set pixels in rightmost byte of line
683
684 L44:    
685         mov     al,MAP_MASK
686         out     dx, ax
687         mov     [edi],bl
688         jmp     Lexit
689
690
691 ; routine for dy >= dx (slope <= 1)
692
693 LoSlopeLine:
694         mov     al,MAP_MASK
695         mov     bh,byte [_modex_line_Color]
696 L10:
697         mov     ah,bl
698
699 L11:
700         or      ah,bl
701         rol     bl,1
702         jc      L14
703
704 ; bit mask not shifted out
705
706         or      esi,esi
707         jns     L12
708         add     esi,[_modex_line_incr1]
709         loop    L11
710
711         out     dx,ax
712         mov     [edi],bh
713         jmp     short Lexit
714
715 L12:
716         add     esi,[_modex_line_incr2]
717         out     dx,ax
718         mov     [edi],bh
719         add     edi,[_modex_line_vertincr]
720         loop    L10
721         jmp     short Lexit
722
723 ; bit mask shifted out
724
725 L14:            out     dx,ax
726         mov     [edi],bh
727         inc     edi
728         or      esi,esi
729         jns     L15
730         add     esi,[_modex_line_incr1]
731         loop    L10
732         jmp     short Lexit
733
734 L15:
735         add     esi,[_modex_line_incr2]
736         add     edi,[_modex_line_vertincr]
737         loop    L10
738         jmp     short Lexit
739
740 ; routine for dy > dx (slope > 1)
741
742 HiSlopeLine:
743         mov     ebx,[_modex_line_vertincr]
744         mov     al,MAP_MASK
745 L21:    out     dx,ax
746         push    eax
747         mov     al,[_modex_line_Color]
748         mov     [edi],al
749         pop     eax
750         add     edi,ebx
751
752 L22:
753         or      esi,esi
754         jns     L23
755
756         add     esi,[_modex_line_incr1]
757         loop    L21
758         jmp     short Lexit
759
760 L23:
761         add     esi,[_modex_line_incr2]
762         rol     ah,1
763         adc     edi,0
764 lx21:   loop    L21
765
766 ; return to caller
767
768 Lexit:
769         popa
770         ret