home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / tegl_ii / svga / grcgabw.asm next >
Encoding:
Assembly Source File  |  1991-10-14  |  60.4 KB  |  2,955 lines

  1.  
  2.         include grphdrvr.inc
  3.  
  4. ;******************************************************************************}
  5. ;                TEGL Windows ToolKit II                   }
  6. ;           Copyright (C) 1990, TEGL Systems Corporation            }
  7. ;                 All Rights Reserved.                   }
  8. ;******************************************************************************}
  9.  
  10.         .code
  11.  
  12.         db   'RT',8,8,'TGI Device Driver (EGA640x350x16/VGA640x480x16) 1.00 - Dec 15 1990',13,10
  13.         db   'Copyright (c) 1989,1990 TEGL Systems Corporation',13,10
  14.         db   01ah         ; end of file for TYPE
  15.         db   00          ; end of Copyright Header
  16.  
  17.         db   7,'GRCGABW',0   ; driver module name
  18.  
  19. mode0:        db    12,'CGA640x200x2',0,0,0,0,0,0,0,0,0
  20.         dw    0         ; Mode Number
  21.         dw    639         ; Device Full Resolution in X
  22.         dw    199         ; Device Full Resolution in Y
  23.         dw    8         ; Standard char size X
  24.         dw    8         ; Standard char size Y
  25.         dw    1         ; Number of colors
  26.         dw    1         ; Number of pages
  27.         dw    1         ; max palette
  28.         dw    0         ; buffer offset for 2 page, active page
  29.         dw    0B800h         ; Screen Segment
  30.         dw    80         ; bytes per line
  31.         dw    4200         ; x aspect
  32.         dw    10000         ; y aspect
  33.         dd    0         ; Driver Pointer
  34.         dd    0         ; Driver Name Pointer
  35.         dd    0         ; Driver Jump Table
  36.         dd    0         ; Graphics Work Buffer
  37.         dw    0         ; Graphics Buffer Size
  38.         dw    0         ; Read/Write modes
  39.         db    0         ; transparency on-$ff/off-$00
  40.         db    0         ; jagged characters
  41.         dd    0         ; pointer to font table
  42.         db    0         ; allow EGA palette changes
  43.         db    0         ; allow VGA 256 palette changes
  44.         db    1         ; proportional font switch
  45.         dw    0ffffh         ; fillmask for lines
  46.         dw    0         ; viewport - minx
  47.         dw    0         ; viewport - miny
  48.         dw    639         ; viewport - maxx
  49.         dw    199         ; viewport - maxy
  50.         db    1         ; viewport - clipping on/off
  51.         dw    15         ; Mouse color
  52.         dw    0         ; Mouse hotspot
  53.         dw    0         ; Mouse hotspot
  54.         dd    0         ; Mouse Cursor Mask
  55.         dd    0         ; Next VideoMode
  56.  
  57. modeend:    dw    0ffffh         ; 0ffff - last mode
  58.  
  59.         dw   initvideomode   ; mode:word,TEGLTable:dword,initflg:byte
  60.         dw   setxlattable    ; XlatTable:dword
  61.         dw   setvideotable   ; TEGLTable:dword
  62.         dw   getvideotable   ; returns pointer to TEGLTable
  63.         dw   imagesize         ; argx1:word,argy1:word,argx2:word,argy2:word
  64.         dw   fastline         ; argx1:word,argy1:word,argx2:word,argy2:word,color:word
  65.         dw   scanborder      ; argx:word,argy:word,bordercolor:word,scan:word
  66.         dw   putpixs         ; argx:word,argy:word,color:word
  67.         dw   getpixs         ; argx:word,argy:word
  68.         dw   getbiti         ; argx0:word,argy0:word,argx1:word,argy1:word,addrbuf:dword
  69.         dw   putbiti         ; argx:word,argy:word,addrbuf:dword,rmwb:word
  70.         dw   extractimg      ; argx0:word,argy0:word,argx1:word,argy1:word,addrbuf1:dword,addrbuf2:dword
  71.         dw   overlayimg      ; argx0:word,argy0:word,addrbuf1:dword,addrbuf2:dword
  72.         dw   extractpixs     ; argx0:word,argy0:word,addrbuff:dword
  73.         dw   wrtchar         ; argc:word,argx:word,argy:word,argfgd:word
  74.         dw   mcursoroff      ;
  75.         dw   mcursoron         ; argx:word,argy:word
  76.         dw   msetpos         ; argx:word,argy:word
  77.         dw   movevideopixels ; argx0:word,argy0:word,argx1:word,argy1:word,argx2:word,argy2:word,vertlines:word,horzlines:word,spage:word,tpage:word
  78.         dw   setvpage         ; pagen:word
  79.         dw   setapage         ; pagen:word
  80.  
  81.         db   16 dup (0) ;required for driver alignment
  82.  
  83. ; 3 bytes/row * 17rows + 5 byte header
  84. mcursorsavearea db   60 dup (0)
  85. mflag        dw   0
  86. scradrofs    dw   0
  87. scradrseg    dw   0
  88. TDTable     dd   0
  89. XLTable     dd   0
  90.  
  91. nextinterleave    =    2000h
  92. firstinterleave =    80-2000h
  93.  
  94.  
  95. initvideomode    proc    far
  96.  
  97.         push    ds
  98.         push    si
  99.         lds    si,cs:TDTable
  100.         mov    bx,ds:[si].vmodenum
  101.         pop    si
  102.         pop    ds
  103.  
  104.         mov    ax,ds
  105.         or    ax,ax
  106.         mov    ax,-10
  107.         jz    noinitmode
  108.  
  109.         or    bx,bx
  110.         jnz    noinitmode
  111.  
  112.         mov    ax,6
  113.         int    10h
  114.         xor    ax,ax
  115. noinitmode:    ret
  116. initvideomode    endp
  117.  
  118.  
  119. setxlattable    proc    far XlatTable:dword
  120.         push    es
  121.         push    di
  122.  
  123.         les    di,XlatTable
  124.         mov    word ptr cs:XLTable,di
  125.         mov    word ptr cs:XLTable+2,es
  126.  
  127.         pop    di
  128.         pop    es
  129.         ret
  130. setxlattable    endp
  131.  
  132. setvideotable    proc    far TEGLTable:dword
  133.         push    es
  134.         push    di
  135.  
  136.         les    di,TEGLTable
  137.         mov    word ptr cs:TDTable,di
  138.         mov    word ptr cs:TDTable+2,es
  139.  
  140.         pop    di
  141.         pop    es
  142.         ret
  143. setvideotable    endp
  144.  
  145. getvideotable    proc    far
  146.  
  147.         mov    ax,word ptr cs:TDTable
  148.         mov    dx,word ptr cs:TDTable+2
  149.  
  150.         ret
  151. getvideotable    endp
  152.  
  153.  
  154. imagesize    proc    far argx1:word,argy1:word,argx2:word,argy2:word
  155.         push    bx
  156.  
  157.         mov    ax,argx2        ;x1-x+1
  158.         sub    ax,argx1
  159.         inc    ax
  160.  
  161.         mov    dx,ax
  162.         mov    cl,3
  163.         shr    ax,cl            ; /8
  164.  
  165.         and    dl,07h            ; check for byte
  166.         jz    hisz01            ; boundary
  167.         inc    ax
  168. hisz01:     mov    bx,argy2        ;y1-y+1
  169.         sub    bx,argy1
  170.         inc    bx
  171.         mul    bx            ;rows x bytes per row
  172.         add    ax,6            ;add 6 for header
  173.         adc    dx,0
  174.  
  175.         pop    bx
  176.         ret
  177. imagesize    endp
  178.  
  179.  
  180. fastline    proc    far argx1:word,argy1:word,argx2:word,argy2:word,color:word
  181.         local    varleafincr:word,varincr1:word,varincr2:word,varroutine:byte
  182.         local    rmwb:byte,fillmask:byte,bpline:word,transparent:byte
  183.  
  184.         push    ds
  185.         push    si
  186.         push    es
  187.         push    di
  188.  
  189.         cld
  190.         colorxlat color
  191.  
  192.         lds    si,cs:TDtable
  193.         mov    ax,ds:[si].rmwbits
  194.         mov    rmwb,al
  195.  
  196.         mov    ax,ds:[si].vbytesperline
  197.         mov    bpline,ax
  198.  
  199.         mov    ax,ds:[si].teglfillmask
  200.         mov    fillmask,al
  201.  
  202.         mov    al,ds:[si].transparency
  203.         mov    transparent,al
  204.  
  205.         mov    si,nextinterleave  ; increment for video buffer interleave
  206.         mov    di,firstinterleave ; increment from last to first interleave
  207.  
  208.         mov    cx,argx2
  209.         sub    cx,argx1    ; cx := x2 - x1
  210.         jz    vertlinecga    ; jump if vertical line
  211.  
  212. ; force x1 < x2
  213.  
  214.         jns    cgl01        ; jump if x2 > x1
  215.  
  216.         neg    cx        ; cx := x1 - x2
  217.  
  218.         mov    bx,argx2    ; exchange x1 and x2
  219.         xchg    bx,argx1
  220.         mov    argx2,bx
  221.  
  222.         mov    bx,argy2    ; exchange y1 and y2
  223.         xchg    bx,argy1
  224.         mov    argy2,bx
  225.  
  226. ; calculate dy = abs(y2-y1)
  227.  
  228. cgl01:        mov    bx,argy2
  229.         sub    bx,argy1    ; bx := y2 - y1
  230.         jnz    cgl02
  231.  
  232.         jmp    horizlinecga    ; jump if horizontal line
  233.  
  234. cgl02:        jns    cgl03
  235.  
  236.         neg    bx        ; bx := y1 - y2
  237.         neg    si        ; negate increments for buffer interleave
  238.         neg    di
  239.         xchg    si,di
  240.  
  241. ; select appropriate routine for slope of line
  242.  
  243. cgl03:        mov    varleafincr,di    ; save increment for buffer interleave
  244.  
  245.         mov    varroutine,0    ; loslopelinecga
  246.         cmp    bx,cx
  247.         jle    cgl04        ; jump if dy <= dx (slope <= 1)
  248.         not    varroutine    ; hislopelinecga
  249.         xchg    bx,cx        ; exchange dy and dx
  250.  
  251. ; calculate initial decision variable and increments
  252.  
  253. cgl04:        shl    bx,1        ; bx := 2 * dy
  254.         mov    varincr1,bx    ; incr1 := 2 * dy
  255.         sub    bx,cx
  256.         mov    di,bx        ; di := d = 2 * dy - dx
  257.         sub    bx,cx
  258.         mov    varincr2,bx    ; incr2 := 2 * (dy - dx)
  259.  
  260. ; calculate first pixel address
  261.  
  262.         push    cx        ; preserve this register
  263.         mov    ax,argy1    ; ax := y
  264.         mov    bx,argx1    ; bx := x
  265.         call    activeaddr    ; ah := bit mask
  266.                     ; es:bx -> buffer
  267.                     ; cl := # bits to shift left
  268.  
  269.         rol    fillmask,cl    ; ***********fillmask
  270.  
  271.         mov    al,byte ptr [color]   ; al := unshifted pixel value
  272.  
  273.         cmp    rmwb,80h
  274.         jnz    oknot
  275.         not    al
  276. oknot:        and    al,1
  277.         shl    ax,cl        ; ah := bit mask in proper position
  278.                     ; al := pixel value in proper position
  279.  
  280.         mov    dx,ax        ; dh := bit mask
  281.                     ; dl := pixel value
  282.         not    dh        ; dh := inverse bit mask
  283.  
  284.         pop    cx        ; restore this register
  285.         inc    cx        ; cx := # of pixels to draw
  286.  
  287.         test    bh,20h
  288.         jz    cgl05
  289.         xchg    si,varleafincr
  290.  
  291. cgl05:        test    varroutine,1    ; jump to appropriate routine for slope
  292.         jnz    jmphislopeline
  293.         jmp    loslopelinecga
  294. jmphislopeline: jmp    hislopelinecga
  295.  
  296.  
  297. ; routine for vertical lines
  298.  
  299. vertlinecga:    mov    ax,argy1    ; ax := y1
  300.         mov    bx,argy2    ; bx := y2
  301.         mov    cx,bx
  302.         sub    cx,ax        ; cx := dy
  303.         jge    cgl31        ; jump if dy >= 0
  304.  
  305.         neg    cx        ; force dy >= 0
  306.         mov    ax,bx        ; ax := y2
  307.  
  308. cgl31:        inc    cx        ; cx := # of pixels to draw
  309.         mov    bx,argx1    ; bx := x
  310.         push    cx        ; preserve this register
  311.         call    activeaddr    ; ah := bit mask
  312.                     ; es:bx -> video buffer
  313.                     ; cl := # bits to shift left
  314.  
  315.         rol    fillmask,cl    ; ***********fillmask
  316.  
  317.         mov    al,byte ptr [color] ; al := unshifted pixel value
  318.  
  319.         cmp    rmwb,80h
  320.         jnz    oknot2
  321.         not    al
  322. oknot2:     and    al,1
  323.         shl    ax,cl        ; ah := bit mask in proper position
  324.                     ; al := pixel value in proper position
  325.         not    ah        ; ah := inverse bit mask
  326.         pop    cx        ; restore this register
  327.  
  328. ; draw the line
  329.         cmp    rmwb,18h    ; fgxor
  330.         jz    cgl36a        ; jump if pixel should be xored
  331.  
  332.         test    rmwb,08h    ; fgand
  333.         jnz    cgl35a        ; jump if pixel should be anded
  334.  
  335.         test    rmwb,10h    ; fgor
  336.         jnz    cgl37a        ; jump if pixel should be ored
  337.  
  338. ;------------------ [fgnorm] set bit
  339. cgl32:        test    bx,2000h
  340.         jz    cgl33
  341.         xchg    si,di
  342. cgl33:        and    es:[bx],ah
  343.  
  344.         mov    dh,al
  345.         and    al,fillmask
  346.  
  347.         or    es:[bx],al    ; set pixel values in buffer
  348.         mov    al,dh
  349.  
  350.         ror    fillmask,1    ; pattern
  351.         add    bx,si        ; increment to next portion of interleave
  352.         xchg    si,di
  353.         loop    cgl33
  354.         jmp    short cgl36
  355.  
  356. ;------------------ [fgand] set bit
  357. cgl35a:     test    bx,2000h
  358.         jz    cgl35b
  359.         xchg    si,di
  360. cgl35b:     mov    dh,es:[bx]
  361.  
  362.         mov    dl,al
  363.         and    al,fillmask
  364.  
  365.         and    dh,al
  366.         and    es:[bx],ah
  367.         or    es:[bx],dh
  368.  
  369.         mov    al,dl
  370.         ror    fillmask,1    ; pattern
  371.  
  372.         add    bx,si        ; increment to next portion of interleave
  373.         xchg    si,di
  374.         loop    cgl35b
  375.         jmp    short cgl36
  376.  
  377. ;------------------ [fgxor] set bit
  378. cgl36a:     test    bx,2000h
  379.         jz    cgl36c
  380.         xchg    si,di
  381. cgl36c:
  382.         mov    dl,al
  383.         and    al,fillmask
  384.  
  385.         xor    es:[bx],al
  386.         mov    al,dl
  387.         ror    fillmask,1    ; pattern
  388.  
  389.         add    bx,si        ; increment to next portion of interleave
  390.         xchg    si,di
  391.         loop    cgl36c
  392.         jmp    short cgl36
  393.  
  394. ;------------------ [fgor] set bit
  395. cgl37a:     test    bx,2000h
  396.         jz    cgl37c
  397.         xchg    si,di
  398. cgl37c:     mov    dh,ah
  399.         not    dh        ; reverse bits
  400.  
  401. cgl37b:     push    dx
  402.         push    ax
  403.  
  404.         and    al,fillmask
  405.         mov    dl,es:[bx]    ; get original screen pixel
  406.         and    dl,dh        ; and with required pixel
  407.         or    al,dl        ; set it on or off
  408.         and    al,dh
  409.         jz    cgl37and
  410.         or    es:[bx],al    ; reset pixel values in buffer
  411.         jmp    short cgl37n
  412. cgl37and:    and    es:[bx],ah    ; reset pixel values in buffer
  413.  
  414. cgl37n:     pop    ax
  415.         pop    dx
  416.  
  417.         ror    fillmask,1    ; pattern
  418.         add    bx,si        ; increment to next portion of interleave
  419.         xchg    si,di
  420.         loop    cgl37b
  421. ;------------------
  422. cgl36:        jmp    cglexit
  423.  
  424.  
  425. ; routine for horizontal lines (slope = 0)
  426.  
  427. horizlinecga:    mov    ax,argy1
  428.         mov    bx,argx1
  429.         call    activeaddr    ; ah := bit mask
  430.                     ; es:bx -> video buffer
  431.                     ; cl := # bits to shift left
  432.         mov    di,bx        ; es:di -> buffer
  433.  
  434.         mov    dh,ah
  435.         not    dh        ; dh := unshifted bit mask for leftmost
  436.                     ;     byte
  437.         mov    dl,0ffh     ; dl := unshifted bit mask for
  438.                     ;     rightmost byte
  439.  
  440.         shl    dh,cl        ; dh := reverse bit mask for first byte
  441.         not    dh        ; dh := bit mask for first byte
  442.  
  443.         test    transparent,0ffh
  444.         jnz    backfill    ; leave the mask alone if pattern fill
  445.         ror    fillmask,cl    ; ***********fillmask
  446.         ror    fillmask,1    ; ***********fillmask
  447.  
  448. backfill:    mov    cx,argx2
  449.         and    cl,7
  450.         xor    cl,7        ; cl := number of bits to shift left
  451.         shl    dl,cl        ; dl := bit mask for last byte
  452.  
  453. ; determine byte offset of first and last pixel in the line
  454.  
  455.         mov    ax,argx2    ; ax := x2
  456.         mov    bx,argx1    ; bx := x1
  457.  
  458.         mov    cl,3        ; number of bits to shift to
  459.                         ;  convert pixels to bytes
  460.  
  461.         shr    ax,cl        ; ax := byte offset of x2
  462.         shr    bx,cl        ; bx := byte offset of x1
  463.         mov    cx,ax
  464.         sub    cx,bx        ; cx := (# bytes in line) - 1
  465.  
  466.         mov    al,byte ptr [color] ; al := pixel value
  467.         mov    ah,byte ptr [fillmask]
  468.         not    ah
  469.  
  470.         xor    al,ah
  471.         test    byte ptr [color],0ffh
  472.         jnz    cglcolored
  473.         xor    al,al
  474.  
  475. cglcolored:    cmp    rmwb,18h    ; fgxor
  476.         jz    cglxor        ; jump if pixel should be xored
  477.  
  478.         test    rmwb,08h    ; fgand
  479.         jnz    cgland        ; jump if pixel should be anded
  480.  
  481.         test    rmwb,10h    ; fgor
  482.         jz    chknot
  483.         jmp    cglor        ; jump if pixel should be ored
  484.  
  485. chknot:     cmp    rmwb,80h
  486.         jnz    cglnorm
  487.         not    al
  488.  
  489. ;------------------ [fgnorm] set bit
  490. cglnorm:    or    dh,dh
  491.         js    cgl43        ; jump if byte-aligned (x1 is leftmost
  492.                     ;  pixel in byte)
  493.         or    cx,cx
  494.         jnz    cgl42        ; jump if more than one byte in the line
  495.         and    dl,dh        ; bit mask for the line
  496.         jmp    short cgl44
  497. cgl42:        mov    ah,al
  498.         and    ah,dh        ; ah := masked pixel bits
  499.         not    dh        ; dh := reverse bit mask for 1st byte
  500.         and    es:[di],dh    ; zero masked pixels in buffer
  501.         or    es:[di],ah    ; update masked pixels in buffer
  502.         inc    di
  503.         dec    cx
  504. cgl43:        rep    stosb        ; update all pixels in the line
  505. cgl44:        and    al,dl        ; al := masked pixels for last byte
  506.         not    dl
  507.         and    es:[di],dl    ; zero masked pixels in buffer
  508.         or    es:[di],al    ; update masked pixels in buffer
  509.         jmp    cglexit
  510.  
  511. ;------------------ [fgxor] set bit
  512. cglxor:
  513.         or    cx,cx
  514.         jnz    hlxor42     ; jump if more than one byte in the line
  515.         and    dl,dh        ; bit mask for the line
  516.         jmp    short hlxor44
  517. hlxor42:    mov    ah,al
  518.         xor    ah,es:[di]
  519.         and    ah,dh        ; ah := masked pixel bits
  520.         not    dh        ; dh := reverse bit mask for 1st byte
  521.         and    es:[di],dh    ; zero masked pixels in buffer
  522.         or    es:[di],ah    ; update masked pixels in buffer
  523.         inc    di
  524.         dec    cx
  525.         jz    hlxor44
  526. hlxor43:    xor    es:[di],al
  527.         inc    di
  528.         loop    hlxor43     ; update all pixels in the line
  529. hlxor44:    xor    al,es:[di]
  530.         and    al,dl        ; al := masked pixels for last byte
  531.         not    dl
  532.         and    es:[di],dl    ; zero masked pixels in buffer
  533.         or    es:[di],al    ; update masked pixels in buffer
  534.         jmp    cglexit
  535.  
  536. ;------------------ [fgand] set bit
  537. cgland:
  538.         or    cx,cx
  539.         jnz    hland42     ; jump if more than one byte in the line
  540.         and    dl,dh        ; bit mask for the line
  541.         jmp    short hland44
  542. hland42:    mov    ah,al
  543.         and    ah,es:[di]
  544.         and    ah,dh        ; ah := masked pixel bits
  545.         not    dh        ; dh := reverse bit mask for 1st byte
  546.         and    es:[di],dh    ; zero masked pixels in buffer
  547.         or    es:[di],ah    ; update masked pixels in buffer
  548.         inc    di
  549.         dec    cx
  550.         jz    hland44
  551. hland43:    and    es:[di],al
  552.         inc    di
  553.         loop    hland43     ; update all pixels in the line
  554. hland44:    and    al,es:[di]
  555.         and    al,dl        ; al := masked pixels for last byte
  556.         not    dl
  557.         and    es:[di],dl    ; zero masked pixels in buffer
  558.         or    es:[di],al    ; update masked pixels in buffer
  559.         jmp    cglexit
  560.  
  561. ;------------------ [fgor] set bit
  562. cglor:
  563.         or    cx,cx
  564.         jnz    hlor42        ; jump if more than one byte in the line
  565.         and    dl,dh        ; bit mask for the line
  566.         jmp    short hlor44
  567. hlor42:     mov    ah,al
  568.         or    ah,es:[di]
  569.         and    ah,dh        ; ah := masked pixel bits
  570.         not    dh        ; dh := reverse bit mask for 1st byte
  571.         and    es:[di],dh    ; zero masked pixels in buffer
  572.         or    es:[di],ah    ; update masked pixels in buffer
  573.         inc    di
  574.         dec    cx
  575.         jz    hlor44
  576. hlor43:     or    es:[di],al
  577.         inc    di
  578.         loop    hlor43        ; update all pixels in the line
  579. hlor44:     or    al,es:[di]
  580.         and    al,dl        ; al := masked pixels for last byte
  581.         not    dl
  582.         and    es:[di],dl    ; zero masked pixels in buffer
  583.         or    es:[di],al    ; update masked pixels in buffer
  584.         jmp    cglexit
  585.  
  586.  
  587.  
  588. ; routine for dy <= dx (slope <= 1)    ; es:bx -> video buffer
  589.                     ; cx = #pixels to draw
  590.                     ; dh = inverse bit mask
  591.                     ; dl = pixel value in proper position
  592.                     ; si = buffer interleave increment
  593.                     ; di = decision variable
  594. loslopelinecga:
  595.  
  596. cgl10:        mov    ah,es:[bx]    ; ah := byte from video buffer
  597.  
  598. cgl11:
  599. ;****************** check for norm/and/or/xor/not
  600.         test    rmwb,0ffh    ; fgnorm
  601.         jz    cgl14d
  602.  
  603.         test    rmwb,08h    ; fgand
  604.         jz    cgl14b
  605.  
  606.         test    rmwb,10h    ; fgxor
  607.         jnz    cgl14a
  608.  
  609.         push    dx
  610.         and    dl,fillmask
  611.         mov    al,ah        ; screen
  612.         and    ah,dl        ; and with bit
  613.         and    al,dh        ; mask screen to zero
  614.         or    ah,al        ; or with new and bit
  615.         pop    dx
  616.         jmp    short cgl14e
  617.  
  618. cgl14a:     mov    al,dl
  619.         and    al,fillmask
  620.         xor    ah,al
  621.         jmp    short cgl14e
  622.  
  623. cgl14b:     test    rmwb,80h    ; fgnot (implemented above)
  624.         jz    cgl14c
  625.         jmp    short cgl14d
  626.  
  627. cgl14c:     test    rmwb,10h    ; fgor
  628.         jz    cgl14d
  629.         jmp    short cgl14f
  630.  
  631. ;        mov    al,dl
  632. ;        and    al,fillmask
  633. ;        or    ah,al        ; set pixel value in byte
  634. ;        jmp    short cgl14e
  635.  
  636. cgl14d:     and    ah,dh        ; zero pixel value at current bit offset
  637. cgl14f:     mov    al,dl
  638.         and    al,fillmask
  639.         or    ah,al        ; set pixel value in byte
  640.  
  641. ;************************************************
  642. cgl14e:     ror    dl,1        ; rotate pixel value
  643.         ror    dh,1        ; rotate bit mask
  644.         jnc    cgl14        ; jump if bit mask rotated to
  645.                     ;  leftmost pixel position
  646.  
  647. ; bit mask not shifted out
  648.  
  649.         or    di,di        ; test sign of d
  650.         jns    cgl12        ; jump if d >= 0
  651.  
  652.         add    di,varincr1    ; d := d + incr1
  653.         loop    cgl11
  654.  
  655.         mov    es:[bx],ah    ; store remaining pixels in buffer
  656.         jmp    cglexit
  657.  
  658. cgl12:        add    di,varincr2    ; d := d + incr2
  659.         mov    es:[bx],ah    ; update buffer
  660.  
  661.         jmp    short cgl15b
  662.  
  663. ;        add    bx,si        ; increment y
  664. ;        xchg    si,varleafincr
  665. ;        loop    cgl10
  666. ;        jmp    cglexit
  667.  
  668. ; bit mask shifted out
  669.  
  670. cgl14:        mov    es:[bx],ah    ; update buffer
  671.         inc    bx        ; bx := offset of next byte
  672.  
  673.         or    di,di        ; test sign of d
  674.         jns    cgl15        ; jump if non-negative
  675.  
  676.         add    di,varincr1    ; d := d + incr1
  677.         loop    cgl10
  678.         jmp    short cglexit
  679.  
  680. cgl15:        add    di,varincr2    ; d := d + incr2
  681.  
  682. cgl15b:     add    bx,si        ; increment y
  683.         xchg    si,varleafincr
  684.         loop    cgl10        ; loop until all pixels are set
  685.         jmp    short cglexit
  686.  
  687.  
  688. ; routine for dy > dx (slope > 1)    ; es:bx -> video buffer
  689.                     ; cx = #pixels to draw
  690.                     ; dh = inverse bit mask
  691.                     ; dl = pixel value in proper position
  692.                     ; si = buffer interleave increment
  693.                     ; di = decision variable
  694. hislopelinecga:
  695.  
  696. cgl21:
  697. ;****************** check for norm/and/or/xor/not
  698.         test    rmwb,0ffh    ; fgnorm
  699.         jz    cgl21d
  700.  
  701.         test    rmwb,08h    ; fgand
  702.         jz    cgl21b
  703.  
  704.         test    rmwb,10h    ; fgxor
  705.         jnz    cgl21a
  706.  
  707.         push    dx
  708.         and    dl,fillmask
  709.         mov    al,es:[bx]    ; screen
  710.         and    al,dl        ; and with bit
  711.         and    es:[bx],dh    ; mask screen to zero
  712.         or    es:[bx],al    ; or with new and bit
  713.         pop    dx
  714.         jmp    short cgl21e
  715.  
  716. cgl21a:     push    dx
  717.         and    dl,fillmask
  718.         xor    es:[bx],dl
  719.         pop    dx
  720.         jmp    short cgl21e
  721.  
  722. cgl21b:     test    rmwb,80h    ; fgnot (implemented above)
  723.         jz    cgl21c
  724.         jmp    short cgl21d
  725.  
  726. cgl21c:     test    rmwb,10h    ; fgor
  727.         jz    cgl21d
  728.         push    dx
  729.         and    dl,fillmask
  730.         or    es:[bx],dl    ; set pixel value in byte
  731.         pop    dx
  732.         jmp    short cgl21e
  733.  
  734. cgl21d:     push    dx
  735.         and    dl,fillmask
  736.         and    es:[bx],dh    ; zero pixel value in video buffer
  737.         or    es:[bx],dl    ; set pixel value in byte
  738.         pop    dx
  739.  
  740. ;************************************************
  741.  
  742. cgl21e:     add    bx,si        ; increment y
  743.         xchg    si,varleafincr
  744.  
  745. cgl22:        or    di,di
  746.         jns    cgl23        ; jump if d >= 0
  747.  
  748.         add    di,varincr1    ; d := d + incr1
  749.         loop    cgl21
  750.         jmp    short cglexit
  751.  
  752.  
  753. cgl23:        add    di,varincr2    ; d := d + incr2
  754.  
  755.         ror    dl,1        ; rotate pixel value
  756.         ror    dh,1        ; rotate bit mask
  757.         cmc            ; cf set if bit mask not rotated to
  758.                     ;  leftmost pixel position
  759.         adc    bx,0        ; bx := offset of next byte
  760.  
  761.         loop    cgl21
  762.  
  763. cglexit:    pop    di
  764.         pop    es
  765.         pop    si
  766.         pop    ds
  767.         ret
  768. fastline    endp
  769.  
  770.  
  771. putpixs     proc    far argx:word,argy:word,color:word
  772.         local    rmwb:word
  773.  
  774.         push    ds
  775.         push    si
  776.         push    es
  777.         push    di
  778.  
  779.         colorxlat color
  780.  
  781.         lds    si,cs:TDtable
  782.         mov    ax,ds:[si].rmwbits
  783.         mov    rmwb,ax
  784.  
  785.         mov    ax,ds:[si].wminy
  786.         cmp    argy,ax
  787.         jl    pix14e
  788.  
  789.         mov    ax,ds:[si].wmaxy
  790.         cmp    argy,ax
  791.         jg    pix14e
  792.  
  793.         mov    ax,ds:[si].wminx
  794.         cmp    argx,ax
  795.         jl    pix14e
  796.  
  797.         mov    ax,ds:[si].wmaxx
  798.         cmp    argx,ax
  799.         jg    pix14e
  800.  
  801.         mov    al,byte ptr [color] ; al := unshifted pixel value
  802.         cmp    rmwb,80h
  803.         jnz    pixnot
  804.         not    al
  805. pixnot:     mov    byte ptr [color],al
  806.  
  807.         mov    ax,argy     ; ax := y
  808.         mov    bx,argx     ; bx := x
  809.         call    activeaddr    ; ah := bit mask
  810.                     ; es:bx -> buffer
  811.                     ; cl := # bits to shift left
  812.  
  813. ; set the pixel value
  814.         shl    ah,cl        ; ah := bit mask in proper position
  815.         mov    al,ah
  816.         not    ah
  817.         and    al,byte ptr [color]
  818.  
  819. ;****************** check for norm/and/or/xor/not
  820.         test    rmwb,0ffh    ; fgnorm
  821.         jz    pix14d
  822.  
  823.         test    rmwb,08h    ; fgand
  824.         jz    pix14b
  825.  
  826.         test    rmwb,10h    ; fgxor
  827.         jnz    pix14a
  828.  
  829.         mov    dl,es:[bx]    ; screen
  830.         and    dl,al        ; and with bit
  831.         and    es:[bx],ah    ; mask screen to zero
  832.         or    es:[bx],dl    ; or with new and bit
  833.         jmp    short pix14e
  834.  
  835. pix14a:     xor    es:[bx],al
  836.         jmp    short pix14e
  837.  
  838. pix14b:     test    rmwb,80h    ; fgnot (implemented above)
  839.         jz    pix14c
  840.         jmp    short pix14d
  841.  
  842. pix14c:     test    rmwb,10h    ; fgor
  843.         jz    pix14d
  844.         or    es:[bx],al
  845.         jmp    short pix14e
  846.  
  847. pix14d:     and    es:[bx],ah
  848.         or    es:[bx],al
  849. ;************************************************
  850. pix14e:
  851.         pop    di
  852.         pop    es
  853.         pop    si
  854.         pop    ds
  855.         ret
  856.  
  857. putpixs     endp
  858.  
  859.  
  860. scanborder    proc    far argx:word,argy:word,bordercolor:word,scan:word
  861.         local    swminx:word,swmaxx:word,bwminx:word,bwmaxx:word
  862.         push    ds
  863.         push    si
  864.         push    es
  865.         push    di
  866.  
  867.         mov    cl,3
  868.         lds    si,cs:TDtable
  869.         mov    ax,ds:[si].wminx
  870.         mov    swminx,ax
  871.         shr    ax,cl
  872.         mov    bwminx,ax
  873.         mov    ax,ds:[si].wmaxx
  874.         mov    swmaxx,ax
  875.         shr    ax,cl
  876.         mov    bwmaxx,ax
  877.  
  878.  
  879.         mov    ax,argy     ; ax := y
  880.         xor    bx,bx        ; bx := x = 0
  881.         call    activeaddr    ; ah := bit mask
  882.                     ; es:bx -> buffer
  883.                     ; cl := #bits to shift
  884.         mov    di,bx        ; es:di -> buffer
  885.  
  886.         mov    ax,argx
  887.         mov    si,ax
  888.         mov    cl,3
  889.         shr    si,cl
  890.         add    di,si
  891.  
  892.         test    scan,8000h
  893.         jz    forwscan
  894.  
  895.         ; inspect first byte
  896. backscan:    mov    cx,argx         ;create mask to check
  897.         not    cl            ;first byte
  898.         and    cl,7
  899.         mov    ch,0ffh
  900.         shl    ch,cl
  901.  
  902.         mov    al,es:[di]
  903.         dec    di
  904.         and    al,ch
  905.         jnz    scanl05
  906.  
  907.         ;scan remainder of line for border pixels
  908.         mov    cx,si
  909.         inc    cx
  910.         sub    cx,bwminx
  911.         jle    scanl05
  912.         jcxz    scanl05
  913.  
  914.         std
  915.         repe    scasb
  916.         mov    al,es:[di+1]
  917.         cld
  918.  
  919. scanl05:    sub    di,bx
  920.         inc    di
  921.         mov    cl,3
  922.         shl    di,cl
  923.         mov    cx,7
  924.  
  925. scanl06:    shr    al,1
  926.         jc    scanl07
  927.         loop    scanl06
  928.  
  929. scanl07:    add    di,cx
  930.         jmp    scanl08
  931.  
  932.  
  933.  
  934.         ; inspect first byte
  935. forwscan:    mov    cx,argx         ;create mask to check
  936.         and    cl,7            ;first byte
  937.         mov    ch,0ffh
  938.         shr    ch,cl
  939.  
  940.         mov    al,es:[di]
  941.         inc    di
  942.         and    al,ch
  943.         jnz    scanl01
  944.  
  945.         ;scan remainder of line for border pixels
  946.  
  947.         mov    cx,bwmaxx
  948.         inc    cx
  949.         sub    cx,si
  950.         jle    scanl01
  951.         jcxz    scanl01
  952.         dec    cx
  953.  
  954.         cld
  955.         repe    scasb
  956.         mov    al,es:[di-1]
  957.  
  958. scanl01:    sub    di,bx
  959.         mov    cl,3
  960.         shl    di,cl
  961.         mov    cx,8
  962.  
  963. scanl02:    shl    al,1
  964.         jc    scanl03
  965.         loop    scanl02
  966.  
  967. scanl03:    sub    di,cx
  968.  
  969. scanl08:    mov    ax,swminx
  970.         dec    ax
  971.         cmp    di,ax
  972.         jle    scanl04
  973.         mov    ax,swmaxx
  974.         inc    ax
  975.         cmp    di,ax
  976.         jge    scanl04
  977.  
  978.         mov    ax,di
  979. scanl04:
  980.         pop    di
  981.         pop    es
  982.         pop    si
  983.         pop    ds
  984.         ret
  985. scanborder    endp
  986.  
  987.  
  988. getpixs     proc    far argx:word,argy:word
  989.         push    si
  990.  
  991.         mov    ax,argy     ; ax := y
  992.         mov    bx,argx     ; bx := x
  993.         call    activeaddr    ; ah := bit mask
  994.                     ; es:bx -> buffer
  995.                     ; cl := #bits to shift
  996.  
  997.         mov    al,es:[bx]
  998.         shr    al,cl
  999.         and    al,ah
  1000.         xor    ah,ah
  1001.  
  1002.         pop    si
  1003.         ret
  1004. getpixs     endp
  1005.  
  1006.  
  1007. getbiti     proc    far argx0:word,argy0:word,argx1:word,argy1:word,addrbuf:dword
  1008.         local    varpixelrows : word, varpixelrowlen : word
  1009.  
  1010.         push    ds
  1011.         push    si
  1012.         push    di
  1013.  
  1014. ; compute dimensions of bit block
  1015.  
  1016.         mov    ax,argx1
  1017.         sub    ax,argx0
  1018.         mov    cx,0ff07h    ; ch := unshifted bit mask
  1019.                     ; cl := and mask for al
  1020.         and    cl,al        ; cl := number of pixels in last
  1021.                     ;  byte of row
  1022.         xor    cl,7        ; cl := number of bits to shift
  1023.         shl    ch,cl        ; ch := bit mask for last byte of row
  1024.         mov    cl,ch
  1025.         push    cx        ; save on stack
  1026.  
  1027.         mov    cl,3
  1028.         shr    ax,cl
  1029.         inc    ax        ; ax := number of bytes per row
  1030.         push    ax        ; save on stack
  1031.  
  1032.         mov    ax,argy1
  1033.         sub    ax,argy0
  1034.         inc    ax        ; ax := number of pixel rows
  1035.         push    ax        ; save on stack
  1036.  
  1037. ; establish addressing
  1038.  
  1039.         mov    ax,argy0
  1040.         mov    bx,argx0
  1041.         call    activeaddr    ; es:bx -> x0,y0 in video buffer
  1042.         xor    cl,7        ; cl := number of bits to shift left
  1043.         push    es
  1044.         pop    ds
  1045.         mov    si,bx        ; ds:si -> video buffer
  1046.  
  1047.         les    di,addrbuf    ; es:di -> buffer in system ram
  1048.  
  1049. ; build 5-byte bit block header
  1050.  
  1051.         pop    ax
  1052.         mov    varpixelrows,ax
  1053.         stosw            ; byte 0-1 := number of pixel rows
  1054.         pop    ax
  1055.         mov    varpixelrowlen,ax
  1056.         stosw            ; byte 2-3 := bytes per pixel row
  1057.         pop    ax
  1058.         mov    ch,al        ; ch := bit mask for last byte
  1059.         stosb            ; byte 4 := bit mask for last byte
  1060.  
  1061. ; copy from video buffer to system ram
  1062.  
  1063. getbl02:    mov    bx,varpixelrowlen
  1064.         push    si        ; preserve si at start of pixel row
  1065.  
  1066. getbl03:    lodsw            ; al := next byte in video buffer
  1067.                     ; ah := (next byte) + 1
  1068.         dec    si        ; ds:si -> (next byte) + 1
  1069.         rol    ax,cl        ; al := next 4 pixels in row
  1070.         stosb            ; copy to system ram
  1071.         dec    bx        ; loop across row
  1072.         jnz    getbl03
  1073.  
  1074.         and    es:[di-1],ch    ; mask last byte of row
  1075.         pop    si        ; ds:si -> start of row
  1076.  
  1077.         test    si,2000h       ; check if second half
  1078.         jnz    gbl03a
  1079.         add    si,nextinterleave-firstinterleave
  1080. gbl03a:     add    si,firstinterleave
  1081.         dec    varpixelrows
  1082.         jnz    getbl02     ; loop down rows
  1083.  
  1084.  
  1085.         pop    di
  1086.         pop    si
  1087.         pop    ds
  1088.         ret
  1089. getbiti     endp
  1090.  
  1091.  
  1092. putbiti     proc    far argx:word,argy:word,addrbuf:dword,rmwb:word
  1093.         local    varpixelrows:word,varpixelrowlen:word
  1094.  
  1095.         ; rmwbits -   normalput        00h
  1096.         ;          xorput           18h
  1097.         ;          orput           10h
  1098.         ;          andput           08h
  1099.         ;          notput           80h
  1100.  
  1101.         push    ds
  1102.         push    si
  1103.         push    di
  1104.  
  1105.         cld
  1106. ; establish addressing
  1107.  
  1108.         mov    ax,argy
  1109.         mov    bx,argx
  1110.         call    activeaddr    ; es:bx -> byte offset of x,y
  1111.         xor    cl,7        ; cl := number of bits to shift right
  1112.  
  1113.         mov    di,bx        ; es:di -> x,y in video buffer
  1114.         lds    si,addrbuf    ; es:di -> buffer in system ram
  1115.  
  1116. ; obtain dimensions of bit block from header
  1117.  
  1118.         lodsw            ; ax := number of pixel rows
  1119.         mov    varpixelrows,ax
  1120.         lodsw            ; ax := bytes per pixel row
  1121.         mov    varpixelrowlen,ax
  1122.         lodsb            ; al := bit mask for last byte in row
  1123.         mov    ch,al
  1124.  
  1125. ;****************** check for norm/and/or/xor/not
  1126.         test    rmwb,0ffh    ; fgnorm
  1127.         jz    replacebitblock
  1128.  
  1129.         cmp    rmwb,18h    ; fgxor
  1130.         jnz    puttst00
  1131.         jmp    xorbitblock
  1132.  
  1133. puttst00:    test    rmwb,08h    ; fgand
  1134.         jz    puttst01
  1135.         jmp    andbitblock
  1136.  
  1137. puttst01:    test    rmwb,10h    ; fgor
  1138.         jz    puttst02
  1139.         jmp    orbitblock
  1140.  
  1141. puttst02:    test    rmwb,80h    ; fgnot
  1142.         jz    replacebitblock
  1143.         jmp    notbitblock
  1144. ;************************************************
  1145.  
  1146. replacebitblock:
  1147.         cmp    cx,0ff00h    ; if mask <> 0ffh or bits to shift <> 0
  1148.         jne    putbl15     ;  jump if not byte-aligned
  1149.  
  1150. ; routine for byte-aligned bit blocks
  1151.  
  1152.         mov    cx,varpixelrowlen
  1153.  
  1154. putbl10:    push    di        ; preserve di and cx
  1155.         push    cx
  1156.         rep    movsb        ; copy one pixel row into video buffer
  1157.         pop    cx        ; restore di and cx
  1158.         pop    di
  1159.  
  1160.         test    di,2000h       ; check if second half
  1161.         jnz    pbl10a
  1162.         add    di,nextinterleave-firstinterleave
  1163. pbl10a:     add    di,firstinterleave
  1164.  
  1165.         dec    varpixelrows
  1166.         jnz    putbl10     ; loop down pixel rows
  1167.  
  1168.         jmp    lexit2
  1169.  
  1170. ; routine for all other bit blocks
  1171.  
  1172. putbl15:    not    ch        ; ch := mask for end of row
  1173.         mov    dx,0ff00h
  1174.         ror    dx,cl        ; dx := rotated mask for each byte
  1175.  
  1176.         mov    bx,varpixelrowlen
  1177.         dec    bx        ; bx := bytes per row - 1
  1178.  
  1179. putbl16:    push    di
  1180.         test    bx,bx
  1181.         jz    putbl18     ; jump if only one byte per row
  1182.  
  1183.         push    bx
  1184.  
  1185. putbl17:    and    es:[di],dx    ; mask next 8 pixels in video buffer
  1186.         lodsb            ; al := pixels in bit block
  1187.         xor    ah,ah
  1188.         ror    ax,cl        ; ax := pixels rotated into position
  1189.         or    es:[di],ax    ; set pixels in video buffer
  1190.         inc    di        ; es:di -> next byte in bit block
  1191.         dec    bx
  1192.         jnz    putbl17
  1193.  
  1194.         pop    bx
  1195.  
  1196. putbl18:    mov    al,ch
  1197.         mov    ah,0ffh     ; ax := mask for last pixels in row
  1198.         ror    ax,cl        ; ax := mask rotated into position
  1199.         and    es:[di],ax    ; mask last pixels in video buffer
  1200.         lodsb            ; al := last byte in row
  1201.         xor    ah,ah
  1202.         ror    ax,cl        ; ax := pixels rotated into position
  1203.         or    es:[di],ax    ; set pixels in video buffer
  1204.  
  1205.         pop    di
  1206.  
  1207.         test    di,2000h       ; check if second half
  1208.         jnz    pbl18a
  1209.         add    di,nextinterleave-firstinterleave
  1210. pbl18a:     add    di,firstinterleave
  1211.         dec    varpixelrows
  1212.         jnz    putbl16     ; loop down pixel rows
  1213.  
  1214.         jmp    lexit2
  1215.  
  1216.  
  1217. xorbitblock:
  1218.         mov    bx,varpixelrowlen
  1219.  
  1220. putbl20:    push    di
  1221.         push    bx
  1222.  
  1223. putbl21:    lodsb            ; al := pixels in bit block
  1224.         xor    ah,ah
  1225.         ror    ax,cl        ; ax := pixels rotated into position
  1226.         xor    es:[di],ax    ; xor pixels into video buffer
  1227.         inc    di        ; es:di -> next byte in bit block
  1228.         dec    bx
  1229.         jnz    putbl21
  1230.  
  1231.         pop    bx
  1232.         pop    di
  1233.  
  1234.         test    di,2000h       ; check if second half
  1235.         jnz    pbl21a
  1236.         add    di,nextinterleave-firstinterleave
  1237. pbl21a:     add    di,firstinterleave
  1238.         dec    varpixelrows
  1239.         jnz    putbl20     ; loop down pixel rows
  1240.  
  1241.         jmp    lexit2
  1242.  
  1243. andbitblock:
  1244.         not    ch        ; ch := mask for end of row
  1245.  
  1246.         mov    bx,varpixelrowlen
  1247.         dec    bx        ; bx := bytes per row - 1
  1248.  
  1249. putbl30:    push    di
  1250.         test    bx,bx
  1251.         jz    putbl32     ; jump if only one byte per row
  1252.  
  1253.         push    bx
  1254.  
  1255. putbl31:    lodsb            ; al := pixels in bit block
  1256.         mov    ah,0ffh
  1257.         ror    ax,cl        ; ax := pixels rotated into position
  1258.         and    es:[di],ax    ; and pixels into video buffer
  1259.         inc    di        ; es:di -> next byte in bit block
  1260.         dec    bx
  1261.         jnz    putbl31
  1262.  
  1263.         pop    bx
  1264.  
  1265. putbl32:    lodsb            ; al := last byte in row
  1266.         or    al,ch        ; mask last pixels in row
  1267.         mov    ah,0ffh
  1268.         ror    ax,cl        ; ax := pixels rotated into position
  1269.         and    es:[di],ax    ; and pixels into video buffer
  1270.  
  1271.         pop    di
  1272.         test    di,2000h       ; check if second half
  1273.         jnz    pbl32a
  1274.         add    di,nextinterleave-firstinterleave
  1275. pbl32a:     add    di,firstinterleave
  1276.         dec    varpixelrows
  1277.         jnz    putbl30     ; loop down pixel rows
  1278.  
  1279.         jmp    lexit2
  1280.  
  1281.  
  1282. orbitblock:
  1283.         mov    bx,varpixelrowlen
  1284.  
  1285. putbl40:    push    di
  1286.         push    bx
  1287.  
  1288. putbl41:    lodsb            ; al := pixels in bit block
  1289.         xor    ah,ah
  1290.         ror    ax,cl        ; ax := pixels rotated into position
  1291.         or    es:[di],ax    ; or pixels into video buffer
  1292.         inc    di        ; es:di -> next byte in bit block
  1293.         dec    bx
  1294.         jnz    putbl41
  1295.  
  1296.         pop    bx
  1297.         pop    di
  1298.         test    di,2000h       ; check if second half
  1299.         jnz    pbl41a
  1300.         add    di,nextinterleave-firstinterleave
  1301. pbl41a:     add    di,firstinterleave
  1302.  
  1303.         dec    varpixelrows
  1304.         jnz    putbl40     ; loop down pixel rows
  1305.         jmp    lexit2
  1306.  
  1307. notbitblock:
  1308.         not    ch        ; ch := mask for end of row
  1309.         mov    dx,0ff00h
  1310.         ror    dx,cl        ; dx := rotated mask for each byte
  1311.  
  1312.         mov    bx,varpixelrowlen
  1313.         dec    bx        ; bx := bytes per row - 1
  1314.  
  1315. notbl16:    push    di
  1316.         test    bx,bx
  1317.         jz    notbl18     ; jump if only one byte per row
  1318.  
  1319.         push    bx
  1320.  
  1321. notbl17:    and    es:[di],dx    ; mask next 8 pixels in video buffer
  1322.         lodsb            ; al := pixels in bit block
  1323.         not    al
  1324.         xor    ah,ah
  1325.         ror    ax,cl        ; ax := pixels rotated into position
  1326.         or    es:[di],ax    ; set pixels in video buffer
  1327.         inc    di        ; es:di -> next byte in bit block
  1328.         dec    bx
  1329.         jnz    notbl17
  1330.  
  1331.         pop    bx
  1332.  
  1333. notbl18:    mov    al,ch
  1334.         mov    ah,0ffh     ; ax := mask for last pixels in row
  1335.         ror    ax,cl        ; ax := mask rotated into position
  1336.         and    es:[di],ax    ; mask last pixels in video buffer
  1337.         lodsb            ; al := last byte in row
  1338.         not    al
  1339.         not    ch
  1340.         and    al,ch
  1341.         not    ch
  1342.         xor    ah,ah
  1343.         ror    ax,cl        ; ax := pixels rotated into position
  1344.         or    es:[di],ax    ; set pixels in video buffer
  1345.  
  1346.         pop    di
  1347.         test    di,2000h       ; check if second half
  1348.         jnz    nbl18a
  1349.         add    di,nextinterleave-firstinterleave
  1350. nbl18a:     add    di,firstinterleave
  1351.         dec    varpixelrows
  1352.         jnz    notbl16     ; loop down pixel rows
  1353.  
  1354.  
  1355. lexit2:     pop    di
  1356.         pop    si
  1357.         pop    ds
  1358.         ret
  1359.  
  1360. putbiti     endp
  1361.  
  1362.  
  1363. extractimg    proc    far argx0:word,argy0:word,argx1:word,argy1:word,addrbuf1:dword,addrbuf2:dword
  1364.         local    var1pixelrows : word, var1pixelrowlen  : word
  1365.         local    var2pixelrows : word, var2pixelrowlen  : word
  1366.  
  1367.         push    ds
  1368.         push    si
  1369.         push    es
  1370.         push    di
  1371.  
  1372.         les    di,addrbuf1
  1373.         lds    si,addrbuf2
  1374.  
  1375.         cld
  1376.         lodsw                ; var2pixelrows
  1377.         mov    var2pixelrows,ax
  1378.         lodsw                ; var2pixelrows
  1379.         mov    var2pixelrowlen,ax
  1380.         lodsb
  1381.  
  1382.  
  1383. ; compute dimensions of bit block
  1384. ; build 5-byte bit block header
  1385.  
  1386.         ; number of pixel rows
  1387.         mov    ax,argy1
  1388.         sub    ax,argy0
  1389.         inc    ax
  1390.         mov    var1pixelrows,ax
  1391.         stosw
  1392.  
  1393.         ; number of bytes per row
  1394.         mov    ax,argx1
  1395.         sub    ax,argx0
  1396.         push    ax
  1397.         mov    cl,3            ; divide by 8 pix per byte
  1398.         shr    ax,cl
  1399.         inc    ax            ; ax := number of bytes per row
  1400.         mov    var1pixelrowlen,ax
  1401.         stosw
  1402.         pop    ax
  1403.  
  1404.         ; last byte in row bit mask
  1405.         mov    cx,0ff07h        ; ch := unshifted bit mask
  1406.                         ; cl := and mask for al
  1407.         and    cl,al            ; cl := remaining pixels in
  1408.                         ; last byte of row
  1409.         xor    cl,7
  1410.         shl    ch,cl            ; create the last byte mask
  1411.  
  1412.         mov    al,ch
  1413.         stosb
  1414.  
  1415. ; establish addressing
  1416.  
  1417.         mov    ax,argy0
  1418.         mov    bx,argx0
  1419.         mov    cl,bl
  1420.  
  1421.         mov    dx,var2pixelrowlen
  1422.         mul    dx            ; multiply rows by bytesperrow
  1423.  
  1424.         shr    bx,1            ; divide x coordinate by 8
  1425.         shr    bx,1
  1426.         shr    bx,1
  1427.         add    bx,ax            ; add to address
  1428.         add    si,bx
  1429.  
  1430.         and    cl,7            ; bits remainder
  1431.  
  1432. ; copy from bit block2 to bit block1
  1433.         mov    dx,var1pixelrows
  1434. extrc07:    mov    bx,var1pixelrowlen
  1435.         push    si
  1436.  
  1437. extrc08:    lodsw
  1438.         dec    si
  1439.         rol    ax,cl
  1440.         stosb
  1441.         dec    bx
  1442.         jnz    extrc08
  1443.  
  1444.         and    es:[di-1],ch
  1445.         pop    si
  1446.         add    si,var2pixelrowlen
  1447.  
  1448.         dec    dx
  1449.         jnz    extrc07
  1450.  
  1451.  
  1452.         pop    di
  1453.         pop    es
  1454.         pop    si
  1455.         pop    ds
  1456.         ret
  1457.  
  1458. extractimg    endp
  1459.  
  1460.  
  1461. overlayimg    proc    far argx0:word,argy0:word,addrbuf1:dword,addrbuf2:dword
  1462.         local    var1pixelrows : word, var1pixelrowlen  : word
  1463.         local    var2pixelrows : word, var2pixelrowlen  : word
  1464.         local    varstartmask  : byte, varendmaskl      : byte
  1465.         local    varendmaskr   : byte, screenmask       : byte
  1466.  
  1467.         push    ds
  1468.         push    si
  1469.         push    es
  1470.         push    di
  1471.  
  1472.         cld
  1473.  
  1474.         lds    si,addrbuf2
  1475.         lodsw            ; var2pixelrows
  1476.         mov    var2pixelrows,ax
  1477.         lodsw            ; var2pixelrows
  1478.         mov    var2pixelrowlen,ax
  1479.         lodsb
  1480.  
  1481.         push    ds
  1482.         push    si
  1483.         pop    di        ; es:di -> addrbuf2
  1484.         pop    es
  1485.  
  1486.         lds    si,addrbuf1
  1487.         lodsw            ; var1pixelrows
  1488.         mov    var1pixelrows,ax
  1489.         lodsw            ; var1pixelrows
  1490.         mov    var1pixelrowlen,ax
  1491.         lodsb
  1492.         mov    ch,al        ; ds:si -> addrbuf1
  1493.                     ; ch    -> last byte mask
  1494.  
  1495. ; establish addressing
  1496.  
  1497.         mov    ax,argy0
  1498.         mov    bx,argx0
  1499.         mov    cl,bl
  1500.  
  1501.         mov    dx,var2pixelrowlen
  1502.         mul    dx        ; multiply rows by bytesperrow
  1503.  
  1504.         shr    bx,1        ; divide x coordinate by 8
  1505.         shr    bx,1
  1506.         shr    bx,1
  1507.         add    bx,ax
  1508.         add    di,bx        ; add to address of addrbuf2
  1509.  
  1510.         and    cl,7
  1511.         xor    cl,7
  1512.         inc    cl
  1513.         and    cl,7        ; bits remainder
  1514.  
  1515.         cmp    cx,0ff00h
  1516.         jne    overl15
  1517.  
  1518. ; routine for byte-aligned bit blocks
  1519.         mov    cx,var1pixelrowlen
  1520.  
  1521.         mov    bx,var1pixelrows
  1522.  
  1523. overl11:    push    di
  1524.         push    cx
  1525.  
  1526.         rep    movsb
  1527.  
  1528.         pop    cx
  1529.         pop    di
  1530.         add    di,var2pixelrowlen
  1531.         dec    bx
  1532.         jnz    overl11
  1533.         jmp    overlexit
  1534.  
  1535.  
  1536. ; copy from bit block2 to bit block1
  1537.  
  1538. overl15:    mov    bx,0ffh     ; bh := 0 (mask for first byte in row
  1539.                     ; bl := 0ffh
  1540.         mov    al,ch        ; al := mask for last byte in pixel row
  1541.         cbw            ; ah := 0ffh (mask for last-1 byte)
  1542.  
  1543.         cmp    var1pixelrowlen,1
  1544.         jne    overl16     ; jump if more than one byte per row
  1545.  
  1546.         mov    bl,ch
  1547.         mov    ah,ch        ; ah := mask for last-1 byte
  1548.         xor    al,al        ; al := 0 (mask for last byte)
  1549.  
  1550. overl16:    shl    ax,cl        ; shift masks into position
  1551.         shl    bx,cl
  1552.  
  1553.  
  1554. ;        use not to invert mask
  1555.         not    ax
  1556.         mov    varendmaskl,ah
  1557.         mov    varendmaskr,al
  1558.         not    bh
  1559.         mov    varstartmask,bh
  1560.  
  1561.         mov    bx,var1pixelrowlen
  1562.  
  1563. ; set pixels row by row in the bit planes
  1564.  
  1565.         mov    ax,var1pixelrows
  1566. overl18:    push    ax
  1567.         push    di        ; offset of start of pixel row
  1568.         push    si        ; offset of row in bit block
  1569.         push    bx        ; bytes per pixel row
  1570.  
  1571.         mov    al,varstartmask ; mask first byte of row
  1572.         mov    screenmask,al
  1573.  
  1574.         lodsw            ; ah := 2nd byte of pixels
  1575.                     ; al := 1st byte of pixels
  1576.         dec    si        ; ds:si -> 2nd byte of pixels
  1577.         test    cl,cl
  1578.         jnz    overl19     ; jump if not left-aligned
  1579.  
  1580.         dec    bx        ; bx := bytes per row - 1
  1581.         jnz    overl20     ; jump if at least 2 bytes per row
  1582.         jmp    short overl22    ; jump if only one byte per row
  1583.  
  1584. overl19:    rol    ax,cl        ; ah := left part of 1st byte,
  1585.                     ;    right part of 2nd byte
  1586.  
  1587.         mov    dl,screenmask
  1588.         push    ax
  1589.         and    es:[di],dl
  1590.         not    dl
  1591.         and    ah,dl
  1592.         or    es:[di],ah    ; or pixels for left part of first byte
  1593.         pop    ax
  1594.  
  1595.         inc    di
  1596.         dec    bx        ; bx := bytes per row - 2
  1597.  
  1598. overl20:    ; set up bit mask for succeeding bytes
  1599.  
  1600.         mov    screenmask,0
  1601.  
  1602.         dec    bx
  1603.         jng    overl22     ; jump if only 1 or 2 bytes in pixel
  1604.  
  1605. ; set pixels in middle of row
  1606.  
  1607. overl21:    mov    dl,screenmask
  1608.         and    es:[di],dl    ; set pixels in right part of current
  1609.         not    dl
  1610.         and    al,dl
  1611.         or    es:[di],al    ; set pixels in right part of current
  1612.         inc    di        ; byte and left part of next byte
  1613.  
  1614.         lodsw            ; ah := next+1 byte of pixels
  1615.         dec    si        ; al := next byte of pixels
  1616.         rol    ax,cl        ; ah := left part of next byte, right
  1617.                     ;    part of next+1 byte
  1618.         dec    bx
  1619.         jnz    overl21     ; loop across pixel row
  1620.  
  1621. ; set pixels at end of row
  1622.  
  1623. overl22:    mov    bx,ax
  1624.         mov    al,varendmaskl
  1625.         and    es:[di],al
  1626.         not    al
  1627.         and    bl,al
  1628.         or    es:[di],bl
  1629.  
  1630.         mov    al,varendmaskr
  1631.         and    es:[di+1],al
  1632.         not    al
  1633.         and    bh,al
  1634.         or    es:[di+1],bh
  1635.  
  1636.         pop    bx
  1637.         pop    si
  1638.         add    si,bx
  1639.         pop    di
  1640.         add    di,var2pixelrowlen
  1641.  
  1642.         pop    ax
  1643.         dec    ax
  1644.         jnz    overl18
  1645.  
  1646. overlexit:    pop    di
  1647.         pop    es
  1648.         pop    si
  1649.         pop    ds
  1650.         ret
  1651. overlayimg    endp
  1652.  
  1653.  
  1654. extractpixs    proc    far argx0:word,argy0:word,addrbuff:dword
  1655.         local    varpixelrows : word, varpixelrowlen  : word
  1656.  
  1657.         push    ds
  1658.         push    si
  1659.         lds    si,addrbuff
  1660.  
  1661.         cld
  1662.         lodsw                ; varpixelrows
  1663.         mov    varpixelrows,ax
  1664.         lodsw                ; varpixelrows
  1665.         mov    varpixelrowlen,ax
  1666.         lodsb
  1667.  
  1668. ; establish addressing
  1669.         mov    ax,argy0
  1670.         mov    bx,argx0
  1671.         mov    cl,bl
  1672.  
  1673.         mov    dx,varpixelrowlen
  1674.         mul    dx            ; multiply rows by bytesperrow
  1675.  
  1676.         shr    bx,1            ; divide x coordinate by 8
  1677.         shr    bx,1
  1678.         shr    bx,1
  1679.         add    bx,ax            ; add to address
  1680.         add    si,bx
  1681.  
  1682.         and    cl,7            ; bits remainder
  1683.         xor    cl,7
  1684.  
  1685.         xor    ax,ax
  1686.  
  1687.         mov    al,ds:[si]
  1688.         shr    al,cl
  1689.         and    al,1
  1690.  
  1691.         pop    si
  1692.         pop    ds
  1693.         ret
  1694.  
  1695. extractpixs    endp
  1696.  
  1697.  
  1698. wrtchar     proc    far argc:word,argx:word,argy:word,argfgd:word,argbgd:word
  1699.         local    varshift:word,jaggy:word,transparent:byte,charshift:byte
  1700.         local    rmwb:word,bpline:word,bpchar:byte,lastbytemask:byte
  1701.  
  1702.         push    ds
  1703.         push    si
  1704.         push    es
  1705.         push    di
  1706.  
  1707.         colorxlat argfgd
  1708.  
  1709. ; set up character definition table addressing
  1710.  
  1711.         lds    si,cs:TDtable
  1712.         les    di,ds:[si].fonttable
  1713.  
  1714.         mov    ax,argc     ; al := character code
  1715.         xor    ah,ah
  1716.         cmp    al,es:[di].FontAsciiStart
  1717.         jb    nowrtjmp
  1718.         cmp    al,es:[di].FontAsciiEnd
  1719.         jbe    okwrtjmp
  1720.  
  1721. nowrtjmp:    jmp    wrtcexit
  1722. okwrtjmp:
  1723.  
  1724.         mov    ax,ds:[si].rmwbits
  1725.         mov    rmwb,ax
  1726.  
  1727.         mov    ax,ds:[si].vbytesperline
  1728.         mov    bpline,ax
  1729.  
  1730.         mov    al,ds:[si].transparency
  1731.         mov    transparent,al
  1732.  
  1733.         xor    ax,ax
  1734.         mov    al,ds:[si].jagged
  1735.         and    al,1
  1736.         xchg    al,ah
  1737.         mov    jaggy,ax
  1738.  
  1739. ; calculate first pixel address
  1740.         push    es
  1741.  
  1742.         mov    ax,argy     ; ax := y
  1743.         mov    bx,argx     ; bx := x
  1744.         call    activeaddr    ; es:bx -> buffer
  1745.                     ; cl := # bits to shift left to mask
  1746.                     ;  pixel
  1747.         inc    cx
  1748.         and    cl,7        ; cl := # bits to shift to mask char
  1749.  
  1750.         mov    ch,0ffh
  1751.         shl    ch,cl        ; ch := bit mask for right side of char
  1752.         mov    varshift,cx
  1753.  
  1754.         push    es        ; transfer es to ds
  1755.         pop    ds
  1756.         mov    si,bx        ; si := video buffer offset
  1757.  
  1758. ; set up character definition table addressing
  1759.         pop    es
  1760.  
  1761.         xor    ax,ax
  1762.         mov    al,es:[di].FontHeight ;Multiply fontheight by fontwidth
  1763.         mov    cx,ax
  1764.  
  1765.         xor    bx,bx
  1766.         mov    bl,es:[di].fontbytewidth
  1767.         mov    bpchar,bl
  1768.         mul    bx
  1769.  
  1770.         mov    dx,argc     ; dl := character code
  1771.         sub    dl,es:[di].FontAsciiStart
  1772.         mul    dx        ; ax := offset into char def table
  1773.                     ;  (points * char code)
  1774.  
  1775.         add    di,255 + size TEGLFontInfo ;skip font table info
  1776.         add    di,ax        ; add character offset
  1777.  
  1778.  
  1779.         xor    bx,bx
  1780.         mov    bl,bpchar    ; bytes per character
  1781.         mov    al,byte ptr [argfgd] ; al := pixel value
  1782.  
  1783.         cmp    rmwb,80h
  1784.         jnz    oknot5
  1785.         not    al
  1786. oknot5:     mov    byte ptr [argfgd],al
  1787.  
  1788. ; select output routine depending on whether character is byte-aligned
  1789.  
  1790.         test    byte ptr [varshift],0ffh ; test # bits to shift
  1791.         jne    I20a        ; jump if character is not byte-aligned
  1792.  
  1793.  
  1794. ; routine for byte-aligned characters
  1795.  
  1796.         mov    dx,jaggy
  1797.         xchg    cl,dl
  1798. wrtcl10:    mov    ah,es:[di]    ; ah := pattern for next row of pixels
  1799.  
  1800.         shr    ah,cl        ; jaggies
  1801.  
  1802.         mov    al,ah
  1803.         and    al,byte ptr [argfgd]
  1804.  
  1805.         cmp    rmwb,18h    ; fgxor
  1806.         jz    wrt14a
  1807.         cmp    rmwb,10h    ; fgor
  1808.         jz    wrt14c
  1809.         test    rmwb,88h    ; fgand and fgnot
  1810.         jz    wrt14b
  1811.         and    al,ds:[si]
  1812.  
  1813. wrt14b:     not    ah
  1814.         and    ds:[si],ah    ; clear bit pixels
  1815.         not    ah
  1816. wrt14c:     or    ds:[si],al
  1817.  
  1818. wrt14e:     inc    di        ; es:di -> next byte in char def table
  1819.         inc    si
  1820.         dec    bl
  1821.         jnz    wrtcl10
  1822.  
  1823.         mov    bl,bpchar
  1824.         sub    si,bx
  1825.         test    si,2000h       ; check if second half
  1826.         jnz    l20a
  1827.         add    si,nextinterleave-firstinterleave
  1828. l20a:        add    si,firstinterleave
  1829.         xchg    cl,dh
  1830.         dec    dl
  1831.         jnz    wrtcl10
  1832.         jmp    short wrtcexit
  1833.  
  1834. wrt14a:     xor    ds:[si],al
  1835.         jmp    short wrt14e
  1836.  
  1837.  
  1838. wrt20a:     xor    ds:[si],dx
  1839.         jmp    short wrt20e
  1840.  
  1841. ; routine for non-byte-aligned characters
  1842.  
  1843. I20a:        mov    ch,cl        ; preserve loop counter
  1844. I20:        mov    cl,byte ptr varshift
  1845.                     ; ch := mask for left side of character
  1846.                     ; cl := # bits to shift left
  1847.  
  1848.         mov    al,es:[di]    ; al := bits for next row of pixels
  1849.         xor    ah,ah
  1850.         shl    ax,cl        ; ah := bits for left side of char
  1851.                     ; al := bits for right side of char
  1852.  
  1853.         mov    cl,byte ptr jaggy ; jaggies
  1854.         shr    ax,cl
  1855.  
  1856.         xchg    al,ah
  1857.         mov    dx,ax
  1858.         and    dl,byte ptr [argfgd]
  1859.         and    dh,byte ptr [argfgd]
  1860.  
  1861.         cmp    rmwb,18h    ; fgxor
  1862.         jz    wrt20a
  1863.         cmp    rmwb,10h    ; fgor
  1864.         jz    wrt20c
  1865.         test    rmwb,88h    ; fgand / fgnot
  1866.         jz    wrt20d
  1867.         and    dx,ds:[si]
  1868.  
  1869. wrt20d:     not    ax
  1870.         and    ds:[si],ax    ; clear bit pixels
  1871.         not    ax
  1872. wrt20c:     or    ds:[si],dx
  1873.  
  1874. wrt20e:     inc    di        ; es:di -> next byte in char def table
  1875.         inc    si
  1876.         dec    bl
  1877.         jnz    I20
  1878.  
  1879.         mov    bl,bpchar
  1880.         sub    si,bx
  1881.  
  1882.         test    si,2000h       ; check if second half
  1883.         jnz    l20b
  1884.         add    si,nextinterleave-firstinterleave
  1885. l20b:        add    si,firstinterleave
  1886.         mov    dx,jaggy
  1887.         xchg    dh,dl
  1888.         mov    jaggy,dx
  1889.         dec    ch
  1890.         jnz    I20
  1891.  
  1892. wrtcexit:
  1893.         pop    di
  1894.         pop    es
  1895.         pop    si
  1896.         pop    ds
  1897.  
  1898.         ret
  1899. wrtchar     endp
  1900.  
  1901.  
  1902. activeaddr    proc    near
  1903.  
  1904.         mov    cl,bl
  1905.  
  1906.         xchg    ah,al        ; ax := 100h * y
  1907.         shr    bx,1        ; bx := x/2
  1908.         shr    ax,1        ; al := 80h*(y&1)
  1909.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  1910.         xor    al,al        ; ax := 100h*(y/2)
  1911.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  1912.         shr    ax,1
  1913.         shr    ax,1        ; ax := 40h*(y/2)
  1914.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  1915.         shr    bx,1
  1916.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  1917. ;        add    bx,0        ; bx := byte offset in video buffer
  1918.  
  1919.         mov    ax,0b800h
  1920.         mov    es,ax        ; es:bx := byte address of pixel
  1921.  
  1922.         and    cl,7
  1923.         xor    cl,7
  1924.         mov    ah,1
  1925.         ret
  1926.  
  1927. activeaddr    endp
  1928.  
  1929.  
  1930. mcursoroff    proc    far
  1931.         push    es
  1932.         push    di
  1933.         push    ds
  1934.         push    si
  1935.  
  1936. ; replace mouse cursor area
  1937.         test    cs:mflag,1
  1938.         jz    nomoff
  1939.  
  1940.         mov    cs:mflag,0
  1941.         les    di,dword ptr cs:scradrofs
  1942.         push    cs
  1943.         pop    ds
  1944.         mov    si,offset mcursorsavearea
  1945.         call    mputblock
  1946.  
  1947. nomoff:     pop    si        ; restore caller registers and return
  1948.         pop    ds
  1949.         pop    di
  1950.         pop    es
  1951.         ret
  1952. mcursoroff    endp
  1953.  
  1954.  
  1955. mcursoron    proc    far argx:word,argy:word
  1956.         local    varshift:word,wordmask:word,mscolor:byte
  1957.         push    es
  1958.         push    di
  1959.         push    ds
  1960.         push    si
  1961.  
  1962. ; save mouse cursor area
  1963.         lds    si,cs:TDtable
  1964.         mov    ax,ds:[si].mousecolor
  1965.         or    al,al
  1966.         jz    okcolor
  1967.         mov    al,0ffh
  1968. okcolor:    mov    mscolor,al
  1969.  
  1970.         mov    ax,argy     ; ax := y
  1971.         sub    ax,ds:[si].mousehotspot_yofs
  1972.         jnc    hotset1
  1973.         mov    ax,argy
  1974.  
  1975. hotset1:    mov    argy,ax
  1976.         mov    bx,argx     ; bx := x
  1977.         sub    bx,ds:[si].mousehotspot_xofs
  1978.         jnc    hotset2
  1979.         mov    bx,argx
  1980.  
  1981. hotset2:    call    activeaddr    ; es:bx -> screen buffer
  1982.         inc    cx
  1983.         and    cl,7        ; cl := # bits to shift to mask char
  1984.         mov    ch,0ffh
  1985.         shl    ch,cl        ; ch := bit mask for right side of char
  1986.         mov    varshift,cx
  1987.  
  1988.         mov    cs:scradrseg,es
  1989.         mov    cs:scradrofs,bx
  1990.         mov    cs:mflag,1     ; mouse cursor on
  1991.  
  1992.         push    es
  1993.         push    cs
  1994.         pop    es
  1995.         pop    ds
  1996.  
  1997.         mov    si,bx
  1998.         mov    di,offset mcursorsavearea
  1999.         call    mgetblock
  2000.  
  2001.  
  2002. ; set up mouse cursor table addressing
  2003.  
  2004.         les    di,cs:TDtable
  2005.         les    di,es:[di].mousemask
  2006.         mov    cx,16        ; number of pixel rows in cursor
  2007.  
  2008.         mov    dx,200        ; modify cx so that cursor does
  2009.         sub    dx,argy     ; not show on upper part of screen
  2010.         cmp    dx,cx        ; when cursor disappears off bottom
  2011.         jg    okcxcount
  2012.         mov    cx,dx
  2013. okcxcount:
  2014.  
  2015. ; set up graphics controller registers
  2016. ; select output routine depending on whether character is byte-aligned
  2017.  
  2018.         test    byte ptr [varshift],0ffh ; test # bits to shift
  2019.         jne    mcl20        ; jump if character is not byte-aligned
  2020.  
  2021.  
  2022. ; routine for byte-aligned characters
  2023. l10:        mov    ax,es:[di]         ; mouse mask
  2024.         and    byte ptr [si],ah     ; ah := bits for left side of char
  2025.         and    byte ptr [si+1],al   ; al := bits for right side of char
  2026.  
  2027.         mov    bl,mscolor
  2028.         mov    ax,es:[di+32]
  2029.         and    al,bl             ;sets it to black or white
  2030.         and    ah,bl
  2031.         or    byte ptr [si],ah
  2032.         or    byte ptr [si+1],al
  2033.  
  2034.         inc    di
  2035.         inc    di
  2036.  
  2037.         test    si,2000h       ; check if second half
  2038.         jnz    l10a
  2039.         add    si,nextinterleave-firstinterleave
  2040. l10a:        add    si,firstinterleave
  2041.         loop    l10
  2042.         jmp    short lexit
  2043.  
  2044.  
  2045. ; routine for non-byte-aligned characters
  2046. mcl20:        push    cx        ; preserve loop counter
  2047.         mov    cx,varshift    ; ch := mask for left side of character
  2048.                     ; cl := # bits to shift left
  2049. ; left side of mask
  2050.         mov    ax,es:[di]
  2051.         push    ax
  2052.  
  2053.         mov    al,ah
  2054.         mov    ah,0ffh
  2055.         rol    ax,cl        ; ah := bits for left side of char
  2056.                     ; al := bits for right side of char
  2057.  
  2058.         and    byte ptr [si],ah
  2059.         and    byte ptr [si+1],al
  2060.  
  2061.         pop    ax
  2062.         mov    ah,0ffh
  2063.         rol    ax,cl        ; ah := bits for left side of char
  2064.                     ; al := bits for right side of char
  2065.         and    byte ptr [si+1],ah
  2066.         and    byte ptr [si+2],al
  2067.  
  2068.  
  2069. ; colorize
  2070.         mov    bl,mscolor
  2071.         mov    ax,es:[di+32]
  2072.         and    al,bl             ;sets it to black or white
  2073.         and    ah,bl
  2074.  
  2075.         push    ax
  2076.         mov    al,ah
  2077.         xor    ah,ah
  2078.         shl    ax,cl        ; ah := bits for left side of char
  2079.                     ; al := bits for right side of char
  2080.         or    byte ptr [si],ah
  2081.         or    byte ptr [si+1],al
  2082.  
  2083.         pop    ax
  2084.         xor    ah,ah
  2085.         shl    ax,cl        ; ah := bits for left side of char
  2086.                     ; al := bits for right side of char
  2087.         or    byte ptr [si+1],ah
  2088.         or    byte ptr [si+2],al
  2089.  
  2090. ; increment to next row of pixels in character
  2091.         inc    di
  2092.         inc    di
  2093.  
  2094.         test    si,2000h       ; check if second half
  2095.         jnz    mcl20a
  2096.         add    si,nextinterleave-firstinterleave
  2097. mcl20a:     add    si,firstinterleave
  2098.  
  2099.         pop    cx
  2100.         loop    mcl20
  2101.  
  2102.  
  2103. lexit:        pop    si        ; restore caller registers and return
  2104.         pop    ds
  2105.         pop    di
  2106.         pop    es
  2107.         ret
  2108.  
  2109. mcursoron    endp
  2110.  
  2111.  
  2112. msetpos     proc    far argx:word,argy:word
  2113.         test    cs:mflag,1
  2114.         jz    nomset
  2115.  
  2116.         call    mcursoroff
  2117.  
  2118.         mov    ax,argx
  2119.         push    ax
  2120.         mov    ax,argy
  2121.         push    ax
  2122.         call    mcursoron
  2123.  
  2124. nomset:     ret
  2125. msetpos     endp
  2126.  
  2127.  
  2128. ; assume ds:si=addrbuf    es:di=screenadr
  2129. mputblock    proc    near
  2130.         cld
  2131.         push    si
  2132.         push    di
  2133.  
  2134.         mov    cx,16
  2135. hcputbl10:    push    di
  2136.         movsw
  2137.         movsb
  2138.         pop    di
  2139.  
  2140.         test    di,2000h       ; check if second half
  2141.         jnz    bl10a
  2142.         add    di,nextinterleave-firstinterleave
  2143. bl10a:        add    di,firstinterleave
  2144.  
  2145.         loop    hcputbl10
  2146.  
  2147.         pop    di
  2148.         pop    si
  2149.         ret
  2150. mputblock    endp
  2151.  
  2152.  
  2153. ; assume es:di=addrbuf    ds:si=screenadr
  2154. mgetblock    proc    near
  2155.         cld
  2156.         push    si
  2157.         push    di
  2158.  
  2159.         mov    cx,16
  2160. getbl01:    push    si
  2161.         movsw
  2162.         movsb
  2163.         pop    si
  2164.  
  2165.         test    si,2000h       ; check if second half
  2166.         jnz    bl01a
  2167.         add    si,nextinterleave-firstinterleave
  2168. bl01a:        add    si,firstinterleave
  2169.         loop    getbl01
  2170.  
  2171.         pop    di
  2172.         pop    si
  2173.         ret
  2174. mgetblock    endp
  2175.  
  2176.  
  2177. incnextline    macro    cofs
  2178.         local    cofsjmp,cofsjmp2
  2179.         test    cofs,2000h    ; check if second half
  2180.         jnz    cofsjmp
  2181.         add    cofs,nextinterleave-firstinterleave
  2182. cofsjmp:    add    cofs,firstinterleave
  2183.         endm
  2184.  
  2185. decnextline    macro    cofs
  2186.         local    cofsjmp,cofsjmp2
  2187.         sub    cofs,firstinterleave
  2188.  
  2189.         test    cofs,2000h    ; check if second half
  2190.         jnz    cofsjmp
  2191.         sub    cofs,nextinterleave-firstinterleave
  2192. cofsjmp:
  2193.         endm
  2194.  
  2195. movevideopixels proc    far argx0:word,argy0:word,argx1:word,argy1:word,argx2:word,argy2:word,vertlines:word,horzlines:word,spage:dword,tpage:dword
  2196.         local    bpline:word,varpixelrows:word,varpixelrowlen:word
  2197.         local    varstartmask:byte,varendmaskl:byte,varendmaskr:byte
  2198.         local    sourcescr:dword,sourceshft:byte,lastbytemask:byte
  2199.         local    targetscr:dword,targetshft:byte,workbuffer:dword
  2200.         local    varpixelcontlen:word
  2201.  
  2202.         push    ds
  2203.         push    es
  2204.         push    si
  2205.         push    di
  2206.  
  2207. ;-----------------------------------------------
  2208.         cld
  2209.  
  2210.         lds    si,cs:TDtable
  2211.         mov    ax,ds:[si].vbytesperline
  2212.         mov    bpline,ax
  2213.  
  2214.         les    di,ds:[si].vgraphbuffer
  2215.         mov    word ptr [workbuffer],di
  2216.         mov    word ptr [workbuffer+2],es
  2217.  
  2218.  
  2219. ;-----------------------------------------------
  2220.         mov    ax,horzlines
  2221.         or    ax,ax
  2222.         jz    noadj_89
  2223.         mov    ax,horzlines
  2224.         test    ah,80h
  2225.         jz    notneg1     ;scroll left?    ;   +-+--------+
  2226.                             ;   | <<<< -1  |
  2227.                             ;   +-+--------+
  2228.         mov    bx,argx0
  2229.         sub    bx,ax
  2230.         mov    argx0,bx
  2231.         jmp    short noadj_89
  2232.  
  2233. notneg1:    mov    bx,argx2    ;scroll right?    ;   +--------+-+
  2234.         add    bx,ax                ;   | 1   >>>> |
  2235.         mov    argx2,bx            ;   +--------+-+
  2236.  
  2237.         mov    bx,argx1
  2238.         sub    bx,ax
  2239.         mov    argx1,bx
  2240.  
  2241. noadj_89:
  2242.  
  2243.         mov    al,byte ptr [argx0]
  2244.         mov    ah,byte ptr [argx2]
  2245.         and    ax,0707h
  2246.         cmp    ah,al
  2247.         jne    movevideobits
  2248.         jmp    movevideobytes
  2249.  
  2250. ;-----------------------------------------------
  2251. movevideobits:    mov    ax,argx1
  2252.         sub    ax,argx0
  2253.         mov    cx,0ff07h
  2254.         and    cl,al
  2255.         xor    cl,7
  2256.         shl    ch,cl        ;last byte mask in ch
  2257.         mov    lastbytemask,ch
  2258.  
  2259.         shr    ax,1        ;number of bytes to mov
  2260.         shr    ax,1
  2261.         shr    ax,1
  2262.         inc    ax
  2263.         mov    varpixelrowlen,ax
  2264.  
  2265.         mov    ax,argy1    ;number of lines
  2266.         sub    ax,argy0    ;number of lines
  2267.         inc    ax
  2268.  
  2269. ;-----------------------------------------------
  2270. ; extablish addressing
  2271.         test    vertlines,8000h
  2272. ;        jnz    bottomupmove
  2273.         jz    bottomdnmove
  2274.         jmp    bottomupmove
  2275.  
  2276. bottomdnmove:    sub    ax,vertlines
  2277.         mov    varpixelrows,ax
  2278.  
  2279.         mov    ax,argy0    ;source     ;   +----------+
  2280.         add    ax,vertlines            ;   +----/\----+
  2281.         mov    bx,argx0            ;   |           |
  2282.                             ;   |           |
  2283.                             ;   +----------+
  2284.         mov    cx,bx
  2285.         and    cl,7
  2286.         mov    sourceshft,cl
  2287.  
  2288.  
  2289.         xchg    ah,al        ; ax := 100h * y
  2290.         shr    bx,1        ; bx := x/2
  2291.         shr    ax,1        ; al := 80h*(y&1)
  2292.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2293.         xor    al,al        ; ax := 100h*(y/2)
  2294.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2295.         shr    ax,1
  2296.         shr    ax,1        ; ax := 40h*(y/2)
  2297.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2298.         shr    bx,1
  2299.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2300.  
  2301.         mov    si,bx
  2302.  
  2303.         mov    ax,word ptr [spage]
  2304.         and    ax,000fh
  2305.         add    si,ax
  2306.  
  2307.         mov    ax,word ptr [spage]
  2308.         shr    ax,1
  2309.         shr    ax,1
  2310.         shr    ax,1
  2311.         shr    ax,1
  2312.         add    ax,word ptr [spage+2]
  2313.         mov    ds,ax
  2314.  
  2315. ;-------
  2316.  
  2317.         mov    ax,argy2    ;target
  2318.         mov    bx,argx2
  2319.  
  2320.         mov    cx,bx
  2321.         xor    cl,7
  2322.         inc    cl
  2323.         and    cl,7
  2324.         mov    targetshft,cl
  2325.  
  2326.         xchg    ah,al        ; ax := 100h * y
  2327.         shr    bx,1        ; bx := x/2
  2328.         shr    ax,1        ; al := 80h*(y&1)
  2329.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2330.         xor    al,al        ; ax := 100h*(y/2)
  2331.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2332.         shr    ax,1
  2333.         shr    ax,1        ; ax := 40h*(y/2)
  2334.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2335.         shr    bx,1
  2336.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2337.         mov    di,bx
  2338.  
  2339.         mov    ax,word ptr [tpage]
  2340.         and    ax,000fh
  2341.         add    di,ax
  2342.  
  2343.         mov    ax,word ptr [tpage]
  2344.         shr    ax,1
  2345.         shr    ax,1
  2346.         shr    ax,1
  2347.         shr    ax,1
  2348.         add    ax,word ptr [tpage+2]
  2349.         mov    es,ax
  2350.  
  2351.         jmp    movevideobl_23
  2352.  
  2353. bottomupmove:    add    ax,vertlines
  2354.         mov    varpixelrows,ax
  2355.  
  2356.         mov    ax,argy0    ;source     ;   +----------+
  2357.         add    ax,varpixelrows         ;   |           |
  2358.         dec    ax                ;   |           |
  2359.         mov    bx,argx0            ;   +----\/----+
  2360.                             ;   +----------+
  2361.         mov    cx,bx
  2362.         and    cl,7
  2363.         mov    sourceshft,cl
  2364.  
  2365.         xchg    ah,al        ; ax := 100h * y
  2366.         shr    bx,1        ; bx := x/2
  2367.         shr    ax,1        ; al := 80h*(y&1)
  2368.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2369.         xor    al,al        ; ax := 100h*(y/2)
  2370.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2371.         shr    ax,1
  2372.         shr    ax,1        ; ax := 40h*(y/2)
  2373.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2374.         shr    bx,1
  2375.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2376.         mov    si,bx
  2377.  
  2378.         mov    ax,word ptr [spage]
  2379.         and    ax,000fh
  2380.         add    si,ax
  2381.  
  2382.         mov    ax,word ptr [spage]
  2383.         shr    ax,1
  2384.         shr    ax,1
  2385.         shr    ax,1
  2386.         shr    ax,1
  2387.         add    ax,word ptr [spage+2]
  2388.         mov    ds,ax
  2389.  
  2390.  
  2391.         mov    ax,argy1
  2392.         sub    ax,argy0
  2393.         add    ax,argy2
  2394.         mov    bx,argx2    ;target
  2395.  
  2396.         mov    cx,bx
  2397.         xor    cl,7
  2398.         inc    cl
  2399.         and    cl,7
  2400.         mov    targetshft,cl
  2401.  
  2402.  
  2403.         xchg    ah,al        ; ax := 100h * y
  2404.         shr    bx,1        ; bx := x/2
  2405.         shr    ax,1        ; al := 80h*(y&1)
  2406.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2407.         xor    al,al        ; ax := 100h*(y/2)
  2408.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2409.         shr    ax,1
  2410.         shr    ax,1        ; ax := 40h*(y/2)
  2411.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2412.         shr    bx,1
  2413.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2414.         mov    di,bx
  2415.  
  2416.         mov    ax,word ptr [tpage]
  2417.         and    ax,000fh
  2418.         add    di,ax
  2419.  
  2420.         mov    ax,word ptr [tpage]
  2421.         shr    ax,1
  2422.         shr    ax,1
  2423.         shr    ax,1
  2424.         shr    ax,1
  2425.         add    ax,word ptr [tpage+2]
  2426.         mov    es,ax
  2427.  
  2428.         xor    ax,ax
  2429.         sub    ax,bpline        ; negate bpline
  2430.         mov    bpline,ax
  2431.  
  2432. ;-----------------------------------------------
  2433. movevideobl_23:
  2434.         mov    word ptr [sourcescr],si
  2435.         mov    word ptr [sourcescr+2],ds
  2436.         mov    word ptr [targetscr],di
  2437.         mov    word ptr [targetscr+2],es
  2438.  
  2439.         mov    cl,targetshft
  2440.         mov    ch,lastbytemask
  2441.         mov    bx,0ffh     ; bx = 00000000 11111111
  2442.         mov    al,ch        ; al = 11110000
  2443.         cbw            ; ax = 11111111 11110000
  2444.  
  2445.         cmp    varpixelrowlen,1 ;if only 1 byte to move then
  2446.         jne    movevideobl_16
  2447.  
  2448.                     ; create start and end mask based
  2449.                     ; on one byte
  2450.         mov    bl,ch        ; bx = 00000000 11110000
  2451.         mov    ah,ch        ;
  2452.         xor    al,al        ; ax = 11110000 00000000
  2453.  
  2454. movevideobl_16: shl    ax,cl
  2455.         shl    bx,cl
  2456.  
  2457.         mov    varendmaskl,ah    ; ah=endmask left
  2458.         mov    varendmaskr,al    ; al=endmask right
  2459.         mov    varstartmask,bh ; bh=startmask
  2460.  
  2461.  
  2462. ;-----------------------------------------------
  2463. ;----move from screen to buffer
  2464. movevideobl_01: lds    si,sourcescr
  2465.         les    di,workbuffer
  2466.  
  2467.         mov    bx,varpixelrowlen
  2468.         mov    cl,sourceshft
  2469.  
  2470.         or    cl,cl        ; bit shifts?
  2471.         jz    mvetobuf_06
  2472.  
  2473.         ; routine for non-aligned bit blocks
  2474. mvetobuf_04:    lodsw
  2475.         dec    si
  2476.         rol    ax,cl
  2477.         stosb
  2478.         dec    bx
  2479.         jnz    mvetobuf_04
  2480.         jmp    short mvetoscr_09
  2481.  
  2482.         ; routine for byte-aligned bit blocks
  2483. mvetobuf_06:    mov    cx,bx
  2484.  
  2485.         shr    cx,1
  2486.         rep    movsw
  2487.         adc    cx,0
  2488.         rep    movsb
  2489.  
  2490. ;----move from buffer to screen
  2491. mvetoscr_09:    lds    si,workbuffer
  2492.         les    di,targetscr
  2493.  
  2494.         mov    bx,varpixelrowlen
  2495.         mov    ch,lastbytemask
  2496.         mov    cl,targetshft
  2497.  
  2498.         cmp    cx,0ff00h    ; start and end must be byte aligned
  2499.         jne    mvetoscr_17
  2500.  
  2501.         ; routine for byte-aligned bit blocks
  2502.         mov    cx,bx
  2503.  
  2504.         shr    cx,1
  2505.         rep    movsw
  2506.         adc    cx,0
  2507.         rep    movsb
  2508.  
  2509.         ; routine for non-aligned bit blocks
  2510. mvetoscr_17:
  2511.         lodsw                ; eg. 10101110 11111111
  2512.         dec    si            ;      <junk>    8 bits
  2513.         or    cl,cl            ; shift?
  2514.         jnz    mvetoscr_shf        ; go shift
  2515.  
  2516.         dec    bx            ; no shift, just dec bx
  2517.         jnz    mvetoscr_mid        ; more bytes
  2518.         jmp    short mvetoscr_end    ; do end bytes
  2519.  
  2520. mvetoscr_shf:    rol    ax,cl            ; eg. 01110111 11111101
  2521.         mov    dl,varstartmask
  2522.         and    ah,dl
  2523.         not    dl
  2524.         and    es:[di],dl        ; and screen 11111000
  2525.         or    es:[di],ah        ; or  screen 00000111
  2526.         inc    di
  2527.         dec    bx            ; bx = 0
  2528.  
  2529. mvetoscr_mid:    dec    bx            ; bx < 0
  2530.         jng    mvetoscr_end
  2531.  
  2532. mvetoscr_loop:    mov    es:[di],al
  2533.         inc    di
  2534.         lodsw
  2535.         dec    si
  2536.         rol    ax,cl
  2537.         dec    bx
  2538.         jnz    mvetoscr_loop
  2539.  
  2540.         ; set pixels at end of row
  2541. mvetoscr_end:    mov    dl,varendmaskl
  2542.         and    al,dl
  2543.         not    dl
  2544.         and    es:[di],dl
  2545.         or    es:[di],al
  2546.         inc    di
  2547.  
  2548.         mov    dl,varendmaskr        ; eg. 00000000
  2549.         and    ah,dl
  2550.         not    dl
  2551.         and    es:[di],dl
  2552.         or    es:[di],ah
  2553. ;-----------------------------------------------------move buffer to screen
  2554.  
  2555. mvetoscr_20:    test    byte ptr bpline+1,80h
  2556.         jnz    mvetoscr_20a
  2557.  
  2558.         incnextline <word ptr [targetscr]>
  2559.         incnextline <word ptr [sourcescr]>
  2560.  
  2561.         dec    varpixelrows
  2562.         jz    movevideobl_02
  2563.         jmp    movevideobl_01
  2564. movevideobl_02: jmp    vertmove_12
  2565.  
  2566.  
  2567. mvetoscr_20a:    decnextline <word ptr [targetscr]>
  2568.         decnextline <word ptr [sourcescr]>
  2569.  
  2570.         dec    varpixelrows
  2571.         jz    movevideobl_02
  2572.         jmp    movevideobl_01
  2573.  
  2574.  
  2575. ; movevideobytes allows for direct latch block moves of pixel lines, rather
  2576. ; than having to (move and shift) a block of pixels to memory and back.
  2577.  
  2578. movevideobytes: mov    ax,argx1
  2579.         mov    cx,0ff07h
  2580.         and    cl,al
  2581.         xor    cl,7
  2582.         shl    ch,cl        ;mask for last byte
  2583.         mov    varendmaskl,ch
  2584.         push    cx
  2585.  
  2586.         mov    bx,argx0
  2587.         mov    cx,0ff07h
  2588.         and    cl,bl
  2589.         shr    ch,cl        ;mask for start byte
  2590.         mov    varstartmask,ch
  2591.  
  2592.         pop    cx
  2593.         shr    bx,1        ;number of bytes to mov
  2594.         shr    bx,1
  2595.         shr    bx,1
  2596.         shr    ax,1
  2597.         shr    ax,1
  2598.         shr    ax,1
  2599.         sub    ax,bx
  2600.         shl    ch,1
  2601.         adc    ax,0        ;1 byte   - start and end bytes same
  2602.                     ;2 bytes  - start and end bytes
  2603.                     ;>2 bytes - start, mid, end bytes
  2604.         mov    varpixelrowlen,ax
  2605.  
  2606.         cmp    ax,1        ;if 1 byte then
  2607.         jne    vertmove_01
  2608.         mov    al,varstartmask
  2609.         and    al,varendmaskl    ;combine both mask together
  2610.         mov    varstartmask,al
  2611.         mov    varendmaskl,0
  2612.  
  2613. vertmove_01:    mov    ah,varstartmask
  2614.         xor    ah,0ffh
  2615.         jnz    vertmove_07
  2616.         mov    varstartmask,ah
  2617. vertmove_07:    mov    ah,varendmaskl
  2618.         xor    ah,0ffh
  2619.         jnz    vertmove_08
  2620.         mov    varendmaskl,ah
  2621. vertmove_08:
  2622.         mov    ax,argy1    ;number of lines
  2623.         sub    ax,argy0
  2624.         inc    ax
  2625.  
  2626. ;-----------------------------------------------
  2627. ; extablish addressing
  2628.         test    vertlines,8000h
  2629.         jnz    vertmove_00
  2630.  
  2631.         sub    ax,vertlines    ;subtract number of lines to scroll
  2632.         mov    varpixelrows,ax
  2633.  
  2634.         mov    ax,argy0    ;source     ;   +----------+
  2635.         add    ax,vertlines            ;   +----/\----+
  2636.         mov    bx,argx0            ;   |           |
  2637.                             ;   |           |
  2638.                             ;   +----------+
  2639.  
  2640.         xchg    ah,al        ; ax := 100h * y
  2641.         shr    bx,1        ; bx := x/2
  2642.         shr    ax,1        ; al := 80h*(y&1)
  2643.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2644.         xor    al,al        ; ax := 100h*(y/2)
  2645.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2646.         shr    ax,1
  2647.         shr    ax,1        ; ax := 40h*(y/2)
  2648.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2649.         shr    bx,1
  2650.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2651.         mov    si,bx
  2652.  
  2653.  
  2654.         mov    ax,word ptr [spage]
  2655.         and    ax,000fh
  2656.         add    si,ax
  2657.  
  2658.         mov    ax,word ptr [spage]
  2659.         shr    ax,1
  2660.         shr    ax,1
  2661.         shr    ax,1
  2662.         shr    ax,1
  2663.         add    ax,word ptr [spage+2]
  2664.         mov    ds,ax
  2665.  
  2666.  
  2667.         mov    ax,argy2    ;target
  2668.         mov    bx,argx2
  2669.  
  2670.         xchg    ah,al        ; ax := 100h * y
  2671.         shr    bx,1        ; bx := x/2
  2672.         shr    ax,1        ; al := 80h*(y&1)
  2673.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2674.         xor    al,al        ; ax := 100h*(y/2)
  2675.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2676.         shr    ax,1
  2677.         shr    ax,1        ; ax := 40h*(y/2)
  2678.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2679.         shr    bx,1
  2680.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2681.         mov    di,bx
  2682.  
  2683.         mov    ax,word ptr [tpage]
  2684.         and    ax,000fh
  2685.         add    di,ax
  2686.  
  2687.         mov    ax,word ptr [tpage]
  2688.         shr    ax,1
  2689.         shr    ax,1
  2690.         shr    ax,1
  2691.         shr    ax,1
  2692.         add    ax,word ptr [tpage+2]
  2693.         mov    es,ax
  2694.  
  2695. ;        mov    bx,bpline
  2696. ;        sub    bx,varpixelrowlen
  2697. ;        mov    varpixelcontlen,bx
  2698.         mov    varpixelcontlen,1
  2699.  
  2700.         jmp    vertmove_31
  2701.  
  2702.  
  2703. vertmove_00:    add    ax,vertlines    ;subtract number of lines to scroll
  2704.         mov    varpixelrows,ax
  2705.  
  2706.         mov    ax,argy0    ;source     ;   +----------+
  2707.         add    ax,varpixelrows         ;   |           |
  2708.         dec    ax                ;   |           |
  2709.         mov    bx,argx0            ;   +----\/----+
  2710.                             ;   +----------+
  2711.  
  2712.         xchg    ah,al        ; ax := 100h * y
  2713.         shr    bx,1        ; bx := x/2
  2714.         shr    ax,1        ; al := 80h*(y&1)
  2715.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2716.         xor    al,al        ; ax := 100h*(y/2)
  2717.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2718.         shr    ax,1
  2719.         shr    ax,1        ; ax := 40h*(y/2)
  2720.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2721.         shr    bx,1
  2722.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2723.         mov    si,bx
  2724.  
  2725.         mov    ax,word ptr [spage]
  2726.         and    ax,000fh
  2727.         add    si,ax
  2728.  
  2729.         mov    ax,word ptr [spage]
  2730.         shr    ax,1
  2731.         shr    ax,1
  2732.         shr    ax,1
  2733.         shr    ax,1
  2734.         add    ax,word ptr [spage+2]
  2735.         mov    ds,ax
  2736.  
  2737.  
  2738.         mov    ax,argy1
  2739.         sub    ax,argy0
  2740.         add    ax,argy2
  2741.         mov    bx,argx2    ;target
  2742.  
  2743.         xchg    ah,al        ; ax := 100h * y
  2744.         shr    bx,1        ; bx := x/2
  2745.         shr    ax,1        ; al := 80h*(y&1)
  2746.         add    bh,al        ; bx := x/2 + 8000h*(y&1)
  2747.         xor    al,al        ; ax := 100h*(y/2)
  2748.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 100h*(y/2)
  2749.         shr    ax,1
  2750.         shr    ax,1        ; ax := 40h*(y/2)
  2751.         add    bx,ax        ; bx := x/2 + 8000h*(y&1) + 140h*(y/2)
  2752.         shr    bx,1
  2753.         shr    bx,1        ; bx := x/8 + 2000h*(y&1) + 50h*(y/2)
  2754.         mov    di,bx
  2755.  
  2756.         mov    ax,word ptr [tpage]
  2757.         and    ax,000fh
  2758.         add    di,ax
  2759.  
  2760.         mov    ax,word ptr [tpage]
  2761.         shr    ax,1
  2762.         shr    ax,1
  2763.         shr    ax,1
  2764.         shr    ax,1
  2765.         add    ax,word ptr [tpage+2]
  2766.         mov    es,ax
  2767.  
  2768.         mov    ax,bpline
  2769.         not    ax
  2770. ;        inc    ax
  2771. ;        sub    ax,varpixelrowlen
  2772.         mov    varpixelcontlen,ax
  2773.  
  2774. ;-----------------------------------------------
  2775. vertmove_31:
  2776.         mov    word ptr [sourcescr],si
  2777.         mov    word ptr [sourcescr+2],ds
  2778.         mov    word ptr [targetscr],di
  2779.         mov    word ptr [targetscr+2],es
  2780.  
  2781.         ; check if we need to move backwards
  2782.  
  2783.         mov    ax,argy0
  2784.         cmp    ax,argy2        ;compare vertical y's
  2785.         jne    vertmove_02        ;jump if not same line
  2786.  
  2787.         mov    ax,word ptr [spage]    ;compare base video segs
  2788.         cmp    ax,word ptr [tpage]
  2789.         jne    vertmove_02        ;jump if different pages
  2790.  
  2791.         mov    ax,word ptr [spage+2]    ;compare base video segs
  2792.         cmp    ax,word ptr [tpage+2]
  2793.         jne    vertmove_02        ;jump if different pages
  2794.  
  2795.         mov    ax,argx0        ;compare end and start segments
  2796.         cmp    ax,argx2
  2797.         jge    vertmove_02        ;jump if tail < begining
  2798.  
  2799.         std
  2800.         mov    ax,varpixelrowlen
  2801.         dec    ax
  2802.         add    si,ax
  2803.         add    di,ax
  2804.         inc    ax
  2805.  
  2806.         add    ax,bpline
  2807.         mov    varpixelcontlen,ax
  2808.         jmp    vertmove_20
  2809.  
  2810. vertmove_02:   mov     cx,varpixelrowlen
  2811.            lds     si,sourcescr
  2812.            les     di,targetscr
  2813.  
  2814.         mov    ah,varstartmask  ; ah := 0ffh (value for bit mask reg)
  2815.         or    ah,ah
  2816.         jz    vertmove_09
  2817.  
  2818. vertmove_03:
  2819.         mov    dh,varstartmask
  2820.         mov    dl,ds:[si]    ; get start byte
  2821.         and    dl,dh
  2822.         not    dh
  2823.         and    es:[di],dh    ; latch destination bytes
  2824.         or    es:[di],dl    ; mask new info
  2825.  
  2826.         shr    bh,1
  2827.         dec    ah
  2828.         jns    vertmove_03
  2829.  
  2830.         dec    cx        ; 1 byte   - start and end bytes same
  2831.         jcxz    vertmove_06    ; 2 bytes  - start and end bytes
  2832.                     ;>2 bytes  - start, mid, end bytes
  2833.         inc    si
  2834.         inc    di
  2835.  
  2836. vertmove_09:    test    varendmaskl,0ffh
  2837.         jz    vertmove_10
  2838.         dec    cx
  2839. vertmove_10:    jcxz    vertmove_04    ;do end part of scroll
  2840.  
  2841. ; middle part of direct memory scroll
  2842.         shr    cx,1
  2843.         rep    movsw
  2844.         adc    cx,0
  2845.         rep    movsb
  2846.  
  2847. ; end part of direct memory scroll
  2848. vertmove_04:    mov    dh,varendmaskl    ; ah := 0ffh (value for bit mask reg)
  2849.         or    dh,dh
  2850.         jz    vertmove_06
  2851.  
  2852.         mov    dl,ds:[si]    ; get end byte
  2853.         and    dl,dh
  2854.         not    dh
  2855.         and    es:[di],dh    ; mask new info
  2856.         or    es:[di],dl
  2857.  
  2858. vertmove_06:
  2859.         test    byte ptr varpixelcontlen+1,80h
  2860.         jnz    vertmove_12_S
  2861.  
  2862.         incnextline <word ptr [targetscr]>
  2863.         incnextline <word ptr [sourcescr]>
  2864.  
  2865.         dec    varpixelrows
  2866.         jz    vertmove_12_F
  2867.         jmp    vertmove_02
  2868. vertmove_12_F:    jmp    vertmove_12
  2869.  
  2870.  
  2871. vertmove_12_S:
  2872.         decnextline <word ptr [targetscr]>
  2873.         decnextline <word ptr [sourcescr]>
  2874.  
  2875.         dec    varpixelrows
  2876.         jz    vertmove_12_F
  2877.         jmp    vertmove_02
  2878.  
  2879. ;-----------------------------------------------
  2880. vertmove_20:    mov    cx,varpixelrowlen
  2881.         lds    si,sourcescr
  2882.         les    di,targetscr
  2883.  
  2884.         mov    al,varendmaskl    ; ah := 0ffh (value for bit mask reg)
  2885.         or    al,al
  2886.         jz    vertmove_21
  2887.  
  2888. vertmove_22:    mov    dl,ds:[si]    ; get start byte
  2889.         and    dl,al
  2890.         not    al
  2891.         and    es:[di],al
  2892.         or    es:[di],dl    ; mask new info
  2893.  
  2894.         dec    cx        ; 1 byte   - start and end bytes same
  2895.         jcxz    vertmove_23    ; 2 bytes  - start and end bytes
  2896.                     ;>2 bytes  - start, mid, end bytes
  2897.  
  2898.         dec    si
  2899.         dec    di
  2900.  
  2901. vertmove_21:    test    varstartmask,0ffh
  2902.         jz    vertmove_24
  2903.         dec    cx
  2904. vertmove_24:    jcxz    vertmove_25    ;do begining part of scroll
  2905.  
  2906. ; middle part of direct memory scroll
  2907.  
  2908.         shr    cx,1
  2909.         rep    movsw
  2910.         adc    cx,0
  2911.         rep    movsb
  2912.  
  2913. ; end part of direct memory scroll
  2914. vertmove_25:
  2915.         mov    al,varstartmask ; ah := 0ffh (value for bit mask reg)
  2916.         test    al,0ffh
  2917.         jz    vertmove_23
  2918.  
  2919. vertmove_26:
  2920.         mov    dl,ds:[si]    ; get start byte
  2921.         and    dl,al
  2922.         not    al
  2923.         and    es:[di],al
  2924.         or    es:[di],dl    ; mask new info
  2925.  
  2926.  
  2927. vertmove_23:
  2928.         decnextline <word ptr [targetscr]>
  2929.         decnextline <word ptr [sourcescr]>
  2930.  
  2931.         dec    varpixelrows
  2932.         jnz    vertmove_20
  2933.  
  2934.  
  2935. vertmove_12:
  2936.         cld
  2937.         pop    di
  2938.         pop    si
  2939.         pop    es
  2940.         pop    ds
  2941.         ret
  2942.  
  2943. movevideopixels endp
  2944.  
  2945.  
  2946. setvpage    proc    far pagen:word
  2947.         ret
  2948. setvpage    endp
  2949.  
  2950. setapage    proc    far pagen:word
  2951.         ret
  2952. setapage    endp
  2953.  
  2954.         end
  2955.