home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / BENCHMAR / FASMATH.ZIP / BIOM.ARC / BIOA.ASM next >
Encoding:
Assembly Source File  |  1989-09-22  |  33.2 KB  |  1,161 lines

  1. title Biomorph
  2. page 58,132
  3. ; Biomorphs (assembler portion)    Version 1.0 By Fred Dunlap from Bert Tyler program
  4. ;                    Bert Tyler (btyler on BIX)
  5.  
  6.     .MODEL    small,c
  7.  
  8.     .386
  9.     .387
  10.     .DATA
  11. dotcount    dd    0        ; dot-counter:  0 to a*b
  12. dotwrite    dw    0        ; write-a-dot routine:  mode-specific
  13. dotread        dw    0        ; read-a-dot routine:   mode-specific
  14. x        dw    0        ; x-axis: 0 to (xdots-1)
  15. y        dw    0        ; y-axis: 0 to (ydots-1)
  16.  
  17. ;                    ; Zoom-Box values (2K x 2K screens max)
  18. boxcount    dw    0        ; (previous) box pt counter: 0 if none.
  19. boxpoints    dd    1028 dup(0)    ; (previous) box data points
  20. boxvalues    db    1028 dup(0)    ; (previous) box color values
  21.  
  22. three           dd      3.0
  23.     .DATA?
  24. limit_sq        dq      ?
  25. cur_x           dq      ?
  26. cur_y           dq      ?
  27. k        dw    ?        ; local counter: 1 to maxit
  28. kbdcount    dw    ?            ; keyboard counter: nnnnn to 0
  29. kbdflag        dw    ?            ; keyboard hit flag: 0 if no, 1 if yes
  30. temp            dt      ?
  31.  
  32.     extrn    dotmode: word        ; video mode:   1 = use the BIOS (yuck)
  33. ;                            2 = use EGA/VGA style
  34. ;                            3 = use MCGA style
  35.  
  36. ; ************************ External variables *****************************
  37.  
  38.     extrn    xmin:qword, ymax:qword
  39.     extrn    c_r:qword,  c_i:qword
  40.     extrn    delx:qword, dely:qword, limit:qword
  41.     extrn    xdots:word, ydots:word    ; number of dots across and down
  42.     extrn    maxit:word, colors:word    ; maximum iterations, colors
  43.     extrn    ixmin:word, ixmax:word    ; for zoom/pan: x and y limits
  44.     extrn    iymin:word, iymax:word    ;  for the local zoom-box
  45.  
  46.     .CODE
  47. ; ***************** Function calcdots() **********************************
  48. calcdots_b3 proc
  49.     push    es            ; save the original ES value
  50.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  51.     mov    es,ax            ; save it here during this routine
  52.  
  53.     xor    eax,eax            ; initialize dot counter
  54.     dec    eax            ;  (to -1: it gets incremented later)
  55.     mov    dotcount,eax        ;  ...
  56.  
  57.     mov    kbdcount,ax        ; initialize keyboard counter (to -1)
  58.     mov    kbdflag,0        ; initialize keyboard int flag: nope
  59.  
  60.                     ; prepare special video-mode speedups
  61.     cmp    dotmode,3        ; MCGA mode?
  62.     je    short mcgamode        ; yup.
  63.     cmp    dotmode,2        ; EGA/VGA mode?
  64.     je    short vgamode            ; yup.
  65.  
  66. dullnormalmode:
  67.     mov    ax,offset normalwrite    ; set up the BIOS write-a-dot routine
  68.     mov    bx,offset normalread    ; set up the BIOS read-a-dot  routine
  69.     jmp    short videomode        ; return to common code
  70. mcgamode:
  71.     mov    ax,offset mcgawrite    ; set up MCGA write-a-dot routine
  72.     mov    bx,offset mcgaread    ; set up the BIOS read-a-dot  routine
  73.     jmp    short videomode        ; return to common code
  74. egamode:
  75. vgamode:
  76.     mov    ax,offset vgawrite    ; set up EGA/VGA write-a-dot routine.
  77.     mov    bx,offset vgaread    ; set up the BIOS read-a-dot  routine
  78.     jmp    short videomode        ; return to common code
  79. videomode:
  80.     mov    dotwrite,ax        ; save the results
  81.     mov    dotread,bx        ;  ...
  82.     fld    limit
  83.     fmul    st,st
  84.     fstp    limit_sq
  85.     fld    ymax
  86.     fstp    cur_y
  87.  
  88.     fld    three           ; Often used constants kept on the stack
  89.     fld     c_i
  90.     fld     c_r
  91.     mov     y,0
  92.  
  93. yloop:                    ; for (y = 0; y < ydots; y++)
  94.     fld    xmin            ; initialize inner loop
  95.     fstp    cur_x
  96.     mov     x,0
  97.  
  98. xloop:                    ; for (x = 0; x < xdots; x++)
  99.     mov    ax,maxit            ; setup k = maxit
  100.     mov    k,ax            ;  (decrementing to 0 is faster)
  101.  
  102.     inc    dotcount        ; increment the dot-counter
  103.  
  104.     dec    kbdcount        ; decrement the keyboard counter
  105.     jns    maxittest        ;  skip keyboard test if still positive
  106.     mov    kbdcount,5000        ; else, stuff an appropriate count val
  107.     mov    ah,1            ; check the keyboard
  108.     int    16h            ; has it been hit?
  109.     jz    maxittest        ; nope.  proceed
  110.     mov    kbdflag,1        ; yup.  reset kbd-hit flag: yes.
  111.     jmp    wedone            ; so, bail out!
  112.  
  113. maxittest:
  114.     fld    cur_y            ; zi(0) - y
  115.     fld    cur_x            ; zr(0) - x
  116.                     ; timing check: avoid the main
  117.     cmp    maxit,1            ;  processing loop if maxit <= 1
  118.     jg    kloop            ;  ...
  119.     mov    maxit,1            ; avoid divides by zero
  120.     mov    k,0            ; pretend we have done 1 loop
  121.     jmp    kloopend        ; and bail out
  122.  
  123. ;    This is the main processing loop.  Here, every T-state counts...
  124.  
  125. kloop:                    ; for (k = 0; k <= maxit; k++)
  126.     fld    st(1)
  127.     fmul    st,st
  128.     fld    st(1)
  129.     fmul    st,st
  130.     fld     st(1)
  131.     fadd    st,st(1)
  132.     fcomp   limit_sq
  133.     fstsw    ax
  134.     sahf
  135.     ja    short gt_limit
  136.     fld     st(1)
  137.     fmul    st,st(7)        ; *3
  138.     fsubr   st,st(1)
  139.     fmul    st,st(3)
  140.     fadd    st,st(5)    ; add Cr
  141.     fstp    st(3)           ; save as new Zr
  142.  
  143.     fmul    st,st(6)        ; Zr*Zr*3
  144.     fsubrp  st(1),st
  145.     fmul    st,st(2)
  146.         fadd    st,st(4)    ; add Ci
  147.     fstp    st(2)           ; new Zi
  148.  
  149.     dec    k            ; while (k < maxit) (dec to 0 is faster)
  150.     jz    short kloopend        ; while (k < maxit) ...
  151.     jmp    kloop
  152.  
  153. gt_limit:
  154.     fstp    st
  155.     fstp    st
  156.     fabs
  157.     fcomp    limit              ; compare to limit
  158.     fstsw    ax
  159.     sahf
  160.     ja      short fred1
  161.     fstp    st
  162.     mov    ax,0            ; reset max-out color to border color
  163.     jmp     short coloradjust2
  164. fred1:
  165.     fabs
  166.     fcomp    limit              ; compare to limit
  167.     fstsw    ax
  168.     sahf
  169.     ja      short kloopend1
  170.     mov    ax,0            ; reset max-out color to border color
  171.     jmp     short coloradjust2
  172.  
  173.  
  174. kloopend:
  175.     fstp    st                       ; pop z off the stack
  176.     fstp    st
  177. kloopend1:
  178.     mov    ax,maxit        ; compute color
  179.     sub    ax,k            ;  (first, re-compute "k")
  180.     sub    kbdcount,ax        ; adjust the keyboard count
  181.     cmp    ax,0            ; convert any "outlier" region 
  182.     jne    coloradjust1        ;  (where abs(x) > 2 or abs(y) > 2)
  183.     mov    ax,1            ;   to look like we ran through
  184. coloradjust1:                ;    at least one loop.
  185.     cmp    ax,maxit        ; did we max out on iterations?
  186.     jne    coloradjust2        ;  nope.
  187.     mov    ax,1            ; reset max-out color to border color
  188. coloradjust2:                ;  (it just looks better, somehow)
  189.     mov    dx,0            ;  convert to a 32-bit value
  190.     div    colors            ;  ...
  191.     mov    al,dl            ; result in al
  192.  
  193.     call    dotwrite        ; invoke the appropriate write-a-dot
  194.  
  195. loopchecks:
  196.     fld    cur_x
  197.     inc    x            ; check for end of xloop
  198.     fadd    delx
  199.     mov    ax,xdots        ;  ...
  200.     cmp    x,ax            ;  ...
  201.     fstp    cur_x
  202.     jb    xloop            ; more to go
  203.  
  204.     fld    cur_y
  205.     inc    y            ; check for end of yloop
  206.     fsub    dely
  207.     mov    ax,ydots        ;  ...
  208.     cmp    y,ax            ;  ...
  209.     fstp    cur_y
  210.     jb    yloop            ; more to go
  211.  
  212. wedone:                    ; restore everything and return.
  213.     fstp    st                      ; pop Cr off the stack
  214.     fstp    st                      ; pop Ci off the stack
  215.     fstp    st                      ; pop three off the tos
  216.     mov    ax,dotwrite        ; check: were we in EGA/VGA mode?
  217.     cmp    ax,offset vgawrite    ;  ...
  218.     jne    wereallydone        ; nope.  no adjustments
  219.     mov    ax,0ff08h        ; restore the default bit mask
  220.     out    dx,ax            ; ...
  221.     mov    ax,0003h        ; restore the function select
  222.     out    dx,ax            ;  ...
  223.     mov    ax,0001h        ; restore the enable set/reset
  224.     out    dx,ax            ;  ...
  225. wereallydone:
  226.     pop    es            ; restore the original ES value
  227.     mov    ax,kbdflag        ; return the keyboard-interrupt flag
  228.     mov    boxcount,0        ; indicate no boxes drawn yet.
  229.     ret                ; and return.
  230.  
  231. calcdots_b3 endp
  232.  
  233. page
  234. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  235. calcdots_f proc
  236.     push    es            ; save the original ES value
  237.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  238.     mov    es,ax            ; save it here during this routine
  239.  
  240.     mov    eax,0            ; initialize dot counter
  241.     dec    eax            ;  (to -1: it gets incremented later)
  242.     mov    dotcount,eax        ;  ...
  243.  
  244.     mov    kbdcount,ax        ; initialize keyboard counter (to -1)
  245.     mov    kbdflag,0        ; initialize keyboard int flag: nope
  246.  
  247.  
  248.                     ; prepare special video-mode speedups
  249.     cmp    dotmode,3        ; MCGA mode?
  250.     je    mcgamode        ; yup.
  251.     cmp    dotmode,2        ; EGA/VGA mode?
  252.     je    vgamode            ; yup.
  253. dullnormalmode:
  254.     mov    ax,offset normalwrite    ; set up the BIOS write-a-dot routine
  255.     mov    bx,offset normalread    ; set up the BIOS read-a-dot  routine
  256.     jmp    videomode        ; return to common code
  257. mcgamode:
  258.     mov    ax,offset mcgawrite    ; set up MCGA write-a-dot routine
  259.     mov    bx,offset mcgaread    ; set up the BIOS read-a-dot  routine
  260.     jmp    videomode        ; return to common code
  261. egamode:
  262. vgamode:
  263.     mov    ax,offset vgawrite    ; set up EGA/VGA write-a-dot routine.
  264.     mov    bx,offset vgaread    ; set up the BIOS read-a-dot  routine
  265.     jmp    videomode        ; return to common code
  266. videomode:
  267.     mov    dotwrite,ax        ; save the results
  268.     mov    dotread,bx        ;  ...
  269.  
  270.     fld    limit
  271.     fld    ymax            ; initialize outer loop
  272.         mov     y,0
  273.  
  274. yloop:                    ; for (y = 0; y < ydots; y++)
  275.     fld    xmin            ; initialize inner loop
  276.         mov     x,0
  277.  
  278. xloop:                    ; for (x = 0; x < xdots; x++)
  279.     mov    ax,maxit            ; setup k = maxit
  280.     mov    k,ax            ;  (decrementing to 0 is faster)
  281.  
  282.     inc    dotcount        ; increment the dot-counter
  283.  
  284.     dec    kbdcount        ; decrement the keyboard counter
  285.     jns    maxittest        ;  skip keyboard test if still positive
  286.     mov    kbdcount,5000        ; else, stuff an appropriate count val
  287.     mov    ah,1            ; check the keyboard
  288.     int    16h            ; has it been hit?
  289.     jz    maxittest        ; nope.  proceed
  290.     mov    kbdflag,1        ; yup.  reset kbd-hit flag: yes.
  291.     fstp    st
  292.     jmp    wedone            ; so, bail out!
  293.  
  294. maxittest:
  295.     fld    st(1)            ; dup ci into zi - y
  296.     fld    st(1)            ; dup cr into zr - x
  297.                     ; timing check: avoid the main
  298.     cmp    maxit,1            ;  processing loop if maxit <= 1
  299.     jg    kloop            ;  ...
  300.     mov    maxit,1            ; avoid divides by zero
  301.     mov    k,0            ; pretend we have done 1 loop
  302.     jmp    kloopend        ; and bail out
  303.  
  304. ;    This is the main processing loop.  Here, every T-state counts...
  305.  
  306. kloop:                    ; for (k = 0; k <= maxit; k++)
  307.     fld    st(1)
  308.     fmul    st,st
  309.     fld    st(1)
  310.     fmul    st,st
  311. ; check against limit
  312.     fld    st
  313.     fadd    st,st(2)
  314.     fcomp    st(7)
  315.     fstsw    ax
  316.  
  317.     dec    k            ; while (k < maxit) (dec to 0 is faster)
  318.     jz    short kloopend        ; while (k < maxit) ...
  319.  
  320.     sahf
  321.     jae    short kloopend
  322.  
  323.     fld    st(3)
  324.     fmul    st,st(3)
  325.     fadd    st,st            ; 2*Zi*Zr
  326.     fadd    st,st(6)        ; add Ci
  327.     fstp    st(4)            ; new Zi stored
  328.  
  329.     fsubrp    st(1),st
  330.     fadd    st,st(3)
  331.     fstp    st(1)            ; (x*x - y*y) + Cr
  332.  
  333.     jmp    kloop            ;  ...
  334.  
  335. kloopend:
  336.         fstp    st                       ; pop z*2
  337.         fstp    st                       ; 
  338.         fstp    st                       ; pop z off the stack
  339.         fstp    st
  340.  
  341.     mov    ax,maxit        ; compute color
  342.     sub    ax,k            ;  (first, re-compute "k")
  343.     sub    kbdcount,ax        ; adjust the keyboard count
  344.     cmp    ax,0            ; convert any "outlier" region 
  345.     jne    coloradjust1        ;  (where abs(x) > 2 or abs(y) > 2)
  346.     mov    ax,1            ;   to look like we ran through
  347. coloradjust1:                ;    at least one loop.
  348.     cmp    ax,maxit        ; did we max out on iterations?
  349.     jne    coloradjust2        ;  nope.
  350.     mov    ax,1            ; reset max-out color to border color
  351. coloradjust2:                ;  (it just looks better, somehow)
  352.     mov    dx,0            ;  convert to a 32-bit value
  353.     div    colors            ;  ...
  354.     mov    al,dl            ; result in al
  355.  
  356.     call    dotwrite        ; invoke the appropriate write-a-dot
  357.  
  358. loopchecks:
  359.     inc    x            ; check for end of xloop
  360.         fadd    delx
  361.     mov    ax,xdots        ;  ...
  362.     cmp    x,ax            ;  ...
  363.     jb    xloop            ; more to go
  364.  
  365.     inc    y            ; check for end of yloop
  366.         fstp    st
  367.         fsub    dely
  368.     mov    ax,ydots        ;  ...
  369.     cmp    y,ax            ;  ...
  370.     jb    yloop            ; more to go
  371.  
  372. wedone:                    ; restore everything and return.
  373.         fstp    st                      ; pop Ci off the stack
  374.         fstp    st                      ; pop limit off the tos
  375.     mov    ax,dotwrite        ; check: were we in EGA/VGA mode?
  376.     cmp    ax,offset vgawrite    ;  ...
  377.     jne    wereallydone        ; nope.  no adjustments
  378.     mov    ax,0ff08h        ; restore the default bit mask
  379.     out    dx,ax            ; ...
  380.     mov    ax,0003h        ; restore the function select
  381.     out    dx,ax            ;  ...
  382.     mov    ax,0001h        ; restore the enable set/reset
  383.     out    dx,ax            ;  ...
  384. wereallydone:
  385.     pop    es            ; restore the original ES value
  386.     mov    ax,kbdflag        ; return the keyboard-interrupt flag
  387.     mov    boxcount,0        ; indicate no boxes drawn yet.
  388.     ret                ; and return.
  389.  
  390. calcdots_f endp
  391.  
  392. page
  393. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  394. calcdots_b5 proc
  395.  
  396.     push    es            ; save the original ES value
  397.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  398.     mov    es,ax            ; save it here during this routine
  399.  
  400.     xor    eax,eax            ; initialize dot counter
  401.     dec    eax            ;  (to -1: it gets incremented later)
  402.     mov    dotcount,eax        ;  ...
  403.  
  404.     mov    kbdcount,ax        ; initialize keyboard counter (to -1)
  405.     mov    kbdflag,0        ; initialize keyboard int flag: nope
  406.  
  407.                     ; prepare special video-mode speedups
  408.     cmp    dotmode,3        ; MCGA mode?
  409.     je    short mcgamode        ; yup.
  410.     cmp    dotmode,2        ; EGA/VGA mode?
  411.     je    short vgamode            ; yup.
  412.  
  413. dullnormalmode:
  414.     mov    ax,offset normalwrite    ; set up the BIOS write-a-dot routine
  415.     mov    bx,offset normalread    ; set up the BIOS read-a-dot  routine
  416.     jmp    short videomode        ; return to common code
  417. mcgamode:
  418.     mov    ax,offset mcgawrite    ; set up MCGA write-a-dot routine
  419.     mov    bx,offset mcgaread    ; set up the BIOS read-a-dot  routine
  420.     jmp    short videomode        ; return to common code
  421. egamode:
  422. vgamode:
  423.     mov    ax,offset vgawrite    ; set up EGA/VGA write-a-dot routine.
  424.     mov    bx,offset vgaread    ; set up the BIOS read-a-dot  routine
  425.     jmp    short videomode        ; return to common code
  426. videomode:
  427.     mov    dotwrite,ax        ; save the results
  428.     mov    dotread,bx        ;  ...
  429.     fld    limit
  430.     fmul    st,st
  431.     fstp    limit_sq
  432.     fld    ymax
  433.     fstp    cur_y
  434.  
  435.     fld    three           ; Often used constants kept on the stack
  436.     fld     c_i
  437.     fld     c_r
  438.     mov     y,0
  439.  
  440. yloop:                    ; for (y = 0; y < ydots; y++)
  441.     fld    xmin            ; initialize inner loop
  442.     fstp    cur_x
  443.     mov     x,0
  444.  
  445. xloop:                    ; for (x = 0; x < xdots; x++)
  446.     mov    ax,maxit            ; setup k = maxit
  447.     mov    k,ax            ;  (decrementing to 0 is faster)
  448.  
  449.     inc    dotcount        ; increment the dot-counter
  450.  
  451.     dec    kbdcount        ; decrement the keyboard counter
  452.     jns    maxittest        ;  skip keyboard test if still positive
  453.     mov    kbdcount,3000        ; else, stuff an appropriate count val
  454.     mov    ah,1            ; check the keyboard
  455.     int    16h            ; has it been hit?
  456.     jz    maxittest        ; nope.  proceed
  457.     mov    kbdflag,1        ; yup.  reset kbd-hit flag: yes.
  458.     jmp    wedone            ; so, bail out!
  459.  
  460. maxittest:
  461.     fld    cur_y            ; zi(0) - y
  462.     fld    cur_x            ; zr(0) - x
  463.                     ; timing check: avoid the main
  464.     cmp    maxit,1            ;  processing loop if maxit <= 1
  465.     jg    kloop            ;  ...
  466.     mov    maxit,1            ; avoid divides by zero
  467.     mov    k,0            ; pretend we have done 1 loop
  468.     jmp    kloopend        ; and bail out
  469.  
  470. ;    This is the main processing loop.  Here, every T-state counts...
  471.  
  472. kloop:                    ; for (k = 0; k <= maxit; k++)
  473.     fld    st(1)
  474.     fmul    st,st
  475.     fld    st(1)
  476.     fmul    st,st
  477.     fld     st(1)
  478.     fadd    st,st(1)
  479.     fcomp   limit_sq
  480.     fstsw    ax
  481.     sahf
  482.     ja    short gt_limit
  483.     fld     st(1)
  484.     fmul    st,st(7)        ; *3
  485.     fsubr   st,st(1)
  486.     fmul    st,st(3)
  487.     fadd    st,st(5)    ; add Cr
  488.     fstp    st(3)           ; save as new Zr
  489.  
  490.     fmul    st,st(6)        ; Zr*Zr*3
  491.     fsubrp  st(1),st
  492.     fmul    st,st(2)
  493.         fadd    st,st(4)    ; add Ci
  494.     fstp    st(2)           ; new Zi
  495.  
  496.     dec    k            ; while (k < maxit) (dec to 0 is faster)
  497.     jz    short kloopend        ; while (k < maxit) ...
  498.     jmp    kloop
  499.  
  500. gt_limit:
  501.     fstp    st
  502.     fstp    st
  503.     fabs
  504.     fcomp    limit              ; compare to limit
  505.     fstsw    ax
  506.     sahf
  507.     ja      short fred1
  508.     fstp    st
  509.     mov    ax,0            ; reset max-out color to border color
  510.     jmp     short coloradjust2
  511. fred1:
  512.     fabs
  513.     fcomp    limit              ; compare to limit
  514.     fstsw    ax
  515.     sahf
  516.     ja      short kloopend1
  517.     mov    ax,0            ; reset max-out color to border color
  518.     jmp     short coloradjust2
  519.  
  520.  
  521. kloopend:
  522.     fstp    st                       ; pop z off the stack
  523.     fstp    st
  524. kloopend1:
  525.     mov    ax,maxit        ; compute color
  526.     sub    ax,k            ;  (first, re-compute "k")
  527.     sub    kbdcount,ax        ; adjust the keyboard count
  528.     cmp    ax,0            ; convert any "outlier" region 
  529.     jne    coloradjust1        ;  (where abs(x) > 2 or abs(y) > 2)
  530.     mov    ax,1            ;   to look like we ran through
  531. coloradjust1:                ;    at least one loop.
  532.     cmp    ax,maxit        ; did we max out on iterations?
  533.     jne    coloradjust2        ;  nope.
  534.     mov    ax,1            ; reset max-out color to border color
  535. coloradjust2:                ;  (it just looks better, somehow)
  536.     mov    dx,0            ;  convert to a 32-bit value
  537.     div    colors            ;  ...
  538.     mov    al,dl            ; result in al
  539.  
  540.     call    dotwrite        ; invoke the appropriate write-a-dot
  541.  
  542. loopchecks:
  543.     fld    cur_x
  544.     inc    x            ; check for end of xloop
  545.     fadd    delx
  546.     mov    ax,xdots        ;  ...
  547.     cmp    x,ax            ;  ...
  548.     fstp    cur_x
  549.     jb    xloop            ; more to go
  550.  
  551.     fld    cur_y
  552.     inc    y            ; check for end of yloop
  553.     fsub    dely
  554.     mov    ax,ydots        ;  ...
  555.     cmp    y,ax            ;  ...
  556.     fstp    cur_y
  557.     jb    yloop            ; more to go
  558.  
  559. wedone:                    ; restore everything and return.
  560.     fstp    st                      ; pop Cr off the stack
  561.     fstp    st                      ; pop Ci off the stack
  562.     fstp    st                      ; pop three off the tos
  563.     mov    ax,dotwrite        ; check: were we in EGA/VGA mode?
  564.     cmp    ax,offset vgawrite    ;  ...
  565.     jne    wereallydone        ; nope.  no adjustments
  566.     mov    ax,0ff08h        ; restore the default bit mask
  567.     out    dx,ax            ; ...
  568.     mov    ax,0003h        ; restore the function select
  569.     out    dx,ax            ;  ...
  570.     mov    ax,0001h        ; restore the enable set/reset
  571.     out    dx,ax            ;  ...
  572. wereallydone:
  573.     pop    es            ; restore the original ES value
  574.     mov    ax,kbdflag        ; return the keyboard-interrupt flag
  575.     mov    boxcount,0        ; indicate no boxes drawn yet.
  576.     ret                ; and return.
  577.  
  578. calcdots_b5 endp
  579.  
  580. page
  581. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  582. calcdots_sin proc
  583.  
  584.     push    es            ; save the original ES value
  585.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  586.     mov    es,ax            ; save it here during this routine
  587.  
  588.     xor    eax,eax            ; initialize dot counter
  589.     dec    eax            ;  (to -1: it gets incremented later)
  590.     mov    dotcount,eax        ;  ...
  591.  
  592.     mov    kbdcount,ax        ; initialize keyboard counter (to -1)
  593.     mov    kbdflag,0        ; initialize keyboard int flag: nope
  594.  
  595.                     ; prepare special video-mode speedups
  596.     cmp    dotmode,3        ; MCGA mode?
  597.     je    short mcgamode        ; yup.
  598.     cmp    dotmode,2        ; EGA/VGA mode?
  599.     je    short vgamode            ; yup.
  600.  
  601. dullnormalmode:
  602.     mov    ax,offset normalwrite    ; set up the BIOS write-a-dot routine
  603.     mov    bx,offset normalread    ; set up the BIOS read-a-dot  routine
  604.     jmp    short videomode        ; return to common code
  605. mcgamode:
  606.     mov    ax,offset mcgawrite    ; set up MCGA write-a-dot routine
  607.     mov    bx,offset mcgaread    ; set up the BIOS read-a-dot  routine
  608.     jmp    short videomode        ; return to common code
  609. egamode:
  610. vgamode:
  611.     mov    ax,offset vgawrite    ; set up EGA/VGA write-a-dot routine.
  612.     mov    bx,offset vgaread    ; set up the BIOS read-a-dot  routine
  613.     jmp    short videomode        ; return to common code
  614. videomode:
  615.     mov    dotwrite,ax        ; save the results
  616.     mov    dotread,bx        ;  ...
  617.     fld    limit
  618.     fmul    st,st
  619.     fstp    limit_sq
  620.     fld    ymax
  621.     fstp    cur_y
  622.  
  623.     mov     y,0
  624.  
  625. yloop:                    ; for (y = 0; y < ydots; y++)
  626.     fld    xmin            ; initialize inner loop
  627.     fstp    cur_x
  628.     mov     x,0
  629.  
  630. xloop:                    ; for (x = 0; x < xdots; x++)
  631.     mov    ax,maxit            ; setup k = maxit
  632.     mov    k,ax            ;  (decrementing to 0 is faster)
  633.  
  634.     inc    dotcount        ; increment the dot-counter
  635.  
  636.     dec    kbdcount        ; decrement the keyboard counter
  637.     jns    maxittest        ;  skip keyboard test if still positive
  638.     mov    kbdcount,2000        ; else, stuff an appropriate count val
  639.     mov    ah,1            ; check the keyboard
  640.     int    16h            ; has it been hit?
  641.     jz    maxittest        ; nope.  proceed
  642.     mov    kbdflag,1        ; yup.  reset kbd-hit flag: yes.
  643.     jmp    wedone            ; so, bail out!
  644.  
  645. maxittest:
  646.     fld    cur_y            ; zi(0) - y
  647.     fld    cur_x            ; zr(0) - x
  648.                     ; timing check: avoid the main
  649.     cmp    maxit,1            ;  processing loop if maxit <= 1
  650.     jg    kloop            ;  ...
  651.     mov    maxit,1            ; avoid divides by zero
  652.     mov    k,0            ; pretend we have done 1 loop
  653.     jmp    kloopend        ; and bail out
  654.  
  655. ;    This is the main processing loop.  Here, every T-state counts...
  656.  
  657. kloop:                    ; for (k = 0; k <= maxit; k++)
  658.     fld    st(1)
  659.     fxam
  660.     fstsw    ax
  661.     fmul    st,st
  662.     fld    st(1)
  663.     fxam
  664.     fstsw    ax
  665.     fmul    st,st
  666.     fadd    
  667.     fcomp   limit_sq
  668.     fstsw    ax
  669.     sahf
  670.     ja      gt_limit
  671. ; put handy things on the stack like sin(a), cos(a), exp(b)/2, exp(-b)/2
  672.     fld    st(1)
  673.     fsincos
  674.     fldl2e
  675.     fmul    st,st(3)
  676.     fld    st    ; save for exp(-b)
  677.  
  678.     fld     st
  679.     frndint
  680.     fxch    st(1)
  681.     fsub    st,st(1)
  682.     f2xm1
  683.     fld1
  684.     fsub    st(2),st    ; divide by 2
  685.     fadd
  686.     fscale
  687.     fstp    st(1)
  688.     fxch    st(1)
  689.  
  690.     fchs
  691.     fld    st
  692.     frndint
  693.     fxch    st(1)
  694.     fsub    st,st(1)
  695.     f2xm1
  696.     fld1
  697.     fsub    st(2),st    ; divide by 2
  698.     fadd
  699.     fscale
  700.     fstp    st(1)
  701. ; stack should now have a, b, sin(a), cos(a), exp(b)/2, exp(-b)/2
  702.  
  703. ; calc new a = (aa-bb)+sin(a)cosh(b)
  704.     fld    st(5)
  705.     fmul    st,st
  706.     fld    st(5)
  707.     fmul    st,st
  708.     fsub
  709.     fld    st(2)
  710.     fadd    st,st(2)
  711.     fmul    st,st(5)
  712.     fadd
  713.         fld     st
  714.         fstp    temp
  715.         fadd    c_r
  716.         fxam
  717.         fstsw   ax
  718.         and     ax,4500h
  719.         cmp     ax,0
  720.         jne     short ok
  721.         out     0e4h,ax
  722.         fstp    temp
  723.         fstp    temp
  724.         fstp    temp    
  725.         fstp    temp    
  726.         fstp    temp
  727.         fstp    temp
  728.         fstp    temp
  729. ok:    fxch    st(6)
  730. ; calc new b = 2ab + cos(a)sinh(b)
  731.     fmul    st,st(5)
  732.     fadd    st,st    ;*2
  733.     fstp    st(5)
  734.     fsub
  735.         fmul    
  736.         fadd    c_i
  737.     faddp    st(2),st
  738.  
  739.     dec    k            ; while (k < maxit) (dec to 0 is faster)
  740.     fstp    st
  741.     jz    short kloopend        ; while (k < maxit) ...
  742.     jmp    kloop
  743.  
  744. gt_limit:
  745.     fabs
  746.     fcomp    limit              ; compare to limit
  747.     fstsw    ax
  748.     sahf
  749.     ja      short fred1
  750.     fstp    st
  751.     mov    ax,0            ; reset max-out color to border color
  752.     jmp     short coloradjust2
  753. fred1:
  754.     fabs
  755.     fcomp    limit              ; compare to limit
  756.     fstsw    ax
  757.     sahf
  758.     ja      short kloopend1
  759.     mov    ax,0            ; reset max-out color to border color
  760.     jmp     short coloradjust2
  761.  
  762.  
  763. kloopend:
  764.     fstp    st                       ; pop z off the stack
  765.     fstp    st
  766. kloopend1:
  767.     mov    ax,maxit        ; compute color
  768.     sub    ax,k            ;  (first, re-compute "k")
  769.     sub    kbdcount,ax        ; adjust the keyboard count
  770.     cmp    ax,0            ; convert any "outlier" region 
  771.     jne    coloradjust1        ;  (where abs(x) > 2 or abs(y) > 2)
  772.     mov    ax,1            ;   to look like we ran through
  773. coloradjust1:                ;    at least one loop.
  774.     cmp    ax,maxit        ; did we max out on iterations?
  775.     jne    coloradjust2        ;  nope.
  776.     mov    ax,1            ; reset max-out color to border color
  777. coloradjust2:                ;  (it just looks better, somehow)
  778.     mov    dx,0            ;  convert to a 32-bit value
  779.     div    colors            ;  ...
  780.     mov    al,dl            ; result in al
  781.  
  782.     call    dotwrite        ; invoke the appropriate write-a-dot
  783.  
  784. loopchecks:
  785.     fld    cur_x
  786.     inc    x            ; check for end of xloop
  787.     fadd    delx
  788.     mov    ax,xdots        ;  ...
  789.     cmp    x,ax            ;  ...
  790.     fstp    cur_x
  791.     jb    xloop            ; more to go
  792.  
  793.     fld    cur_y
  794.     inc    y            ; check for end of yloop
  795.     fsub    dely
  796.     mov    ax,ydots        ;  ...
  797.     cmp    y,ax            ;  ...
  798.     fstp    cur_y
  799.     jb    yloop            ; more to go
  800.  
  801. wedone:                    ; restore everything and return.
  802.     mov    ax,dotwrite        ; check: were we in EGA/VGA mode?
  803.     cmp    ax,offset vgawrite    ;  ...
  804.     jne    wereallydone        ; nope.  no adjustments
  805.     mov    ax,0ff08h        ; restore the default bit mask
  806.     out    dx,ax            ; ...
  807.     mov    ax,0003h        ; restore the function select
  808.     out    dx,ax            ;  ...
  809.     mov    ax,0001h        ; restore the enable set/reset
  810.     out    dx,ax            ;  ...
  811. wereallydone:
  812.     pop    es            ; restore the original ES value
  813.     mov    ax,kbdflag        ; return the keyboard-interrupt flag
  814.     mov    boxcount,0        ; indicate no boxes drawn yet.
  815.     ret                ; and return.
  816.  
  817. calcdots_sin endp
  818.  
  819.  
  820. ; **************** internal Read/Write-a-dot routines ***********************
  821.  
  822. normalwrite    proc    near        ; generic write-a-dot routine
  823.     push    ax            ; save the AX register for a tad
  824.     mov    eax,dotcount        ; determine the row and cloumn
  825.     mov    edx,dotcount        ; need it in a DX:AX pair
  826.     ror    edx,16            ;  now we have it
  827.     div    xdots            ; perform the divide
  828.     mov    cx,dx            ; this is the x-coord
  829.     mov    dx,ax            ; this is the y-coord
  830.     pop    ax            ; now retrieve the AX register
  831.     mov    ah,12            ; write the dot (al == color)
  832.     mov    bx,0            ; this page
  833.     push    bp            ; some BIOS's don't save this
  834.     int    10h            ; do it.
  835.     pop    bp            ; restore the saved register
  836.     ret                ; we done.
  837. normalwrite    endp
  838.  
  839. normalread    proc    near        ; generic read-a-dot routine
  840.     mov    eax,dotcount        ; determine the row and cloumn
  841.     mov    edx,dotcount        ; need it in a DX:AX pair
  842.     ror    edx,16            ;  now we have it
  843.     div    xdots            ; perform the divide
  844.     mov    cx,dx            ; this is the x-coord
  845.     mov    dx,ax            ; this is the y-coord
  846.     mov    ah,13            ; read the dot (al == color)
  847.     mov    bx,0            ; this page
  848.     push    bp            ; some BIOS's don't save this
  849.     int    10h            ; do it.
  850.     pop    bp            ; restore the saved register
  851.     ret                ; we done.
  852. normalread    endp
  853.  
  854. mcgawrite    proc    near        ; MCGA 320*200, 246 colors
  855.     mov    ebx,dotcount        ; load up an offset register
  856.     mov    es:[bx],al        ; write the dot
  857.     ret                ; we done.
  858. mcgawrite    endp
  859.  
  860. mcgaread    proc    near        ; MCGA 320*200, 246 colors
  861.     mov    ebx,dotcount        ; load up an offset register
  862.     mov    al,es:[bx]        ; retrieve the previous value
  863.     ret                ; we done.
  864. mcgaread    endp
  865.  
  866. vgawrite    proc    near        ; EGA/VGA write mode 0
  867.     mov    bh,al            ; save the color value for a bit
  868.     mov    esi,dotcount        ; compute the buffer offset
  869.     mov    cx,si            ; and bit mask
  870.     shr    esi,3            ; (buffer offset == dotcount / 8)
  871.     and    cx,7            ; bit-mask shift calculation
  872.     xor    cl,7            ;  ...
  873.     mov    dx,03ceh        ; graphics controller address
  874.     mov    ax,0108h        ; set up controller bit mask register
  875.     shl    ah,cl            ;  ...
  876.     out    dx,ax            ;  ...
  877.     mov    ah,bh            ; set set/reset registers
  878.     mov    al,0            ;  ...
  879.     out    dx,ax            ;  ...
  880.     mov    ax,0f01h        ; enable set/reset registers
  881.     out    dx,ax            ;  ...
  882.     or    es:[si],al        ; update all bit planes
  883.     ret                ; we done.
  884. vgawrite    endp
  885.  
  886. vgaread    proc    near            ; EGA/VGA read mode 0
  887.     mov    esi,dotcount        ; compute the buffer offset
  888.     mov    cx,si            ; and bit mask
  889.     shr    esi,3            ; (buffer offset == dotcount / 8)
  890.     and    cx,7            ; bit-mask shift calculation
  891.     xor    cl,7            ;  ...
  892.     mov    ch,01h            ; bit mask to shift
  893.     shl    ch,cl            ;  ...
  894.     mov    bx,0            ; initialize bits-read value (none)
  895.     mov    dx,03ceh        ; graphics controller address
  896.     mov    ax,0304h        ; set up controller address register
  897. vgareadloop:
  898.     out    dx,ax            ; do it
  899.     mov    bh,es:[si]        ; retrieve the old value
  900.     and    bh,ch            ; mask one bit
  901.     neg    bh            ; set bit 7 correctly
  902.     rol    bx,1            ; rotate the bit into bl
  903.     dec    ah            ; go for another bit?
  904.     jge    vgareadloop        ;  sure, why not.
  905.     mov    al,bl            ; returned pixel value
  906.     ret                ; we done.
  907. vgaread    endp
  908.  
  909. ; ******************** Function drawbox() *******************************
  910.  
  911. drawbox    proc
  912.     local    fluff7:dword        ; stack fluff for safety's sake
  913.     local    loc_xmax:dword        ; double-word copies of x and y
  914.     local    loc_xmin:dword        ;  zoom-box minimums and maximums
  915.     local    loc_ymax:dword        ;  ...
  916.     local    loc_ymin:dword        ;  ...
  917.     local    dxdots:dword        ; double-word versions of total
  918.     local    dydots:dword        ;  number of x, y dots on screen
  919.     local    xstep:dword        ; box drawing: x-step increments
  920.     local    ystep:dword        ; box drawing: y-step increments
  921.     local    fluff8:dword        ; stack fluff for safety's sake
  922.     local    boxcolor:byte        ; box drawing: box color
  923.     local    fluff9:dword        ; stack fluff for safety's sake
  924.  
  925.     mov    eax,0            ; move word min, max values to dwords
  926.     mov    ax,ixmin        ;  ...
  927.     mov    loc_xmin,eax        ;  ...
  928.     mov    ax,ixmax        ;  ...
  929.     mov    loc_xmax,eax        ;  ...
  930.     mov    ax,iymin        ;  ...
  931.     mov    loc_ymin,eax        ;  ...
  932.     mov    ax,iymax        ;  ...
  933.     mov    loc_ymax,eax        ;  ...
  934.     mov    ax,xdots        ; move xdots, ydots values to dwords
  935.     mov    dxdots,eax        ;  ...
  936.     mov    ax,ydots        ;  ...
  937.     mov    dydots,eax        ;  ...
  938.  
  939.     mov    eax,1            ; default x-step:  every pixel
  940.     mov    xstep,eax        ;  ...
  941.     mov    eax,dxdots        ; default y-step:  every row
  942.     mov    ystep,eax        ;  ...
  943.     mov    eax,loc_xmax        ; just how big is this zoom-box?
  944.     sub    eax,loc_xmin        ;  this many dots,...
  945.     shl    eax,3            ; an eighth of the screen or less?
  946.     cmp    eax,dxdots        ;  ...
  947.     jb    short solidbox        ;  yup.  keep the box solid.
  948.     mov    xstep,2            ; nope.  make the box every other pixel
  949.     mov    edx,ystep        ;  ...
  950.     add    ystep,edx        ;  ...
  951. solidbox:
  952.     shr    eax,1            ; a quarter of the screen or less?
  953.     cmp    eax,dxdots        ;  ...
  954.     jb    short solidbox2        ;  yup.  keep the box (semi) solid.
  955.     mov    xstep,4            ; nope.  make the box every 4th pixel
  956.     add    ystep,edx        ;  ...
  957. solidbox2:
  958.  
  959.     mov    ax,colors        ; define the zoom-box color
  960.     dec    al            ;  ...
  961.     cmp    al,15            ; do we have 16 colors?
  962.     jbe    short whitebox        ;  nope.  use what we can get.
  963.     mov    al,15            ; force a white zoom box
  964. whitebox:
  965.     mov    boxcolor,al        ; save the box color
  966.  
  967.     push    es            ; save the original ES value
  968.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  969.     mov    es,ax            ; save it here during this routine
  970.  
  971.     mov    bx,boxcount        ; load up a counter: # points to clear
  972.     dec    bx            ; switch to an offset value
  973.     js    short calcnewbox        ;  oops. no old box to clear.
  974. eraseoldbox:
  975.     shl    bx,2            ; switch to double-word counter
  976.     mov    edx,boxpoints[bx]    ; get the (previous) point location
  977.     mov    dotcount,edx        ; save it for the subroutine call
  978.     shr    bx,2            ; switch back to character counter
  979.     mov    al,boxvalues[bx]    ; get the (previous) color
  980.     push    bx            ; save the counter
  981.     call    dotwrite        ; adjust the dot.
  982.     pop    bx            ; restore the counter
  983.     dec    bx            ; are we done yet?
  984.     jns    eraseoldbox        ;  nope.  try again.
  985. calcnewbox:
  986.     mov    eax,loc_ymin        ; calculate top-left point
  987.     mul    dxdots            ;  == yoffset * dots/xline
  988.     add    eax,loc_xmin        ;     + xoffset
  989.     mov    boxpoints,eax        ; save it.
  990.     sub    eax,loc_xmin        ; now calculate top-right point
  991.     add    eax,loc_xmax        ;  ...
  992.     mov    boxpoints+4,eax        ; save it.
  993.     mov    eax,loc_ymax        ; calculate bottom-left point
  994.     mul    dxdots            ;  == yoffset * dots/xline
  995.     add    eax,loc_xmin        ;     + xoffset
  996.     mov    boxpoints+8,eax        ; save it.
  997.     sub    eax,loc_xmin        ; now calculate bot-right point
  998.     add    eax,loc_xmax        ;  ...
  999.     mov    boxpoints+12,eax    ; save it.
  1000.     mov    boxcount,4        ; set flag: new box drawn.
  1001.     mov    bx,boxcount        ; get set to draw lines
  1002.     shl    bx,2            ; switch to double-word pointers
  1003. starttop:
  1004.     mov    eax,boxpoints        ; now, draw the top line.
  1005.     mov    edx,xstep        ; draw every 'step'th dot
  1006. topline:
  1007.     add    eax,edx            ; calculate the next dot address
  1008.     cmp    eax,boxpoints+4        ; gone past the end-of-line?
  1009.     jae    short startbottom        ;  yup.  bail out.
  1010.     mov    boxpoints[bx],eax    ; save this point.
  1011.     add    bx,4            ; bump up the pointer offsets
  1012.     inc    boxcount        ; and counters
  1013.     jmp    topline            ; and try again.
  1014. startbottom:
  1015.     mov    eax,boxpoints+8        ; now, draw the bottom line.
  1016. bottomline:
  1017.     add    eax,edx            ; calculate the next dot address
  1018.     cmp    eax,boxpoints+12    ; gone past the end-of-line?
  1019.     jae    short startleft        ;  yup.  bail out.
  1020.     mov    boxpoints[bx],eax    ; save this point.
  1021.     add    bx,4            ; bump up the pointer offsets
  1022.     inc    boxcount        ; and counters
  1023.     jmp    bottomline        ; and try again.
  1024. startleft:
  1025.     mov    eax,boxpoints        ; now, draw the left line.
  1026.     mov    edx,ystep        ; draw every 'step'th dot
  1027. leftline:
  1028.     add    eax,edx            ; calculate the next dot address
  1029.     cmp    eax,boxpoints+8        ; gone past the end-of-line?
  1030.     jae    short startright        ;  yup.  bail out.
  1031.     mov    boxpoints[bx],eax    ; save this point.
  1032.     add    bx,4            ; bump up the pointer offsets
  1033.     inc    boxcount        ; and counters
  1034.     jmp    leftline        ; and try again.
  1035. startright:
  1036.     mov    eax,boxpoints+4        ; now, draw the right line.
  1037. rightline:
  1038.     add    eax,edx            ; calculate the next dot address
  1039.     cmp    eax,boxpoints+12    ; gone past the end-of-line?
  1040.     jae    short endlines        ;  yup.  bail out.
  1041.     mov    boxpoints[bx],eax    ; save this point.
  1042.     add    bx,4            ; bump up the pointer offsets
  1043.     inc    boxcount        ; and counters
  1044.     jmp    rightline        ; and try again.
  1045. endlines:
  1046.     mov    bx,boxcount        ; load up a counter: # points to draw
  1047.     dec    bx            ; switch to an offset
  1048. readnewbox:
  1049.     shl    bx,2            ; switch to double-word counter
  1050.     mov    edx,boxpoints[bx]    ; get the (new) point location
  1051.     mov    dotcount,edx        ; save it for the subroutine call
  1052.     shr    bx,2            ; switch back to character counter
  1053.     push    bx            ; save the counter
  1054.     call    dotread            ; read the (previous) dot value
  1055.     pop    bx            ; restore the counter
  1056.     mov    boxvalues[bx],al    ; get the (previous) color
  1057.     dec    bx            ; are we done yet?
  1058.     jns    readnewbox        ;  nope.  try again.
  1059.     mov    bx,boxcount        ; load up a counter: # points to draw
  1060.     dec    bx            ; switch to an offset
  1061. drawnewbox:
  1062.     shl    bx,2            ; switch to double-word counter
  1063.     mov    edx,boxpoints[bx]    ; get the (new) point location
  1064.     mov    dotcount,edx        ; save it for the subroutine call
  1065.     shr    bx,2            ; switch back to character counter
  1066.     push    bx            ; save the counter
  1067.     mov    al,boxcolor        ; set the (new) box color
  1068.     call    dotwrite        ; adjust the dot.
  1069.     pop    bx            ; restore the counter
  1070.     dec    bx            ; are we done yet?
  1071.     jns    drawnewbox        ;  nope.  try again.
  1072.  
  1073.     mov    ax,dotwrite        ; check: were we in EGA/VGA mode?
  1074.     cmp    ax,offset vgawrite    ;  ...
  1075.     jne    short dotsdone        ; nope.  no adjustments
  1076.     mov    ax,0ff08h        ; restore the default bit mask
  1077.     out    dx,ax            ; ...
  1078.     mov    ax,0003h        ; restore the function select
  1079.     out    dx,ax            ;  ...
  1080.     mov    ax,0001h        ; restore the enable set/reset
  1081.     out    dx,ax            ;  ...
  1082. dotsdone:
  1083.     pop    es            ; restore ES register
  1084.     ret                ; we done.
  1085.  
  1086. drawbox    endp
  1087.  
  1088. ; **************** Function setvideomode(ax, bx, cx, dx) ****************
  1089.  
  1090. ;    This function sets the (alphanumeric or graphic) video mode
  1091. ;    of the monitor.   Called with the proper values of AX thru DX.
  1092. ;    No returned values, as there is no particular standard to
  1093. ;    adhere to in this case.
  1094.  
  1095. setvideomode    proc    argax:word, argbx:word, argcx:word, argdx:word
  1096.     push    ax            ; save registers
  1097.     push    bx            ;  ...
  1098.     push    cx            ;  ...
  1099.     push    dx            ;  ...
  1100.     push    bp            ;  ...
  1101.     mov    ax,argax        ; load up for the interrupt call
  1102.     mov    bx,argbx        ;  ...
  1103.     mov    cx,argcx        ;  ...
  1104.     mov    dx,argdx        ;  ...
  1105.     int    10h            ; do it.
  1106.     pop    bp            ; restore registers
  1107.     pop    dx            ;  ...
  1108.     pop    cx            ;  ...
  1109.     pop    bx            ;  ...
  1110.     pop    ax            ;  ...
  1111.     ret
  1112. setvideomode    endp
  1113.  
  1114.  
  1115. ; ****************** Function getakey() *****************************
  1116.  
  1117. ;    This function gets a key from either a "normal" or an enhanced
  1118. ;    keyboard.   Returns either the vanilla ASCII code for regular
  1119. ;    keys, or 1000+(the scan code) for special keys (like F1, etc)
  1120. ;    Use of this routine permits the Control-Up/Down arrow keys on
  1121. ;    enhanced keyboards.
  1122. ;
  1123. ;    The concept for this routine was "borrowed" from the MSKermit
  1124. ;    SCANCHEK utility
  1125.  
  1126. getakey    proc
  1127.     push    es                ; save ES for a tad
  1128.     mov    ax,40h                ; reload ES with BIOS data seg
  1129.     mov    es,ax                ;  ...
  1130.     mov    ah,es:96h            ; get the keyboard byte
  1131.     pop    es                ; restore ES
  1132.     and    ah,10h                ; isolate the Enhanced KBD bit
  1133.     int    16h                ; now get a key
  1134.     cmp    al,0e0h                ; check: Enhanced Keyboard key?
  1135.     jne    short getakey1            ; nope.  proceed
  1136.     cmp    ah,0                ; part 2 of Enhanced Key check
  1137.     je    short getakey1            ; failed.  normal key.
  1138.     mov    al,0                ; Turn enhanced key "normal"
  1139.     jmp    short getakey2            ; jump to common code
  1140. getakey1:            
  1141.     cmp    ah,0e0h                ; check again:  Enhanced Key?
  1142.     jne    short getakey2            ;  nope.  proceed.
  1143.     mov    ah,al                ; Turn Enhanced key "normal"
  1144.     mov    al,0                ;  ...
  1145. getakey2:
  1146.     cmp    al,0                ; Function Key?
  1147.     jne    short getakey3            ;  nope.  proceed.
  1148.     mov    al,ah                ; klooge into ASCII Key
  1149.     mov    ah,0                ; clobber the scan code
  1150.     add    ax,1000                ;  + 1000
  1151.     jmp    short getakey4            ; go to common return
  1152. getakey3:
  1153.     mov    ah,0                ; clobber the scan code
  1154. getakey4:
  1155.     ret
  1156. getakey    endp
  1157.  
  1158.        end
  1159.  
  1160.