home *** CD-ROM | disk | FTP | other *** search
/ Mega A/V / mega_av.zip / mega_av / GRAPHUTL / FRASR172.ZIP / VIDEO.ASM < prev    next >
Assembly Source File  |  1992-01-17  |  206KB  |  7,178 lines

  1. ;    Generic assembler routines having to do with video adapter
  2. ;
  3. ; ---- Video Routines
  4. ;
  5. ;    setvideomode()
  6. ;    setvideotext()
  7. ;    getcolor()
  8. ;    putcolor()
  9. ;    out_line()
  10. ;    drawbox()
  11. ;    home()
  12. ;    movecursor()
  13. ;    keycursor()
  14. ;    putstring()
  15. ;    setattr()
  16. ;    scrollup()
  17. ;    scrolldown()
  18. ;    putstr()
  19. ;    loaddac()
  20. ;    spindac()
  21. ;    adapter_init
  22. ;    adapter_detect
  23. ;    setnullvideo
  24. ;
  25. ; ---- Help (Video) Support
  26. ;
  27. ;    setfortext()
  28. ;    setforgraphics()
  29. ;    setclear()
  30. ;    findfont()
  31. ;
  32.  
  33. ;             required for compatibility if Turbo ASM
  34. IFDEF ??version
  35.     MASM51
  36.     QUIRKS
  37. ENDIF
  38.  
  39.     .MODEL    medium,c
  40.  
  41.     .8086
  42.  
  43.     ; these must NOT be in any segment!!
  44.     ; this get's rid of TURBO-C fixup errors
  45.  
  46.     extrn    startvideo:far        ; start your-own-video routine
  47.     extrn    readvideo:far        ; read    your-own-video routine
  48.     extrn    writevideo:far        ; write your-own-video routine
  49.     extrn    endvideo:far        ; end    your-own-video routine
  50.     extrn    readvideopalette:far    ; read-your-own-palette routine
  51.     extrn    writevideopalette:far    ; write-your-own-palette routine
  52.  
  53.     extrn    startdisk:far        ; start disk-video routine
  54.     extrn    readdisk:far        ; read    disk-video routine
  55.     extrn    writedisk:far        ; write disk-video routine
  56.     extrn    enddisk:far        ; end    disk-video routine
  57.  
  58.     extrn    buzzer:far        ; nyaah, nyaah message
  59.  
  60.     extrn    getakey:far        ; for keycursor routine
  61.     extrn    keypressed:far        ;  ...
  62.  
  63. ; TARGA 28 May 80 - j mclain
  64.     extrn    StartTGA  :far        ; start TARGA
  65.     extrn    ReadTGA   :far        ; read    TARGA
  66.     extrn    WriteTGA  :far        ; write TARGA
  67.     extrn    EndTGA      :far        ; end    TARGA
  68.     extrn    ReopenTGA :far        ; restart TARGA
  69.  
  70. ; TARGA+ Mark Peterson 2-12-91
  71.     extrn    MatchTPlusMode:far
  72.     extrn    CheckForTPlus:far
  73.     extrn    WriteTPlusBankedPixel:far
  74.     extrn    ReadTPlusBankedPixel:far
  75.     extrn    TPlusLUT:far
  76.  
  77. ; 8514/A routines
  78.     extrn    open8514  :far        ; start 8514a
  79.     extrn    reopen8514:far        ; restart 8514a
  80.     extrn    close8514 :far        ; stop 8514a
  81.     extrn    fr85wdot  :far        ; 8514a write dot
  82.     extrn    fr85wbox  :far        ; 8514a write box
  83.     extrn    fr85rdot  :far        ; 8514a read dot
  84.     extrn    fr85rbox  :far        ; 8514a read box
  85.     extrn    w8514pal  :far        ; 8514a pallete update
  86.  
  87. ; Hercules Routines
  88.     extrn    inithgc   :far        ; Initialize Hercules card graphics mode
  89.     extrn    termhgc   :far        ; Terminate Hercules card graphics mode
  90.     extrn    writehgc  :far        ; Hercules write dot
  91.     extrn    readhgc   :far        ; Hercules read dot
  92.  
  93. ; setforgraphics/setfortext textsafe=save
  94.     extrn    savegraphics    :far
  95.     extrn    restoregraphics :far
  96.  
  97. .DATA
  98.  
  99. ; ************************ External variables *****************************
  100.  
  101.     extrn    oktoprint: word     ; flag: == 1 if printf() will work
  102.     extrn    videoentry:byte     ; video table entry flag
  103.     extrn    dotmode: word        ; video mode (see the comments
  104.                     ; in front of the internal video
  105.                     ; table for legal dot modes)
  106.     extrn    textsafe2: word     ; textsafe over-ride from videotable
  107.  
  108.     extrn    sxdots:word,sydots:word ; physical screen number of dots
  109.     extrn    sxoffs:word,syoffs:word ; logical screen top left
  110.     extrn    colors:word        ; colors
  111.     extrn    cyclelimit:word     ; limiting factor for DAC-cycler
  112.     extrn    debugflag:word        ; for debugging purposes only
  113.  
  114.     extrn    boxcount:word        ; (previous) box pt counter: 0 if none.
  115.     extrn    boxx:word, boxy:word    ; zoom-box save-value locations
  116.     extrn    boxvalues:byte        ; zoom-box save-pixel locations
  117.  
  118.     extrn    xorTARGA:word        ; TARGA 3 June 89 j mclain
  119.                     ; flag says xor pixels for box
  120.  
  121.     extrn    cpu:word        ; CPU type (86, 186, 286, or 386)
  122.     extrn    extraseg:word        ; location of the EXTRA segment
  123.  
  124.     extrn    suffix:word        ; (safe place during video-mode switches)
  125.  
  126.     extrn    swaplength:word     ; savegraphics/restoregraphics stuff
  127.     extrn    swapoffset:dword    ; ...
  128.     extrn    swapvidbuf:dword    ; ...
  129.     extrn    swaptotlen:dword    ; ...
  130.  
  131.     extrn    rotate_lo:word, rotate_hi:word
  132.  
  133.     extrn    bios_palette:word
  134.     extrn    paldata:byte
  135.  
  136.     extrn    xdots:word
  137.     extrn    ydots:word
  138.     extrn    colors:word
  139.     extrn    NonInterlaced:word
  140.     extrn    PixelZoom:word
  141.     extrn    MaxColorRes:word
  142.     extrn    TPlusFlag:WORD        ; TARGA+ Mark Peterson 2-12-91
  143.  
  144. ; ************************ Public variables *****************************
  145.  
  146. public        andcolor        ; used by 'calcmand'
  147. public        videotable
  148. public        loadPalette        ; flag for loading VGA/TARGA palette from disk
  149. public        dacbox            ; GIF saves use this
  150. public        daclearn, daccount    ; Rotate may want to use this
  151. public        rowcount        ; row-counter for decoder and out_line
  152. public        gotrealdac        ; loaddac worked, really got a dac
  153. public        reallyega        ; "really an EGA" (faking a VGA) flag
  154. public        diskflag        ; disk video active flag
  155. public        video_type        ; video adapter type
  156. public        svga_type        ; SuperVGA video adapter type
  157. public        mode7text        ; for egamono and hgc
  158. public        textaddr        ; text segment
  159. public        textsafe        ; setfortext/setforgraphics logic
  160. public        boxcolor        ; zoom box color
  161. public        goodmode        ; video mode ok?
  162. public        text_type        ; current mode's type of text
  163. public        textrow         ; current row in text mode
  164. public        textcol         ; current column in text mode
  165. public        textrbase        ; textrow is relative to this
  166. public        textcbase        ; textcol is relative to this
  167.  
  168. public        color_dark        ; darkest color in palette
  169. public        color_bright        ; brightest color in palette
  170. public        color_medium        ; nearest to medbright grey in palette
  171.  
  172. public        swapsetup        ; for savegraphics/restoregraphics
  173.  
  174. public        TPlusInstalled
  175.  
  176. public        vesa_detect        ; set to 1 to disable VESA-detection
  177.  
  178. ;        arrays declared here, used elsewhere
  179. ;        arrays not used simultaneously are deliberately overlapped
  180.  
  181. ; ************************ Internal variables *****************************
  182.  
  183. vxdots        dw    0        ; virtual scan line length (bytes)
  184.  
  185. goodmode    dw    0        ; if non-zero, OK to read/write pixels
  186. dotwrite    dw    0        ; write-a-dot routine:    mode-specific
  187. dotread     dw    0        ; read-a-dot routine:    mode-specific
  188. linewrite    dw    0        ; write-a-line routine: mode-specific
  189. lineread    dw    0        ; read-a-line routine: mode-specific
  190. swapsetup    dd    0        ; setfortext/graphics setup routine
  191. andcolor    dw    0        ; "and" value used for color selection
  192. color        db    0        ; the color to set a pixel
  193. videoflag    db    0        ; special "your-own-video" flag
  194. tgaflag     db    0        ; TARGA 28 May 89 - j mclain
  195. loadPalette    db    0        ; TARGA/VGA load palette from disk
  196.  
  197. f85flag     db    0        ;flag for 8514a
  198.  
  199. HGCflag     db    0        ;flag for Hercules Graphics Adapter
  200.  
  201. TPlusInstalled    dw    0
  202.  
  203. xga_pos_base    dw    0        ; MCA Pos Base value
  204. xga_cardid    dw    0        ; MCA Card ID value
  205. xga_reg_base    dw    -1        ; XGA IO Reg Base (-1 means dunno yet)
  206. xga_1mb     dd    0        ; XGA 1MB aperture address
  207. xga_4mb     dd    0        ; XGA 4MB aperture address
  208. xga_result    dw    0        ; XGA_detect result code
  209. xga_isinmode    dw    0        ; XGA is in this mode right now
  210. xga_iscolors    dw    0        ; XGA using this many colors (0=64K)
  211. xga_clearvideo    db    0        ; set to 80h to prevent video-clearing
  212. xga_loaddac    db    0        ; set to 1 to load 'dacbox' on modesw
  213. xga_xdots    dw    0        ; pixels per scan line
  214.  
  215.         align    2
  216. tmpbufptr    dd    0
  217. color_dark    dw    0        ; darkest color in palette
  218. color_bright    dw    0        ; brightest color in palette
  219. color_medium    dw    0        ; nearest to medbright grey in palette
  220. ;                    ; Zoom-Box values (2K x 2K screens max)
  221. boxcolor    dw    0        ; Zoom-Box color
  222. reallyega    dw    0        ; 1 if its an EGA posing as a VGA
  223. gotrealdac    dw    0        ; 1 if loaddac has a dacbox
  224. diskflag    dw    0        ; special "disk-video" flag
  225. palettega    db    17 dup(0)    ; EGA palette registers go here
  226. daclearn    db    0        ; 0 if "learning" DAC speed
  227. dacnorm     db    0        ; 0 if "normal" DAC update
  228. daccount    dw    0        ; DAC registers to update in 1 pass
  229. dacbox        db    773 dup(0)    ; DAC goes here
  230. ;;saved_dacreg    dw    0ffffh,0,0,0    ; saved DAC register goes here
  231.  
  232. orvideo     db    0        ; "or" value for setvideo
  233.         align    2
  234. rowcount    dw    0        ; row-counter for decoder and out_line
  235.  
  236. videomem    dw    0a000h        ; VGA videomemory
  237. videoax     dw    0        ; graphics mode values: ax
  238. videobx     dw    0        ; graphics mode values: bx
  239. videocx     dw    0        ; graphics mode values: cx
  240. videodx     dw    0        ; graphics mode values: dx
  241.  
  242. video_type    dw    0        ; actual video adapter type:
  243.                     ;   0  = type not yet determined
  244.                     ;   1  = Hercules
  245.                     ;   2  = CGA (assumed if nothing else)
  246.                     ;   3  = EGA
  247.                     ;   4  = MCGA
  248.                     ;   5  = VGA
  249.                     ;   6  = VESA (not yet checked)
  250.                     ;  11  = 8514/A (not yet checked)
  251.                     ;  12  = TIGA    (not yet checked)
  252.                     ;  13  = TARGA    (not yet checked)
  253. svga_type    dw    0        ;  (forced) SVGA type
  254.                     ;   1 = ahead "A" type
  255.                     ;   2 = ATI
  256.                     ;   3 = C&T
  257.                     ;   4 = Everex
  258.                     ;   5 = Genoa
  259.                     ;   6 = Ncr
  260.                     ;   7 = Oak-Tech
  261.                     ;   8 = Paradise
  262.                     ;   9 = Trident
  263.                     ;  10 = Tseng 3000
  264.                     ;  11 = Tseng 4000
  265.                     ;  12 = Video-7
  266.                     ;  13 = ahead "B" type
  267.                     ;  14 = "null" type (for testing only)
  268. mode7text    dw    0        ; nonzero for egamono and hgc
  269. textaddr    dw    0b800h        ; b800 for mode 3, b000 for mode 7
  270. textsafe    dw    0        ; 0 = default, runup chgs to 1
  271.                     ; 1 = yes
  272.                     ; 2 = no, use 640x200
  273.                     ; 3 = bios, yes plus use int 10h-1Ch
  274.                     ; 4 = save, save entire image
  275. text_type    dw    0        ; current mode's type of text:
  276.                     ;   0  = real text, mode 3 (or 7)
  277.                     ;   1  = 640x200x2, mode 6
  278.                     ;   2  = some other mode, graphics
  279. video_entries    dw    0        ; offset into video_entries table
  280. video_bankadr    dw    0        ; offset  of  video_banking routine
  281. video_bankseg    dw    0        ; segment of  video_banking routine
  282.  
  283. textrow     dw    0        ; for putstring(-1,...)
  284. textcol     dw    0        ; for putstring(..,-1,...)
  285. textrbase    dw    0        ; textrow is relative to this
  286. textcbase    dw    0        ; textcol is relative to this
  287. cursortyp    dw    0
  288.  
  289. tandyseg    dw    ?        ;Tandy 1000 video segment address
  290. tandyofs    dw    ?        ;Tandy 1000 Offset into video buffer
  291. tandyscan    dw    ?        ;Tandy 1000 scan line address pointer
  292.  
  293.  
  294. ; ******************* "Tweaked" VGA mode variables ************************
  295.  
  296.                         ; 704 x 528 mode
  297. x704y528    db    704/8            ; number of screen columns
  298.         db    528/16            ; number of screen rows
  299.         db     68h, 57h, 58h, 8Bh    ; CRTC Registers
  300.         db     59h, 86h, 3EH,0F0h
  301.         db      0h, 60h,  0h,  0h
  302.         db      0h,  0h,  2h, 3Dh
  303.         db     19h, 8Bh, 0Fh, 2Ch
  304.         db      0h, 18h, 38h,0E3h
  305.         db    0FFh
  306.                         ; 720 x 540 mode
  307. x720y540    db    720/8            ; number of screen columns
  308.         db    540/16            ; number of screen rows
  309.         db     6Ah, 59h, 5Ah, 8Dh    ; CRTC Registers
  310.         db     5Eh, 8Bh, 4AH,0F0h
  311.         db      0h, 60h,  0h,  0h
  312.         db      0h,  0h,  2h, 49h
  313.         db     24h, 86h, 1Bh, 2Dh
  314.         db      0h, 24h, 44h,0E3h
  315.         db    0FFh
  316.                         ; 736 x 552 mode
  317. x736y552    db    736/8            ; number of screen columns
  318.         db    552/16            ; number of screen rows
  319.         db     6Ch, 5Bh, 5Ch, 8Fh    ; CRTC Registers
  320.         db     5Fh, 8Ch, 56H,0F0h
  321.         db      0h, 60h,  0h,  0h
  322.         db      0h,  0h,  2h, 55h
  323.         db     2Bh, 8Dh, 27h, 2Eh
  324.         db      0h, 30h, 50h,0E3h
  325.         db    0FFh
  326.                         ; 752 x 564 mode
  327. x752y564    db    752/8            ; number of screen columns
  328.         db    564/16            ; number of screen rows
  329.         db     6Eh, 5Dh, 5Eh, 91h    ; CRTC Registers
  330.         db     62h, 8Fh, 62H,0F0h
  331.         db      0h, 60h,  0h,  0h
  332.         db      0h,  0h,  2h, 61h
  333.         db     37h, 89h, 33h, 2Fh
  334.         db      0h, 3Ch, 5Ch,0E3h
  335.         db    0FFh
  336.                         ; 768 x 576 mode
  337. x768y576    db    768/8            ; number of screen columns
  338.         db    576/16            ; number of screen rows
  339.         db     70h, 5Fh, 60h, 93h    ; CRTC Registers
  340.         db     66h, 93h, 6EH,0F0h
  341.         db      0h, 60h,  0h,  0h
  342.         db      0h,  0h,  2h, 6Dh
  343.         db     43h, 85h, 3Fh, 30h
  344.         db      0h, 48h, 68h,0E3h
  345.         db    0FFh
  346.                         ; 784 x 588 mode
  347. x784y588    db    784/8            ; number of screen columns
  348.         db    588/16            ; number of screen rows
  349.         db     72h, 61h, 62h, 95h    ; CRTC Registers
  350.         db     69h, 96h, 7AH,0F0h
  351.         db      0h, 60h,  0h,  0h
  352.         db      0h,  0h,  2h, 79h
  353.         db     4Fh, 81h, 4Bh, 31h
  354.         db      0h, 54h, 74h,0E3h
  355.         db    0FFh
  356.                         ; 800 x 600 mode
  357. x800y600    db    800/8            ; number of screen columns
  358.         db    600/16            ; number of screen rows
  359.         db     74h, 63h, 64h, 97h    ; CRTC Registers
  360.         db     68h, 95h, 86H,0F0h
  361.         db      0h, 60h,  0h,  0h
  362.         db      0h,  0h,  2h, 85h
  363.         db     5Bh, 8Dh, 57h, 32h
  364.         db      0h, 60h, 80h,0E3h
  365.         db    0FFh
  366.  
  367. x360y480    db    360/8            ; number of screen columns
  368.         db    480/16            ; number of screen rows
  369.         db     6bh, 59h, 5ah, 8eh    ; CRTC Registers
  370.         db     5eh, 8ah, 0DH,03Eh
  371.         db      0h, 40h, 00h,  0h
  372.         db      0h,  0h,  0h, 31h
  373.         db    0EAh, 0ACh, 0DFh, 2Dh
  374.         db      0h,0E7h, 06h,0E3h
  375.         db    0FFh
  376.  
  377. x320y480    db    320/8            ; number of screen columns
  378.         db    480/16            ; number of screen rows
  379.         db     5fh, 4fh, 50h, 82h    ; CRTC Registers
  380.         db     54h, 80h, 0DH,03Eh
  381.         db      0h, 40h, 00h,  0h
  382.         db      0h,  0h,  0h,  0h
  383.         db    0EAh, 0AEh, 0DFh, 28h
  384.         db      0h,0E7h, 006h,0E3h
  385.         db    0FFh
  386.  
  387. ; mode x from Michael Abrash
  388. x320y240    db    320/8            ; number of screen columns
  389.         db    240/16            ; number of screen rows
  390.         db    05fh, 04fh, 050h, 082h
  391.         db    054h, 080h, 0dh, 03eh
  392.         db    00h, 041h, 00h, 00h
  393.         db    00h, 00h, 00h, 00h
  394.         db    0eah, 0ach, 0dfh, 028h
  395.         db    00h, 0e7h, 06h, 0e3h
  396.         db     0ffh
  397.  
  398. x320y400    db    320/8            ; number of screen columns
  399.         db    400/16            ; number of screen rows
  400.         db     5fh, 4fh, 50h, 82h    ; CRTC Registers
  401.         db     54h, 80h,0bfh, 1fh
  402.         db     00h, 40h, 00h, 00h
  403.         db     00h, 00h, 00h, 00h
  404.         db     9ch, 8eh, 8fh, 28h
  405.         db     00h, 96h,0b9h,0E3h
  406.         db    0FFh
  407.  
  408. x640y400    db    640/8            ; number of screen columns
  409.         db    400/16            ; number of screen rows
  410.         db     5eh, 4fh, 50h, 01h    ; CRTC Registers
  411.         db     54h, 9fh,0c0h, 1fh
  412.         db     00h, 40h, 00h, 00h
  413.         db     00h, 00h, 00h, 00h
  414.         db     9ch,08eh, 8fh, 28h
  415.         db     00h, 95h,0bch,0c3h
  416.         db     0ffh
  417. ;for VGA
  418. x400y600    db    400/8
  419.         db    600/16
  420.         db    74h,63h,64h,97h
  421.         db    68h,95h,86h,0F0h
  422.         db    00h,60h,00h,00h
  423.         db    00h,00h,00h,31h
  424.         db    5Bh,8Dh,57h,32h
  425.         db    0h,60h,80h,0E3h
  426.         db    0FFh
  427. ;for VGA
  428. x376y564    db    376/8
  429.         db    564/16
  430.         db    6eh,5dh,5eh,91h
  431.         db    62h,8fh,62h,0F0h
  432.         db    00h,60h,00h,00h
  433.         db    00h,00h,00h,31h
  434.         db    37h,89h,33h,2fh
  435.         db    0h,3ch,5ch,0E3h
  436.         db    0FFh
  437. ;for VGA
  438. x400y564    db    400/8
  439.         db    564/16
  440.         db    74h,63h,64h,97h
  441.         db    68h,95h,62h,0F0h
  442.         db    00h,60h,00h,00h
  443.         db    00h,00h,00h,31h
  444.         db    37h,89h,33h,32h
  445.         db    0h,3ch,5ch,0E3h
  446.         db    0FFh
  447.  
  448. testati     db    832/8
  449.         db    612/16
  450.         db    7dh,65h,68h,9fh
  451.         db    69h,92h,44h,1Fh
  452.         db    00h,00h,00h,00h
  453.         db    00h,00h,00h,00h
  454.         db    34h,86h,37h,34h
  455.         db    0fh,34h,40h,0E7h
  456.         db    0FFh
  457.  
  458.         align    2
  459.  
  460. tweaks        dw    offset x704y528     ; tweak table
  461.         dw    offset x704y528
  462.         dw    offset x720y540
  463.         dw    offset x736y552
  464.         dw    offset x752y564
  465.         dw    offset x768y576
  466.         dw    offset x784y588
  467.         dw    offset x800y600
  468.         dw    offset x360y480
  469.         dw    offset x320y400
  470.         dw    offset x640y400     ; Tseng Super VGA
  471.         dw    offset x400y600     ; new tweak (VGA)
  472.         dw    offset x376y564     ; new tweak (VGA)
  473.         dw    offset x400y564     ; new tweak (VGA)
  474.         dw    offset x720y540     ; ATI Tweak
  475.         dw    offset x736y552     ; ATI Tweak
  476.         dw    offset x752y564     ; ATI Tweak
  477.         dw    offset testati        ; ATI 832x816 (works!)
  478.         dw    offset x320y480
  479.         dw    offset x320y240
  480.  
  481. tweakflag    dw    0            ; tweak mode active flag
  482. tweaktype    dw    0            ; 8 or 9 (320x400 or 360x480)
  483.  
  484. bios_vidsave    dw    0            ; for setfortext/graphics
  485.  
  486. .CODE
  487.  
  488. FRAME    MACRO regs
  489.     push    bp
  490.     mov    bp, sp
  491.     IRP    reg, <regs>
  492.       push    reg
  493.       ENDM
  494.     ENDM
  495.  
  496. UNFRAME MACRO regs
  497.     IRP    reg, <regs>
  498.       pop reg
  499.       ENDM
  500.     pop bp
  501.     ENDM
  502.  
  503.  
  504. ;            Video Table Entries
  505. ;
  506. ;    The Video Table has been moved to a FARDATA segment to relieve
  507. ;    some of the pressure on the poor little overloaded 64K DATA segment.
  508.  
  509. .code
  510.  
  511. video_requirements    dw    0        ; minimal video_type req'd
  512.     dw    1, 3, 4, 5, 5, 5, 5, 5, 1, 1    ; dotmodes  1 - 10
  513.     dw    1, 5, 2, 1, 5, 5, 5, 5, 1, 5    ; dotmodes 11 - 20
  514.     dw    5, 5, 5, 5, 5, 5, 5, 5, 5, 5    ; dotmodes 21 - 30
  515.  
  516. videotable    label    byte    ; video table actually starts on the NEXT byte
  517.  
  518. ;    Feel free to add your favorite video adapter to FRACTINT.CFG.
  519. ;    The entries hard coded here are repeated from fractint.cfg in case
  520. ;    it gets lost/destroyed, so a user can still have some modes.
  521.  
  522. ;    Currently available Video Modes are (use the BIOS as a last resort)
  523. ;        1) use the BIOS (INT 10H, AH=12/13, AL=color) ((SLOW))
  524. ;        2) pretend it's a (perhaps super-res) EGA/VGA
  525. ;        3) pretend it's an MCGA
  526. ;        4) SuperVGA 256-Color mode using the Tseng Labs Chipset
  527. ;        5) SuperVGA 256-Color mode using the Paradise Chipset
  528. ;        6) SuperVGA 256-Color mode using the Video-7 Chipset
  529. ;        7) Non-Standard IBM VGA 360 x 480 x 256-Color mode
  530. ;        8) SuperVGA 1024x768x16 mode for the Everex Chipset
  531. ;        9) TARGA video modes
  532. ;        10) HERCULES video mode
  533. ;        11) Non-Video [disk or RAM] "video"
  534. ;        12) 8514/A video modes
  535. ;        13) CGA 320x200x4-color and 640x200x2-color modes
  536. ;        14) Tandy 1000 video modes
  537. ;        15) SuperVGA 256-Color mode using the Trident Chipset
  538. ;        16) SuperVGA 256-Color mode using the Chips & Tech Chipset
  539. ;        17) SuperVGA 256-Color mode using the ATI VGA Wonder Chipset
  540. ;        18) SuperVGA 256-Color mode using the Everex Chipset
  541. ;        19) Roll-Your-Own video, as defined in YOURVID.C
  542. ;        20) SuperVGA 1024x768x16 mode for the ATI VGA Wonder Chipset
  543. ;        21) SuperVGA 1024x768x16 mode for the Tseng Labs Chipset
  544. ;        22) SuperVGA 1024x768x16 mode for the Trident Chipset
  545. ;        23) SuperVGA 1024x768x16 mode for the Video 7 Chipset
  546. ;        24) SuperVGA 1024x768x16 mode for the Paradise Chipset
  547. ;        25) SuperVGA 1024x768x16 mode for the Chips & Tech Chipset
  548. ;        26) SuperVGA 1024x768x16 mode for the Everex Chipset
  549. ;        27) SuperVGA Auto-Detect mode
  550. ;        28) VESA modes
  551. ;        29) True Color Auto-Detect
  552.  
  553. ;    (Several entries have been commented out - they should/did work,
  554. ;    but are handled by alternative entries.  Where multiple SuperVGA
  555. ;    entries are covered by a single SuperVGA Autodetect mode, the
  556. ;    individual modes have been commented out.  Where a SuperVGA
  557. ;    Autodetect mode covers only one brand of adapter, the Autodetect
  558. ;    mode has been commented out to avoid confusion.)
  559.  
  560. ;        |--Adapter/Mode-Name------|-------Comments-----------|
  561.  
  562. ;        |------INT 10H------|Dot-|--Resolution---|
  563. ;        |key|--AX---BX---CX---DX|Mode|--X-|--Y-|Color|
  564.  
  565.     db    "IBM 16-Color EGA         ",0,"Standard EGA hi-res mode ",0
  566.     dw 1060,  10h,     0,   0,   0,    2, 640, 350,  16
  567.     db    "IBM 256-Color VGA/MCGA   ",0,"Quick and LOTS of colors ",0
  568.     dw 1061,  13h,     0,   0,   0,    3, 320, 200, 256
  569.     db    "IBM 16-Color VGA         ",0,"Nice high resolution     ",0
  570.     dw 1062,  12h,     0,   0,   0,    2, 640, 480,  16
  571.     db    "IBM 4-Color CGA          ",0,"(Ugh - Yuck - Bleah)     ",0
  572.     dw 1063,   4h,     0,   0,   0,  13, 320, 200,   4
  573.     db    "IBM Hi-Rez B&W CGA       ",0,"('Hi-Rez' Ugh - Yuck)    ",0
  574.     dw 1064,   6h,     0,   0,   0,  13, 640, 200,   2
  575.     db    "IBM B&W EGA              ",0,"(Monochrome EGA)         ",0
  576.     dw 1065,  0fh,     0,   0,   0,    2, 640, 350,   2
  577.     db    "IBM B&W VGA              ",0,"(Monochrome VGA)         ",0
  578.     dw 1066,  11h,     0,   0,   0,    2, 640, 480,   2
  579.     db    "IBM Low-Rez EGA          ",0,"Quick but chunky         ",0
  580.     dw 1067,  0dh,     0,   0,   0,    2, 320, 200,  16
  581.     db    "IBM VGA (non-std)        ",0,"Register Compatibles ONLY",0
  582.     dw 1068,   0h,     0,   0,   9,    7, 320, 400, 256
  583.     db    "IBM VGA (non-std)        ",0,"Register Compatibles ONLY",0
  584.     dw 1084,   0h,     0,   0,   8,    7, 360, 480, 256
  585.     db    "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
  586.     dw 1085,    0,     0,   0,   0,  27, 800, 600,  16
  587.     db    "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
  588.     dw 1086,    0,     0,   0,   0,  27,1024, 768,  16
  589.     db    "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
  590.     dw 1087,    0,     0,   0,   0,  27, 640, 400, 256
  591.     db    "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
  592.     dw 1088,    0,     0,   0,   0,  27, 640, 480, 256
  593.     db    "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
  594.     dw 1089,    0,     0,   0,   0,  27, 800, 600, 256
  595.     db    "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
  596.     dw 1090,    0,     0,   0,   0,  27,1024, 768, 256
  597.     db    "VESA Standard interface  ",0,"OK: Andy Fu - Chips&Tech ",0
  598.     dw 1091,4f02h,106h,   0,   0,  28,1280,1024,  16
  599.     db    "VESA Standard interface  ",0,"OK: Andy Fu - Chips&Tech ",0
  600.     dw 1092,4f02h,107h,   0,   0,  28,1280,1024, 256
  601.     db    "8514/A Low  Res          ",0,"Requires IBM's HDILOAD   ",0
  602.     dw 1093,   3h,     0,   0,   1,  12, 640, 480, 256
  603.     db    "8514/A High Res          ",0,"Requires IBM's HDILOAD   ",0
  604.     dw 1094,   3h,     0,   0,   1,  12,1024, 768, 256
  605.     db    "8514/A Low  W/Border     ",0,"Requires IBM's HDILOAD   ",0
  606.     dw 1095,   3h,     0,   0,   1,  12, 632, 474, 256
  607.     db    "8514/A High W/Border     ",0,"Requires IBM's HDILOAD   ",0
  608.     dw 1096,   3h,     0,   0,   1,  12,1016, 762, 256
  609.     db    "IBM Med-Rez EGA          ",0,"(Silly but it's there!)  ",0
  610.     dw 1097,  0eh,     0,   0,   0,    2, 640, 200,  16
  611.     db    "IBM VGA (non-std)        ",0,"Register Compatibles ONLY",0
  612.     dw 1098,   0h,     0,   0,  18,    7, 320, 480, 256
  613.     db    "Hercules Graphics        ",0,"OK: Timothy Wegner       ",0
  614.     dw 1099,   8h,     0,   0,   0,  10, 720, 348,   2
  615.     db    "Tandy 1000               ",0,"OK: Joseph Albrecht      ",0
  616.     dw 1100,   9h,     0,   0,   0,  14, 320, 200,  16
  617.     db    "Pdise/AST/COMPAQ VGA     ",0,"OK: Phil Wilson          ",0
  618.     dw 1101,  59h,     0,   0,   0,    1, 800, 600,   2
  619.     db    140    dup(0)    ; 2 unused slots here default table
  620.     db    "Disk/RAM 'Video'         ",0,"Full-Page L-Jet @  75DPI ",0
  621.     dw 1104,   3h,     0,   0,   0,  11, 800, 600,   2
  622.     db    "Disk/RAM 'Video'         ",0,"Full-Page L-Jet @ 150DPI ",0
  623.     dw 1105,   3h,     0,   0,   0,  11,1600,1200,   2
  624.     db    "Disk/RAM 'Video'         ",0,"Full-Page Epson @ 120DPI ",0
  625.     dw 1106,   3h,     0,   0,   0,  11, 768, 960,   2
  626.     db    "Disk/RAM 'Video'         ",0,"Full-Page Paintjet 90DPI ",0
  627.     dw 1107,   3h,     0,   0,   0,  11, 960, 720, 256
  628.     db    "Disk/RAM 'Video'         ",0,"For Background Fractals  ",0
  629.     dw 1108,   3h,     0,   0,   0,  11, 800, 600, 256
  630.     db    "Disk/RAM 'Video'         ",0,"For Background Fractals  ",0
  631.     dw 1109,   3h,     0,   0,   0,  11,2048,2048, 256
  632.     db    280    dup(0)    ; 4 unused slots here default table
  633.     db     70    dup(0)    ; 1 slot reserved for unassigned current mode
  634.  
  635.  
  636. bios_savebuf db 256 dup(0)  ; enough for 4 blocks (64 bytes/block)
  637.  
  638. .code
  639.  
  640. ;        XGA Graphics mode setup values
  641. ;        (the first two entries in each line
  642. ;        indicate where the table values are to be stored)
  643. ;
  644. ;        1024x768x256 vvv
  645. ;        1024x768x16  -----vvvv
  646. ;        640x480x256  -----------vvvv
  647. ;        640x480x65536 ----------------vvvv
  648. ;        800x600x16   -----------------------vvvv
  649. ;        800x600x256  -----------------------------vvvv
  650. ;        800x600x65536 ----------------------------------vvvv
  651.  
  652. xga_twidth dw    9                    ; width of these tables
  653.  
  654. xga_requir dw       0,     0,  0dh,  05h,  01h,  09h,  01h,  01h,  09h    ; adapter requirements
  655. xga_colors dw       0,     0,  256,   16,  256,     0,   16,  256,    0    ; 0 means 64K colors
  656. xga_swidth dw       0,     0, 1024,  512,  640, 1280,  400,  800, 1600    ; bytes / scan line
  657.  
  658. xga_val db    004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; interrupt enable
  659.     db    005h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; interrupt status
  660.     db    000h, 000h, 004h, 004h, 004h, 004h, 004h, 004h, 004h    ; operating mode
  661.     db    00ah, 064h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; palette mask
  662.     db    001h, 000h, 001h, 001h, 001h, 001h, 001h, 001h, 001h    ; vid mem aper cntl
  663.     db    008h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; vid mem aper indx
  664.     db    006h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; virt mem ctl
  665.     db    009h, 000h, 003h, 002h, 003h, 004h, 002h, 003h, 004h    ; mem access mode
  666.     db    00ah, 050h, 001h, 001h, 001h, 001h, 001h, 001h, 001h    ; disp mode 1
  667.     db    00ah, 050h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; disp mode 1
  668.     db    00ah, 010h, 09dh, 09dh, 063h, 063h, 088h, 088h, 088h    ; horiz tot lo.
  669.     db    00ah, 011h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; horiz tot hi.
  670.     db    00ah, 012h, 07fh, 07fh, 04fh, 04fh, 063h, 063h, 063h    ; hor disp end lo
  671.     db    00ah, 013h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor disp end hi
  672.     db    00ah, 014h, 080h, 080h, 050h, 050h, 064h, 064h, 064h    ; hor blank start lo
  673.     db    00ah, 015h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor blank start hi
  674.     db    00ah, 016h, 09ch, 09ch, 062h, 062h, 087h, 087h, 087h    ; hor blank end lo
  675.     db    00ah, 017h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor blank end hi
  676.     db    00ah, 018h, 087h, 087h, 055h, 055h, 06ah, 06ah, 06ah    ; hor sync start lo
  677.     db    00ah, 019h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor sync start hi
  678.     db    00ah, 01ah, 09ch, 09ch, 061h, 061h, 084h, 084h, 084h    ; hor sync end lo
  679.     db    00ah, 01bh, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; hor sync end hi
  680.     db    00ah, 01ch, 040h, 040h, 000h, 000h, 000h, 000h, 000h    ; hor sync pos
  681.     db    00ah, 01eh, 004h, 004h, 000h, 000h, 000h, 000h, 000h    ; hor sync pos
  682.     db    00ah, 020h, 030h, 030h, 00ch, 00ch, 086h, 086h, 086h    ; vert tot lo
  683.     db    00ah, 021h, 003h, 003h, 002h, 002h, 002h, 002h, 002h    ; vert tot hi
  684.     db    00ah, 022h, 0ffh, 0ffh, 0dfh, 0dfh, 057h, 057h, 057h    ; vert disp end lo
  685.     db    00ah, 023h, 002h, 002h, 001h, 001h, 002h, 002h, 002h    ; vert disp end hi
  686.     db    00ah, 024h, 000h, 000h, 0e0h, 0e0h, 058h, 058h, 058h    ; vert blank start lo
  687.     db    00ah, 025h, 003h, 003h, 001h, 001h, 002h, 002h, 002h    ; vert blank start hi
  688.     db    00ah, 026h, 02fh, 02fh, 00bh, 00bh, 085h, 085h, 085h    ; vert blank end lo
  689.     db    00ah, 027h, 003h, 003h, 002h, 002h, 002h, 002h, 002h    ; vert blank end hi
  690.     db    00ah, 028h, 000h, 000h, 0eah, 0eah, 058h, 058h, 058h    ; vert sync start lo
  691.     db    00ah, 029h, 003h, 003h, 001h, 001h, 002h, 002h, 002h    ; vert sync start hi
  692.     db    00ah, 02ah, 008h, 008h, 0ech, 0ech, 06eh, 06eh, 06eh    ; vert sync end
  693.     db    00ah, 02ch, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; vert line comp lo
  694.     db    00ah, 02dh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; vert line comp hi
  695.     db    00ah, 036h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; sprite cntl
  696.     db    00ah, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; start addr lo
  697.     db    00ah, 041h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; start addr me
  698.     db    00ah, 042h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; start addr hi
  699.     db    00ah, 043h, 080h, 040h, 050h, 0a0h, 032h, 064h, 0c8h    ; pixel map width lo
  700.     db    00ah, 044h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; pixel map width hi
  701.     db    00ah, 054h, 00dh, 00dh, 000h, 000h, 001h, 001h, 001h    ; clock sel
  702.     db    00ah, 051h, 003h, 002h, 003h, 004h, 002h, 003h, 004h    ; display mode 2
  703.     db    00ah, 070h, 000h, 000h, 000h, 000h, 080h, 080h, 080h    ; ext clock sel
  704.     db    00ah, 050h, 00fh, 00fh, 0c7h, 0c7h, 007h, 007h, 007h    ; display mode 1
  705.     db    00ah, 055h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Border Color
  706.     db    00ah, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pal Lo
  707.     db    00ah, 061h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pal hi
  708.     db    00ah, 062h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pre Lo
  709.     db    00ah, 063h, 000h, 000h, 000h, 000h, 000h, 000h, 000h    ; Sprite Pre hi
  710.     db    00ah, 064h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; Palette Mask
  711.     db    0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh    ; end of the list
  712.  
  713.  
  714. xga_newbank    proc            ; XGA-specific bank-switching routine
  715.     cmp    xga_isinmode,2        ; are we in an XGA-specific mode?
  716.     jl    return            ;  nope.  bail out.
  717.     mov    curbk,ax        ; save the new current bank value
  718.     mov    dx,xga_reg_base     ; Select Page
  719.     add    dx,08h
  720.     out    dx,al            ; assumes bank number is in al
  721. return: ret
  722. xga_newbank    endp
  723.  
  724. xga_16linewrite proc    near        ; 16-color Line Write
  725.     mov    bx,ax            ; calculate the # of columns
  726.     sub    bx,cx
  727.     mov    ax,xga_xdots        ; this many dots / line
  728.     mul    dx            ; times this many lines - ans in dx:ax
  729.     push    cx            ; save the X-value for a tad
  730.     shr    cx,1            ; and adjust for two bits per pixel
  731.     add    ax,cx            ; plus this many x-dots
  732.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  733.     mov    di,ax            ; save offset in DI
  734.     pop    cx            ; restore the X-value
  735.     mov    ax,dx            ; xga_newbank expects bank in al
  736. new_bank:
  737.     call    far ptr xga_newbank
  738. same_bank:
  739.     mov    ah,es:[di]        ; grab the old byte value
  740.     mov    al,[si]         ; and the new color value
  741.     and    al,0fh            ; isolate the bits we want
  742.     test    cx,1            ; odd pixel address?
  743.     jnz    xga_sk1         ;  yup
  744.     and    ah,0f0h         ; isolate the low-order
  745.     jmp    short    xga_sk2
  746. xga_sk1:and    ah,0fh            ; isolate the high-order
  747.     shl    al,1
  748.     shl    al,1
  749.     shl    al,1
  750.     shl    al,1
  751. xga_sk2:or    al,ah            ; combine the two nibbles
  752.     mov    es:[di],al        ; write the dot
  753.     inc    si            ; increment the source addr
  754.     dec    bx            ; more to go?
  755.     jz    done            ; nope
  756.     inc    cx            ; next pixel
  757.     test    cx,1            ; odd pixel?
  758.     jnz    same_bank        ;  yup
  759.     inc    di            ; increment the destination
  760.     cmp    di,0            ; segment wrap?
  761.     jnz    same_bank        ;  nope
  762.     mov    ax,curbk        ; update the bank cvalue
  763.     inc    ax
  764.     jmp    new_bank
  765. done:    ret
  766. xga_16linewrite     endp
  767.  
  768. xga_super16addr proc near        ; can be put in-line but shared by
  769.                     ; read and write routines
  770.     clc                ; clear carry flag
  771.     push    ax            ; save this for a tad
  772.     mov    ax,xga_xdots        ; this many dots / line
  773.     mul    dx            ; times this many lines - ans in dx:ax
  774.     push    cx            ; save the X-value for a tad
  775.     shr    cx,1            ; and adjust for two bits per pixel
  776.     add    ax,cx            ; plus this many x-dots
  777.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  778.     pop    cx            ; restore the X-value
  779.     mov    bx,ax            ; save this in BX
  780.     cmp    dx,curbk        ; see if bank changed
  781.     je    same_bank        ; jump if old bank ok
  782.     mov    ax,dx            ; xga_newbank expects bank in al
  783.     call    far ptr xga_newbank
  784. same_bank:
  785.     pop    ax            ; restore AX
  786.     ret
  787. xga_super16addr endp
  788.  
  789. xga_16write    proc near        ; XGA 256 colors write-a-dot
  790.     call    xga_super16addr     ; calculate address and switch banks
  791.     mov    ah,es:[bx]        ; grab the old byte value
  792.     and    al,0fh            ; isolate the bits we want
  793.     test    cx,1            ; odd pixel address?
  794.     jnz    xga_sk1         ;  yup
  795.     and    ah,0f0h         ; isolate the low-order
  796.     jmp    short    xga_sk2
  797. xga_sk1:and    ah,0fh            ; isolate the high-order
  798.     shl    al,1
  799.     shl    al,1
  800.     shl    al,1
  801.     shl    al,1
  802. xga_sk2:or    al,ah            ; combine the two nibbles
  803.     mov    es:[bx],al        ; write the dot
  804.     ret                ; we done.
  805. xga_16write    endp
  806.  
  807. xga_16read    proc near        ; XGA 256 colors read-a-dot
  808.     call    xga_super16addr     ; calculate address and switch banks
  809.     mov    al,es:[bx]        ; read the dot
  810.     test    cx,1            ; odd number of pixels?
  811.     jz    xga_sk1         ;  nope
  812.     shr    ax,1            ; adjust for odd pixel count
  813.     shr    ax,1
  814.     shr    ax,1
  815.     shr    ax,1
  816. xga_sk1:and    ax,0fh            ; isolate the byte value
  817.     ret                ; we done.
  818. xga_16read    endp
  819.  
  820. xga_clear    proc    uses es si di    ; clear the XGA memory
  821.     cmp    xga_clearvideo,0    ; should we really do this?
  822.     jne    return            ;  nope.  skip it.
  823.     mov    bx,xga_result        ; find out how much memory we have
  824.     and    bx,08h            ;  in 64K pages
  825.     add    bx,08h
  826.     mov    ax,0a000h        ; set up to clear 0a0000-0affff
  827.     push    ax
  828.     pop    es
  829. xloop:    mov    ax,bx            ; initialize the bank addr
  830.     call    xga_newbank
  831.     mov    ax,0
  832.     mov    cx,16384        ; clear out 32K
  833.     mov    di,0
  834.     rep    stosw
  835.     mov    cx,16384        ; clear out 32K
  836.     rep    stosw
  837.     dec    bx            ; another page?
  838.     cmp    bx,0
  839.     jge    xloop
  840. return: ret
  841. xga_clear    endp
  842.  
  843. xga_setpalette    proc    uses es si di, palette:word    ; set the XGA palette
  844.     cmp    xga_isinmode,2        ; are we in an XGA graphics mode?
  845.     jl    return            ;  nope
  846.  
  847.     mov    dx,xga_reg_base     ; wait for a retrace
  848.     add    dx,5
  849.     mov    al,1            ; clear the start-of-blanking
  850.     out    dx,al
  851. bloop:    in    al,dx
  852.     test    al,01h            ; blanking started?
  853.     jz    bloop            ;  nope - try again
  854.  
  855.     mov    dx,xga_reg_base     ; set up for a palette load
  856.     add    dx,0ah
  857.     mov    ax,0064h        ; make invisible
  858.     out    dx,ax
  859.     mov    ax,0055h        ; border color
  860.     out    dx,ax
  861.     mov    ax,0066h        ; palette mode
  862.     out    dx,ax
  863.     mov    ax,0060h        ; start at palette 0
  864.     out    dx,ax
  865.     mov    ax,0061h
  866.     out    dx,ax
  867.  
  868.     mov    si,palette
  869.     mov    cx,768
  870.     mov    ax,065h         ; palette update
  871.     out    dx,al
  872.     inc    dx            ; palette data
  873. .186
  874.     rep    outsb
  875. .8086
  876.     dec    dx
  877.  
  878.     mov    ax,0ff64h        ; make visible
  879.     out    dx,ax
  880.  
  881. return: ret
  882. xga_setpalette    endp
  883.  
  884. xga_detect    proc    uses es di si
  885.  
  886.     cmp    xga_reg_base,-2     ; has the XGA detector already failed?
  887.     jne    xga_sk1         ; ne = not yet
  888.     jmp    xga_notfound        ; e = yes, fail again
  889. xga_sk1:cmp    xga_reg_base,-1     ; have we already found the XGA?
  890.     je    xga_loc         ; e = no
  891.     jmp    xga_found        ; yes, process it
  892.  
  893. xga_loc:mov    ah,35h            ; DOS get interrupt vector
  894.     mov    al,15h            ; Int 15h
  895.     int    21h            ; returns vector in es:bx
  896.     mov    ax,es            ; segment part
  897.     or    ax,ax            ; undefined vector?
  898.     jnz    xga_sk2         ; nz = no, OK so far
  899.     jmp    xga_notfound        ; z = yes - not an MCA machine
  900. xga_sk2:mov    dx,-1            ; start with an invalid POS address
  901.     mov    ax,0c400h        ; look for POS base address
  902.     int    15h            ;  (Microchannel machines only)
  903.     jnc    xga_sk3         ; nc = success
  904.     jmp    xga_notfound        ; error - not an MC machine
  905. xga_sk3:mov    xga_pos_base,dx     ; save pos_base_address
  906.     xor    cx,cx            ; check all MCA slots & motherboard
  907.     cmp    dx,-1            ; do we have a good POS?
  908.     jne    xga_lp1         ; ne = yes, proceed with MCA checks
  909.     jmp    xga_notfound        ; no, fail
  910.  
  911. xga_lp1:cli                ; no interrupts, please
  912.     cmp    cx,0            ; treat the motherboard differently?
  913.     jne    xga_sk4         ; ne = yes
  914.     mov    al,0dfh         ; enable the motherboard for setup
  915.     mov    dx,94h
  916.     out    dx,al
  917.     jmp    short xga_sk5
  918. xga_sk4:mov    ax,0c401h        ; enable an MCA slot for setup
  919.     mov    bx,cx            ;  this slot
  920.     int    15h
  921. xga_sk5:mov    dx,xga_pos_base     ; get pos record for the slot ID
  922.     in    ax,dx
  923.     mov    xga_cardid,ax
  924.     add    dx,2            ; compute IO Res Base
  925.     in    al,dx            ;  get POS data byte1
  926.     mov    byte ptr xga_1mb,al    ;   save it temporarily
  927.     inc    dx            ; switch to byte 2
  928.     in    al,dx            ;  get POS data
  929.     mov    byte ptr xga_1mb+1,al    ;   save it temporarily
  930.     inc    dx            ; switch to byte 3
  931.     in    al,dx            ;  get POS data
  932.     mov    byte ptr xga_1mb+2,al    ;   save it temporarily
  933.     inc    dx            ; switch to byte 4
  934.     in    al,dx            ;  get POS data
  935.     mov    byte ptr xga_1mb+3,al    ;   save it temporarily
  936.     cmp    cx,0            ; treat the motherboard differently
  937.     jne    xga_sk6         ; ne = yes
  938.     mov    al,0ffh         ; enable the motherboard for normal
  939.     out    094h,al
  940.     jmp    short xga_sk7
  941. xga_sk6:mov    ax,0c402h        ; enable the MCA slot for normal
  942.     mov    bx,cx            ;  this slot
  943.     int    15h
  944. xga_sk7:sti                ; interrupts on again
  945.  
  946.     mov    ax,xga_cardid        ; is an XGA adapter on this slot?
  947.     cmp    ax,08fd8h
  948.     jae    xga_sk8         ; ae = yes
  949.     jmp    xga_lp2         ; try another slot
  950. xga_sk8:cmp    ax,08fdbh        ; still within range?
  951.     jbe    xga_sk9         ; be = yes
  952.     jmp    xga_lp2         ; no, try another slot
  953.  
  954. xga_sk9:mov    al,byte ptr xga_1mb    ;  restore POS data byte 1
  955.     and    ax,0eh            ;  muck about with it to get reg base
  956.     shl    ax,1
  957.     shl    ax,1
  958.     shl    ax,1
  959.     add    ax,2100h
  960.     mov    xga_reg_base,ax
  961.     mov    dx,xga_reg_base     ; is there a monitor on this slot?
  962.     add    dx,0ah
  963.     mov    al,052h
  964.     out    dx,al
  965.     mov    dx,xga_reg_base
  966.     add    dx,0bh
  967.     in    al,dx
  968.     and    al,0fh
  969.     cmp    al,00h            ; illegal value, returned under Win 3.0
  970.     je    xga_lp2
  971.     cmp    al,0fh
  972.     jne    xga_isthere        ; ne = yes
  973.  
  974. xga_lp2:inc    cx            ; try another adapter?
  975.     cmp    cx,9            ; done all slots?
  976.     ja    xga_ska         ; a = yes
  977.     jmp    xga_lp1         ; no, try another slot
  978.  
  979. xga_ska:jmp    xga_notfound        ; forget it - no XGA here
  980.  
  981. xga_isthere:
  982.     and    ax,06h            ; strip off the low & high bit
  983.     xor    ax,05h            ; reverse the 3rd & low bits
  984.     mov    xga_result,ax        ; save the result flag
  985.  
  986.     mov    dx,xga_reg_base     ; is this XGA in VGA mode?
  987.     in    al,dx
  988.     test    al,1
  989.     jnz    xga_skb         ; nz = yes - single-monitor setup
  990.     or    xga_result,10h        ;  dual-monitor setup
  991. xga_skb:
  992.  
  993.     mov    ah,byte ptr xga_1mb+2    ; retrieve POS data byte 3
  994.     and    ax,0fe00h        ; eliminate the low-order bits
  995.     mov    bl,byte ptr xga_1mb    ; retrieve POS data byte 1
  996.     and    bx,0eh            ; strip it down to the IODA
  997.     mov    cx,5            ; shift it up 5 bits
  998.     shl    bx,cl
  999.     or    ax,bx            ; compute the 4MB aperture value
  1000.     mov    word ptr xga_4mb+2,ax    ; save the result
  1001.  
  1002.     mov    al, byte ptr xga_1mb+3    ; retrieve POS data byte 4
  1003.     and    ax,0fh            ; select the 1MB aperture bits
  1004.     mov    cx,4            ; shift it up 4 bits
  1005.     shl    ax,cl
  1006.     mov    word ptr xga_1mb+2,ax    ; save the result
  1007.     mov    ax,0
  1008.     mov    word ptr xga_1mb,ax
  1009.  
  1010.     mov    dx,xga_reg_base     ; Interrupt Disable
  1011.     add    dx,4
  1012.     xor    al,al
  1013.     out    dx,al
  1014.  
  1015.     mov    dx,xga_reg_base     ; Switch to Extended Mode
  1016. ;;    add    dx,00h
  1017.     mov    al,4
  1018.     out    dx,al
  1019.  
  1020.     mov    dx,xga_reg_base     ; Aperture Control
  1021.     add    dx,01h
  1022.     mov    al,1
  1023.     out    dx,al
  1024.  
  1025.     mov    dx,xga_reg_base     ; disable Palette Mask
  1026.     add    dx,0ah
  1027.     mov    ax,0064h
  1028.     out    dx,ax
  1029.  
  1030.     mov    xga_isinmode,2        ; pretend we're already in graphics
  1031.     mov    al,12            ; select page 12
  1032.     call    xga_newbank
  1033.  
  1034.     push    es            ; see if this page has any memory
  1035.     mov    ax,0a000h
  1036.     push    ax
  1037.     pop    es
  1038.     mov    ah,000a5h
  1039.     mov    es:0,al
  1040.     mov    es:1,ah
  1041.     cmp    es:0,al
  1042.     jne    xga_512
  1043.     add    xga_result,8        ; 1MB RAM found
  1044. xga_512:pop    es
  1045.  
  1046.     mov    al,0            ; select page 0
  1047.     call    xga_newbank
  1048.     mov    xga_isinmode,0        ; replace the "in-graphics" flag
  1049.  
  1050.     mov    dx,xga_reg_base     ; Palette Mask
  1051.     add    dx,0ah
  1052.     mov    ax,0ff64h
  1053.     out    dx,ax
  1054.  
  1055.     test    xga_result,10h        ; dual monitor setup?
  1056.     jnz    xga_found        ;  yup - don't restore as a VGA
  1057.  
  1058.     mov    dx,xga_reg_base     ; Switch to VGA Mode
  1059. ;;    add    dx,00h
  1060.     mov    al,1
  1061.     out    dx,al
  1062.  
  1063.     mov    dx,03c3h        ; Enable VGA Address Code
  1064.     mov    al,1
  1065.     out    dx,al
  1066.  
  1067.     jmp    short    xga_found
  1068.  
  1069. xga_notfound:
  1070.     mov    xga_reg_base,-2     ; set failure flag
  1071. xga_found:
  1072.     mov    ax,xga_result        ; return the result
  1073.     ret
  1074.  
  1075. xga_detect    endp
  1076.  
  1077. xga_mode    proc    uses es di si, mode:word
  1078.  
  1079.     mov    curbk,-1        ; preload impossible bank number
  1080.  
  1081.     call    xga_detect        ; is an XGA adapter present?
  1082.     cmp    ax,0
  1083.     jne    whichmode
  1084.     jmp    nope            ;  nope
  1085. whichmode:
  1086.     mov    bx,mode
  1087.     cmp    bx,xga_twidth        ; mode number out of range?
  1088.     jb    whichmode0
  1089.     jmp    nope            ;  yup - fail right now.
  1090. whichmode0:
  1091.     cmp    mode,0            ; 80-col VGA text mode?
  1092.     jne    whichmode1
  1093.     jmp    mode_0            ;  yup
  1094. whichmode1:
  1095.     cmp    mode,1            ; 132-col VGA text mode?
  1096.     jne    whichmode2
  1097.     jmp    nope            ;  Fractint doesn't use this routine
  1098. whichmode2:
  1099.     mov    bx,mode         ; locate the table entries
  1100.     add    bx,mode
  1101.     mov    dx,xga_requir[bx]    ; does our setup support this mode?
  1102.     and    al,dl
  1103.     cmp    al,dl
  1104.     je    whichmode3
  1105.     jmp    nope            ;  nope
  1106. whichmode3:
  1107.  
  1108.     mov    ax,13h            ; switch to 320x200x256 mode
  1109.     call    maybeor         ; maybe or AL or (for Video-7s) BL
  1110.     int    10h
  1111.     push    ds            ; reset ES==DS
  1112.     pop    es
  1113.     mov    ax,1017h        ; get the DAC values
  1114.     mov    bx,0
  1115.     mov    cx,256
  1116.     mov    dx,offset paldata    ; a safe place when switching XGA modes
  1117.     int    10h
  1118.     cmp    xga_loaddac,0        ; save the palette?
  1119.     je    paskip            ;  (yes, if we want to fake 'loaddac')
  1120.     mov    si, offset paldata
  1121.     mov    di, offset dacbox
  1122.     mov    cx,768/2
  1123.     rep    movsw
  1124.     mov    xga_loaddac,0        ; reset the toggle for next time
  1125. paskip:
  1126.     mov    bx,769            ; adjust the palette
  1127. paloop:    dec    bx
  1128.     mov    ah,paldata[bx]
  1129.  
  1130.     shl    ah,1
  1131.     shl    ah,1
  1132.     mov    paldata[bx],ah
  1133.     cmp    bx,0
  1134.     jne    paloop
  1135.  
  1136.     mov    dx,xga_reg_base     ; Palette Mask
  1137.     add    dx,0ah
  1138.     mov    ax,00064h        ; (Disable the XGA palette)
  1139.     out    dx,ax
  1140.  
  1141.     mov    dx,xga_swidth[bx]    ; collect and save the scan-line length
  1142.     mov    xga_xdots,dx
  1143.     mov    dx,xga_colors[bx]    ; how many colors do we have?
  1144.     mov    xga_iscolors,dx     ; save this
  1145.  
  1146. mode_3: mov    dx,03c3h        ; Enable VGA Address Code
  1147.     mov    al,1
  1148.     out    dx,al
  1149.  
  1150.     mov    si,offset xga_val    ; point to start of values table
  1151.     mov    bx,mode         ; use mode as an offset
  1152. model1: mov    dx,xga_reg_base     ; get the base pointer
  1153.     mov    ah,0            ; get the increment
  1154.     mov    al,cs:0[si]
  1155.     cmp    al,0ffh         ; end of the table?
  1156.     je    model2            ;  yup
  1157.     add    dx,ax
  1158.     cmp    al,0ah            ; check for access type
  1159.     je    modsk2
  1160.     mov    al,cs:0[si+bx]        ; get the value and OUT it
  1161.     out    dx,al
  1162.     jmp    short modsk3
  1163. modsk2: mov    al,cs:1[si]        ; get the value and OUT it
  1164.     mov    ah,cs:0[si+bx]
  1165.     out    dx,ax
  1166. modsk3: add    si,xga_twidth        ; try another table entry
  1167.     jmp    short model1
  1168. model2:
  1169.  
  1170.     mov    xga_isinmode,2        ; pretend we're already in graphics
  1171.     call    xga_clear        ; clear out the memory
  1172.     mov    curbk,-1        ; reset the bank counter
  1173.  
  1174.     mov    dx,xga_reg_base     ; set up for final loads
  1175.     add    dx,0ah
  1176.     mov    bx,mode         ; how many colors do we have?
  1177.     add    bx,mode
  1178.     cmp    xga_colors[bx],0    ; "true color" mode?
  1179.     jne    modsk4            ; nope - skip the funny palette load
  1180.  
  1181.     mov    ax,0064h        ; make invisible
  1182.     out    dx,ax
  1183.     mov    ax,8055h        ; border color
  1184.     out    dx,ax
  1185.     mov    ax,0066h        ; palette mode
  1186.     out    dx,ax
  1187.     mov    ax,0060h        ; start at palette 0
  1188.     out    dx,ax
  1189.     mov    ax,0061h        ; ""
  1190.     out    dx,ax
  1191.  
  1192.     mov    cx,0            ; ready to update the palette
  1193.     mov    al,065h         ; palette update
  1194.     out    dx,al
  1195.     inc    dx            ; palette data
  1196. model3: mov    al,0            ; zero out the...
  1197.     out    dx,al            ;  red value
  1198.     out    dx,al            ;  and the green value
  1199.     mov    al,cl            ; klooge up the blue value
  1200.     and    al,1fh            ; convert to 1,2,...1f
  1201.     shl    al,1            ; convert to 2,4,...3e
  1202.     shl    al,1            ; convert to 4,8,...7c
  1203.     shl    al,1            ; convert to 8,16,..fd
  1204.     out    dx,al            ; blue value
  1205.     inc    cx            ; another palette value to go?
  1206.     cmp    cx,128
  1207.     jb    model3
  1208.     dec    dx            ; back to normal
  1209.  
  1210.     mov    ax,0ff64h        ; make the palette visible
  1211.     out    dx,ax
  1212.     jmp    ok
  1213.  
  1214. modsk4:    mov    bx, offset paldata    ; reset the palette
  1215.     push    bx
  1216.     mov    xga_isinmode,2
  1217.     call    xga_setpalette
  1218.     pop    bx
  1219.     jmp    ok
  1220.  
  1221. mode_0:                 ; Set 80 column mode
  1222.     mov    dx,xga_reg_base     ; Aperture Control
  1223.     add    dx,01h
  1224.     xor    al,al            ; (disable the XGA 64K aperture)
  1225.     out    dx,al
  1226.  
  1227.     mov    dx,xga_reg_base     ; Interrupt Disable
  1228.     add    dx,4
  1229.     xor    al,al
  1230.     out    dx,al
  1231.  
  1232.     mov    dx,xga_reg_base     ; Clear Interrupts
  1233.     add    dx,5
  1234.     mov    al,0ffh
  1235.     out    dx,al
  1236.  
  1237.     test    xga_result,10h        ; dual monitor setup?
  1238.     jz    mode_0a
  1239.     jmp    nope            ;  yup - don't restore as a VGA
  1240. mode_0a:
  1241.  
  1242.     mov    dx,xga_reg_base     ; Palette Mask
  1243.     add    dx,0ah
  1244.     mov    ax,0ff64h        ; (Enable the XGA palette)
  1245.     out    dx,ax
  1246.  
  1247.     mov    dx,xga_reg_base     ; Enable VFB, Prepare for Reset
  1248.     add    dx,0ah
  1249.     mov    ax,1550h
  1250.     out    dx,ax
  1251.  
  1252.     mov    dx,xga_reg_base     ; Enable VFB, reset CRTC
  1253.     add    dx,0ah
  1254.     mov    ax,1450h
  1255.     out    dx,ax
  1256.  
  1257.     mov    dx,xga_reg_base     ; Normal Scale Factors
  1258.     add    dx,0ah
  1259.     mov    ax,0051h
  1260.     out    dx,ax
  1261.  
  1262.     mov    dx,xga_reg_base     ; Select VGA Oscillator
  1263.     add    dx,0ah
  1264.     mov    ax,0454h
  1265.     out    dx,ax
  1266.  
  1267.     mov    dx,xga_reg_base     ; Ext Oscillator (VGA)
  1268.     add    dx,0ah
  1269.     mov    ax,7f70h
  1270.     out    dx,ax
  1271.  
  1272.     mov    dx,xga_reg_base     ; Ensure no Vsynch Interrupts
  1273.     add    dx,0ah
  1274.     mov    ax,202ah
  1275.     out    dx,ax
  1276.  
  1277.     mov    dx,xga_reg_base     ; Switch to VGA Mode
  1278. ;;    add    dx,00h
  1279.     mov    al,1
  1280.     out    dx,al
  1281.  
  1282.     mov    dx,03c3h        ; Enable VGA Address Code
  1283.     mov    al,1
  1284.     out    dx,al
  1285.  
  1286.     mov    ax,1202h        ; select 400 scan lines
  1287.     mov    bl,30h
  1288.     int    10h
  1289.  
  1290.     mov    ax,0+3            ; set video mode 3
  1291.     or    al,xga_clearvideo    ; (might supress video-clearing)
  1292.     cmp    xga_clearvideo,0    ; clear the video option set?
  1293.     je    mode_0b
  1294.     mov    ax,08eh         ; ugly klooge: VGA graphics, no clear
  1295. mode_0b:
  1296.     int    10h
  1297.  
  1298.     jmp    ok            ; we're done
  1299.  
  1300. nope:
  1301.     mov    xga_isinmode,0
  1302.     mov    ax,0            ; return failure
  1303.     ret
  1304. ok:
  1305.     mov    ax,mode         ; remember the mode we're in
  1306.     mov    xga_isinmode,ax
  1307.     mov    ax,1            ; return OK
  1308.     ret
  1309. xga_mode    endp
  1310.  
  1311.  
  1312. ; **************** internal Read/Write-a-dot routines ***********************
  1313. ;
  1314. ;    These Routines all assume the following register values:
  1315. ;
  1316. ;        AL = The Color (returned on reads, sent on writes)
  1317. ;        CX = The X-Location of the Pixel
  1318. ;        DX = The Y-Location of the Pixel
  1319.  
  1320. nullwrite    proc    near        ; "do-nothing" write
  1321.     ret
  1322. nullwrite    endp
  1323.  
  1324. nullread    proc    near        ; "do-nothing" read
  1325.     mov    ax,0            ; "return" black pixels
  1326.     ret
  1327. nullread    endp
  1328.  
  1329. normalwrite    proc    near        ; generic write-a-dot routine
  1330.     mov    ah,12            ; write the dot (al == color)
  1331.     mov    bx,0            ; this page
  1332.     push    bp            ; some BIOS's don't save this
  1333.     int    10h            ; do it.
  1334.     pop    bp            ; restore the saved register
  1335.     ret                ; we done.
  1336. normalwrite    endp
  1337.  
  1338. normalread    proc    near        ; generic read-a-dot routine
  1339.     mov    ah,13            ; read the dot (al == color)
  1340.     mov    bx,0            ; this page
  1341.     push    bp            ; some BIOS's don't save this
  1342.     int    10h            ; do it.
  1343.     pop    bp            ; restore the saved register
  1344.     ret                ; we done.
  1345. normalread    endp
  1346.  
  1347. mcgawrite    proc    near        ; MCGA 320*200, 246 colors
  1348.     xchg    dh,dl            ; bx := 256*y
  1349.     mov    bx,cx            ; bx := x
  1350.     add    bx,dx            ; bx := 256*y + x
  1351.     shr    dx,1
  1352.     shr    dx,1            ; dx := 64*y
  1353.     add    bx,dx            ; bx := 320*y + x
  1354.     mov    es:[bx],al        ; write the dot
  1355.     ret                ; we done.
  1356. mcgawrite    endp
  1357.  
  1358. mcgaread    proc    near        ; MCGA 320*200, 246 colors
  1359.     xchg    dh,dl            ; dx := 256*y
  1360.     mov    bx,cx            ; bx := x
  1361.     add    bx,dx            ; bx := 256*y + x
  1362.     shr    dx,1
  1363.     shr    dx,1            ; dx := 64*y
  1364.     add    bx,dx            ; bx := 320*y + x
  1365.     mov    al,es:[bx]        ; retrieve the previous value
  1366.     ret                ; we done.
  1367. mcgaread    endp
  1368.  
  1369. ;    These routines are for bit-plane 16 color modes, including bank
  1370. ;    switched superVGA varieties such as the Tseng 1024x768x16 mode.
  1371. ;        Tim Wegner
  1372. ;
  1373. vgawrite    proc    near        ; bank-switched EGA/VGA write mode 0
  1374.     mov    bh,al            ; save the color value for a bit
  1375.     mov    ax,vxdots        ; this many dots / line
  1376.     mul    dx            ; times this many lines
  1377.     add    ax,cx            ; plus this many x-dots
  1378.     adc    dx,0            ; DX:AX now holds the pixel count
  1379.     mov    cx,ax            ; save this for the bit mask
  1380.     and    cx,7            ; bit-mask shift calculation
  1381.     xor    cl,7            ;  ...
  1382.     mov    si,ax            ; set up for the address shift
  1383.     shr    dx,1            ; (ugly) 32-bit shift-by-3 logic
  1384.     rcr    si,1            ;  ((works on ANY 80x6 processor))
  1385.     shr    dx,1            ;  ...
  1386.     rcr    si,1            ;  ...
  1387.     shr    dx,1            ;  ...
  1388.     rcr    si,1            ;  ...
  1389.  
  1390.     cmp    dx,curbk        ; see if bank changed
  1391.     je    vgasame_bank        ; jump if old bank ok
  1392.     mov    ax,dx            ; newbank expects bank in al
  1393.     call    far ptr newbank     ; switch banks
  1394. vgasame_bank:
  1395.  
  1396.     mov    dx,03ceh        ; graphics controller address
  1397.     mov    ax,0108h        ; set up controller bit mask register
  1398.     shl    ah,cl            ;  ...
  1399.     out    dx,ax            ;  ...
  1400.     mov    ah,bh            ; set set/reset registers
  1401.     mov    al,0            ;  ...
  1402.     out    dx,ax            ;  ...
  1403.     mov    ax,0f01h        ; enable set/reset registers
  1404.     out    dx,ax            ;  ...
  1405.     or    es:[si],al        ; update all bit planes
  1406.     ret                ; we done.
  1407. vgawrite    endp
  1408.  
  1409. vgaread proc    near        ; bank-switched EGA/VGA read mode 0
  1410.     mov    ax,vxdots        ; this many dots / line
  1411.     mul    dx            ; times this many lines
  1412.     add    ax,cx            ; plus this many x-dots
  1413.     adc    dx,0            ; DX:AX now holds the pixel count
  1414.     mov    cx,ax            ; save this for the bit mask
  1415.     and    cx,7            ; bit-mask shift calculation
  1416.     xor    cl,7            ;  ...
  1417.     mov    si,ax            ; set up for the address shift
  1418.     shr    dx,1            ; (ugly) 32-bit shift-by-3 logic
  1419.     rcr    si,1            ;  ((works on ANY 80x6 processor))
  1420.     shr    dx,1            ;  ...
  1421.     rcr    si,1            ;  ...
  1422.     shr    dx,1            ;  ...
  1423.     rcr    si,1            ;  ...
  1424.  
  1425.     cmp    dx,curbk        ; see if bank changed
  1426.     je    vgasame_bank        ; jump if old bank ok
  1427.     mov    ax,dx            ; newbank expects bank in al
  1428.     call    far ptr newbank     ; switch banks
  1429. vgasame_bank:
  1430.  
  1431.     mov    ch,01h            ; bit mask to shift
  1432.     shl    ch,cl            ;  ...
  1433.     mov    bx,0            ; initialize bits-read value (none)
  1434.     mov    dx,03ceh        ; graphics controller address
  1435.     mov    ax,0304h        ; set up controller address register
  1436. vgareadloop:
  1437.     out    dx,ax            ; do it
  1438.     mov    bh,es:[si]        ; retrieve the old value
  1439.     and    bh,ch            ; mask one bit
  1440.     neg    bh            ; set bit 7 correctly
  1441.     rol    bx,1            ; rotate the bit into bl
  1442.     dec    ah            ; go for another bit?
  1443.     jge    vgareadloop        ;  sure, why not.
  1444.     mov    al,bl            ; returned pixel value
  1445.     ret                ; we done.
  1446. vgaread endp
  1447.  
  1448. outax8bit    proc    near        ; convert OUT DX,AX to
  1449.     push    ax            ; several OUT DX,ALs
  1450.     out    dx,al            ; (leaving registers intact)
  1451.     inc    dx
  1452.     mov    al,ah
  1453.     out    dx,al
  1454.     dec    dx
  1455.     pop    ax
  1456.     ret
  1457. outax8bit    endp
  1458.  
  1459.  
  1460. ; --------------------------------------------------------------------------
  1461.  
  1462. ; new Tandy and CGA code from Joseph Albrecht
  1463.  
  1464.         align    2
  1465. ;Scan line address table for 16K video memory
  1466. scan16k     dw    0000h,2000h,0050h,2050h,00A0h,20A0h,00F0h,20F0h
  1467.         dw    0140h,2140h,0190h,2190h,01E0h,21E0h,0230h,2230h
  1468.         dw    0280h,2280h,02D0h,22D0h,0320h,2320h,0370h,2370h
  1469.         dw    03C0h,23C0h,0410h,2410h,0460h,2460h,04B0h,24B0h
  1470.         dw    0500h,2500h,0550h,2550h,05A0h,25A0h,05F0h,25F0h
  1471.         dw    0640h,2640h,0690h,2690h,06E0h,26E0h,0730h,2730h
  1472.         dw    0780h,2780h,07D0h,27D0h,0820h,2820h,0870h,2870h
  1473.         dw    08C0h,28C0h,0910h,2910h,0960h,2960h,09B0h,29B0h
  1474.         dw    0A00h,2A00h,0A50h,2A50h,0AA0h,2AA0h,0AF0h,2AF0h
  1475.         dw    0B40h,2B40h,0B90h,2B90h,0BE0h,2BE0h,0C30h,2C30h
  1476.         dw    0C80h,2C80h,0CD0h,2CD0h,0D20h,2D20h,0D70h,2D70h
  1477.         dw    0DC0h,2DC0h,0E10h,2E10h,0E60h,2E60h,0EB0h,2EB0h
  1478.         dw    0F00h,2F00h,0F50h,2F50h,0FA0h,2FA0h,0FF0h,2FF0h
  1479.         dw    1040h,3040h,1090h,3090h,10E0h,30E0h,1130h,3130h
  1480.         dw    1180h,3180h,11D0h,31D0h,1220h,3220h,1270h,3270h
  1481.         dw    12C0h,32C0h,1310h,3310h,1360h,3360h,13B0h,33B0h
  1482.         dw    1400h,3400h,1450h,3450h,14A0h,34A0h,14F0h,34F0h
  1483.         dw    1540h,3540h,1590h,3590h,15E0h,35E0h,1630h,3630h
  1484.         dw    1680h,3680h,16D0h,36D0h,1720h,3720h,1770h,3770h
  1485.         dw    17C0h,37C0h,1810h,3810h,1860h,3860h,18B0h,38B0h
  1486.         dw    1900h,3900h,1950h,3950h,19A0h,39A0h,19F0h,39F0h
  1487.         dw    1A40h,3A40h,1A90h,3A90h,1AE0h,3AE0h,1B30h,3B30h
  1488.         dw    1B80h,3B80h,1BD0h,3BD0h,1C20h,3C20h,1C70h,3C70h
  1489.         dw    1CC0h,3CC0h,1D10h,3D10h,1D60h,3D60h,1DB0h,3DB0h
  1490.         dw    1E00h,3E00h,1E50h,3E50h,1EA0h,3EA0h,1EF0h,3EF0h
  1491.  
  1492. ;Scan line address table for 32K video memory
  1493. scan32k     dw    0000h,2000h,4000h,6000h,00a0h,20a0h,40a0h,60a0h
  1494.         dw    0140h,2140h,4140h,6140h,01e0h,21e0h,41e0h,61e0h
  1495.         dw    0280h,2280h,4280h,6280h,0320h,2320h,4320h,6320h
  1496.         dw    03c0h,23c0h,43c0h,63c0h,0460h,2460h,4460h,6460h
  1497.         dw    0500h,2500h,4500h,6500h,05a0h,25a0h,45a0h,65a0h
  1498.         dw    0640h,2640h,4640h,6640h,06e0h,26e0h,46e0h,66e0h
  1499.         dw    0780h,2780h,4780h,6780h,0820h,2820h,4820h,6820h
  1500.         dw    08c0h,28c0h,48c0h,68c0h,0960h,2960h,4960h,6960h
  1501.         dw    0a00h,2a00h,4a00h,6a00h,0aa0h,2aa0h,4aa0h,6aa0h
  1502.         dw    0b40h,2b40h,4b40h,6b40h,0be0h,2be0h,4be0h,6be0h
  1503.         dw    0c80h,2c80h,4c80h,6c80h,0d20h,2d20h,4d20h,6d20h
  1504.         dw    0dc0h,2dc0h,4dc0h,6dc0h,0e60h,2e60h,4e60h,6e60h
  1505.         dw    0f00h,2f00h,4f00h,6f00h,0fa0h,2fa0h,4fa0h,6fa0h
  1506.         dw    1040h,3040h,5040h,7040h,10e0h,30e0h,50e0h,70e0h
  1507.         dw    1180h,3180h,5180h,7180h,1220h,3220h,5220h,7220h
  1508.         dw    12c0h,32c0h,52c0h,72c0h,1360h,3360h,5360h,7360h
  1509.         dw    1400h,3400h,5400h,7400h,14a0h,34a0h,54a0h,74a0h
  1510.         dw    1540h,3540h,5540h,7540h,15e0h,35e0h,55e0h,75e0h
  1511.         dw    1680h,3680h,5680h,7680h,1720h,3720h,5720h,7720h
  1512.         dw    17c0h,37c0h,57c0h,77c0h,1860h,3860h,5860h,7860h
  1513.         dw    1900h,3900h,5900h,7900h,19a0h,39a0h,59a0h,79a0h
  1514.         dw    1a40h,3a40h,5a40h,7a40h,1ae0h,3ae0h,5ae0h,7ae0h
  1515.         dw    1b80h,3b80h,5b80h,7b80h,1c20h,3c20h,5c20h,7c20h
  1516.         dw    1cc0h,3cc0h,5cc0h,7cc0h,1d60h,3d60h,5d60h,7d60h
  1517.         dw    1e00h,3e00h,5e00h,7e00h,1ea0h,3ea0h,5ea0h,7ea0h
  1518.  
  1519. ;Scan line address table for 64K video memory
  1520. scan64k     dw    00000h,00140h,00280h,003c0h,00500h,00640h,00780h,008c0h
  1521.         dw    00a00h,00b40h,00c80h,00dc0h,00f00h,01040h,01180h,012c0h
  1522.         dw    01400h,01540h,01680h,017c0h,01900h,01a40h,01b80h,01cc0h
  1523.         dw    01e00h,01f40h,02080h,021c0h,02300h,02440h,02580h,026c0h
  1524.         dw    02800h,02940h,02a80h,02bc0h,02d00h,02e40h,02f80h,030c0h
  1525.         dw    03200h,03340h,03480h,035c0h,03700h,03840h,03980h,03ac0h
  1526.         dw    03c00h,03d40h,03e80h,03fc0h,04100h,04240h,04380h,044c0h
  1527.         dw    04600h,04740h,04880h,049c0h,04b00h,04c40h,04d80h,04ec0h
  1528.         dw    05000h,05140h,05280h,053c0h,05500h,05640h,05780h,058c0h
  1529.         dw    05a00h,05b40h,05c80h,05dc0h,05f00h,06040h,06180h,062c0h
  1530.         dw    06400h,06540h,06680h,067c0h,06900h,06a40h,06b80h,06cc0h
  1531.         dw    06e00h,06f40h,07080h,071c0h,07300h,07440h,07580h,076c0h
  1532.         dw    07800h,07940h,07a80h,07bc0h,07d00h,07e40h,07f80h,080c0h
  1533.         dw    08200h,08340h,08480h,085c0h,08700h,08840h,08980h,08ac0h
  1534.         dw    08c00h,08d40h,08e80h,08fc0h,09100h,09240h,09380h,094c0h
  1535.         dw    09600h,09740h,09880h,099c0h,09b00h,09c40h,09d80h,09ec0h
  1536.         dw    0a000h,0a140h,0a280h,0a3c0h,0a500h,0a640h,0a780h,0a8c0h
  1537.         dw    0aa00h,0ab40h,0ac80h,0adc0h,0af00h,0b040h,0b180h,0b2c0h
  1538.         dw    0b400h,0b540h,0b680h,0b7c0h,0b900h,0ba40h,0bb80h,0bcc0h
  1539.         dw    0be00h,0bf40h,0c080h,0c1c0h,0c300h,0c440h,0c580h,0c6c0h
  1540.         dw    0c800h,0c940h,0ca80h,0cbc0h,0cd00h,0ce40h,0cf80h,0d0c0h
  1541.         dw    0d200h,0d340h,0d480h,0d5c0h,0d700h,0d840h,0d980h,0dac0h
  1542.         dw    0dc00h,0dd40h,0de80h,0dfc0h,0e100h,0e240h,0e380h,0e4c0h
  1543.         dw    0e600h,0e740h,0e880h,0e9c0h,0eb00h,0ec40h,0ed80h,0eec0h
  1544.         dw    0f000h,0f140h,0f280h,0f3c0h,0f500h,0f640h,0f780h,0f8c0h
  1545.  
  1546. ;
  1547. ; ***** CGA Video Routines *****
  1548. ;
  1549.  
  1550. ;plot a point on 320x200x4 color graphics screen
  1551. plotcga4    proc    near
  1552.  
  1553.     mov    bx,0b800h        ;point es at video buffer
  1554.     mov    es,bx            ; ..
  1555.     mov    bx,dx            ;get scan line address
  1556.     shl    bx,1            ; ..
  1557.     mov    bx,cs:scan16k[bx]    ; ..
  1558.     mov    ah,cl            ;save low byte of column
  1559.     shr    cx,1            ;get column offset
  1560.     shr    cx,1            ; ..
  1561.     add    bx,cx            ;add column offset to address
  1562.     not    ah            ;get shift count
  1563.     and    ah,3            ; ..
  1564.     shl    ah,1            ; ..
  1565.     mov    cl,ah            ; ..
  1566.     and    al,3            ;mask off unwanted bits
  1567.     rol    al,cl            ;get or mask
  1568.     mov    ah,0fch         ;get and mask
  1569.     rol    ah,cl            ; ..
  1570.     mov    cl,es:[bx]        ;plot the point
  1571.     and    cl,ah            ; ..
  1572.     or    cl,al            ; ..
  1573.     mov    es:[bx],cl        ; ..
  1574.     ret
  1575.  
  1576. plotcga4    endp
  1577.  
  1578. ;return a point from 320x200x4 color graphics screen
  1579. getcga4     proc    near
  1580.  
  1581.     mov    bx,0b800h        ;point es at video buffer
  1582.     mov    es,bx            ; ..
  1583.     mov    bx,dx            ;get scan line address
  1584.     shl    bx,1            ; ..
  1585.     mov    bx,cs:scan16k[bx]    ; ..
  1586.     mov    ax,cx            ;save column
  1587.     shr    ax,1            ;get column offset
  1588.     shr    ax,1            ; ..
  1589.     add    bx,ax            ;add column offset to address
  1590.     not    cl            ;get shift count
  1591.     and    cl,3            ; ..
  1592.     shl    cl,1            ; ..
  1593.     mov    al,es:[bx]        ;return the point
  1594.     ror    al,cl            ; ..
  1595.     and    ax,3            ; ..
  1596.     ret
  1597.  
  1598. getcga4     endp
  1599.  
  1600. ;plot a point on 640x200x2 color graphics screen
  1601. plotcga2    proc    near
  1602.  
  1603.     mov    bx,0b800h        ;point es at video buffer
  1604.     mov    es,bx            ; ..
  1605.     mov    bx,dx            ;get scan line address
  1606.     shl    bx,1            ; ..
  1607.     mov    bx,cs:scan16k[bx]    ; ..
  1608.     mov    ah,cl            ;save low order byte of column
  1609.     shr    cx,1            ;get column offset
  1610.     shr    cx,1            ; ..
  1611.     shr    cx,1            ; ..
  1612.     add    bx,cx            ;add column offset to address
  1613.     not    ah            ;get shift count
  1614.     and    ah,7            ; ..
  1615.     mov    cl,ah            ; ..
  1616.     and    al,1            ;mask off unwanted bits
  1617.     rol    al,cl            ;get or mask
  1618.     mov    ah,0feh         ;get and mask
  1619.     rol    ah,cl            ; ..
  1620.     mov    cl,es:[bx]        ;plot the point
  1621.     and    cl,ah            ; ..
  1622.     or    cl,al            ; ..
  1623.     mov    es:[bx],cl        ; ..
  1624.     ret
  1625.  
  1626. plotcga2    endp
  1627.  
  1628. ;return a point from 640x200x2 color graphics screen
  1629. getcga2     proc    near
  1630.  
  1631.     mov    bx,0b800h        ;point es at video buffer
  1632.     mov    es,bx            ; ..
  1633.     mov    bx,dx            ;get scan line address
  1634.     shl    bx,1            ; ..
  1635.     mov    bx,cs:scan16k[bx]    ; ..
  1636.     mov    ax,cx            ;save column
  1637.     shr    ax,1            ;get column offset
  1638.     shr    ax,1            ; ..
  1639.     shr    ax,1            ; ..
  1640.     add    bx,ax            ;add column offset to address
  1641.     not    cl            ;get shift count
  1642.     and    cl,7            ; ..
  1643.     mov    al,es:[bx]        ;return the point
  1644.     ror    al,cl            ; ..
  1645.     and    ax,1            ; ..
  1646.     ret
  1647.  
  1648. getcga2     endp
  1649.  
  1650. ;
  1651. ; ***** Tandy 1000 Video Routines *****
  1652. ;
  1653.  
  1654. ;plot a point on tandy 1000 640x200x4 color graphics screen
  1655. plottandy4    proc    near
  1656.  
  1657.     mov    bx,0b800h        ;point es at video segment
  1658.     mov    es,bx            ; ..
  1659.     mov    bx,dx            ;get scan line address
  1660.     shl    bx,1            ; ..
  1661.     mov    bx,cs:scan32k[bx]    ; ..
  1662.     mov    dx,cx            ;save column
  1663.     shr    dx,1            ;get column offset
  1664.     shr    dx,1            ; ..
  1665.     and    dl,0feh         ; ..
  1666.     add    bx,dx            ;add column offset to address
  1667.     not    cl            ;get shift count
  1668.     and    cl,7            ; ..
  1669.     mov    ah,al            ;get or mask
  1670.     shr    ah,1            ; ..
  1671.     and    ax,101h         ; ..
  1672.     rol    ax,cl            ; ..
  1673.     mov    dx,0fefeh        ;get and mask
  1674.     rol    dx,cl            ; ..
  1675.     mov    cx,es:[bx]        ;plot the point
  1676.     and    cx,dx            ; ..
  1677.     or    cx,ax            ; ..
  1678.     mov    es:[bx],cx        ; ..
  1679.     ret
  1680.  
  1681. plottandy4    endp
  1682.  
  1683. ;return a point from tandy 1000 640x200x4 color graphics screen
  1684. gettandy4    proc    near
  1685.  
  1686.     mov    bx,0b800h        ;point es at video segment
  1687.     mov    es,bx            ; ..
  1688.     mov    bx,dx            ;get scan line address
  1689.     shl    bx,1            ; ..
  1690.     mov    bx,cs:scan32k[bx]    ; ..
  1691.     mov    ax,cx            ;save column
  1692.     shr    ax,1            ;get column offset
  1693.     shr    ax,1            ; ..
  1694.     and    al,0feh         ; ..
  1695.     add    bx,ax            ;add column offset to address
  1696.     not    cl            ;get shift count
  1697.     and    cl,7            ; ..
  1698.     mov    ax,es:[bx]        ;return the point
  1699.     ror    ax,cl            ; ..
  1700.     and    ax,101h         ; ..
  1701.     rol    ah,1            ; ..
  1702.     or    al,ah            ; ..
  1703.     and    ax,3            ; ..
  1704.     ret
  1705.  
  1706. gettandy4    endp
  1707.  
  1708. ;plot a point on tandy 1000 16 color graphics screen
  1709. plottandy16    proc    near
  1710.  
  1711.     mov    es,tandyseg        ;point es at video buffer
  1712.     mov    bx,dx            ;get scan line address
  1713.     shl    bx,1            ; ..
  1714.     add    bx,tandyscan        ; ..
  1715.     mov    bx,cs:[bx]        ; ..
  1716.     mov    ah,0f0h         ;set mask for odd pixel
  1717.     mov    dx,cx            ;save x
  1718.     shr    dx,1            ;get column offset
  1719.     jc    plottandy16a        ;check for odd/even pixel
  1720.     not    ah            ;set mask for even pixel
  1721.     mov    cl,4            ;move color to proper pobxtion
  1722.     shl    al,cl            ; ..
  1723. plottandy16a:
  1724.     add    bx,dx            ;add column offset to address
  1725.     mov    dl,es:[bx]        ;plot the point
  1726.     and    dl,ah            ; ..
  1727.     or    dl,al            ; ..
  1728.     mov    es:[bx],dl        ; ..
  1729.     ret
  1730.  
  1731. plottandy16    endp
  1732.  
  1733. ;return a point from tandy 1000 16 color graphics mode
  1734. gettandy16    proc    near
  1735.  
  1736.     mov    es,tandyseg        ;point es at video buffer
  1737.     mov    bx,dx            ;get scan line address
  1738.     shl    bx,1            ; ..
  1739.     add    bx,tandyscan        ; ..
  1740.     mov    bx,cs:[bx]        ; ..
  1741.     mov    dx,cx            ;save x
  1742.     shr    cx,1            ;add column offset to address
  1743.     add    bx,cx            ; ..
  1744.     mov    al,es:[bx]        ;get pixel
  1745.     test    dl,1            ;check for odd/even pixel
  1746.     jnz    gettandy16a        ; ..
  1747.     mov    cl,4            ;move color to proper position
  1748.     shr    al,cl            ; ..
  1749. gettandy16a:
  1750.     and    ax,0fh            ;mask off unwanted bits
  1751.     ret
  1752.  
  1753. gettandy16    endp
  1754.  
  1755. ;setup tandy 1000 640x200x16 color mode
  1756. tandysetup    proc    near
  1757.     mov    dx,03d4h        ; write to this address
  1758.     mov    ax,07100h        ; write to this register and value
  1759.     call    tandyport        ;  do it.
  1760.     mov    ax,05001h        ; write to this register and value
  1761.     call    tandyport        ;  do it.
  1762.     mov    ax,05a02h        ; write to this register and value
  1763.     call    tandyport        ;  do it.
  1764.     mov    ax,00e03h        ; write to this register and value
  1765.     call    tandyport        ;  do it.
  1766.     mov    ax,0ff04h        ; write to this register and value
  1767.     call    tandyport        ;  do it.
  1768.     mov    ax,00605h        ; write to this register and value
  1769.     call    tandyport        ;  do it.
  1770.     mov    ax,0c806h        ; write to this register and value
  1771.     call    tandyport        ;  do it.
  1772.     mov    ax,0e207h        ; write to this register and value
  1773.     call    tandyport        ;  do it.
  1774.     mov    ax,00009h        ; write to this register and value
  1775.     call    tandyport        ;  do it.
  1776.     mov    ax,0000ch        ; write to this register and value
  1777.     call    tandyport        ;  do it.
  1778.     mov    ax,01810h        ; write to this register and value
  1779.     call    tandyport        ;  do it.
  1780.     mov    ax,04612h        ; write to this register and value
  1781.     call    tandyport        ;  do it.
  1782.     mov    dx,03d8h        ; new port
  1783.     mov    al,01bh         ;  and value
  1784.     out    dx,al            ;  do it.
  1785.     mov    dx,03d9h        ; new port
  1786.     mov    al,000h         ;  and value
  1787.     out    dx,al            ;  do it.
  1788.     mov    dx,03ddh        ; new port
  1789.     mov    al,000h         ;  and value
  1790.     out    dx,al            ;  do it.
  1791.     mov    dx,03dfh        ; new port
  1792.     mov    al,024h         ;  and value
  1793.     out    dx,al            ;  do it.
  1794.     mov    dx,03dah        ; new port
  1795.     mov    al,001h         ;  and value
  1796.     out    dx,al            ;  do it.
  1797.     mov    dx,03deh        ; new port
  1798.     mov    al,00fh         ;  and value
  1799.     out    dx,al            ;  do it.
  1800.     mov    dx,03dah        ; new port
  1801.     mov    al,002h         ;  and value
  1802.     out    dx,al            ;  do it.
  1803.     mov    dx,03deh        ; new port
  1804.     mov    al,000h         ;  and value
  1805.     out    dx,al            ;  do it.
  1806.     mov    dx,03dah        ; new port
  1807.     mov    al,003h         ;  and value
  1808.     out    dx,al            ;  do it.
  1809.     mov    dx,03deh        ; new port
  1810.     mov    al,010h         ;  and value
  1811.     out    dx,al            ;  do it.
  1812.     mov    dx,03dah        ; new port
  1813.     mov    al,005h         ;  and value
  1814.     out    dx,al            ;  do it.
  1815.     mov    dx,03deh        ; new port
  1816.     mov    al,001h         ;  and value
  1817.     out    dx,al            ;  do it.
  1818.     mov    dx,03dah        ; new port
  1819.     mov    al,008h         ;  and value
  1820.     out    dx,al            ;  do it.
  1821.     mov    dx,03deh        ; new port
  1822.     mov    al,002h         ;  and value
  1823.     out    dx,al            ;  do it.
  1824.  
  1825. ;set color palette registers to default state
  1826.     mov    cx,16            ;reset colors 0-15 to default state
  1827.     xor    bh,bh            ;set initial color
  1828.     xor    bl,bl            ;set initial paletter register
  1829.     mov    di,2            ;reset border color
  1830.     call    settandypal        ; ..
  1831. tandysetup1:
  1832.     mov    di,16            ;port offset for palette registers
  1833.     call    settandypal        ;set palette register
  1834.     inc    bl            ;bump up to next palette register
  1835.     inc    bh            ;bump up to next color
  1836.     loop    tandysetup1        ;do remaining palette registers
  1837.  
  1838.     cmp    orvideo,0        ; are we supposed to clear RAM?
  1839.     jne    tandysetup2        ;  (nope)
  1840.     push    es            ; save ES for a tad
  1841.     mov    ax,0a000h        ; clear the memory
  1842.     mov    es,ax            ;  ...
  1843.     cld                ; string ops forward
  1844.     mov    cx,07d00h        ; this many words
  1845.     mov    di,0            ; starting here
  1846.     mov    ax,0            ; clear out to zero
  1847.     rep    stosw            ; do it.
  1848.     pop    es            ; restore ES
  1849. tandysetup2:
  1850.     mov    oktoprint,0        ; no printing in this mode
  1851.     ret
  1852.  
  1853. tandysetup    endp
  1854.  
  1855. ;write data to 6845 registers
  1856. tandyport    proc    near
  1857.  
  1858.     out    dx,al            ;write 6845 reg number to port 3d4
  1859.     mov    al,ah            ;write 6845 reg data to port 3d5
  1860.     inc    dx            ; ..
  1861.     out    dx,al            ; ..
  1862.     dec    dx            ;point back to port 3d4
  1863.     ret
  1864.  
  1865. tandyport    endp
  1866.  
  1867. ;subroutine to set a Tandy 1000 palette register
  1868. settandypal    proc    near
  1869.     mov    dx,3dah         ;address & status register
  1870.     cli                ;disable interrupts
  1871. settandypal2:
  1872.     in    al,dx            ;get status register
  1873.     and    al,8            ;look for bit 3
  1874.     jz    settandypal2        ;wait for vertical retrace
  1875.     mov    al,bl            ;get palette number
  1876.     cbw                ; ..
  1877.     add    ax,di            ;add offset for palette register
  1878.     out    dx,al            ;set palette
  1879.     mov    al,bh            ;get color to store
  1880.     mov    dx,3deh         ;palette data register
  1881.     out    dx,al            ;set palette color
  1882.     mov    dx,3dah         ;address & status register
  1883.     xor    ax,ax            ;al = 0 to reset address register
  1884.     out    dx,al            ;reset it
  1885.     sti                ;re-enable interrupts
  1886.     ret
  1887.  
  1888. settandypal    endp
  1889.  
  1890. ; -----------------------------------------------------------------------------
  1891.  
  1892.  
  1893. ;    The 360x480 mode draws heavily on Michael Abrash's article in
  1894. ;    the January/February 1989 "Programmer's Journal" and files uploaded
  1895. ;    to Compuserv's PICS forum by Dr. Lawrence Gozum - integrated here
  1896. ;    by Timothy Wegner
  1897.  
  1898. ; Michael Abrash equates. Not all used, but I'll leave for reference.
  1899.  
  1900. VGA_SEGMENT      EQU    0A000h
  1901. SC_INDEX      EQU    3C4h     ;Sequence Controller Index register
  1902. GC_INDEX      EQU    3CEh     ;Graphics Controller Index register
  1903. CRTC_INDEX      EQU    3D4h     ;CRT Controller Index register
  1904. MAP_MASK      EQU    2     ;Map Mask register index in SC
  1905. MEMORY_MODE      EQU    4     ;Memory Mode register in SC
  1906. MAX_SCAN_LINE      EQU    9     ;Maximum Scan Line reg index in CRTC
  1907.                  ;Use 9 for 2 pages of 320x400
  1908. ;MAX_SCAN_LINE      EQU    1     ;Use 1 for 4 pages of 320x200
  1909. START_ADD_HIGH      EQU    0Ch     ;Start Address High reg index in CRTC
  1910. UNDERLINE      EQU    14h     ;Underline Location reg index in CRTC
  1911. MODE_CONTROL      EQU    17h     ;Mode Control reg index in CRTC
  1912. READ_MAP      EQU    4     ;Read Mask register index in SC
  1913. GRAPHICS_MODE      EQU    5     ;Graphics Mode register index in SC
  1914. MISC          EQU    6     ;Miscellaneous register index in SC
  1915. WORD_OUTS_OK      EQU    1     ;set to 0 to assemble for computers
  1916.                  ;that can't handle word outs to indexed
  1917.                  ;VGA registers
  1918. ;
  1919. ;Macro to output a word value to a port
  1920. ;
  1921. OUT_WORD MACRO
  1922. IF WORD_OUTS_OK
  1923.      OUT      DX,AX
  1924. ELSE
  1925.      OUT      DX,AL
  1926.      INC      DX
  1927.      XCHG      AH,AL
  1928.      OUT      DX,AL
  1929.      DEC      DX
  1930.      XCHG      AH,AL
  1931. ENDIF
  1932.      ENDM
  1933.  
  1934. ;Macro to ouput a constant value to an indexed VGA register
  1935. CONSTANT_TO_INDEXED_REGISTER     MACRO    ADDRESS,INDEX,VALUE
  1936.      MOV      DX,ADDRESS
  1937.      MOV      AX,(VALUE SHL 8)+INDEX
  1938.      OUT_WORD
  1939.      ENDM
  1940.  
  1941. tweak256read    proc near uses si    ; Tweaked-VGA ...x256 color mode
  1942.  
  1943.   mov      ax,vxdots
  1944. ;;  shr   ax,1
  1945. ;;  shr   ax,1             ; now ax = vxdots/4
  1946.   mul      dx             ;Point to start of desired row
  1947.   push      cx             ;Save X coordinate for later
  1948.   shr      cx,1             ;There are 4 pixels at each address
  1949.   shr      cx,1             ;so divide X by 4
  1950.   add      ax,cx          ;Point to pixels address
  1951.   mov      si,ax
  1952.   pop      ax             ;Retrieve X coordinate
  1953.   and      al,3             ;Get the plane number of the pixel
  1954.   mov      ah,al
  1955.   mov      al,READ_MAP
  1956.   mov      dx,GC_INDEX
  1957.   OUT_WORD             ;Set to write to the proper plane for the
  1958.                  ;pixel
  1959.   xor      ax,ax
  1960.   lods      byte ptr es:[si]     ;Read the pixel
  1961.   ret
  1962.  
  1963. tweak256read    endp
  1964.  
  1965. tweak256write    proc near uses di    ; Tweaked-VGA ...x256 color mode
  1966.   mov      bl,al         ; color
  1967.   mov      ax,vxdots
  1968. ;;  shr   ax, 1
  1969. ;;  shr   ax, 1          ; now ax = vxdots/4
  1970.   mul      dx            ;Point to start of desired row
  1971.   push      cx            ;Save X coordinate for later
  1972.   shr      cx,1            ;There are 4 pixels at each address
  1973.   shr      cx,1            ;so divide X by 4
  1974.   add      ax,cx         ;Point to pixels address
  1975.   mov      di,ax
  1976.   pop      cx            ;Retrieve X coordinate
  1977.   and      cl,3            ;Get the plane number of the pixel
  1978.   mov      ah,1
  1979.   shl      ah,cl         ;Set the bit corresponding to the plane
  1980.                 ;the pixel is in
  1981.   mov      al,MAP_MASK
  1982.   mov      dx,SC_INDEX
  1983.   OUT_WORD             ;Set to write to the proper plane for the
  1984.                  ;pixel
  1985.   mov      es:[di],bl         ;Draw the pixel
  1986.  
  1987.   ret
  1988. tweak256write    endp
  1989.  
  1990. ;    The following ATI 1024x768x16 mode is courtesy of Mark Peterson
  1991.  
  1992. ati1024read    proc near        ; ATI 1024x768x16 read
  1993.     call    ati1024addr        ; calculate the address
  1994.     mov    al,es:[bx]        ; get the byte the pixel is in
  1995.  
  1996.     cmp    xga_isinmode,0        ; say, is this really XGA-style I/O?
  1997.     je    notxga            ;  nope
  1998.     test    cl,1            ; is X odd?
  1999.     jnz    atireadhigh        ;  Yup.  Use the high bits
  2000.     jmp    short atireadlow    ;  else use the low bits
  2001. notxga:
  2002.  
  2003.     test    cl,1            ; is X odd?
  2004.     jz    atireadhigh        ;  Nope.  Use the high bits
  2005. atireadlow:
  2006.     and    ax,0fh            ; zero out the high-order bits
  2007.     ret
  2008. atireadhigh:
  2009.     and    ax,0f0h         ; zero out the low-order bits
  2010.     mov    cl,4            ; shift the results
  2011.     shr    al,cl            ;  ...
  2012.     ret
  2013. ati1024read    endp
  2014.  
  2015. ati1024write    proc near        ; ATI 1024x768x16 write
  2016.     call    ati1024addr        ; calculate the address
  2017.     mov    dl,es:[bx]        ; get the byte the pixel is in
  2018.     and    al,00fh         ; zero out the high-order color bits
  2019.  
  2020.     cmp    xga_isinmode,0        ; say, is this really XGA-style I/O?
  2021.     je    notxga            ;  nope
  2022.     test    cl,1            ; is X odd?
  2023.     jnz    atiwritehigh        ;  Yup.  Use the high bits
  2024.     jmp    short atiwritelow    ;  else use the low bits
  2025. notxga:
  2026.  
  2027.     test    cl,1            ; is X odd?
  2028.     jz    atiwritehigh        ;  Nope.  Use the high bits
  2029. atiwritelow:
  2030.     and    dl,0f0h         ; zero out the low-order video bits
  2031.     or    dl,al            ; add the two together
  2032.     mov    es:[bx],dl        ; and write the results
  2033.     ret
  2034. atiwritehigh:
  2035.     mov    cl,4            ; shift the color bits
  2036.     shl    al,cl            ;  ...
  2037.     and    dl,0fh            ; zero out the high-order video bits
  2038.     or    dl,al            ; add the two together
  2039.     mov    es:[bx],dl        ; and write the results
  2040.     ret
  2041. ati1024write    endp
  2042.  
  2043. ati1024addr    proc    near        ; modification of TIW's Super256addr
  2044.     clc                ; clear carry flag
  2045.     push    ax            ; save this for a tad
  2046.     mov    ax,vxdots        ; this many dots / line
  2047.     mul    dx            ; times this many lines - ans in dx:ax
  2048.     add    ax,cx            ; plus this many x-dots
  2049.     adc    dx,0            ; answer in dx:ax
  2050.     shr    dx,1            ; shift the answer right one bit
  2051.     rcr    ax,1            ;  .. in the 32-bit DX:AX combo
  2052.     mov    bx,ax            ; save this in BX
  2053.     cmp    dx,curbk        ; see if bank changed
  2054.     je    atisame_bank        ; jump if old bank ok
  2055.     mov    ax,dx            ; newbank expects bank in al
  2056.     call    far ptr newbank
  2057. atisame_bank:
  2058.     pop    ax            ; restore AX
  2059.     ret
  2060. ati1024addr    endp
  2061.  
  2062. ;
  2063. ;    The following 'Super256' code is courtesy of Timothy Wegner.
  2064. ;
  2065.  
  2066. super256write    proc near        ; super-VGA ...x256 colors write-a-dot
  2067.     call    super256addr        ; calculate address and switch banks
  2068.     mov    es:[bx],al        ; write the dot
  2069.     ret                ; we done.
  2070. super256write    endp
  2071.  
  2072. super256read    proc near        ; super-VGA ...x256 colors read-a-dot
  2073.     call    super256addr        ; calculate address and switch banks
  2074.     mov    al,es:[bx]        ; read the dot
  2075.     ret                ; we done.
  2076. super256read    endp
  2077.  
  2078. super256addr    proc near        ; can be put in-line but shared by
  2079.                     ; read and write routines
  2080.     clc                ; clear carry flag
  2081.     push    ax            ; save this for a tad
  2082.     mov    ax,vxdots        ; this many dots / line
  2083.     mul    dx            ; times this many lines - ans in dx:ax
  2084.     add    ax,cx            ; plus this many x-dots
  2085.     adc    dx,0            ; answer in dx:ax - dl=bank, ax=offset
  2086.     mov    bx,ax            ; save this in BX
  2087.     cmp    dx,curbk        ; see if bank changed
  2088.     je    same_bank        ; jump if old bank ok
  2089.     mov    ax,dx            ; newbank expects bank in al
  2090.     call    far ptr newbank
  2091. same_bank:
  2092.     pop    ax            ; restore AX
  2093.     ret
  2094. super256addr    endp
  2095.  
  2096. ;
  2097. ;    BANKS.ASM was used verbatim except:
  2098. ;       1) removed ".model small"
  2099. ;       2) deleted "end"
  2100. ;    Integrated by Tim Wegner 8/15/89
  2101. ;    (switched to John's 9/7/89 version on 9/10/89 - Bert)
  2102. ;    (switched to John's 1/5/90 version on 1/9/90  - Bert)
  2103. ;    (switched to John's version 3 on 4/27/90  - Bert)
  2104. ;    (added logic for various resolution on 9/10/90 - Bert)
  2105. ;    (upgraded to John's version 3.5 on 5/14/91 - Bert)
  2106. ;
  2107.  
  2108. ;    .MODEL medium,c
  2109.  
  2110. ;
  2111. ;    Copyright 1988,89,90,91 John Bridges
  2112. ;    Free for use in commercial, shareware or freeware applications
  2113. ;
  2114. ;    SVGAMODE.ASM
  2115. ;
  2116. .data
  2117.  
  2118. OSEG    equ    SS:            ;segment override for variable access
  2119.  
  2120. bankadr dw    offset $nobank
  2121. if @CodeSize
  2122. bankseg dw    seg $nobank
  2123. endif
  2124.  
  2125. vesa_bankswitch     dd    $vesa_nullbank ; initially, do-nothing
  2126. vesa_mapper        dd    $nobank
  2127. vesa_detect        dw    1    ; set to 0 to disable VESA-detection
  2128. vesa_gran_offset    dw    0
  2129. vesa_low_window     dw    0
  2130. vesa_high_window    dw    1
  2131. vesa_granularity    db    0    ; BDT VESA Granularity value
  2132.  
  2133.     public    curbk
  2134.  
  2135.         align    2
  2136. curbk    dw    0
  2137.  
  2138.     public    vga512, vga1024
  2139.  
  2140. vga512    dw    0
  2141. vga1024 dw    0
  2142.  
  2143.  
  2144.     public    cirrus,everex,paradise,tseng,trident,t8900
  2145.     public    ativga,aheada,aheadb,oaktech,video7
  2146.     public    chipstech,tseng4,genoa,ncr,compaq,vesa
  2147.  
  2148.     public    vesa        ; Bert
  2149. vesa    dw    0        ; Bert
  2150.  
  2151. cirrus    dw    0
  2152. video7    dw    0
  2153. tseng    dw    0
  2154. tseng4    dw    0
  2155. paradise dw    0
  2156. chipstech dw    0
  2157. trident dw    0
  2158. ativga    dw    0
  2159. everex    dw    0
  2160. aheada    dw    0
  2161. aheadb    dw    0
  2162. oaktech dw    0
  2163. t8900    dw    0
  2164. genoa    dw    0
  2165. ncr    dw    0
  2166. compaq    dw    0
  2167. xga    dw    0
  2168.  
  2169. done_detect dw    0        ;flag to call adapter_detect & whichvga once
  2170.  
  2171.         ; this part is new - Bert
  2172. .code
  2173.  
  2174. vesa_entries    dw    0
  2175.     dw     640, 400,256, 4f02h,100h
  2176.     dw     640, 480,256, 4f02h,101h
  2177.     dw     800, 600, 16, 4f02h,102h
  2178.     dw     800, 600,256, 4f02h,103h
  2179.     dw    1024, 768, 16, 4f02h,104h
  2180.     dw    1024, 768,256, 4f02h,105h
  2181.     dw    1280,1024, 16, 4f02h,106h
  2182.     dw    1280,1024,256, 4f02h,107h
  2183. ahead_entries    dw    0
  2184.     dw     800, 600, 16, 06ah,0
  2185.     dw     800, 600, 16, 071h,0
  2186.     dw    1024, 768, 16, 074h,0
  2187.     dw     640, 400,256, 060h,0
  2188.     dw     640, 480,256, 061h,0
  2189.     dw     800, 600,256, 062h,0
  2190.     dw    1024, 768,256, 063h,0
  2191. ati_entries    dw    0
  2192.     dw     800, 600, 16, 054h,0
  2193.     dw    1024, 768, 16, 065h,0ffh    ; (non-standard mode flag)
  2194.     dw     640, 400,256, 061h,0
  2195.     dw     640, 480,256, 062h,0
  2196.     dw     800, 600,256, 063h,0
  2197.     dw    1024, 768,256, 064h,0
  2198. chips_entries    dw    0
  2199.     dw     800, 600, 16, 070h,0
  2200.     dw    1024, 768, 16, 072h,0
  2201.     dw     640, 400,256, 078h,0
  2202.     dw     640, 480,256, 079h,0
  2203.     dw     800, 600,256, 07bh,0
  2204. compaq_entries    dw    0
  2205.     dw     640, 480,256, 02eh,0fdh    ; (non-standard mode flag)
  2206. everex_entries    dw    0
  2207.     dw     752, 410, 16, 070h,01h
  2208.     dw     800, 600, 16, 070h,02h
  2209.     dw    1280, 350,  4, 070h,11h
  2210.     dw    1280, 600,  4, 070h,12h
  2211.     dw     640, 350,256, 070h,13h
  2212.     dw     640, 400,256, 070h,14h
  2213.     dw     512, 480,256, 070h,15h
  2214.     dw    1024, 768, 16, 070h,20h
  2215.     dw     640, 480,256, 070h,30h
  2216.     dw     800, 600,256, 070h,31h
  2217. genoa_entries    dw    0
  2218.     dw    1024, 768,  4, 07fh,0
  2219.     dw     720, 512, 16, 059h,0
  2220.     dw     800, 600, 16, 079h,0
  2221.     dw    1024, 768, 16, 05fh,0
  2222.     dw     640, 350,256, 05bh,0
  2223.     dw     640, 400,256, 07eh,0
  2224.     dw     640, 480,256, 05ch,0
  2225.     dw     720, 512,256, 05dh,0
  2226.     dw     800, 600,256, 05eh,0
  2227. ncr_entries     dw    0
  2228.     dw    1024, 768,  2, 5ah,0
  2229.     dw     800, 600, 16, 58h,0
  2230.     dw    1024, 768, 16, 5dh,0
  2231.     dw     640, 400,256, 5eh,0
  2232.     dw     640, 480,256, 5fh,0
  2233.     dw     800, 600,256, 5ch,0
  2234.     dw    0
  2235. oaktech_entries dw    0
  2236.     dw     800, 600, 16, 52h,0
  2237.     dw     640, 480,256, 53h,0
  2238.     dw     800, 600,256, 54h,0
  2239.     dw    1024, 768, 16, 56h,0
  2240.     dw    0
  2241. paradise_entries    dw    0
  2242.     dw     800, 600,  2, 059h,0
  2243.     dw     800, 600, 16, 058h,0
  2244.     dw     640, 400,256, 05eh,0
  2245.     dw     640, 480,256, 05fh,0
  2246.     dw    1024, 768, 16, 05dh,0
  2247.     dw     800, 600,256, 05ch,0    ; Chuck Ebbert, 910524
  2248. trident_entries dw     0
  2249.     dw     1024, 768,  4, 060h,0
  2250.     dw    800, 600, 16, 05bh,0
  2251.     dw     1024, 768, 16, 05fh,0
  2252.     dw    640, 400,256, 05ch,0
  2253.     dw    640, 480,256, 05dh,0
  2254.     dw    800, 600,256, 05eh,0
  2255.     dw     1024, 768,256, 062h,0
  2256. tseng_entries    dw    0
  2257.     dw     800, 600, 16, 029h,0
  2258.     dw    1024, 768, 16, 037h,0
  2259.     dw     640, 350,256, 02dh,0
  2260.     dw     640, 400,256, 0,0feh    ; (non-standard mode flag)
  2261.     dw     640, 480,256, 02eh,0
  2262.     dw     720, 512,256, 02fh,0
  2263.     dw     800, 600,256, 030h,0
  2264.     dw    1024, 768,256, 038h,0
  2265. tseng4_entries    dw    0
  2266.     dw     800, 600, 16, 29h,0
  2267.     dw    1024, 768, 16, 37h,0
  2268.     dw     640, 350,256, 2dh,0
  2269.     dw     640, 400,256, 2fh,0
  2270.     dw     640, 480,256, 2eh,0
  2271.     dw     800, 600,256, 30h,0
  2272.     dw    1024, 768,256, 38h,0
  2273. video7_entries    dw    0
  2274.     dw     752, 410, 16, 6f05h,60h
  2275.     dw     720, 540, 16, 6f05h,61h
  2276.     dw     800, 600, 16, 6f05h,62h
  2277.     dw    1024, 768,  2, 6f05h,63h
  2278.     dw    1024, 768,  4, 6f05h,64h
  2279.     dw    1024, 768, 16, 6f05h,65h
  2280.     dw     640, 400,256, 6f05h,66h
  2281.     dw     640, 480,256, 6f05h,67h
  2282.     dw     720, 540,256, 6f05h,68h
  2283.     dw     800, 600,256, 6f05h,69h
  2284. xga_entries    dw    0
  2285.     dw    1024, 768,256,0ffffh,02h
  2286.     dw    1024, 768, 16,0ffffh,03h
  2287.     dw     640, 400,256,0ffffh,04h
  2288.     dw     640, 480,256,0ffffh,04h
  2289.     dw     800, 600, 16,0ffffh,06h
  2290.     dw     800, 600,256,0ffffh,07h
  2291. no_entries    dw    0
  2292.     dw     320, 200,256, 13h,0
  2293.     dw     640, 480, 16, 12h,0
  2294.     dw    0
  2295.  
  2296. .code
  2297.  
  2298. newbank proc            ;bank number is in AX
  2299.     cli
  2300.     mov    OSEG[curbk],ax
  2301. if @CodeSize
  2302.     call    dword ptr OSEG[bankadr]
  2303. else
  2304.     call    word ptr OSEG[bankadr]
  2305. endif
  2306.     ret
  2307. newbank endp
  2308.  
  2309. $tseng    proc        ;Tseng
  2310.     push    ax
  2311.     push    dx
  2312.     and    al,7
  2313.     mov    ah,al
  2314.     shl    ah,1
  2315.     shl    ah,1
  2316.     shl    ah,1
  2317.     or    al,ah
  2318.     or    al,01000000b
  2319.     mov    dx,3cdh
  2320.     out    dx,al
  2321.     sti
  2322.     pop    dx
  2323.     pop    ax
  2324.     ret
  2325. $tseng    endp
  2326.  
  2327. $tseng4 proc        ;Tseng 4000 series
  2328.     push    ax
  2329.     push    dx
  2330.     mov    ah,al
  2331.     mov    dx,3bfh         ;Enable access to extended registers
  2332.     mov    al,3
  2333.     out    dx,al
  2334.     mov    dl,0d8h
  2335.     mov    al,0a0h
  2336.     out    dx,al
  2337.     and    ah,15
  2338.     mov    al,ah
  2339.     shl    al,1
  2340.     shl    al,1
  2341.     shl    al,1
  2342.     shl    al,1
  2343.     or    al,ah
  2344.     mov    dl,0cdh
  2345.     out    dx,al
  2346.     sti
  2347.     pop    dx
  2348.     pop    ax
  2349.     ret
  2350. $tseng4 endp
  2351.  
  2352. $trident proc        ;Trident
  2353.     push    ax
  2354.     push    dx
  2355.     mov    dx,3ceh     ;set page size to 64k
  2356.     mov    al,6
  2357.     out    dx,al
  2358.     inc    dl
  2359.     in    al,dx
  2360.     dec    dl
  2361.     or    al,4
  2362.     mov    ah,al
  2363.     mov    al,6
  2364.     out    dx,ax
  2365.  
  2366.     mov    dl,0c4h     ;switch to BPS mode
  2367.     mov    al,0bh
  2368.     out    dx,al
  2369.     inc    dl
  2370.     in    al,dx
  2371.     dec    dl
  2372.  
  2373.     mov    ah,byte ptr OSEG[curbk]
  2374.     xor    ah,2
  2375.     mov    dx,3c4h
  2376.     mov    al,0eh
  2377.     out    dx,ax
  2378.     sti
  2379.     pop    dx
  2380.     pop    ax
  2381.     ret
  2382. $trident endp
  2383.  
  2384. $video7 proc        ;Video 7
  2385.     push    ax
  2386.     push    dx
  2387.     push    cx
  2388. ; Video-7 1024x768x16 mode patch (thanks to Frank Lozier 11/8/89).
  2389.     cmp    colors,16
  2390.     jne    video7xx
  2391.     shl    ax,1
  2392.     shl    ax,1
  2393. video7xx:
  2394.     and    ax,15
  2395.     mov    ch,al
  2396.     mov    dx,3c4h
  2397.     mov    ax,0ea06h
  2398.     out    dx,ax
  2399.     mov    ah,ch
  2400.     and    ah,1
  2401.     mov    al,0f9h
  2402.     out    dx,ax
  2403.     mov    al,ch
  2404.     and    al,1100b
  2405.     mov    ah,al
  2406.     shr    ah,1
  2407.     shr    ah,1
  2408.     or    ah,al
  2409.     mov    al,0f6h
  2410.     out    dx,al
  2411.     inc    dx
  2412.     in    al,dx
  2413.     dec    dx
  2414.     and    al,not 1111b
  2415.     or    ah,al
  2416.     mov    al,0f6h
  2417.     out    dx,ax
  2418.     mov    ah,ch
  2419.     mov    cl,4
  2420.     shl    ah,cl
  2421.     and    ah,100000b
  2422.     mov    dl,0cch
  2423.     in    al,dx
  2424.     mov    dl,0c2h
  2425.     and    al,not 100000b
  2426.     or    al,ah
  2427.     out    dx,al
  2428.     sti
  2429.     pop    cx
  2430.     pop    dx
  2431.     pop    ax
  2432.     ret
  2433. $video7 endp
  2434.  
  2435. $paradise proc        ;Paradise
  2436.     push    ax
  2437.     push    dx
  2438.     mov    dx,3ceh
  2439.     mov    ax,50fh     ;turn off write protect on VGA registers
  2440.     out    dx,ax
  2441.     mov    ah,byte ptr OSEG[curbk]
  2442.     shl    ah,1
  2443.     shl    ah,1
  2444.     shl    ah,1
  2445.     shl    ah,1
  2446.     mov    al,9
  2447.     out    dx,ax
  2448.     mov    ax,000Fh    ;reprotect registers, 910512
  2449.     out    dx,ax
  2450.     sti
  2451.     pop    dx
  2452.     pop    ax
  2453.     ret
  2454. $paradise endp
  2455.  
  2456. $chipstech proc     ;Chips & Tech
  2457.     push    ax
  2458.     push    dx
  2459.     mov    dx,46e8h    ;place chip in setup mode
  2460.     mov    ax,1eh
  2461.     out    dx,ax
  2462.     mov    dx,103h     ;enable extended registers
  2463.     mov    ax,0080h    ; (patched per JB's msg - Bert)
  2464.     out    dx,ax
  2465.     mov    dx,46e8h    ;bring chip out of setup mode
  2466.     mov    ax,0eh
  2467.     out    dx,ax
  2468.     mov    ah,byte ptr OSEG[curbk]
  2469.     shl    ah,1        ;change 64k bank number into 16k bank number
  2470.     shl    ah,1
  2471.     mov    al,10h
  2472.     mov    dx,3d6h
  2473.     out    dx,ax
  2474.     sti
  2475.     pop    dx
  2476.     pop    ax
  2477.     ret
  2478. $chipstech endp
  2479.  
  2480. $ativga proc        ;ATI VGA Wonder
  2481.     push    ax
  2482.     push    dx
  2483.     mov    ah,al
  2484.     mov    dx,1ceh
  2485.     mov    al,0b2h
  2486.     out    dx,al
  2487.     inc    dl
  2488.     in    al,dx
  2489.     shl    ah,1
  2490.     and    al,0e1h
  2491.     or    ah,al
  2492.     mov    al,0b2h
  2493.     dec    dl
  2494.     out    dx,ax
  2495.     sti
  2496.     pop    dx
  2497.     pop    ax
  2498.     ret
  2499. $ativga endp
  2500.  
  2501. $everex proc        ;Everex
  2502.     push    ax
  2503.     push    dx
  2504.     push    cx
  2505.     mov    cl,al
  2506.     mov    dx,3c4h
  2507.     mov    al,8
  2508.     out    dx,al
  2509.     inc    dl
  2510.     in    al,dx
  2511.     dec    dl
  2512.     shl    al,1
  2513.     shr    cl,1
  2514.     rcr    al,1
  2515.     mov    ah,al
  2516.     mov    al,8
  2517.     out    dx,ax
  2518.     mov    dl,0cch
  2519.     in    al,dx
  2520.     mov    dl,0c2h
  2521.     and    al,0dfh
  2522.     shr    cl,1
  2523.     jc    nob2
  2524.     or    al,20h
  2525. nob2:    out    dx,al
  2526.     sti
  2527.     pop    cx
  2528.     pop    dx
  2529.     pop    ax
  2530.     ret
  2531. $everex endp
  2532.  
  2533. $aheada proc
  2534.     push    ax
  2535.     push    dx
  2536.     push    cx
  2537.     mov    ch,al
  2538.     mov    dx,3ceh     ;Enable extended registers
  2539.     mov    ax,200fh
  2540.     out    dx,ax
  2541.     mov    dl,0cch     ;bit 0
  2542.     in    al,dx
  2543.     mov    dl,0c2h
  2544.     and    al,11011111b
  2545.     shr    ch,1
  2546.     jnc    temp_1
  2547.     or    al,00100000b
  2548. temp_1: out    dx,al
  2549.     mov    dl,0cfh     ;bits 1,2,3
  2550.     mov    al,0
  2551.     out    dx,al
  2552.     inc    dx
  2553.     in    al,dx
  2554.     dec    dx
  2555.     and    al,11111000b
  2556.     or    al,ch
  2557.     mov    ah,al
  2558.     mov    al,0
  2559.     out    dx,ax
  2560.     sti
  2561.     pop    cx
  2562.     pop    dx
  2563.     pop    ax
  2564.     ret
  2565. $aheada endp
  2566.  
  2567. $aheadb proc
  2568.     push    ax
  2569.     push    dx
  2570.     push    cx
  2571.     mov    ch,al
  2572.     mov    dx,3ceh     ;Enable extended registers
  2573.     mov    ax,200fh
  2574.     out    dx,ax
  2575.     mov    ah,ch
  2576.     mov    cl,4
  2577.     shl    ah,cl
  2578.     or    ah,ch
  2579.     mov    al,0dh
  2580.     out    dx,ax
  2581.     sti
  2582.     pop    cx
  2583.     pop    dx
  2584.     pop    ax
  2585.     ret
  2586. $aheadb endp
  2587.  
  2588. $oaktech proc        ;Oak Technology Inc OTI-067
  2589.     push    ax
  2590.     push    dx
  2591.     and    al,15
  2592.     mov    ah,al
  2593.     shl    al,1
  2594.     shl    al,1
  2595.     shl    al,1
  2596.     shl    al,1
  2597.     or    ah,al
  2598.     mov    al,11h
  2599.     mov    dx,3deh
  2600.     out    dx,ax
  2601.     sti
  2602.     pop    dx
  2603.     pop    ax
  2604.     ret
  2605. $oaktech endp
  2606.  
  2607. $genoa    proc            ;GENOA GVGA
  2608.     push    ax
  2609.     push    dx
  2610.     mov    ah,al
  2611.     shl    al,1
  2612.     shl    al,1
  2613.     shl    al,1
  2614.     or    ah,al
  2615.     mov    al,6
  2616.     or    ah,40h
  2617.     mov    dx,3c4h
  2618.     out    dx,ax
  2619.     sti
  2620.     pop    dx
  2621.     pop    ax
  2622.     ret
  2623. $genoa    endp
  2624.  
  2625. $ncr    proc                ;NCR 77C22E
  2626.     push    ax
  2627.     push    dx
  2628.     shl    al,1        ;change 64k bank number into 16k bank number
  2629.     shl    al,1
  2630.     mov    ah,al
  2631.     mov    al,18h
  2632.     mov    dx,3c4h
  2633.     out    dx,ax
  2634.     mov    ax,19h
  2635.     out    dx,ax
  2636.     sti
  2637.     pop    dx
  2638.     pop    ax
  2639.     ret
  2640. $ncr    endp
  2641.  
  2642. $compaq proc            ;Compaq
  2643.     push    ax
  2644.     push    dx
  2645.     mov    dx,3ceh
  2646.     mov    ax,50fh     ;unlock extended registers
  2647.     out    dx,ax
  2648.     mov    ah,byte ptr OSEG[curbk]
  2649.     shl    ah,1        ;change 64k bank number into 4k bank number
  2650.     shl    ah,1
  2651.     shl    ah,1
  2652.     shl    ah,1
  2653.     mov    al,45h
  2654.     out    dx,ax
  2655.     sti
  2656.     pop    dx
  2657.     pop    ax
  2658.     ret
  2659. $compaq endp
  2660.  
  2661. ;
  2662. ;  Read/Write 64K pages
  2663. ;
  2664. $vesa1    proc                ; VESA bank switching
  2665.     push    ax
  2666.     push    bx
  2667.     push    dx
  2668.     mul    vesa_granularity    ; Adjust for the granularity factor
  2669.     mov    dx,ax            ; Select window position
  2670.     mov    bx,0            ; select window (bank) sub-command
  2671.     call    dword ptr vesa_bankswitch  ; do it!
  2672.     pop    dx
  2673.     pop    bx
  2674.     pop    ax
  2675.     sti
  2676.     ret
  2677. $vesa1    endp
  2678. ;
  2679. ;  Read-only/Write-only 64K pages
  2680. ;
  2681. $vesa2    proc                ; VESA bank switching
  2682.     push    ax
  2683.     push    bx
  2684.     push    dx
  2685.     mul    vesa_granularity    ; Adjust for the granularity factor
  2686.     mov    dx,ax            ; Select window position
  2687.     push    dx
  2688.     mov    bx,0            ; select window (bank) sub-command
  2689.     call    dword ptr vesa_bankswitch  ; do it!
  2690.     pop    dx
  2691.     inc    bx
  2692.     call    dword ptr vesa_bankswitch
  2693.     pop    dx
  2694.     pop    bx
  2695.     pop    ax
  2696.     sti
  2697.     ret
  2698. $vesa2    endp
  2699. ;
  2700. ;  Read/Write 32K pages
  2701. ;
  2702. $vesa3    proc                ; VESA bank switching
  2703.     push    ax
  2704.     push    bx
  2705.     push    dx
  2706.     mul    vesa_granularity    ; Adjust for the granularity factor
  2707.     mov    dx,ax            ; Select window position
  2708.     push    dx
  2709.     mov    bx,vesa_low_window    ; select window (bank) sub-command
  2710.     call    dword ptr vesa_bankswitch  ; do it!
  2711.     pop    dx
  2712.     add    dx,vesa_gran_offset    ; 2nd window is at 32K offset from 1st
  2713.     mov    bx,vesa_high_window
  2714.     call    dword ptr vesa_bankswitch
  2715.     pop    dx
  2716.     pop    bx
  2717.     pop    ax
  2718.     sti
  2719.     ret
  2720. $vesa3    endp
  2721.  
  2722. $vesa_nullbank proc ; null routine for vesa_bankswitch when unknown
  2723.     ret
  2724. $vesa_nullbank endp
  2725.  
  2726. $nobank proc
  2727.     sti
  2728.     ret
  2729. $nobank endp
  2730.  
  2731. bkadr    macro    flag,func,entries        ; Bert
  2732.     mov    video_entries, offset entries    ; Bert
  2733.     mov    [flag],1
  2734.     mov    [bankadr],offset func
  2735. if @CodeSize
  2736.     mov    [bankseg],seg func
  2737. endif
  2738.     endm
  2739.  
  2740. nojmp    macro
  2741.     local    lbl
  2742.     jmp    lbl
  2743. lbl:
  2744.     endm
  2745.  
  2746. whichvga proc    near
  2747.     push    bp            ; save it around all the int 10s
  2748.  
  2749.     cmp    svga_type,0        ; was a SuperVGA adapter forced?
  2750.     jne    type1_forced        ;  yup - wade through the options
  2751.     jmp    not_forced        ;  nope - skip this section
  2752. type1_forced:
  2753.     cmp    svga_type,1
  2754.     jne    type2_forced
  2755.     bkadr    aheada,$aheada,ahead_entries
  2756. type2_forced:
  2757.     cmp    svga_type,2
  2758.     jne    type3_forced
  2759.     bkadr    ativga,$ativga,ati_entries
  2760. type3_forced:
  2761.     cmp    svga_type,3
  2762.     jne    type4_forced
  2763.     bkadr    chipstech,$chipstech,chips_entries
  2764. type4_forced:
  2765.     cmp    svga_type,4
  2766.     jne    type5_forced
  2767.     bkadr    everex,$everex,everex_entries
  2768. type5_forced:
  2769.     cmp    svga_type,5
  2770.     jne    type6_forced
  2771.     bkadr    genoa,$genoa,genoa_entries
  2772. type6_forced:
  2773.     cmp    svga_type,6
  2774.     jne    type7_forced
  2775.     bkadr    ncr,$ncr,ncr_entries
  2776. type7_forced:
  2777.     cmp    svga_type,7
  2778.     jne    type8_forced
  2779.     bkadr    oaktech,$oaktech,oaktech_entries
  2780. type8_forced:
  2781.     cmp    svga_type,8
  2782.     jne    type9_forced
  2783.     bkadr    paradise,$paradise,paradise_entries
  2784. type9_forced:
  2785.     cmp    svga_type,9
  2786.     jne    type10_forced
  2787.     bkadr    trident,$trident,trident_entries
  2788. type10_forced:
  2789.     cmp    svga_type,10
  2790.     jne    type11_forced
  2791.     bkadr    tseng,$tseng,tseng_entries
  2792. type11_forced:
  2793.     cmp    svga_type,11
  2794.     jne    type12_forced
  2795.     bkadr    tseng4,$tseng4,tseng4_entries
  2796. type12_forced:
  2797.     cmp    svga_type,12
  2798.     jne    type13_forced
  2799.     bkadr    video7,$video7,video7_entries
  2800. type13_forced:
  2801.     cmp    svga_type,13
  2802.     jne    type14_forced
  2803.     bkadr    aheadb,$aheadb,ahead_entries
  2804. type14_forced:
  2805.     jmp    fini
  2806. not_forced:
  2807.  
  2808.     cmp    vesa_detect,0        ; is VESA-detection disabled?
  2809.     je    notvesa         ;  yup - skip this
  2810.     mov    ax,4f00h        ; check for VESA adapter
  2811.     push    ds            ; set ES == DS
  2812.     pop    es            ;  ...
  2813.     mov    di, offset dacbox    ; answer goes here (a safe place)
  2814.     int    10h            ; do it.
  2815.     cmp    ax,004fh        ; successful response?
  2816.     jne    notvesa         ; nope.  Not a VESA adapter
  2817.  
  2818.     cmp    byte ptr 0[di],'V'      ; string == 'VESA'?
  2819.     jne    notvesa         ; nope.  Not a VESA adapter
  2820.     cmp    byte ptr 1[di],'E'      ; string == 'VESA'?
  2821.     jne    notvesa         ; nope.  Not a VESA adapter
  2822.     cmp    byte ptr 2[di],'S'      ; string == 'VESA'?
  2823.     jne    notvesa         ; nope.  Not a VESA adapter
  2824.     cmp    byte ptr 3[di],'A'      ; string == 'VESA'?
  2825.     jne    notvesa         ; nope.  Not a VESA adapter
  2826.     bkadr    vesa,$vesa_nullbank, vesa_entries
  2827.     jmp    fini
  2828. notvesa:
  2829.  
  2830.     call    xga_detect        ; XGA Adapter?
  2831.     cmp    ax,0
  2832.     je    notxga            ; nope
  2833.     bkadr    xga,xga_newbank, xga_entries
  2834.     jmp    fini
  2835. notxga:
  2836.  
  2837.     mov    si,1
  2838.     mov    ax,0c000h
  2839.     mov    es,ax
  2840.     cmp    word ptr es:[40h],'13'
  2841.     jnz    noati
  2842.     bkadr    ativga,$ativga,ati_entries        ; Bert
  2843.     cli
  2844.     mov    dx,1ceh
  2845.     mov    al,0bbh
  2846.     out    dx,al
  2847.     inc    dl
  2848.     in    al,dx
  2849.     sti
  2850.     and    al,20h
  2851.     jz    no512
  2852.     mov    [vga512],1
  2853. no512:    jmp    fini
  2854.  
  2855. noati:    mov    ax,7000h        ;Test for Everex
  2856.     xor    bx,bx
  2857.     cld
  2858.     int    10h
  2859.     cmp    al,70h
  2860.     jnz    noev
  2861.     bkadr    everex,$everex, everex_entries        ; Bert
  2862.     and    ch,11000000b
  2863.     jz    temp_2
  2864.     mov    [vga512],1
  2865. temp_2: and    dx,0fff0h
  2866.     cmp    dx,6780h
  2867.     jz    yeste
  2868.     cmp    dx,2360h
  2869.     jnz    note
  2870. yeste:    bkadr    trident,$trident, everex_entries    ; Bert
  2871.     mov    everex,0
  2872. note:    jmp    fini
  2873.  
  2874. noev:
  2875.     mov    ax,0bf03h        ;Test for Compaq
  2876.     xor    bx,bx
  2877.     mov    cx,bx
  2878.     int    10h
  2879.     cmp    ax,0bf03h
  2880.     jnz    nocp
  2881.     test    cl,40h            ;is 640x480x256 available? ;(??)
  2882.     jz    nocp
  2883.     bkadr    compaq,$compaq,compaq_entries        ; Bert
  2884.     mov    [vga512],1
  2885.     jmp    fini
  2886.  
  2887. nocp:    mov    dx,3c4h         ;Test for NCR 77C22E
  2888.     mov    ax,0ff05h
  2889.     call    $isport2
  2890.     jnz    noncr
  2891.     mov    ax,5            ;Disable extended registers
  2892.     out    dx,ax
  2893.     mov    ax,0ff10h        ;Try to write to extended register 10
  2894.     call    $isport2        ;If it writes then not NCR
  2895.     jz    noncr
  2896.     mov    ax,105h         ;Enable extended registers
  2897.     out    dx,ax
  2898.     mov    ax,0ff10h
  2899.     call    $isport2
  2900.     jnz    noncr            ;If it does NOT write then not NCR
  2901.     bkadr    ncr,$ncr,ncr_entries        ; Bert
  2902.     mov    [vga512],1
  2903.     jmp    fini
  2904.  
  2905. noncr:    mov    dx,3c4h         ;Test for Trident
  2906.     mov    al,0bh
  2907.     out    dx,al
  2908.     inc    dl
  2909.     in    al,dx
  2910.     cmp    al,06h
  2911.     ja    notri
  2912.     cmp    al,2
  2913.     jb    notri
  2914.     bkadr    trident,$trident, trident_entries    ; Bert
  2915.     cmp    al,3
  2916.     jb    no89
  2917.     mov    [t8900],1
  2918.     mov    dx,3d5h
  2919.     mov    al,1fh
  2920.     out    dx,al
  2921.     inc    dx
  2922.     in    al,dx
  2923.     and    al,3
  2924.     cmp    al,1
  2925.     jb    notmem
  2926.     mov    [vga512],1
  2927.     je    notmem
  2928.     mov    [vga1024],1
  2929. notmem: jmp    fini
  2930.  
  2931. no89:    mov    [vga512],1
  2932.     jmp    fini
  2933.  
  2934. notri:    mov    ax,6f00h        ;Test for Video 7
  2935.     xor    bx,bx
  2936.     cld
  2937.     int    10h
  2938.     cmp    bx,'V7'
  2939.     jnz    nov7
  2940.     bkadr    video7,$video7, video7_entries        ; Bert
  2941.     mov    ax,6f07h
  2942.     cld
  2943.     int    10h
  2944.     and    ah,7fh
  2945.     cmp    ah,1
  2946.     jbe    temp_3
  2947.     mov    [vga512],1
  2948. temp_3: jmp    fini
  2949.  
  2950. nov7:    mov    dx,3d4h         ;Test for GENOA GVGA
  2951.     mov    ax,032eh        ;check for Herchi Register
  2952.     call    $isport2
  2953.     jnz    nogn
  2954.     mov    dx,3c4h         ;check for memory segment register
  2955.     mov    ax,3f06h
  2956.     call    $isport2
  2957.     jnz    nogn
  2958.     bkadr    genoa,$genoa, genoa_entries        ; Bert
  2959.     mov    [vga512],1
  2960.     jmp    fini
  2961.  
  2962. nogn:    call    $cirrus         ;Test for Cirrus
  2963.     cmp    [cirrus],0
  2964.     je    noci
  2965.     jmp    fini
  2966.  
  2967. noci:    mov    dx,3ceh         ;Test for Paradise
  2968.     mov    al,9            ;check Bank switch register
  2969.     out    dx,al
  2970.     inc    dx
  2971.     in    al,dx
  2972.     dec    dx
  2973.     or    al,al
  2974.     jnz    nopd
  2975.  
  2976.     mov    ax,50fh         ;turn off write protect on VGA registers
  2977.     out    dx,ax
  2978.     mov    dx,offset $pdrsub
  2979.     mov    cx,1
  2980.     call    $chkbk
  2981.     jc    nopd            ;if bank 0 and 1 same not paradise
  2982.     bkadr    paradise,$paradise, paradise_entries    ; Bert
  2983.     mov    dx,3ceh
  2984.     mov    al,0bh            ;512k detect from Bob Berry
  2985.     out    dx,al
  2986.     inc    dx
  2987.     in    al,dx
  2988.     test    al,80h            ;if top bit set then 512k
  2989.     jz    nop512
  2990.     mov    [vga512],1
  2991. nop512: jmp    fini
  2992.  
  2993. nopd:    mov    ax,5f00h        ;Test for Chips & Tech
  2994.     xor    bx,bx
  2995.     cld
  2996.     int    10h
  2997.     cmp    al,5fh
  2998.     jnz    noct
  2999.     bkadr    chipstech,$chipstech, chips_entries    ; Bert
  3000.     cmp    bh,1
  3001.     jb    temp_5
  3002.     mov    [vga512],1
  3003. temp_5:
  3004.     jmp    fini
  3005.  
  3006. noct:    mov    ch,0
  3007.     mov    dx,3d4h         ;check for Tseng 4000 series
  3008.     mov    ax,0f33h
  3009.     call    $isport2
  3010.     jnz    not4
  3011.     mov    ch,1
  3012.  
  3013.     mov    dx,3bfh         ;Enable access to extended registers
  3014.     mov    al,3
  3015.     out    dx,al
  3016.     mov    dx,3d8h
  3017.     mov    al,0a0h
  3018.     out    dx,al
  3019.     jmp    short yes4
  3020.  
  3021. not4:    mov    dx,3d4h         ;Test for Tseng 3000 or 4000
  3022.     mov    ax,1f25h        ;is the Overflow High register there?
  3023.     call    $isport2
  3024.     jnz    nots
  3025.     mov    al,03fh         ;bottom six bits only
  3026.     jmp    short yes3
  3027. yes4:    mov    al,0ffh
  3028. yes3:    mov    dx,3cdh         ;test bank switch register
  3029.     call    $isport1
  3030.     jnz    nots
  3031.     bkadr    tseng,$tseng, tseng_entries        ; Bert
  3032.     cmp    ch,0
  3033.     jnz    t4mem
  3034.     mov    [vga512],1
  3035.     jmp    fini
  3036.  
  3037. t4mem:    mov    dx,3d4h         ;Tseng 4000 memory detect 1meg
  3038.     mov    al,37h
  3039.     out    dx,al
  3040.     inc    dx
  3041.     in    al,dx
  3042.     test    al,1000b        ;if using 64kx4 RAMs then no more than 256k
  3043.     jz    nomem
  3044.     and    al,3
  3045.     cmp    al,1            ;if 8 bit wide bus then only two 256kx4 RAMs
  3046.     jbe    nomem
  3047.     mov    [vga512],1
  3048.     cmp    al,2            ;if 16 bit wide bus then four 256kx4 RAMs
  3049.     je    nomem
  3050.     mov    [vga1024],1        ;full meg with eight 256kx4 RAMs
  3051. nomem:    bkadr    tseng4,$tseng4, tseng4_entries        ; Bert
  3052.     jmp    fini
  3053.  
  3054. nots:
  3055.     mov    dx,3ceh     ;Test for Above A or B chipsets
  3056.     mov    ax,200fh
  3057.     out    dx,ax
  3058.     inc    dx
  3059.     nojmp
  3060.     in    al,dx
  3061.     cmp    al,21h
  3062.     jz    verb
  3063.     cmp    al,20h
  3064.     jnz    noab
  3065.     bkadr    aheada,$aheada, ahead_entries        ; Bert
  3066.     mov    [vga512],1
  3067.     jmp    short fini
  3068.  
  3069. verb:    bkadr    aheadb,$aheadb, ahead_entries        ; Bert
  3070.     mov    [vga512],1
  3071.     jmp    short fini
  3072.  
  3073. noab:    mov    dx,3deh         ;Test for Oak Technology
  3074.     mov    ax,0ff11h        ;look for bank switch register
  3075.     call    $isport2
  3076.     jnz    nooak
  3077.     bkadr    oaktech,$oaktech, oaktech_entries        ; Bert
  3078.     mov    al,0dh
  3079.     out    dx,al
  3080.     inc    dx
  3081.     nojmp
  3082.     in    al,dx
  3083.     test    al,80h
  3084.     jz    no4ram
  3085.     mov    [vga512],1
  3086. no4ram: jmp    short fini
  3087.  
  3088. nooak:    mov    si,0
  3089.  
  3090. fini:    mov    ax,si
  3091.     pop    bp
  3092.     ret
  3093. whichvga endp
  3094.  
  3095.  
  3096. $cirrus proc    near
  3097.     mov    dx,3d4h     ; assume 3dx addressing
  3098.     mov    al,0ch        ; screen a start address hi
  3099.     out    dx,al        ; select index
  3100.     inc    dx        ; point to data
  3101.     mov    ah,al        ; save index in ah
  3102.     in    al,dx        ; get screen a start address hi
  3103.     xchg    ah,al        ; swap index and data
  3104.     push    ax        ; save old value
  3105.     push    dx        ; save crtc address
  3106.     xor    al,al        ; clear crc
  3107.     out    dx,al        ; and out to the crtc
  3108.  
  3109.     mov    al,1fh        ; Eagle ID register
  3110.     dec    dx        ; back to index
  3111.     out    dx,al        ; select index
  3112.     inc    dx        ; point to data
  3113.     in    al,dx        ; read the id register
  3114.     mov    bh,al        ; and save it in bh
  3115.  
  3116.     mov    cl,4        ; nibble swap rotate count
  3117.     mov    dx,3c4h     ; sequencer/extensions
  3118.     mov    bl,6        ; extensions enable register
  3119.  
  3120.     ror    bh,cl        ; compute extensions disable value
  3121.     mov    ax,bx        ; extensions disable
  3122.     out    dx,ax        ; disable extensions
  3123.     inc    dx        ; point to data
  3124.     in    al,dx        ; read enable flag
  3125.     or    al,al        ; disabled ?
  3126.     jnz    exit        ; nope, not an cirrus
  3127.  
  3128.     ror    bh,cl        ; compute extensions enable value
  3129.     dec    dx        ; point to index
  3130.     mov    ax,bx        ; extensions enable
  3131.     out    dx,ax        ; enable extensions
  3132.     inc    dx        ; point to data
  3133.     in    al,dx        ; read enable flag
  3134.     cmp    al,1        ; enabled ?
  3135.     jne    exit        ; nope, not an cirrus
  3136.     mov    [cirrus],1
  3137.     mov    video_entries, offset no_entries    ; Bert
  3138.     mov    [bankadr],offset $nobank
  3139. if @CodeSize
  3140.     mov    [bankseg],seg $nobank
  3141. endif
  3142. exit:    pop    dx        ; restore crtc address
  3143.     dec    dx        ; point to index
  3144.     pop    ax        ; recover crc index and data
  3145.     out    dx,ax        ; restore crc value
  3146.     ret
  3147. $cirrus endp
  3148.  
  3149. $chkbk    proc    near        ;paradise bank switch check
  3150.     mov    di,0b800h
  3151.     mov    es,di
  3152.     xor    di,di
  3153.     mov    bx,1234h
  3154.     call    $gochk
  3155.     jnz    nopd
  3156.     mov    bx,4321h
  3157.     call    $gochk
  3158.     jnz    nopd
  3159.     clc
  3160.     ret
  3161. nopd:    stc
  3162.     ret
  3163. $chkbk    endp
  3164.  
  3165. $gochk    proc    near
  3166.     push    si
  3167.     mov    si,bx
  3168.  
  3169.     mov    al,cl
  3170.     call    dx
  3171.     xchg    bl,es:[di]
  3172.     mov    al,ch
  3173.     call    dx
  3174.     xchg    bh,es:[di]
  3175.  
  3176.     xchg    si,bx
  3177.  
  3178.     mov    al,cl
  3179.     call    dx
  3180.     xor    bl,es:[di]
  3181.     mov    al,ch
  3182.     call    dx
  3183.     xor    bh,es:[di]
  3184.  
  3185.     xchg    si,bx
  3186.  
  3187.     mov    al,ch
  3188.     call    dx
  3189.     mov    es:[di],bh
  3190.     mov    al,cl
  3191.     call    dx
  3192.     mov    es:[di],bl
  3193.  
  3194.     mov    al,0
  3195.     call    dx
  3196.     or    si,si
  3197.     pop    si
  3198.     ret
  3199. $gochk    endp
  3200.  
  3201.  
  3202. $pdrsub proc    near        ;Paradise
  3203.     push    dx
  3204.     mov    ah,al
  3205.     mov    dx,3ceh
  3206.     mov    al,9
  3207.     out    dx,ax
  3208.     pop    dx
  3209.     ret
  3210. $pdrsub endp
  3211.  
  3212. $isport2 proc    near
  3213.     push    bx
  3214.     mov    bx,ax
  3215.     out    dx,al
  3216.     mov    ah,al
  3217.     inc    dx
  3218.     in    al,dx
  3219.     dec    dx
  3220.     xchg    al,ah
  3221.     push    ax
  3222.     mov    ax,bx
  3223.     out    dx,ax
  3224.     out    dx,al
  3225.     mov    ah,al
  3226.     inc    dx
  3227.     in    al,dx
  3228.     dec    dx
  3229.     and    al,bh
  3230.     cmp    al,bh
  3231.     jnz    noport
  3232.     mov    al,ah
  3233.     mov    ah,0
  3234.     out    dx,ax
  3235.     out    dx,al
  3236.     mov    ah,al
  3237.     inc    dx
  3238.     in    al,dx
  3239.     dec    dx
  3240.     and    al,bh
  3241.     cmp    al,0
  3242. noport: pop    ax
  3243.     out    dx,ax
  3244.     pop    bx
  3245.     ret
  3246. $isport2 endp
  3247.  
  3248. $isport1 proc    near
  3249.     mov    ah,al
  3250.     in    al,dx
  3251.     push    ax
  3252.     mov    al,ah
  3253.     out    dx,al
  3254.     in    al,dx
  3255.     and    al,ah
  3256.     cmp    al,ah
  3257.     jnz    noport
  3258.     mov    al,0
  3259.     out    dx,al
  3260.     in    al,dx
  3261.     and    al,ah
  3262.     cmp    al,0
  3263. noport: pop    ax
  3264.     out    dx,al
  3265.     ret
  3266. $isport1 endp
  3267.  
  3268. videowrite    proc    near        ; your-own-video write routine
  3269.     mov    ah,0            ; clear the high-order color byte
  3270.     push    ax            ; colors parameter
  3271.     push    dx            ; 'y' parameter
  3272.     push    cx            ; 'x' parameter
  3273.     call    far ptr writevideo    ; let the external routine do it
  3274.     add    sp,6            ; pop the parameters
  3275.     ret                ; we done.
  3276. videowrite    endp
  3277.  
  3278. videoread    proc    near        ; your-own-video read routine
  3279.     push    dx            ; 'y' parameter
  3280.     push    cx            ; 'x' parameter
  3281.     call    far ptr readvideo    ; let the external routine do it
  3282.     add    sp,4            ; pop the parameters
  3283.     ret                ; we done.
  3284. videoread    endp
  3285.  
  3286. diskwrite    proc    near        ; disk-video write routine
  3287.     push    ax            ; colors parameter
  3288.     push    dx            ; 'y' parameter
  3289.     push    cx            ; 'x' parameter
  3290.     call    far ptr writedisk    ; let the external routine do it
  3291.     add    sp,6            ; pop the parameters
  3292.     ret                ; we done.
  3293. diskwrite    endp
  3294.  
  3295. diskread    proc    near        ; disk-video read routine
  3296.     push    dx            ; 'y' parameter
  3297.     push    cx            ; 'x' parameter
  3298.     call    far ptr readdisk    ; let the external routine do it
  3299.     add    sp,4            ; pop the parameters
  3300.     ret                ; we done.
  3301. diskread    endp
  3302.  
  3303.  
  3304. ; ***********************************************************************
  3305. ;
  3306. ; TARGA MODIFIED 1 JUNE 89 - j mclain
  3307. ;
  3308. tgawrite    proc    near
  3309.     push    ax            ; colors parameter
  3310.     push    dx            ; 'y' parameter
  3311.     push    cx            ; 'x' parameter
  3312.     call    far ptr WriteTGA    ; writeTGA( x, y, color )
  3313.     add    sp,6            ; pop the parameters
  3314.     ret
  3315. tgawrite    endp
  3316.  
  3317. tgaread     proc    near
  3318.     push    dx            ; 'y' parameter
  3319.     push    cx            ; 'x' parameter
  3320.     call    far ptr ReadTGA     ; readTGA( x, y )
  3321.     add    sp,4            ; pop the parameters
  3322.     ret
  3323. tgaread endp
  3324.  
  3325.  
  3326. ; TARGA+ Code 2-11-91, Mark Peterson
  3327.  
  3328. TPlusWrite    PROC    NEAR
  3329.     push    ax
  3330.     push    dx
  3331.     push    cx
  3332.     call    FAR PTR WriteTPlusBankedPixel
  3333.     add    sp, 6
  3334.     ret
  3335. TPlusWrite     ENDP
  3336.  
  3337. TPlusRead      PROC    NEAR
  3338.     push    dx
  3339.     push    cx
  3340.     call    FAR PTR ReadTPlusBankedPixel
  3341.     add    sp, 4
  3342.     ret
  3343. TPlusRead      ENDP
  3344.  
  3345.  
  3346. f85start    proc    near
  3347.     call   far ptr open8514
  3348.     ret
  3349. f85start    endp
  3350.  
  3351. f85end    proc    near
  3352.     call   far ptr close8514
  3353.     ret
  3354. f85end    endp
  3355.  
  3356. f85write    proc    near
  3357.     call   far ptr fr85wdot
  3358.     ret
  3359. f85write    endp
  3360.  
  3361. f85read proc    near
  3362.     call   far ptr fr85rdot
  3363.     ret
  3364. f85read endp
  3365.  
  3366. hgcwrite proc near
  3367.     mov    ah,0            ; clear the high-order color byte
  3368.     push    ax            ; colors parameter
  3369.     push    dx            ; 'y' parameter
  3370.     push    cx            ; 'x' parameter
  3371.     call    far ptr writehgc    ; let the Herc. Write dot routine do it
  3372.     add    sp,6            ; pop the parameters
  3373.     ret
  3374. hgcwrite endp
  3375.  
  3376. hgcread proc near
  3377.     push    dx            ; 'y' parameter
  3378.     push    cx            ; 'x' parameter
  3379.     call    far ptr readhgc     ; call the Hercules Read dot routine
  3380.     add    sp,4            ; pop the parameters
  3381.     ret
  3382. hgcread endp
  3383.  
  3384. hgcstart    proc    near        ; hercules start routine
  3385.     call    far ptr inithgc     ; let the external routine do it
  3386.     ret                ; we done.
  3387. hgcstart    endp
  3388.  
  3389. hgcend        proc    near        ; hercules end routine
  3390.     call    far ptr termhgc     ; let the external routine do it
  3391.     ret                ; we done.
  3392. hgcend        endp
  3393.  
  3394. ; **************** video adapter initialization *******************
  3395. ;
  3396. ; adapter_init:
  3397. ;    called from general.asm once per run
  3398.  
  3399. adapter_init    proc    far        ; initialize the video adapter (to VGA)
  3400.     mov    ax,[bankadr]        ; Initialize the bank-switching
  3401.     mov    video_bankadr,ax    ;  logic to the do-nothing routine
  3402.     mov    ax,[bankseg]        ;  ...
  3403.     mov    video_bankseg,ax    ;  ...
  3404.     mov    bx,0            ; clear out all of the 256-mode flags
  3405.     mov    tseng,bx        ;  ...
  3406.     mov    trident,bx        ;  ...
  3407.     mov    video7,bx        ;  ...
  3408.     mov    paradise,bx        ;  ...
  3409.     mov    chipstech,bx        ;  ...
  3410.     mov    ativga,bx        ;  ...
  3411.     mov    everex,bx        ;  ...
  3412.     mov    cirrus,bx        ;  ...
  3413.     mov    aheada,bx        ;  ...
  3414.     mov    aheadb,bx        ;  ...
  3415.     mov    tseng4,bx        ;  ...
  3416.     mov    oaktech,bx        ;  ...
  3417.     mov    [bankadr],offset $nobank
  3418.     mov    [bankseg],seg $nobank
  3419.     mov    video_entries, offset no_entries    ; ...
  3420.     ret
  3421. adapter_init    endp
  3422.  
  3423. ; adapter_detect:
  3424. ;    This routine performs a few quick checks on the type of
  3425. ;    video adapter installed.
  3426. ;    It sets variables video_type and textsafe,
  3427. ;    and fills in a few bank-switching routines.
  3428.  
  3429. adapter_detect    proc    uses di si es
  3430.     push    bp            ; some bios's don't save during int 10h
  3431.     cmp    done_detect,0        ; been called already?
  3432.     je    adapter_detect2     ;  nope
  3433.     jmp    adapter_ret        ; yup, do nothing
  3434. adapter_detect2:
  3435.     inc    done_detect        ; don't get called again
  3436.  
  3437.     cmp    video_type,0        ; video_type preset by command line arg?
  3438.     jne    go_adapter_set        ;  yup, use what we're told
  3439.  
  3440.     cmp    TPlusFlag, 0
  3441.     je    NotTPlus
  3442.     call    far ptr CheckForTPlus
  3443.     or    ax, ax
  3444.     jz    NotTPlus
  3445.     mov    TPlusInstalled, 1    ; flag it and check for primary adapter
  3446.  
  3447. NotTPlus:
  3448.     mov    ax,1a00h        ; start by trying int 10 func 1A
  3449.     int    10h            ;  ...
  3450.     cmp    al,1ah            ; was AL modified?
  3451.     je    adapter_detect_4    ;  yup. go decode what we got
  3452.     mov    ax,1200h        ; try this vga-only function
  3453.     mov    bl,34h            ;  enable cursor emulation
  3454.     int    10h            ;  ...
  3455.     cmp    al,12h            ; did it work?
  3456.     je    adapter_detect_vga    ;  yup, vga
  3457.     mov    ah,12h            ; look for an EGA
  3458.     mov    bl,10h            ;  by using an EGA-specific call
  3459.     int    10h            ;  ...
  3460.     cmp    bl,10h            ; was BL modified?
  3461.     je    adapter_detect_notega    ;  nope, < EGA
  3462.     mov    video_type,3        ; set the video type: EGA
  3463.     cmp    bh,1            ; monochrome monitor?
  3464.     jne    go_adapter_set        ;  nope
  3465.     mov    mode7text,1        ; yup, use mode 7 for text
  3466.     jmp    short go_adapter_set    ; We done.
  3467. adapter_detect_4:
  3468.     cmp    bl,1            ; =1?
  3469.     jne    adapter_detect_4a    ;  nope
  3470.     jmp    adapter_detect_hgc    ; MDA, assume HGC (nothing else works)
  3471. adapter_detect_4a:
  3472.     mov    video_type,2        ; set the video type: CGA
  3473.     cmp    bl,3            ; <=2?
  3474.     jb    go_adapter_set        ;  exit with type CGA
  3475.     mov    video_type,3        ; set the video type: EGA
  3476.     cmp    bl,5            ; =5?
  3477.     jne    adapter_detect_5    ;  nope
  3478.     mov    mode7text,1        ; yup, monochrome monitor, mode 7 text
  3479. go_adapter_set:
  3480.     jmp    adapter_set
  3481. adapter_detect_5:
  3482.     cmp    bl,6            ; <=5?
  3483.     jb    go_adapter_set        ;  exit with type EGA
  3484.     cmp    bl,10            ; <=9?
  3485.     jb    adapter_detect_vga    ;  vga, go check which kind
  3486.     mov    video_type,4        ; set the video type: MCGA
  3487.     cmp    bl,13            ; <=12?
  3488.     jb    go_adapter_set        ;  exit with type MCGA
  3489. adapter_detect_vga:
  3490.     mov    video_type,5        ; set the video type: VGA
  3491.     call    whichvga        ; autodetect which VGA is there
  3492.     mov    ax,[bankadr]        ; save the results
  3493.     mov    video_bankadr,ax    ;  ...
  3494.     mov    ax,[bankseg]        ;  ...
  3495.     mov    video_bankseg,ax    ;  ...
  3496.     jmp    adapter_set
  3497. adapter_detect_notega:
  3498.     mov    video_type,2        ; set the video type: CGA
  3499.     ; HGC detect code from book by Richard Wilton follows
  3500.     mov    dx,3B4h         ; check for MDA, use MDA CRTC address
  3501.     mov    al,0Fh            ; select 6845 reg 0Fh (Cursor Low)
  3502.     out    dx,al
  3503.     inc    dx
  3504.     in    al,dx            ; AL := current Cursor Low value
  3505.     mov    ah,al            ; preserve in AH
  3506.     mov    al,66h            ; AL := arbitrary value
  3507.     out    dx,al            ; try to write to 6845
  3508.     mov    cx,200h
  3509. mdalp:    loop    mdalp            ; wait for 6845 to respond
  3510.     in    al,dx            ; read cursor low again
  3511.     xchg    ah,al
  3512.     out    dx,al            ; restore original value
  3513.     cmp    ah,66h            ; test whether 6845 responded
  3514.     jne    adapter_set        ;  nope, exit with type CGA
  3515.     mov    dl,0BAh         ; DX := 3BAh (status port)
  3516.     in    al,dx
  3517.     and    al,80h
  3518.     mov    ah,al            ; AH := bit 7 (vertical sync on HGC)
  3519.     mov    cx,8000h        ; do this 32768 times
  3520. mdalp2: in    al,dx
  3521.     and    al,80h            ; isolate bit 7
  3522.     cmp    ah,al
  3523.     loope    mdalp2            ; wait for bit 7 to change
  3524.     je    adapter_set        ;  didn't change, exit with type CGA
  3525. ;;    in    al,dx
  3526. ;;    and    al,01100000b        ; mask off bits 5 and 6
  3527. ;; Next line probably backwards but doesn't matter, the test in this area
  3528. ;; distinguishes HGC/HGC+/InColor, which we don't care about anyway.
  3529. ;;    jnz    adapter_set        ; not hgc/hgc+, exit with type CGA
  3530. adapter_detect_hgc:
  3531.     mov    video_type,1        ; HGC
  3532.     mov    mode7text,1        ; use mode 7 for text
  3533.  
  3534. adapter_set:
  3535.     ; ensure a nice safe standard state
  3536.     mov    ax,3            ; set 80x25x16 text mode, clear screen
  3537.     cmp    mode7text,0        ; use mode 7 for text?
  3538.     je    adapter_set2        ;  nope
  3539.     mov    ax,7            ; set mono text mode, clear screen
  3540. adapter_set2:
  3541.     int    10h            ; set text mode
  3542.     mov    ax,0500h        ; select display page zero
  3543.     int    10h            ;  ...
  3544.  
  3545.     ; now the color text stuff
  3546.     cmp    textsafe,2        ; command line textsafe=no?
  3547.     je    adapter_go_ret        ;  yup, believe the user
  3548.     cmp    video_type,3        ; >= ega?
  3549.     jae    adapter_setup        ;  yup
  3550.     mov    textsafe,2        ; textsafe=no
  3551. adapter_go_ret:             ; a label for some short jumps
  3552.     jmp    adapter_ret        ;  to the exit
  3553.  
  3554. adapter_setup:
  3555.     ; more standard state, ega and up stuff
  3556.     mov    ax,1003h        ; top attribute bit means blink
  3557.     mov    bl,01h            ;  ...
  3558.     int    10h            ;  ...
  3559.     mov    ax,1103h        ; font block 0, 256 chars (not 512)
  3560.     mov    bl,00h            ;  ...
  3561.     int    10h            ;  ...
  3562.     mov    ax,1202h        ; 400 scan lines in text mode (vga)
  3563.     mov    bl,30h            ;  ...
  3564.     int    10h            ;  ...
  3565.     mov    ax,1200h        ; cga cursor emulation (vga)
  3566.     mov    bl,34h            ;  ...
  3567.     int    10h            ;  ...
  3568.     mov    ax,1200h        ; enable default palette loading
  3569.     mov    bl,31h            ;  ...
  3570.     int    10h            ;  ...
  3571.     cmp    textsafe,0        ; were we told textsafe=yes|bios|save?
  3572.     jne    adapter_ret        ;  yup
  3573.     mov    textsafe,1        ; set textsafe=yes
  3574. adapter_ret:
  3575.     cld                ; some MSC 6.0 libraries assume this!
  3576.     pop    bp
  3577.     ret
  3578. adapter_detect    endp
  3579.  
  3580.  
  3581. ; select_vga_plane:
  3582. ;    Call this routine with cx = plane number.
  3583. ;    It works for vga and for ega.  (I hope.)
  3584. ;    It uses no local variables, caller may have ds register modified.
  3585. ;    On return from this routine, the requested vid mem plane is mapped
  3586. ;    to A0000;  this means that the sequencer and graphics controller
  3587. ;    states are not very useful for further real work - before any further
  3588. ;    screen painting, better reset video mode.
  3589.  
  3590. select_vga_plane proc near        ; cl = plane number
  3591.     ; some callers may have ds modified, use no variables in here!
  3592.     mov    dx,SC_INDEX        ; sequencer controller
  3593.     mov    ax,0102h        ; select plane
  3594.     shl    ah,cl            ;  bit for desired plane
  3595.     out    dx,ax            ;  ...
  3596.     mov    ax,0604h        ; no chaining
  3597.     out    dx,ax            ;  ...
  3598.     mov    dx,GC_INDEX        ; graphics controller
  3599.     mov    ax,0001h        ; use processor data
  3600.     out    dx,ax            ;  ...
  3601.     mov    al,  04h        ; select read plane
  3602.     mov    ah,cl            ;  desired plane
  3603.     out    dx,ax            ;  ...
  3604.     mov    ax,0005h        ; no even/odd, write mode 0
  3605.     out    dx,ax            ;  ...
  3606.     mov    ax,0106h        ; map to a000, no chain, graphics
  3607.     out    dx,ax            ;  ...
  3608.     mov    ax,0ff08h        ; enable 8 bits per write
  3609.     out    dx,ax            ;  ...
  3610.     ret                ; all done
  3611. select_vga_plane endp
  3612.  
  3613.  
  3614. ; **************** internal Read/Write-a-line routines *********************
  3615. ;
  3616. ;    These routines are called by out_line(), put_line() and get_line().
  3617. ;    They assume the following register values:
  3618. ;
  3619. ;        si = offset of array of colors for a row (write routines)
  3620. ;        di = offset of array of colors for a row (read routines)
  3621. ;
  3622. ;        ax = stopping column
  3623. ;        bx =
  3624. ;        cx = starting column
  3625. ;        dx = row
  3626. ;
  3627. ; Note: so far have converted only normaline, normalineread, mcgaline,
  3628. ;    mcgareadline, super256line, super256readline -- Tim
  3629.  
  3630. normaline    proc    near        ; Normal Line
  3631. normal_line1:
  3632.     push    ax            ; save stop col
  3633.     mov    al,[si]         ; retrieve the color
  3634.     xor    ah,ah            ; MCP 6-7-91
  3635.     push    cx            ; save the counter around the call
  3636.     push    dx            ; save column around the call
  3637.     push    si            ; save the pointer around the call also
  3638.     call    dotwrite        ; write the dot via the approved method
  3639.     pop    si            ; restore the pointer
  3640.     pop    dx            ; restore the column
  3641.     pop    cx            ; restore the counter
  3642.     inc    si            ; bump it up
  3643.     inc    cx            ; bump it up
  3644.     pop    ax            ; retrieve number of dots
  3645.     cmp    cx,ax            ; more to go?
  3646.     jle    normal_line1        ; yup.    do it.
  3647.     ret
  3648. normaline    endp
  3649.  
  3650. normalineread    proc    near        ; Normal Line
  3651.     mov    bx,videomem
  3652.     mov    es,bx
  3653. normal_lineread1:
  3654.     push    ax            ; save stop col
  3655.     push    cx            ; save the counter around the call
  3656.     push    dx            ; save column around the call
  3657.     push    di            ; save the pointer around the call also
  3658.     call    dotread         ; read the dot via the approved method
  3659.     pop    di            ; restore the pointer
  3660.     pop    dx            ; restore the column
  3661.     pop    cx            ; restore the counter
  3662.     mov    bx,di            ; locate the actual pixel color
  3663.     mov    [bx],al         ; retrieve the color
  3664.     inc    di            ; bump it up
  3665.     inc    cx            ; bump it up
  3666.     pop    ax            ; retrieve number of dots
  3667.     cmp    cx,ax            ; more to go?
  3668.     jle    normal_lineread1    ; yup.    do it.
  3669.     ret
  3670. normalineread    endp
  3671.  
  3672. mcgaline    proc    near        ; MCGA 320*200, 246 colors
  3673.     sub    ax,cx            ; last col - first col
  3674.     inc    ax            ;   + 1
  3675.  
  3676.     xchg    dh,dl            ; bx := 256*y
  3677.     mov    bx,cx            ; bx := x
  3678.     add    bx,dx            ; bx := 256*y + x
  3679.     shr    dx,1
  3680.     shr    dx,1            ; dx := 64*y
  3681.     add    bx,dx            ; bx := 320*y + x
  3682.     mov    di,bx            ; di = offset of row in video memory
  3683.  
  3684.     mov    cx,ax            ; move this many bytes
  3685.     rep    movsb            ; zap line into memory
  3686.     ret
  3687. mcgaline    endp
  3688.  
  3689. mcgareadline    proc    near        ; MCGA 320*200, 246 colors
  3690.  
  3691.     sub    ax,cx            ; last col - first col
  3692.     inc    ax            ;   + 1
  3693.  
  3694.     xchg    dh,dl            ; bx := 256*y
  3695.     mov    bx,cx            ; bx := x
  3696.     add    bx,dx            ; bx := 256*y + x
  3697.     shr    dx,1
  3698.     shr    dx,1            ; dx := 64*y
  3699.     add    bx,dx            ; bx := 320*y + x
  3700.     mov    si,bx            ; di = offset of row in video memory
  3701.  
  3702.     mov    cx,ax            ; move this many bytes
  3703.     mov    ax,ds            ; copy data segment to ...
  3704.     mov    es,ax            ;  ... es
  3705.     mov    ax,videomem        ; copy video segment to ...
  3706.     mov    ds,ax            ;  ... ds
  3707.     rep    movsb            ; zap line into memory
  3708.     mov    ax,es
  3709.     mov    ds,ax            ; restore data segement to ds
  3710.     ret
  3711. mcgareadline    endp
  3712.  
  3713. vgaline proc    near        ; Bank Switch EGA/VGA line write
  3714.     push    cx            ; save a few registers
  3715.     push    ax            ;  ...
  3716.     push    dx            ;  ...
  3717.  
  3718.     mov    bx,dx            ; save the rowcount
  3719.     mov    ax,vxdots        ; compute # of dots / pass
  3720.     shr    ax,1            ;  (given 8 passes)
  3721.     shr    ax,1            ;  ...
  3722.     shr    ax,1            ;  ...
  3723.     mov    di,ax
  3724.     neg    di            ; temp: to see if line will overflow
  3725.     mul    bx            ; now calc first video addr
  3726.     cmp    dx,curbk        ; see if bank changed
  3727.     jne    bank_is_changing    ; if bank change call normaline
  3728.     cmp    ax,di
  3729.     ja    bank_is_changing    ; if bank WILL change, call normaline
  3730.  
  3731.     mov    di,cx            ; compute the starting destination
  3732.     shr    di,1            ; divide by 8
  3733.     shr    di,1            ;  ...
  3734.     shr    di,1            ;  ...
  3735.     add    di,ax            ; add the first pixel offset
  3736.  
  3737.     mov    dx,03ceh        ; set up graphics cntrlr addr
  3738.     mov    ax,8008h        ; set up for the bit mask
  3739.     and    cx,7            ; adjust for the first pixel offset
  3740.     ror    ah,cl            ;  ...
  3741.  
  3742.     pop    bx            ; flush old DX value
  3743.     pop    bx            ; flush old AX value
  3744.     pop    cx            ; flush old CX value
  3745.     sub    bx,cx            ; convert to a length value
  3746.     add    bx,si            ; locate the last source locn
  3747.  
  3748.     mov    cx,ax            ; save the bit mask
  3749.  
  3750. vgaline1:
  3751.     out    dx,ax            ; set the graphics bit mask
  3752.     push    ax            ; save registers for a tad
  3753.     push    si            ;  ...
  3754.     push    di            ;  ...
  3755. vgaline2:
  3756.     mov    ah,ds:[si]        ; get the color
  3757.     mov    al,0            ; set set/reset registers
  3758.     out    dx,ax            ;  do it.
  3759.     mov    ax,0f01h        ; enable set/reset registers
  3760.     out    dx,ax            ;  do it.
  3761.     or    es:[di],al        ; update all bit planes
  3762.     inc    di            ; set up the next video addr
  3763.     add    si,8            ;  and the next source addr
  3764.     cmp    si,bx            ; are we beyond the end?
  3765.     jbe    vgaline2        ; loop if more dots this pass
  3766.     pop    di            ; restore the saved registers
  3767.     pop    si            ;  ...
  3768.     pop    ax            ;  ...
  3769.     inc    si            ; offset the source 1 byte
  3770.     cmp    si,bx            ; are we beyond the end?
  3771.     ja    vgaline4        ; stop if no more dots this pass
  3772.     ror    ah,1            ; alter bit mask value
  3773.     cmp    ah,80h            ; time to update DI:
  3774.     jne    vgaline3        ;  nope
  3775.     inc    di            ;  yup
  3776. vgaline3:
  3777.     cmp    ah,ch            ; already done all 8 of them?
  3778.     jne    vgaline1        ;  nope.  do another one.
  3779. vgaline4:
  3780. ;;;    call    videocleanup        ; else cleanup time.
  3781.     ret                ;  and we done.
  3782.  
  3783. bank_is_changing:
  3784.     pop    dx            ; restore the registers
  3785.     pop    ax            ;  ...
  3786.     pop    cx            ;  ...
  3787.     call    normaline        ; just calling newbank didn't quite
  3788.     ret                ;  work. This depends on no bank
  3789. vgaline endp                ;  change mid line (ok for 1024 wide)
  3790.  
  3791. vgareadline    proc    near        ; Bank Switch EGA/VGA line read
  3792.     push    cx            ; save a few registers
  3793.     push    ax            ;  ...
  3794.     push    dx            ;  ...
  3795.  
  3796.     mov    bx,dx            ; save the rowcount
  3797.     mov    ax,vxdots        ; compute # of dots / pass
  3798.     shr    ax,1            ;  (given 8 passes)
  3799.     shr    ax,1            ;  ...
  3800.     shr    ax,1            ;  ...
  3801.     mul    bx            ; now calc first video addr
  3802.     cmp    dx,curbk        ; see if bank changed
  3803.     jne    bank_is_changing    ; if bank change call normaline
  3804.  
  3805.     mov    si,cx            ; compute the starting destination
  3806.     shr    si,1            ; divide by 8
  3807.     shr    si,1            ;  ...
  3808.     shr    si,1            ;  ...
  3809.     add    si,ax            ; add the first pixel offset
  3810.  
  3811.     and    cx,7            ; adjust for the first pixel offset
  3812.     mov    ch,cl            ; save the original offset value
  3813.  
  3814.     pop    bx            ; flush old DX value
  3815.     pop    bx            ; flush old AX value
  3816.     pop    ax            ; flush old CX value
  3817.     sub    bx,ax            ; convert to a length value
  3818.     add    bx,di            ; locate the last dest locn
  3819.  
  3820.     mov    ax,0a000h        ; EGA/VGA screen starts here
  3821.     mov    es,ax            ;  ...
  3822.  
  3823.     mov    dx,03ceh        ; set up graphics cntrlr addr
  3824.  
  3825. vgaline1:
  3826.     push    bx            ; save BX for a tad
  3827.     mov    ch,80h            ; bit mask to shift
  3828.     shr    ch,cl            ;  ...
  3829.     mov    bx,0            ; initialize bits-read value (none)
  3830.     mov    ax,0304h        ; set up controller address register
  3831. vgareadloop:
  3832.     out    dx,ax            ; do it
  3833.     mov    bh,es:[si]        ; retrieve the old value
  3834.     and    bh,ch            ; mask one bit
  3835.     neg    bh            ; set bit 7 correctly
  3836.     rol    bx,1            ; rotate the bit into bl
  3837.     dec    ah            ; go for another bit?
  3838.     jge    vgareadloop        ;  sure, why not.
  3839.     mov    ds:[di],bl        ; returned pixel value
  3840.     pop    bx            ; restore BX
  3841.     inc    di            ; set up the next dest addr
  3842.     cmp    di,bx            ; are we beyond the end?
  3843.     ja    vgaline3        ;  yup.  We done.
  3844.     inc    cl            ; alter bit mask value
  3845.     cmp    cl,8            ; time to update SI:
  3846.     jne    vgaline2        ;  nope
  3847.     inc    si            ;  yup
  3848.     mov    cl,0            ;  ...
  3849. vgaline2:
  3850.     jmp    short vgaline1        ;  do another one.
  3851.  
  3852. vgaline3:
  3853. ;;;    call    videocleanup        ; else cleanup time.
  3854.     ret                ;  and we done.
  3855.  
  3856. bank_is_changing:
  3857.     pop    dx            ; restore the registers
  3858.     pop    ax            ;  ...
  3859.     pop    cx            ;  ...
  3860.     call    normalineread        ; just calling newbank didn't quite
  3861.     ret                ;  work. This depends on no bank
  3862. vgareadline    endp            ;  change mid line (ok for 1024 wide)
  3863.  
  3864. super256lineaddr    proc    near        ; super VGA 256 colors
  3865.     mov    ax,vxdots     ; this many dots / line
  3866.     mov    bx,dx         ; rowcount
  3867.     mul    bx         ; times this many lines
  3868.     push    ax         ; save pixel address for later
  3869.     cmp    dx,curbk     ; bank ok?
  3870.     push    dx         ; save bank
  3871.     je    bank_is_ok     ; jump if bank ok
  3872.     mov    al,dl         ; newbank needs bank in al
  3873.     call    far ptr newbank
  3874. bank_is_ok:
  3875.     inc    bx         ; next row
  3876.     mov    ax,vxdots     ; this many dots / line
  3877.     mul    bx         ; times this many lines
  3878.     sub    ax,1         ; back up some to the last pixel of the
  3879.     sbb    dx,0         ; previous line
  3880.     pop    bx         ; bank at start of row
  3881.     pop    ax         ; ax = offset of row in video memory
  3882.     ret
  3883. super256lineaddr endp
  3884.  
  3885. super256line    proc    near        ; super VGA 256 colors
  3886.     push    ax            ; stop col
  3887.     push    dx            ; row
  3888.     call super256lineaddr        ; ax=video,dl=newbank,bl=oldbank
  3889.     mov    di,ax            ; video offset
  3890.     cmp    dl,bl            ; did bank change?
  3891.     pop    dx            ; row
  3892.     pop    ax            ; stop col
  3893.     jne    bank_did_chg
  3894.     add    di,cx            ; add start col to video address
  3895.     sub    ax,cx            ; ax = stop - start
  3896.     mov    cx,ax            ;  + start column
  3897.     inc    cx            ; number of bytes to move
  3898.     rep    movsb            ; zap line into memory
  3899.     jmp    short linedone
  3900. bank_did_chg:
  3901.     call    normaline        ; normaline can handle bank change
  3902. linedone:
  3903.     ret
  3904. super256line    endp
  3905.  
  3906. super256readline    proc    near     ; super VGA 256 colors
  3907.     push    ax            ; stop col
  3908.     push    dx            ; row
  3909.     call super256lineaddr        ; ax=video,dl=newbank,bl=oldbank
  3910.     mov    si,ax            ; video offset
  3911.     cmp    dl,bl            ; did bank change?
  3912.     pop    dx            ; row
  3913.     pop    ax            ; stop col
  3914.     jne    bank_did_chg
  3915.  
  3916.     add    si,cx            ; add start col to video address
  3917.     sub    ax,cx            ; ax = stop - start
  3918.     mov    cx,ax            ;  + start column
  3919.     inc    cx            ; number of bytes to move
  3920.     mov    ax,ds            ; save data segment to es
  3921.     mov    es,ax
  3922.     mov    ax,videomem        ; video segment to es
  3923.     mov    ds,ax
  3924.     rep    movsb            ; zap line into memory
  3925.     mov    ax,es            ; restore data segment to ds
  3926.     mov    ds,ax
  3927.     jmp    short linedone
  3928. bank_did_chg:
  3929.     call    normalineread        ; normaline can handle bank change
  3930. linedone:
  3931.     ret
  3932. super256readline    endp
  3933.  
  3934. tweak256line    proc    near        ; Normal Line:    no assumptions
  3935.   local plane:byte
  3936.     mov    bx,ax            ; bx = stop col
  3937.     sub    bx,cx            ; bx = stop-start
  3938.     inc    bx            ; bx = how many pixels to write
  3939.     cmp    bx,3            ; less than four points?
  3940.     jg    nottoosmall        ; algorithm won't work as written
  3941.     call    normaline        ;  - give up and call normaline
  3942.     ret                ; we done
  3943. nottoosmall:                ; at least four points - go for it!
  3944.     push    bx            ; save number of pixels
  3945.     and    bx,3            ;  pixels modulo 4 = no of extra pts
  3946.     mov    ax,vxdots        ; width of video row
  3947. ;;    shr    ax, 1
  3948. ;;    shr    ax, 1            ; now ax = vxdots/4
  3949.     mul    dx            ; ax points to start of desired row
  3950.     push    cx            ; Save starting column for later
  3951.     shr    cx,1            ; There are 4 pixels at each address
  3952.     shr    cx,1            ;   so divide X by 4
  3953.     add    ax,cx            ; Point to pixel's address
  3954.     mov    di,ax            ; video offset of first point
  3955.     pop    cx            ; Retrieve starting column
  3956.     and    cl,3            ; Get the plane number of the pixel
  3957.     mov    ah,1
  3958.     shl    ah,cl            ; Set the bit corresponding to the plane
  3959.                     ;  the pixel is in
  3960.     mov    plane,ah        ; Save starting plane for ending test
  3961.     mov    al,MAP_MASK        ;
  3962.     mov    dx,SC_INDEX
  3963.     pop    cx            ; number of pixels to write
  3964.     shr    cx,1
  3965.     shr    cx,1            ; cx = number of pixels/4
  3966.     cmp    bx,0            ; extra pixels?
  3967.     je    tweak256line1        ; nope - don't add one
  3968.     inc    cx            ; yup - add one more pixel
  3969. tweak256line1:
  3970.     OUT     DX,AX            ; set up VGA registers for plane
  3971.     push    cx            ; save registers changed by movsb
  3972.     push    si            ;  ...
  3973.     push    di            ;  ...
  3974. tweak256line2:
  3975.     movsb                ; move the next pixel
  3976.     add    si,3            ; adjust the source addr (+4, not +1)
  3977.     loop    tweak256line2        ; loop if more dots this pass
  3978.     pop    di            ; restore the saved registers
  3979.     pop    si            ;  ...
  3980.     pop    cx            ;  ...
  3981.     dec    bx            ; one less extra pixel
  3982.     cmp    bx,0            ; out of extra pixels?
  3983.     jne    noextra
  3984.     dec    cx            ; yup - next time one fewer to write
  3985. noextra:
  3986.     inc    si            ; offset the source 1 byte
  3987.     shl    ah,1            ; set up for the next video plane
  3988.     cmp    ah,16            ; at last plane?
  3989.     jne    notlastplane
  3990.     mov    ah,1            ; start over with plane 0
  3991.     inc    di            ; bump up video memory
  3992. notlastplane:
  3993.     cmp    ah,plane        ; back to first plane?
  3994.     jne    tweak256line1        ;  nope.  perform another loop.
  3995.     ret
  3996. tweak256line    endp
  3997.  
  3998. tweak256readline    proc    near        ; Normal Line:    no assumptions
  3999.   local plane:byte
  4000.     mov    bx,ax            ; bx = stop col
  4001.     sub    bx,cx            ; bx = stop-start
  4002.     inc    bx            ; bx = how many pixels to write
  4003.     cmp    bx,3            ; less than four points?
  4004.     jg    nottoosmall        ; algorithm won't work as written
  4005.     call    normalineread        ;  - give up and call normalineread
  4006.     ret                ; we done
  4007. nottoosmall:                ; at least four points - go for it!
  4008.     push    bx            ; save number of pixels
  4009.     and    bx,3            ;  pixels modulo 4 = no of extra pts
  4010.     mov    ax,vxdots        ; width of video row
  4011. ;;    shr    ax, 1
  4012. ;;    shr    ax, 1            ; now ax = vxdots/4
  4013.     mul    dx            ; ax points to start of desired row
  4014.     push    cx            ; Save starting column for later
  4015.     shr    cx,1            ; There are 4 pixels at each address
  4016.     shr    cx,1            ;   so divide X by 4
  4017.     add    ax,cx            ; Point to pixel's address
  4018.     mov    si,ax
  4019.     pop    cx            ; Retrieve starting column
  4020.     and    cl,3            ; Get the plane number of the pixel
  4021.     mov    ah,cl
  4022.     mov    plane,ah        ; Save starting plane
  4023.     mov    al,READ_MAP
  4024.     mov    dx,GC_INDEX
  4025.     pop    cx            ; number of pixels to write
  4026.     shr    cx,1
  4027.     shr    cx,1            ; cx = number of pixels/4
  4028.     cmp    bx,0            ; extra pixels?
  4029.     je    tweak256line1        ; nope - don't add one
  4030.     inc    cx            ; yup - add one more pixel
  4031. tweak256line1:
  4032.     out    dx,ax
  4033.     push    ax            ; save registers
  4034.     push    cx            ;  ...
  4035.     push    di            ;  ...
  4036.     push    si            ;  ...
  4037.     mov    ax,ds            ; copy data segment to es
  4038.     mov    es,ax            ;  ...
  4039.     mov    ax,videomem        ; copy video segment to ds
  4040.     mov    ds,ax            ;  ...
  4041. tweak256line2:
  4042.     movsb                ; move the next pixel
  4043.     add    di,3            ; adjust the source addr (+4, not +1)
  4044.     loop    tweak256line2        ; loop if more dots this pass
  4045.     mov    ax,es
  4046.     mov    ds,ax            ; restore data segement to ds
  4047.     pop    si            ; restore the saved registers
  4048.     pop    di            ;  ...
  4049.     pop    cx            ;  ...
  4050.     pop    ax            ;  ...
  4051.     dec    bx            ; one less extra pixel
  4052.     cmp    bx,0            ; out of extra pixels?
  4053.     jne    noextra
  4054.     dec    cx            ; yup - next time one fewer to write
  4055. noextra:
  4056.     inc    di            ; offset the source 1 byte
  4057.     inc    ah            ; set up for the next video plane
  4058.     and    ah,3
  4059.     cmp    ah,0            ; at last plane?
  4060.     jne    notlastplane
  4061.     inc    si            ; bump up video memory
  4062. notlastplane:
  4063.     cmp    ah,plane        ; back to first plane?
  4064.     jne    tweak256line1        ;  nope.  perform another loop.
  4065.     ret
  4066. tweak256readline    endp
  4067.  
  4068.  
  4069. f85line proc    near
  4070.     call    fr85wbox    ;put out the box
  4071.     ret
  4072. f85line endp
  4073.  
  4074. f85readline proc    near
  4075.     call    fr85rbox    ;read the box
  4076.     ret
  4077. f85readline endp
  4078.  
  4079. ; ******************** Function videocleanup() **************************
  4080.  
  4081. ;    Called at the end of any assembler video read/writes to make
  4082. ;    the world safe for 'printf()'s.
  4083. ;    Currently, only ega/vga needs cleanup work, but who knows?
  4084. ;
  4085.  
  4086. ;;videocleanup      proc      near
  4087. ;;      mov      ax,dotwrite          ; check: were we in EGA/VGA mode?
  4088. ;;      cmp      ax,offset vgawrite      ;  ...
  4089. ;;      jne      short videocleanupdone  ; nope.  no adjustments
  4090. ;;      mov      dx,03ceh          ; graphics controller address
  4091. ;;      mov      ax,0ff08h          ; restore the default bit mask
  4092. ;;      out      dx,ax           ; ...
  4093. ;;      mov      ax,0003h          ; restore the function select
  4094. ;;      out      dx,ax           ;  ...
  4095. ;;      mov      ax,0001h          ; restore the enable set/reset
  4096. ;;      out      dx,ax           ;  ...
  4097. ;;videocleanupdone:
  4098. ;;      ret
  4099. ;;videocleanup      endp
  4100.  
  4101.  
  4102. ; ******************** Zoombox functions **************************
  4103.  
  4104. clearbox proc     uses di si es
  4105.     mov    xorTARGA,1        ; faster to flag xorTARGA rather
  4106.                     ; than check if TARGA is runnin
  4107.  
  4108.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  4109.     mov    es,ax            ; save it here during this routine
  4110.  
  4111.     mov    bx,boxcount        ; load up a counter: # points to clear
  4112.     dec    bx            ; switch to an offset value
  4113. eraseoldbox:
  4114.     shl    bx,1            ; switch to a word pointer
  4115.     mov    cx,boxx[bx]        ; get the (previous) point location
  4116.     mov    dx,boxy[bx]        ;  ...
  4117.     shr    bx,1            ; switch back to character pointer
  4118.     mov    al,boxvalues[bx]    ; get the (previous) color
  4119.     push    bx            ; save the counter
  4120.     call    dotwrite        ; adjust the dot.
  4121.     pop    bx            ; restore the counter
  4122.     dec    bx            ; are we done yet?
  4123.     jns    eraseoldbox        ;  nope.  try again.
  4124.     mov    xorTARGA,0        ; in case of TARGA, no more xor
  4125. ;;;    call    videocleanup        ; perform any video cleanup required
  4126.     ret                ; we done.
  4127. clearbox endp
  4128.  
  4129. dispbox proc    uses di si es
  4130.     mov    xorTARGA,1        ; faster to flag xorTARGA rather
  4131.                     ; than check if TARGA is runnin
  4132.  
  4133.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  4134.     mov    es,ax            ; save it here during this routine
  4135.  
  4136.     mov    bx,boxcount        ; load up a counter: # points to draw
  4137.     dec    bx            ; switch to an offset
  4138. readnewbox:
  4139.     shl    bx,1            ; switch to word counter
  4140.     mov    cx,boxx[bx]        ; get the (new) point location
  4141.     mov    dx,boxy[bx]        ;  ...
  4142.     shr    bx,1            ; switch back to character counter
  4143.     push    bx            ; save the counter
  4144.     call    dotread         ; read the (previous) dot value
  4145.     pop    bx            ; restore the counter
  4146.     mov    boxvalues[bx],al    ; get the (previous) color
  4147.     dec    bx            ; are we done yet?
  4148.     jns    readnewbox        ;  nope.  try again.
  4149.     mov    bx,boxcount        ; load up a counter: # points to draw
  4150.     dec    bx            ; switch to an offset
  4151. drawnewbox:
  4152.     shl    bx,1            ; switch to word counter
  4153.     mov    cx,boxx[bx]        ; get the (new) point location
  4154.     mov    dx,boxy[bx]        ;  ...
  4155.     shr    bx,1            ; switch back to character counter
  4156.     mov    ax,colors        ; set the (new) box color
  4157.     dec    ax
  4158.     and    ax,boxcolor
  4159.     cmp    colors,2        ; uhh, is this a B&W screen?
  4160.     jne    drawnewnotbw        ;  nope.  proceed
  4161.     mov    al,1            ; XOR the old color
  4162.     sub    al,boxvalues[bx]    ;  for visibility
  4163. drawnewnotbw:
  4164.     push    bx            ; save the counter
  4165.     call    dotwrite        ; adjust the dot.
  4166.     pop    bx            ; restore the counter
  4167.     dec    bx            ; are we done yet?
  4168.     jns    drawnewbox        ;  nope.  try again.
  4169.     mov    xorTARGA,0        ; in case of TARGA, no more xor
  4170. ;;;    call    videocleanup        ; perform any video cleanup required
  4171.     ret                ; we done.
  4172.  
  4173. dispbox endp
  4174.  
  4175.  
  4176. ; ********************** Function setvideotext() ************************
  4177.  
  4178. ;    Sets video to text mode, using setvideomode to do the work.
  4179.  
  4180. setvideotext    proc
  4181.     sub    ax,ax
  4182.     mov    dotmode,ax        ; make this zero to avoid trouble
  4183.     push    ax
  4184.     push    ax
  4185.     push    ax
  4186.     mov    ax,3
  4187.     push    ax
  4188.     call    far ptr setvideomode    ; (3,0,0,0)
  4189.     add    sp,8
  4190.     ret
  4191. setvideotext    endp
  4192.  
  4193.  
  4194. ; **************** Function setvideomode(ax, bx, cx, dx) ****************
  4195.  
  4196. ;    This function sets the (alphanumeric or graphic) video mode
  4197. ;    of the monitor.   Called with the proper values of AX thru DX.
  4198. ;    No returned values, as there is no particular standard to
  4199. ;    adhere to in this case.
  4200.  
  4201. ;    (SPECIAL "TWEAKED" VGA VALUES:  if AX==BX==CX==0, assume we have a
  4202. ;    genuine VGA or register compatable adapter and program the registers
  4203. ;    directly using the coded value in DX)
  4204.  
  4205. setvideomode    proc    uses di si es,argax:word,argbx:word,argcx:word,argdx:word
  4206.  
  4207.     mov    ax,sxdots        ; initially, set the virtual line
  4208.     mov    vxdots,ax        ; to be the scan line length
  4209.  
  4210.     cmp    dotmode, 29
  4211.     jne    NotTrueColorMode
  4212.     jmp    TrueColorAuto
  4213. NotTrueColorMode:
  4214.     cmp    diskflag,1        ; is disk video active?
  4215.     jne    nodiskvideo        ;  nope.
  4216.     call    far ptr enddisk     ; yup, external disk-video end routine
  4217. nodiskvideo:
  4218.     cmp    videoflag,1        ; say, was the last video your-own?
  4219.     jne    novideovideo        ;  nope.
  4220.     call    far ptr endvideo    ; yup, external your-own end routine
  4221.     mov    videoflag,0        ; set flag: no your-own-video
  4222.     jmp    short notarga
  4223. novideovideo:
  4224.     cmp    tgaflag,1        ; TARGA MODIFIED 2 June 89 j mclain
  4225.     jne    notarga
  4226.     call    far ptr EndTGA        ; endTGA( void )
  4227.     mov    tgaflag,0        ; set flag: targa cleaned up
  4228. notarga:
  4229.  
  4230.     cmp    xga_isinmode,0        ; XGA in graphics mode?
  4231.     je    noxga            ; nope
  4232.     mov    ax,0            ; pull it out of graphics mode
  4233.     push    ax
  4234.     mov    xga_clearvideo,al
  4235.     call    far ptr xga_mode
  4236.     pop    ax
  4237. noxga:
  4238.  
  4239.     cmp    f85flag, 1        ; was the last video 8514?
  4240.     jne    no8514            ; nope.
  4241.     call    f85end
  4242.     mov    f85flag, 0
  4243. no8514:
  4244.     cmp    HGCflag, 1        ; was last video Hercules
  4245.     jne    noHGC            ; nope
  4246.     call    hgcend
  4247.     mov    HGCflag, 0
  4248. noHGC:
  4249.     mov    oktoprint,1        ; say it's OK to use printf()
  4250.     mov    goodmode,1        ; assume a good video mode
  4251.     mov    xga_loaddac,1        ; tell the XGA to fake a 'loaddac'
  4252.     mov    ax,video_bankadr    ; restore the results of 'whichvga()'
  4253.     mov    [bankadr],ax        ;  ...
  4254.     mov    ax,video_bankseg    ;  ...
  4255.     mov    [bankseg],ax        ;  ...
  4256.  
  4257.     mov    ax,argax        ; load up for the interrupt call
  4258.     mov    bx,argbx        ;  ...
  4259.     mov    cx,argcx        ;  ...
  4260.     mov    dx,argdx        ;  ...
  4261.  
  4262.     mov    videoax,ax        ; save the values for future use
  4263.     mov    videobx,bx        ;  ...
  4264.     mov    videocx,cx        ;  ...
  4265.     mov    videodx,dx        ;  ...
  4266.  
  4267.     call    setvideo        ; call the internal routine first
  4268.  
  4269.     cmp    goodmode,0        ; is it still a good video mode?
  4270.     jne    videomodeisgood     ; yup.
  4271.     mov    ax,offset nullwrite    ; set up null write-a-dot routine
  4272.     mov    bx,offset mcgaread    ; set up null read-a-dot  routine
  4273.     mov    cx,offset normaline    ; set up normal linewrite routine
  4274.     mov    dx,offset mcgareadline    ; set up normal linewrite routine
  4275.     mov    si,offset swapnormread    ; set up the normal swap routine
  4276.     jmp    videomode        ; return to common code
  4277.  
  4278. videomodeisgood:
  4279.     mov    bx,dotmode        ; set up for a video table jump
  4280.     cmp    bx,30            ; are we within the range of dotmodes?
  4281.     jbe    videomodesetup        ; yup.    all is OK
  4282.     mov    bx,0            ; nope.  use dullnormalmode
  4283. videomodesetup:
  4284.     shl    bx,1            ; switch to a word offset
  4285.     mov    bx,cs:videomodetable[bx]    ; get the next step
  4286.     jmp    bx            ; and go there
  4287. videomodetable    dw    offset dullnormalmode    ; mode 0
  4288.     dw    offset dullnormalmode    ; mode 1
  4289.     dw    offset vgamode        ; mode 2
  4290.     dw    offset mcgamode     ; mode 3
  4291.     dw    offset tseng256mode    ; mode 4
  4292.     dw    offset paradise256mode    ; mode 5
  4293.     dw    offset video7256mode    ; mode 6
  4294.     dw    offset tweak256mode    ; mode 7
  4295.     dw    offset everex16mode    ; mode 8
  4296.     dw    offset targaMode    ; mode 9
  4297.     dw    offset hgcmode        ; mode 10
  4298.     dw    offset diskmode     ; mode 11
  4299.     dw    offset f8514mode    ; mode 12
  4300.     dw    offset cgamode        ; mode 13
  4301.     dw    offset tandymode    ; mode 14
  4302.     dw    offset trident256mode    ; mode 15
  4303.     dw    offset chipstech256mode ; mode 16
  4304.     dw    offset ati256mode    ; mode 17
  4305.     dw    offset everex256mode    ; mode 18
  4306.     dw    offset yourownmode    ; mode 19
  4307.     dw    offset ati1024mode    ; mode 20
  4308.     dw    offset tseng16mode    ; mode 21
  4309.     dw    offset trident16mode    ; mode 22
  4310.     dw    offset video716mode    ; mode 23
  4311.     dw    offset paradise16mode    ; mode 24
  4312.     dw    offset chipstech16mode    ; mode 25
  4313.     dw    offset everex16mode    ; mode 26
  4314.     dw    offset VGAautomode    ; mode 27
  4315.     dw    offset VESAmode     ; mode 28
  4316.     dw    offset TrueColorAuto    ; mode 29
  4317.     dw    offset dullnormalmode    ; mode 30
  4318.     dw    offset dullnormalmode    ; mode 31
  4319.  
  4320. tandymode:    ; from Joseph Albrecht
  4321.     mov    tandyseg,0b800h     ; set video segment address
  4322.     mov    tandyofs,0        ; set video offset address
  4323.     mov    ax,offset plottandy16    ; set up write-a-dot
  4324.     mov    bx,offset gettandy16    ; set up read-a-dot
  4325.     mov    cx,offset normaline    ; set up the normal linewrite routine
  4326.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4327.     mov    si,offset swapnormread    ; set up the normal swap routine
  4328.     cmp    videoax,8        ; check for 160x200x16 color mode
  4329.     je    tandy16low        ; ..
  4330.     cmp    videoax,9        ; check for 320x200x16 color mode
  4331.     je    tandy16med        ; ..
  4332.     cmp    videoax,0ah        ; check for 640x200x4 color mode
  4333.     je    tandy4high        ; ..
  4334.     cmp    videoax,0bh        ; check for 640x200x16 color mode
  4335.     je    tandy16high        ; ..
  4336. tandy16low:
  4337.     mov    tandyscan,offset scan16k; set scan line address table
  4338.     jmp    videomode        ; return to common code
  4339. tandy16med:
  4340.     mov    tandyscan,offset scan32k; set scan line address table
  4341.     jmp    videomode        ; return to common code
  4342. tandy4high:
  4343.     mov    ax,offset plottandy4    ; set up write-a-dot
  4344.     mov    bx,offset gettandy4    ; set up read-a-dot
  4345.     jmp    videomode        ; return to common code
  4346. tandy16high:
  4347.     mov    tandyseg,0a000h     ; set video segment address
  4348.     mov    tandyofs,8000h        ; set video offset address
  4349.     mov    tandyscan,offset scan64k; set scan line address table
  4350.     jmp    videomode        ; return to common code
  4351. dullnormalmode:
  4352.     mov    ax,offset normalwrite    ; set up the BIOS write-a-dot routine
  4353.     mov    bx,offset normalread    ; set up the BIOS read-a-dot  routine
  4354.     mov    cx,offset normaline    ; set up the normal linewrite routine
  4355.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4356.     mov    si,offset swapnormread    ; set up the normal swap routine
  4357.     jmp    videomode        ; return to common code
  4358. mcgamode:
  4359.     mov    ax,offset mcgawrite    ; set up MCGA write-a-dot routine
  4360.     mov    bx,offset mcgaread    ; set up MCGA read-a-dot  routine
  4361.     mov    cx,offset mcgaline    ; set up the MCGA linewrite routine
  4362.     mov    dx,offset mcgareadline    ; set up the MCGA lineread  routine
  4363.     mov    si,offset swap256    ; set up the MCGA swap routine
  4364.     jmp    videomode        ; return to common code
  4365. tseng16mode:
  4366.     mov    tseng,1         ; set chipset flag
  4367.     mov    [bankadr],offset $tseng
  4368.     mov    [bankseg],seg $tseng
  4369.     jmp    vgamode     ; set ega/vga functions
  4370. trident16mode:
  4371.     mov    trident,1        ; set chipset flag
  4372.     mov    [bankadr],offset $trident
  4373.     mov    [bankseg],seg $trident
  4374.     jmp    vgamode
  4375. video716mode:
  4376.     mov    video7,1        ; set chipset flag
  4377.     mov    [bankadr],offset $video7
  4378.     mov    [bankseg],seg $video7
  4379.     jmp    vgamode
  4380. paradise16mode:
  4381.     mov    paradise,1        ; set chipset flag
  4382.     mov    [bankadr],offset $paradise
  4383.     mov    [bankseg],seg $paradise
  4384.     jmp    vgamode
  4385. chipstech16mode:
  4386.     mov    chipstech,1        ; set chipset flag
  4387.     mov    [bankadr],offset $chipstech
  4388.     mov    [bankseg],seg $chipstech
  4389.     jmp    vgamode
  4390. everex16mode:
  4391.     mov    everex,1        ; set chipset flag
  4392.     mov    [bankadr],offset $everex
  4393.     mov    [bankseg],seg $everex
  4394.     jmp    vgamode
  4395. VESAmode:                ; set VESA 16-color mode
  4396.     mov    ax,word ptr vesa_mapper
  4397.     mov    [bankadr],ax
  4398.     mov    ax,word ptr vesa_mapper+2
  4399.     mov    [bankseg],ax
  4400. VGAautomode:                ; set VGA auto-detect mode
  4401.     cmp    colors,256        ; 256 colors?
  4402.     je    VGAauto256mode        ; just like SuperVGA
  4403.     cmp    xga_isinmode,0        ; in an XGA mode?
  4404.     jne    xgamode
  4405.     cmp    colors,16        ; 16 colors?
  4406.     je    vgamode         ; just like a VGA
  4407.     jmp    dullnormalmode        ; otherwise, use the BIOS
  4408.  
  4409. xgamode:
  4410.     mov    ax,offset xga_16write       ; set up XGA write-a-dot routine
  4411.     mov    bx,offset xga_16read       ; set up XGA read-a-dot  routine
  4412.     mov    cx,offset xga_16linewrite  ; set up the XGA linewrite routine
  4413.     mov    dx,offset normalineread    ; set up the XGA lineread  routine
  4414.     mov    si,offset swap256       ; set up the swap routine
  4415.     jmp    videomode           ; return to common code
  4416.  
  4417. VGAauto256mode:
  4418.     jmp    super256mode        ; just like a SuperVGA
  4419. egamode:
  4420. vgamode:
  4421. ;;;    shr    vxdots,1        ; scan line increment is in bytes...
  4422. ;;;    shr    vxdots,1
  4423. ;;;    shr    vxdots,1
  4424.     mov    ax,offset vgawrite    ; set up EGA/VGA write-a-dot routine.
  4425.     mov    bx,offset vgaread    ; set up EGA/VGA read-a-dot  routine
  4426.     mov    cx,offset vgaline    ; set up the EGA/VGA linewrite routine
  4427.     mov    dx,offset vgareadline    ; set up the EGA/VGA lineread  routine
  4428.     mov    si,offset swapvga    ; set up the EGA/VGA swap routine
  4429.     jmp    videomode        ; return to common code
  4430. tseng256mode:
  4431.     mov    tseng,1         ; set chipset flag
  4432.     mov    [bankadr],offset $tseng
  4433.     mov    [bankseg],seg $tseng
  4434.     jmp    super256mode        ; set super VGA linear memory functions
  4435. paradise256mode:
  4436.     mov    paradise,1        ; set chipset flag
  4437.     mov    [bankadr],offset $paradise
  4438.     mov    [bankseg],seg $paradise
  4439.     jmp    super256mode        ; set super VGA linear memory functions
  4440. video7256mode:
  4441.     mov    video7, 1        ; set chipset flag
  4442.     mov    [bankadr],offset $video7
  4443.     mov    [bankseg],seg $video7
  4444.     jmp    super256mode        ; set super VGA linear memory functions
  4445. trident256mode:
  4446.     mov    trident,1        ; set chipset flag
  4447.     mov    [bankadr],offset $trident
  4448.     mov    [bankseg],seg $trident
  4449.     jmp    super256mode        ; set super VGA linear memory functions
  4450. chipstech256mode:
  4451.     mov    chipstech,1        ; set chipset flag
  4452.     mov    [bankadr],offset $chipstech
  4453.     mov    [bankseg],seg $chipstech
  4454.     jmp    super256mode        ; set super VGA linear memory functions
  4455. ati256mode:
  4456.     mov    ativga,1        ; set chipset flag
  4457.     mov    [bankadr],offset $ativga
  4458.     mov    [bankseg],seg $ativga
  4459.     jmp    super256mode        ; set super VGA linear memory functions
  4460. everex256mode:
  4461.     mov    everex,1        ; set chipset flag
  4462.     mov    [bankadr],offset $everex
  4463.     mov    [bankseg],seg $everex
  4464.     jmp    super256mode        ; set super VGA linear memory functions
  4465. VGA256automode:             ; Auto-detect SuperVGA
  4466.     jmp    super256mode        ; set super VGA linear memory functions
  4467. VESA256mode:                ; set VESA 256-color mode
  4468.     mov    ax,word ptr vesa_mapper
  4469.     mov    [bankadr],ax
  4470.     mov    ax,word ptr vesa_mapper+2
  4471.     mov    [bankseg],ax
  4472.     jmp    super256mode        ; set super VGA linear memory functions
  4473. super256mode:
  4474.     mov    ax,offset super256write ; set up superVGA write-a-dot routine
  4475.     mov    bx,offset super256read    ; set up superVGA read-a-dot  routine
  4476.     mov    cx,offset super256line    ; set up the  linewrite routine
  4477.     mov    dx,offset super256readline ; set up the normal lineread  routine
  4478.     mov    si,offset swap256    ; set up the swap routine
  4479.     jmp    videomode        ; return to common code
  4480. tweak256mode:
  4481.     shr    vxdots,1        ; scan line increment is in bytes...
  4482.     shr    vxdots,1
  4483.     mov    oktoprint,0        ; NOT OK to printf() in this mode
  4484.     mov    ax,offset tweak256write ; set up tweaked-256 write-a-dot
  4485.     mov    bx,offset tweak256read    ; set up tweaked-256 read-a-dot
  4486.     mov    cx,offset tweak256line    ; set up tweaked-256 read-a-line
  4487.     mov    dx,offset tweak256readline ; set up the normal lineread  routine
  4488.     mov    si,offset swapvga    ; set up the swap routine
  4489.     jmp    videomode        ; return to common code
  4490. cgamode:
  4491.     mov    cx,offset normaline    ; set up the normal linewrite routine
  4492.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4493.     mov    si,offset swapnormread    ; set up the normal swap routine
  4494.     cmp    videoax,4        ; check for 320x200x4 color mode
  4495.     je    cga4med         ; ..
  4496.     cmp    videoax,5        ; ..
  4497.     je    cga4med         ; ..
  4498.     cmp    videoax,6        ; check for 640x200x2 color mode
  4499.     je    cga2high        ; ..
  4500. cga4med:
  4501.     mov    ax,offset plotcga4    ; set up CGA write-a-dot
  4502.     mov    bx,offset getcga4    ; set up CGA read-a-dot
  4503.     jmp    videomode        ; return to common code
  4504. cga2high:
  4505.     mov    ax,offset plotcga2    ; set up CGA write-a-dot
  4506.     mov    bx,offset getcga2    ; set up CGA read-a-dot
  4507.     jmp    videomode        ; return to common code
  4508. ati1024mode:
  4509.     mov    ativga,1        ; set ATI flag.
  4510.     mov    ax,offset ati1024write    ; set up ATI1024 write-a-dot
  4511.     mov    bx,offset ati1024read    ; set up ATI1024 read-a-dot
  4512.     mov    cx,offset normaline    ; set up the normal linewrite routine
  4513.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4514.     mov    si,offset swap256    ; set up the swap routine
  4515.     jmp    videomode        ; return to common code
  4516. diskmode:
  4517.     call    far ptr startdisk    ; external disk-video start routine
  4518.     mov    ax,offset diskwrite    ; set up disk-vid write-a-dot routine
  4519.     mov    bx,offset diskread    ; set up disk-vid read-a-dot routine
  4520.     mov    cx,offset normaline    ; set up the normal linewrite routine
  4521.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4522.     mov    si,offset swapnormread    ; set up the normal swap routine
  4523.     jmp    videomode        ; return to common code
  4524. yourownmode:
  4525.     call    far ptr startvideo    ; external your-own start routine
  4526.     mov    ax,offset videowrite    ; set up ur-own-vid write-a-dot routine
  4527.     mov    bx,offset videoread    ; set up ur-own-vid read-a-dot routine
  4528.     mov    cx,offset normaline    ; set up the normal linewrite routine
  4529.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4530.     mov    si,offset swapnormread    ; set up the normal swap routine
  4531.     mov    videoflag,1        ; flag "your-own-end" needed.
  4532.     jmp    videomode        ; return to common code
  4533. targaMode:                ; TARGA MODIFIED 2 June 89 - j mclain
  4534.     call    far ptr StartTGA
  4535.     mov    ax,offset tgawrite    ;
  4536.     mov    bx,offset tgaread    ;
  4537.     mov    cx,offset normaline    ; set up the normal linewrite routine
  4538.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4539.     mov    si,offset swapnormread    ; set up the normal swap routine
  4540.     mov    tgaflag,1        ;
  4541.     jmp    videomode        ; return to common code
  4542. f8514mode:                ; 8514 modes
  4543.     call    open8514        ; start the 8514a
  4544.     jnc    f85ok
  4545.     mov    goodmode,0        ; oops - problems.
  4546.     mov    dotmode, 0        ; if problem starting use normal mode
  4547.     jmp    dullnormalmode
  4548. hgcmode:
  4549.     mov    oktoprint,0        ; NOT OK to printf() in this mode
  4550.     call    hgcstart        ; Initialize the HGC card
  4551.     mov    ax,offset hgcwrite    ; set up HGC write-a-dot routine
  4552.     mov    bx,offset hgcread    ; set up HGC read-a-dot  routine
  4553.     mov    cx,offset normaline    ; set up normal linewrite routine
  4554.     mov    dx,offset normalineread ; set up the normal lineread  routine
  4555.     mov    si,offset swapnormread    ; set up the normal swap routine
  4556.     mov    HGCflag,1        ; flag "HGC-end" needed.
  4557.     jmp    videomode        ; return to common code
  4558. f85ok:
  4559.     mov    ax,offset f85write    ;
  4560.     mov    bx,offset f85read    ;
  4561.     mov    cx,offset f85line    ;
  4562.     mov    dx,offset f85readline    ;
  4563.     mov    si,offset swapnormread    ; set up the normal swap routine
  4564.     mov    f85flag,1        ;
  4565.     mov    oktoprint,0        ; NOT OK to printf() in this mode
  4566.     jmp    videomode        ; return to common code
  4567.  
  4568. TrueColorAuto:
  4569.     cmp    TPlusInstalled, 1
  4570.     jne    NoTPlus
  4571.     push    NonInterlaced
  4572.     push    PixelZoom
  4573.     push    MaxColorRes
  4574.     push    ydots
  4575.     push    xdots
  4576.     call    far ptr MatchTPlusMode
  4577.     add    sp, 10
  4578.     or    ax, ax
  4579.     jz    NoTrueColorCard
  4580.  
  4581.     cmp    ax, 1              ; Are we limited to 256 colors or less?
  4582.     jne    SetTPlusRoutines      ; All right! True color mode!
  4583.  
  4584.     mov    cx, MaxColorRes       ; Aw well, give'm what they want.
  4585.     shl    ax, cl
  4586.     mov    colors, ax
  4587.  
  4588. SetTPlusRoutines:
  4589.     mov    goodmode, 1
  4590.     mov    oktoprint, 1
  4591.     mov    ax, offset TPlusWrite
  4592.     mov    bx, offset TPlusRead
  4593.     mov    cx, offset normaline
  4594.     mov    dx, offset normalineread
  4595.     mov    si, offset swapnormread
  4596.     jmp    videomode
  4597.  
  4598. NoTPlus:
  4599. NoTrueColorCard:
  4600.     mov    goodmode, 0
  4601.     jmp    videomode
  4602.  
  4603. videomode:
  4604.     mov    dotwrite,ax        ; save the results
  4605.     mov    dotread,bx        ;  ...
  4606.     mov    linewrite,cx        ;  ...
  4607.     mov    lineread,dx        ;  ...
  4608.     mov    word ptr swapsetup,si    ;  ...
  4609.     mov    ax,cs            ;  ...
  4610.     mov    word ptr swapsetup+2,ax ;  ...
  4611.  
  4612.     mov    ax,colors        ; calculate the "and" value
  4613.     dec    ax            ; to use for eventual color
  4614.     mov    andcolor,ax        ; selection
  4615.  
  4616.     mov    boxcount,0        ; clear the zoom-box counter
  4617.  
  4618.     mov    daclearn,0        ; set the DAC rotates to learn mode
  4619.     mov    daccount,6        ; initialize the DAC counter
  4620.     cmp    cpu,88            ; say, are we on a 186/286/386?
  4621.     jbe    setvideoslow        ;  boo!  hiss!
  4622.     mov    daclearn,1        ; yup.    bypass learn mode
  4623.     mov    ax,cyclelimit        ;  and go as fast as he wants
  4624.     mov    daccount,ax        ;  ...
  4625. setvideoslow:
  4626.     call    far ptr loaddac     ; load the video dac, if we can
  4627.     ret
  4628. setvideomode    endp
  4629.  
  4630. set_vesa_mapping_func proc near
  4631.     mov    cx, word ptr suffix+2
  4632.     and    cx,0707h
  4633.     cmp    cx,0305h
  4634.     je    use_vesa2
  4635.     cmp    cx,0503h
  4636.     je    use_vesa2
  4637.     test    ch,01h
  4638.     jz    use_vesa1
  4639.     cmp    word ptr suffix+6,32    ; None of the above -- 2 32K R/W?
  4640.     jne    use_vesa1        ;    if not, use original 1 64K R/W!
  4641.     mov    word ptr vesa_mapper,offset $vesa3
  4642.     mov    ax,32
  4643.     div    byte ptr suffix+4    ; Get number of pages in 32K
  4644.     mov    vesa_gran_offset,ax    ; Save it for mapping function
  4645.     xor    dx,dx
  4646.     mov    al,1
  4647.     test    word ptr suffix+8, 00800h
  4648.     jz    low_high_seq
  4649.     xchg    ax,dx
  4650. low_high_seq:
  4651.     mov    vesa_low_window,dx    ; Window number at A000-A7FF
  4652.     mov    vesa_high_window,ax    ; Window number at A800-AFFF
  4653.     jmp    short vesamapselected
  4654. use_vesa2:
  4655.     mov    word ptr vesa_mapper,offset $vesa2
  4656.     jmp    short vesamapselected
  4657. use_vesa1:
  4658.     mov    word ptr vesa_mapper,offset $vesa1
  4659. vesamapselected:
  4660.     mov    word ptr vesa_mapper+2,seg $vesa1
  4661.     ret
  4662. set_vesa_mapping_func endp
  4663.  
  4664.  
  4665. setnullvideo proc
  4666.     mov    ax,offset nullwrite    ; set up null write-a-dot routine
  4667.     mov    dotwrite,ax        ;  ...
  4668.     mov    ax,offset nullread    ; set up null read-a-dot routine
  4669.     mov    dotread,ax        ;  ...
  4670.     ret
  4671. setnullvideo endp
  4672.  
  4673. setvideo    proc    near        ; local set-video more
  4674.  
  4675.     cmp    xga_isinmode,0        ; XGA in graphics mode?
  4676.     je    noxga            ; nope
  4677.     push    ax
  4678.     push    bx
  4679.     push    cx
  4680.     push    dx
  4681.     mov    ax,0            ; pull it out of graphics mode
  4682.     push    ax
  4683.     mov    xga_clearvideo,al
  4684.     call    far ptr xga_mode
  4685.     pop    ax
  4686.     pop    dx
  4687.     pop    cx
  4688.     pop    bx
  4689.     pop    ax
  4690. noxga:
  4691.  
  4692.     push    bp            ; save it around all the int 10s
  4693.     mov    text_type,2        ; set to this for most exit paths
  4694.     mov    si,offset $vesa_nullbank ; set to do nothing if mode not vesa
  4695.     mov    word ptr vesa_bankswitch,si
  4696.     mov    si,seg $vesa_nullbank
  4697.     mov    word ptr vesa_bankswitch+2,si
  4698.     mov    word ptr vesa_mapper,offset $nobank
  4699.     mov    word ptr vesa_mapper+2,seg $nobank
  4700.     mov    tweakflag,0
  4701.  
  4702.     cmp    ax,0            ; TWEAK?:  look for AX==BX==CX==0
  4703.     jne    short setvideobios    ;  ...
  4704.     cmp    bx,0            ;  ...
  4705.     jne    short setvideobios    ;  ...
  4706.     cmp    cx,0            ;  ...
  4707.     jne    short setvideobios    ;  ...
  4708.  
  4709.     cmp    dotmode, 27        ; check for auto-detect modes
  4710.     je    setvideoauto1
  4711.     cmp    dotmode, 20        ; check for auto-detect modes
  4712.     je    setvideoauto1
  4713.     cmp    dotmode, 4        ; check for auto-detect modes
  4714.     je    setvideoauto1
  4715.     cmp    dotmode, 28        ; check for auto-detect modes
  4716.     je    setvideoauto1
  4717.  
  4718.     jmp    setvideoregs        ; anything else - assume register tweak
  4719.  
  4720. setvideoauto1:
  4721.     jmp    setvideoauto        ; stupid short 'je' instruction!!
  4722.  
  4723. setvideobios:
  4724.     mov    text_type,0        ; if next branch taken this is true
  4725.     cmp    ax,3            ; text mode?
  4726.     jne    setvideobios2        ;  nope
  4727.     mov    textaddr,0b800h
  4728.     cmp    mode7text,0        ; egamono/hgc?
  4729.     je    setvideobios_doit    ;  nope.  Just do it.
  4730.     mov    textaddr,0b000h
  4731.     mov    ax,7            ; use mode 7
  4732.     call    maybeor         ; maybe or AL or (for Video-7s) BL
  4733.     push    bp            ; weird but necessary, set mode twice
  4734.     int    10h            ;  get colors right on vga systems
  4735.     pop    bp            ;  ..
  4736.     mov    ax,7            ; for the 2nd hit
  4737.     jmp    short setvideobios_doit
  4738. setvideobios2:
  4739.     mov    text_type,1        ; if next branch taken this is true
  4740.     cmp    ax,6            ; 640x200x2 mode?
  4741.     je    setvideobios_doit    ;  yup.  Just do it.
  4742.     mov    text_type,2        ; not mode 3 nor 6, so this is true
  4743.     mov    si,dotmode        ; compare the dotmode against
  4744.     mov    di,video_type        ; the video type
  4745.     add    si,si            ; (convert to a word pointer)
  4746.     cmp    cs:video_requirements[si],di
  4747.     jbe    setvideobios_doit    ; ok
  4748.     jmp    setvideoerror        ;  Error.
  4749. setvideobios_doit:
  4750.     cmp    dotmode,14        ; check for Tandy 1000 mode
  4751.     jne    setvideobios_doit2    ; ..
  4752.     cmp    ax,0ah            ; check for Tandy 640x200x4 color mode
  4753.     jne    setvideobios_doit1    ; ..
  4754.     push    bp            ; setup Tandy 640x200x4 color mode
  4755.     int    10h            ; ..
  4756.     pop    bp            ; ..
  4757.     mov    di,16            ;port offset for palette registers
  4758.     mov    bx,0b01h        ; remap colors for better display on
  4759.     call    settandypal        ; .. Tandy 640x200x4 color mode
  4760.     mov    di,16            ;port offset for palette registers
  4761.     mov    bx,0d02h        ; ..
  4762.     call    settandypal        ; ..
  4763.     mov    di,16            ;port offset for palette registers
  4764.     mov    bx,0f03h        ; ..
  4765.     call    settandypal        ; ..
  4766.     jmp    setvideobios_worked
  4767. setvideobios_doit1:
  4768.     cmp    ax,0bh            ; check for Tandy 640x200x16 color mode
  4769.     jne    setvideobios_doit2    ; ..
  4770.     call    tandysetup        ; setup Tandy 640x200x16 color mode
  4771.     jmp    setvideobios_worked
  4772. setvideobios_doit2:
  4773.     call    maybeor         ; maybe or AL or (for Video-7s) BL
  4774.     push    bp            ; some BIOS's don't save this
  4775.     int    10h            ; do it via the BIOS.
  4776.     pop    bp            ; restore the saved register
  4777.     cmp    dotmode,28        ; VESA mode?
  4778.     jne    setvideobios_worked    ;  Nope. Return.
  4779.     cmp    ah,0            ; did it work?
  4780.     jne    setvideoerror        ;  Nope. Failed.
  4781.     mov    vesa_granularity,1    ; say use 64K granules
  4782.     push    es            ; set ES == DS
  4783.     mov    ax,ds            ;  ...
  4784.     mov    es,ax            ;  ...
  4785.     mov    ax,4f01h        ; ask about this video mode
  4786.     mov    cx,bx            ;  this mode
  4787.     and    cx,07fffh        ; (oops - correct for the high-bit)
  4788.     mov    di, offset suffix    ; (a safe spot for 256 bytes)
  4789.     int    10h            ; do it
  4790.     cmp    ax,004fh        ; did the call work?
  4791.     jne    nogoodvesamode        ;  nope
  4792.     mov    cx, word ptr suffix    ; get the attributes
  4793.     test    cx,1            ; available video mode?
  4794.     jz    nogoodvesamode        ; nope.  skip some code
  4795.     call    set_vesa_mapping_func
  4796.     mov    cx, word ptr suffix+12    ; get the Bank-switching routine
  4797.     mov    word ptr vesa_bankswitch, cx  ;  ...
  4798.     mov    cx, word ptr suffix+14    ;   ...
  4799.     mov    word ptr vesa_bankswitch+2, cx    ;  ...
  4800.     mov    cx, word ptr suffix+16    ; get the bytes / scan line
  4801.     cmp    cx,0            ; is this entry filled in?
  4802.     je    skipvesafix        ;  nope
  4803. ;;;    cmp    colors,256        ; 256-color mode?
  4804. ;;;    jne    skipvesafix        ;  nope
  4805.     cmp    byte ptr suffix+24,1
  4806.     jbe    store_vesa_bytes
  4807.     shl    cx,1            ; if a planar mode, bits are pixels
  4808.     shl    cx,1            ; so we multiply bytes by 8
  4809.     shl    cx,1
  4810. store_vesa_bytes:
  4811.     mov    vxdots,cx        ; adjust the screen width accordingly XXX
  4812.     cmp    cx,sxdots
  4813.     je    skipvesafix
  4814.     mov    ax,offset swapnormread    ; use the slow swap routine
  4815.     mov    word ptr swapsetup,ax    ;  ...
  4816. skipvesafix:
  4817.     mov    cx, word ptr suffix+4    ; get the granularity
  4818.     cmp    cl,1            ; ensure the divide won't blow out
  4819.     jb    nogoodvesamode        ;  granularity == 0???
  4820.     mov    ax,64            ;  ...
  4821.     div    cl            ; divide 64K by granularity
  4822.     mov    vesa_granularity,al    ; multiply the bank number by this
  4823. nogoodvesamode:
  4824.     pop    es            ; restore ES
  4825.     mov    ax,4f02h        ; restore the original call
  4826. setvideobios_worked:
  4827.     jmp    setvideoreturn        ;  Return.
  4828.  
  4829. setvideoerror:                ; oops.  No match found.
  4830.     mov    goodmode,0        ; note that the video mode is bad
  4831.     mov    ax,3            ; switch to text mode
  4832.     jmp    setvideobios_doit
  4833.  
  4834. setvideoauto:
  4835.     mov    si, video_entries    ; look for the correct resolution
  4836.     sub    si,8            ; get a running start
  4837. setvideoloop:
  4838.     add    si,10            ; get next entry
  4839.     mov    ax,cs:0[si]        ; check X-res
  4840.     cmp    ax,0            ; anything there?
  4841.     je    setvideoerror        ; nope.  No match
  4842.     cmp    ax,sxdots
  4843.     jne    setvideoloop
  4844.     mov    ax,cs:2[si]        ; check Y-res
  4845.     cmp    ax,sydots
  4846.     jne    setvideoloop
  4847.     mov    ax,cs:4[si]        ; check Colors
  4848.     cmp    ax,colors
  4849.     jne    setvideoloop
  4850.     mov    ax,cs:6[si]        ; got one!  Load AX
  4851.     mov    bx,cs:8[si]        ;        Load BX
  4852.  
  4853.     cmp    ax,0ffffh        ; XGA special?
  4854.     jne    notxgamode
  4855.     mov    al,orvideo
  4856.     mov    xga_clearvideo,al
  4857.     cmp    al,0            ; clearing the video?
  4858.     jne    xgask1            ;  yup
  4859.     mov    ax,03h            ; switch to text mode (briefly)
  4860.     int    10h
  4861. xgask1:
  4862.     push    bx
  4863.     call    far ptr xga_mode
  4864.     pop    bx
  4865.     cmp    ax,0
  4866.     je    setvideoloop
  4867.     jmp    setvideoreturn
  4868. notxgamode:
  4869.  
  4870.     cmp    bx,0ffh         ; ATI 1024x768x16 special?
  4871.     jne    notatimode
  4872.     mov    dotmode,20        ; Convert to ATI specs
  4873.     mov    al,65h
  4874.     mov    bx,0
  4875.     jmp    setvideobios
  4876. notatimode:
  4877.     cmp    bx,0feh         ; Tseng 640x400x256 special?
  4878.     jne    nottsengmode
  4879.     mov    ax,0            ; convert to Tseng specs
  4880.     mov    bx,0
  4881.     mov    cx,0
  4882.     mov    dx,10
  4883.     mov    dotmode,4
  4884.     jmp    setvideoregs
  4885. nottsengmode:
  4886.     cmp    bx,0fdh         ; Compaq 640x480x256 special?
  4887.     jne    notcompaqmode
  4888.     mov    vxdots,1024        ; (compaq uses 1024-byte scanlines)
  4889.     mov    bx,offset swapnormread    ; use the slow swap routine
  4890.     mov    word ptr swapsetup,bx    ;  ...
  4891.     mov    bx,0
  4892.     jmp    setvideobios
  4893. notcompaqmode:
  4894.     cmp    ax,4f02h        ; VESA mode?
  4895.     jne    notvesamode
  4896.     mov    dotmode,28        ; convert to VESA specs
  4897. notvesamode:
  4898.     jmp    setvideobios
  4899.  
  4900. setvideoregs:                ; assume genuine VGA and program regs
  4901.     mov    si, dotmode        ; compare the dotmode against
  4902.     mov    di,video_type        ; the video type
  4903.     add    si,si            ; (convert to a word pointer)
  4904.     cmp    cs:video_requirements[si],di
  4905.     jbe    setvideoregs_doit    ;  good value.    Do it.
  4906.     jmp    setvideoerror        ;  bad value.  Error.
  4907. setvideoregs_doit:
  4908.     mov    si,dx            ; get the video table offset
  4909.     shl    si,1            ;  ...
  4910.     mov    si,word ptr tweaks[si]    ;  ...
  4911.  
  4912.     mov    tweaktype, dx        ; save tweaktype
  4913.     cmp    dx,8            ; 360x480 tweak256mode?
  4914.     je    isatweaktype        ; yup
  4915.     cmp    dx,9            ; 320x400 tweak256mode?
  4916.     je    isatweaktype        ; yup
  4917.     cmp    dx,18            ; 320x480 tweak256mode?
  4918.     je    isatweaktype        ; yup
  4919.     cmp    dx,19            ; 320x240 tweak256mode?
  4920.     je    isatweaktype        ; yup
  4921.     cmp    dx,10            ; Tseng tweak?
  4922.     je    tsengtweak        ; yup
  4923. ;Patch - Michael D. Burkey (5/22/90)
  4924.     cmp    dx,14            ; ATI Mode Support
  4925.     je    ATItweak
  4926.     cmp    dx,15
  4927.     je    ATItweak
  4928.     cmp    dx,16
  4929.     je    ATItweak
  4930.     cmp    dx,17
  4931.     je    ATItweak2        ; ATI 832x616 mode
  4932.     cmp    dx,11            ; tweak256mode? (11 & up)
  4933.     jae    isatweaktype        ; yup
  4934. ;End Patch
  4935.     jmp    not256            ; nope none of the above
  4936. tsengtweak:
  4937.     mov    ax,46            ; start with S-VGA mode 2eh
  4938.     call    maybeor         ; maybe don't clear the video memory
  4939.     int    10h            ; let the bios clear the video memory
  4940.     mov    dx,3c2h         ; misc output
  4941.     mov    al,063h         ; dot clock
  4942.     out    dx,al            ; select it
  4943.     mov    dx,3c4h         ; sequencer again
  4944.     mov    ax,0300h        ; restart sequencer
  4945.     out    dx,ax            ; running again
  4946.     jmp    is256;
  4947. ATItweak:
  4948.     mov    ax,62h
  4949. ;; pb, why no maybeor call here?
  4950.     int    10h
  4951.     mov    dx,3c2h
  4952.     mov    al,0e3h
  4953.     out    dx,al
  4954.     mov    dx,3c4h
  4955.     mov    ax,0300h
  4956.     out    dx,ax
  4957.     jmp    is256
  4958.  
  4959. ATItweak2:
  4960.     mov    ax,63h
  4961. ;; pb, why no maybeor call here?
  4962.     int    10h
  4963.     mov    dx,3c4h
  4964.     mov    ax,0300h
  4965.     out    dx,ax
  4966.     jmp    is256
  4967.  
  4968. isatweaktype:
  4969.     mov    tweakflag,1
  4970.     mov    ax,0013h        ; invoke video mode 13h
  4971.     call    maybeor         ; maybe or AL or (for Video-7s) BL
  4972.     int    10h            ; do it
  4973.  
  4974.     mov    dx,3c4h         ; alter sequencer registers
  4975.     mov    ax,0604h        ; disable chain 4
  4976.     out    dx,ax
  4977.  
  4978.     cmp    orvideo,0        ; are we supposed to clear RAM?
  4979.     jne    noclear256        ;  (nope)
  4980.  
  4981.     mov    dx,03c4h        ; alter sequencer registers
  4982.     mov    ax,0f02h        ; enable writes to all planes
  4983.     OUT_WORD
  4984.  
  4985.     push    es            ; save ES for a tad
  4986.     mov    ax,VGA_SEGMENT        ; clear out all 256K of
  4987.     mov    es,ax            ;  video memory
  4988.     sub    di,di            ;  (64K at a time, but with
  4989.     mov    ax,di            ;  all planes enabled)
  4990.     mov    cx,8000h        ;# of words in 64K
  4991.     cld
  4992.     rep stosw            ;clear all of display memory
  4993.     pop    es            ; restore ES
  4994.  
  4995. noclear256:
  4996.     mov    dx,3c4h         ; alter sequencer registers
  4997.     mov    ax,0604h        ; disable chain 4
  4998.     out    dx,ax
  4999.  
  5000.     jmp    short is256        ; forget the ROM characters
  5001.  
  5002. not256:
  5003.  
  5004.     mov    ax,0012h        ; invoke video mode 12h
  5005.     call    maybeor         ; maybe or AL or (for Video-7s) BL
  5006.     int    10h            ; do it.
  5007.  
  5008. is256:    push    es            ; save ES for a tad
  5009.     mov    ax,40h            ; Video BIOS DATA area
  5010.     mov    es,ax            ;  ...
  5011.  
  5012.     mov    dx,word ptr es:[63h]    ; say, where's the 6845?
  5013.     add    dx,6            ; locate the status register
  5014. vrdly1: in    al,dx            ; loop until vertical retrace is off
  5015.     test    al,8            ;   ...
  5016.     jnz    vrdly1            ;   ...
  5017. vrdly2: in    al,dx            ; now loop until it's on!
  5018.     test    al,8            ;   ...
  5019.     jz    vrdly2            ;   ...
  5020.  
  5021.     cli                ; turn off all interrupts
  5022.     mov    dx,tweaktype
  5023.     cmp    dx,9            ; 320x400 mode?
  5024.     je    not256mode        ; yup - skip this stuff
  5025.     cmp    dx,10            ; Tseng tweak mode?
  5026.     je    not256mode        ; yup - skip this stuff
  5027. ;patch #2 (M. Burkey 5/22/90)
  5028.     cmp    dx,17            ; for 832x616 ATI Mode
  5029.     je    not256mode
  5030. ;patch end
  5031.     mov    cl,0E7h         ; value for misc output reg
  5032.     cmp    dx,18            ; 320x480 mode?
  5033.     je    setmisc320        ;  nope, use above value
  5034.     cmp    dx,19            ; 320x240 mode?
  5035.     jne    setmiscoreg        ;  nope, use above value
  5036. setmisc320:
  5037.     mov    cl,0E3h         ; value for misc output reg
  5038. setmiscoreg:
  5039.     mov    dx,03c4h        ; Sequencer Synchronous reset
  5040.     mov    ax,0100h        ; set sequencer reset
  5041.     out    dx,ax
  5042.     mov    dx,03c2h        ; Update Misc Output Reg
  5043.     mov    al,cl
  5044.     out    dx,al
  5045.     mov    dx,03c4h        ; Sequencer Synchronous reset
  5046.     mov    ax,0300h        ; clear sequencer reset
  5047.     out    dx,ax
  5048. not256mode:
  5049.     mov    dx,word ptr es:[63h]    ; say, where's the 6845?
  5050.     add    si,2            ; point SI to the CRTC registers table
  5051.     mov    al,11h            ; deprotect registers 0-7
  5052.     mov    ah,byte ptr [si+11h]
  5053.     and    ah,7fh
  5054.     out    dx,ax
  5055.  
  5056.     mov    cx,18h            ; update this many registers
  5057.     mov    bx,00            ; starting with this one.
  5058. crtcloop:
  5059.     mov    al,bl            ; update this register
  5060.     mov    ah,byte ptr [bx+si]    ; to this
  5061.     out    dx,ax
  5062.     inc    bx            ; ready for the next register
  5063.     loop    crtcloop        ; (if there is a next register)
  5064.     sti                ; restore interrupts
  5065.  
  5066.     pop    es            ; restore ES
  5067.  
  5068. setvideoreturn:
  5069.     mov    curbk,0ffffh        ; stuff impossible value into cur-bank
  5070.     mov    orvideo,0        ; reset the video to clobber memory
  5071.     pop    bp
  5072.     ret
  5073. setvideo    endp
  5074.  
  5075. maybeor proc    near            ; or AL or BL for mon-destr switch
  5076.     cmp    ah,4fh            ; VESA special mode?
  5077.     je    maybeor2        ;  yup.  Do this one different
  5078.     cmp    ah,6fh            ; video-7 special mode?
  5079.     je    maybeor1        ;  yup.  do this one different
  5080.     or    al,orvideo        ; normal non-destructive switch
  5081.     jmp    short maybeor99     ; we done.
  5082. maybeor1:
  5083.     or    bl,orvideo        ; video-7 switch
  5084.     jmp    short maybeor99
  5085. maybeor2:
  5086.     or    bh,orvideo        ; VESA switch
  5087. maybeor99:
  5088.     ret                ; we done.
  5089. maybeor endp
  5090.  
  5091.  
  5092. ; ********* Functions setfortext() and setforgraphics() ************
  5093.  
  5094. ;    setfortext() resets the video for text mode and saves graphics data
  5095. ;    setforgraphics() restores the graphics mode and data
  5096. ;    setclear() clears the screen after setfortext()
  5097.  
  5098. monocolors db  0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  5099.  
  5100. setfortext    proc    uses es si di
  5101.     push    bp            ; save it around the int 10s
  5102.     cmp    dotmode, 12        ;check for 8514
  5103.     jne    tnot8514
  5104.     cmp    f85flag, 0        ;check 8514 active flag
  5105.     je    go_dosettext
  5106.     call    close8514        ;close adapter if not
  5107.     mov    f85flag, 0
  5108. go_dosettext:
  5109.     jmp    dosettext        ; safe to go to mode 3
  5110. tnot8514:
  5111.     cmp    dotmode,9        ; Targa?
  5112.     je    go_dosettext        ;  yup, leave it open & go to text
  5113.  
  5114.     cmp    xga_isinmode,0        ; XGA in graphics mode?
  5115.     je    noxga            ;  nope
  5116.     mov    ax,xga_isinmode     ; remember if we were in XGA mode
  5117.     mov    xga_clearvideo,80h    ; don't clear the video!
  5118.     mov    ax,0            ; switch to VGA (graphics) mode
  5119.     push    ax
  5120.     call    far ptr xga_mode
  5121.     pop    ax            ; proceed on like nothing happened
  5122.     mov    xga_clearvideo,0    ; reset the clear-video flag
  5123. noxga:
  5124.  
  5125.     cmp    dotmode,14        ; (klooge for Tandy 640x200x16)
  5126.     je    setfortextcga
  5127.     cmp    videoax,0        ; check for CGA modes
  5128.     je    go_setfortextnocga    ;  not this one
  5129.     cmp    dotmode,10        ; Hercules?
  5130.     je    setfortextcga        ;  yup
  5131.     cmp    videoax,7        ; <= vid mode 7?
  5132.     jbe    setfortextcga        ;  yup
  5133. go_setfortextnocga:
  5134.     jmp    setfortextnocga     ;  not this one
  5135. setfortextcga:    ; from mode ensures we can go to mode 3, so do it
  5136.     mov    ax,extraseg        ; set ES == Extra Segment
  5137.     add    ax,1000h        ; (plus 64K)
  5138.     mov    es,ax            ;  ...
  5139.     mov    di,4000h        ; save the video data here
  5140.     mov    ax,0b800h        ; video data starts here <XXX>
  5141.     mov    si,0            ;  ...
  5142.     cmp    videoax,3        ; from mode 3?
  5143.     jne    setfortextcga2        ;  nope
  5144.     cmp    mode7text,0        ; egamono/hgc?
  5145.     je    setfortextcga2        ;  nope
  5146.     mov    ax,0b000h        ; video data starts here
  5147. setfortextcga2:
  5148.     mov    cx,2000h        ; save this many words
  5149.     cmp    dotmode,10        ; Hercules?
  5150.     jne    setfortextcganoherc    ;  nope
  5151.     mov    di,0            ; (save 32K)
  5152.     mov    ax,0b000h        ; (from here)
  5153.     mov    cx,4000h        ; (save this many words)
  5154. setfortextcganoherc:
  5155.     cmp    dotmode,14        ; check for Tandy 1000 specific modes
  5156.     jne    setfortextnotandy    ; ..
  5157.     mov    ax,tandyseg        ; video data starts here
  5158.     mov    si,tandyofs        ; save video data here
  5159.     mov    di,0            ; save the video data here
  5160.     mov    cx,4000h        ; save this many words
  5161. setfortextnotandy:
  5162.     push    ds            ; save DS for a tad
  5163.     mov    ds,ax            ;  reset DS
  5164.     cld                ; clear the direction flag
  5165.     rep    movsw            ;  save them.
  5166.     pop    ds            ; restore DS
  5167.     cmp    dotmode,10        ; Hercules?
  5168.     jne    dosettext        ;  nope
  5169.     cmp    HGCflag, 0        ; check HGC active flag
  5170.     je    dosettext
  5171.     call    hgcend            ; close adapter
  5172.     mov    HGCflag, 0
  5173. dosettext:
  5174.     mov    ax,3            ; set up the text call
  5175.     mov    bx,0            ;  ...
  5176.     mov    cx,0            ;  ...
  5177.     mov    dx,0            ;  ...
  5178.     call    setvideo        ; set the video
  5179.     jmp    setfortextreturn
  5180. setfortextnocga:
  5181.     mov    bios_vidsave,0        ; default, not using bios for state save
  5182.     mov    ax,textsafe2        ; videotable override?
  5183.     cmp    ax,0            ;  ...
  5184.     jne    setfortextsafe        ;  yup
  5185.     mov    ax,textsafe        ; nope, use general setting
  5186. setfortextsafe:
  5187.     cmp    ax,2            ; textsafe=no?
  5188.     jne    setforcolortext     ;  nope
  5189.     jmp    setfordummytext     ;  yup, use 640x200x2
  5190. setforcolortext:
  5191.     ; must be ega, mcga, or vga, else we'd have set textsafe=no in runup
  5192.     cmp    ax,4            ; textsafe=save?
  5193.     jne    setforcolortext2    ;  nope
  5194.     mov    ax,0            ; disable the video (I think)
  5195.     call    disablevideo        ;  ...
  5196.     call    far ptr savegraphics    ; C rtn which uses swapsetup
  5197.     call    swapvga_reset        ; some cleanup for swapvga case
  5198.     mov    orvideo,80h        ; preserve memory, just for speed
  5199.     cmp    videoax,0fh        ; ega 640x350x2?
  5200.     jne    dosettext        ;  nope, go call bios for mode 3
  5201.     mov    ax,83h            ; I know this is silly! have to set
  5202.     int    10h            ; mode twice when coming from mode 0fh
  5203.     jmp    dosettext        ; on some machines to get right colors
  5204. setforcolortext2:
  5205.     cmp    ax,3            ; textsafe=bios?
  5206.     jne    setforcolortext3    ;  nope
  5207.     cmp    video_type,5        ; vga?
  5208.     jl    setforcolortext3    ;  nope
  5209.     mov    ax,1c00h        ; check size of reqd save area
  5210.     mov    cx,3            ;  for hardware + bios states
  5211.     int    10h            ;  ask...
  5212.     cmp    al,1ch            ; function recognized?
  5213.     jne    setforcolortext3    ;  nope
  5214.     cmp    bx,4            ; buffer big enough? (3 seems usual)
  5215.     ja    setforcolortext3    ;  nope
  5216.     mov    bios_vidsave,1        ; using bios to save vid state
  5217.     mov    ax,cs            ; ptr to save buffer
  5218.     mov    es,ax            ;  ...
  5219.     mov    bx,offset bios_savebuf    ;  ...
  5220.     mov    ax,1c01h        ;  save state
  5221.     mov    cx,3            ;  hardware + bios
  5222.     int    10h            ;  ...
  5223. setforcolortext3:
  5224.     push    ds            ; save ds
  5225.     mov    ax,extraseg        ; set ES == Extra Segment
  5226.     add    ax,1000h        ; (plus 64K)
  5227.     mov    es,ax            ;  ...
  5228.     cld
  5229.     mov    ax,0a000h        ; video mem address
  5230.     cmp    video_type,4        ; mcga?
  5231.     jne    setfortextegavga    ;  nope
  5232.     mov    ds,ax            ; set ds to video mem
  5233.     xor    di,di            ; from vid offset 0
  5234.     xor    si,si            ; to save offset 0
  5235.     mov    cx,1000h        ; save 4k words
  5236.     rep movsw            ; font info
  5237.     mov    si,8000h        ; from vid offset 8000h
  5238.     mov    cx,0800h        ; save 2k words
  5239.     rep movsw            ; characters and attributes
  5240.     pop    ds            ; restore ds
  5241.     mov    orvideo,80h        ; set the video to preserve memory
  5242.     jmp    dosettext        ; (else more than we saved gets cleared)
  5243. setfortextegavga:
  5244.     sub    ax,ax            ; set bank just in case
  5245.     call far ptr newbank
  5246.     mov    ax,8eh            ; switch to a mode with known mapping
  5247.     cmp    videoax,0fh        ; coming from ega 640x350x2?
  5248.     jne    sftknownmode        ;  nope
  5249.     mov    ax,8fh            ; yup, stay in it but do the set mode
  5250. sftknownmode:
  5251.     int    10h            ; set the safe mode
  5252.     mov    ax,0            ; disable the video (I think)
  5253.     call    disablevideo        ;  ...
  5254.     mov    ax,0a000h        ; video mem address
  5255.     mov    ds,ax            ; set ds to video mem
  5256.     xor    di,di            ; to offset 0 in save area
  5257. ;;    mov    cx,0            ; set to plane 0
  5258. ;;    call    select_vga_plane    ;  ...
  5259. ;;    mov    cx,0800h        ; save 2k words
  5260. ;;    xor    si,si            ; from offset 0 in vid mem
  5261. ;;    rep movsw            ; save plane 0 2k bytes (char values)
  5262.     mov    cx,2            ; set to plane 2
  5263.     call    select_vga_plane    ;  ...
  5264.     mov    cx,1000h        ; save 4k words
  5265.     xor    si,si            ; from offset 0 in vid mem
  5266.     rep movsw            ; save plane 2 8k bytes (font)
  5267. ;;    mov    cx,1            ; set to plane 1
  5268. ;;    call    select_vga_plane    ;  ...
  5269. ;;    mov    cx,0800h        ; save 2k words
  5270. ;;    xor    si,si            ; from offset 0 in vid mem
  5271. ;;    rep movsw            ; save plane 1 2k bytes (attributes)
  5272. ;;    push    ds            ; now zap attributes to zero to
  5273. ;;    pop    es            ;  avoid flicker in the next stages
  5274. ;;    xor    di,di            ;  ...
  5275. ;;    xor    ax,ax            ;  ...
  5276. ;;    mov    cx,0400h        ;  ...
  5277. ;;    rep stosw            ;  ...
  5278.     pop    ds            ; restore ds
  5279.     mov    orvideo,80h        ; set the video to preserve memory
  5280.     mov    ax,3            ; set up the text call
  5281.     mov    bx,0            ;  ...
  5282.     mov    cx,0            ;  ...
  5283.     mov    dx,0            ;  ...
  5284.     call    setvideo        ; set the video
  5285.     push    ds            ; save ds
  5286.     mov    ax,extraseg        ; set ES == Extra Segment
  5287.     add    ax,1000h        ; (plus 64K)
  5288.     mov    es,ax            ;  ...
  5289.     mov    ax,textaddr
  5290.     mov    ds,ax
  5291.     cld
  5292.     xor    si,si
  5293.     mov    di,2000h        ; past the saved font info
  5294.     mov    cx,0800h        ; 2k words (text & attrs)
  5295.     rep    movsw            ; save them
  5296.     pop    ds
  5297.     jmp    setfortextreturn
  5298. setfordummytext:            ; use 640x200x2 simulated text mode
  5299.     mov    ax,0            ; disable the video (I think)
  5300.     call    disablevideo        ;  ...
  5301.     mov    orvideo,80h        ; set the video to preserve memory
  5302.     mov    ax,6            ; set up the text call
  5303.     mov    bx,0            ;  ...
  5304.     mov    cx,0            ;  ...
  5305.     mov    dx,0            ;  ...
  5306.     call    setvideo        ; set the video
  5307.     mov    ax,0            ; disable the video (I think)
  5308.     call    disablevideo        ;  ...
  5309.     cld                ; clear the direction flag
  5310.     mov    ax,extraseg        ; set ES == Extra Segment
  5311.     add    ax,1000h        ; (plus 64K)
  5312.     mov    es,ax            ;  ...
  5313.     mov    di,4000h        ; save the video data here
  5314.     mov    ax,0b800h        ; video data starts here
  5315.     push    ds            ; save DS for a tad
  5316.     mov    ds,ax            ;  reset DS
  5317.     mov    si,0            ;  ...
  5318.     mov    cx,4000         ; save this many words
  5319.     rep    movsw            ;  save them.
  5320.     mov    si,2000h        ;  ...
  5321.     mov    cx,4000         ; save this many words
  5322.     rep    movsw            ;  save them.
  5323.     pop    ds            ; restore DS
  5324.     mov    ax,0b800h        ; clear the video buffer
  5325.     mov    es,ax            ;  ...
  5326.     mov    di,0            ;  ...
  5327.     mov    ax,0            ; to blanks
  5328.     mov    cx,4000         ; this many blanks
  5329.     rep    stosw            ; do it.
  5330.     mov    di,2000h        ;  ...
  5331.     mov    cx,4000         ; this many blanks
  5332.     rep    stosw            ; do it.
  5333.     mov    ax,20h            ; enable the video (I think)
  5334.     call    disablevideo        ;  ...
  5335.     mov    bx,23            ; set mode 6 fgrd to grey
  5336.     mov    cx,2a2ah        ; register 23, rgb white
  5337.     mov    dh,2ah            ;  ...
  5338.     mov    ax,1010h        ; int 10 10-10 affects mcga,vga
  5339.     int    10h            ;  ...
  5340.     mov    ax,cs            ; do it again, another way
  5341.     mov    es,ax            ;  ...
  5342.     mov    dx,offset monocolors    ;  ...
  5343.     mov    ax,1002h        ; int 10 10-02 handles pcjr,ega,vga
  5344.     int    10h            ;  ...
  5345.  
  5346. setfortextreturn:
  5347.     call    far ptr setclear    ; clear and home the cursor
  5348.     pop    bp
  5349.     ret
  5350. setfortext    endp
  5351.  
  5352. setforgraphics    proc    uses es si di
  5353.     push    bp            ; save it around the int 10s
  5354.     cmp    dotmode, 12        ;check for 8514
  5355.     jne    gnot8514
  5356.     cmp    f85flag, 0
  5357.     jne    go_graphicsreturn
  5358.     call    reopen8514
  5359.     mov    f85flag, 1
  5360. go_graphicsreturn:
  5361.     jmp    setforgraphicsreturn
  5362. gnot8514:
  5363.     cmp    dotmode,9        ; Targa?
  5364.     jne    gnottarga        ;  nope
  5365.     call    far ptr ReopenTGA
  5366.     jmp    short go_graphicsreturn
  5367. gnottarga:
  5368.  
  5369.     cmp    dotmode,14        ; check for Tandy 1000 specific modes
  5370.     je    setforgraphicscga    ;  yup
  5371.     cmp    videoax,0        ; check for CGA modes
  5372.     je    setforgraphicsnocga_x    ;  not this one
  5373.     cmp    dotmode,10        ; Hercules?
  5374.     je    setforgraphicscga    ;  yup
  5375.     cmp    videoax,7        ; vid mode <=7?
  5376.     jbe    setforgraphicscga    ;  CGA mode
  5377. setforgraphicsnocga_x:
  5378.     jmp    setforgraphicsnocga
  5379. setforgraphicscga:
  5380.     cmp    dotmode,10        ; Hercules?
  5381.     jne    tnotHGC2        ;  (nope.  dull-normal stuff)
  5382.     call    hgcstart        ; Initialize the HGC card
  5383.     mov    HGCflag,1        ; flag "HGC-end" needed.
  5384.     jmp    short twasHGC2        ; bypass the normal setvideo call
  5385. tnotHGC2:
  5386.     cmp    dotmode,14        ; Tandy?
  5387.     jne    tnottandy1        ;  nope
  5388.     mov    orvideo,80h        ; set the video to preserve memory
  5389. tnottandy1:
  5390.     mov    ax,videoax        ; set up the video call
  5391.     mov    bx,videobx        ;  ...
  5392.     mov    cx,videocx        ;  ...
  5393.     mov    dx,videodx        ;  ...
  5394.     call    setvideo        ; do it.
  5395. twasHGC2:
  5396.     mov    bx,extraseg        ; restore is from Extraseg
  5397.     add    bx,1000h        ; (plus 64K)
  5398.     mov    si,4000h        ; video data is saved here
  5399.     mov    ax,0b800h        ; restore the video area
  5400.     mov    di,0            ;  ...
  5401.     cmp    videoax,3        ; from mode 3?
  5402.     jne    setforgraphicscga2    ;  nope
  5403.     cmp    mode7text,0        ; egamono/hgc?
  5404.     je    setforgraphicscga2    ;  nope
  5405.     mov    ax,0b000h        ; video data starts here
  5406. setforgraphicscga2:
  5407.     mov    cx,2000h        ; restore this many words
  5408.     cmp    dotmode,10        ; Hercules?
  5409.     jne    setforgraphicscganoherc ;  nope
  5410.     mov    si,0            ; (restore 32K)
  5411.     mov    ax,0b000h        ; (to here)
  5412.     mov    cx,4000h        ; (restore this many words)
  5413. setforgraphicscganoherc:
  5414.     cmp    dotmode,14        ; check for Tandy 1000 specific modes
  5415.     jne    tnottandy2        ; ..
  5416.     mov    ax,tandyseg        ; video data starts here
  5417.     mov    di,tandyofs        ; save video data here
  5418.     mov    si,0            ; video data is saved here
  5419.     mov    cx,4000h        ; save this many words
  5420. tnottandy2:
  5421.     push    ds            ; save DX for a tad
  5422.     mov    es,ax            ; load the dest seg into ES
  5423.     mov    ds,bx            ; restore it from the source seg
  5424.     cld                ; clear the direction flag
  5425.     rep    movsw            ; restore them.
  5426.     pop    ds            ; restore DS
  5427.     jmp    setforgraphicsreturn
  5428. setforgraphicsnocga:
  5429.     mov    ax,0            ; disable the video (I think)
  5430.     call    disablevideo        ;  ...
  5431.     cld                ; clear the direction flag
  5432.     mov    ax,textsafe2        ; videotable override?
  5433.     cmp    ax,0            ;  ...
  5434.     jne    setforgraphicssafe    ;  yup
  5435.     mov    ax,textsafe        ; nope, use general setting
  5436. setforgraphicssafe:
  5437.     cmp    ax,2            ; textsafe=no?
  5438.     jne    setforgraphicsnocga2
  5439.     jmp    setfordummygraphics    ;  yup, 640x200x2
  5440. setforgraphicsnocga2:
  5441.     ; must be ega, mcga, or vga, else we'd have set textsafe=no in runup
  5442.     cmp    ax,4            ; textsafe=save?
  5443.     jne    setforgraphicsnocga3    ;  nope
  5444. ;; pb, always clear video here:
  5445. ;;  need if for ega/vga with < 16 colors to clear unused planes
  5446. ;;  and, some bios's don't implement ah or'd with 80h?!?, dodge their bugs
  5447. ;;    cmp    dotmode,2        ; ega/vga, <=16 colors?
  5448. ;;    jne    setfgncfast        ;  nope
  5449. ;;    cmp    colors,16        ; < 16 colors?
  5450. ;;    jae    setfgncfast        ;  nope
  5451. ;;    jmp    short setfgncsetvid    ; special, need unused planes clear
  5452. ;;setfgncfast:
  5453. ;;    mov    orvideo,80h        ; preserve memory (just to be fast)
  5454. ;;setfgncsetvid:
  5455.     mov    ax,videoax        ; set up the video call
  5456.     mov    bx,videobx        ;  ...
  5457.     mov    cx,videocx        ;  ...
  5458.     mov    dx,videodx        ;  ...
  5459.     call    setvideo        ; do it.
  5460.     sub    ax,ax            ; disable the video (I think)
  5461.     call    disablevideo        ;  ...
  5462.     call    far ptr restoregraphics ; C rtn which uses swapsetup
  5463.     call    swapvga_reset        ; some cleanup for swapvga case
  5464.     mov    ax,20h            ; enable the video (I think)
  5465.     call    disablevideo        ;  ...
  5466.     jmp    setforgraphicsreturn
  5467. setforgraphicsnocga3:
  5468.     push    ds            ; save ds
  5469.     mov    ax,0a000h        ; set es to video mem
  5470.     mov    es,ax            ;  ...
  5471.     cmp    video_type,4        ; mcga?
  5472.     jne    setforgraphicsegavga    ;  nope
  5473.     mov    ax,extraseg        ; set DS == Extra Segment
  5474.     add    ax,1000h        ; (plus 64K)
  5475.     mov    ds,ax            ;  ...
  5476.     xor    si,si            ; from save offset 0
  5477.     xor    di,di            ; to vid offset 0
  5478.     mov    cx,1000h        ; restore 4k words
  5479.     rep movsw            ; font info
  5480.     mov    di,8000h        ; to vid offset 8000h
  5481.     mov    cx,0800h        ; restore 2k words
  5482.     rep movsw            ; characters and attributes
  5483.     jmp    short setforgraphicsdoit
  5484. setforgraphicsegavga:
  5485. ;;    mov    cx,0            ; set to plane 0
  5486. ;;    call    select_vga_plane    ;  ...
  5487. ;;    mov    ax,extraseg        ; set DS == Extra Segment
  5488. ;;    add    ax,1000h        ; (plus 64K)
  5489. ;;    mov    ds,ax            ;  ...
  5490. ;;    mov    cx,0800h        ; restore 2k words
  5491. ;;    xor    si,si            ; from offset 0 in save area
  5492. ;;    xor    di,di            ; to offset 0 in vid mem
  5493. ;;    rep movsw            ; restore plane 0 2k bytes (char values)
  5494.     mov    ax,textaddr
  5495.     mov    es,ax
  5496.     mov    ax,extraseg        ; set DS == Extra Segment
  5497.     add    ax,1000h        ; (plus 64K)
  5498.     mov    ds,ax            ;  ...
  5499.     cld
  5500.     xor    di,di
  5501.     mov    si,2000h        ; past the saved font info
  5502.     mov    cx,0800h        ; 2k words (text & attrs)
  5503.     rep    movsw            ; restore them
  5504.     pop    ds
  5505.     mov    ax,8eh            ; switch to a mode with known mapping
  5506.     cmp    videoax,0fh        ; returning to ega 640x350x2?
  5507.     jne    sfgnotega        ;  nope
  5508.     mov    ax,8fh            ; yup, go directly to it
  5509. sfgnotega:
  5510.     int    10h            ; set the safe mode
  5511.     mov    ax,0            ; disable the video (I think)
  5512.     call    disablevideo        ;  ...
  5513.     mov    cx,2            ; set to plane 2
  5514.     call    select_vga_plane    ;  ...
  5515.     push    ds
  5516.     mov    ax,0a000h        ; set es to video mem
  5517.     mov    es,ax            ;  ...
  5518.     mov    ax,extraseg        ; set DS == Extra Segment
  5519.     add    ax,1000h        ; (plus 64K)
  5520.     mov    ds,ax            ;  ...
  5521.     mov    cx,1000h        ; restore 4k words
  5522.     xor    di,di            ; to offset 0 in vid mem
  5523.     xor    si,si            ; from offset 0 in extraseg
  5524.     rep movsw            ; restore plane 2 8k bytes (font)
  5525. ;;    mov    cx,1            ; set to plane 1
  5526. ;;    call    select_vga_plane    ;  ...
  5527. ;;    mov    cx,0800h        ; restore 2k words
  5528. ;;    xor    di,di            ; to offset 0 in vid mem
  5529. ;;    rep movsw            ; restore plane 1 2k bytes (attributes)
  5530.     jmp    short setforgraphicsdoit
  5531. setfordummygraphics:
  5532.     push    ds            ; save ds
  5533.     mov    ax,0b800h        ; restore the video area
  5534.     mov    es,ax            ; ES == video addr
  5535.     mov    di,0            ;  ...
  5536.     mov    ax,extraseg        ;  ...
  5537.     add    ax,1000h        ; (plus 64K)
  5538.     mov    ds,ax            ;  ...
  5539.     mov    si,4000h        ; video data is saved here
  5540.     mov    cx,4000         ; restore this many words
  5541.     rep    movsw            ; restore them.
  5542.     mov    di,2000h
  5543.     mov    cx,4000         ; restore this many words
  5544.     rep    movsw            ; restore them.
  5545. setforgraphicsdoit:
  5546.     pop    ds            ; restore DS
  5547.     cmp    bios_vidsave,0        ; did setfortext use bios state save?
  5548.     je    setforgraphicssetvid    ;  nope
  5549.     mov    ax,cs            ; ptr to save buffer
  5550.     mov    es,ax            ;  ...
  5551.     mov    bx,offset bios_savebuf    ;  ...
  5552.     mov    ax,1c02h        ;  restore state
  5553.     mov    cx,3            ;  hardware + bios
  5554.     int    10h            ;  ...
  5555.     jmp    short setforgraphicsreturn
  5556. setforgraphicssetvid:
  5557.     mov    orvideo,80h        ; set the video to preserve memory
  5558.     mov    ax,videoax        ; set up the video call
  5559.     mov    bx,videobx        ;  ...
  5560.     mov    cx,videocx        ;  ...
  5561.     mov    dx,videodx        ;  ...
  5562.     call    setvideo        ; do it.
  5563.     mov    ax,20h            ; enable the video (I think)
  5564.     call    disablevideo        ;  ...
  5565. setforgraphicsreturn:
  5566.     mov    curbk,0ffffh        ; stuff impossible value into cur-bank
  5567.     mov    ax,1            ; set up call to spindac(0,1)
  5568.     push    ax            ;  ...
  5569.     mov    ax,0            ;  ...
  5570.     push    ax            ;  ...
  5571.     call    far ptr spindac     ; do it.
  5572.     pop    ax            ; restore the registers
  5573.     pop    ax            ;  ...
  5574.     pop    bp
  5575.     ret
  5576. setforgraphics    endp
  5577.  
  5578. ; swapxxx routines: indirect call via swapsetup, used by savegraphics
  5579. ;            and restoregraphics
  5580.  
  5581. swap256     proc uses es si di    ; simple linear banks version
  5582.     mov    ax,word ptr swapoffset+2; high word of offset is bank
  5583.     call    far ptr newbank     ; map in the bank
  5584.     mov    ax,0a000h        ; high word of vid addr
  5585.     mov    word ptr swapvidbuf+2,ax; store it
  5586.     mov    ax,word ptr swapoffset    ; offset in bank
  5587.     mov    word ptr swapvidbuf,ax    ; store as low word of vid addr
  5588.     neg    ax            ; 65536-offset
  5589.     jz    swap256ret        ; offset 0
  5590.     cmp    ax,swaplength        ; rest of bank smaller than req length?
  5591.     jae    swap256ret        ;  nope
  5592.     mov    swaplength,ax        ; yup, reduce length to what's available
  5593. swap256ret:
  5594.     ret
  5595. swap256     endp
  5596.  
  5597. swapvga     proc uses es si di    ; 4 (or less) planes version
  5598.     xor    si,si            ; this will be plane number
  5599.     mov    ax,word ptr swaptotlen    ; dx,ax = total length
  5600.     mov    dx,word ptr swaptotlen+2
  5601.     mov    cx,word ptr swapoffset    ; bx,cx = offset
  5602.     mov    bx,word ptr swapoffset+2
  5603.     cmp    colors,4        ; 4 or 2 color mode?
  5604.     jle    swapvga_2        ;  yup, no plane 2/3
  5605.     shr    dx,1            ; 1/2 of total
  5606.     rcr    ax,1            ;  ...
  5607.     cmp    dx,bx            ; 1/2 total <= offset?
  5608.     jb    swapvga_1        ;  yup
  5609.     ja    swapvga_2        ;  nope
  5610.     cmp    ax,cx            ; ...
  5611.     ja    swapvga_2        ;  nope
  5612. swapvga_1:
  5613.     mov    si,2            ; plane 2
  5614.     sub    cx,ax            ; subtract 1/2 total from offset
  5615.     sbb    bx,dx            ;  ...
  5616. swapvga_2:
  5617.     cmp    colors,2        ; 2 color mode?
  5618.     jle    swapvga_4        ;  yup, just plane 0
  5619.     shr    dx,1            ; 1/4 of total (or 1/2 if 4 colors)
  5620.     rcr    ax,1            ;  ...
  5621.     cmp    dx,bx            ; 1/4 total <= remaining offset?
  5622.     jb    swapvga_3        ;  yup
  5623.     ja    swapvga_4        ;  nope
  5624.     cmp    ax,cx            ; ...
  5625.     ja    swapvga_4        ;  nope
  5626. swapvga_3:
  5627.     inc    si            ; plane 1 or 3
  5628.     sub    cx,ax            ; subtract 1/4 total from offset
  5629.     sbb    bx,dx            ;  ...
  5630. swapvga_4:
  5631.     mov    di,0            ; bank size (65536 actually)
  5632.     cmp    bx,dx            ; in last bank?
  5633.     jne    swapvga_5        ;  nope
  5634.     mov    di,ax            ; yup, note its size
  5635. swapvga_5:
  5636.     mov    ax,0a000h        ; high word of vid addr
  5637.     mov    word ptr swapvidbuf+2,ax; store it
  5638.     mov    word ptr swapvidbuf,cx    ; low word of vid addr (offset in bank)
  5639.     sub    di,cx            ; bank size - offset
  5640.     je    swapvga_6        ; 0 implies bank = 65536
  5641.     cmp    di,swaplength        ; rest of bank smaller than req length?
  5642.     jae    swapvga_6        ;  nope
  5643.     mov    swaplength,di        ; yup, reduce length to what's available
  5644. swapvga_6:
  5645.     push    si            ; remember plane
  5646.     mov    ax,bx            ; top word of offset is bank
  5647.     call    far ptr newbank     ; map in the bank
  5648.     mov    dx,03ceh        ; graphics controller address
  5649.     pop    cx            ; plane
  5650.     mov    ah,cl            ;  ...
  5651.     mov    al,04h            ; set up controller address register
  5652.     out    dx,ax            ; map the plane into memory for reads
  5653.     mov    ax,0001h        ; set/reset enable - all bits processor
  5654.     out    dx,ax            ;  ...
  5655.     mov    ax,0ff08h        ; bit mask - all bits processor
  5656.     out    dx,ax            ;  ...
  5657.     mov    dx,03c4h        ; sequencer address
  5658.     mov    ah,1            ; 1 << plane number
  5659.     shl    ah,cl            ;  ...
  5660.     mov    al,02h            ; sequencer plane write enable register
  5661.     out    dx,ax            ; enable just this plane for writing
  5662.     ret
  5663. swapvga     endp
  5664.  
  5665. swapvga_reset    proc near
  5666.     cmp    word ptr swapsetup,offset swapvga; swapvga being used?
  5667.     jne    swapvga_reset_ret
  5668.     mov    ax,0f02h        ; write enable register, all planes
  5669.     mov    dx,03c4h        ; sequencer address
  5670.     out    dx,ax
  5671. swapvga_reset_ret:
  5672.     ret
  5673. swapvga_reset    endp
  5674.  
  5675. swapnormread    proc uses es si di    ; the SLOW version
  5676.     local    xdot:word,ydot:word,bytesleft:word,bits:word,bitctr:word
  5677.     local    savebyte:byte
  5678.     mov    ax,swaplength        ; bytes to save
  5679.     mov    bytesleft,ax        ;  ...
  5680.     mov    bits,8            ; bits/pixel
  5681.     mov    bx,word ptr swapoffset    ; pixel offset to save
  5682.     mov    cx,word ptr swapoffset+2
  5683.     mov    ax,colors        ; colors
  5684. swapnorm_bits:
  5685.     cmp    ax,256            ; accounted for 8 bits yet?
  5686.     jae    swapnorm_gotbits    ;  yup
  5687.     shr    bits,1            ; nope, halve the bits/pixel
  5688.     shl    bx,1            ; double the pixel offset
  5689.     rcl    cx,1            ;  ...
  5690.     mul    ax            ; square colors accounted for
  5691.     jmp    short swapnorm_bits    ; check if enough yet
  5692. swapnorm_gotbits:
  5693.     mov    ax,bx            ; pixel offset now in dx:ax
  5694.     mov    dx,cx            ;  ...
  5695.     div    sxdots            ; translate pixel offset to row/col
  5696.     mov    ydot,ax         ;  ...
  5697.     mov    xdot,dx         ;  ...
  5698.     mov    ax,extraseg        ; Extra Segment
  5699.     add    ax,1000h        ;  plus 64K
  5700.     mov    word ptr swapvidbuf+2,ax; temp buffer to return to caller
  5701.     mov    word ptr swapvidbuf,0    ;  ...
  5702.     mov    word ptr tmpbufptr+2,ax ; running ptr for building buffer
  5703.     mov    word ptr tmpbufptr,0    ;  ...
  5704.     mov    bitctr,0
  5705. swapnorm_loop:
  5706.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  5707.     mov    es,ax            ;  for dotread
  5708.     mov    cx,xdot         ; load up the registers
  5709.     mov    dx,ydot         ;  for the video routine
  5710.     call    dotread         ; read the dot via the approved method
  5711.     mov    cx,bits         ; bits per pixel
  5712.     cmp    cx,8            ; 1 byte per pixel?
  5713.     je    swapnorm_store        ;  yup, go store a byte
  5714.     add    bitctr,cx        ; nope, add how many we're storing
  5715.     mov    bl,savebyte        ; load the byte being built
  5716. swapnorm_shift:
  5717.     shr    al,1            ; shift pixel into byte
  5718.     rcr    bl,1            ;  ...
  5719.     loop    swapnorm_shift        ; for number of bits/pixel
  5720.     mov    savebyte,bl        ; save byte we're building
  5721.     cmp    bitctr,8        ; filled a byte yet?
  5722.     jb    swapnorm_nxt        ;  nope
  5723.     mov    al,bl            ; yup, set up to store
  5724.     mov    bitctr,0        ; clear counter for next time
  5725. swapnorm_store:
  5726.     les    di,tmpbufptr        ; buffer pointer
  5727.     stosb                ; store byte
  5728.     dec    bytesleft        ; finished?
  5729.     jz    swapnorm_ret        ;  yup
  5730.     mov    word ptr tmpbufptr,di    ; store incremented buffer pointer
  5731. swapnorm_nxt:
  5732.     inc    xdot            ; for next dotread call
  5733.     mov    ax,xdot         ; past row length?
  5734.     cmp    ax,sxdots        ;  ...
  5735.     jb    swapnorm_loop        ;  nope, go for next pixel
  5736.     inc    ydot            ; yup, increment row
  5737.     mov    xdot,0            ; and reset column
  5738.     jmp    short swapnorm_loop    ; go for next pixel
  5739. swapnorm_ret:
  5740.     ret
  5741. swapnormread    endp
  5742.  
  5743. swapnormwrite    proc uses es si di    ; the SLOW way
  5744.     local    xdot:word,ydot:word,bytesleft:word,bits:word,bitctr:word
  5745.     local    savebyte:byte
  5746.     mov    ax,swaplength        ; bytes to restore
  5747.     inc    ax            ; +1
  5748.     mov    bytesleft,ax        ; save it
  5749.     mov    bits,8            ; bits/pixel
  5750.     mov    bx,word ptr swapoffset    ; pixel offset to restore
  5751.     mov    cx,word ptr swapoffset+2;  ...
  5752.     mov    ax,colors        ; colors
  5753. swapnormw_bits:
  5754.     cmp    ax,256            ; accounted for 8 bits yet?
  5755.     jae    swapnormw_gotbits    ;  yup
  5756.     shr    bits,1            ; nope, halve the bits/pixel
  5757.     shl    bx,1            ; double the pixel offset
  5758.     rcl    cx,1            ;  ...
  5759.     mul    ax            ; square colors accounted for
  5760.     jmp    short swapnormw_bits    ; check if enough yet
  5761. swapnormw_gotbits:
  5762.     mov    ax,bx            ; pixel offset now in dx:ax
  5763.     mov    dx,cx            ;  ...
  5764.     div    sxdots            ; translate pixel offset to row/col
  5765.     mov    ydot,ax         ;  ...
  5766.     mov    xdot,dx         ;  ...
  5767.     mov    dx,word ptr swapvidbuf+2; temp buffer from caller
  5768.     mov    ax,word ptr swapvidbuf    ;  ...
  5769.     mov    word ptr tmpbufptr+2,dx ; running ptr in buffer
  5770.     mov    word ptr tmpbufptr,ax    ;  ...
  5771.     mov    bitctr,0
  5772. swapnormw_loop:
  5773.     mov    cx,bits         ; bits per pixel
  5774.     sub    bitctr,cx        ; subtract a pixel from counter
  5775.     jg    swapnormw_extract    ;  got some left in savebyte
  5776.     dec    bytesleft        ; all done?
  5777.     jz    swapnormw_ret        ;  yup
  5778.     les    si,tmpbufptr        ; buffer pointer
  5779.     mov    dl,es:[si]        ; next byte
  5780.     inc    word ptr tmpbufptr    ; incr buffer pointer for next time
  5781.     mov    bitctr,8        ; reset unused bit count
  5782.     cmp    cx,8            ; 1 byte/pixel?
  5783.     je    swapnormw_store     ;  yup, go the fast way
  5784.     mov    bl,dl            ; byte to extract from
  5785.     jmp    short swapnormw_extract2
  5786. swapnormw_extract:
  5787.     mov    bl,savebyte        ; byte with bits left to use
  5788.     mov    dl,bl            ; current pixel in bottom n bits
  5789. swapnormw_extract2:
  5790.     shr    bl,1            ; for next time
  5791.     loop    swapnormw_extract2    ; for bits per pixel
  5792.     mov    savebyte,bl        ; save remaining bits
  5793. swapnormw_store:
  5794.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  5795.     mov    es,ax            ;  for dotread
  5796.     mov    al,dl            ; color to write
  5797.     and    ax,andcolor        ;  ...
  5798.     mov    cx,xdot         ; load up the registers
  5799.     mov    dx,ydot         ;  for the video routine
  5800.     call    dotwrite        ; write the dot via the approved method
  5801.     inc    xdot            ; for next dotread call
  5802.     mov    ax,xdot         ; past row length?
  5803.     cmp    ax,sxdots        ;  ...
  5804.     jb    swapnormw_loop        ;  nope, go for next pixel
  5805.     inc    ydot            ; yup, increment row
  5806.     mov    xdot,0            ; and reset column
  5807.     jmp    short swapnormw_loop    ; go for next pixel
  5808. swapnormw_ret:
  5809.     ret
  5810. swapnormwrite    endp
  5811.  
  5812. ; far move routine for savegraphics/restoregraphics
  5813.  
  5814. movewords proc    uses es di si, len:word, fromptr:dword, toptr:dword
  5815.     push    ds            ; save DS
  5816.     mov    cx,len            ; words to move
  5817.     les    di,toptr        ; destination buffer
  5818.     lds    si,fromptr        ; source buffer
  5819.     cld                ; direction=forward
  5820.     rep    movsw            ; do it.
  5821.     pop    ds            ; restore DS
  5822.     ret                ; we done.
  5823. movewords endp
  5824.  
  5825. ; clear text screen
  5826.  
  5827. setclear    proc    uses es si di    ; clear the screen after setfortext
  5828.     call    far ptr home        ; home the cursor
  5829.     mov    ax,textaddr
  5830.     mov    es,ax
  5831.     xor    di,di
  5832.     cmp    text_type,0        ; real text mode?
  5833.     jne    setcbw            ;  nope
  5834.     mov    ax,0720h        ; blank with white attribute
  5835.     mov    cx,2000         ; 80x25
  5836.     rep    stosw            ; clear it
  5837.     jmp    short setcdone
  5838. setcbw: xor    ax,ax            ; graphics text
  5839.     mov    cx,4000         ; 640x200x2 / 8
  5840.     rep    stosw            ; clear it
  5841.     mov    di,2000h        ; second part
  5842.     mov    cx,4000
  5843.     rep    stosw            ; clear it
  5844. setcdone:
  5845.     xor    ax,ax            ; zero
  5846.     mov    textrbase,ax        ; clear this
  5847.     mov    textcbase,ax        ;  and this
  5848.     ret                ; we done.
  5849. setclear    endp
  5850.  
  5851.  
  5852. disablevideo    proc    near        ; wierd video trick to disable/enable
  5853.     push    dx            ; save some registers
  5854.     push    ax            ;  ...
  5855.     mov    dx,03bah        ; set attribute comtroller flip-flop
  5856.     in    al,dx            ;  regardless of video mode
  5857.     mov    dx,03dah        ;  ...
  5858.     in    al,dx            ;  ...
  5859.     mov    dx,03c0h        ; attribute controller address
  5860.     pop    ax            ; 00h = disable, 20h = enable
  5861.     out    dx,al            ;  trust me.
  5862.     pop    dx            ; restore DX and we done.
  5863.     ret
  5864. disablevideo    endp
  5865.  
  5866.  
  5867. ;***************** Shadow Video Routines, MCP 6-7-91 ***********
  5868.  
  5869. .DATA
  5870.  
  5871. extrn    AntiAliasing:WORD
  5872.  
  5873. extrn Shadowing:WORD
  5874. public ShadowColors
  5875.  
  5876. ShadowRead    dw    ?
  5877. ShadowWrite    dw    ?
  5878. ShadowLineWrite dw    ?
  5879. ShadowLineRead    dw    ?
  5880. ShadowSwap    dd    ?
  5881. ShadowColors    dw    ?
  5882.  
  5883. .CODE
  5884.  
  5885. ; Passing this routine 0 turns off shadow, nonzero turns it on.
  5886. ShadowVideo    proc    uses di si, state:WORD
  5887.     mov    ax, state
  5888.     cmp    ax, Shadowing
  5889.     jne    SetShadowing
  5890.     jmp    ExitShadowVideo
  5891.  
  5892. SetShadowing:
  5893.     mov    Shadowing, ax
  5894.     or    ax, ax
  5895.     jz    ShadowVideoOff
  5896.  
  5897.     mov    cx, AntiAliasing
  5898.     shl    xdots, cl
  5899.     shl    ydots, cl
  5900.     shl    sxdots, cl
  5901.     shl    sydots, cl
  5902.  
  5903.     cmp    ShadowColors, 0
  5904.     jne    NoTColors
  5905.  
  5906.     mov    colors, 256
  5907.  
  5908. NoTColors:
  5909.     mov    ax,offset diskwrite    ; set up disk-vid write-a-dot routine
  5910.     mov    bx,offset diskread    ; set up disk-vid read-a-dot routine
  5911.     mov    cx,offset normaline    ; set up the normal linewrite routine
  5912.     mov    dx,offset normalineread ; set up the normal lineread  routine
  5913.     mov    si, offset ShadowSwapFnct
  5914.     mov    di, cs
  5915.     jmp    SetShadowVideo
  5916.  
  5917. ShadowVideoOff:
  5918.     mov    cx, AntiAliasing
  5919.     shr    xdots, cl
  5920.     shr    ydots, cl
  5921.     shr    sxdots, cl
  5922.     shr    sydots, cl
  5923.  
  5924.     mov    ax, ShadowColors
  5925.     mov    colors, ax
  5926.  
  5927.     mov    ax, ShadowWrite
  5928.     mov    bx, ShadowRead
  5929.     mov    cx, ShadowLineWrite
  5930.     mov    dx, ShadowLineRead
  5931.     mov    si, WORD PTR ShadowSwap
  5932.     mov    di, WORD PTR ShadowSwap+2
  5933.  
  5934. SetShadowVideo:
  5935.     mov    dotwrite,ax        ; save the results
  5936.     mov    dotread,bx        ;  ...
  5937.     mov    linewrite,cx        ;  ...
  5938.     mov    lineread,dx        ;  ...
  5939.     mov    WORD PTR swapsetup, si
  5940.     mov    WORD PTR swapsetup+2, di
  5941.  
  5942. ExitShadowVideo:
  5943.     ret
  5944. ShadowVideo    ENDP
  5945.  
  5946.  
  5947. SetupShadowVideo    PROC
  5948.     mov    ax, dotwrite        ; save the results
  5949.     mov    ShadowWrite, ax
  5950.     mov    ax, dotread        ;  ...
  5951.     mov    ShadowRead, ax
  5952.     mov    ax, linewrite
  5953.     mov    ShadowLineWrite, ax
  5954.     mov    ax, lineread
  5955.     mov    ShadowLineRead, ax
  5956.     mov    ax, WORD PTR swapsetup
  5957.     mov    WORD PTR ShadowSwap, ax
  5958.     mov    ax, WORD PTR swapsetup+2
  5959.     mov    WORD PTR ShadowSwap+2, ax
  5960.     mov    ax, colors
  5961.     mov    ShadowColors, ax
  5962.  
  5963.     mov    Shadowing, 0
  5964.     mov    ax, 1
  5965.     push    ax
  5966.     call    ShadowVideo
  5967.     add    sp, 2
  5968.  
  5969.     call    far ptr startdisk
  5970.  
  5971.     ret
  5972. SetupShadowVideo    ENDP
  5973.  
  5974.  
  5975. ; This routine makes sure the right routines are set for swapping what's
  5976. ;   really on the screen.
  5977. ShadowSwapFnct        PROC
  5978.     xor   ax, ax
  5979.     push  ax
  5980.     call  ShadowVideo
  5981.     add   sp, 2
  5982.     call  [ShadowSwap]
  5983.     mov   ax, 1
  5984.     push  ax
  5985.     call  ShadowVideo
  5986.     add   sp, 2
  5987.     ret
  5988. ShadowSwapFnct        ENDP
  5989.  
  5990.  
  5991. ; ************** Function findfont(n) ******************************
  5992.  
  5993. ;    findfont(0) returns far pointer to 8x8 font table if it can
  5994. ;            find it, NULL otherwise;
  5995. ;            nonzero parameter reserved for future use
  5996.  
  5997. findfont    proc    uses es si di, fontparm:word
  5998.     mov    ax,01130h        ; func 11, subfunc 30
  5999.     mov    bh,03h            ; 8x8 font, bottom 128 chars
  6000.     sub    cx,cx            ; so we can tell if anything happens
  6001.     int    10h            ; ask bios
  6002.     sub    ax,ax            ; default return, NULL
  6003.     sub    dx,dx            ;  ...
  6004.     or    cx,cx            ; did he set cx?
  6005.     jz    findfontret        ; nope, return with NULL
  6006.     mov    dx,es            ; yup, return far pointer
  6007.     mov    ax,bp            ;  ...
  6008. findfontret:
  6009.     ret                ; note that "uses" gets bp reset here
  6010. findfont    endp
  6011.  
  6012. ; **************** Function home()  ********************************
  6013.  
  6014. ;    Home the cursor (called before printfs)
  6015.  
  6016. home    proc
  6017.     mov    ax,0200h        ; force the cursor
  6018.     mov    bx,0            ; in page 0
  6019.     mov    dx,0            ; to the home position
  6020.     mov    textrow,dx        ; update our local values
  6021.     mov    textcol,dx        ;  ...
  6022.     push    bp            ; some BIOS's don't save this
  6023.     int    10h            ; do it.
  6024.     pop    bp            ; restore the saved register
  6025.     ret
  6026. home    endp
  6027.  
  6028. ; **************** Function movecursor(row, col)  **********************
  6029.  
  6030. ;    Move the cursor (called before printfs)
  6031.  
  6032. movecursor    proc    row:word, col:word
  6033.     mov    ax,row            ; row specified?
  6034.     cmp    ax,-1            ;  ...
  6035.     je    mccol            ;  nope, inherit it
  6036.     mov    textrow,ax        ; yup, store it
  6037. mccol:    mov    ax,col            ; col specified?
  6038.     cmp    ax,-1            ;  ...
  6039.     je    mcdoit            ;  nope, inherit it
  6040.     mov    textcol,ax        ; yup, store it
  6041. mcdoit: mov    ax,0200h        ; force the cursor
  6042.     mov    bx,0            ; in page 0
  6043.     mov    dh,byte ptr textrow    ; move to this row
  6044.     add    dh,byte ptr textrbase    ;  ...
  6045.     mov    dl,byte ptr textcol    ; move to this column
  6046.     add    dl,byte ptr textcbase    ;  ...
  6047.     push    bp            ; some BIOS's don't save this
  6048.     int    10h            ; do it.
  6049.     pop    bp            ; restore the saved register
  6050.     ret
  6051. movecursor    endp
  6052.  
  6053. ; **************** Function keycursor(row, col)  **********************
  6054.  
  6055. ;    Subroutine to wait cx ticks, or till keystroke pending
  6056.  
  6057. tickwait  proc
  6058.     FRAME    <es>            ; std stack frame for TC++ overlays
  6059. tickloop1:
  6060.     push    cx            ; save loop ctr
  6061.     sub    ax,ax            ; set ES to BIOS data area
  6062.     mov    es,ax            ;  ...
  6063.     mov    bx,es:046ch        ; obtain the current timer value
  6064.     push    bx
  6065.     call    far ptr keypressed    ; check if keystroke pending
  6066.     pop    bx
  6067.     pop    cx            ; restore loop ctr
  6068.     cmp    ax,0            ; keystroke?
  6069.     jne    tickret         ;  yup, return
  6070. tickloop2:
  6071.     cmp    bx,es:046ch        ; a new clock tick started yet?
  6072.     je    tickloop2        ;  nope
  6073.     loop    tickloop1        ; wait another tick?
  6074.     xor    ax,ax            ; nope, exit no key, ticks done
  6075. tickret:
  6076.     UNFRAME <es>            ; pop stack frame
  6077.     ret
  6078. tickwait    endp
  6079.  
  6080. ;    Show cursor, wait for a key, disable cursor, return key
  6081.  
  6082. keycursor    proc   uses es si di, row:word, col:word
  6083.     mov    cursortyp,0607h     ; default cursor
  6084.     mov    ax,row            ; row specified?
  6085.     cmp    ax,-1            ;  ...
  6086.     je    ckcol            ;  nope, inherit it
  6087.     test    ax,08000h        ; top bit on?
  6088.     je    ckrow            ;  nope
  6089.     and    ax,07fffh        ; yup, clear it
  6090.     mov    cursortyp,0507h     ; and use a bigger cursor
  6091. ckrow:    mov    textrow,ax        ; store row
  6092. ckcol:    mov    ax,col            ; col specified?
  6093.     cmp    ax,-1            ;  ...
  6094.     je    ckmode            ;  nope, inherit it
  6095.     mov    textcol,ax        ; yup, store it
  6096. ckmode: cmp    text_type,1        ; are we in 640x200x2 mode?
  6097.     jne    ck_text         ;  nope.  do it the easy way
  6098. ck_bwloop:                ; 640x200x2 cursor loop
  6099.     mov    cx,3            ; wait 3 ticks for keystroke
  6100.     call    far ptr tickwait    ;  ...
  6101.     cmp    ax,0            ; got a keystroke?
  6102.     je    ckwait            ;  nope
  6103.     jmp    ck_get            ; yup, fetch it and return
  6104. ckwait: mov    ax,320            ; offset in vid mem of top row 1st byte:
  6105.     mov    bx,textrow        ;  row
  6106.     add    bx,textrbase        ;  ...
  6107.     mul    bx            ;  row*320 + col
  6108.     add    ax,textcol        ;  ...
  6109.     add    ax,textcbase        ;  ...
  6110.     mov    di,ax            ;  ...
  6111.     mov    ax,0b800h        ; set es to vid memory
  6112.     mov    es,ax            ;  ...
  6113.     mov    ah,byte ptr es:00f0h[di]; row 6 of character
  6114.     mov    al,byte ptr es:20f0h[di]; row 7 of character
  6115.     push    ax            ; save them
  6116.     mov    cx,8            ; count on bits in orig value
  6117.     xor    bx,bx            ;  ...
  6118. ckbits: shl    al,1            ;  ...
  6119.     adc    bx,0            ;  ...
  6120.     loop    ckbits            ;  ...
  6121.     mov    al,0            ; black cursor
  6122.     cmp    bx,4            ; >= 4 on bits in orig value?
  6123.     jge    ckbwgo            ;  yup, use black cursor
  6124.     not    al            ; nope, use white cursor
  6125. ckbwgo: mov    byte ptr es:20f0h[di],al; turn on cursor, row 7
  6126.     cmp    cursortyp,0607h     ; small cursor?
  6127.     je    ckbwwt            ;  yup
  6128.     mov    byte ptr es:00f0h[di],al; nope, turn on cursor row 6
  6129. ckbwwt: mov    cx,3            ; wait 3 ticks for keystroke
  6130.     call    far ptr tickwait    ;  ...
  6131.     pop    bx            ; saved orig value
  6132.     mov    byte ptr es:00f0h[di],bh; turn off cursor, row 6
  6133.     mov    byte ptr es:20f0h[di],bl; turn off cursor, row 7
  6134.     cmp    ax,0            ; got a keystroke?
  6135.     jne    ck_get            ;  yup, fetch it and return
  6136.     jmp    short ck_bwloop     ; and keep waiting
  6137. ck_text:
  6138.     cmp    text_type,0        ; real text mode?
  6139.     jne    ckgetw            ;  nope, no cursor at all
  6140.     push    bp            ; some bios's don't save this
  6141.     mov    ah,1            ; set cursor type
  6142.     mov    cx,cursortyp        ;  ...
  6143.     int    10h            ;  ...
  6144.     mov    ah,02            ; move cursor
  6145.     xor    bx,bx            ;  page
  6146.     mov    dh,byte ptr textrow    ;  row
  6147.     add    dh,byte ptr textrbase    ;  ...
  6148.     mov    dl,byte ptr textcol    ;  col
  6149.     add    dh,byte ptr textcbase    ;  ...
  6150.     int    10h            ;  ...
  6151.     pop    bp
  6152. ckgetw: call    far ptr keypressed    ; not getakey, help/tab mey be enabled
  6153.     cmp    ax,0            ; key available?
  6154.     je    ckgetw            ;  nope, keep waiting
  6155. ck_get: call    far ptr getakey     ; get the keystroke
  6156.     cmp    text_type,0        ; real text mode?
  6157.     jne    ck_ret            ;  nope, done
  6158.     push    bp            ; some bios's don't save this
  6159.     push    ax            ; save it
  6160.     mov    ah,1            ; make cursor normal size
  6161.     mov    cx,0607h        ;  ...
  6162.     int    10h            ;  ...
  6163.     mov    ah,02            ; move cursor
  6164.     xor    bx,bx            ;  page
  6165.     mov    dx,1950h        ;  off the display
  6166.     int    10h            ;  ...
  6167.     pop    ax            ; keystroke value
  6168.     pop    bp
  6169. ck_ret:
  6170.     ret
  6171. keycursor    endp
  6172.  
  6173. ; ************* Function scrollup(toprow, botrow) ******************
  6174.  
  6175. ;    Scroll the screen up (from toprow to botrow)
  6176.  
  6177. scrollup    proc    uses    es, toprow:word, botrow:word
  6178.  
  6179.     mov    ax,0601h        ; scropp up one line
  6180.     mov    bx,0700h        ; new line is black
  6181.     mov    cx,toprow        ; this row,
  6182.     mov    ch,cl            ;  ...
  6183.     mov    cl,0            ;  first column
  6184.     mov    dx,botrow        ; to this row,
  6185.     mov    dh,dl            ;  ...
  6186.     mov    dl,79            ;  last column
  6187.     push    bp            ; some BIOS's don't save this
  6188.     int    10h            ; do it.
  6189.     pop    bp            ; restore the saved register
  6190.     ret                ; we done.
  6191. scrollup    endp
  6192.  
  6193. ; ************* Function scrolldown(toprow, botrow) ******************
  6194.  
  6195. ;    Scroll the screen down (from toprow to botrow)
  6196.  
  6197. scrolldown    proc    uses    es, toprow:word, botrow:word
  6198.  
  6199.     mov    ax,0701h        ; scropp down one line
  6200.     mov    bx,0700h        ; new line is black
  6201.     mov    cx,toprow        ; this row,
  6202.     mov    ch,cl            ;  ...
  6203.     mov    cl,0            ;  first column
  6204.     mov    dx,botrow        ; to this row,
  6205.     mov    dh,dl            ;  ...
  6206.     mov    dl,79            ;  last column
  6207.     push    bp            ; some BIOS's don't save this
  6208.     int    10h            ; do it.
  6209.     pop    bp            ; restore the saved register
  6210.     ret                ; we done.
  6211. scrolldown    endp
  6212.  
  6213.  
  6214. ; **************** Function getcolor(xdot, ydot) *******************
  6215.  
  6216. ;    Return the color on the screen at the (xdot,ydot) point
  6217.  
  6218. getcolor    proc    uses di si es, xdot:word, ydot:word
  6219.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  6220.     mov    es,ax            ; save it here during this routine
  6221.     mov    cx,xdot         ; load up the registers
  6222.     mov    dx,ydot         ;  for the video routine
  6223.     add    cx,sxoffs        ;  ...
  6224.     add    dx,syoffs        ;  ...
  6225.     call    dotread         ; read the dot via the approved method
  6226.     mov    ah,0            ; clear the high-order bits
  6227.     ret                ; we done.
  6228. getcolor    endp
  6229.  
  6230. ; Fastcall version, called when C programs are compiled by MSC 6.00A:
  6231.  
  6232. @getcolor    proc    FORTRAN ; ax=xdot, dx=ydot
  6233.     push    si            ; preserve these
  6234.     push    di            ;  ...
  6235.     mov    cx,ax            ; load up the registers
  6236.     add    cx,sxoffs        ;  ...
  6237.     add    dx,syoffs        ;  ...
  6238.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  6239.     mov    es,ax            ;  ...
  6240.     call    dotread         ; read the dot via the approved method
  6241.     xor    ah,ah            ; clear the high-order bits
  6242.     pop    di            ; restore
  6243.     pop    si            ;  ...
  6244.     ret                ; we done.
  6245. @getcolor    endp
  6246.  
  6247. ; ************** Function putcolor(xdot, ydot, color) *******************
  6248.  
  6249. ;    write the color on the screen at the (xdot,ydot) point
  6250.  
  6251. putcolor    proc    uses di si es, xdot:word, ydot:word, xcolor:word
  6252.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  6253.     mov    es,ax            ; save it here during this routine
  6254.     mov    cx,xdot         ; load up the registers
  6255.     mov    dx,ydot         ;  for the video routine
  6256.     add    cx,sxoffs        ;  ...
  6257.     add    dx,syoffs        ;  ...
  6258.     mov    ax,xcolor        ;  ...
  6259.     and    ax,andcolor        ; (ensure that 'color' is in the range)
  6260.     call    dotwrite        ; write the dot via the approved method
  6261. ;;;    call    videocleanup        ; perform any video cleanup required
  6262.     ret                ; we done.
  6263. putcolor    endp
  6264.  
  6265. ; Fastcall version, called when C programs are compiled by MSC 6.00A:
  6266.  
  6267. @putcolor    proc    FORTRAN ; ax=xdot, dx=ydot, bx=color
  6268.     push    si            ; preserve these
  6269.     push    di            ;  ...
  6270.     mov    cx,ax            ; load up the registers
  6271.     add    cx,sxoffs        ;  ...
  6272.     add    dx,syoffs        ;  ...
  6273.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  6274.     mov    es,ax            ;  ...
  6275.     mov    ax,bx            ; color
  6276.     and    ax,andcolor        ; ensure that 'color' is in range
  6277.     call    dotwrite        ; write the dot via the approved method
  6278. ;;;    call    videocleanup        ; perform any video cleanup required
  6279.     pop    di            ; restore
  6280.     pop    si            ;  ...
  6281.     ret                ; we done.
  6282. @putcolor    endp
  6283.  
  6284.  
  6285. ; ***************Function out_line(pixels,linelen) *********************
  6286.  
  6287. ;    This routine is a 'line' analog of 'putcolor()', and sends an
  6288. ;    entire line of pixels to the screen (0 <= xdot < xdots) at a clip
  6289. ;    Called by the GIF decoder
  6290.  
  6291. out_line    proc    uses di si es, pixels:ptr byte, linelen:word
  6292.     mov    cx,sxoffs        ; start at left side of logical screen
  6293.     mov    dx,rowcount        ; sanity check: don't proceed
  6294.     add    dx,syoffs        ;  ...
  6295.     cmp    dx,sydots        ; beyond the end of the screen
  6296.     ja    out_lineret        ;  ...
  6297.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  6298.     mov    es,ax            ; save it here during this routine
  6299.     mov    ax, linelen        ; last pixel column
  6300.     add    ax, sxoffs        ;  ...
  6301.     dec    ax            ;  ...
  6302.     mov    si,pixels        ; get the color for dot 'x'
  6303.     call    linewrite        ; mode-specific linewrite routine
  6304.     inc    rowcount        ; next row
  6305. out_lineret:
  6306.     xor    ax,ax            ; return 0
  6307.     ret
  6308.  
  6309. out_line    endp
  6310.  
  6311. ; ***Function get_line(int row,int startcol,int stopcol, unsigned char *pixels) ***
  6312.  
  6313. ;    This routine is a 'line' analog of 'getcolor()', and gets a segment
  6314. ;    of a line from the screen and stores it in pixels[] at one byte per
  6315. ;    pixel
  6316. ;    Called by the GIF decoder
  6317.  
  6318. get_line    proc uses di si es, row:word, startcol:word, stopcol:word, pixels:ptr byte
  6319.     mov    cx,startcol        ; sanity check: don't proceed
  6320.     add    cx,sxoffs        ;  ...
  6321.     cmp    cx,sxdots        ; beyond the right end of the screen
  6322.     ja    get_lineret        ;  ...
  6323.     mov    dx,row            ; sanity check: don't proceed
  6324.     add    dx,syoffs        ;  ...
  6325.     cmp    dx,sydots        ; beyond the bottom of the screen
  6326.     ja    get_lineret        ;  ...
  6327.     mov    ax, stopcol        ; last pixel to read
  6328.     add    ax, sxoffs        ;  ...
  6329.     mov    di, pixels        ; get the color for dot 'x'
  6330.     call    lineread        ; mode-specific lineread routine
  6331. get_lineret:
  6332.     xor    ax,ax            ; return 0
  6333.     ret
  6334. get_line    endp
  6335.  
  6336. ; ***Function put_line(int row,int startcol,int stopcol, unsigned char *pixels) ***
  6337.  
  6338. ;    This routine is a 'line' analog of 'putcolor()', and puts a segment
  6339. ;    of a line from the screen and stores it in pixels[] at one byte per
  6340. ;    pixel
  6341. ;    Called by the GIF decoder
  6342.  
  6343. put_line    proc uses di si es, row:word, startcol:word, stopcol:word, pixels:ptr byte
  6344.     mov    cx,startcol        ; sanity check: don't proceed
  6345.     add    cx,sxoffs        ;  ...
  6346.     cmp    cx,sxdots        ; beyond the right end of the screen
  6347.     ja    put_lineret        ;  ...
  6348.     mov    dx,row            ; sanity check: don't proceed
  6349.     add    dx,syoffs        ;  ...
  6350.     cmp    dx,sydots        ; beyond the bottom of the screen
  6351.     ja    put_lineret        ;  ...
  6352.     mov    ax,0a000h        ; EGA, VGA, MCGA starts here
  6353.     mov    es,ax            ; save it here during this routine
  6354.     mov    ax, stopcol        ; last column
  6355.     add    ax, sxoffs;        ;  ...
  6356.     cmp    ax,sxdots        ; beyond the right end of the screen?
  6357.     ja    put_lineret        ;  ...
  6358.     mov    si,pixels        ; put the color for dot 'x'
  6359.     call    linewrite        ; mode-specific linewrite routine
  6360. put_lineret:
  6361.     xor    ax,ax            ; return 0
  6362.     ret
  6363. put_line    endp
  6364.  
  6365.  
  6366. ;-----------------------------------------------------------------
  6367.  
  6368. ; setattr(row, col, attr, count) where
  6369. ;      row, col = row and column to start printing.
  6370. ;      attr = color attribute.
  6371. ;      count = number of characters to set
  6372. ;      This routine works only in real color text mode.
  6373.  
  6374. setattr     proc uses es di, row:word, col:word, attr:word, count:word
  6375.     mov    ax,row            ; row specified?
  6376.     cmp    ax,-1            ;  ...
  6377.     je    setac            ;  nope, inherit it
  6378.     mov    textrow,ax        ; yup, store it
  6379. setac:    mov    ax,col            ; col specified?
  6380.     cmp    ax,-1            ;  ...
  6381.     je    setago            ;  nope, inherit it
  6382.     mov    textcol,ax        ; yup, store it
  6383. setago: cmp    text_type,0        ; real color text mode?
  6384.     jne    setax            ;  nope, do nothing
  6385.     mov    ax,textrow        ; starting row
  6386.     add    ax,textrbase        ;  ...
  6387.     mov    cx,160            ; x 2 bytes/row (char & attr bytes)
  6388.     imul    cx
  6389.     mov    bx,textcol        ; add starting column
  6390.     add    bx,textcbase        ;  ...
  6391.     add    ax,bx            ; twice since 2 bytes/char
  6392.     add    ax,bx            ;  ...
  6393.     mov    di,ax            ; di -> start location in Video segment
  6394.     mov    cx,count        ; number of bytes to set
  6395.     jcxz    setax            ; none?
  6396.     mov    ax,attr         ; get color attributes in al
  6397.     mov    dx,0b800h        ; set video pointer
  6398.     cmp    mode7text,0        ; egamono/hgc?
  6399.     je    setalstore        ;  nope
  6400.     mov    dx,0b000h        ; mode 7 address
  6401.     mov    al,07h            ; normal mda ttribute
  6402.     cmp    ah,0            ; inverse?
  6403.     jge    setalchkbright        ;  nope
  6404.     mov    al,70h            ; yup
  6405.     jmp    short setalstore
  6406. setalchkbright:
  6407.     test    ah,40h            ; bright?
  6408.     jz    setalstore        ;  nope
  6409.     mov    al,0Fh            ; yup
  6410. setalstore:
  6411.     mov    es,dx            ;  ...
  6412. setalp: mov    byte ptr es:1[di],al    ; set attribute
  6413.     add    di,2            ; for next one
  6414.     loop    setalp            ; do next char
  6415. setax:    ret
  6416. setattr     endp
  6417.  
  6418.  
  6419. ;-----------------------------------------------------------------
  6420.  
  6421. ; PUTSTR.asm puts a string directly to video display memory. Called from C by:
  6422. ;    putstring(row, col, attr, string) where
  6423. ;      row, col = row and column to start printing.
  6424. ;      attr = color attribute.
  6425. ;      string = far pointer to the null terminated string to print.
  6426. ;    Written for the A86 assembler (which has much less 'red tape' than MASM)
  6427. ;    by Bob Montgomery, Orlando, Fla.          7-11-88
  6428. ;    Adapted for MASM 5.1 by Tim Wegner      12-11-89
  6429. ;    Furthur mucked up to handle graphics
  6430. ;    video modes by Bert Tyler          1-07-90
  6431. ;    Reworked for:  row,col update/inherit;
  6432. ;    620x200x2 inverse video;  far ptr to string;
  6433. ;    fix to avoid scrolling when last posn chgd;
  6434. ;    divider removed;  newline ctl chars;  PB  9-25-90
  6435.  
  6436. putstring    proc uses es di si, row:word, col:word, attr:word, string:far ptr byte
  6437.     mov    ax,row            ; row specified?
  6438.     cmp    ax,-1            ;  ...
  6439.     je    putscol         ;  nope, inherit it
  6440.     mov    textrow,ax        ; yup, store it
  6441. putscol:
  6442.     mov    ax,col            ; col specified?
  6443.     cmp    ax,-1            ;  ...
  6444.     je    putsmode        ;  nope, inherit it
  6445.     mov    textcol,ax        ; yup, store it
  6446. putsmode:
  6447.     les    si,string        ; load buffer pointer
  6448.     cmp    text_type,0        ; are we in color text mode?
  6449.     jne    short put_substring    ;  nope
  6450.     jmp    put_text        ; yup
  6451.  
  6452. put_substring:                ; graphics mode substring loop
  6453.     push    si            ; save start pointer
  6454.     push    textcol         ; save start column
  6455. put_loop:
  6456.     mov    al,byte ptr es:[si]    ; get next char
  6457.     cmp    al,0            ; end of string?
  6458.     je    puts_chk_invert     ;  yup
  6459.     cmp    al,10            ; end of line?
  6460.     je    puts_chk_invert     ;  yup
  6461.     push    si            ; save offset
  6462.     push    es            ; save this
  6463.     push    bp            ; and this
  6464.     push    ax            ; and this last, needed soonest
  6465.     mov    ah,02h            ; set up bios set cursor call
  6466.     xor    bh,bh            ;  page 0
  6467.     mov    dl,byte ptr textcol    ;  screen location
  6468.     add    dl,byte ptr textcbase    ;   ...
  6469.     mov    dh,byte ptr textrow    ;   ...
  6470.     add    dh,byte ptr textrbase    ;   ...
  6471.     int    10h            ;  invoke the bios
  6472.     pop    ax            ; the character to write
  6473.     mov    ah,09h            ; set up the bios write char call
  6474.     mov    bx,7            ;  page zero, color
  6475.     mov    cx,1            ;  write 1 character
  6476.     int    10h            ;  invoke the bios
  6477.     pop    bp            ; restore
  6478.     pop    es            ; restore
  6479.     pop    si            ; restore
  6480.     inc    si            ; on to the next character
  6481.     inc    textcol         ;  ...
  6482.     jmp    short put_loop        ;  ...
  6483. puts_chk_invert:
  6484.     pop    bx            ; starting column number
  6485.     pop    dx            ; restore start offset
  6486.     cmp    attr,0            ; top bit of attribute on?
  6487.     jge    short puts_endsubstr    ;  nope, nothing more to do
  6488.     cmp    text_type,1        ; 640x200x2 mode?
  6489.     jne    short puts_endsubstr    ;  nope, can't do anything more
  6490.     mov    cx,si            ; calc string length
  6491.     sub    cx,dx            ;  ...
  6492.     jcxz    short puts_endsubstr    ; empty string?
  6493.     push    ax            ; remember terminating char
  6494.     push    es            ;  and this
  6495.     ; make the string inverse video on display
  6496.     mov    ax,320            ; offset in vid mem of 1st byte's top
  6497.     mov    di,textrow        ;  row*320 + col
  6498.     add    di,textrbase        ;  ...
  6499.     mul    di            ;  ...
  6500.     add    ax,bx            ;  ...
  6501.     add    ax,textcbase        ;  ...
  6502.     mov    di,ax            ;  ...
  6503.     mov    ax,0b800h        ; set es to vid memory
  6504.     mov    es,ax            ;  ...
  6505. puts_invert:
  6506.     not    byte ptr es:0000h[di]    ; invert the 8x8 making up a character
  6507.     not    byte ptr es:2000h[di]
  6508.     not    byte ptr es:0050h[di]
  6509.     not    byte ptr es:2050h[di]
  6510.     not    byte ptr es:00a0h[di]
  6511.     not    byte ptr es:20a0h[di]
  6512.     not    byte ptr es:00f0h[di]
  6513.     not    byte ptr es:20f0h[di]
  6514.     inc    di
  6515.     loop    puts_invert        ; on to the next character
  6516.     pop    es            ; restore
  6517.     pop    ax            ;  ...
  6518. puts_endsubstr:
  6519.     cmp    al,0            ; the very end?
  6520.     je    short putstring_ret    ; we done.
  6521.     inc    si            ; go past the newline char
  6522.     mov    textcol,0        ; do newline
  6523.     inc    textrow         ;  ...
  6524.     jmp    put_substring        ; on to the next piece
  6525.  
  6526. put_text:                ; text mode substring loop
  6527.     mov    ax,textrow        ; starting row
  6528.     add    ax,textrbase        ;  ...
  6529.     mov    cx,160            ; x 2 bytes/row (char & attr bytes)
  6530.     imul    cx
  6531.     mov    bx,textcol        ; add starting column
  6532.     add    bx,textcbase        ;  ...
  6533.     add    ax,bx            ; twice since 2 bytes/char
  6534.     add    ax,bx            ;  ...
  6535.     mov    di,ax            ; di -> start location in Video segment
  6536.     mov    ax,attr         ; get color attributes in ah
  6537.     cmp    mode7text,0        ; egamono/hgc? (MDA)
  6538.     je    B0            ; nope, use color attr
  6539.     mov    al,07h            ; default, white on blank
  6540.     cmp    ah,0            ; top bit of attr set?
  6541.     jge    mdachkbright        ;  nope
  6542.     mov    al,70h            ; inverse video
  6543.     jmp    short B0
  6544. mdachkbright:
  6545.     test    ah,40h            ; 2nd bit of attr set?
  6546.     jz    B0            ;  nope
  6547.     mov    al,0Fh            ; bright
  6548. B0:    mov    ah,al
  6549. B1:    mov    al,byte ptr es:[si]    ; get a char in al
  6550.     cmp    al,0            ; end of string?
  6551.     je    putstring_ret        ;  yes, done
  6552.     inc    si            ; bump for next time
  6553.     cmp    al,10            ; newline?
  6554.     jne    B2            ;  nope
  6555.     mov    textcol,0        ; yup, do it
  6556.     inc    textrow         ; ...
  6557.     jmp    short put_text        ; on to the next substring
  6558. B2:    push    es            ; No, store char & attribute
  6559.     mov    dx,textaddr        ;  ...
  6560.     mov    es,dx            ;  ...
  6561.     stosw                ;  ...
  6562.     pop    es            ;  ...
  6563.     inc    textcol         ; update local var
  6564.     jmp    short B1        ; do next char
  6565.  
  6566. putstring_ret:
  6567.     ret
  6568. putstring endp
  6569.  
  6570.  
  6571. ; ****************  EGA Palette <==> VGA DAC Conversion Routines **********
  6572.  
  6573. ;    paltodac    converts a 16-palette EGA value to a 256-color VGA
  6574. ;            value (duplicated 16 times)
  6575. ;    dactopal    converts the first 16 VGA values to a 16-palette
  6576. ;            EGA value
  6577.  
  6578. ;    local routines called with register values
  6579. ;        BH = VGA Red Color    xxRRRRRR
  6580. ;        BL = VGA Green Color    xxGGGGGG
  6581. ;        CH = VGA Blue Color    xxBBBBBB
  6582. ;        CL = EGA Palette    xxrgbRGB
  6583. ;
  6584. ;    palettetodac    converts CL to BH/BL/CH
  6585. ;    dactopalette    converte BH/BL/CH to CL
  6586.  
  6587. ; *************************************************************************
  6588.  
  6589. palettetodac    proc    near
  6590.     mov    bx,0            ; initialize RGB values to 0
  6591.     mov    ch,0            ;  ...
  6592.     test    cl,20h            ; low-red high?
  6593.     jz    palettetodac1        ;  nope
  6594.     or    bh,10h            ; set it
  6595. palettetodac1:
  6596.     test    cl,10h            ; low-green high?
  6597.     jz    palettetodac2        ;  nope
  6598.     or    bl,10h            ; set it
  6599. palettetodac2:
  6600.     test    cl,08h            ; low-blue high?
  6601.     jz    palettetodac3        ;  nope
  6602.     or    ch,10h            ; set it
  6603. palettetodac3:
  6604.     test    cl,04h            ; high-red high?
  6605.     jz    palettetodac4        ;  nope
  6606.     or    bh,20h            ; set it
  6607. palettetodac4:
  6608.     test    cl,02h            ; high-green high?
  6609.     jz    palettetodac5        ;  nope
  6610.     or    bl,20h            ; set it
  6611. palettetodac5:
  6612.     test    cl,01h            ; high-blue high?
  6613.     jz    palettetodac6        ;  nope
  6614.     or    ch,20h            ; set it
  6615. palettetodac6:
  6616.     ret
  6617. palettetodac    endp
  6618.  
  6619. dactopalette    proc    near
  6620.     mov    cl,0            ; initialize RGB values to 0
  6621.     test    bh,10h            ; low-red high?
  6622.     jz    dactopalette1        ;  nope
  6623.     or    cl,20h            ; set it
  6624. dactopalette1:
  6625.     test    bl,10h            ; low-green high?
  6626.     jz    dactopalette2        ;  nope
  6627.     or    cl,10h            ; set it
  6628. dactopalette2:
  6629.     test    ch,10h            ; low-blue high?
  6630.     jz    dactopalette3        ;  nope
  6631.     or    cl,08h            ; set it
  6632. dactopalette3:
  6633.     test    bh,20h            ; high-red high?
  6634.     jz    dactopalette4        ;  nope
  6635.     or    cl,04h            ; set it
  6636. dactopalette4:
  6637.     test    bl,20h            ; high-green high?
  6638.     jz    dactopalette5        ;  nope
  6639.     or    cl,02h            ; set it
  6640. dactopalette5:
  6641.     test    ch,20h            ; high-blue high?
  6642.     jz    dactopalette6        ;  nope
  6643.     or    cl,01h            ; set it
  6644. dactopalette6:
  6645.     ret
  6646. dactopalette    endp
  6647.  
  6648. paltodac    proc    uses es si di
  6649.     mov    si,0            ; initialize the loop values
  6650.     mov    di,0
  6651. paltodacloop:
  6652.     mov    cl,palettega[si]    ; load up a single palette register
  6653.     call    palettetodac        ; convert it to VGA colors
  6654.     mov    dacbox+0[di],bh     ; save the red value
  6655.     mov    dacbox+1[di],bl     ;  and the green value
  6656.     mov    dacbox+2[di],ch     ;  and the blue value
  6657.     inc    si            ; bump up the registers
  6658.     add    di,3            ;  ...
  6659.     cmp    si,16            ; more to go?
  6660.     jne    paltodacloop        ;  yup.
  6661.     push    ds            ; set ES to DS temporarily
  6662.     pop    es            ;  ...
  6663.     mov    ax,15            ; do this 15 times to get to 256
  6664.     mov    di,offset dacbox+48    ; set up the first destination
  6665. paltodacloop2:
  6666.     mov    cx,24            ; copy another block of 16 registers
  6667.     mov    si,offset dacbox    ; set up for the copy
  6668.     rep    movsw            ;  do it
  6669.     dec    ax            ; need to do another block?
  6670.     jnz    paltodacloop2        ;  yup.  do it.
  6671.     ret                ;  we done.
  6672. paltodac    endp
  6673.  
  6674. dactopal    proc    uses es si di
  6675.     mov    si,0            ; initialize the loop values
  6676.     mov    di,0
  6677. dactopalloop:
  6678.     mov    bh,dacbox+0[di]     ; load up the VGA red value
  6679.     mov    bl,dacbox+1[di]     ;  and the green value
  6680.     mov    ch,dacbox+2[di]     ;  and the blue value
  6681.     call    dactopalette        ; convert it to an EGA palette
  6682.     mov    palettega[si],cl    ; save as a single palette register
  6683.     inc    si            ; bump up the registers
  6684.     add    di,3            ;  ...
  6685.     cmp    si,16            ; more to go?
  6686.     jne    dactopalloop        ;  yup.
  6687.     mov    cl,palettega        ; copy palette 0
  6688.     mov    palettega+16,cl     ;  to the overscan register
  6689.     ret                ;  we done.
  6690. dactopal    endp
  6691.  
  6692.  
  6693. ; *********************** Function loaddac() ****************************
  6694.  
  6695. ;    Function to Load the dacbox[][] array, if it can
  6696. ;    (sets gotrealdac to 0 if it can't, 1 if it can)
  6697.  
  6698. loaddac proc    uses es
  6699.     cmp    dotmode, 29        ; truecolor?  MCP 5-29-91
  6700.     jne    NotTPlusLoaddac
  6701.     mov    ax,4402h
  6702.     push    ax
  6703.     mov    ax,256 * 3
  6704.     push    ax
  6705.     xor    ax,ax
  6706.     push    ax
  6707.     push    ds
  6708.     mov    ax,OFFSET dacbox
  6709.     push    ax
  6710.     call    far ptr TPlusLUT
  6711.     add    sp, 10
  6712.     or    ax, ax
  6713.     jz    NotTPlusLoaddac     ; Didn't work, try a regular palette
  6714.     jmp    loaddacdone
  6715. NotTPlusLoaddac:
  6716.     cmp    dotmode,19        ; roll-your-own video mode?
  6717.     jne    loaddac_notyourown
  6718.     call    far ptr readvideopalette
  6719.     cmp    ax,-1            ; palette-write handled yet?
  6720.     jne    go_loaddacdone        ;  yup.
  6721. loaddac_notyourown:
  6722.     mov    reallyega,0        ; set flag: not an EGA posing as a VGA
  6723.     cmp    dotmode,9        ; TARGA 3 June 89 j mclain
  6724.     je    go_loaddacdone
  6725.     cmp    f85flag, 0
  6726.     jne    go_loaddacdone
  6727.  
  6728.     cmp    xga_isinmode,0        ; XGA graphics mode?
  6729.     jne    go_loaddacdone
  6730.  
  6731.     mov    dacbox,255        ; a flag value to detect invalid DAC
  6732.     cmp    debugflag,16        ; pretend we're not a VGA?
  6733.     je    loaddacdebug        ;  yup.
  6734.     push    ds            ;  ...
  6735.     pop    es            ;  ...
  6736.     mov    ax,1017h        ; get the old DAC values
  6737.     mov    bx,0            ;  (assuming, of course, they exist)
  6738.     mov    cx,256            ;  ...
  6739.     mov    dx,offset dacbox    ;  ...
  6740.     push    bp
  6741.     int    10h            ; do it.
  6742.     pop    bp
  6743. loaddacdebug:
  6744.     cmp    dacbox,255        ; did it work?    do we have a VGA?
  6745.     je    loaddacega        ;  nope, go check ega
  6746.     cmp    colors,16        ; 16 color vga?
  6747.     jne    go_loaddacdone        ;  nope, all done
  6748.     cld                ; yup, must straighten out dacbox,
  6749.     push    ds            ;  16 color vga uses indirection thru
  6750.     pop    es            ;  palette select
  6751.     mov    si,offset dacbox+60    ; dac[20] is used for color 6 so
  6752.     mov    di,offset dacbox+18    ;  copy dacbox[20] to dacbox[6]
  6753.     mov    cx,3            ;  ...
  6754.     rep    movsb            ;  ...
  6755.     mov    si,offset dacbox+168    ; dac[56-63] are used for colors 8-15 so
  6756.     mov    di,offset dacbox+24    ;  copy dacbox[56-63] to dacbox[8-15]
  6757.     mov    cx,24            ;  ...
  6758.     rep    movsb            ;  ...
  6759. go_loaddacdone:
  6760.     jmp    short loaddacdone
  6761. loaddacega:
  6762.     cmp    colors,16        ; are we using 16 or more colors?
  6763.     jb    loaddacdone        ;  nope.  forget it.
  6764. ;;    cmp    sydots,350        ; 640x350 range?
  6765.     cmp    video_type,3        ; EGA or better?
  6766.     jb    loaddacdone        ;  nope.  forget it.
  6767.     mov    bx,offset palettega    ; make up a dummy palette
  6768.     mov    cx,3800h        ; start with color 0 == black
  6769. loaddacega1:                ; and         color 8 == low-white
  6770.     mov    0[bx],cl        ; save one color
  6771.     mov    8[bx],ch        ; and another color
  6772.     inc    bx            ; bump up the DAC
  6773.     add    cx,0101h        ; and the colors
  6774.     cmp    cl,8            ; finished 8 colors?
  6775.     jne    loaddacega1        ;  nope.  get more.
  6776.     mov    reallyega,1        ; note that this is really an EGA
  6777.     call    far ptr paltodac    ; "convert" it to a VGA DAC
  6778.     mov    daclearn,1        ; bypass learn mode
  6779.     mov    ax,cyclelimit        ;  and spin as fast as he wants
  6780.     mov    daccount,ax        ;  ...
  6781. loaddacdone:
  6782.     cmp    colors,16        ; 16 color mode?
  6783.     jne    loaddacdone2        ;  nope
  6784.     cld                ; yup, clear the excess dacbox
  6785.     mov    cx,360            ;  entries to all zeros for editpal
  6786.     sub    ax,ax
  6787.     push    ds
  6788.     pop    es
  6789.     mov    di,offset dacbox+48
  6790.     rep    stosw
  6791. loaddacdone2:
  6792.     cmp    tweakflag,0        ; tweaked mode?
  6793.     je    loaddacdone3        ;  nope
  6794.     mov    dx,3c4h         ; alter sequencer registers
  6795.     mov    ax,0604h        ; disable chain 4
  6796.     out    dx,ax
  6797. loaddacdone3:
  6798.     mov    gotrealdac,1        ; flag for whether mode supports DAC
  6799.     cmp    dacbox,255        ; did DAC get loaded or fudged?
  6800.     jne    loaddacret        ;  yup
  6801.     mov    gotrealdac,0        ; nope
  6802. loaddacret:
  6803.     ret
  6804. loaddac endp
  6805.  
  6806. ; *************** Function spindac(direction, rstep) ********************
  6807.  
  6808. ;    Rotate the MCGA/VGA DAC in the (plus or minus) "direction"
  6809. ;    in "rstep" increments - or, if "direction" is 0, just replace it.
  6810.  
  6811. spindac proc    uses di si es, direction:word, rstep:word
  6812.     cmp    dotmode,9        ; TARGA 3 June 89 j mclain
  6813.     je    spinbailout
  6814.     cmp    dotmode,11        ; disk video mode?
  6815.     je    spinbailout
  6816.     cmp    gotrealdac,0        ; do we have DAC registers to spin?
  6817.     je    spinbailout        ;  nope.  bail out.
  6818.     cmp    colors,16        ; at least 16 colors?
  6819.     jge    spindacdoit        ;  yup.  spin away.
  6820. spinbailout:
  6821.     jmp    spindacreturn        ;  nope.  bail out.
  6822.  
  6823. spindacdoit:
  6824.     push    ds            ; need ES == DS here
  6825.     pop    es            ;  ...
  6826.     cmp    direction,0        ; just replace it?
  6827.     je    newDAC            ;  yup.
  6828.  
  6829.     mov    cx, rstep        ; loop through the rotate "rstep" times
  6830. stepDAC:
  6831.     push    cx            ; save the loop counter for a tad
  6832.     mov    si,offset dacbox
  6833.     mov    di,si
  6834.     mov    ax,rotate_lo        ; calc low end of rotate range
  6835.     cmp    ax,colors        ; safety check for 16 color mode
  6836.     jae    nextDAC         ;  out of range, none to rotate
  6837.     add    si,ax
  6838.     add    si,ax
  6839.     add    si,ax
  6840.     mov    ax,rotate_hi        ; calc high end of rotate range
  6841.     cmp    ax,colors        ; safety check for 16 color mode
  6842.     jb    stepDAC2        ;  ok, in range
  6843.     mov    ax,colors        ; out of range, use colors-1
  6844.     dec    ax            ;  ...
  6845. stepDAC2:
  6846.     add    di,ax
  6847.     add    di,ax
  6848.     add    di,ax
  6849.     mov    cx,di            ; size of rotate range - 1
  6850.     sub    cx,si
  6851.     jcxz    nextDAC         ; do nothing if range 0
  6852.     cmp    direction,1        ; rotate upwards?
  6853.     jne    short downDAC        ;  nope.  downwards
  6854.     mov    bx,word ptr [si]    ; save the first entry
  6855.     mov    dl,byte ptr [si+2]    ;  ...
  6856.     cld                ; set the direction
  6857.     mov    di,si            ; set up the rotate
  6858.     add    si,3            ;  ...
  6859.     rep    movsb            ; rotate it
  6860.     mov    word ptr [di],bx    ; store the last entry
  6861.     mov    byte ptr [di+2],dl    ;  ...
  6862.     jmp    short nextDAC        ; set the new DAC
  6863. downDAC:
  6864.     std                ; set the direction
  6865.     mov    bx,word ptr [di]    ; save the last entry
  6866.     mov    dl,byte ptr [di+2]    ;  ...
  6867.     mov    si,di            ; set up the rotate
  6868.     dec    si            ;  ...
  6869.     add    di,2            ;  ...
  6870.     rep    movsb            ; rotate it
  6871.     mov    word ptr [si+1],bx    ; store the first entry
  6872.     mov    byte ptr [si+3],dl    ;  ...
  6873.     cld                ; reset the direction
  6874. nextDAC:
  6875.     pop    cx            ; restore the loop counter
  6876.     loop    stepDAC         ; and loop until done.
  6877.  
  6878. newDAC:
  6879.     cmp    dotmode,19        ; roll-your-own video?
  6880.     jne    spin_notyourown     ; nope
  6881.     call    far ptr writevideopalette
  6882.     cmp    ax,-1            ; negative result?
  6883.     je    go_spindoit        ; yup.    handle it locally.
  6884.     jmp    spindacreturn        ; else we done.
  6885. go_spindoit:
  6886.     jmp    spindoit
  6887.  
  6888. spin_notyourown:
  6889.     cmp    dotmode, 29
  6890.     je    TPlusOrXGAspindac
  6891.     cmp    xga_isinmode,0        ; XGA extended graphics?
  6892.     je    notxga
  6893.  
  6894. TPlusOrXGAspindac:
  6895.     mov    si,offset dacbox
  6896.     push    si
  6897.     mov    bx,0
  6898. xgalp1: mov    al,[si+bx]        ; adjust VGA -> XGA
  6899.     shl    al,1
  6900.     shl    al,1
  6901.     mov    [si+bx],al
  6902.     inc    bx
  6903.     cmp    bx,768
  6904.     jne    xgalp1
  6905.  
  6906.     cmp    dotmode, 29        ; Are we a TARGA+?
  6907.     jne    XGAPaletteCall        ;  nope - XGA
  6908.     mov    ax,4403h
  6909.     push    ax
  6910.     mov    ax,256 * 3
  6911.     push    ax
  6912.     xor    ax,ax
  6913.     push    ax
  6914.     push    ds
  6915.     mov    ax,OFFSET dacbox
  6916.     push    ax
  6917.     call    far ptr TPlusLUT
  6918.     add    sp, 10
  6919.     jmp    TPlusOrXGASet
  6920.  
  6921. XGAPaletteCall:
  6922.     call    far ptr xga_setpalette
  6923.  
  6924. TPlusOrXGASet:
  6925.     pop    si
  6926.     mov    bx,0
  6927. xgalp2: mov    al,[si+bx]        ; adjust XGA -> VGA
  6928.     shr    al,1
  6929.     shr    al,1
  6930.     mov    [si+bx],al
  6931.     inc    bx
  6932.     cmp    bx,768
  6933.     jne    xgalp2
  6934.     jmp    spindacreturn
  6935. notxga:
  6936.  
  6937.     cmp    bios_palette,0        ; BIOS palette updates forced?
  6938.     je    not_bios_palette    ;  nope
  6939.     mov    ax,1012h        ; use a BIOS update
  6940.     mov    bx,0
  6941.     mov    cx,256
  6942.     push    ds
  6943.     pop    es
  6944.     mov    dx,offset dacbox
  6945.     int    10h
  6946.     jmp    spindacreturn
  6947. not_bios_palette:
  6948.  
  6949.     cmp    f85flag, 0        ; if 8514a then update pallette
  6950.     je    spindoit
  6951.     jmp    spin8514
  6952.  
  6953. spindoit:
  6954.     cmp    colors,16        ; 16 color vga?
  6955.     jne    spindoit2        ;  nope
  6956.     cmp    reallyega,1        ; is this really an EGA?
  6957.     je    spindoit2        ;  yup
  6958.     cld                ; vga 16 color, straighten out dacbox,
  6959.     push    ds            ;  16 color vga uses indirection thru
  6960.     pop    es            ;  palette select
  6961.     mov    si,offset dacbox+18    ; dac[20] is used for color 6 so
  6962.     mov    di,offset dacbox+60    ;  copy dacbox[6] to dacbox[20]
  6963.     mov    cx,3            ;  ...
  6964.     rep    movsb            ;  ...
  6965.     mov    si,offset dacbox+24    ; dac[56-63] are used for colors 8-15 so
  6966.     mov    di,offset dacbox+168    ;  copy dacbox[8-15] to dacbox[56-63]
  6967.     mov    cx,24            ;  ...
  6968.     rep    movsb            ;  ...
  6969. spindoit2:
  6970.     mov    bx,0            ;  set up to update the DAC
  6971.     mov    dacnorm,0        ;  indicate no overflow
  6972. dacupdate:
  6973.     mov    cx,daccount        ;  ...
  6974.     mov    ax,256            ; calculate 256 - BX
  6975.     sub    ax,bx            ;  ...
  6976.     cmp    ax,cx            ; is that less than the update count?
  6977.     jge    retrace1        ;  nope.  no adjustment
  6978.     mov    cx,ax            ;  else adjust
  6979.     mov    dacnorm,1        ; and indicate overflow
  6980. retrace1:
  6981.     mov    dx,03dah        ; wait for no retrace
  6982.     in    al,dx            ;  ...
  6983.     and    al,8            ; this bit is high during a retrace
  6984.     jnz    retrace1        ;  so loop until it goes low
  6985. retrace2:
  6986.     in    al,dx            ; wait for no retrace
  6987.     and    al,8            ; this bit is high during a retrace
  6988.     jz    retrace2        ;  so loop until it goes high
  6989.     cmp    reallyega,1        ; is this really an EGA?
  6990.     je    spinega         ;  yup.  spin it that way.
  6991.     cmp    cpu,88            ; are we on a (yuck, ugh) 8088/8086?
  6992.     jle    spinbios        ;  yup. go through the BIOS
  6993. .186
  6994.     mov    dx,03c8h        ; set up for a blitz-write
  6995.     mov    ax,bx            ; from this register
  6996.     cli                ; critical section:  no ints
  6997.     out    dx,al            ; starting register
  6998.     inc    dx            ; set up to update colors
  6999.     mov    si, offset dacbox    ; get starting addr in SI
  7000.     add    si,bx            ;  ...
  7001.     add    si,bx            ;  ...
  7002.     add    si,bx            ;  ...
  7003.     mov    ax,cx            ; triple the value in CX
  7004.     add    cx,ax            ;  ...
  7005.     add    cx,ax            ;  ...
  7006.     rep    outsb            ; whap!  Zango!  They're updated!
  7007.     sti                ; end of critical section
  7008.     mov    cx,ax            ; restore CX for code below
  7009.     jmp    spindone        ; skip over the BIOS version.
  7010. .8086
  7011. spinbios:
  7012.     mov    dx,offset dacbox    ; set up the DAC box offset
  7013.     add    dx,bx            ;  ...
  7014.     add    dx,bx            ;  ...
  7015.     add    dx,bx            ;  ...
  7016.     push    bp            ;  save some registers
  7017.     push    cx            ;  (AMSTRAD might need this)
  7018.     push    dx            ;  ...
  7019.     push    bx            ;  ...
  7020.     mov    ax,1012h        ; update the DAC
  7021.     int    10h            ; do it.
  7022.     pop    bx            ; restore the registers
  7023.     pop    dx            ;  ...
  7024.     pop    cx            ;  ...
  7025.     pop    bp            ;  ...
  7026.     jmp    spindone        ; jump to common code
  7027. spinega:
  7028.     cmp    bx,0            ; skip this if not the first time thru
  7029.     jne    spindone        ;  ...
  7030.     push    bx            ; save some registers
  7031.     push    cx            ;  aroud the call
  7032.     call    far ptr dactopal    ; convert the VGA DAC to an EGA palette
  7033.     pop    cx            ; restore the registers
  7034.     pop    bx            ;  from prior to the call
  7035.     mov    ax,1002h        ; update the EGA palette
  7036.     mov    dx,offset palettega    ;  ...
  7037.     int    10h            ; do it.
  7038. spindone:
  7039.     cmp    daclearn,0        ; are we still in learn mode?
  7040.     jne    nolearn         ;  nope.
  7041.     mov    dx,03dah        ; check for the retrace
  7042.     in    al,dx            ;  ...
  7043.     and    al,1            ; this bit is high if display disabled
  7044.     jz    donelearn        ;  oops.  retrace finished first.
  7045.     cmp    dacnorm,0        ; was this a "short" update?
  7046.     jne    short nolearn        ;  then don't increment it
  7047.     inc    daccount        ; increment the daccount value
  7048.     inc    daccount        ; increment the daccount value
  7049.     inc    daccount        ; increment the daccount value
  7050.     mov    ax,cyclelimit        ; collect the cycle-limit value
  7051.     cmp    daccount,ax        ; sanity check: don't update too far
  7052.     jle    short nolearn        ;  proceed if reasonable.
  7053. donelearn:
  7054.     sub    daccount,6        ; done learning: reduce the daccount
  7055.     mov    daclearn,1        ; set flag: no more learning
  7056.     cmp    daccount,4        ; there's a limit to how slow we go
  7057.     jge    nolearn         ;  ...
  7058.     mov    daccount,4        ;  ...
  7059. nolearn:
  7060.     add    bx,cx            ; set up for the next batch
  7061.     cmp    bx,256            ; more to go?
  7062.     jge    spindacreturn        ;  nope.  we done.
  7063.     jmp    dacupdate        ;  yup.  do it.
  7064.  
  7065. spin8514:
  7066.     call    w8514pal
  7067.  
  7068. spindacreturn:
  7069.     ret
  7070. spindac endp
  7071.  
  7072. ; *************** Function find_special_colors ********************
  7073.  
  7074. ;    Find the darkest and brightest colors in palette, and a medium
  7075. ;    color which is reasonably bright and reasonably grey.
  7076.  
  7077. find_special_colors proc uses si
  7078.     mov    color_dark,0        ; for default cases
  7079.     mov    color_medium,7        ;  ...
  7080.     mov    color_bright,15     ;  ...
  7081.     cmp    colors,2        ; 2 color mode?
  7082.     jg    fscnot2
  7083.     mov    color_medium,1        ; yup, set assumed values and return
  7084.     mov    color_bright,1
  7085.     ret
  7086. fscnot2:
  7087.     cmp    colors,16        ; < 16 color mode? (ie probably 4)
  7088.     jge    fscnot4
  7089.     mov    color_medium,2        ; yup, set assumed values and return
  7090.     mov    color_bright,3
  7091.     ret
  7092. fscnot4:
  7093.     cmp    gotrealdac,0        ; dac valid?
  7094.     je    fscret            ; nope, return with defaults set earlier
  7095.     mov    bh,255            ; bh is lowest brightness found yet
  7096.     sub    bl,bl            ; bl is highest found yet
  7097.     sub    ah,ah            ; ah is best found for medium choice yet
  7098.     mov    si,offset dacbox    ; use si as pointer to dac
  7099.     sub    cx,cx            ; use cx for color number
  7100. fscloop:
  7101.     mov    al,byte ptr 0[si]    ; add red,green,blue (assumed all <= 63)
  7102.     add    al,byte ptr 1[si]    ;  ...
  7103.     add    al,byte ptr 2[si]    ;  ...
  7104.     cmp    al,bh            ; less than lowest found so far?
  7105.     jae    fscchkbright
  7106.     mov    color_dark,cx        ; yup, note new darkest
  7107.     mov    bh,al            ;  ...
  7108. fscchkbright:
  7109.     cmp    al,bl            ; > highest found so far?
  7110.     jbe    fscchkmedium
  7111.     mov    color_bright,cx     ; yup, note new brightest
  7112.     mov    bl,al            ;  ...
  7113. fscchkmedium:
  7114.     cmp    al,150            ; too bright?
  7115.     jae    fscnextcolor        ; yup, don't check for medium
  7116.     add    al,80            ; so the subtract below will be safe
  7117.     cmp    al,ah            ; already less than best found?
  7118.     jbe    fscnextcolor
  7119.     mov    dh,byte ptr 0[si]    ; penalize by (maxgun-mingun)/2
  7120.     mov    dl,byte ptr 1[si]
  7121.     cmp    dh,dl            ; set dh to max gun
  7122.     jae    fscmed1
  7123.     xchg    dh,dl            ; now dh=max(0,1), dl=min(0,1)
  7124. fscmed1:
  7125.     cmp    dh,byte ptr 2[si]    ; 2 > dh?
  7126.     jae    fscmed2
  7127.     mov    dh,byte ptr 2[si]
  7128. fscmed2:
  7129.     cmp    dl,byte ptr 2[si]    ; 2 < dl?
  7130.     jbe    fscmed3
  7131.     mov    dl,byte ptr 2[si]
  7132. fscmed3:
  7133.     sub    dh,dl            ; now subtract the penalty
  7134.     shr    dh,1
  7135.     sub    al,dh
  7136.     cmp    al,ah            ; a new best?
  7137.     jbe    fscnextcolor
  7138.     mov    color_medium,cx     ; yup, note new medium
  7139.     mov    ah,al            ;  ...
  7140. fscnextcolor:
  7141.     add    si,3            ; point to next dac entry
  7142.     inc    cx            ; next color number
  7143.     cmp    cx,colors        ; scanned them all?
  7144.     jl    fscloop         ; nope, go around again
  7145.     cmp    ah,0            ; find any medium color?
  7146.     jne    fscret            ; yup, all done
  7147.     mov    ax,color_bright     ; must be a pretty bright image,
  7148.     mov    color_medium,ax     ; use the brightest for medium
  7149. fscret:
  7150.     ret
  7151. find_special_colors endp
  7152.  
  7153.  
  7154. ; *************** Functions get_a_char, put_a_char ********************
  7155.  
  7156. ;    Get and put character and attribute at cursor
  7157. ;    Hi nybble=character, low nybble attribute. Text mode only
  7158.  
  7159. get_a_char proc
  7160.     mov    ah,8
  7161.     xor    bh,bh
  7162.     int    10h
  7163.     ret
  7164. get_a_char endp
  7165.  
  7166. put_a_char proc character:word
  7167.     mov    ax,character
  7168.     mov    bl,ah
  7169.     mov    ah,9
  7170.     xor    bh,bh
  7171.     mov    cx,1
  7172.     int    10h
  7173.     ret
  7174. put_a_char endp
  7175.  
  7176.     end
  7177.  
  7178.