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