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