home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fractint / fras1611.zip / VIDEO.ASM < prev    next >
Assembly Source File  |  1991-07-09  |  201KB  |  7,007 lines

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