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