home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / graf / fract3.zip / VIDEO.ASM < prev    next >
Assembly Source File  |  1989-12-18  |  98KB  |  3,045 lines

  1. ;    Generic assembler routines having to do with video adapters
  2. ;
  3. ; ---- Video Routines 
  4. ;
  5. ;    setvideomode()
  6. ;    getcolor()
  7. ;    putcolor()
  8. ;    out_line()
  9. ;    drawbox()
  10. ;    home()
  11. ;    movecursor()
  12. ;    clscr()
  13. ;    scrollup()
  14. ;    putblock()
  15. ;    putstr()
  16. ;    scroll()
  17. ;    storedac()        TARGA - NEW - 3 June 89 j mclain
  18. ;    loaddac()
  19. ;    spindac()
  20. ;    asmdotwrite        (called by CALCMAND.ASM using registers)
  21. ;    asmvideocleanup            ""
  22. ;
  23. ; ---- Help (Video) Support
  24. ;
  25. ;    setfortext()
  26. ;    setforgraphics()
  27. ;    setclear()
  28. ;
  29.  
  30. ;             required for compatibility if Turbo ASM
  31. IFDEF ??version
  32.     MASM51
  33.     QUIRKS
  34. ENDIF
  35.  
  36.     .MODEL  medium,c
  37.  
  38.     .8086
  39.  
  40.         ; these must NOT be in any segment!!
  41.         ; this get's rid of TURBO-C fixup errors
  42.  
  43.         extrn   startvideo:far          ; start your-own-video routine
  44.         extrn   readvideo:far           ; read  your-own-video routine
  45.         extrn   writevideo:far          ; write your-own-video routine
  46.         extrn   endvideo:far            ; end   your-own-video routine
  47.  
  48.         extrn   startdisk:far           ; start disk-video routine
  49.         extrn   readdisk:far            ; read  disk-video routine
  50.         extrn   writedisk:far           ; write disk-video routine
  51.         extrn   enddisk:far             ; end   disk-video routine
  52.  
  53. ; TARGA 28 May 80 - j mclain
  54.         extrn   StartTGA  :far        ; start    TARGA
  55.         extrn   ReadTGA   :far        ; read    TARGA
  56.         extrn   WriteTGA  :far        ; write    TARGA
  57.     extrn    LineTGA   :far        ; line    TARGA
  58.         extrn   EndTGA    :far        ; end    TARGA
  59.  
  60.  
  61. ; 8514/A routines
  62.     extrn   open8514  :far      ; start 8514a
  63.     extrn   reopen8514:far      ; restart 8514a
  64.     extrn   close8514 :far      ; stop 8514a
  65.     extrn   fr85wdot  :far      ; 8514a write dot
  66.     extrn   fr85wbox  :far      ; 8514a write box
  67.     extrn   fr85rdot  :far      ; 8514a read dot
  68.     extrn   w8514pal  :far      ; 8514a pallete update
  69.  
  70. ; Hercules Routines
  71.     extrn    inithgc      :far      ; Initialize Hercules card graphics mode
  72.     extrn    termhgc   :far      ; Terminate Hercules card graphics mode
  73.     extrn    writehgc  :far      ; Hercules write dot
  74.     extrn   readhgc   :far      ; Hercules read dot
  75.     extrn   linehgc   :far      ; Hercules line draw
  76.     extrn   charhgc   :far      ; Draw an ASCII char in Hercules graphics 
  77.  
  78. .DATA
  79.  
  80. ; ************************ External variables *****************************
  81.  
  82.     extrn    oktoprint: word        ; flag: == 1 if printf() will work
  83.     extrn    videoentry:byte        ; video table entry flag
  84.     extrn    dotmode: word        ; video mode:
  85. ;                        1 = use the BIOS (yuck)
  86. ;                        2 = use EGA/VGA style
  87. ;                        3 = use MCGA style
  88. ;                        4 = use Tseng 256 color
  89. ;                        5 = use Paradise 256 color
  90. ;                        6 = use Video 7 256 color
  91. ;                        7 = MVGA 256 color
  92. ;                        9 = use TARGA
  93. ;                        10= Hercules
  94. ;                        11= "disk" video
  95. ;                        12= 8514/A 
  96. ;                        13= CGA 4,2-color
  97. ;                        14= Tandy-1000 (someday)
  98. ;                        15= use Trident 256 color
  99. ;                        16= use Chips & Tech 256 color
  100. ;                        17= use ATI VGA Wonder 256 color
  101. ;                        18= use Everex 256 color
  102. ;                        19= use roll-your-own
  103. ;                            (see YOURVID.C)
  104. ;                        20= use ATI 1024  16 color
  105. ;                        21= use tseng     16 color
  106. ;                        22= use trident   16 color
  107. ;                        23= use video7    16 color
  108. ;                        24= use paradise  16 color
  109. ;                        25= use chipstech 16 color
  110. ;                        26= use everex    16 color
  111.  
  112.     extrn    xdots:word, ydots:word    ; number of dots across and down
  113.     extrn    maxit:word, colors:word    ; maximum iterations, colors
  114.     extrn    ixmin:word, ixmax:word    ; for zoom/pan: x and y limits
  115.     extrn    iymin:word, iymax:word    ;  for the local zoom-box
  116.     extrn    cyclelimit:word        ; limiting factor for DAC-cycler
  117.     extrn    debugflag:word        ; for debugging purposes only
  118.  
  119.     extrn    boxcount:word        ; (previous) box pt counter: 0 if none.
  120.     extrn    boxx:word, boxy:word    ; zoom-box save-value locations
  121.     extrn    boxvalues:byte        ; zoom-box save-pixel locations
  122.  
  123.     extrn    xorTARGA:word        ; TARGA 3 June 89 j mclain
  124.                     ; flag says xor pixels for box
  125.  
  126.     extrn    cpu:word        ; CPU type (86, 186, 286, or 386)
  127.     extrn    extraseg:word        ; location of the EXTRA segment
  128.  
  129. ; ************************ Public variables *****************************
  130.  
  131. public        andcolor        ; used by 'calcmand'
  132.  
  133. public        loadPalette        ; flag for loading VGA/TARGA palette from disk
  134. public        dacbox            ; GIF saves use this
  135. public        daclearn, daccount    ; Rotate may want to use this
  136. public        rowcount        ; row-counter for decoder and out_line
  137. public        reallyega        ; "really an EGA" (faking a VGA) flag
  138.  
  139. ;        arrays declared here, used elsewhere
  140. ;        arrays not used simultaneously are deliberately overlapped
  141.  
  142. ; ************************ Internal variables *****************************
  143.  
  144. dotwrite    dw    0        ; write-a-dot routine:  mode-specific
  145. dotread        dw    0        ; read-a-dot routine:   mode-specific
  146. linewrite    dw    0        ; write-a-line routine: mode-specific
  147. andcolor    dw    0        ; "and" value used for color selection
  148. color        db    0        ; the color to set a pixel
  149. videoflag    db    0        ; special "your-own-video" flag
  150. diskflag    db    0        ; special "disk-video" flag
  151. tgaflag        db    0        ; TARGA 28 May 89 - j mclain
  152. loadPalette    db    0        ; TARGA/VGA load palette from disk
  153.  
  154. f85flag        db    0        ;flag for 8514a
  155.  
  156. HGCflag        db    0        ;flag for Hercules Graphics Adapter
  157.  
  158. ;                    ; Zoom-Box values (2K x 2K screens max)
  159. step        dw    0        ; Zoom-Box drawing step-size
  160. boxcolor    db    0        ; Zoom-Box color
  161. reallyega    dw    0        ; 1 if its an EGA posing as a VGA
  162. palettega    db    17 dup(0)    ; EGA palette registers go here
  163. daclearn    db    0        ; 0 if "learning" DAC speed
  164. dacnorm        db    0        ; 0 if "normal" DAC update
  165. daccount    dw    0        ; DAC registers to update in 1 pass
  166. dacbox        db    773 dup(0)    ; DAC goes here
  167.  
  168. rowcount    dw    0        ; row-counter for decoder and out_line
  169.  
  170. orvideo        db    0        ; "or" value for setvideo
  171. videoax        dw    0        ; graphics mode values: ax
  172. videobx        dw    0        ; graphics mode values: bx
  173. videocx        dw    0        ; graphics mode values: cx
  174. videodx        dw    0        ; graphics mode values: dx
  175.  
  176. ; ******************* "Tweaked" VGA mode variables ************************
  177.  
  178.                         ; 704 x 528 mode
  179. x704y528    db    704/8            ; number of screen columns
  180.         db    528/16            ; number of screen rows
  181.         db     68h, 57h, 58h, 8Bh    ; CRTC Registers
  182.         db     59h, 86h, 3EH,0F0h
  183.         db      0h, 60h,  0h,  0h
  184.         db      0h,  0h,  2h, 3Dh
  185.         db     19h, 8Bh, 0Fh, 2Ch
  186.         db      0h, 18h, 38h,0E3h
  187.         db    0FFh
  188.                         ; 720 x 540 mode
  189. x720y540    db    720/8            ; number of screen columns
  190.         db    540/16            ; number of screen rows
  191.         db     6Ah, 59h, 5Ah, 8Dh    ; CRTC Registers
  192.         db     5Eh, 8Bh, 4AH,0F0h
  193.         db      0h, 60h,  0h,  0h
  194.         db      0h,  0h,  2h, 49h
  195.         db     24h, 86h, 1Bh, 2Dh
  196.         db      0h, 24h, 44h,0E3h
  197.         db    0FFh
  198.                         ; 736 x 552 mode
  199. x736y552    db    736/8            ; number of screen columns
  200.         db    552/16            ; number of screen rows
  201.         db     6Ch, 5Bh, 5Ch, 8Fh    ; CRTC Registers
  202.         db     5Fh, 8Ch, 56H,0F0h
  203.         db      0h, 60h,  0h,  0h
  204.         db      0h,  0h,  2h, 55h
  205.         db     2Bh, 8Dh, 27h, 2Eh
  206.         db      0h, 30h, 50h,0E3h
  207.         db    0FFh
  208.                         ; 752 x 564 mode
  209. x752y564    db    752/8            ; number of screen columns
  210.         db    564/16            ; number of screen rows
  211.         db     6Eh, 5Dh, 5Eh, 91h    ; CRTC Registers
  212.         db     62h, 8Fh, 62H,0F0h
  213.         db      0h, 60h,  0h,  0h
  214.         db      0h,  0h,  2h, 61h
  215.         db     37h, 89h, 33h, 2Fh
  216.         db      0h, 3Ch, 5Ch,0E3h
  217.         db    0FFh
  218.                         ; 768 x 576 mode
  219. x768y576    db    768/8            ; number of screen columns
  220.         db    576/16            ; number of screen rows
  221.         db     70h, 5Fh, 60h, 93h    ; CRTC Registers
  222.         db     66h, 93h, 6EH,0F0h
  223.         db      0h, 60h,  0h,  0h
  224.         db      0h,  0h,  2h, 6Dh
  225.         db     43h, 85h, 3Fh, 30h
  226.         db      0h, 48h, 68h,0E3h
  227.         db    0FFh
  228.                         ; 784 x 588 mode
  229. x784y588    db    784/8            ; number of screen columns
  230.         db    588/16            ; number of screen rows
  231.         db     72h, 61h, 62h, 95h    ; CRTC Registers
  232.         db     69h, 96h, 7AH,0F0h
  233.         db      0h, 60h,  0h,  0h
  234.         db      0h,  0h,  2h, 79h
  235.         db     4Fh, 81h, 4Bh, 31h
  236.         db      0h, 54h, 74h,0E3h
  237.         db    0FFh
  238.                         ; 800 x 600 mode
  239. x800y600    db    800/8            ; number of screen columns
  240.         db    600/16            ; number of screen rows
  241.         db     74h, 63h, 64h, 97h    ; CRTC Registers
  242.         db     68h, 95h, 86H,0F0h
  243.         db      0h, 60h,  0h,  0h
  244.         db      0h,  0h,  2h, 85h
  245.         db     5Bh, 8Dh, 57h, 32h
  246.         db      0h, 60h, 80h,0E3h
  247.         db    0FFh
  248.  
  249. x360y480    db    360/8            ; number of screen columns
  250.         db    480/16            ; number of screen rows
  251.         db     6bh, 59h, 5ah, 8eh    ; CRTC Registers
  252.         db     5eh, 8ah, 0DH,03Eh
  253.         db      0h, 40h, 00h,  0h
  254.         db      0h,  0h,  0h, 31h
  255.         db    0EAh, 0ACh, 0DFh, 2Dh
  256.         db      0h,0E7h, 06h,0E3h
  257.         db    0FFh
  258.  
  259.  
  260. x320y400        db      320/8                   ; number of screen columns
  261.                 db      400/16                  ; number of screen rows
  262.                 db       5fh, 4fh, 50h, 82h     ; CRTC Registers
  263.                 db       54h, 80h,0bfh, 1fh
  264.                 db       00h, 40h, 00h, 00h
  265.                 db       00h, 00h, 00h, 00h
  266.                 db       9ch, 8eh, 8fh, 28h
  267.                 db       00h, 96h,0b9h,0E3h
  268.                 db      0FFh
  269.  
  270. x640y400        db      640/8            ; number of screen columns
  271.                 db      400/16                  ; number of screen rows   
  272.         db     5eh, 4fh, 50h, 01h     ; CRTC Registers          
  273.         db       54h, 9fh,0c0h, 1fh
  274.         db       00h, 40h, 00h, 00h
  275.         db       00h, 00h, 00h, 00h
  276.         db       9ch,08eh, 8fh, 28h
  277.         db       00h, 95h,0bch,0c3h
  278.         db       0ffh               
  279.  
  280. tweaks        dw    offset x704y528        ; tweak table
  281.         dw    offset x704y528
  282.         dw    offset x720y540
  283.         dw    offset x736y552
  284.         dw    offset x752y564
  285.         dw    offset x768y576
  286.         dw    offset x784y588
  287.         dw    offset x800y600
  288.         dw    offset x360y480
  289.         dw    offset x320y400
  290.         dw    offset x640y400        ; Tseng Super VGA
  291.  
  292. tweaktype    dw    0            ; 8 or 9 (320x400 or 360x480)
  293.  
  294. .CODE
  295.  
  296. ;            Video Table Entries
  297. ;
  298. ;    The Video Table has been moved to a FARDATA segment to relieve
  299. ;    some of the pressure on the poor little    overloaded 64K DATA segment.
  300.  
  301. ;    This code has three entry points:
  302. ;
  303. ;    sizeoftable = initvideotable();        returns the # of table entries
  304. ;
  305. ;    fromvideotable(i);            copies table entry #i into
  306. ;                        the videoentry structure
  307. ;
  308. ;    tovideotable(i);            moves the videoentry structure
  309. ;                        into the table at entry #i
  310.  
  311.  
  312. .code
  313.  
  314. videotable    db    0    ; video table actually starts on the NEXT byte
  315.  
  316. ;    Feel free to add your favorite video adapter to the following table.
  317. ;    Just remember that only the first 100 or so entries get displayed and
  318. ;    assigned Function keys.
  319.  
  320. ;    Currently available Video Modes are (use the BIOS as a last resort)
  321.  
  322. ;        1) use the BIOS (INT 10H, AH=12/13, AL=color) ((SLOW))
  323. ;        2) pretend it's a (perhaps super-res) EGA/VGA
  324. ;        3) pretend it's an MCGA
  325. ;        4) SuperVGA 256-Color mode using the Tseng Labs Chipset
  326. ;        5) SuperVGA 256-Color mode using the Paradise Chipset
  327. ;        6) SuperVGA 256-Color mode using the Video-7 Chipset
  328. ;        7) Non-Standard IBM VGA 360 x 480 x 256-Color mode
  329. ;        8) SuperVGA 1024x768x16 mode for the Everex Chipset
  330. ;        9) TARGA video modes
  331. ;        10) HERCULES video mode
  332. ;        11) Non-Video [disk or RAM] "video"
  333. ;        12) 8514/A video modes
  334. ;        13) CGA 320x200x4-color and 640x200x2-color modes
  335. ;        14) Reserved for Tandy 1000 video modes
  336. ;        15) SuperVGA 256-Color mode using the Trident Chipset
  337. ;        16) SuperVGA 256-Color mode using the Chips & Tech Chipset
  338. ;        17) SuperVGA 256-Color mode using the ATI VGA Wonder Chipset
  339. ;        18) SuperVGA 256-Color mode using the Everex Chipset
  340. ;        19) Roll-Your-Own video, as defined in YOURVID.C
  341. ;        20) SuperVGA 1024x768x16 mode for the ATI VGA Wonder Chipset
  342. ;        21) SuperVGA 1024x768x16 mode for the Tseng Labs Chipset
  343. ;        22) SuperVGA 1024x768x16 mode for the Trident Chipset
  344. ;        23) SuperVGA 1024x768x16 mode for the Video 7 Chipset
  345. ;        24) SuperVGA 1024x768x16 mode for the Paradise Chipset
  346. ;        25) SuperVGA 1024x768x16 mode for the Chips & Tech Chipset
  347.  
  348. ;               |--Adapter/Mode-Name------|-------Comments-----------|
  349.  
  350. ;        |------INT 10H------|Dot-|--Resolution---|
  351. ;        |--AX---BX---CX---DX|Mode|--X-|--Y-|Color|
  352.  
  353.     db    "IBM Low-Rez EGA           Quick but chunky          "
  354.     dw      0dh,   0,   0,   0,   2, 320, 200,  16
  355.     db    "IBM 16-Color EGA          Slower but lots nicer     "
  356.     dw      10h,   0,   0,   0,   2, 640, 350,  16
  357.     db    "IBM 256-Color MCGA        Quick and LOTS of colors  "
  358.     dw      13h,   0,   0,   0,   3, 320, 200, 256
  359.     db    "IBM 16-Color VGA          Nice high resolution      "
  360.     dw      12h,   0,   0,   0,   2, 640, 480,  16
  361.     db    "IBM 4-Color CGA           (Ugh - Yuck - Bleah)      "
  362.     dw       4h,   0,   0,   0,  13, 320, 200,   4
  363.     db    "IBM Hi-Rez B&W CGA        ('Hi-Rez' Ugh - Yuck)     "
  364.     dw       6h,   0,   0,   0,  13, 640, 200,   2
  365.     db    "IBM B&W EGA               (Monochrome EGA)          "
  366.     dw      0fh,   0,   0,   0,   2, 640, 350,   2
  367.     db    "IBM B&W VGA               (Monochrome VGA)          "
  368.     dw      11h,   0,   0,   0,   2, 640, 480,   2
  369.     db    "IBM Med-Rez EGA           (Silly but it's there!)   "
  370.     dw      0eh,   0,   0,   0,   2, 640, 200,  16
  371.     db    "IBM VGA (non-std/no text) Register Compatibles ONLY "
  372.     dw       0h,   0,   0,   9,   7, 320, 400, 256
  373.     db    "IBM VGA (non-std/no text) Register Compatibles ONLY "
  374.     dw       0h,   0,   0,   8,   7, 360, 480, 256
  375.     db    "8514/A Low  Res           Requires IBM's HDIDLOAD   "
  376.     dw       3h,   0,   0,   1,  12, 640, 480, 256
  377.     db    "8514/A High Res           Requires IBM's HDIDLOAD   "
  378.     dw       3h,   0,   0,   1,  12,1024, 768, 256
  379.     db    "8514/A Low  W/Border      Requires IBM's HDIDLOAD   "
  380.     dw       3h,   0,   0,   1,  12, 632, 474, 256
  381.     db    "8514/A High W/Border      Requires IBM's HDIDLOAD   "
  382.     dw       3h,   0,   0,   1,  12,1016, 762, 256
  383.     db    "VESA Standard interface   UNTESTED: may not work    "
  384.     dw      6ah,   0,   0,   0,   2, 800, 600,  16
  385.     db    "COMPAQ Portable 386       OK: Michael Kaufman       "
  386.     dw      40h,   0,   0,   0,   1, 640, 400,   2
  387.     db    "Video-7 Vram VGA          OK: Ira Emus              "
  388.     dw    6f05h, 60h,   0,   0,   2, 752, 410,  16
  389.     db    "Video-7 Vram VGA          OK: Ira Emus              "
  390.     dw    6f05h, 61h,   0,   0,   2, 720, 540,  16
  391.     db    "Video-7 Vram VGA          OK: Ira Emus              "
  392.     dw    6f05h, 62h,   0,   0,   2, 800, 600,  16
  393.     db    "Video-7 Vram VGA          OK: Ira Emus              "
  394.     dw    6f05h, 63h,   0,   0,   1,1024, 768,   2
  395.     db    "Video-7 Vram VGA          OK: Ira Emus              "
  396.     dw    6f05h, 64h,   0,   0,   1,1024, 768,   4
  397.     db    "Video-7 Vram VGA w/512K   OK: Sandy & Frank Lozier  "
  398.     dw    6f05h, 65h,   0,   0,  23,1024, 768,  16
  399.     db    "Video-7 Vram VGA          OK: Michael Kaufman       "
  400.     dw    6f05h, 66h,   0,   0,   6, 640, 400, 256
  401.     db    "Video-7  w/512K           OK: Greg Reznick          "
  402.     dw    6f05h, 67h,   0,   0,   6, 640, 480, 256
  403.     db    "Video-7  w/512K           OK: Greg Reznick          "
  404.     dw    6f05h, 68h,   0,   0,   6, 720, 540, 256
  405.     db    "Video-7  w/512K           OK: Greg Reznick          "
  406.     dw    6f05h, 69h,   0,   0,   6, 800, 600, 256
  407.     db    "Tseng SuperVGA tweaked    (adds missing Tseng mode) "
  408.     dw       0h,   0,   0,  10,   4, 640, 400, 256
  409.     db    "Orchid/STB/GENOA/SIGMA    OK: Monte Davis           "
  410.     dw      2eh,   0,   0,   0,   4, 640, 480, 256
  411.     db    "Orchid/STB/GENOA/SIGMA    OK: Monte Davis           "
  412.     dw      29h,   0,   0,   0,   2, 800, 600,  16
  413.     db    "Orchid/STB/GENOA/SIGMA    OK: Monte Davis           "
  414.     dw      30h,   0,   0,   0,   4, 800, 600, 256
  415.     db    "Orchid/STB/GENOA/SIGMA    OK: Timothy Wegner        "
  416.     dw      37h,   0,   0,   0,  21,1024, 768,  16
  417.     db    "GENOA/STB                 OK: Timothy Wegner        "
  418.     dw      2dh,   0,   0,   0,   4, 640, 350, 256
  419.     db    "GENOA                     OK: Timothy Wegner        "
  420.     dw      27h,   0,   0,   0,   2, 720, 512,  16
  421.     db    "GENOA                     OK: Timothy Wegner        "
  422.     dw      2fh,   0,   0,   0,   4, 720, 512, 256
  423.     db    "GENOA                     OK: Timothy Wegner        "
  424.     dw      7ch,   0,   0,   0,   2, 512, 512,  16
  425.     db    "GENOA                     OK: Timothy Wegner        "
  426.     dw      7dh,   0,   0,   0,   4, 512, 512, 256
  427.     db    "STB                       UNTESTED: may not work    "
  428.     dw      36h,   0,   0,   0,   1, 960, 720,  16
  429.     db    "Everex EVGA               OK: Travis Harrison       "
  430.     dw      70h,   0,   0,   0,   2, 640, 480,  16
  431.     db    "Everex EVGA               OK: Travis Harrison       "
  432.     dw      70h,  1h,   0,   0,   2, 752, 410,  16
  433.     db    "Everex EVGA               OK: Travis Harrison       "
  434.     dw      70h,  2h,   0,   0,   2, 800, 600,  16
  435.     db    "Everex EVGA               OK: Travis Harrison       "
  436.     dw      70h, 11h,   0,   0,   1,1280, 350,   4
  437.     db    "Everex EVGA               OK: Travis Harrison       "
  438.     dw      70h, 12h,   0,   0,   1,1280, 600,   4
  439.     db    "Everex EVGA               UNTESTED: may not work    "
  440.     dw      70h, 13h,   0,   0,  18, 640, 350, 256
  441.     db    "Everex EVGA               UNTESTED: may not work    "
  442.     dw      70h, 14h,   0,   0,  18, 640, 400, 256
  443.     db    "Everex EVGA               UNTESTED: may not work    "
  444.     dw      70h, 15h,   0,   0,  18, 512, 480, 256
  445.     db    "ATI EGA Wonder            OK: Garrett Wollman       "
  446.     dw      51h,   0,   0,   0,   1, 640, 480,  16
  447.     db    "ATI EGA Wonder            OK: Garrett Wollman       "
  448.     dw      52h,   0,   0,   0,   1, 800, 560,  16
  449.     db    "ATI VGA Wonder            OK: Henry So              "
  450.     dw      54h,   0,   0,   0,   2, 800, 600,  16
  451.     db    "ATI VGA Wonder            OK: Mark Peterson         "
  452.     dw      61h,   0,   0,   0,  17, 640, 400, 256
  453.     db    "ATI VGA Wonder (512K)     OK: Mark Peterson         "
  454.     dw      62h,   0,   0,   0,  17, 640, 480, 256
  455.     db    "ATI VGA Wonder (512K)     OK: Mark Peterson         "
  456.     dw      63h,   0,   0,   0,  17, 800, 600, 256
  457.     db    "ATI VGA Wonder (512K)     OK: Mark Peterson         "
  458.     dw      65h,   0,   0,   0,  20,1024, 768,  16
  459.     db    "Paradise EGA-480          UNTESTED: may not work    "
  460.     dw      50h,   0,   0,   0,   1, 640, 480,  16
  461.     db    "Pdise/AST/COMPAQ VGA      OK: Tom Devlin            "
  462.     dw      5eh,   0,   0,   0,   5, 640, 400, 256
  463.     db    "Pdise/AST/COMPAQ VGA      OK: Phil Wilson           "
  464.     dw      5fh,   0,   0,   0,   5, 640, 480, 256
  465.     db    "Pdise/AST/COMPAQ VGA      OK: by Chris Green        "
  466.     dw      58h,   0,   0,   0,   2, 800, 600,  16
  467.     db    "Pdise/AST/COMPAQ VGA      OK: Phil Wilson           "
  468.     dw      59h,   0,   0,   0,   1, 800, 600,   2
  469.     db    "Tandy 1000 16 Clr LoRez   OK: Tom Price             "
  470.     dw       8h,   0,   0,   0,   1, 160, 200,  16
  471.     db    "Tandy 1000 16 Color CGA   OK: Tom Price             "
  472.     dw       9h,   0,   0,   0,   1, 320, 200,  16
  473.     db    "Tandy 1000 4 Color hi-rez OK: Tom Price             "
  474.     dw      0ah,   0,   0,   0,   1, 640, 200,   4
  475.     db    "AT&T 6300                 UNTESTED: may not work    "
  476.     dw      41h,   0,   0,   0,   1, 640, 200,  16
  477.     db    "AT&T 6300                 OK: Michael Kaufman       "
  478.     dw      40h,   0,   0,   0,   1, 640, 400,   2
  479.     db    "AT&T 6300                 OK: Colby Norton          "
  480.     dw      42h,   0,   0,   0,   1, 640, 400,  16
  481.     db    "TARGA 256 Color video     OK: Bruce Goren           "
  482.     dw       0h,   0,   0,   0,   9, 512, 482, 256
  483.     db    "TARGA 256 Color 35mm      OK: Bruce Goren           "
  484.     dw       0h,   0,   0,   0,   9, 512, 342, 256
  485.     db    "TARGA 256 Color 4 x 5     OK: Bruce Goren           "
  486.     dw       0h,   0,   0,   0,   9, 512, 384, 256
  487.     db    "TRIDENT Chipset           OK: Warren Gold           "
  488.     dw      5bh,   0,   0,   0,   2, 800, 600,  16
  489.     db    "TRIDENT Chipset           OK: Warren Gold           "
  490.     dw      5ch,   0,   0,   0,  15, 640, 400, 256
  491.     db    "TRIDENT Chipset           OK: Warren Gold           "
  492.     dw      5dh,   0,   0,   0,  15, 640, 480, 256
  493.     db    "TRIDENT Chipset           OK: Warren Gold           "
  494.     dw      5eh,   0,   0,   0,  15, 800, 600, 256
  495.     db    "TRIDENT Chipset           UNTESTED: May not work    "
  496.     dw      5fh,   0,   0,   0,  22,1024, 768,  16
  497.     db    "Chips & Tech Chipset      OK: Andy Fu               "
  498.     dw      78h,   0,   0,   0,  16, 640, 400, 256
  499.     db    "Chips & Tech Chipset      OK: Andy Fu               "
  500.     dw      79h,   0,   0,   0,  16, 640, 480, 256
  501.     db    "Chips & Tech Chipset      OK: Andy Fu               "
  502.     dw      7bh,   0,   0,   0,  16, 800, 600, 256
  503.     db    "Chips & Tech Chipset      OK: Andy Fu               "
  504.     dw      70h,   0,   0,   0,   2, 800, 600,  16
  505.     db    "Chips & Tech Chipset      UNTESTED: May not work    "
  506.     dw      72h,   0,   0,   0,  25,1024, 768,  16
  507.     db    "Hercules Graphics         OK: Timothy Wegner        "
  508.     dw       8h,   0,   0,   0,  10, 720, 348,   2
  509.     db    "Disk/RAM 'Video'          Full-Page Epson @  60DPI  "
  510.     dw       3h,   0,   0,   0,  11, 768, 480,   2
  511.     db    "Disk/RAM 'Video'          Full-Page Epson @ 120DPI  "
  512.     dw       3h,   0,   0,   0,  11, 768, 960,   2
  513.     db    "Disk/RAM 'Video'          Full-Page Epson @ 240DPI  "
  514.     dw       3h,   0,   0,   0,  11, 768,1920,   2
  515.     db    "Disk/RAM 'Video'          Full-Page L-Jet @  75DPI  "
  516.     dw       3h,   0,   0,   0,  11, 800, 600,   2
  517.     db    "Disk/RAM 'Video'          Full-Page L-Jet @ 150DPI  "
  518.     dw       3h,   0,   0,   0,  11,1600,1200,   2
  519.     db    "Disk/RAM 'Video'          For Background Fractals   "
  520.     dw       3h,   0,   0,   0,  11, 320, 200, 256
  521.     db    "Disk/RAM 'Video'          For Background Fractals   "
  522.     dw       3h,   0,   0,   0,  11, 360, 480, 256
  523.     db    "Disk/RAM 'Video'          For Background Fractals   "
  524.     dw       3h,   0,   0,   0,  11, 640, 350, 256
  525.     db    "Disk/RAM 'Video'          For Background Fractals   "
  526.     dw       3h,   0,   0,   0,  11, 640, 400, 256
  527.     db    "Disk/RAM 'Video'          For Background Fractals   "
  528.     dw       3h,   0,   0,   0,  11, 640, 480, 256
  529.     db    "Disk/RAM 'Video'          For Background Fractals   "
  530.     dw       3h,   0,   0,   0,  11, 800, 600, 256
  531.     db    "Disk/RAM 'Video'          For Background Fractals   "
  532.     dw       3h,   0,   0,   0,  11,1024, 768, 256
  533.     db    "Disk/RAM 'Video'          For Background Fractals   "
  534.     dw       3h,   0,   0,   0,  11,2048,2048, 256
  535.     db    "IBM VGA (+tweaked+)       Register Compatibles ONLY "
  536.     dw       0h,   0,   0,   1,   2, 704, 528,  16
  537.     db    "IBM VGA (+tweaked+)       Register Compatibles ONLY "
  538.     dw       0h,   0,   0,   2,   2, 720, 540,  16
  539.     db    "IBM VGA (+tweaked+)       Register Compatibles ONLY "
  540.     dw       0h,   0,   0,   3,   2, 736, 552,  16
  541.     db    "IBM VGA (+tweaked+)       Register Compatibles ONLY "
  542.     dw       0h,   0,   0,   4,   2, 752, 564,  16
  543.     db    "IBM VGA (+tweaked+)       Register Compatibles ONLY "
  544.     dw       0h,   0,   0,   5,   2, 768, 576,  16
  545.     db    "IBM VGA (+tweaked+)       Register Compatibles ONLY "
  546.     dw       0h,   0,   0,   6,   2, 784, 588,  16
  547.     db    "IBM VGA (+tweaked+)       Register Compatibles ONLY "
  548.     dw       0h,   0,   0,   7,   2, 800, 600,  16
  549.     db    "END                       Must be the END of list   "
  550.     dw       0h,   0,   0,   0,   0,   0,   0,  0
  551.  
  552.     db    680 dup(0)        ; room for 10 more video modes
  553.  
  554. .code
  555.  
  556. initvideotable proc uses ds es di
  557.     mov    di, offset videotable+1    ; get the start of the video table
  558.     mov    ax,0            ; initially, no entries found
  559. initvideotableloop:
  560.     cmp    word ptr cs:66[di],0    ; does the next entry have any colors?
  561.     je    initvideotablereturn    ;  nope.  we done.
  562.     inc    ax            ; indicate we found an entry
  563.     add    di,68            ; locate the next entry
  564.     jmp    initvideotableloop    ;  and try again.
  565. initvideotablereturn:
  566.     ret
  567. initvideotable endp
  568.  
  569. fromvideotable proc uses es si di, tablenumber:word
  570.     push    cs            ; get the video table segment into ES
  571.     pop    es            ;  ...
  572.     mov    cx,68            ; retrieve the table entry length
  573.     mov    ax,tablenumber        ; compute the video table offset
  574.     mul    cl            ;  == that entry # x the entry length
  575.     add    ax,offset videotable+1    ;  + the start of the table
  576.     mov    si,ax            ; store it here
  577.     mov    di,offset videoentry    ; get the offset of the entry ptr
  578.     push    ds            ; swap DS and ES temporarily
  579.     push    es            ;  ...
  580.     pop    ds            ;  ...
  581.     pop    es            ;  ...
  582.     rep    movsb            ; move it
  583.     push    es            ; restore DS again
  584.     pop    ds            ;  ...    
  585.     mov    di,offset videoentry    ; get the offset of the entry ptr
  586.     mov    al,0            ; stuff a few zeroes in where appr.
  587.     mov    25[di],al        ;  ...
  588.     mov    51[di],al        ;  ...
  589.     ret
  590. fromvideotable endp
  591.  
  592. tovideotable proc uses es si di, tablenumber:word
  593.     push    cs            ; get the video table segment into ES
  594.     pop    es            ;  ...
  595.     mov    cx,68            ; retrieve the table entry length
  596.     mov    ax,tablenumber        ; compute the video table offset
  597.     mul    cl            ;  == that entry # x the entry length
  598.     add    ax,offset videotable+1    ;  + the start of the table
  599.     mov    di,ax            ; store it here
  600.     mov    si,offset videoentry    ; get the offset of the entry ptr
  601.     rep    movsb            ; move it
  602.     ret
  603. tovideotable endp
  604.  
  605. ;    Routines called by this code
  606.  
  607. ; **************** Routines called by 'calcmand.asm' *********************
  608. ;
  609. ;    parameters passed directly in registers - just call near routine
  610.  
  611. asmdotwrite    proc    far        ; called by 'calcmand.asm'
  612.         call    dotwrite    ; call the appropriate write-a-dot
  613.         ret            ; we done
  614. asmdotwrite    endp
  615.  
  616. asmvideocleanup    proc    far        ; called by 'calcmand.asm'
  617.         call    videocleanup    ; call the local routine
  618.         ret            ; we done.
  619. asmvideocleanup    endp
  620.  
  621. ; **************** internal Read/Write-a-dot routines ***********************
  622. ;
  623. ;    These Routines all assume the following register values:
  624. ;
  625. ;        AL = The Color (returned on reads, sent on writes)
  626. ;        CX = The X-Location of the Pixel
  627. ;        DX = The Y-Location of the Pixel
  628.  
  629. normalwrite    proc    near        ; generic write-a-dot routine
  630.     mov    ah,12            ; write the dot (al == color)
  631.     mov    bx,0            ; this page
  632.     push    bp            ; some BIOS's don't save this
  633.     int    10h            ; do it.
  634.     pop    bp            ; restore the saved register
  635.     ret                ; we done.
  636. normalwrite    endp
  637.  
  638. normalread    proc    near        ; generic read-a-dot routine
  639.     mov    ah,13            ; read the dot (al == color)
  640.     mov    bx,0            ; this page
  641.     push    bp            ; some BIOS's don't save this
  642.     int    10h            ; do it.
  643.     pop    bp            ; restore the saved register
  644.     ret                ; we done.
  645. normalread    endp
  646.  
  647. cgawrite    proc    near        ; CGA 320x200 4-color, 640x200 2-color
  648.     mov    bx,colors        ; restrict ourselves to the color cnt
  649.     dec    bx            ;  ...
  650.     and    al,bl            ;  ...
  651.     push    es            ; save ES for a bit
  652.     push    ax            ; save AX for a bit
  653.     call    near ptr cgasegoff    ; compute the segment and offset
  654.     mov    dl,es:[bx]        ; retrieve the byte
  655.     and    dl,al            ; clear out the proper bits
  656.     pop    ax            ; restore AX (the color)
  657.     shl    al,cl            ; apply the shift mask
  658.     or    dl,al            ; add in the color
  659.     mov    es:[bx],dl        ; and write the color back out
  660.     pop    es            ; restore ES
  661.     ret                ; we done
  662. cgawrite    endp
  663.  
  664. cgaread    proc    near            ; CGA 320x200 4-color, 640x200 2-color
  665.     push    es            ; save ES for a bit
  666.     call    near ptr cgasegoff    ; compute the segment and offset
  667.     mov    dl,es:[bx]        ; retrieve the byte
  668.     not    al            ; reset AL for the AND
  669.     and    al,dl            ; clear out all but the proper bits
  670.     shr    al,cl            ; apply the shift mask
  671.     mov    ah,0            ; clear out the high byte
  672.     pop    es            ; restore ES
  673.     ret                ; we done
  674. cgaread    endp
  675.  
  676. cgasegoff    proc    near        ; common CGA routine
  677.     mov    ax,0b800h        ; buffer is really here
  678.     shr    dx,1            ; provide the interleaving logic
  679.     jnc    cgasegeven        ;  skip if odd
  680.     add    ax,200h            ; use the other half of the buffer
  681. cgasegeven:
  682.     mov    es,ax            ; set it up
  683.     mov    bx,dx            ; each row is 80 bytes - shift
  684.     shl    bx,1            ;  instead of multiply (8088s multiply
  685.     shl    bx,1            ;  REAL slowly)
  686.     shl    bx,1            ;  ...
  687.     shl    bx,1            ;  ...
  688.     mov    ax,bx            ;  x*80 = (x<<4) + ((x<<4)<<2)
  689.     shl    bx,1            ;  ...
  690.     shl    bx,1            ;  ...
  691.     add    ax,bx            ; (Finally!)
  692.     cmp    colors,2        ; 2-color mode?
  693.     je    short cgaseg2color    ;  yup.  branch off
  694.     mov    bx,cx            ; get the column offset
  695.     shr    bx,1            ; four columns per byte
  696.     shr    bx,1            ;  ...
  697.     add    bx,ax            ; BX now contains the offset
  698.     and    cx,3            ; calculate the bit mask
  699.     xor    cx,3            ;  ...
  700.     shl    cx,1            ; shift left this many bits
  701.     push    cx            ; save the bit shift
  702.     mov    al,0fch            ; set up the bit mask
  703.     rol    al,cl            ; AL now contains the bit mask
  704.     pop    cx            ; restore the shift count
  705.     ret                ; we done.
  706. cgaseg2color:                ; two-color option
  707.     mov    bx,cx            ; get the column offset
  708.     shr    bx,1            ; eight columns per byte
  709.     shr    bx,1            ;  ...
  710.     shr    bx,1            ;  ...
  711.     add    bx,ax            ; BX now contains the offset
  712.     and    cx,7            ; calculate the bit mask
  713.     xor    cx,7            ;  ...
  714.     push    cx            ; save the bit shift
  715.     mov    al,0feh            ; set up the bit mask
  716.     rol    al,cl            ; AL now contains the bit mask
  717.     pop    cx            ; restore the shift count
  718.     ret
  719. cgasegoff    endp
  720.  
  721. mcgawrite    proc    near        ; MCGA 320*200, 246 colors
  722.     push    ax            ; save this for a tad
  723.     mov    ax,xdots        ; this many dots / line
  724.     mul    dx            ; times this many lines
  725.     add    ax,cx            ; plus this many x-dots
  726.     mov    bx,ax            ; save this in BX
  727.     pop    ax            ; restore AX
  728.     mov    es:[bx],al        ; write the dot
  729.     ret                ; we done.
  730. mcgawrite    endp
  731.  
  732. mcgaread    proc    near        ; MCGA 320*200, 246 colors
  733.     mov    ax,xdots        ; this many dots / line
  734.     mul    dx            ; times this many lines
  735.     add    ax,cx            ; plus this many x-dots
  736.     mov    bx,ax            ; save this in BX
  737.     mov    al,es:[bx]        ; retrieve the previous value
  738.     ret                ; we done.
  739. mcgaread    endp
  740.  
  741. ;    These routines are for bit-plane 16 color modes, including bank 
  742. ;    switched superVGA varieties such as the Tseng 1024x768x16 mode.
  743. ;        Tim Wegner
  744. ;
  745. vgawrite    proc    near        ; bank-switched EGA/VGA write mode 0
  746.     mov    bh,al            ; save the color value for a bit
  747.     mov    ax,xdots        ; this many dots / line
  748.     mul    dx            ; times this many lines
  749.     add    ax,cx            ; plus this many x-dots
  750.     adc    dx,0            ; DX:AX now holds the pixel count
  751.     mov    cx,ax            ; save this for the bit mask
  752.     and    cx,7            ; bit-mask shift calculation
  753.     xor    cl,7            ;  ...
  754.     mov    si,ax            ; set up for the address shift
  755.     shr    dx,1            ; (ugly) 32-bit shift-by-3 logic
  756.     rcr    si,1            ;  ((works on ANY 80x6 processor))
  757.     shr    dx,1            ;  ...
  758.     rcr    si,1            ;  ...
  759.     shr    dx,1            ;  ...
  760.     rcr    si,1            ;  ...
  761.  
  762.         cmp    dx,curbk        ; see if bank changed
  763.         je    vgasame_bank        ; jump if old bank ok
  764.         mov    ax,dx            ; newbank expects bank in al
  765.         call    far ptr newbank        ; switch banks
  766. vgasame_bank:
  767.  
  768.     mov    dx,03ceh        ; graphics controller address
  769.     mov    ax,0108h        ; set up controller bit mask register
  770.     shl    ah,cl            ;  ...
  771.     out    dx,ax            ;  ...
  772.     mov    ah,bh            ; set set/reset registers
  773.     mov    al,0            ;  ...
  774.     out    dx,ax            ;  ...
  775.     mov    ax,0f01h        ; enable set/reset registers
  776.     out    dx,ax            ;  ...
  777.     or    es:[si],al        ; update all bit planes
  778.     ret                ; we done.
  779. vgawrite    endp
  780.  
  781. vgaread    proc    near        ; bank-switched EGA/VGA read mode 0
  782.     mov    ax,xdots        ; this many dots / line
  783.     mul    dx            ; times this many lines
  784.     add    ax,cx            ; plus this many x-dots
  785.     adc    dx,0            ; DX:AX now holds the pixel count
  786.     mov    cx,ax            ; save this for the bit mask
  787.     and    cx,7            ; bit-mask shift calculation
  788.     xor    cl,7            ;  ...
  789.     mov    si,ax            ; set up for the address shift
  790.     shr    dx,1            ; (ugly) 32-bit shift-by-3 logic
  791.     rcr    si,1            ;  ((works on ANY 80x6 processor))
  792.     shr    dx,1            ;  ...
  793.     rcr    si,1            ;  ...
  794.     shr    dx,1            ;  ...
  795.     rcr    si,1            ;  ...
  796.  
  797.         cmp    dx,curbk        ; see if bank changed
  798.         je    vgasame_bank        ; jump if old bank ok
  799.         mov    ax,dx            ; newbank expects bank in al
  800.         call    far ptr newbank        ; switch banks
  801. vgasame_bank:
  802.  
  803.     mov    ch,01h            ; bit mask to shift
  804.     shl    ch,cl            ;  ...
  805.     mov    bx,0            ; initialize bits-read value (none)
  806.     mov    dx,03ceh        ; graphics controller address
  807.     mov    ax,0304h        ; set up controller address register
  808. vgareadloop:
  809.     out    dx,ax            ; do it
  810.     mov    bh,es:[si]        ; retrieve the old value
  811.     and    bh,ch            ; mask one bit
  812.     neg    bh            ; set bit 7 correctly
  813.     rol    bx,1            ; rotate the bit into bl
  814.     dec    ah            ; go for another bit?
  815.     jge    vgareadloop        ;  sure, why not.
  816.     mov    al,bl            ; returned pixel value
  817.     ret                ; we done.
  818. vgaread    endp
  819.  
  820.  
  821. ;    The 360x480 mode draws heavily on Michael Abrash's article in
  822. ;    the January/February 1989 "Programmer's Journal" and files uploaded
  823. ;    to Compuserv's PICS forum by Dr. Lawrence Gozum - integrated here
  824. ;    by Timothy Wegner
  825.  
  826. ; Michael Abrash equates. Not all used, but I'll leave for reference.
  827.  
  828. VGA_SEGMENT       EQU   0A000h
  829. SC_INDEX          EQU   3C4h     ;Sequence Controller Index register
  830. GC_INDEX          EQU   3CEh     ;Graphics Controller Index register
  831. CRTC_INDEX        EQU   3D4h     ;CRT Controller Index register
  832. MAP_MASK          EQU   2        ;Map Mask register index in SC
  833. MEMORY_MODE       EQU   4        ;Memory Mode register in SC
  834. MAX_SCAN_LINE     EQU   9        ;Maximum Scan Line reg index in CRTC
  835.                                  ;Use 9 for 2 pages of 320x400
  836. ;MAX_SCAN_LINE    EQU   1        ;Use 1 for 4 pages of 320x200
  837. START_ADD_HIGH    EQU   0Ch      ;Start Address High reg index in CRTC
  838. UNDERLINE         EQU   14h      ;Underline Location reg index in CRTC
  839. MODE_CONTROL      EQU   17h      ;Mode Control reg index in CRTC
  840. READ_MAP          EQU   4        ;Read Mask register index in SC
  841. GRAPHICS_MODE     EQU   5        ;Graphics Mode register index in SC
  842. MISC              EQU   6        ;Miscellaneous register index in SC
  843. WORD_OUTS_OK      EQU   1        ;set to 0 to assemble for computers
  844.                                  ;that can't handle word outs to indexed
  845.                                  ;VGA registers
  846. ;
  847. ;Macro to output a word value to a port
  848. ;
  849. OUT_WORD MACRO
  850. IF WORD_OUTS_OK
  851.          OUT      DX,AX
  852. ELSE
  853.          OUT      DX,AL
  854.          INC      DX
  855.          XCHG     AH,AL
  856.          OUT      DX,AL
  857.          DEC      DX
  858.          XCHG     AH,AL
  859. ENDIF
  860.          ENDM
  861.  
  862. ;Macro to ouput a constant value to an indexed VGA register
  863. CONSTANT_TO_INDEXED_REGISTER     MACRO  ADDRESS,INDEX,VALUE
  864.          MOV      DX,ADDRESS
  865.          MOV      AX,(VALUE SHL 8)+INDEX
  866.          OUT_WORD
  867.          ENDM
  868.  
  869. tweak256read    proc near uses si     ; Tweaked-VGA ...x256 color mode
  870.  
  871.   mov     ax,xdots
  872.   shr     ax,1    
  873.   shr     ax,1                   ; now ax = xdots/4     
  874.   mul     dx                     ;Point to start of desired row
  875.   push    cx                     ;Save X coordinate for later
  876.   shr     cx,1                   ;There are 4 pixels at each address
  877.   shr     cx,1                   ;so divide X by 4
  878.   add     ax,cx                  ;Point to pixels address
  879.   mov     si,ax
  880.   pop     ax                     ;Retrieve X coordinate
  881.   and     al,3                   ;Get the plane number of the pixel
  882.   mov     ah,al
  883.   mov     al,READ_MAP            
  884.   mov     dx,GC_INDEX
  885.   OUT_WORD                       ;Set to write to the proper plane for the
  886.                                  ;pixel
  887.   xor     ax,ax     
  888.   lods      byte ptr es:[si]       ;Read the pixel
  889.   ret 
  890.  
  891. tweak256read    endp
  892.  
  893. tweak256write    proc near uses di    ; Tweaked-VGA ...x256 color mode
  894.   mov     bl,al            ; color
  895.   mov     ax,xdots
  896.   shr     ax, 1    
  897.   shr     ax, 1                  ; now ax = xdots/4     
  898.   mul     dx                      ;Point to start of desired row
  899.   push    cx                    ;Save X coordinate for later
  900.   shr     cx,1                  ;There are 4 pixels at each address
  901.   shr     cx,1                  ;so divide X by 4
  902.   add     ax,cx                 ;Point to pixels address
  903.   mov     di,AX
  904.   pop     cx                    ;Retrieve X coordinate
  905.   and     cl,3                  ;Get the plane number of the pixel
  906.   mov     ah,1
  907.   shl     ah,CL                 ;Set the bit corresponding to the plane
  908.                                 ;the pixel is in
  909.   mov     al,MAP_MASK            
  910.   mov     dx,SC_INDEX
  911.   OUT_WORD                       ;Set to write to the proper plane for the
  912.                                  ;pixel
  913.   mov     es:[di],bl             ;Draw the pixel
  914.  
  915.   ret 
  916. tweak256write    endp
  917.  
  918. ;    The following ATI 1024x768x16 mode is courtesy of Mark Peterson
  919.  
  920. ati1024read    proc near        ; ATI 1024x768x16 read
  921.     call    ati1024addr        ; calculate the address
  922.     mov    al,es:[bx]        ; get the byte the pixel is in
  923.     test    cl,1            ; is X odd?
  924.     jz    atireadhigh        ;  Nope.  Use the high bits
  925.     and    ax,0fh            ; zero out the high-order bits
  926.     ret
  927. atireadhigh:
  928.     and    ax,0f0h            ; zero out the low-order bits
  929.     mov    cl,4            ; shift the results
  930.     shr    al,cl            ;  ...
  931.     ret
  932. ati1024read    endp
  933.  
  934. ati1024write    proc near        ; ATI 1024x768x16 write
  935.     call    ati1024addr        ; calculate the address
  936.     mov    dl,es:[bx]        ; get the byte the pixel is in
  937.     and    al,00fh            ; zero out the high-order color bits
  938.     test    cl,1            ; is X odd?
  939.     jz    atiwritehigh        ;  Nope.  Use the high bits
  940.     and    dl,0f0h            ; zero out the low-order video bits
  941.     or    dl,al            ; add the two together
  942.     mov    es:[bx],dl        ; and write the results
  943.     ret
  944. atiwritehigh:
  945.     mov    cl,4            ; shift the color bits
  946.     shl    al,cl            ;  ...
  947.     and    dl,0fh            ; zero out the high-order video bits
  948.     or    dl,al            ; add the two together
  949.     mov    es:[bx],dl        ; and write the results
  950.     ret
  951. ati1024write    endp
  952.  
  953. ati1024addr    proc    near        ; modification of TIW's Super256addr
  954.         clc                ; clear carry flag
  955.     push    ax            ; save this for a tad
  956.     mov    ax,xdots        ; this many dots / line
  957.     mul    dx            ; times this many lines - ans in dx:ax
  958.     add    ax,cx            ; plus this many x-dots
  959.         adc     dx,0            ; answer in dx:ax
  960.     shr    dx,1            ; shift the answer right one bit
  961.     rcr    ax,1            ;  .. in the 32-bit DX:AX combo
  962.     mov    bx,ax            ; save this in BX
  963.         cmp    dx,curbk        ; see if bank changed
  964.         je    atisame_bank        ; jump if old bank ok
  965.         mov    ax,dx            ; newbank expects bank in al
  966.         call    far ptr newbank
  967. atisame_bank:
  968.     pop    ax            ; restore AX
  969.     ret
  970. ati1024addr    endp
  971.  
  972. ;
  973. ;    The following 'Super256' code is courtesy of Timothy Wegner.
  974. ;
  975.  
  976. super256write    proc near        ; super-VGA ...x256 colors write-a-dot
  977.         call    super256addr        ; calculate address and switch banks
  978.     mov    es:[bx],al        ; write the dot
  979.     ret                ; we done.
  980. super256write    endp
  981.  
  982. super256read    proc near        ; super-VGA ...x256 colors read-a-dot
  983.         call    super256addr        ; calculate address and switch banks
  984.     mov    al,es:[bx]        ; read the dot
  985.     ret                ; we done.
  986. super256read    endp
  987.  
  988. super256addr    proc near        ; can be put in-line but shared by
  989.                     ; read and write routines
  990.         clc                ; clear carry flag
  991.     push    ax            ; save this for a tad
  992.     mov    ax,xdots        ; this many dots / line
  993.     mul    dx            ; times this many lines - ans in dx:ax
  994.     add    ax,cx            ; plus this many x-dots
  995.         adc     dx,0            ; answer in dx:ax - dl=bank, ax=offset
  996.     mov    bx,ax            ; save this in BX
  997.         cmp    dx,curbk        ; see if bank changed
  998.         je    same_bank        ; jump if old bank ok
  999.         mov    ax,dx            ; newbank expects bank in al
  1000.         call    far ptr newbank
  1001. same_bank:
  1002.     pop    ax            ; restore AX
  1003.         ret
  1004. super256addr    endp
  1005.  
  1006. ;
  1007. ;       BANKS.ASM was used verbatim except:
  1008. ;          1) removed ".model small"
  1009. ;          2) deleted "end"
  1010. ;       Integrated by Tim Wegner 8/15/89 
  1011. ;    (switched to John's 9/7/89 version on 9/10/89 - Bert)
  1012. ;        
  1013.  
  1014. ;
  1015. ;    Copyright 1988,89 John Bridges
  1016. ;    Free for use in commercial, shareware or freeware applications
  1017. ;
  1018. ;    BANKS.ASM
  1019. ;
  1020. ;
  1021. .data
  1022.  
  1023.     public    curbk
  1024.  
  1025. curbk    dw    0ffffh        ;current bank number
  1026.  
  1027.  
  1028.     public    tseng,trident,video7,paradise,chipstech,ativga,everex
  1029.  
  1030. tseng    dw    0
  1031. trident    dw    0
  1032. video7    dw    0
  1033. paradise dw    0
  1034. chipstech dw    0
  1035. ativga    dw    0
  1036. everex    dw    0
  1037.  
  1038. .code
  1039.  
  1040. newbank    proc            ;bank number is in AX
  1041.     cli
  1042.     mov    [curbk],ax
  1043.     cmp    [tseng],0
  1044.     jz    nots
  1045.     push    ax        ;Tseng
  1046.     push    dx
  1047.     and    al,7
  1048.     mov    ah,al
  1049.     shl    ah,1
  1050.     shl    ah,1
  1051.     shl    ah,1
  1052.     or    al,ah
  1053.     or    al,01000000b
  1054.     mov    dx,3cdh
  1055.     out    dx,al
  1056.     sti
  1057.     pop    dx
  1058.     pop    ax
  1059.     ret
  1060.  
  1061. nots:    cmp    [trident],0
  1062.     jz    notri
  1063.     push    ax        ;Trident
  1064.     push    dx
  1065.         
  1066.     mov    dx,3ceh        ;set page size to 64k
  1067.     mov    al,6
  1068.     out    dx,al
  1069.     inc    dl
  1070.     in    al,dx
  1071.     dec    dl
  1072.     or    al,4
  1073.     mov    ah,al
  1074.     mov    al,6
  1075.     out    dx,ax
  1076.         
  1077.     mov    dl,0c4h        ;switch to BPS mode
  1078.     mov    al,0bh
  1079.     out    dx,al
  1080.     inc    dl
  1081.     in    al,dx
  1082.     dec    dl
  1083.  
  1084.     mov    ah,byte ptr [curbk]
  1085.     xor    ah,2
  1086.     mov    dx,3c4h
  1087.     mov    al,0eh
  1088.     out    dx,ax
  1089.     sti
  1090.     pop    dx
  1091.     pop    ax
  1092.     ret
  1093.  
  1094. notri:    cmp    [video7],0
  1095.     jz    nov7
  1096.     push    ax        ;Video 7
  1097.     push    dx
  1098.     push    cx
  1099. ; Video-7 1024x768x16 mode patch (thanks to Frank Lozier 11/8/89).
  1100.         cmp     colors,16
  1101.         jne     video7xx
  1102.         shl     ax,1
  1103.         shl     ax,1
  1104. video7xx:
  1105.     and    ax,15
  1106.     mov    ch,al
  1107.     mov    dx,3c4h
  1108.     mov    ax,0ea06h
  1109.     out    dx,ax
  1110.     mov    ah,ch
  1111.     and    ah,1
  1112.     mov    al,0f9h
  1113.     out    dx,ax
  1114.     mov    al,ch
  1115.     and    al,1100b
  1116.     mov    ah,al
  1117.     shr    ah,1
  1118.     shr    ah,1
  1119.     or    ah,al
  1120.     mov    al,0f6h
  1121.     out    dx,al
  1122.     inc    dx
  1123.     in    al,dx
  1124.     dec    dx
  1125.     and    al,not 1111b
  1126.     or    ah,al
  1127.     mov    al,0f6h
  1128.     out    dx,ax
  1129.     mov    ah,ch
  1130.     mov    cl,4
  1131.     shl    ah,cl
  1132.     and    ah,100000b
  1133.     mov    dl,0cch
  1134.     in    al,dx
  1135.     mov    dl,0c2h
  1136.     and    al,not 100000b
  1137.     or    al,ah
  1138.     out    dx,al
  1139.     sti
  1140.     pop    cx
  1141.     pop    dx
  1142.     pop    ax
  1143.     ret
  1144.     
  1145. nov7:    cmp    [paradise],0
  1146.     jz    nopd
  1147.     push    ax        ;Paradise
  1148.     push    dx
  1149.     mov    dx,3ceh
  1150.     mov    ax,50fh        ;turn off write protect on VGA registers
  1151.     out    dx,ax
  1152.     mov    ah,byte ptr [curbk]
  1153.     shl    ah,1        ;change 64k bank number into 4k bank number
  1154.     shl    ah,1
  1155.     shl    ah,1
  1156.     shl    ah,1
  1157.     mov    al,9
  1158.     out    dx,ax
  1159.     sti
  1160.     pop    dx
  1161.     pop    ax
  1162.     ret
  1163.  
  1164. nopd:    cmp    [chipstech],0
  1165.     jz    noct
  1166.     push    ax        ;Chips & Tech
  1167.     push    dx
  1168.  
  1169. ;    mov     dx,46e8h    ;place chip in setup mode
  1170. ;    mov     ax,1eh
  1171. ;    out     dx,ax
  1172. ;    mov     dx,103h        ;enable extended registers
  1173. ;    mov     ax,0080
  1174. ;    out     dx,ax
  1175. ;    mov     dx,46e8h    ;bring chip out of setup mode
  1176. ;    mov     ax,0eh
  1177. ;    out     dx,ax
  1178.  
  1179.     mov    ah,byte ptr [curbk]
  1180.     shl    ah,1        ;change 64k bank number into 16k bank number
  1181.     shl    ah,1
  1182.     mov    al,10h
  1183.     mov    dx,3d6h
  1184.     out    dx,ax
  1185.     sti
  1186.     pop    dx
  1187.     pop    ax
  1188.     ret
  1189.  
  1190. noct:    cmp    [ativga],0
  1191.     jz    noati
  1192.     push    ax        ;ATI VGA Wonder
  1193.     push    dx
  1194.     mov    ah,al
  1195.     mov    dx,1ceh
  1196.     mov    al,0b2h
  1197.     out    dx,al
  1198.     inc    dl
  1199.     in    al,dx
  1200.     shl    ah,1
  1201.     and    al,0e1h
  1202.     or    ah,al
  1203.     mov    al,0b2h
  1204.     dec    dl
  1205.     out    dx,ax
  1206.     sti
  1207.     pop    dx
  1208.     pop    ax
  1209.     ret
  1210.  
  1211. noati:    cmp    [everex],0
  1212.     jz    noev
  1213.     push    ax        ;Everex
  1214.     push    cx
  1215.     push    dx
  1216.     sti
  1217.     mov    cl,al
  1218.     mov    dx,3c4h
  1219.     mov    al,8
  1220.     out    dx,al
  1221.     inc    dl
  1222.     in    al,dx
  1223.     dec    dl
  1224.     shl    al,1
  1225.     shr    cl,1
  1226.     rcr    al,1
  1227.     mov    ah,al
  1228.     mov    al,8
  1229.     out    dx,ax
  1230.     mov    dl,0cch
  1231.     in    al,dx
  1232.     mov    dl,0c2h
  1233.     and    al,0dfh
  1234.     shr    cl,1
  1235.     jc    nob2
  1236.     or    al,20h
  1237. nob2:    out    dx,al
  1238.     pop    dx
  1239.     pop    cx
  1240.     pop    ax
  1241.     ret
  1242.  
  1243. noev:    sti
  1244.     ret
  1245. newbank    endp
  1246.  
  1247. videowrite    proc    near        ; your-own-video write routine
  1248.     push    es            ; save registers around the call
  1249.     push    si            ; save registers around the call
  1250.     push    di            ; save registers around the call
  1251.     mov    ah,0            ; clear the high-order color byte
  1252.     push    ax            ; colors parameter
  1253.     push    dx            ; 'y' parameter
  1254.     push    cx            ; 'x' parameter
  1255.     call    far ptr writevideo    ; let the external routine do it
  1256.     pop    cx            ; restore registers
  1257.     pop    dx            ; restore registers
  1258.     pop    ax            ; restore registers
  1259.     pop    di            ; restore registers
  1260.     pop    si            ; restore registers
  1261.     pop    es            ; restore registers
  1262.     ret                ; we done.
  1263. videowrite    endp
  1264.  
  1265. videoread    proc    near        ; your-own-video read routine
  1266.     push    es            ; save registers around the call
  1267.     push    si            ; save registers around the call
  1268.     push    di            ; save registers around the call
  1269.     push    dx            ; 'y' parameter
  1270.     push    cx            ; 'x' parameter
  1271.     call    far ptr readvideo    ; let the external routine do it
  1272.     pop    cx            ; restore registers
  1273.     pop    dx            ; restore registers
  1274.     pop    di            ; restore registers
  1275.     pop    si            ; restore registers
  1276.     pop    es            ; restore registers
  1277.     ret                ; we done.
  1278. videoread    endp
  1279.  
  1280. videostart    proc    near        ; your-own-video start routine
  1281.     push    es            ; save registers around the call
  1282.     push    si            ; save registers around the call
  1283.     push    di            ; save registers around the call
  1284.     call    far ptr startvideo    ; let the external routine do it
  1285.     pop    di            ; restore registers
  1286.     pop    si            ; restore registers
  1287.     pop    es            ; restore registers
  1288.     ret                ; we done.
  1289. videostart    endp
  1290.  
  1291. videoend    proc    near        ; your-own-video end routine
  1292.     push    es            ; save registers around the call
  1293.     push    si            ; save registers around the call
  1294.     push    di            ; save registers around the call
  1295.     call    far ptr endvideo    ; let the external routine do it
  1296.     pop    di            ; restore registers
  1297.     pop    si            ; restore registers
  1298.     pop    es            ; restore registers
  1299.     ret                ; we done.
  1300. videoend        endp
  1301.  
  1302. diskwrite    proc    near        ; disk-video write routine
  1303.     push    es            ; save registers around the call
  1304.     push    si            ; save registers around the call
  1305.     push    di            ; save registers around the call
  1306.     mov    ah,0            ; clear the high-order color byte
  1307.     push    ax            ; colors parameter
  1308.     push    dx            ; 'y' parameter
  1309.     push    cx            ; 'x' parameter
  1310.     call    far ptr writedisk    ; let the external routine do it
  1311.     pop    cx            ; restore registers
  1312.     pop    dx            ; restore registers
  1313.     pop    ax            ; restore registers
  1314.     pop    di            ; restore registers
  1315.     pop    si            ; restore registers
  1316.     pop    es            ; restore registers
  1317.     ret                ; we done.
  1318. diskwrite    endp
  1319.  
  1320. diskread    proc    near        ; disk-video read routine
  1321.     push    es            ; save registers around the call
  1322.     push    si            ; save registers around the call
  1323.     push    di            ; save registers around the call
  1324.     push    dx            ; 'y' parameter
  1325.     push    cx            ; 'x' parameter
  1326.     call    far ptr readdisk    ; let the external routine do it
  1327.     pop    cx            ; restore registers
  1328.     pop    dx            ; restore registers
  1329.     pop    di            ; restore registers
  1330.     pop    si            ; restore registers
  1331.     pop    es            ; restore registers
  1332.     ret                ; we done.
  1333. diskread    endp
  1334.  
  1335. diskstart    proc    near        ; disk-video start routine
  1336.     push    es            ; save registers around the call
  1337.     push    si            ; save registers around the call
  1338.     push    di            ; save registers around the call
  1339.     call    far ptr startdisk    ; let the external routine do it
  1340.     pop    di            ; restore registers
  1341.     pop    si            ; restore registers
  1342.     pop    es            ; restore registers
  1343.     ret                ; we done.
  1344. diskstart    endp
  1345.  
  1346. diskend        proc    near        ; disk-video end routine
  1347.     push    es            ; save registers around the call
  1348.     push    si            ; save registers around the call
  1349.     push    di            ; save registers around the call
  1350.     call    far ptr enddisk        ; let the external routine do it
  1351.     pop    di            ; restore registers
  1352.     pop    si            ; restore registers
  1353.     pop    es            ; restore registers
  1354.     ret                ; we done.
  1355. diskend        endp
  1356.  
  1357. ; ***********************************************************************
  1358. ;
  1359. ; TARGA MODIFIED 1 JUNE 89 - j mclain
  1360. ;
  1361. tgawrite     proc    near        ;
  1362.         push    es            ;
  1363.         push    si            ;
  1364.         push    di            ;
  1365.     push    ax            ; colors parameter
  1366.     push    dx            ; 'y' parameter
  1367.     push    cx            ; 'x' parameter
  1368.     call    far ptr WriteTGA    ; writeTGA( x, y, color )
  1369.     pop    cx            ;
  1370.     pop    dx            ;
  1371.     pop    ax            ;
  1372.         pop    di            ;
  1373.     pop    si            ;
  1374.     pop    es            ;
  1375.     ret                ;
  1376. tgawrite    endp
  1377.  
  1378. tgaline     proc    near        ; 
  1379.         push    es            ;
  1380.       push    si            ;
  1381.     push    di            ;
  1382.     mov    ax,xdots        ; pixels on line
  1383.     push    ax            ; 
  1384.     mov    ax,rowcount        ; line to do it too
  1385.     push    ax            ; 
  1386.     push    ds            ; far ptr
  1387.     push    si            ; line data
  1388.     call    far ptr LineTGA        ; lineTGA( ldata, line, cnt )
  1389.     add    sp,8            ; stack bias
  1390.     pop    di            ;
  1391.     pop    si            ;
  1392.     pop    es            ;
  1393.     ret
  1394. tgaline    endp
  1395.  
  1396. tgaread        proc    near        ;
  1397.     push    es            ;
  1398.     push    si            ;
  1399.     push    di            ;
  1400.     push    dx            ; 'y' parameter
  1401.     push    cx            ; 'x' parameter
  1402.     call    far ptr ReadTGA        ; readTGA( x, y )
  1403.     pop    cx            ;
  1404.     pop    dx            ;
  1405.     pop    di            ;
  1406.     pop    si            ;
  1407.     pop    es            ;
  1408.     ret                ;
  1409. tgaread    endp
  1410.  
  1411. tgastart    proc    near        ;
  1412.     push    es            ;
  1413.     push    si            ;
  1414.     push    di            ;
  1415.     mov    ax,ydots
  1416.     push    ax
  1417.     mov    ax,xdots
  1418.     push    ax
  1419.     call    far ptr StartTGA    ; startTGA( xdim, ydim )
  1420.     add    sp,4            ; stack bias, pointer to dacbox
  1421.     pop    di            ;
  1422.     pop    si            ;
  1423.     pop    es            ;
  1424.     ret                ;
  1425. tgastart    endp
  1426.  
  1427. tgaend        proc    near        ;
  1428.     push    es            ;
  1429.     push    si            ;
  1430.     push    di            ;
  1431.     call    far ptr EndTGA        ; endTGA( void )
  1432.     pop    di            ;
  1433.     pop    si            ;
  1434.     pop    es            ;
  1435.     mov    tgaflag,0        ; 
  1436.     ret                ;
  1437. tgaend        endp
  1438.  
  1439. f85start    proc    near
  1440.  
  1441.     call   far ptr open8514
  1442.     ret
  1443.  
  1444. f85start    endp
  1445.  
  1446.  
  1447. f85end    proc    near
  1448.  
  1449.     call   far ptr close8514
  1450.     ret
  1451.  
  1452. f85end    endp
  1453.  
  1454.  
  1455. f85write    proc    near
  1456.  
  1457.     call   far ptr fr85wdot
  1458.     ret
  1459.  
  1460. f85write    endp
  1461.  
  1462. f85read proc    near
  1463.  
  1464.     call   far ptr fr85rdot
  1465.     ret
  1466.  
  1467. f85read endp
  1468.  
  1469. hgcwrite proc near
  1470.     push    es            ; save registers around the call
  1471.     push    si            ; save registers around the call
  1472.     push    di            ; save registers around the call
  1473.     mov    ah,0            ; clear the high-order color byte
  1474.     push    ax            ; colors parameter
  1475.     push    dx            ; 'y' parameter
  1476.     push    cx            ; 'x' parameter
  1477.     call    far ptr writehgc    ; let the Herc. Write dot routine do it
  1478.     pop    cx            ; restore registers
  1479.     pop    dx            ; restore registers
  1480.     pop    ax            ; restore registers
  1481.     pop    di            ; restore registers
  1482.     pop    si            ; restore registers
  1483.     pop    es            ; restore registers
  1484.     ret
  1485. hgcwrite endp
  1486.  
  1487. hgcread proc near
  1488.     push    es            ; save registers around the call
  1489.     push    si            ; save registers around the call
  1490.     push    di            ; save registers around the call
  1491.     push    dx            ; 'y' parameter
  1492.     push    cx            ; 'x' parameter
  1493.     call    far ptr readhgc        ; call the Hercules Read dot routine
  1494.     pop    cx            ; restore registers
  1495.     pop    dx            ; restore registers
  1496.     pop    di            ; restore registers
  1497.     pop    si            ; restore registers
  1498.     pop    es            ; restore registers
  1499.     ret
  1500. hgcread endp
  1501.  
  1502. hgcstart    proc    near        ; hercules start routine
  1503.     push    es            ; save registers around the call
  1504.     push    si            ; save registers around the call
  1505.     push    di            ; save registers around the call
  1506.     call    far ptr inithgc        ; let the external routine do it
  1507.     pop    di            ; restore registers
  1508.     pop    si            ; restore registers
  1509.     pop    es            ; restore registers
  1510.     ret                ; we done.
  1511. hgcstart    endp
  1512.  
  1513. hgcend        proc    near        ; hercules end routine
  1514.     push    es            ; save registers around the call
  1515.     push    si            ; save registers around the call
  1516.     push    di            ; save registers around the call
  1517.     call    far ptr termhgc        ; let the external routine do it
  1518.     pop    di            ; restore registers
  1519.     pop    si            ; restore registers
  1520.     pop    es            ; restore registers
  1521.     ret                ; we done.
  1522. hgcend        endp
  1523.  
  1524.  
  1525. ; **************** internal Write-a-line routines ***********************
  1526. ;
  1527. ;    These Routines all assume the following register values:
  1528. ;
  1529. ;        SI = Offset of array of colors for a row
  1530.  
  1531. normaline    proc    near        ; Normal Line:  no assumptions
  1532.     xor    cx,cx            ; zero the counter    
  1533. normal_line1:
  1534.     mov    dx,rowcount        ; set the y-pixel
  1535.         mov     bx,si            ; locate the actual pixel color
  1536.     add    bx,cx            ;  ...
  1537.     mov    al,[bx]            ; retrieve the color
  1538.     push    cx            ; save the counter around the call
  1539.     push    si            ; save the pointer around the call also
  1540.     call    dotwrite        ; write the dot via the approved method
  1541.     pop    si                 ; restore the pointer
  1542.     pop    cx                 ; restore the counter
  1543.     inc    cx            ; bump it up
  1544.     cmp    cx,xdots        ; more to go?
  1545.     jl    normal_line1        ; yup.  do it.
  1546.         ret
  1547. normaline    endp
  1548.  
  1549. mcgaline    proc    near        ; MCGA 320*200, 246 colors
  1550.     mov    ax,xdots        ; this many dots / line
  1551.     mul    rowcount        ; times this many lines
  1552.         mov    di,ax            ; di = offset of row in video memory
  1553.         mov    cx,xdots        ; move this many bytes
  1554.     shr    cx,1            ; convert bytes to words
  1555.     rep    movsw            ; zap line into memory
  1556.         ret
  1557. mcgaline    endp
  1558.  
  1559. vgaline    proc    near        ; Bank Switch EGA/VGA line write
  1560.     mov    ax,xdots        ; compute # of dots / pass
  1561.     shr    ax,1            ;  (given 8 passes)
  1562.     shr    ax,1            ;  ...
  1563.     shr    ax,1            ;  ...
  1564.     mov    cx,ax            ; save the dots / pass here
  1565.         xor     dx,dx
  1566.     mul    rowcount        ; now calc first video addr
  1567.  
  1568.         cmp    dx,curbk        ; see if bank changed
  1569.         jne    bank_is_changing    ; if bank change call normaline
  1570. ;same_bank:
  1571.  
  1572.     mov    di,ax            ; save the starting addr here
  1573.     mov    dx,03ceh        ; set up graphics cntrlr addr
  1574.     mov    ax,8008h        ; set up for the bit mask
  1575. vgaline1:
  1576.     out    dx,ax            ; set the graphics bit mask
  1577.     push    ax            ; save registers for a tad
  1578.     push    cx            ;  ...
  1579.     push    si            ;  ...
  1580.     push    di            ;  ...
  1581. vgaline2:
  1582.     mov    ah,ds:[si]        ; get the color
  1583.     mov    al,0            ; set set/reset registers
  1584.     out    dx,ax            ;  do it.
  1585.     mov    ax,0f01h        ; enable set/reset registers
  1586.     out    dx,ax            ;  do it.
  1587.     or    es:[di],al        ; update all bit planes
  1588.     inc    di            ; set up the next video addr
  1589.     add    si,8            ;  and the next source addr
  1590.     loop    vgaline2        ; loop if more dots this pass
  1591.     pop    di            ; restore the saved registers
  1592.     pop    si            ;  ...
  1593.     pop    cx            ;  ...
  1594.     pop    ax            ;  ...
  1595.     inc    si            ; offset the source 1 byte
  1596.     ror    ah,1            ; alter bit mask value
  1597.     cmp    ah,80h            ; already done all 8 of them?
  1598.     jne    vgaline1        ;  nope.  do another one.
  1599.     call    videocleanup        ; else cleanup time.
  1600.     ret                ;  and we done.
  1601. bank_is_changing:
  1602.         call    normaline        ; just calling newbank didn't quite
  1603.         ret                ;  work. This depends on no bank
  1604. vgaline    endp                ;  change mid line (ok for 1024 wide)
  1605.  
  1606. super256line    proc    near     ; super VGA 256 colors
  1607.         mov     ax,xdots         ; this many dots / line
  1608.         mov     cx,rowcount      ; cx = row
  1609.         mul     cx               ; times this many lines
  1610.         push    ax               ; save pixel address for later
  1611.         cmp     dx,curbk         ; bank ok?
  1612.         push    dx               ; save bank
  1613.         je      bank_is_ok       ; jump if bank ok
  1614.         mov     al,dl            ; newbank needs bank in al
  1615.         call    far ptr newbank
  1616. bank_is_ok:
  1617.         inc     cx               ; next row
  1618.         mov     ax,xdots         ; this many dots / line
  1619.         mul     cx               ; times this many lines
  1620.     sub    ax,1         ; back up some to the last pixel of the 
  1621.     sbb    dx,0         ; previous line
  1622.         pop     cx               ; bank at start of row
  1623.         cmp     dl,cl            ; did bank change?
  1624.         pop     di               ; di = offset of row in video memory
  1625.         jne     bank_did_chg
  1626.         mov     cx,xdots         ; move this many bytes
  1627.     shr    cx,1         ; convert bytes to words
  1628.         rep     movsw            ; zap line into memory
  1629.         jmp     short linedone
  1630. bank_did_chg:
  1631.         call    normaline        ; normaline can handle bank change
  1632. linedone:
  1633.         ret
  1634. super256line    endp
  1635.  
  1636. tweak256line    proc    near        ; Normal Line:  no assumptions
  1637.     mov     cx,xdots
  1638.     shr     cx, 1    
  1639.     shr     cx, 1                   ; now ax = xdots/4     
  1640.     mov    ax,cx            ; calculate the first video address
  1641.     mul    rowcount        ;  (pixel 0 on this line)
  1642.     mov    di,ax            ; save the first address here
  1643.         mov     al,MAP_MASK        ; set up for the bit plane adjustment
  1644.     mov    ah,1            ;  (first plane first)
  1645.         mov     dx,SC_INDEX        ;  ...
  1646. tweak256line1:
  1647.     OUT_WORD            ; set up the bit plane
  1648.     push    ax            ; save a few registers around the loop
  1649.     push    cx            ;  ...
  1650.     push    si            ;  ...
  1651.     push    di            ;  ...
  1652. tweak256line2:
  1653.     movsb                ; move the next pixel
  1654.     add    si,3            ; adjust the source addr (+4, not +1)
  1655.     loop    tweak256line2        ; loop if more dots this pass
  1656.     pop    di            ; restore the saved registers
  1657.     pop    si            ;  ...
  1658.     pop    cx            ;  ...
  1659.     pop    ax            ;  ...
  1660.     inc    si            ; offset the source 1 byte
  1661.     shl    ah,1            ; set up for the next video plane
  1662.     cmp    ah,16            ; there IS a next plane, isn't there?
  1663.     jne    tweak256line1        ;  yup.  perform another loop.
  1664.         ret
  1665. tweak256line    endp
  1666.  
  1667. f85line proc    near
  1668.  
  1669.     mov ax, 0           ;a line is a box one line high
  1670.     mov bx, rowcount
  1671.     mov cx, xdots
  1672.     mov dx, 1
  1673.     
  1674.     call    fr85wbox        ;put out the box
  1675.     ret
  1676.  
  1677. f85line endp
  1678.  
  1679.  
  1680. ; ******************** Function videocleanup() **************************
  1681.  
  1682. ;    Called at the end of any assembler video read/writes to make
  1683. ;    the world safe for 'printf()'s.
  1684. ;    Currently, only ega/vga needs cleanup work, but who knows?
  1685. ;
  1686.  
  1687. videocleanup    proc    near
  1688.     mov    ax,dotwrite        ; check: were we in EGA/VGA mode?
  1689.     cmp    ax,offset vgawrite    ;  ...
  1690.     jne    short videocleanupdone    ; nope.  no adjustments
  1691.     mov    dx,03ceh        ; graphics controller address
  1692.     mov    ax,0ff08h        ; restore the default bit mask
  1693.     out    dx,ax            ; ...
  1694.     mov    ax,0003h        ; restore the function select
  1695.     out    dx,ax            ;  ...
  1696.     mov    ax,0001h        ; restore the enable set/reset
  1697.     out    dx,ax            ;  ...
  1698. videocleanupdone:
  1699.     ret
  1700. videocleanup    endp
  1701.  
  1702.  
  1703. ; ******************** Function drawbox(newbox) **************************
  1704.  
  1705. ;    if newbox == 0, just erase old box.  Else erase old and draw new.
  1706.  
  1707. drawbox    proc    uses di si es, newbox:word
  1708.  
  1709.     mov    step,1            ; default step:  every pixel
  1710.     mov    ax,ixmax        ; just how big is this zoom-box?
  1711.     sub    ax,ixmin        ;  this many dots,...
  1712.     shl    ax,1            ; an eighth of the screen or less?
  1713.     shl    ax,1            ;  ...
  1714.     shl    ax,1            ;  ...
  1715.     cmp    ax,xdots        ;  ...
  1716.     jb    short solidbox        ;  yup.  keep the box solid.
  1717.     mov    step,2            ; nope.  make the box every other pixel
  1718. solidbox:
  1719.     shr    ax,1            ; a quarter of the screen or less?
  1720.     cmp    ax,xdots        ;  ...
  1721.     jb    short solidbox2        ;  yup.  keep the box (semi) solid.
  1722.     mov    step,4            ; nope.  make the box every 4th pixel
  1723. solidbox2:
  1724.  
  1725.     mov    ax,colors        ; define the zoom-box color
  1726.     dec    al            ;  ...
  1727.     cmp    al,15            ; do we have 16 colors?
  1728.     jbe    short whitebox        ;  nope.  use what we can get.
  1729.     mov    al,15            ; force a white zoom box
  1730. whitebox:
  1731. ; TARGA 3 June 89 j mclain
  1732.                     ;
  1733.     mov    xorTARGA,1        ; faster to flag xorTARGA rather
  1734.                     ; than check if TARGA is runnin
  1735. notTGAbox:
  1736.     mov    boxcolor,al        ; save the box color
  1737.  
  1738.     push    es            ; save the original ES value
  1739.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  1740.     mov    es,ax            ; save it here during this routine
  1741.  
  1742.     mov    bx,boxcount        ; load up a counter: # points to clear
  1743.     dec    bx            ; switch to an offset value
  1744.     js    short calcnewbox    ;  oops. no old box to clear.
  1745. eraseoldbox:
  1746.     shl    bx,1            ; switch to a word pointer
  1747.     mov    cx,boxx[bx]        ; get the (previous) point location
  1748.     mov    dx,boxy[bx]        ;  ...
  1749.     shr    bx,1            ; switch back to character pointer
  1750.     mov    al,boxvalues[bx]    ; get the (previous) color
  1751.     push    bx            ; save the counter
  1752.     call    dotwrite        ; adjust the dot.
  1753.     pop    bx            ; restore the counter
  1754.     dec    bx            ; are we done yet?
  1755.     jns    eraseoldbox        ;  nope.  try again.
  1756. calcnewbox:
  1757.     mov    boxcount,0        ; set counter flag: no dots yet
  1758.     cmp    newbox,0        ; should we draw a new box?
  1759.     jne    short calcnewbox2    ; yup.
  1760.     jmp    endofdrawbox        ; nope.  bail out now.
  1761. calcnewbox2:
  1762.     mov    bx,boxcount        ; get set to draw lines
  1763.     shl    bx,1            ; switch to word pointers
  1764. starttop:
  1765.     mov    cx,ixmin        ; now, draw the top line.
  1766.     mov    dx,iymin        ;  ...
  1767. topline:
  1768.     mov    boxx[bx],cx        ; save this point.
  1769.     mov    boxy[bx],dx        ;  ...
  1770.     add    bx,2            ; bump up the pointer offsets
  1771.     inc    boxcount        ; and counters
  1772.     add    cx,step            ; calculate the next dot address
  1773.     cmp    cx,ixmax        ; gone past the end-of-line?
  1774.     jbe    short topline        ;  nope.  try again.
  1775. startbottom:
  1776.     mov    cx,ixmin        ; now, draw the bottom line.
  1777.     mov    dx,iymax        ; ...
  1778. bottomline:
  1779.     mov    boxx[bx],cx        ; save this point.
  1780.     mov    boxy[bx],dx        ;  ...
  1781.     add    bx,2            ; bump up the pointer offsets
  1782.     inc    boxcount        ; and counters
  1783.     add    cx,step            ; calculate the next dot address
  1784.     cmp    cx,ixmax        ; gone past the end-of-line?
  1785.     jbe    short bottomline    ;  nope.  try again.
  1786. startleft:
  1787.     mov    cx,ixmin        ; now, draw the left line.
  1788.     mov    dx,iymin        ; ...
  1789. leftline:
  1790.     mov    boxx[bx],cx        ; save this point.
  1791.     mov    boxy[bx],dx        ;  ...
  1792.     add    bx,2            ; bump up the pointer offsets
  1793.     inc    boxcount        ; and counters
  1794.     add    dx,step            ; calculate the next dot address
  1795.     cmp    dx,iymax        ; gone past the end-of-line?
  1796.     jbe    short leftline        ;  nope.  try again.
  1797. startright:
  1798.     mov    cx,ixmax        ; now, draw the right line.
  1799.     mov    dx,iymin        ;  ...
  1800. rightline:
  1801.     mov    boxx[bx],cx        ; save this point.
  1802.     mov    boxy[bx],dx        ;  ...
  1803.     add    bx,2            ; bump up the pointer offsets
  1804.     inc    boxcount        ; and counters
  1805.     add    dx,step            ; calculate the next dot address
  1806.     cmp    dx,iymax        ; gone past the end-of-line?
  1807.     jbe    short rightline        ;  nope.  try again.
  1808. endlines:
  1809.     mov    bx,boxcount        ; load up a counter: # points to draw
  1810.     dec    bx            ; switch to an offset
  1811. readnewbox:
  1812.     shl    bx,1            ; switch to word counter
  1813.     mov    cx,boxx[bx]        ; get the (new) point location
  1814.     mov    dx,boxy[bx]        ;  ...
  1815.     shr    bx,1            ; switch back to character counter
  1816.     push    bx            ; save the counter
  1817.     call    dotread            ; read the (previous) dot value
  1818.     pop    bx            ; restore the counter
  1819.     mov    boxvalues[bx],al    ; get the (previous) color
  1820.     dec    bx            ; are we done yet?
  1821.     jns    readnewbox        ;  nope.  try again.
  1822.     mov    bx,boxcount        ; load up a counter: # points to draw
  1823.     dec    bx            ; switch to an offset
  1824. drawnewbox:
  1825.     shl    bx,1            ; switch to word counter
  1826.     mov    cx,boxx[bx]        ; get the (new) point location
  1827.     mov    dx,boxy[bx]        ;  ...
  1828.     shr    bx,1            ; switch back to character counter
  1829.     mov    al,boxcolor        ; set the (new) box color
  1830.     cmp    colors,2        ; uhh, is this a B&W screen?
  1831.     jne    drawnewnotbw        ;  nope.  proceed
  1832.     mov    al,1            ; XOR the old color
  1833.     sub    al,boxvalues[bx]    ;  for visibility
  1834. drawnewnotbw:
  1835.     push    bx            ; save the counter
  1836.     call    dotwrite        ; adjust the dot.
  1837.     pop    bx            ; restore the counter
  1838.     dec    bx            ; are we done yet?
  1839.     jns    drawnewbox        ;  nope.  try again.
  1840.  
  1841. ; TARGA 3 June 89 j mclain
  1842.                     ;
  1843.     mov    xorTARGA,0        ; in case of TARGA, no more xor
  1844.                     ;             
  1845. endofdrawbox:
  1846.     call    videocleanup        ; perform any video cleanup required
  1847.     pop    es            ; restore ES register
  1848.     ret                ; we done.
  1849.  
  1850. drawbox    endp
  1851.  
  1852. ; **************** Function setvideomode(ax, bx, cx, dx) ****************
  1853.  
  1854. ;    This function sets the (alphanumeric or graphic) video mode
  1855. ;    of the monitor.   Called with the proper values of AX thru DX.
  1856. ;    No returned values, as there is no particular standard to
  1857. ;    adhere to in this case.
  1858.  
  1859. ;    (SPECIAL "TWEAKED" VGA VALUES:  if AX==BX==CX==0, assume we have a 
  1860. ;    genuine VGA or register compatable adapter and program the registers
  1861. ;    directly using the coded value in DX)
  1862.  
  1863. setvideomode    proc    uses di si es,argax:word,argbx:word,argcx:word,argdx:word
  1864.  
  1865.     cmp    videoflag,1        ; say, was the last video your-own?
  1866.     jne    novideovideo        ;  nope.
  1867.     call    videoend        ; yup.  end the your-own-video mode
  1868.     mov    videoflag,0        ; set flag: no your-own-video
  1869.     jmp    short notarga
  1870. novideovideo:
  1871.     cmp    diskflag,1        ; say, was the last video disk-video?
  1872.     jne    nodiskvideo        ;  nope.
  1873.     call    diskend            ; yup.  end the disk-video mode
  1874.     mov    diskflag,0        ; set flag: no disk-video
  1875.     jmp    short notarga
  1876. nodiskvideo:
  1877.     cmp    tgaflag,1        ; TARGA MODIFIED 2 June 89 j mclain
  1878.     jne    notarga
  1879.     call    tgaend
  1880.     mov    tgaflag,0        ; set flag: targa cleaned up
  1881. notarga:
  1882.     cmp    f85flag, 1        ; was the last video 8514?
  1883.     jne    no8514            ; nope.
  1884.     call    f85end
  1885.     mov    f85flag, 0
  1886. no8514:
  1887.     cmp    HGCflag, 1        ; was last video Hercules
  1888.     jne    noHGC            ; nope
  1889.     call    hgcend
  1890.     mov    HGCflag, 0
  1891. noHGC:
  1892.     mov    ax,argax        ; load up for the interrupt call
  1893.     mov    bx,argbx        ;  ...
  1894.     mov    cx,argcx        ;  ...
  1895.     mov    dx,argdx        ;  ...
  1896.  
  1897.     mov    videoax,ax        ; save the values for future use
  1898.     mov    videobx,bx        ;  ...
  1899.     mov    videocx,cx        ;  ...
  1900.     mov    videodx,dx        ;  ...
  1901.  
  1902.     call    setvideo        ; call the internal routine first
  1903.                     ; prepare special video-mode speedups
  1904.     mov    bx,0            ; clear out all of the 256-mode flags
  1905.     mov    tseng,bx        ;  ...
  1906.     mov    trident,bx        ;  ...
  1907.     mov    video7,bx        ;  ...
  1908.     mov    paradise,bx        ;  ...
  1909.     mov    chipstech,bx        ;  ...
  1910.     mov    ativga,bx        ;  ...
  1911.     mov    everex,bx        ;  ...
  1912.     mov    oktoprint,1        ; say it's OK to use printf()
  1913.     mov    bx,dotmode        ; set up for a video table jump
  1914.     cmp    bx,30            ; are we within the range of dotmodes?
  1915.     jbe    videomodesetup        ; yup.  all is OK
  1916.     mov    bx,0            ; nope.  use dullnormalmode
  1917. videomodesetup:
  1918.     shl    bx,1            ; switch to a word offset
  1919.     mov    bx,cs:videomodetable[bx]    ; get the next step
  1920.     jmp    bx            ; and go there
  1921. videomodetable     dw    offset dullnormalmode    ; mode 0
  1922.     dw    offset dullnormalmode    ; mode 1
  1923.     dw    offset vgamode        ; mode 2
  1924.     dw    offset mcgamode        ; mode 3
  1925.     dw    offset tseng256mode    ; mode 4
  1926.     dw    offset paradise256mode    ; mode 5
  1927.     dw    offset video7256mode    ; mode 6
  1928.     dw    offset tweak256mode    ; mode 7
  1929.     dw    offset everex16mode    ; mode 8
  1930.     dw    offset targaMode    ; mode 9 
  1931.     dw    offset hgcmode        ; mode 10
  1932.     dw    offset diskmode        ; mode 11
  1933.     dw    offset f8514mode    ; mode 12
  1934.     dw    offset cgacolor        ; mode 13
  1935.     dw    offset dullnormalmode    ; mode 14
  1936.     dw    offset trident256mode    ; mode 15
  1937.     dw    offset chipstech256mode    ; mode 16
  1938.     dw    offset ati256mode    ; mode 17
  1939.     dw    offset everex256mode    ; mode 18
  1940.     dw    offset yourownmode    ; mode 19
  1941.     dw    offset ati1024mode    ; mode 20
  1942.     dw    offset tseng16mode    ; mode 21
  1943.     dw    offset trident16mode    ; mode 22
  1944.     dw    offset video716mode    ; mode 23
  1945.     dw    offset paradise16mode    ; mode 24
  1946.     dw    offset chipstech16mode    ; mode 25
  1947.     dw    offset dullnormalmode    ; mode 26
  1948.     dw    offset dullnormalmode    ; mode 27
  1949.     dw    offset dullnormalmode    ; mode 28
  1950.     dw    offset dullnormalmode    ; mode 29
  1951.     dw    offset dullnormalmode    ; mode 30
  1952.  
  1953. dullnormalmode:
  1954.     mov    ax,offset normalwrite    ; set up the BIOS write-a-dot routine
  1955.     mov    bx,offset normalread    ; set up the BIOS read-a-dot  routine
  1956.     mov    cx,offset normaline     ; set up the normal linewrite routine
  1957.     jmp    videomode        ; return to common code
  1958. mcgamode:
  1959.     mov    ax,offset mcgawrite    ; set up MCGA write-a-dot routine
  1960.     mov    bx,offset mcgaread    ; set up MCGA read-a-dot  routine
  1961.     mov    cx,offset mcgaline     ; set up the MCGA linewrite routine
  1962.     jmp    videomode        ; return to common code
  1963. tseng16mode:
  1964.         mov     tseng,1            ; set chipset flag
  1965.         jmp    vgamode        ; set ega/vga functions
  1966. trident16mode:
  1967.         mov     trident,1        ; set chipset flag
  1968.         jmp    vgamode
  1969. video716mode:
  1970.         mov     video7,1        ; set chipset flag
  1971.         jmp    vgamode
  1972. paradise16mode:
  1973.         mov     paradise,1        ; set chipset flag
  1974.         jmp    vgamode
  1975. chipstech16mode:
  1976.         mov     chipstech,1        ; set chipset flag
  1977.         jmp    vgamode
  1978. everex16mode:
  1979.         mov     everex,1        ; set chipset flag
  1980.         jmp    vgamode
  1981. egamode:
  1982. vgamode:
  1983.     mov    ax,offset vgawrite    ; set up EGA/VGA write-a-dot routine.
  1984.     mov    bx,offset vgaread    ; set up EGA/VGA read-a-dot  routine
  1985.     mov    cx,offset vgaline     ; set up the EGA/VGA linewrite routine
  1986.     jmp    videomode        ; return to common code
  1987. tseng256mode:
  1988.     mov    tseng,1            ; set chipset flag
  1989.      jmp    super256mode        ; set super VGA linear memory functions 
  1990. paradise256mode:
  1991.     mov    paradise,1        ; set chipset flag
  1992.      jmp    super256mode        ; set super VGA linear memory functions 
  1993. video7256mode:
  1994.     mov    video7,    1        ; set chipset flag
  1995.      jmp    super256mode        ; set super VGA linear memory functions 
  1996. trident256mode:
  1997.     mov    trident,1        ; set chipset flag
  1998.      jmp    super256mode        ; set super VGA linear memory functions 
  1999. chipstech256mode:
  2000.     mov    chipstech,1        ; set chipset flag
  2001.      jmp    super256mode        ; set super VGA linear memory functions 
  2002. ati256mode:
  2003.     mov    ativga,1        ; set chipset flag
  2004.      jmp    super256mode        ; set super VGA linear memory functions 
  2005. everex256mode:
  2006.     mov    everex,1        ; set chipset flag
  2007.      jmp    super256mode        ; set super VGA linear memory functions 
  2008. super256mode:
  2009.     mov    ax,offset super256write    ; set up superVGA write-a-dot routine
  2010.     mov    bx,offset super256read    ; set up superVGA read-a-dot  routine
  2011.     mov    cx,offset super256line     ; set up the  linewrite routine
  2012.     jmp    videomode        ; return to common code
  2013. tweak256mode:
  2014.     mov    oktoprint,0        ; NOT OK to printf() in this mode
  2015.     mov    ax,offset tweak256write    ; set up tweaked-256 write-a-dot
  2016.     mov    bx,offset tweak256read    ; set up tweaked-256 read-a-dot
  2017.     mov    cx,offset tweak256line     ; set up the normal linewrite routine
  2018.     jmp    videomode        ; return to common code
  2019. cgacolor:
  2020.     mov    ax,offset cgawrite    ; set up CGA write-a-dot
  2021.     mov    bx,offset cgaread    ; set up CGA read-a-dot
  2022.     mov    cx,offset normaline     ; set up the normal linewrite routine
  2023.     jmp    videomode        ; return to common code
  2024. ati1024mode:
  2025.     mov    ativga,1        ; set ATI flag.
  2026.     mov    ax,offset ati1024write    ; set up ATI1024 write-a-dot
  2027.     mov    bx,offset ati1024read    ; set up ATI1024 read-a-dot
  2028.     mov    cx,offset normaline     ; set up the normal linewrite routine
  2029.     jmp    videomode        ; return to common code
  2030. diskmode:
  2031.     call    diskstart        ; start up the disk routines
  2032.     mov    ax,offset diskwrite    ; set up disk-vid write-a-dot routine
  2033.     mov    bx,offset diskread    ; set up disk-vid read-a-dot routine
  2034.     mov    cx,offset normaline     ; set up the normal linewrite routine
  2035.     mov    diskflag,1        ; flag "disk-end" needed.
  2036.     jmp    videomode        ; return to common code
  2037. yourownmode:
  2038.     call    videostart        ; start up your-own-video routines
  2039.     mov    ax,offset videowrite    ; set up ur-own-vid write-a-dot routine
  2040.     mov    bx,offset videoread    ; set up ur-own-vid read-a-dot routine
  2041.     mov    cx,offset normaline     ; set up the normal linewrite routine
  2042.     mov    videoflag,1        ; flag "your-own-end" needed.
  2043.     jmp    videomode        ; return to common code
  2044. targaMode:                ; TARGA MODIFIED 2 June 89 - j mclain
  2045.     call    tgastart        ; 
  2046.     mov    ax,offset tgawrite    ; 
  2047.     mov    bx,offset tgaread    ; 
  2048. ;    mov    cx,offset tgaline     ; 
  2049.     mov    cx,offset normaline     ; set up the normal linewrite routine
  2050.     mov    tgaflag,1        ; 
  2051.     jmp    videomode        ; return to common code
  2052. f8514mode:                     ; 8514 modes
  2053.        cmp     videodx, 1      ; requiring dx=1 for turn on allows
  2054.        jne     not8514on       ; setvideomode(3,0,0,0) to display text
  2055.        call    open8514        ; start the 8514a
  2056.        jnc     f85ok
  2057.        mov     dotmode, 0      ; if problem starting use normal mode
  2058. not8514on:
  2059.        jmp     dullnormalmode
  2060. hgcmode:
  2061.     mov    oktoprint,0        ; NOT OK to printf() in this mode
  2062.     call    hgcstart        ; Initialize the HGC card
  2063.     mov    ax,offset hgcwrite    ; set up HGC write-a-dot routine
  2064.     mov    bx,offset hgcread    ; set up HGC read-a-dot  routine
  2065.     mov    cx,offset normaline    ; set up normal linewrite routine
  2066.     mov    HGCflag,1        ; flag "HGC-end" needed.
  2067.     jmp    videomode        ; return to common code
  2068. f85ok:
  2069.     mov    ax,offset f85write      ; 
  2070.     mov    bx,offset f85read       ; 
  2071.     mov    cx,offset f85line       ; 
  2072.     mov    f85flag,1           ; 
  2073.     mov    oktoprint,0         ; NOT OK to printf() in this mode
  2074.     jmp    videomode           ; return to common code
  2075.  
  2076.  
  2077. videomode:
  2078.     mov    dotwrite,ax        ; save the results
  2079.     mov    dotread,bx        ;  ...
  2080.     mov    linewrite,cx        ;  ...
  2081.  
  2082.     mov    ax,colors        ; calculate the "and" value
  2083.     dec    ax            ; to use for eventual color 
  2084.     mov    andcolor,ax        ; selection
  2085.  
  2086.     mov    boxcount,0        ; clear the zoom-box counter
  2087.  
  2088.     mov    daclearn,0        ; set the DAC rotates to learn mode
  2089.     mov    daccount,6        ; initialize the DAC counter
  2090.     cmp    cpu,88            ; say, are we on a 186/286/386?
  2091.     jbe    setvideoslow        ;  boo!  hiss!
  2092.     mov    daclearn,1        ; yup.  bypass learn mode
  2093.     mov    ax,cyclelimit        ;  and go as fast as he wants
  2094.     mov    daccount,ax        ;  ...
  2095. setvideoslow:
  2096.  
  2097.     call    far ptr loaddac        ; load the video dac, if we can
  2098.  
  2099.     ret
  2100. setvideomode    endp
  2101.  
  2102. setvideo    proc    near        ; local set-video more
  2103.  
  2104.     cmp    ax,0            ; TWEAK?:  look for AX==BX==CX==0
  2105.     jne    short setvideobios    ;  ...
  2106.     cmp    bx,0            ;  ...
  2107.     jne    short setvideobios    ;  ...
  2108.     cmp    cx,0            ;  ...
  2109.     je    short setvideoregs    ;  ...
  2110.  
  2111. setvideobios:
  2112.     call    maybeor            ; maybe or AL or (for Video-7s) BL
  2113.     push    bp            ; some BIOS's don't save this
  2114.     int    10h            ; do it via the BIOS.
  2115.     pop    bp            ; restore the saved register
  2116.     jmp    setvideoreturn        ;  and return.
  2117.  
  2118. setvideoregs:                ; assume genuine VGA and program regs
  2119.  
  2120.     mov    si,dx            ; get the video table offset
  2121.     shl    si,1            ;  ...
  2122.     mov    si,word ptr tweaks[si]    ;  ...
  2123.  
  2124.         mov     tweaktype, dx           ; save tweaktype 
  2125.     cmp    dx,8            ; 360x480 tweak256mode?    
  2126.     je    isatweaktype        ; yup    
  2127.     cmp    dx,9            ; 320x400 tweak256mode?
  2128.     je    isatweaktype        ; yup
  2129.         cmp    dx,10            ; Tseng tweak?
  2130.     je    tsengtweak        ; yup
  2131.         jmp    not256            ; nope none of the above
  2132. tsengtweak:
  2133.     mov     ax,46              ; start with S-VGA mode 2eh
  2134.     call    maybeor            ; maybe don't clear the video memory
  2135.      int     10h              ; let the bios clear the video memory
  2136.      mov     dx,3c2h          ; misc output
  2137.      mov     al,063h          ; dot clock
  2138.      out     dx,al              ; select it
  2139.      mov     dx,3c4h          ; sequencer again
  2140.      mov     ax,0300h        ; restart sequencer
  2141.      out     dx,ax             ; running again
  2142.         jmp     is256;
  2143.  
  2144. isatweaktype:    
  2145.          mov        ax,0013h             ; invoke video mode 13h
  2146.          call       maybeor              ; maybe or AL or (for Video-7s) BL
  2147.          int        10h                  ; do it
  2148.    
  2149.          mov        dx,3c4h              ; alter sequencer registers
  2150.          mov        ax,0604h             ; disable chain 4
  2151.          out        dx,ax
  2152.    
  2153.          cmp       orvideo,0             ; are we supposed to clear RAM?
  2154.          jne       noclear256            ;  (nope)
  2155.  
  2156.     mov    dx,03c4h        ; alter sequencer registers
  2157.     mov    ax,0f02h        ; enable writes to all planes
  2158.     OUT_WORD
  2159.  
  2160.     push    es            ; save ES for a tad
  2161.     mov    ax,VGA_SEGMENT        ; clear out all 256K of 
  2162.     mov    es,ax            ;  video memory
  2163.     sub    di,di            ;  (64K at a time, but with
  2164.     mov    ax,di            ;  all planes enabled)
  2165.     mov    cx,8000h        ;# of words in 64K
  2166.     cld
  2167.     rep stosw            ;clear all of display memory
  2168.     pop    es            ; restore ES
  2169.  
  2170. noclear256:
  2171.     mov    dx,3c4h            ; alter sequencer registers
  2172.     mov    ax,0604h        ; disable chain 4
  2173.     out    dx,ax
  2174.  
  2175.     jmp    short is256        ; forget the ROM characters
  2176.  
  2177. not256:
  2178.  
  2179.     mov    ax,0012h        ; invoke video mode 12h
  2180.     call    maybeor            ; maybe or AL or (for Video-7s) BL
  2181.     int    10h            ; do it.
  2182.  
  2183.     mov    ax,1124h        ; load ROM 8*16 characters
  2184.     mov    bx,0
  2185.     mov    dh,0
  2186.     mov    dl,byte ptr [si+1]    ; number of rows on the screen
  2187.     int    10h
  2188.  
  2189. is256:    push    es            ; save ES for a tad
  2190.     mov    ax,40h            ; Video BIOS DATA area
  2191.     mov    es,ax            ;  ...
  2192.  
  2193.     mov    ah,0
  2194.     mov    al,byte ptr [si]    ; number of columns on the screen
  2195.     mov    word ptr es:[4ah],ax
  2196.     mul    byte ptr [si+1]        ; number of characters on the screen
  2197.     shl    ax,1            ; (attributes, also)
  2198.     mov    word ptr es:[4ch],ax
  2199.  
  2200.     mov    dx,word ptr es:[63h]    ; say, where's the 6845?
  2201.     add    dx,6            ; locate the status register
  2202. vrdly1:    in    al,dx            ; loop until vertical retrace is off
  2203.     test    al,8            ;   ...
  2204.     jnz    vrdly1            ;   ...
  2205. vrdly2:    in    al,dx            ; now loop until it's on!
  2206.     test    al,8            ;   ...
  2207.     jz    vrdly2            ;   ...
  2208.  
  2209.     cli                ; turn off all interrupts
  2210.         mov     dx,tweaktype
  2211.         cmp    dx,9            ; 320x400 mode?
  2212.         je    not256mode        ; yup - skip this stuff
  2213.         cmp    dx,10            ; Tseng tweak mode?
  2214.         je    not256mode        ; yup - skip this stuff
  2215.     mov    dx,03c4h        ; Sequencer Synchronous reset
  2216.     mov    ax,0100h        ; set sequencer reset
  2217.     out    dx,ax
  2218.     mov    dx,03c2h        ; Update Misc Output Reg
  2219.     mov    al,0E7h
  2220.     out    dx,al
  2221.     mov    dx,03c4h        ; Sequencer Synchronous reset
  2222.     mov    ax,0300h        ; clear sequencer reset
  2223.     out    dx,ax
  2224. not256mode:
  2225.     mov    dx,word ptr es:[63h]    ; say, where's the 6845?
  2226.     add    si,2            ; point SI to the CRTC registers table
  2227.     mov    al,11h            ; deprotect registers 0-7
  2228.     mov    ah,byte ptr [si+11h]
  2229.     and    ah,7fh
  2230.     out    dx,ax
  2231.  
  2232.     mov    cx,18h            ; update this many registers
  2233.     mov    bx,00            ; starting with this one.
  2234. crtcloop:
  2235.     mov    al,bl            ; update this register
  2236.     mov    ah,byte ptr [bx+si]    ; to this
  2237.     out    dx,ax
  2238.     inc    bx            ; ready for the next register
  2239.     loop    crtcloop        ; (if there is a next register)
  2240.     sti                ; restore interrupts
  2241.  
  2242.     pop    es            ; restore ES
  2243.  
  2244. setvideoreturn:
  2245.  
  2246.     mov    curbk,0ffffh        ; stuff impossible value into cur-bank
  2247.  
  2248.     mov    orvideo,0        ; reset the video to clobber memory
  2249.  
  2250.     ret
  2251. setvideo    endp
  2252.  
  2253. maybeor    proc    near            ; or AL or BL for mon-destr switch
  2254.     cmp    ah,6fh            ; video-7 special mode?
  2255.     je    maybeor1        ;  yup.  do this one different
  2256.     or    al,orvideo        ; normal non-destructive switch
  2257.     jmp    short maybeor2        ; we done.
  2258. maybeor1:
  2259.     or    bl,orvideo        ; video-7 switch
  2260. maybeor2:
  2261.     ret                ; we done.
  2262. maybeor    endp
  2263.  
  2264.  
  2265. ; ********* Functions setfortext() and setforgraphics() ************
  2266.  
  2267. ;    setfortext() resets the video for text mode and saves graphics data
  2268. ;    setforgraphics() restores the graphics mode and data
  2269. ;    setclear() clears the screen after setfortext() [which may be wierd]
  2270.  
  2271. setfortext    proc    uses es si di
  2272.     cmp    dotmode, 12        ;check for 8514
  2273.     jne    tnot8514
  2274.     cmp    f85flag, 0         ;check 8514 active flag
  2275.     je    dosettext
  2276.     call    close8514        ;close adapter if not
  2277.     mov    f85flag, 0
  2278.     jmp    short dosettext
  2279. tnot8514:
  2280.     cmp    videoax,0        ; check for CGA modes
  2281.     je    setfortextnocga        ;  not this one
  2282.     cmp    ydots,348        ; (only Hercules modes have this res)
  2283.     je    setfortextcga        ;  ...
  2284.     cmp    videoax,7        ;  ...
  2285.     ja    setfortextnocga        ;  not this one
  2286. setfortextcga:
  2287.     mov    ax,extraseg        ; set ES == Extra Segment
  2288.     add    ax,1000h        ; (plus 64K)
  2289.     mov    es,ax            ;  ...
  2290.     mov    di,4000h        ; save the video data here
  2291.     mov    ax,0b800h        ; video data starts here <XXX>
  2292.     mov    si,0            ;  ...
  2293.     mov    cx,2000h        ; save this many words
  2294.     cmp    ydots,348        ; (only Hercules modes have this res)
  2295.     jne    setfortextcganoherc    ;  ...
  2296.     mov    di,0            ; (save 32K)
  2297.     mov    ax,0b000h        ; (from here)
  2298.     mov    cx,4000h        ; (save this many words)
  2299. setfortextcganoherc:
  2300.     push    ds            ; save DS for a tad
  2301.     mov    ds,ax            ;  reset DS
  2302.     cld                ; clear the direction flag
  2303.     rep    movsw            ;  save them.
  2304.     pop    ds            ; restore DS
  2305.     cmp    dotmode, 10        ;check for Hercules-specific dotmode
  2306.     jne    tnotHGC
  2307.     cmp    HGCflag, 0         ;check HGC active flag
  2308.     je    dosettext
  2309.     call    hgcend            ;close adapter if not
  2310.     mov    HGCflag, 0
  2311.     jmp    short dosettext
  2312. tnotHGC:
  2313. dosettext:
  2314.     mov    ax,3            ; set up the text call
  2315.     mov    bx,0            ;  ...
  2316.     mov    cx,0            ;  ...
  2317.     mov    dx,0            ;  ...
  2318.     call    setvideo        ; set the video
  2319.     jmp    setfortextreturn
  2320. setfortextnocga:    
  2321.     mov    ax,0            ; disable the video (I think)
  2322.     call    disablevideo        ;  ...
  2323.     mov    orvideo,80h        ; set the video to preserve memory
  2324.     mov    ax,6            ; set up the text call
  2325.     mov    bx,0            ;  ...
  2326.     mov    cx,0            ;  ...
  2327.     mov    dx,0            ;  ...
  2328.     call    setvideo        ; set the video
  2329.     mov    ax,0            ; disable the video (I think)
  2330.     call    disablevideo        ;  ...
  2331.     cld                ; clear the direction flag
  2332.     mov    ax,extraseg        ; set ES == Extra Segment
  2333.     add    ax,1000h        ; (plus 64K)
  2334.     mov    es,ax            ;  ...
  2335.     mov    di,4000h        ; save the video data here
  2336.     mov    ax,0b800h        ; video data starts here
  2337.     push    ds            ; save DS for a tad
  2338.     mov    ds,ax            ;  reset DS
  2339.     mov    si,0            ;  ...
  2340.     mov    cx,2000h        ; save this many words
  2341.     rep    movsw            ;  save them.
  2342.     pop    ds            ; restore DS
  2343.     mov    ax,0b800h        ; clear the video buffer
  2344.     mov    es,ax            ;  ...
  2345.     mov    di,0            ;  ...
  2346.     mov    ax,0            ; to blanks
  2347.     mov    cx,2000h        ; this many blanks
  2348.     rep    stosw            ; do it.
  2349.     mov    ax,20h            ; enable the video (I think)
  2350.     call    disablevideo        ;  ...
  2351. setfortextreturn:
  2352.     call    far ptr home        ; home the cursor
  2353.     ret
  2354. setfortext    endp
  2355.  
  2356. setforgraphics    proc    uses es si di
  2357.     cmp     dotmode, 12        ;check for 8514
  2358.     jne    gnot8514
  2359.     cmp    f85flag, 0
  2360.     jne    f85isgraphics
  2361.     call    reopen8514
  2362.     mov    f85flag, 1
  2363. f85isgraphics:
  2364.     jmp    setforgraphicsreturn
  2365. gnot8514:
  2366.     cmp    videoax,0        ; check for CGA modes
  2367.     je    setforgraphicsnocga    ;  not this one
  2368.     cmp    ydots,348        ; (only Hercules modes have this res)
  2369.     je    setforgraphicscga    ;  ...
  2370.     cmp    videoax,7        ;  ...
  2371.     ja    setforgraphicsnocga    ;  not this one
  2372. setforgraphicscga:
  2373.     cmp    dotmode, 10        ;check for Hercules-specific dotmode
  2374.     jne    tnotHGC2        ;  (nope.  dull-normal stuff)
  2375.     call    hgcstart        ; Initialize the HGC card
  2376.     mov    HGCflag,1        ; flag "HGC-end" needed.
  2377.     jmp    short twasHGC2        ; bypass the normal setvideo call
  2378. tnotHGC2:
  2379.     mov    ax,videoax        ; set up the video call
  2380.     mov    bx,videobx        ;  ...
  2381.     mov    cx,videocx        ;  ...
  2382.     mov    dx,videodx        ;  ...
  2383.     call    setvideo        ; do it.
  2384. twasHGC2:
  2385.     mov    bx,extraseg        ; restore is from Extraseg
  2386.     add    bx,1000h        ; (plus 64K)
  2387.     mov    si,4000h        ; video data is saved here
  2388.     mov    ax,0b800h        ; restore the video area
  2389.     mov    di,0            ;  ...
  2390.     mov    cx,2000h        ; restore this many words
  2391.     cmp    ydots,348        ; (only Hercules modes have this res)
  2392.     jne    setforgraphicscganoherc    ;  ...
  2393.     mov    si,0            ; (restore 32K)
  2394.     mov    ax,0b000h        ; (to here)
  2395.     mov    cx,4000h        ; (restore this many words)
  2396. setforgraphicscganoherc:
  2397.     push    ds            ; save DX for a tad
  2398.     mov    es,ax            ; load the dest seg into ES
  2399.     mov    ds,bx            ; restore it from the source seg
  2400.     cld                ; clear the direction flag
  2401.     rep    movsw            ; restore them.
  2402.     pop    ds            ; restore DS
  2403.     jmp    setforgraphicsreturn
  2404. setforgraphicsnocga:
  2405.     mov    ax,0            ; disable the video (I think)
  2406.     call    disablevideo        ;  ...
  2407.     cld                ; clear the direction flag
  2408.     mov    ax,0b800h        ; restore the video area
  2409.     mov    es,ax            ; ES == video addr
  2410.     mov    di,0            ;  ...
  2411.     push    ds            ; reset DS to Extraseg temporarily
  2412.     mov    ax,extraseg        ;  ...
  2413.     add    ax,1000h        ; (plus 64K)
  2414.     mov    ds,ax            ;  ...
  2415.     mov    si,4000h        ; video data is saved here
  2416.     mov    cx,2000h        ; restore this many words
  2417.     rep    movsw            ; restore them.
  2418.     pop    ds            ; restore DS
  2419.     mov    orvideo,80h        ; set the video to preserve memory
  2420.     mov    ax,videoax        ; set up the video call
  2421.     mov    bx,videobx        ;  ...
  2422.     mov    cx,videocx        ;  ...
  2423.     mov    dx,videodx        ;  ...
  2424.     call    setvideo        ; do it.
  2425.     mov    ax,20h            ; enable the video (I think)
  2426.     call    disablevideo        ;  ...
  2427. setforgraphicsreturn:
  2428.     mov    ax,1            ; set up call to spindac(0,1)
  2429.     push    ax            ;  ...
  2430.     mov    ax,0            ;  ...
  2431.     push    ax            ;  ...
  2432.     call    far ptr spindac        ; do it.
  2433.     pop    ax            ; restore the registers
  2434.     pop    ax            ;  ...
  2435.     ret
  2436. setforgraphics    endp
  2437.  
  2438. setclear    proc    uses es si di    ; clear the screen after setfortext
  2439.     cmp    videoax,0        ; check for CGA modes
  2440.     je    setclearnocga        ;  not this one
  2441.     cmp    videoax,7        ;  ...
  2442.     ja    setclearnocga        ;  not this one
  2443. setclearcga:
  2444.     call    far ptr clscr        ; cga mode; normal clear
  2445.     jmp    setclearreturn        ; we done.
  2446. setclearnocga:
  2447.     mov    ax,0b800h        ; clear the video buffer
  2448.     mov    es,ax            ;  ...
  2449.     mov    di,0            ;  ...
  2450.     mov    ax,0            ; to blanks
  2451.     mov    cx,8192            ; this many blanks
  2452.     rep    stosw            ; do it.
  2453. setclearreturn:
  2454.     ret
  2455. setclear    endp
  2456.  
  2457. disablevideo    proc    near        ; wierd video trick to disable/enable
  2458.     push    dx            ; save some registers
  2459.     push    ax            ;  ...
  2460.     mov    dx,03bah        ; set attribute comtroller flip-flop
  2461.     in    al,dx            ;  regardless of video mode
  2462.     mov    dx,03dah        ;  ...
  2463.     in    al,dx            ;  ...
  2464.     mov    dx,03c0h        ; attribute controller address
  2465.     pop    ax            ; 00h = disable, 20h = enable
  2466.     out    dx,al            ;  trust me.
  2467.     pop    dx            ; restore DX and we done.
  2468.     ret
  2469. disablevideo    endp
  2470.  
  2471. ; **************** Function home()  ********************************
  2472.  
  2473. ;    Home the cursor (called before printfs)
  2474.  
  2475. home    proc
  2476.     mov    ax,0200h        ; force the cursor
  2477.     mov    bx,0            ; in page 0
  2478.     mov    dx,0            ; to the home position
  2479.     push    bp            ; some BIOS's don't save this
  2480.     int    10h            ; do it.
  2481.     pop    bp            ; restore the saved register
  2482.     ret
  2483. home    endp
  2484.  
  2485. ; **************** Function movecursor(row, col)  **********************
  2486.  
  2487. ;    Move the cursor (called before printfs)
  2488.  
  2489. movecursor    proc    cursorrow:word, cursorcol:word
  2490.     mov    ax,0200h        ; force the cursor
  2491.     mov    bx,0            ; in page 0
  2492.     mov    cx,cursorrow        ; put this in a register temporarily
  2493.     mov    dx,cursorcol        ; move to this column
  2494.     mov    dh,cl            ; move to this row
  2495.     push    bp            ; some BIOS's don't save this
  2496.     int    10h            ; do it.
  2497.     pop    bp            ; restore the saved register
  2498.     ret
  2499. movecursor    endp
  2500.  
  2501. ; **************** Function clscr() ********************************
  2502.  
  2503. ;    Clear the screen (in between text screens)
  2504.  
  2505. clscr    proc
  2506.     call    home            ; home the cursor
  2507.     mov    ax,0600h        ; clear the entire screen
  2508.     mov    bx,0700h        ; to black
  2509.     mov    cx,0            ; top left
  2510.     mov    dx,1979h        ; bottom right
  2511.     push    bp            ; some BIOS's don't save this
  2512.     int    10h            ; do it.
  2513.     pop    bp            ; restore the saved register
  2514.     ret                ; we done.
  2515. clscr    endp
  2516.  
  2517. ; ************* Function scrollup(toprow, botrow) ******************
  2518.  
  2519. ;    Scroll the screen up (from toprow to botrow)
  2520.  
  2521. scrollup    proc    uses    es, toprow:word, botrow:word
  2522.  
  2523.     mov    ax,0601h        ; scropp up one line
  2524.     mov    bx,0700h        ; new line is black
  2525.     mov    cx,toprow        ; this row,
  2526.     mov    ch,cl            ;  ...
  2527.     mov    cl,0            ;  first column
  2528.     mov    dx,botrow        ; to this row,
  2529.     mov    dh,dl            ;  ...
  2530.     mov    dl,79            ;  last column
  2531.     push    bp            ; some BIOS's don't save this
  2532.     int    10h            ; do it.
  2533.     pop    bp            ; restore the saved register
  2534.     ret                ; we done.
  2535. scrollup    endp
  2536.  
  2537.  
  2538. ; **************** Function getcolor(xdot, ydot) *******************
  2539.  
  2540. ;    Return the color on the screen at the (xdot,ydot) point
  2541.  
  2542. getcolor    proc    uses di si es, xdot:word, ydot:word
  2543.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  2544.     mov    es,ax            ; save it here during this routine
  2545.     mov    cx,xdot            ; load up the registers
  2546.     mov    dx,ydot            ;  for the video routine
  2547.     call    dotread            ; read the dot via the approved method
  2548.     mov    ah,0            ; clear the high-order bits
  2549.     ret                ; we done.
  2550. getcolor    endp
  2551.  
  2552. ; ************** Function putcolor(xdot, ydot, color) *******************
  2553.  
  2554. ;    write the color on the screen at the (xdot,ydot) point
  2555.  
  2556. putcolor    proc    uses di si es, xdot:word, ydot:word, xcolor:word
  2557.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  2558.     mov    es,ax            ; save it here during this routine
  2559.     mov    cx,xdot            ; load up the registers
  2560.     mov    dx,ydot            ;  for the video routine
  2561.     mov    ax,xcolor        ;  ...
  2562.     and    ax,andcolor        ; (ensure that 'color' is in the range)
  2563.     call    dotwrite        ; write the dot via the approved method
  2564.     call    videocleanup        ; perform any video cleanup required
  2565.     ret                ; we done.
  2566. putcolor    endp
  2567.  
  2568. ; ************** Function putblock(xmin, ymin, xmax, ymax, color) *******************
  2569.  
  2570. ;    write a block of color on the screen  
  2571. ;    on the rectangle bounded by (xmin,ymin) and (xmax,ymax)
  2572.  
  2573. putblock    proc    uses di si es, xmin:word, ymin:word, xmax:word, ymax:word, xcolor:word
  2574.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  2575.     mov    es,ax            ; save it here during this routine
  2576.     mov    cx,xmin            ; x-loop
  2577.     dec    cx            ; get a running start
  2578. putblx:    inc    cx            ; next x-dot
  2579.     mov    dx,ymin            ; y-loop
  2580.     dec    dx            ; get a running start
  2581. putbly:    inc    dx            ; next y-dot
  2582.     push    cx            ; save registers aroud the call
  2583.     push    dx            ;  ...
  2584.     mov    ax,xcolor        ;  ...
  2585.     call    dotwrite        ; write the dot via the approved method
  2586.     pop    dx            ; restore registers
  2587.     pop    cx            ;  ...
  2588.     cmp    dx,ymax            ; done with y-loop?
  2589.     jne    putbly            ; nope.
  2590.     cmp    cx,xmax            ; done with x-loop:
  2591.     jne    putblx            ; nope.
  2592.     call    videocleanup        ; perform any video cleanup required
  2593.     ret                ; we done.
  2594. putblock    endp
  2595.  
  2596. ; ***************Function out_line(color) *********************
  2597.  
  2598. ;    This routine is a 'line' analog of 'putcolor()', and sends an
  2599. ;    entire line of pixels to the screen (0 <= xdot < xdots) at a clip
  2600. ;    Called by the GIF decoder
  2601.  
  2602. out_line    proc    uses di si es, ycolor:word
  2603.     mov    ax,rowcount        ; sanity check: don't proceed
  2604.     cmp    ax,ydots        ; beyond the end of the screen
  2605.     ja    out_lineret        ;  ...
  2606.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  2607.     mov    es,ax            ; save it here during this routine
  2608.     mov    si,offset ycolor    ; get the color for dot 'x'
  2609.         call    linewrite        ; mode-specific linewrite routine
  2610.         inc    rowcount        ; next row
  2611. out_lineret:
  2612.         xor    ax,ax            ; return 0
  2613.     ret
  2614. out_line    endp
  2615.  
  2616.  
  2617. ; PUTSTR.asm puts a string directly to video display memory. Called from C by:
  2618. ;    putstring(row, col, attr, string, divider) where
  2619. ;         row, col = row and column to start printing.
  2620. ;         attr = color attribute.
  2621. ;         string = pointer to the null terminated string to print.
  2622. ;         divider = flag to add red column divider at end of string.
  2623. ;    Written for the A86 assembler (which has much less 'red tape' than MASM)
  2624. ;    by Bob Montgomery, Orlando, Fla.             7-11-88
  2625. ;    Adapted for MASM 5.1 by Tim Wegner          12-11-89  
  2626.      
  2627. .model medium,c
  2628.  
  2629. ;-----------------------------------------------------------------
  2630. .data
  2631.  
  2632. extrn     video_seg:word     ;Segment for video memory defined in C code.
  2633. extrn     crtcols:word       ;Columns/row
  2634. extrn     crtrows:word
  2635. ;-----------------------------------------------------------------
  2636.  
  2637. .code
  2638.  
  2639. putstring    proc uses es di si, row:word, col:word, attr:word, string:word, divider:word
  2640.  
  2641.      mov  ax,row              ;Get starting row
  2642.      mov  cx,crtcols         ;Multiply by 2 x bytes/row (char & attr bytes)
  2643.      shl  cx,1
  2644.      imul cx
  2645.      add  ax,col              ;Add starting column
  2646.      add  ax,col              ;twice since 2 bytes/char
  2647.      mov  di,ax               ; di now points to start location in Video segment
  2648.      mov  ax,video_seg       ;Get Video segment to es
  2649.      mov  es,ax
  2650.      mov  si,string           ; ds:si points to string to print
  2651.      mov  ax,attr             ;Get color attribute in ah
  2652.      xchg ah,al
  2653. ; Now print the string
  2654. B1:  lodsb                    ;Get a char in al
  2655.      cmp  al,0                ;End of string?
  2656.      je   B2                  ;Yes
  2657.      stosw                    ;No, store char & attribute
  2658.      jmp  B1                  ;Do next char
  2659.  
  2660. B2:  cmp  divider,0           ;Divider requested?
  2661.      je   B3                  ;No
  2662.      mov  ax,04B3h            ;Yes, red vertical line
  2663.           stosw
  2664. B3:  ret
  2665. putstring endp
  2666.  
  2667.  
  2668. scroll    proc uses ds es di si, rows:word, startrow:word
  2669.  
  2670. ; Get start offset and number of bytes to move.
  2671.      mov  ax,crtcols         ;Get chars/row
  2672.      mov  bx,crtrows         ;Get rows/screen
  2673.      sub  bx,rows             ;Get rows not moved
  2674.      push bx                 ;Save rows/screen & cols/row
  2675.      push ax
  2676.      push ax
  2677.      mul  startrow            ;Get chars to start
  2678.      shl  ax,1                ;Since char & attr in each pos
  2679.      mov  si,ax               ;in si
  2680.      mov  di,0                ;Move to start of screen
  2681.      pop  ax                  ;Get chars to move
  2682.      mul  rows
  2683.      mov  cx,ax               ;to cx
  2684. ; Move the rows.
  2685.      mov  ax,video_seg       ;Get Video segment to es
  2686.      mov  es,ax
  2687.      mov  ds,ax               ;and ds
  2688.      rep  movsw               ;Move the data (scroll screen)
  2689. ; Clear the rest of the screen.
  2690.      pop  ax                  ;Get chars/row & rows to clear
  2691.      pop  bx
  2692.      mul  bx                  ;Get chars to do
  2693.      mov  cx,ax
  2694.      mov  ax,0620h            ;Clear them
  2695.      rep  stosw
  2696. ; Return to C.
  2697.      ret                      ;and return to C
  2698. scroll     endp
  2699.  
  2700.  
  2701. ; ****************  EGA Palette <==> VGA DAC Conversion Routines **********
  2702.  
  2703. ;    paltodac    converts a 16-palette EGA value to a 256-color VGA
  2704. ;            value (duplicated 16 times)
  2705. ;    dactopal    converts the first 16 VGA values to a 16-palette
  2706. ;            EGA value
  2707.  
  2708. ;    local routines called with register values
  2709. ;        BH = VGA Red Color    xxRRRRRR
  2710. ;        BL = VGA Green Color    xxGGGGGG
  2711. ;        CH = VGA Blue Color    xxBBBBBB
  2712. ;        CL = EGA Palette    xxrgbRGB
  2713. ;
  2714. ;    palettetodac    converts CL to BH/BL/CH
  2715. ;    dactopalette    converte BH/BL/CH to CL
  2716.  
  2717. ; *************************************************************************
  2718.  
  2719. palettetodac    proc    near
  2720.     mov    bx,0            ; initialize RGB values to 0
  2721.     mov    ch,0            ;  ...
  2722.     test    cl,20h            ; low-red high?
  2723.     jz    palettetodac1        ;  nope
  2724.     or    bh,10h            ; set it
  2725. palettetodac1:
  2726.     test    cl,10h            ; low-green high?
  2727.     jz    palettetodac2        ;  nope
  2728.     or    bl,10h            ; set it
  2729. palettetodac2:
  2730.     test    cl,08h            ; low-blue high?
  2731.     jz    palettetodac3        ;  nope
  2732.     or    ch,10h            ; set it
  2733. palettetodac3:
  2734.     test    cl,04h            ; high-red high?
  2735.     jz    palettetodac4        ;  nope
  2736.     or    bh,20h            ; set it
  2737. palettetodac4:
  2738.     test    cl,02h            ; high-green high?
  2739.     jz    palettetodac5        ;  nope
  2740.     or    bl,20h            ; set it
  2741. palettetodac5:
  2742.     test    cl,01h            ; high-blue high?
  2743.     jz    palettetodac6        ;  nope
  2744.     or    ch,20h            ; set it
  2745. palettetodac6:
  2746.     ret
  2747. palettetodac    endp
  2748.  
  2749. dactopalette    proc    near
  2750.     mov    cl,0            ; initialize RGB values to 0
  2751.     test    bh,10h            ; low-red high?
  2752.     jz    dactopalette1        ;  nope
  2753.     or    cl,20h            ; set it
  2754. dactopalette1:
  2755.     test    bl,10h            ; low-green high?
  2756.     jz    dactopalette2        ;  nope
  2757.     or    cl,10h            ; set it
  2758. dactopalette2:
  2759.     test    ch,10h            ; low-blue high?
  2760.     jz    dactopalette3        ;  nope
  2761.     or    cl,08h            ; set it
  2762. dactopalette3:
  2763.     test    bh,20h            ; high-red high?
  2764.     jz    dactopalette4        ;  nope
  2765.     or    cl,04h            ; set it
  2766. dactopalette4:
  2767.     test    bl,20h            ; high-green high?
  2768.     jz    dactopalette5        ;  nope
  2769.     or    cl,02h            ; set it
  2770. dactopalette5:
  2771.     test    ch,20h            ; high-blue high?
  2772.     jz    dactopalette6        ;  nope
  2773.     or    cl,01h            ; set it
  2774. dactopalette6:
  2775.     ret
  2776. dactopalette    endp
  2777.  
  2778. paltodac    proc    uses es si di
  2779.     mov    si,0            ; initialize the loop values
  2780.     mov    di,0
  2781. paltodacloop:
  2782.     mov    cl,palettega[si]    ; load up a single palette register
  2783.     call    palettetodac        ; convert it to VGA colors
  2784.     mov    dacbox+0[di],bh        ; save the red value
  2785.     mov    dacbox+1[di],bl        ;  and the green value
  2786.     mov    dacbox+2[di],ch        ;  and the blue value
  2787.     inc    si            ; bump up the registers
  2788.     add    di,3            ;  ...
  2789.     cmp    si,16            ; more to go?
  2790.     jne    paltodacloop        ;  yup.
  2791.     push    ds            ; set ES to DS temporarily
  2792.     pop    es            ;  ...
  2793.     mov    ax,15            ; do this 15 times to get to 256
  2794.     mov    di,offset dacbox+48    ; set up the first destination
  2795. paltodacloop2:
  2796.     mov    cx,24            ; copy another block of 16 registers
  2797.     mov    si,offset dacbox    ; set up for the copy
  2798.     rep    movsw            ;  do it
  2799.     dec    ax            ; need to do another block?
  2800.     jnz    paltodacloop2        ;  yup.  do it.
  2801.     ret                ;  we done.
  2802. paltodac    endp
  2803.  
  2804. dactopal    proc    uses es si di
  2805.     mov    si,0            ; initialize the loop values
  2806.     mov    di,0
  2807. dactopalloop:
  2808.     mov    bh,dacbox+0[di]        ; load up the VGA red value
  2809.     mov    bl,dacbox+1[di]        ;  and the green value
  2810.     mov    ch,dacbox+2[di]        ;  and the blue value
  2811.     call    dactopalette        ; convert it to an EGA palette
  2812.     mov    palettega[si],cl    ; save as a single palette register
  2813.     inc    si            ; bump up the registers
  2814.     add    di,3            ;  ...
  2815.     cmp    si,16            ; more to go?
  2816.     jne    dactopalloop        ;  yup.
  2817.     mov    cl,palettega        ; copy palette 0
  2818.     mov    palettega+16,cl        ;  to the overscan register
  2819.     ret                ;  we done.
  2820. dactopal    endp
  2821.  
  2822.  
  2823. ; *********************** Function storedac() ****************************
  2824.  
  2825. ;    Function to Store the dacbox[][] array into VGA,
  2826. ;    called from loaddac() durring initialization.
  2827.  
  2828. storedac    proc
  2829.     push    es            ; need ES == DS temporarily
  2830.     push    ds            ;  ...
  2831.     pop    es            ;  ...
  2832.     mov    ax,1012h        ; get the old DAC values
  2833.     mov    bx,0            ;  (assuming, of course, they exist)
  2834.     mov    cx,256            ;  ...
  2835.     mov    dx,offset dacbox    ;  ...
  2836.     int    10h            ; do it.
  2837.     pop    es            ;  ...
  2838.     ret
  2839. storedac endp
  2840.  
  2841. ; *********************** Function loaddac() ****************************
  2842.  
  2843. ;    Function to Load the dacbox[][] array, if it can
  2844. ;    (sets dacbox[0][0] to an invalid '255' if it can't)
  2845.  
  2846. loaddac    proc
  2847.     mov    reallyega,0        ; set flag: not an EGA posing as a VGA
  2848.     cmp    dotmode,9        ; TARGA 3 June 89 j mclain
  2849.     je    loaddacdone
  2850.     cmp    f85flag, 0
  2851.     jne    loaddacdone
  2852.     cmp    loadPalette,1        ; TARGA/VGA 3 June 89 j mclain
  2853.     jne    normalLoadDac
  2854.     call    storedac
  2855.     jmp    short loaddacdone
  2856. normalLoadDac:
  2857.     mov    dacbox,255        ; a flag value to detect invalid DAC
  2858.     cmp    debugflag,16        ; pretend we're not a VGA?
  2859.     je    loaddacdebug        ;  yup.
  2860.     push    es            ; need ES == DS temporarily
  2861.     push    ds            ;  ...
  2862.     pop    es            ;  ...
  2863.     mov    ax,1017h        ; get the old DAC values
  2864.     mov    bx,0            ;  (assuming, of course, they exist)
  2865.     mov    cx,256            ;  ...
  2866.     mov    dx,offset dacbox    ;  ...
  2867.     push    bp            ; some older BIOSes don't save this
  2868.     int    10h            ; do it.
  2869.     pop    bp            ; restore registers
  2870.     pop    es            ;  ...
  2871. loaddacdebug:
  2872.     cmp    dacbox,255        ; did it work?  do we have a VGA?
  2873.     jne    loaddacdone        ;  yup.
  2874.     cmp    colors,16        ; are we using 16 or more colors?
  2875.     jb    loaddacdone        ;  nope.  forget it.
  2876.     cmp    ydots,350        ; 640x350 range?
  2877.     jb    loaddacdone        ;  nope.  forget it.
  2878.     mov    bx,offset palettega    ; make up a dummy palette
  2879.     mov    cx,3800h        ; start with color 0 == black
  2880. loaddacega1:                ; and        color 8 == low-white
  2881.     mov    0[bx],cl        ; save one color
  2882.     mov    8[bx],ch        ; and another color
  2883.     inc    bx            ; bump up the DAC
  2884.     add    cx,0101h        ; and the colors
  2885.     cmp    cl,8            ; finished 8 colors?
  2886.     jne    loaddacega1        ;  nope.  get more.
  2887.     mov    reallyega,1        ; note that this is really an EGA
  2888.     call    far ptr paltodac    ; "convert" it to a VGA DAC
  2889.     mov    daclearn,1        ; bypass learn mode
  2890.     mov    ax,cyclelimit        ;  and spin as fast as he wants
  2891.     mov    daccount,ax        ;  ...
  2892. loaddacdone:
  2893.     ret
  2894. loaddac    endp
  2895.  
  2896. ; *************** Function spindac(direction, rstep) ********************
  2897.  
  2898. ;    Rotate the MCGA/VGA DAC in the (plus or minus) "direction"
  2899. ;    in "rstep" increments - or, if "direction" is 0, just replace it.
  2900.  
  2901. spindac    proc    uses di si es, direction:word, rstep:word
  2902.     cmp    dotmode,9        ; TARGA 3 June 89 j mclain
  2903.     je    spinbailout
  2904.     cmp    dacbox,255        ; do we have DAC registers to spin?
  2905.     je    spinbailout        ;  nope.  bail out.
  2906.     cmp    colors,16        ; at least 16 colors?
  2907.     jge    spindacdoit        ;  yup.  spin away.
  2908. spinbailout:
  2909.     jmp    spindacreturn        ;  nope.  bail out.
  2910.  
  2911. spindacdoit:
  2912.     push    ds            ; need ES == DS here
  2913.     pop    es            ;  ...
  2914.  
  2915.     mov    cx, rstep        ; loop through the rotate "rstep" times
  2916. stepDAC:
  2917.     push    cx            ; save the loop counter for a tad
  2918.  
  2919.     cmp    direction,0        ; just replace it?
  2920.     je    newDAC            ;  yup.
  2921.     cmp    direction,1        ; rotate upwards?
  2922.     jne    short downDAC        ;  nope.  downwards
  2923.     cld                ; set the direction
  2924.     mov    si,offset dacbox+3    ; set up the rotate
  2925.     mov    di,offset dacbox+768    ;  ...
  2926.     mov    cx,3            ;  ...
  2927.     rep    movsb            ; rotate it.
  2928.     mov    si,offset dacbox+6    ; set up the rotate
  2929.     mov    di,offset dacbox+3    ;  ...
  2930.     mov    cx,765            ;  ...
  2931.     rep    movsb            ; rotate it.
  2932.     jmp    short newDAC        ; set the new DAC
  2933. downDAC:
  2934.     std                ; set the direction
  2935.     mov    si,offset dacbox+767    ; set up the rotate
  2936.     mov    di,offset dacbox+770    ;  ...
  2937.     mov    cx,765            ;  ...
  2938.     rep    movsb            ; rotate it.
  2939.     mov    si,offset dacbox+770    ; set up the rotate
  2940.     mov    di,offset dacbox+5    ;  ...
  2941.     mov    cx,3            ;  ...
  2942.     rep    movsb            ; rotate it.
  2943. newDAC:
  2944.     cld                ; set the direction
  2945.     pop    cx            ; restore the loop counter
  2946.     loop    stepDAC            ; and loop until done.
  2947.  
  2948.     cmp    f85flag, 0        ; if 8514a then update pallette
  2949.     je    spindoit
  2950.     jmp    spin8514
  2951.  
  2952. spindoit:
  2953.     mov    bx,0            ;  set up to update the DAC
  2954.     mov    dacnorm,0        ;  indicate no overflow
  2955. dacupdate:
  2956.     mov    cx,daccount        ;  ...
  2957.     mov    ax,256            ; calculate 256 - BX
  2958.     sub    ax,bx            ;  ...
  2959.     cmp    ax,cx            ; is that less than the update count?
  2960.     jge    retrace1        ;  nope.  no adjustment
  2961.     mov    cx,ax            ;  else adjust
  2962.     mov    dacnorm,1        ; and indicate overflow
  2963. retrace1:
  2964.     mov    dx,03dah        ; wait for no retrace
  2965.     in    al,dx            ;  ...
  2966.     and    al,8            ; this bit is high during a retrace
  2967.     jnz    retrace1        ;  so loop until it goes low
  2968. retrace2:
  2969.     in    al,dx            ; wait for no retrace
  2970.     and    al,8            ; this bit is high during a retrace
  2971.     jz    retrace2        ;  so loop until it goes high
  2972.     cmp    reallyega,1        ; is this really an EGA?
  2973.     je    spinega            ;  yup.  spin it that way.
  2974.     cmp    cpu,88            ; are we on a (yuck, ugh) 8088/8086?
  2975.     jle    spinbios        ;  yup. go through the BIOS
  2976. .186
  2977.     mov    dx,03c8h        ; set up for a blitz-write
  2978.     mov    ax,bx            ; from this register
  2979.     cli                ; critical section:  no ints
  2980.     out    dx,al            ; starting register
  2981.     inc    dx            ; set up to update colors
  2982.     mov    si, offset dacbox    ; get starting addr in SI
  2983.     add    si,bx            ;  ...
  2984.     add    si,bx            ;  ...
  2985.     add    si,bx            ;  ...
  2986.     mov    ax,cx            ; triple the value in CX
  2987.     add    cx,ax            ;  ...
  2988.     add    cx,ax            ;  ...
  2989.     rep    outsb            ; whap!  Zango!  They're updated!
  2990.     sti                ; end of critical section
  2991.     mov    cx,ax            ; restore CX for code below
  2992.     jmp    spindone        ; skip over the BIOS version.
  2993. .8086
  2994. spinbios:
  2995.     mov    dx,offset dacbox    ; set up the DAC box offset
  2996.     add    dx,bx            ;  ...
  2997.     add    dx,bx            ;  ...
  2998.     add    dx,bx            ;  ...
  2999.     mov    ax,1012h        ; update the DAC
  3000.     int    10h            ; do it.
  3001.     jmp    spindone        ; jump to common code
  3002. spinega:
  3003.     cmp    bx,0            ; skip this if not the first time thru
  3004.     jne    spindone        ;  ...
  3005.     push    bx            ; save some registers
  3006.     push    cx            ;  aroud the call
  3007.     call    far ptr dactopal    ; convert the VGA DAC to an EGA palette
  3008.     pop    cx            ; restore the registers
  3009.     pop    bx            ;  from prior to the call
  3010.     mov    ax,1002h        ; update the EGA palette
  3011.     mov    dx,offset palettega    ;  ...
  3012.     int    10h            ; do it.
  3013. spindone:
  3014.     cmp    daclearn,0        ; are we still in learn mode?
  3015.     jne    nolearn            ;  nope.
  3016.     mov    dx,03dah        ; check for the retrace
  3017.     in    al,dx            ;  ...
  3018.     and    al,1            ; this bit is high if display disabled
  3019.     jz    donelearn        ;  oops.  retrace finished first.
  3020.     cmp    dacnorm,0        ; was this a "short" update?
  3021.     jne    short nolearn        ;  then don't increment it
  3022.     inc    daccount        ; increment the daccount value
  3023.     inc    daccount        ; increment the daccount value
  3024.     inc    daccount        ; increment the daccount value
  3025.     mov    ax,cyclelimit        ; collect the cycle-limit value
  3026.     cmp    daccount,ax        ; sanity check: don't update too far
  3027.     jle    short nolearn        ;  proceed if reasonable.
  3028. donelearn:
  3029.     sub    daccount,6        ; done learning: reduce the daccount
  3030.     mov    daclearn,1        ; set flag: no more learning
  3031. nolearn:
  3032.     add    bx,cx            ; set up for the next batch
  3033.     cmp    bx,256            ; more to go?
  3034.     jge    spindacreturn        ;  nope.  we done.
  3035.     jmp    dacupdate        ;  yup.  do it.
  3036.  
  3037. spin8514:
  3038.     call    w8514pal
  3039.  
  3040. spindacreturn:
  3041.     ret
  3042. spindac    endp
  3043.     end
  3044.  
  3045.