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