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