home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / C / TGE129D / 640X480.ASM < prev    next >
Assembly Source File  |  1993-09-03  |  50KB  |  2,500 lines

  1. ; 640x480x256 (requires register-compatible VGA+)
  2. ; Loadable driver for The Graphics Engine
  3. ; Copyright (c) 1993 by Matthew Hildebrand
  4. ; Turbo Assembler syntax
  5. ; Portions by John Bridges
  6.  
  7. IDEAL
  8. MODEL LARGE TGE640X480_TEXT
  9. P386N
  10.  
  11.  
  12. SCREEN_WIDE    =    640
  13. SCREEN_DEEP    =    480
  14. NUM_COLOURS    =    256
  15.  
  16.  
  17.         CODESEG TGE640X480_TEXT
  18.         ORG    0
  19.  
  20. ;*** Signature
  21.             db    'TGE3'
  22. ;*** Non-I/O functions
  23. _initGraphics        dw    initGraphics        ; initGraphics
  24.             dw    ?
  25. _deInitGraphics        dw    0            ; deInitGraphics
  26.             dw    ?
  27. _setPaletteReg        dw    setPaletteReg        ; setPaletteReg
  28.             dw    ?
  29. _getPaletteReg        dw    getPaletteReg        ; getPaletteReg
  30.             dw    ?
  31. _setBlockPalette    dw    setBlockPalette        ; setBlockPalette
  32.             dw    ?
  33. _getBlockPalette    dw    getBlockPalette        ; getBlockPalette
  34.             dw    ?
  35. _colourCloseTo        dw    0            ; colourCloseTo
  36.             dw    ?
  37. _colourCloseToX        dw    0            ; colourCloseToX
  38.             dw    ?
  39. _imageSize        dw    0            ; imageSize
  40.             dw    ?
  41. _imageSizeDim        dw    0            ; imageSizeDim
  42.             dw    ?
  43. _setPage        dw    0            ; setPage (not implemented yet)
  44.             dw    ?
  45.  
  46. ;*** Currently active I/O functions (filled in by loadGraphDriver())
  47.             dd    20    DUP(?)
  48.  
  49. ;*** Input functions
  50. _getImage_scr        dw    0            ; getImage
  51.             dw    ?
  52. _getImage_mem        dw    0
  53.             dw    ?
  54. _getLine_scr        dw      getLine_scr              ; getLine
  55.             dw    ?
  56. _getLine_mem        dw    getLine_mem
  57.             dw    ?
  58. _getPixel_scr        dw    getPixel_scr        ; getPixel
  59.             dw    ?
  60. _getPixel_mem        dw    getPixel_mem
  61.             dw    ?
  62.  
  63. ;*** Output functions
  64. _putImage_scr_copy    dw    0            ; putImage
  65.             dw    ?
  66. _putImage_scr_and    dw    0
  67.             dw    ?
  68. _putImage_scr_not    dw    0
  69.             dw    ?
  70. _putImage_scr_or    dw    0
  71.             dw    ?
  72. _putImage_scr_xor    dw    0
  73.             dw    ?
  74. _putImage_mem_copy    dw    0
  75.             dw    ?
  76. _putImage_mem_and    dw    0
  77.             dw    ?
  78. _putImage_mem_not    dw    0
  79.             dw    ?
  80. _putImage_mem_or    dw    0
  81.             dw    ?
  82. _putImage_mem_xor    dw    0
  83.             dw    ?
  84. _putImageInv_scr_copy    dw    0            ; putImageInv
  85.             dw    ?
  86. _putImageInv_scr_and    dw    0
  87.             dw    ?
  88. _putImageInv_scr_not    dw      0
  89.             dw    ?
  90. _putImageInv_scr_or    dw      0
  91.             dw    ?
  92. _putImageInv_scr_xor    dw    0
  93.             dw    ?
  94. _putImageInv_mem_copy    dw    0
  95.             dw    ?
  96. _putImageInv_mem_and    dw    0
  97.             dw    ?
  98. _putImageInv_mem_not    dw    0
  99.             dw    ?
  100. _putImageInv_mem_or    dw    0
  101.             dw    ?
  102. _putImageInv_mem_xor    dw    0
  103.             dw    ?
  104. _putLine_scr_copy          dw    putLine_scr_copy    ; putLine
  105.             dw    ?
  106. _putLine_scr_and          dw      0
  107.             dw    ?
  108. _putLine_scr_not          dw      0
  109.             dw    ?
  110. _putLine_scr_or          dw      0
  111.             dw    ?
  112. _putLine_scr_xor          dw    0
  113.             dw    ?
  114. _putLine_mem_copy    dw      putLine_mem_copy
  115.             dw    ?
  116. _putLine_mem_and    dw      0
  117.             dw    ?
  118. _putLine_mem_not    dw      0
  119.             dw    ?
  120. _putLine_mem_or        dw      0
  121.             dw    ?
  122. _putLine_mem_xor    dw    0
  123.             dw    ?
  124. _putLineInv_scr_copy       dw    0            ; putLineInv
  125.             dw    ?
  126. _putLineInv_scr_and       dw    0
  127.             dw    ?
  128. _putLineInv_scr_not       dw    0
  129.             dw    ?
  130. _putLineInv_scr_or       dw    0
  131.             dw    ?
  132. _putLineInv_scr_xor       dw    0
  133.             dw    ?
  134. _putLineInv_mem_copy    dw    putLineInv_mem_copy
  135.             dw    ?
  136. _putLineInv_mem_and    dw    0
  137.             dw    ?
  138. _putLineInv_mem_not    dw    0
  139.             dw    ?
  140. _putLineInv_mem_or    dw    0
  141.             dw    ?
  142. _putLineInv_mem_xor    dw    0
  143.             dw    ?
  144. _putPixel_scr_copy    dw    putPixel_scr_copy    ; putPixel
  145.             dw    ?
  146. _putPixel_scr_and    dw      0
  147.             dw    ?
  148. _putPixel_scr_not    dw      0
  149.             dw    ?
  150. _putPixel_scr_or    dw      0
  151.             dw    ?
  152. _putPixel_scr_xor    dw    0
  153.             dw    ?
  154. _putPixel_mem_copy    dw    putPixel_mem_copy
  155.             dw    ?
  156. _putPixel_mem_and    dw      putPixel_mem_and
  157.             dw    ?
  158. _putPixel_mem_not    dw      putPixel_mem_not
  159.             dw    ?
  160. _putPixel_mem_or    dw      putPixel_mem_or
  161.             dw    ?
  162. _putPixel_mem_xor    dw    putPixel_mem_xor
  163.             dw    ?
  164. _line_scr_copy        dw    0            ; line
  165.             dw    ?
  166. _line_scr_and        dw      0
  167.             dw    ?
  168. _line_scr_not        dw      0
  169.             dw    ?
  170. _line_scr_or        dw      0
  171.             dw    ?
  172. _line_scr_xor        dw    0
  173.             dw    ?
  174. _line_mem_copy        dw    0
  175.             dw    ?
  176. _line_mem_and        dw    0
  177.             dw    ?
  178. _line_mem_not        dw    0
  179.             dw    ?
  180. _line_mem_or        dw    0
  181.             dw    ?
  182. _line_mem_xor        dw    0
  183.             dw    ?
  184. _horizLine_scr_copy    dw    horizLine_scr_copy      ; horizLine
  185.             dw    ?
  186. _horizLine_scr_and    dw      0
  187.             dw    ?
  188. _horizLine_scr_not    dw      0
  189.             dw    ?
  190. _horizLine_scr_or    dw      0
  191.             dw    ?
  192. _horizLine_scr_xor    dw    0
  193.             dw    ?
  194. _horizLine_mem_copy    dw    horizLine_mem_copy
  195.             dw    ?
  196. _horizLine_mem_and    dw      0
  197.             dw    ?
  198. _horizLine_mem_not    dw      0
  199.             dw    ?
  200. _horizLine_mem_or    dw      0
  201.             dw    ?
  202. _horizLine_mem_xor    dw    0
  203.             dw    ?
  204. _vertLine_scr_copy    dw    0             ; vertLine
  205.             dw    ?
  206. _vertLine_scr_and    dw    0
  207.             dw    ?
  208. _vertLine_scr_not    dw    0
  209.             dw    ?
  210. _vertLine_scr_or    dw    0
  211.             dw    ?
  212. _vertLine_scr_xor    dw    0
  213.             dw    ?
  214. _vertLine_mem_copy    dw    0
  215.             dw    ?
  216. _vertLine_mem_and    dw    0
  217.             dw    ?
  218. _vertLine_mem_not    dw    0
  219.             dw    ?
  220. _vertLine_mem_or    dw    0
  221.             dw    ?
  222. _vertLine_mem_xor    dw    0
  223.             dw    ?
  224. _drawRect_scr_copy    dw    0            ; drawRect
  225.             dw    ?
  226. _drawRect_scr_and    dw    0
  227.             dw    ?
  228. _drawRect_scr_not    dw    0
  229.             dw    ?
  230. _drawRect_scr_or    dw    0
  231.             dw    ?
  232. _drawRect_scr_xor    dw    0
  233.             dw    ?
  234. _drawRect_mem_copy    dw    0
  235.             dw    ?
  236. _drawRect_mem_and    dw    0
  237.             dw    ?
  238. _drawRect_mem_not    dw    0
  239.             dw    ?
  240. _drawRect_mem_or    dw    0
  241.             dw    ?
  242. _drawRect_mem_xor    dw    0
  243.             dw    ?
  244. _filledRect_scr_copy    dw    0            ; filledRect
  245.             dw    ?
  246. _filledRect_scr_and    dw      0
  247.             dw    ?
  248. _filledRect_scr_not    dw      0
  249.             dw    ?
  250. _filledRect_scr_or    dw      0
  251.             dw    ?
  252. _filledRect_scr_xor    dw    0
  253.             dw    ?
  254. _filledRect_mem_copy    dw    0
  255.             dw    ?
  256. _filledRect_mem_and    dw    0
  257.             dw    ?
  258. _filledRect_mem_not    dw    0
  259.             dw    ?
  260. _filledRect_mem_or    dw    0
  261.             dw    ?
  262. _filledRect_mem_xor    dw    0
  263.             dw    ?
  264. _clearGraphics_scr_copy    dw    0            ; clearGraphics
  265.             dw    ?
  266. _clearGraphics_scr_and    dw      0
  267.             dw    ?
  268. _clearGraphics_scr_not    dw      0
  269.                   dw    ?
  270. _clearGraphics_scr_or    dw      0
  271.             dw    ?
  272. _clearGraphics_scr_xor    dw    0
  273.             dw    ?
  274. _clearGraphics_mem_copy    dw    0
  275.             dw    ?
  276. _clearGraphics_mem_and    dw    0
  277.             dw    ?
  278. _clearGraphics_mem_not    dw    0
  279.             dw    ?
  280. _clearGraphics_mem_or    dw    0
  281.             dw    ?
  282. _clearGraphics_mem_xor    dw    0
  283.             dw    ?
  284. _ellipse_scr_copy    dw    0            ; ellipse
  285.             dw    ?
  286. _ellipse_scr_and    dw    0
  287.             dw    ?
  288. _ellipse_scr_not    dw    0
  289.             dw    ?
  290. _ellipse_scr_or        dw    0
  291.             dw    ?
  292. _ellipse_scr_xor    dw    0
  293.             dw    ?
  294. _ellipse_mem_copy    dw    0
  295.             dw    ?
  296. _ellipse_mem_and    dw    0
  297.             dw    ?
  298. _ellipse_mem_not    dw    0
  299.             dw    ?
  300. _ellipse_mem_or        dw    0
  301.             dw    ?
  302. _ellipse_mem_xor    dw    0
  303.             dw    ?
  304. _filledEllipse_scr_copy    dw    0            ; filledEllipse
  305.             dw    ?
  306. _filledEllipse_scr_and    dw    0
  307.             dw    ?
  308. _filledEllipse_scr_not    dw    0
  309.             dw    ?
  310. _filledEllipse_scr_or    dw    0
  311.             dw    ?
  312. _filledEllipse_scr_xor    dw    0
  313.             dw    ?
  314. _filledEllipse_mem_copy    dw    0
  315.             dw    ?
  316. _filledEllipse_mem_and    dw    0
  317.             dw    ?
  318. _filledEllipse_mem_not    dw    0
  319.             dw    ?
  320. _filledEllipse_mem_or    dw    0
  321.             dw    ?
  322. _filledEllipse_mem_xor    dw    0
  323.             dw    ?
  324. _circle_scr_copy    dw    0            ; circle
  325.             dw    ?
  326. _circle_scr_and        dw    0
  327.             dw    ?
  328. _circle_scr_not        dw    0
  329.             dw    ?
  330. _circle_scr_or        dw    0
  331.             dw    ?
  332. _circle_scr_xor        dw    0
  333.             dw    ?
  334. _circle_mem_copy    dw    0
  335.             dw    ?
  336. _circle_mem_and        dw    0
  337.             dw    ?
  338. _circle_mem_not        dw    0
  339.             dw    ?
  340. _circle_mem_or        dw    0
  341.             dw    ?
  342. _circle_mem_xor        dw    0
  343.             dw    ?
  344. _filledCircle_scr_copy    dw    0            ; filledCircle
  345.             dw    ?
  346. _filledCircle_scr_and    dw    0
  347.             dw    ?
  348. _filledCircle_scr_not    dw    0
  349.             dw    ?
  350. _filledCircle_scr_or    dw    0
  351.             dw    ?
  352. _filledCircle_scr_xor    dw    0
  353.             dw    ?
  354. _filledCircle_mem_copy    dw    0
  355.             dw    ?
  356. _filledCircle_mem_and    dw    0
  357.             dw    ?
  358. _filledCircle_mem_not    dw    0
  359.             dw    ?
  360. _filledCircle_mem_or    dw    0
  361.             dw    ?
  362. _filledCircle_mem_xor    dw    0
  363.             dw    ?
  364. _fillRegion_scr_copy    dw    0            ; fillRegion
  365.             dw    ?
  366. _fillRegion_scr_and    dw    0
  367.             dw    ?
  368. _fillRegion_scr_not    dw    0
  369.             dw    ?
  370. _fillRegion_scr_or    dw    0
  371.             dw    ?
  372. _fillRegion_scr_xor    dw    0
  373.             dw    ?
  374. _fillRegion_mem_copy    dw    0
  375.             dw    ?
  376. _fillRegion_mem_and    dw    0
  377.             dw    ?
  378. _fillRegion_mem_not    dw    0
  379.             dw    ?
  380. _fillRegion_mem_or    dw    0
  381.             dw    ?
  382. _fillRegion_mem_xor    dw    0
  383.             dw    ?
  384. _fillLine_scr_copy    dw    horizLine_scr_copy    ; fillLine
  385.             dw    ?
  386. _fillLine_scr_and    dw      0
  387.             dw    ?
  388. _fillLine_scr_not    dw      0
  389.             dw    ?
  390. _fillLine_scr_or    dw      0
  391.             dw    ?
  392. _fillLine_scr_xor    dw    0
  393.             dw    ?
  394. _fillLine_mem_copy    dw    horizLine_mem_copy
  395.             dw    ?
  396. _fillLine_mem_and    dw      0
  397.             dw    ?
  398. _fillLine_mem_not    dw      0
  399.             dw    ?
  400. _fillLine_mem_or    dw      0
  401.             dw    ?
  402. _fillLine_mem_xor    dw    0
  403.             dw    ?
  404. ;*** Mode information
  405. scrnMaxX        dw    639    ; physical dimensions
  406. scrnMaxY        dw    479
  407. maxColour        dw    255    ; maximum colour number
  408. xRatio                   dw    4    ; aspect ratio 4:3 (640:480 in
  409. yRatio            dw    3    ;   lowest terms)
  410. bitsPerPixel        dw    8    ; 8 bits per pixel
  411. inMaxX            dw    639    ; current input screen dimensions
  412. inMaxY            dw    479
  413. outMaxX            dw    639    ; current output screen dimensions
  414. outMaxY            dw    479
  415. inScreenWide        dw    ?    ; needed only for virtual screens
  416. outScreenWide        dw    ?
  417. ;*** Viewport information
  418. inViewportULX        dw    0
  419. inViewportULY        dw    0
  420. inViewportLRX        dw    639
  421. inViewportLRY        dw    479
  422. outViewportULX        dw    0
  423. outViewportULY        dw    0
  424. outViewportLRX        dw    639
  425. outViewportLRY        dw    479
  426. ;*** Paging information
  427. pagingSupported        dw    ?    ; not implemented yet
  428. curPage            dw    ?    ; not implemented yet
  429. maxPage            dw    ?    ; not implemented yet
  430. ;*** Force (image width MOD imageWideAdjust) = 0.
  431. imageWideAdjust        dw    ?    ; not implemented yet
  432. ;*** Current and screen addresses
  433.     LABEL    inAddr    DWORD        ; current input address
  434. inOff    dw    0
  435. inSeg    dw    0A000h
  436.     LABEL    outAddr    DWORD        ; current output address
  437. outOff    dw    0
  438. outSeg    dw    0A000h
  439.     LABEL    scrAddr    DWORD        ; screen address
  440. scrOff    dw    0
  441. scrSeg    dw    0A000h
  442. ;*** Copyright string
  443.     db    'The Graphics Engine -- Copyright (c) 1993 by Matthew Hildebrand'
  444.  
  445.  
  446. inited        db    0
  447. colourPalette    db    768    DUP(?)
  448. lineOffs    dw    SCREEN_DEEP    DUP(?)
  449. bankNum        dw    SCREEN_DEEP    DUP(?)
  450. bankChanges    dw    SCREEN_DEEP    DUP(?)
  451. curBank        dw    ?
  452. screenWide    dw    ?
  453.  
  454. bankadr        dw    OFFSET _nobank
  455. vgamem        dw    ?
  456. bksize        dw    ?
  457. bksizeShl10Dec    dw    ?
  458. retval        dw    ?        ; first return value from whichVGA()
  459. scanline        dw      SCREEN_WIDE
  460.  
  461. acumos        dw    ?
  462. aheada        dw    ?
  463. aheadb        dw    ?
  464. ativga        dw    ?
  465. chipstech     dw    ?
  466. cirrus        dw    ?
  467. compaq        dw    ?
  468. everex        dw    ?
  469. genoa        dw    ?
  470. ncr        dw    ?
  471. oak067        dw    ?
  472. paradise     dw    ?
  473. trident        dw    ?
  474. t8900        dw    ?
  475. tseng        dw    ?
  476. tseng4        dw    ?
  477. video7        dw    ?
  478. vesa        dw    ?
  479.  
  480.  
  481. ; VESA information
  482.     STRUC    vgainfo
  483. VESASignature    db    4 dup (?)    ; 4 signature bytes
  484. VESAVersion    dw    ?        ; VESA version number
  485. OEMStringPtr    dd    ?        ; Pointer to OEM string
  486. Capabilities    db    4 dup (?)    ; Capabilities of the video environment
  487. VideoModePtr    dd    ?        ; Pointer to supported Super VGA modes
  488.     ENDS
  489.     STRUC    vesamode
  490. ModeAttributes    dw    ?    ; mode attributes
  491. WinAAttributes    db    ?    ; window A attributes
  492. WinBAttributes    db    ?    ; window B attributes
  493. WinGranularity    dw    ?    ; window granularity
  494. WinSize        dw    ?    ; window size
  495. WinASegment    dw    ?    ; window A start segment
  496. WinBSegment    dw    ?    ; window B start segment
  497. WinFuncPtr    dd    ?    ; pointer to window function
  498. BytesPerLine    dw    ?    ; bytes per scan line
  499. ; optional information (provided if bit D1 of ModeAttributes is set)
  500. XResolution    dw    ?    ; horizontal resolution
  501. YResolution    dw    ?    ; vertical resolution
  502. XCharSize    db    ?    ; character cell width
  503. YCharSize    db    ?    ; character cell height
  504. NumberOfPlanes    db    ?    ; number of memory planes
  505. BitsPerPixel    db    ?    ; bits per pixel
  506. NumberOfBanks    db    ?    ; number of banks
  507. MemoryModel    db    ?    ; memory model type
  508. BankSize    db    ?    ; bank size in kb
  509.     db    227    DUP(?)    ; pad to 256 bytes
  510.     ENDS
  511.  
  512. vesabuf        db    256    DUP(?)
  513. modebuf        vesamode    ?
  514.  
  515.  
  516. MACRO    NEWBANK
  517.   call    [bankadr]
  518. ENDM
  519.  
  520.  
  521. ;*****
  522. ;***** initGraphics
  523. ;*****
  524.  
  525. PROC    C    initGraphics
  526.   cmp    [inited],0
  527.   je    @@NotInited
  528.   call    setMode
  529.   mov    ax,1
  530.   retf
  531.  
  532.       @@NotInited:
  533.   call    whichVGA
  534.   or    ax,ax                ; was function successful?
  535.   jz    @@Error                ; no, quit
  536.   call    setMode
  537.   or    ax,ax                 ; was function successful?
  538.   jz    @@Error                ; no, quit
  539.   call    makeAddrTable
  540.  
  541.   cmp    [vgamem],512            ; ensure enough memory
  542.   jb    @@Error                ; abort if <512 K of video RAM
  543.  
  544.   mov    ax,[bksize]            ; initialize bksizeShl10Dec
  545.   shl    ax,10                ; shift it
  546.   dec    ax                ; decrement it
  547.   mov    [bksizeShl10Dec],ax        ; store it
  548.  
  549.   mov    ax,1
  550.   mov    [inited],al
  551.   retf
  552.  
  553.     @@Error:
  554.   xor    ax,ax
  555.   retf
  556. ENDP
  557.  
  558.  
  559. ;*****
  560. ;***** putLine
  561. ;*****
  562.  
  563. PROC    C    putLine_scr_copy
  564.     ARG    y:WORD, xOff:WORD, lineLen:WORD, buf:DWORD
  565.   push    ds si di
  566.  
  567.   cld
  568.   mov    bx,[y]                ; Decide if bank changes mid-line
  569.   shl    bx,1
  570.   cmp    [cs:bankChanges+bx],0
  571.   jne    @@BankChanged
  572.  
  573.   mov    ax,[cs:bankNum+bx]
  574.   cmp    ax,[curBank]            ; set bank only if necessary
  575.   je    @@NoNewBank
  576.   NEWBANK
  577.  
  578.     @@NoNewBank:
  579.   mov    cx,[lineLen]            ; blast the line into video memory
  580.   mov    ax,0A000h
  581.   mov    es,ax
  582.   mov    di,[cs:lineOffs+bx]
  583.   add    di,[xOff]
  584.   lds    si,[buf]
  585.   mov    dx,cx                ; DX = CX
  586.   shr    cx,2                ; CX = line length in dwords
  587.   rep    movsd                ; copy the dwords
  588.   mov    cx,dx                ; CX = line length in bytes
  589.   and    cx,0000000000000011b        ; CX = number of residual bytes
  590.   rep    movsb                ; copy the residual bytes, if any
  591.   pop    di si ds            ; restore registers
  592.   leave                        ; clean up call stack
  593.   retf                    ; return
  594.  
  595.     @@BankChanged:                  ; slow pixel-by-pixel
  596.   mov    cx,[lineLen]
  597.   mov    dx,[y]
  598.   mov    bx,[xOff]
  599.   lds    si,[buf]
  600.     @@Loop:
  601.   lodsb
  602.   push    bx cx dx si
  603.   call    far putPixel_scr_copy C,bx,dx,ax
  604.   pop    si dx cx bx
  605.   inc    bx
  606.   loop    @@Loop
  607.  
  608.   pop    di si ds
  609.   leave
  610.   retf
  611. ENDP
  612.  
  613. PROC    C    putLine_mem_copy
  614.     ARG    y:WORD, xOff:WORD, lineLen:WORD, buf:DWORD
  615.   push    ds si di            ; save these registers
  616.  
  617.   xor    eax,eax                ; clear EAX
  618.   xor    edx,edx                ; clear EDX
  619.   xor    edi,edi                ; clear EDI
  620.  
  621.   les    di,[outAddr]            ; load output address
  622.   mov    ax,[y]
  623.   mov    dx,[outScreenWide]
  624.   mul    edx                    ; EDX:EAX = offset - EDI - x
  625.   add    edi,eax                ; EDI = offset - x
  626.   mov    dx,[xOff]
  627.   add    edi,edx                ; EDI = offset
  628.   mov    edx,edi                ; EDX = offset
  629.   shr    edx,4                ; EDX = # of paragraphs (segments)
  630.   add    dx,[outSeg]            ; DX = new segment
  631.   mov    es,dx                ; ES = new segment
  632.   and    di,0000000000001111b             ; DI = offset within new segment
  633.  
  634.   lds    si,[buf]            ; load input address
  635.   mov    dx,si                ; DX = offset
  636.   shr    dx,4                ; DX = # of paragraphs (segments)
  637.   mov    ax,ds                ; AX = DS
  638.   add    ax,dx                ; AX = new DS
  639.   mov    ds,ax                ; DS = new DS
  640.   and    si,0000000000001111b        ; SI = offset within new segment
  641.  
  642.   cld
  643.   mov    cx,[lineLen]            ; CX = line length
  644.   mov    dx,cx                ; DX = line length
  645.   shr    cx,2                ; CX = line length in dwords
  646.   rep    movsd                     ; move the dwords if necessary
  647.   mov    cx,dx                ; CX = line length in bytes
  648.   and    cx,0000000000000011b        ; CX = any residual bytes
  649.   rep    movsb                ; move the bytes if necessary
  650.  
  651.   pop    di si ds            ; restore registers
  652.   leave                    ; clean up
  653.   retf                    ; return
  654. ENDP
  655.  
  656.  
  657. ;*****
  658. ;***** putLineInv
  659. ;*****
  660.  
  661. PROC    C    putLineInv_mem_copy
  662.     ARG    y:WORD, xOff:WORD, lineLen:WORD, buf:DWORD
  663.   push    ds si di            ; save these registers
  664.  
  665.   xor    eax,eax                ; clear EAX
  666.   xor    edx,edx                ; clear EDX
  667.   xor    edi,edi                ; clear EDI
  668.  
  669.   les    di,[outAddr]            ; load output address
  670.   mov    ax,[y]
  671.   mov    dx,[outScreenWide]
  672.   mul    edx                    ; EDX:EAX = offset - EDI - x
  673.   add    edi,eax                ; EDI = offset - x
  674.   mov    dx,[xOff]
  675.   add    edi,edx                ; EDI = offset
  676.   mov    edx,edi                ; EDX = offset
  677.   shr    edx,4                ; EDX = # of paragraphs (segments)
  678.   add    dx,[outSeg]            ; DX = new segment
  679.   mov    es,dx                ; ES = new segment
  680.   and    di,0000000000001111b             ; DI = offset within new segment
  681.  
  682.   lds    si,[buf]            ; load input address
  683.   mov    dx,si                ; DX = offset
  684.   shr    dx,4                ; DX = # of paragraphs (segments)
  685.   mov    ax,ds                ; AX = DS
  686.   add    ax,dx                ; AX = new DS
  687.   mov    ds,ax                ; DS = new DS
  688.   and    si,0000000000001111b        ; SI = offset within new segment
  689.  
  690.   cld
  691.   mov    cx,[lineLen]            ; CX = line length
  692.  
  693.     @@loopStart:
  694.   lodsb                    ; grab a pixel
  695.   or    al,al                ; is it a zero pixel?
  696.   jz    @@invisible            ; yes, don't copy it
  697.   stosb                    ; no, copy it ...
  698.   loop    @@loopStart            ; ... and start loop again
  699.   jmp    short    @@loopDone        ; quit loop when completed
  700.     @@invisible:
  701.   inc    di                ; skip past pixel ...
  702.   loop    @@loopStart            ; ... and start loop again
  703.  
  704.     @@loopDone:
  705.   pop    di si ds            ; restore registers
  706.   leave                    ; clean up
  707.   retf                    ; return
  708. ENDP
  709.  
  710.  
  711. ;*****
  712. ;***** getLine
  713. ;*****
  714.  
  715. PROC    C    getLine_scr
  716.     ARG    y:WORD, xOff:WORD, lineLen:WORD, buf:DWORD
  717.   push    ds si di
  718.  
  719.   cld
  720.   mov    bx,[y]                ; Decide if bank changes mid-line
  721.   shl    bx,1
  722.   cmp    [cs:bankChanges+bx],0
  723.   jne    @@BankChanged
  724.  
  725.   mov    ax,[cs:bankNum+bx]
  726.   cmp    ax,[curBank]            ; set bank only if necessary
  727.   je    @@NoNewBank
  728.   NEWBANK
  729.  
  730.     @@NoNewBank:
  731.   mov    cx,[lineLen]            ; blast the line into video memory
  732.   mov    ax,0A000h
  733.   mov    ds,ax
  734.   mov    si,[cs:lineOffs+bx]
  735.   add    si,[xOff]
  736.   les    di,[buf]
  737.   mov    dx,cx                ; DX = CX
  738.   shr    cx,2                ; CX = line length in dwords
  739.   rep    movsd                ; copy the dwords
  740.   mov    cx,dx                ; CX = line length in bytes
  741.   and    cx,0000000000000011b        ; CX = number of residual bytes
  742.   rep    movsb                ; copy the residual bytes, if any
  743.   pop    di si ds            ; restore registers
  744.   leave                        ; clean up call stack
  745.   retf                    ; return
  746.  
  747.     @@BankChanged:                  ; slow pixel-by-pixel
  748.   mov    cx,[lineLen]
  749.   mov    dx,[y]
  750.   mov    bx,[xOff]
  751.   les    di,[buf]
  752.     @@Loop:
  753.   push    bx cx dx di es
  754.   call    far getPixel_scr C,bx,dx
  755.   pop    es di dx cx bx
  756.   stosb
  757.   inc    bx
  758.   loop    @@Loop
  759.  
  760.   pop    di si ds
  761.   leave
  762.   retf
  763. ENDP
  764.  
  765. PROC    C    getLine_mem
  766.     ARG    y:WORD, xOff:WORD, lineLen:WORD, buf:DWORD
  767.   push    ds si di            ; save these registers
  768.  
  769.   xor    eax,eax                ; clear EAX
  770.   xor    edx,edx                ; clear EDX
  771.   xor    esi,esi                ; clear ESI
  772.  
  773.   les    si,[inAddr]            ; load input address
  774.   mov    ax,[y]
  775.   mov    dx,[inScreenWide]
  776.   mul    edx                    ; EDX:EAX = offset - ESI - x
  777.   add    esi,eax                ; ESI = offset - x
  778.   mov    dx,[xOff]
  779.   add    esi,edx                ; ESI = offset
  780.   mov    edx,esi                ; EDX = offset
  781.   shr    edx,4                ; EDX = # of paragraphs (segments)
  782.   add    dx,[inSeg]            ; DX = new segment
  783.   mov    ds,dx                ; ES = new segment
  784.   and    si,0000000000001111b             ; SI = offset within new segment
  785.  
  786.   les    di,[buf]            ; load output address
  787.   mov    dx,di                ; DX = offset
  788.   shr    dx,4                ; DX = # of paragraphs (segments)
  789.   mov    ax,es                ; AX = ES
  790.   add    ax,dx                ; AX = new ES
  791.   mov    es,ax                ; ES = new ES
  792.   and    di,0000000000001111b        ; DI = offset within new segment
  793.  
  794.   cld
  795.   mov    cx,[lineLen]            ; CX = line length
  796.   mov    dx,cx                ; DX = line length
  797.   shr    cx,2                ; CX = line length in dwords
  798.   rep    movsd                     ; move the dwords if necessary
  799.   mov    cx,dx                ; CX = line length in bytes
  800.   and    cx,0000000000000011b        ; CX = any residual bytes
  801.   rep    movsb                ; move the bytes if necessary
  802.  
  803.   pop    di si ds            ; restore registers
  804.   leave                    ; clean up
  805.   retf                    ; return
  806. ENDP
  807.  
  808.  
  809. ;*****
  810. ;***** putPixel
  811. ;*****
  812.  
  813. ; Copy a pixel to the screen
  814. PROC    C    putPixel_scr_copy
  815.     ARG    x:WORD, y:WORD, colour:BYTE
  816.   mov    bx,[y]                ; BX = y coordinate
  817.   shl    bx,1                ; to access a table of words
  818.   mov    ax,[cs:bankNum+bx]        ; AX = bank at start of line
  819.   mov    bx,[cs:lineOffs+bx]        ; DX = offset at start of line
  820.   add    bx,[x]                ; BX = offset of pixel
  821.   adc    ax,0                ; in case of overflow, inc AX
  822.   mov    dx,[bksizeShl10Dec]        ; DX = bank size in bytes - 1
  823.   cmp    bx,dx                ; is offset > than bank size
  824.   jbe    @@offsetOK            ; no, proceed
  825.  
  826.   sub    bx,dx                ; BX = fixed offset
  827.   inc    ax                ; AX = new bank
  828.  
  829.     @@offsetOK:
  830.   cmp    ax,[curBank]
  831.   je    @@NoNew
  832.   NEWBANK                ; switch banks if a new bank entered
  833.     @@NoNew:
  834.   mov    ax,0A000h            ; setup screen segment A000
  835.   mov    es,ax
  836.   mov    al,[colour]            ; get color of pixel to plot
  837.   mov    [es:bx],al
  838.   leave
  839.   retf
  840. ENDP
  841.  
  842. ; Copy a pixel to memory
  843. PROC    C    putPixel_mem_copy
  844.     ARG    x:WORD,y:WORD,colour:BYTE
  845.   xor    eax,eax                ; clear EAX
  846.   xor    ebx,ebx                ; clear EBX
  847.   xor    edx,edx                ; clear EDX
  848.  
  849.   les    bx,[outAddr]            ; load output address
  850.   mov    ax,[y]
  851.   mov    dx,[outScreenWide]
  852.   mul    edx                    ; EDX:EAX = offset - EBX - x
  853.   add    ebx,eax                ; EBX = offset - x
  854.   mov    dx,[x]
  855.   add    ebx,edx                ; EBX = offset
  856.  
  857.   mov    edx,ebx                ; EDX = offset
  858.   shr    edx,4                ; EDX = # of paragraphs (segments)
  859.   add    dx,[outSeg]            ; DX = new segment
  860.   mov    es,dx                ; ES = new segment
  861.   and    bx,0000000000001111b             ; BX = offset within new segment
  862.  
  863.   mov    al,[colour]            ; colour in AL
  864.   mov    [es:bx],al            ; store pixel
  865.   leave                    ; clean up
  866.   retf                    ; return
  867. ENDP
  868.  
  869. ; AND a pixel to memory
  870. PROC    C    putPixel_mem_and
  871.     ARG    x:WORD,y:WORD,colour:BYTE
  872.   xor    eax,eax                ; clear EAX
  873.   xor    ebx,ebx                ; clear EBX
  874.   xor    edx,edx                ; clear EDX
  875.  
  876.   les    bx,[outAddr]            ; load output address
  877.   mov    ax,[y]
  878.   mov    dx,[outScreenWide]
  879.   mul    edx                    ; EDX:EAX = offset - EBX - x
  880.   add    ebx,eax                ; EBX = offset - x
  881.   mov    dx,[x]
  882.   add    ebx,edx                ; EBX = offset
  883.  
  884.   mov    edx,ebx                ; EDX = offset
  885.   shr    edx,4                ; EDX = # of paragraphs (segments)
  886.   add    dx,[outSeg]            ; DX = new segment
  887.   mov    es,dx                ; ES = new segment
  888.   and    bx,0000000000001111b             ; BX = offset within new segment
  889.  
  890.   mov    al,[colour]            ; colour in AL
  891.   and    [es:bx],al            ; AND pixel
  892.   leave                    ; clean up
  893.   retf                    ; return
  894. ENDP
  895.  
  896. ; NOT a pixel to memory
  897. PROC    C    putPixel_mem_not
  898.     ARG    x:WORD,y:WORD,colour:BYTE
  899.   xor    eax,eax                ; clear EAX
  900.   xor    ebx,ebx                ; clear EBX
  901.   xor    edx,edx                ; clear EDX
  902.  
  903.   les    bx,[outAddr]            ; load output address
  904.   mov    ax,[y]
  905.   mov    dx,[outScreenWide]
  906.   mul    edx                    ; EDX:EAX = offset - EBX - x
  907.   add    ebx,eax                ; EBX = offset - x
  908.   mov    dx,[x]
  909.   add    ebx,edx                ; EBX = offset
  910.  
  911.   mov    edx,ebx                ; EDX = offset
  912.   shr    edx,4                ; EDX = # of paragraphs (segments)
  913.   add    dx,[outSeg]            ; DX = new segment
  914.   mov    es,dx                ; ES = new segment
  915.   and    bx,0000000000001111b             ; BX = offset within new segment
  916.  
  917.   mov    al,[colour]            ; colour in AL
  918.   not    al                ; NOT it
  919.   mov    [es:bx],al            ; store NOTed pixel
  920.   leave                    ; clean up
  921.   retf                    ; return
  922. ENDP
  923.  
  924. ; OR a pixel to memory
  925. PROC    C    putPixel_mem_or
  926.     ARG    x:WORD,y:WORD,colour:BYTE
  927.   xor    eax,eax                ; clear EAX
  928.   xor    ebx,ebx                ; clear EBX
  929.   xor    edx,edx                ; clear EDX
  930.  
  931.   les    bx,[outAddr]            ; load output address
  932.   mov    ax,[y]
  933.   mov    dx,[outScreenWide]
  934.   mul    edx                    ; EDX:EAX = offset - EBX - x
  935.   add    ebx,eax                ; EBX = offset - x
  936.   mov    dx,[x]
  937.   add    ebx,edx                ; EBX = offset
  938.  
  939.   mov    edx,ebx                ; EDX = offset
  940.   shr    edx,4                ; EDX = # of paragraphs (segments)
  941.   add    dx,[outSeg]            ; DX = new segment
  942.   mov    es,dx                ; ES = new segment
  943.   and    bx,0000000000001111b             ; BX = offset within new segment
  944.  
  945.   mov    al,[colour]            ; colour in AL
  946.   or    [es:bx],al            ; OR pixel
  947.   leave                    ; clean up
  948.   retf                    ; return
  949. ENDP
  950.  
  951. ; XOR a pixel to memory
  952. PROC    C    putPixel_mem_xor
  953.     ARG    x:WORD,y:WORD,colour:BYTE
  954.   xor    eax,eax                ; clear EAX
  955.   xor    ebx,ebx                ; clear EBX
  956.   xor    edx,edx                ; clear EDX
  957.  
  958.   les    bx,[outAddr]            ; load output address
  959.   mov    ax,[y]
  960.   mov    dx,[outScreenWide]
  961.   mul    edx                    ; EDX:EAX = offset - EBX - x
  962.   add    ebx,eax                ; EBX = offset - x
  963.   mov    dx,[x]
  964.   add    ebx,edx                ; EBX = offset
  965.  
  966.   mov    edx,ebx                ; EDX = offset
  967.   shr    edx,4                ; EDX = # of paragraphs (segments)
  968.   add    dx,[outSeg]            ; DX = new segment
  969.   mov    es,dx                ; ES = new segment
  970.   and    bx,0000000000001111b             ; BX = offset within new segment
  971.  
  972.   mov    al,[colour]            ; colour in AL
  973.   xor    [es:bx],al            ; XOR pixel
  974.   leave                    ; clean up
  975.   retf                    ; return
  976. ENDP
  977.  
  978.  
  979. ;*****
  980. ;***** getPixel
  981. ;*****
  982.  
  983. ; Get a pixel from the screen
  984. PROC    C    getPixel_scr
  985.     ARG    x:WORD, y:WORD
  986.   mov    bx,[y]                ; BX = y coordinate
  987.   shl    bx,1                ; to access a table of words
  988.   mov    ax,[cs:bankNum+bx]        ; AX = bank at start of line
  989.   mov    bx,[cs:lineOffs+bx]        ; DX = offset at start of line
  990.   add    bx,[x]                ; BX = offset of pixel
  991.   adc    ax,0                ; in case of overflow, inc AX
  992.   mov    dx,[bksizeShl10Dec]        ; DX = bank size in bytes - 1
  993.   cmp    bx,dx                ; is offset > than bank size
  994.   jb    @@offsetOK            ; no, proceed
  995.  
  996.   sub    bx,dx                ; BX = fixed offset
  997.   inc    ax                ; AX = new bank
  998.  
  999.     @@offsetOK:
  1000.   cmp    ax,[curBank]
  1001.   je    @@NoNew
  1002.   NEWBANK                ; switch banks if a new bank entered
  1003.     @@NoNew:
  1004.   mov    ax,0A000h            ; setup screen segment A000
  1005.   mov    es,ax
  1006.   mov    al,[es:bx]            ; AL = colour for return
  1007.   leave
  1008.   retf
  1009. ENDP
  1010.  
  1011. ; Get a pixel from memory
  1012. PROC    C    getPixel_mem
  1013.     ARG    x:WORD,y:WORD
  1014.   xor    eax,eax                ; clear EAX
  1015.   xor    ebx,ebx                ; clear EBX
  1016.   xor    edx,edx                ; clear EDX
  1017.  
  1018.   les    bx,[inAddr]            ; load input address
  1019.   mov    ax,[y]
  1020.   mov    dx,[inScreenWide]
  1021.   mul    edx                    ; EDX:EAX = offset - EBX - x
  1022.   add    ebx,eax                ; EBX = offset - x
  1023.   mov    dx,[x]
  1024.   add    ebx,edx                ; EBX = offset
  1025.  
  1026.   mov    edx,ebx                ; EDX = offset
  1027.   shr    edx,4                ; EDX = # of paragraphs (segments)
  1028.   add    dx,[inSeg]            ; DX = new segment
  1029.   mov    es,dx                ; ES = new segment
  1030.   and    bx,0000000000001111b             ; BX = offset within new segment
  1031.  
  1032.   xor    ax,ax                ; clear AX
  1033.   mov    al,[es:bx]            ; store pixel in AX for return
  1034.   leave                    ; clean up
  1035.   retf                    ; return
  1036. ENDP
  1037.  
  1038.  
  1039. ;*****
  1040. ;***** horizLine
  1041. ;*****
  1042.  
  1043. PROC    C    horizLine_scr_copy
  1044.     ARG    y:WORD, x1:WORD, x2:WORD, colour:BYTE
  1045.   push    di
  1046.  
  1047.   cld
  1048.   mov    bx,[y]                ; Decide if bank changes mid-line
  1049.   shl    bx,1
  1050.   cmp    [cs:bankChanges+bx],0
  1051.   jne    @@BankChanged
  1052.  
  1053.   mov    ax,[cs:bankNum+bx]
  1054.   cmp    ax,[curBank]            ; set bank only if necessary
  1055.   je    @@NoNewBank
  1056.   NEWBANK
  1057.  
  1058.     @@NoNewBank:
  1059.   mov    ax,0A000h
  1060.   mov    es,ax
  1061.   mov    ax,[x1]
  1062.   mov    di,[cs:lineOffs+bx]
  1063.   add    di,ax
  1064.   mov    cx,[x2]                ; blast the line into video memory
  1065.   inc    cx
  1066.   sub    cx,ax
  1067.   mov    al,[colour]            ; AL = colour
  1068.   mov    ah,al                ; AH = colour
  1069.   mov    dx,ax                ; DX = colour:colour
  1070.   shl    eax,16                ; EAX = colour:colour:?:?
  1071.   mov    ax,dx                ; EAX = colour:colour:colour:colour
  1072.   mov    dx,cx                ; DX = CX
  1073.   shr    cx,2                ; CX = line length in dwords
  1074.   rep    stosd                ; store the dwords
  1075.   mov    cx,dx                ; CX = line length in bytes
  1076.   and    cx,0000000000000011b        ; CX = number of residual bytes
  1077.   rep    stosb                ; store the residual bytes, if any
  1078.   pop    di                ; restore DI
  1079.   leave                    ; clean up call stack
  1080.   retf                    ; return
  1081.  
  1082.     @@BankChanged:                  ; slow pixel-by-pixel
  1083.   mov    bx,[x1]
  1084.   mov    cx,[x2]
  1085.   inc    cx
  1086.   sub    cx,bx
  1087.   mov    dx,[y]
  1088.     @@Loop:
  1089.   push    bx cx dx
  1090.   mov    al,[colour]
  1091.   call    far putPixel_scr_copy C,bx,dx,ax
  1092.   pop    dx cx bx
  1093.   inc    bx
  1094.   loop    @@Loop
  1095.  
  1096.   pop    di
  1097.   leave
  1098.   retf
  1099. ENDP
  1100.  
  1101. PROC    C    horizLine_mem_copy
  1102.     ARG    y:WORD, x1:WORD, x2:WORD, colour:BYTE
  1103.   push    edi                ; store EDI
  1104.  
  1105.   xor    eax,eax                ; clear EAX
  1106.   xor    edi,edi                ; clear EDI
  1107.   xor    edx,edx                ; clear EDX
  1108.  
  1109.   les    di,[outAddr]            ; load output address
  1110.   mov    ax,[y]
  1111.   mov    dx,[outScreenWide]
  1112.   mul    edx                    ; EDX:EAX = offset - EDI - x
  1113.   add    edi,eax                ; EDI = offset - x
  1114.   mov    dx,[x1]
  1115.   add    edi,edx                ; EDI = offset
  1116.   mov    edx,edi                ; EDX = offset
  1117.   shr    edx,4                ; EDX = # of paragraphs (segments)
  1118.   add    dx,[outSeg]            ; DX = new segment
  1119.   mov    es,dx                ; ES = new segment
  1120.   and    di,0000000000001111b             ; DI = offset within new segment
  1121.  
  1122.   mov    al,[colour]            ; colour in AL
  1123.   mov    ah,al                ; colour in AH
  1124.   mov    bx,ax
  1125.   shl    eax,16
  1126.   mov    ax,bx                 ; colour in each byte of EAX
  1127.  
  1128.   mov    cx,[x2]
  1129.   sub    cx,[x1]
  1130.   inc    cx                ; CX = line length in pixels
  1131.   mov    dx,cx                ; DX = line length in bytes
  1132.  
  1133.   shr    cx,2                ; CX = line length in dwords
  1134.   rep    stosd                ; store four bytes at a time
  1135.   mov    cx,dx                ; CX = line length in pixels
  1136.   and    cx,0000000000000011b        ; CX = any remaining bytes
  1137.   rep    stosb                ; store the remaining bytes
  1138.  
  1139.   pop    edi                    ; restore EDI
  1140.   leave                    ; clean up
  1141.   retf                    ; return
  1142. ENDP
  1143.  
  1144.  
  1145. ;*****
  1146. ;***** setPaletteReg
  1147. ;*****
  1148.  
  1149. PROC    C    setPaletteReg
  1150.     ARG    palNum:WORD,red:BYTE,green:BYTE,blue:BYTE
  1151.   mov    bx,[palNum]
  1152.  
  1153.   mov    dx,3C8h                ; set for correct palette register
  1154.   mov    ax,[palNum]
  1155.   out    dx,al
  1156.   inc    dx
  1157.  
  1158.   mov    al,[red]            ; red
  1159.   shr    al,2
  1160.   jnc    @@L1
  1161.   cmp    al,63
  1162.   je    @@L1
  1163.   inc    al
  1164.     @@L1:
  1165.   out    dx,al
  1166.  
  1167.   mov    al,[green]            ; green
  1168.   shr    al,2
  1169.   jnc    @@L2
  1170.   cmp    al,63
  1171.   je    @@L2
  1172.   inc    al
  1173.     @@L2:
  1174.   out    dx,al
  1175.  
  1176.   mov    al,[blue]            ; blue
  1177.   shr    al,2
  1178.   jnc    @@L3
  1179.   cmp    al,63
  1180.   je    @@L3
  1181.   inc    al
  1182.     @@L3:
  1183.   out    dx,al
  1184.  
  1185.   leave
  1186.   retf
  1187. ENDP
  1188.  
  1189.  
  1190. ;*****
  1191. ;***** getPaletteReg
  1192. ;*****
  1193.  
  1194. PROC    C    getPaletteReg
  1195.     ARG    palNum:WORD,red:DWORD,green:DWORD,blue:DWORD
  1196.   push    ds si
  1197.  
  1198.   mov    dx,3C7h                ; set for correct palette register
  1199.   mov    ax,[palNum]
  1200.   out    dx,al
  1201.   mov    dx,3C9h
  1202.  
  1203.   in    al,dx                ; red
  1204.   lds    si,[red]
  1205.   shl    al,2
  1206.   mov    [ds:si],al
  1207.   in    al,dx                ; green
  1208.   lds    si,[green]
  1209.   shl    al,2
  1210.   mov    [ds:si],al
  1211.   in    al,dx                ; blue
  1212.   lds    si,[blue]
  1213.   shl    al,2
  1214.   mov    [ds:si],al
  1215.  
  1216.   pop    si ds
  1217.   leave
  1218.   retf
  1219. ENDP
  1220.  
  1221.  
  1222. ;*****
  1223. ;***** setBlockPalette
  1224. ;*****
  1225.  
  1226. PROC    C    setBlockPalette
  1227.     ARG    firstReg:WORD,lastReg:WORD,paletteData:DWORD
  1228.   push    ds si
  1229.  
  1230.   lds    si,[paletteData]        ; set up
  1231.   mov    dx,3C8h
  1232.   mov    ax,[firstReg]
  1233.   out    dx,al
  1234.   inc    dx
  1235.   mov    cx,[lastReg]            ; CX = number of registers
  1236.   sub    cx,ax
  1237.   inc    cx
  1238.   cld
  1239.  
  1240.     @@LLoop:
  1241.   lodsb            ; red
  1242.   shr    al,2
  1243.   jnc    @@L1
  1244.   cmp    al,63
  1245.   je    @@L1
  1246.   inc    al
  1247.       @@L1:
  1248.   out    dx,al
  1249.  
  1250.   lodsb            ; green
  1251.   shr    al,2
  1252.   jnc    @@L2
  1253.   cmp    al,63
  1254.   je    @@L2
  1255.   inc    al
  1256.       @@L2:
  1257.   out    dx,al
  1258.  
  1259.   lodsb            ; blue
  1260.   shr    al,2
  1261.   jnc    @@L3
  1262.   cmp    al,63
  1263.   je    @@L3
  1264.   inc    al
  1265.       @@L3:
  1266.   out    dx,al
  1267.  
  1268.   loop    @@LLoop
  1269.  
  1270.     @@LExit:
  1271.   pop    si ds
  1272.   leave
  1273.   retf
  1274. ENDP
  1275.  
  1276.  
  1277. ;*****
  1278. ;***** getBlockPalette
  1279. ;*****
  1280.  
  1281. PROC    C    getBlockPalette
  1282.     ARG    firstReg:WORD,lastReg:WORD,paletteData:DWORD
  1283.   push    di
  1284.  
  1285.   les    di,[paletteData]        ; set up
  1286.   mov    dx,3C7h
  1287.   mov    ax,[firstReg]
  1288.   out    dx,al
  1289.   mov    dx,3C9h
  1290.   mov    cx,[lastReg]            ; CX = number of registers
  1291.   sub    cx,ax
  1292.   inc    cx
  1293.   cld
  1294.  
  1295.     @@L1:
  1296.   in    al,dx
  1297.   shl    al,2
  1298.   stosb            ; red
  1299.   in    al,dx
  1300.   shl    al,2
  1301.   stosb            ; green
  1302.   in    al,dx
  1303.   shl    al,2
  1304.   stosb            ; blue
  1305.   loop    @@L1
  1306.  
  1307.     @@LExit:
  1308.   pop    di
  1309.   leave
  1310.   retf
  1311. ENDP
  1312.  
  1313.  
  1314. ;*****
  1315. ;***** Bank switching routines
  1316. ;*****
  1317.  
  1318. _acumos:                ; AcuMos
  1319.   push    ax dx ax
  1320.   cli
  1321.   mov    [curBank],ax
  1322.   mov    dx,3C4h            ; sequencer index 6
  1323.   mov    ax,1206h        ; disable write protect on VGA registers
  1324.   out    dx,ax
  1325.   mov    dx,3CEh
  1326.   pop    ax
  1327.   mov    ah,al
  1328.   mov    al,9
  1329.   out    dx,ax
  1330.   sti
  1331.   pop    dx ax
  1332.   ret
  1333.  
  1334. _aheada:                ; Ahead Systems Ver A
  1335.   push    ax dx cx
  1336.   cli
  1337.   mov    [curBank],ax
  1338.   mov    ch,al
  1339.   mov    dx,3CEh            ; Enable extended registers
  1340.   mov    ax,200Fh
  1341.   out    dx,ax
  1342.   mov    dl,0CCh            ; bit 0
  1343.   in    al,dx
  1344.   mov    dl,0C2h
  1345.   and    al,11011111b
  1346.   shr    ch,1
  1347.   jnc    @@skpa
  1348.   or    al,00100000b
  1349.       @@skpa:
  1350.   out    dx,al
  1351.   mov    dl,0CFh            ; bits 1,2,3
  1352.   xor    al,al
  1353.   out    dx,al
  1354.   inc    dx
  1355.   in    al,dx
  1356.   dec    dx
  1357.   and    al,11111000b
  1358.   or    al,ch
  1359.   mov    ah,al
  1360.   xor    al,al
  1361.   out    dx,ax
  1362.   sti
  1363.   pop    cx dx ax
  1364.   ret
  1365.  
  1366. _aheadb:                ; Ahead Systems Ver B
  1367.   push    ax dx cx
  1368.   cli
  1369.   mov    [curBank],ax
  1370.   mov    ch,al
  1371.   mov    dx,3CEh            ; Enable extended registers
  1372.   mov    ax,200Fh
  1373.   out    dx,ax
  1374.   mov    ah,ch
  1375.   mov    cl,4
  1376.   shl    ah,cl
  1377.   or    ah,ch
  1378.   mov    al,0Dh
  1379.   out    dx,ax
  1380.   sti
  1381.   pop    cx dx ax
  1382.   ret
  1383.  
  1384. _ativga:                ; ATI VGA Wonder
  1385.   push    ax dx
  1386.   cli
  1387.   mov    [curBank],ax
  1388.   mov    ah,al
  1389.   mov    dx,1CEh
  1390.   mov    al,0B2h
  1391.   out    dx,al
  1392.   inc    dl
  1393.   in    al,dx
  1394.   shl    ah,1
  1395.   and    al,0E1h
  1396.   or    ah,al
  1397.   mov    al,0B2h
  1398.   dec    dl
  1399.   out    dx,ax
  1400.   sti
  1401.   pop    dx ax
  1402.   ret
  1403.  
  1404. _chipstech:                ; Chips & Tech
  1405.   push    ax dx ax
  1406.   cli
  1407.   mov    [curBank],ax
  1408.   mov    dx,46E8h        ; place chip in setup mode
  1409.   mov    ax,1Eh
  1410.   out    dx,ax
  1411.   mov    dx,103h            ; enable extended registers
  1412.   mov    ax,0080h
  1413.   out    dx,ax
  1414.   mov    dx,46E8h        ; bring chip out of setup mode
  1415.   mov    ax,0Eh
  1416.   out    dx,ax
  1417.   pop    ax
  1418.   mov    ah,al
  1419.   mov    al,10h
  1420.   mov    dx,3D6h
  1421.   out    dx,ax
  1422.   sti
  1423.   pop    dx ax
  1424.   ret
  1425.  
  1426. _cirrus:                ; Cirrus
  1427.   push    ax dx
  1428.   cli
  1429.   mov    [curBank],ax
  1430.   mov    dx,3CEh
  1431.   shl    al,4
  1432.   mov    ah,al
  1433.   mov    al,9
  1434.   out    dx,ax
  1435.   sti
  1436.   pop    dx ax
  1437.   ret
  1438.  
  1439. _compaq:                ; Compaq
  1440.   push    ax dx ax
  1441.   cli
  1442.   mov    [curBank],ax
  1443.   mov    dx,3CEh
  1444.   mov    ax,50Fh            ; unlock extended registers
  1445.   out    dx,ax
  1446.   pop    ax
  1447.   mov    ah,al
  1448.   mov    al,45h
  1449.   out    dx,ax
  1450.   sti
  1451.   pop    dx ax
  1452.   ret
  1453.  
  1454. _everex:                ; Everex
  1455.   push    ax dx cx
  1456.   cli
  1457.   mov    [curBank],ax
  1458.   mov    cl,al
  1459.   mov    dx,3C4h
  1460.   mov    al,8
  1461.   out    dx,al
  1462.   inc    dl
  1463.   in    al,dx
  1464.   dec    dl
  1465.   shl    al,1
  1466.   shr    cl,1
  1467.   rcr    al,1
  1468.   mov    ah,al
  1469.   mov    al,8
  1470.   out    dx,ax
  1471.   mov    dl,0CCh
  1472.   in    al,dx
  1473.   mov    dl,0C2h
  1474.   and    al,0DFh
  1475.   shr    cl,1
  1476.   jc    @@nob2
  1477.   or    al,20h
  1478.     @@nob2:
  1479.   out    dx,al
  1480.   sti
  1481.   pop    cx dx ax
  1482.   ret
  1483.  
  1484. _genoa:                    ; GENOA GVGA
  1485.   push    ax dx
  1486.   cli
  1487.   mov    [curBank],ax
  1488.   mov    ah,al
  1489.   shl    al,3
  1490.   or    ah,al
  1491.   mov    al,6
  1492.   or    ah,40h
  1493.   mov    dx,3C4h
  1494.   out    dx,ax
  1495.   sti
  1496.   pop    dx ax
  1497.   ret
  1498.  
  1499. _ncr:                    ; NCR 77C22E
  1500.   push    ax dx
  1501.   cli
  1502.   mov    [curBank],ax
  1503.   mov    ah,al
  1504.   mov    al,18h
  1505.   mov    dx,3C4h
  1506.   out    dx,ax
  1507.   mov    ax,19h
  1508.   out    dx,ax
  1509.   sti
  1510.   pop    dx ax
  1511.   ret
  1512.  
  1513. _oak067:                                ; Oak Technology OTI-067
  1514.   push    ax dx
  1515.   cli
  1516.   mov    [curBank],ax
  1517.   and    al,15
  1518.   mov    ah,al
  1519.   shl    al,4
  1520.   or    ah,al
  1521.   mov    al,11h
  1522.   mov    dx,3DEh
  1523.   out    dx,ax
  1524.   sti
  1525.   pop    dx ax
  1526.   ret
  1527.  
  1528. _paradise:                ; Paradise
  1529.   push    ax dx
  1530.   cli
  1531.   mov    [curBank],ax
  1532.   mov   dx,3CEh
  1533.   mov    ah,al
  1534.   shl   ah,4                    ; 64K bank number -> 4K bank number
  1535.   mov   al,09h                  ; program PR0A
  1536.   out    dx,ax
  1537. ;  mov   al,0Ah                  ; program PR0B
  1538. ;  out   dx,ax
  1539.   sti
  1540.   pop    dx ax
  1541.   ret
  1542.  
  1543. _trident:                ; Trident
  1544.   push    ax dx ax
  1545.   cli
  1546.   mov    [curBank],ax
  1547.   mov    dx,3CEh            ; set pagesize to 64k
  1548.   mov    al,6
  1549.   out    dx,al
  1550.   inc    dl
  1551.   in    al,dx
  1552.   dec    dl
  1553.   or    al,4
  1554.   mov    ah,al
  1555.   mov    al,6
  1556.   out    dx,ax
  1557.  
  1558.   mov    dl,0C4h            ; switch to BPS mode
  1559.   mov    al,0Bh
  1560.   out    dx,al
  1561.   inc    dl
  1562.   in    al,dx
  1563.   dec    dl
  1564.  
  1565.   pop    ax
  1566.   mov    ah,al
  1567.   xor    ah,2
  1568.   mov    dx,3C4h
  1569.   mov    al,0Eh
  1570.   out    dx,ax
  1571.   sti
  1572.   pop    dx ax
  1573.   ret
  1574.  
  1575. _tseng:                    ; Tseng
  1576.   push    ax dx
  1577.   cli
  1578.   mov    [curBank],ax
  1579.   and    al,7
  1580.   mov    ah,al
  1581.   shl    al,3
  1582.   or    al,ah
  1583.   or    al,01000000b
  1584.   mov    dx,3CDh
  1585.   out    dx,al
  1586.   sti
  1587.   pop    dx ax
  1588.   ret
  1589.  
  1590. _tseng4:                ; Tseng 4000 series
  1591. ;  push  ax dx
  1592. ;  cli
  1593. ;  mov   [curBank],ax
  1594. ;  mov   ah,al
  1595. ;  mov   dx,3BFh                 ; enable access to extended registers
  1596. ;  mov   al,3
  1597. ;  out   dx,al
  1598. ;  mov   dl,0D8h
  1599. ;  mov   al,0A0h
  1600. ;  out   dx,al
  1601. ;  and   ah,15
  1602. ;  mov   al,ah
  1603. ;  shl   al,4
  1604. ;  or    al,ah
  1605. ;  mov   dl,0CDh
  1606. ;  out   dx,al
  1607. ;  sti
  1608. ;  pop   dx ax
  1609. ;  ret
  1610.   push  ax dx
  1611.   cli
  1612.   mov   [curBank],ax
  1613.   and   al,0Fh
  1614.   mov   ah,al
  1615.   shl   ah,4
  1616.   or    al,ah
  1617.   mov   dx,3CDh
  1618.   out   dx,al
  1619.   sti
  1620.   pop   dx ax
  1621.   ret
  1622.  
  1623. _video7:                ; Video 7
  1624.   push    ax dx cx
  1625.   cli
  1626.   mov    [curBank],ax
  1627.   and    ax,15
  1628.   mov    ch,al
  1629.   mov    dx,3C4h
  1630.   mov    ax,0EA06h
  1631.   out    dx,ax
  1632.   mov    ah,ch
  1633.   and    ah,1
  1634.   mov    al,0F9h
  1635.   out    dx,ax
  1636.   mov    al,ch
  1637.   and    al,1100b
  1638.   mov    ah,al
  1639.   shr    ah,2
  1640.   or    ah,al
  1641.   mov    al,0F6h
  1642.   out    dx,al
  1643.   inc    dx
  1644.   in    al,dx
  1645.   dec    dx
  1646.   and    al,NOT 1111b
  1647.   or    ah,al
  1648.   mov    al,0F6h
  1649.   out    dx,ax
  1650.   mov    ah,ch
  1651.   mov    cl,4
  1652.   shl    ah,cl
  1653.   and    ah,100000b
  1654.   mov    dl,0CCh
  1655.   in    al,dx
  1656.   mov    dl,0C2h
  1657.   and    al,NOT 100000b
  1658.   or    al,ah
  1659.   out    dx,al
  1660.   sti
  1661.   pop    cx dx ax
  1662.   ret
  1663.  
  1664. _vesa:                ; VESA SVGA interface
  1665.   push    ax bx dx
  1666.   cli
  1667.   mov    [curBank],ax
  1668.   mov    dx,ax
  1669.   xor    bx,bx
  1670.   mov    ax,4F05h
  1671.   int    10h
  1672.   sti
  1673.   pop    dx bx ax
  1674.   ret
  1675.  
  1676. _nobank:
  1677.   cli
  1678.   mov    [curBank],ax
  1679.   sti
  1680.   ret
  1681.  
  1682.  
  1683. MACRO    BKADR    func
  1684.   mov    [func],1
  1685.   mov    [bankadr],OFFSET _&func
  1686. ENDM
  1687.  
  1688. MACRO    NOJMP
  1689.   local    lbl
  1690.   jmp    short    lbl
  1691.     lbl:
  1692. ENDM
  1693.  
  1694.  
  1695. PROC    whichVGA    NEAR
  1696.   push    si di
  1697.  
  1698.   cmp    [inited],1
  1699.   jne    @@goTest
  1700.   mov    ax,[retval]
  1701.   pop    di si
  1702.   ret
  1703.  
  1704.     @@goTest:
  1705.   mov    [bankadr],OFFSET _nobank         ; Initialize variables
  1706.   mov    [vgamem],256
  1707.   mov    [bksize],64
  1708.   xor    ax,ax
  1709.   mov    [curBank],ax
  1710.   mov    [acumos],ax
  1711.   mov    [aheada],ax
  1712.   mov    [aheadb],ax
  1713.   mov    [ativga],ax
  1714.   mov    [chipstech],ax
  1715.   mov    [cirrus],ax
  1716.   mov    [compaq],ax
  1717.   mov    [everex],ax
  1718.   mov    [genoa],ax
  1719.   mov    [ncr],ax
  1720.   mov    [oak067],ax
  1721.   mov    [paradise],ax
  1722.   mov    [trident],ax
  1723.   mov    [t8900],ax
  1724.   mov    [tseng],ax
  1725.   mov    [tseng4],ax
  1726.   mov    [video7],ax
  1727.   mov    [vesa],ax
  1728.  
  1729.   mov    si,1                ; success code; changed on error
  1730.  
  1731.   mov    ax,cs                ; Test for VESA
  1732.   mov    es,ax
  1733.   mov    di,OFFSET vesabuf
  1734.   mov    ax,4F00h
  1735.   int    10h
  1736.   cmp    ax,004Fh
  1737.   jne    @@noVESA
  1738.   BKADR    vesa
  1739.   mov    [bksize],64            ; assume 64 K bank size (for now)
  1740.   mov    [vgamem],512            ; assume 512 K if VESA
  1741.   jmp    @@fini
  1742.  
  1743.     @@noVESA:
  1744.   mov    ax,0C000h            ; Test for ATI
  1745.   mov    es,ax
  1746.   cmp    [word ptr es:40h],'13'    ; ATI Signiture on the Video BIOS
  1747.   jnz    @@noATI
  1748.   BKADR    ativga
  1749.   mov    [bksize],64        ; 64K bank size
  1750.   mov    dx,[es:10h]        ; get value of ATI extended register
  1751.   mov    bl,[es:43h]        ; get value of ATI chip version
  1752.   cmp    bl,'3'
  1753.   jae    @@v6up            ; use different method to find memory size
  1754.   mov    al,0BBh
  1755.   cli
  1756.   out    dx,al
  1757.   inc    dx
  1758.   in    al,dx
  1759.   sti
  1760.   test    al,20h
  1761.   jz    @@no512
  1762.   mov    [vgamem],512
  1763.   jmp    short    @@no512
  1764.     @@v6up:
  1765.   mov    al,0B0h            ; method for newer ATIs
  1766.   cli
  1767.   out    dx,al
  1768.   inc    dx
  1769.   in    al,dx            ; get RAM size for versions 3-5
  1770.   sti
  1771.   test    al,10h            ; check if 256 K or 512 K
  1772.   jz    @@v7up
  1773.   mov    [vgamem],512
  1774.       @@v7up:
  1775.   cmp    bl,'4'            ; get RAM size for versions 4 & 5
  1776.   jb    @@no512
  1777.   test    al,8            ; check if version 5 chip has 1024 K
  1778.   jz    @@no512
  1779.   mov    [vgamem],1024
  1780.       @@no512:
  1781.   jmp    @@fini
  1782.  
  1783.     @@noATI:
  1784.   mov    ax,7000h            ; Test for Everex
  1785.   xor    bx,bx
  1786.   cld
  1787.   int    10h
  1788.   cmp    al,70h
  1789.   jnz    @@noEverex
  1790.   BKADR    everex
  1791.   mov    [bksize],64        ; 64 K bank size
  1792.   and    ch,11000000b        ; how much memory on board?
  1793.   jz    @@skp
  1794.   mov    [vgamem],512
  1795.      @@skp:            ; fall through for Everex boards using Trident or Tseng4000
  1796.  
  1797.     @@noEverex:
  1798.   mov    ax,0BF03h            ; Test for Compaq
  1799.   xor    bx,bx
  1800.   mov    cx,bx
  1801.   int    10h
  1802.   cmp    ax,0BF03h
  1803.   jnz    @@noCompaq
  1804.   test    cl,40h            ; is 640x480x256 available?
  1805.   jz    @@noCompaq
  1806.   BKADR    compaq
  1807.   mov    [bksize],4              ; 4 K bank size
  1808.   mov    [vgamem],512
  1809.   jmp    @@fini
  1810.  
  1811.     @@noCompaq:
  1812.   mov    dx,3C4h                ; Test for NCR 77C22E
  1813.   mov    ax,0FF05h
  1814.   call    _isport2
  1815.   jnz    @@noNCR
  1816.   mov    ax,5                   ; Disable extended registers
  1817.   out    dx,ax
  1818.   mov    ax,0FF10h        ; Try to write to extended register 10
  1819.   call    _isport2        ; If it writes then not NCR
  1820.   jz    @@noNCR
  1821.   mov    ax,105h            ; Enable extended registers
  1822.   out    dx,ax
  1823.   mov    ax,0FF10h
  1824.   call    _isport2
  1825.   jnz    @@noNCR            ; If it does NOT write then not NCR
  1826.   BKADR    ncr
  1827.   mov    [bksize],16        ; 16 K bank size
  1828.   mov    [vgamem],512
  1829.   jmp    @@fini
  1830.  
  1831.     @@noNCR:
  1832.   mov    dx,3C4h                ; Test for Trident
  1833.   mov    al,0Eh            ; Read mode control register #1
  1834.   out    dx,al
  1835.   inc    dx
  1836.   in    al,dx            ; Read old value
  1837.   xor    al,2
  1838.   push    ax
  1839.   xor    al,al            ; Write new value bit 1=0, all other bits=0
  1840.   out    dx,al
  1841.   in    al,dx            ; Read new value
  1842.   and    al,0Fh
  1843.   cmp    al,2            ; Check for Trident
  1844.   pop    ax            ; Old value in AX
  1845.   out    dx,al            ; Restore old value
  1846.   jne    @@noTrident
  1847.  
  1848.   BKADR    trident            ; Trident found
  1849.   mov    [bksize],64
  1850.  
  1851.   dec    dx            ; Distinguish 8800/8900
  1852.   mov    al,0Bh            ; Index of version register
  1853.   out    dx,al            ; Select version register
  1854.   inc    dx
  1855.   xor    al,al
  1856.   out    dx,al            ; Dummy write to force old definitions
  1857.   in    al,dx            ; Read causes new definitions
  1858.   cmp    al,3            ; Is it 8900+?
  1859.   jb    @@Trident8800        ; no, 8800
  1860.   mov    [t8900],1        ; yes
  1861.   mov    dx,3D5h
  1862.   mov    al,1Fh
  1863.   out    dx,al
  1864.   inc    dx
  1865.   in    al,dx
  1866.   and    al,3
  1867.   cmp    al,1
  1868.   jb    @@noTmem
  1869.   mov    [vgamem],512
  1870.   je    @@noTmem
  1871.   mov    [vgamem],1024
  1872.     @@noTmem:
  1873.   jmp    @@fini
  1874.         @@Trident8800:
  1875.   mov    [vgamem],512
  1876.   jmp    @@fini
  1877.  
  1878.         @@noTrident:
  1879.   mov    ax,6F00h            ; Test for Video 7
  1880.   xor    bx,bx
  1881.   cld
  1882.   int    10h
  1883.   cmp    bx,'V7'
  1884.   jnz    @@noVideo7
  1885.   BKADR    video7
  1886.   mov    [bksize],64        ; 64 K bank size
  1887.   mov    ax,6F07h
  1888.   cld
  1889.   int    10h
  1890.   and    ah,7Fh
  1891.   cmp    ah,1
  1892.   jbe    @@skp2
  1893.   mov    [vgamem],512
  1894.     @@skp2:
  1895.   cmp    ah,3
  1896.   jbe    @@skp3
  1897.   mov    [vgamem],1024
  1898.     @@skp3:
  1899.   jmp    @@fini
  1900.  
  1901.     @@noVideo7:
  1902.   mov    dx,3D4h                ; Test for GENOA GVGA
  1903.   mov    ax,032Eh        ; check for Herchi Register
  1904.   call    _isport2
  1905.   jnz    @@noGenoa
  1906.   mov    dx,3C4h            ; check for memory segment register
  1907.   mov    ax,3F06h
  1908.   call    _isport2
  1909.   jnz    @@noGenoa
  1910.   BKADR    genoa
  1911.   mov    [bksize],64        ; 64 K bank size
  1912.   mov    [vgamem],512
  1913.   jmp    @@fini
  1914.  
  1915.     @@noGenoa:
  1916.   mov    ax,0C000h            ; Test for Cirrus
  1917.   mov    es,ax
  1918.   mov    bx,0006h
  1919.   mov    ax,[es:bx]
  1920.   cmp    ax,4C43h             ; is 'CL' ID string at C000:0006?
  1921.   jne    @@noCirrus        ; no, not a Cirrus card
  1922.  
  1923.   ; Cirrus found -- Enable extended registers
  1924.   mov    ax,1206h
  1925.   mov    dx,3C4h
  1926.   out    dx,ax
  1927.   ; Get memory size
  1928.   mov    dx,3C4h
  1929.   mov    al,0Fh
  1930.   out    dx,al
  1931.   inc    dx
  1932.   in    al,dx
  1933.   shr    al,3
  1934.   and    al,3
  1935.   cmp    al,1
  1936.   jb    @@noCirrus        ; only 256 kb
  1937.   mov    [vgamem],512
  1938.   cmp    al,2
  1939.   jb    @@CirrusSetup        ; 512 kb
  1940.   mov    [vgamem],1024        ; 1 Mb
  1941.     @@CirrusSetup:
  1942.   ; Set up for Cirrus card
  1943.   BKADR    cirrus
  1944.   mov    [bksize],64
  1945.   jmp    @@fini
  1946.  
  1947.     @@noCirrus:
  1948.   mov   ax,0C000h                       ; Test for Paradise
  1949.   mov   es,ax
  1950.   mov   bx,007Dh
  1951.   mov   eax,[es:bx]
  1952.   cmp   eax,3D414756h           ; is 'VGA=' ID string at C000:007D?
  1953.   jne   @@noParadise            ; no, not a Paradise card
  1954.   BKADR paradise                ; yes, set up for Paradise card
  1955.   mov   [bksize],64
  1956.  
  1957.   ; Disable write-protect of VGA registers
  1958.   mov    ax,050Fh
  1959.   mov    dx,3CEh
  1960.   out    dx,ax
  1961.   ; Unlock extended sequencer registers
  1962.   mov    ax,4806h
  1963.   mov    dx,3C4h
  1964.   out    dx,ax
  1965.   ; Enable access to PR10-17
  1966.   mov    ax,8529h
  1967.   mov    dx,3D4h
  1968.   out    dx,ax
  1969.   ; Allow access to all SVGA memory
  1970.   mov   dx,3D4h
  1971.   mov    al,2Fh
  1972.   out    dx,al
  1973.   inc    dx
  1974.   in    al,dx
  1975.   and    al,NOT 2
  1976.   out    dx,al
  1977.   ; Detect memory size
  1978.   mov  dx,3CEh
  1979.   mov  al,0Bh
  1980.   out  dx,al
  1981.   inc  dx
  1982.   in   al,dx
  1983.   test al,80h                  ; if top bit set then 512k
  1984.   jz   @@nop512
  1985.   mov  [vgamem],512
  1986.        @@nop512:
  1987.   jmp  @@fini
  1988.  
  1989.     @@noParadise:
  1990.   mov    ax,5F00h            ; Test for Chips & Tech
  1991.   xor    bx,bx
  1992.   cld
  1993.   int    10h
  1994.   cmp    al,5Fh
  1995.   jnz    @@noChipsTech
  1996.   BKADR    chipstech
  1997.   mov    [bksize],16        ; 16 K bank size
  1998.   cmp    bh,1
  1999.   jb    @@skp4
  2000.   mov    [vgamem],512
  2001.   cmp    bh,2
  2002.   jb    @@skp4
  2003.   mov    [vgamem],1024
  2004.     @@skp4:
  2005.   jmp    @@fini
  2006.  
  2007.     @@noChipsTech:
  2008.   xor    ch,ch                ; check for Tseng 4000 series
  2009.   mov    dx,3D4h
  2010.   mov    ax,0F33h
  2011.   call    _isport2
  2012.   jnz    @@noTseng4
  2013.   mov    ch,1
  2014.  
  2015.   mov    dx,3BFh            ; Enable access to extended registers
  2016.   mov    al,3
  2017.   out    dx,al
  2018.   mov    dx,3D8h
  2019.   mov    al,0A0h
  2020.   out    dx,al
  2021.   jmp    short @@yes4
  2022.  
  2023.     @@noTseng4:
  2024.   mov    dx,3D4h                ; Test for Tseng 3000 or 4000
  2025.   mov    ax,1F25h        ; is the Overflow High register there?
  2026.   call    _isport2
  2027.   jnz    @@noTseng
  2028.   mov    al,03Fh            ; bottom six bits only
  2029.   jmp    short @@yes3
  2030.     @@yes4:
  2031.   mov    al,0FFh
  2032.     @@yes3:
  2033.   mov    dx,3CDh            ; test bank switch register
  2034.   call    _isport1
  2035.   jnz    @@noTseng
  2036.   BKADR    tseng
  2037.   mov    [bksize],64        ; 64 K bank size
  2038.   or    ch,ch
  2039.   jnz    @@t4mem
  2040.   mov    [vgamem],512
  2041.   jmp    @@fini
  2042.  
  2043.     @@t4mem:
  2044.   mov    dx,3D4h            ; Tseng 4000 memory detect 1meg
  2045.   mov    al,37h
  2046.   out    dx,al
  2047.   inc    dx
  2048.   in    al,dx
  2049.   test    al,1000b        ; if using 64kx4 RAMs then no more than 256k
  2050.   jz    @@nomem
  2051.   and    al,3
  2052.   cmp    al,1            ; if 8 bit wide bus then only two 256kx4 RAMs
  2053.   jbe    @@nomem
  2054.   mov    [vgamem],512
  2055.   cmp    al,2            ; if 16 bit wide bus then four 256kx4 RAMs
  2056.   je    @@nomem
  2057.   mov    [vgamem],1024        ; full meg with eight 256kx4 RAMs
  2058.     @@nomem:
  2059.   ; Special setup for ET4000
  2060.   mov   dx,3BFh
  2061.   mov   al,3
  2062.   out   dx,al
  2063.   mov   dl,0D8h
  2064.   mov   al,0A0h
  2065.   out   dx,al
  2066.   BKADR tseng4
  2067.  
  2068.   jmp    @@fini
  2069.  
  2070.     @@noTseng:
  2071.   mov    dx,3CEh                ; Test for Above A or B chipsets
  2072.   mov    ax,200Fh
  2073.   out    dx,ax
  2074.   inc    dx
  2075.   NOJMP
  2076.   in    al,dx
  2077.   cmp    al,21h
  2078.   jz    @@verB
  2079.   cmp    al,20h
  2080.   jnz    @@noAbove
  2081.   BKADR    aheada
  2082.   mov    [bksize],64        ; 64 K bank size
  2083.   mov    [vgamem],512
  2084.   jmp    @@fini
  2085.     @@verB:
  2086.   BKADR    aheadb
  2087.   mov    [bksize],64        ; 64 K bank size
  2088.   mov    [vgamem],512
  2089.   jmp   @@fini
  2090.  
  2091.     @@noAbove:
  2092.   mov    dx,3C4h                ; Test for AcuMos chipsets
  2093.   mov    ax,0006h
  2094.   out    dx,ax
  2095.   mov    ax,0FF09h
  2096.   call    _isport2           ; is scratchpad at index 9 writeable?
  2097.   jz    @@noAcumos
  2098.   mov    ax,0FF0Ah
  2099.   call    _isport2        ; is scratchpad at index 10 writeable?
  2100.   jz    @@noAcumos
  2101.   mov    ax,1206h
  2102.   out    dx,ax
  2103.   mov    ax,0FF09h
  2104.   call    _isport2
  2105.   jnz    @@noAcumos
  2106.   mov    ax,0FF0Ah
  2107.   call    _isport2
  2108.   jnz    @@noAcumos
  2109.   mov    dx,OFFSET _acumos
  2110.   mov    cx,1
  2111.   call    _chkbk
  2112.   jc    @@noAcumos
  2113.   BKADR    acumos
  2114.   mov    [bksize],4        ; 4 K bank size
  2115.   mov    dx,3C4h
  2116.   mov    al,0Ah
  2117.   out    dx,al
  2118.   inc     dx
  2119.   in    al,dx
  2120.   and    al,3
  2121.   cmp    al,1
  2122.   jb    @@noAcumosMem
  2123.   mov    [vgamem],512
  2124.   cmp    al,2
  2125.   jb    @@noAcumosMem
  2126.   mov    [vgamem],1024
  2127.   cmp    al,3
  2128.   jb    @@noAcumosMem
  2129.   mov    [vgamem],2048
  2130.       @@noAcumosMem:
  2131.   jmp    short    @@fini
  2132.  
  2133.     @@noAcumos:
  2134.   mov    dx,3DEh                ; Test for Oak Technology
  2135.   mov    ax,0FF11h        ; look for bank switch register
  2136.   call    _isport2
  2137.   jnz    @@fini
  2138.   BKADR    oak067
  2139.   mov    [bksize],64        ; 64 K bank size
  2140.   mov    al,0Dh
  2141.   out    dx,al
  2142.   inc    dx
  2143.   NOJMP
  2144.   in    al,dx
  2145.   test    al,11000000b
  2146.   jz    @@fini
  2147.   mov    [vgamem],512
  2148.   test    al,01000000b
  2149.   jz    @@fini
  2150.   mov    [vgamem],1024
  2151.   jmp    short    @@fini
  2152.  
  2153.       @@noSVGA:
  2154.   xor    si,si                ; set error flag
  2155.  
  2156.     @@fini:
  2157.   mov    ax,si                ; success code in AX for return
  2158.   mov    [retval],ax
  2159.   pop    di si
  2160.   ret
  2161. ENDP
  2162.  
  2163.  
  2164. PROC    _chkbk    NEAR            ; bank switch check routine
  2165.   mov    di,0B800h
  2166.   mov    es,di
  2167.   xor    di,di
  2168.   mov    bx,1234h
  2169.   call    _gochk
  2170.   jnz    @@badchk
  2171.   mov    bx,4321h
  2172.   call    _gochk
  2173.   jnz    @@badchk
  2174.   clc
  2175.   ret
  2176.     @@badchk:
  2177.   stc
  2178.   ret
  2179. ENDP
  2180.  
  2181.  
  2182. PROC    _gochk    NEAR
  2183.   push    si
  2184.   mov    si,bx
  2185.  
  2186.   mov    al,cl
  2187.   call    dx
  2188.   xchg    bl,[es:di]
  2189.   mov    al,ch
  2190.   call    dx
  2191.   xchg    bh,[es:di]
  2192.  
  2193.   xchg    si,bx
  2194.  
  2195.   mov    al,cl
  2196.   call    dx
  2197.   xor    bl,[es:di]
  2198.   mov    al,ch
  2199.   call    dx
  2200.   xor    bh,[es:di]
  2201.  
  2202.   xchg    si,bx
  2203.  
  2204.   mov    al,ch
  2205.   call    dx
  2206.   mov    [es:di],bh
  2207.   mov    al,cl
  2208.   call    dx
  2209.   mov    [es:di],bl
  2210.  
  2211.   xor    al,al
  2212.   call    dx
  2213.   or    si,si
  2214.   pop    si
  2215.   ret
  2216. ENDP
  2217.  
  2218.  
  2219. PROC    _isport2    NEAR        ; check for valid I/O port
  2220.                     ; AL is index, AH is bit mask
  2221.   push    bx
  2222.   mov    bx,ax
  2223.   out    dx,al
  2224.   mov    ah,al
  2225.   inc    dx
  2226.   in    al,dx
  2227.   dec    dx
  2228.   xchg    al,ah
  2229.   push    ax
  2230.   mov    ax,bx
  2231.   out    dx,ax
  2232.   out    dx,al
  2233.   mov    ah,al
  2234.   inc    dx
  2235.   in    al,dx
  2236.   dec    dx
  2237.   and    al,bh
  2238.   cmp    al,bh
  2239.   jnz    @@noport
  2240.   mov    al,ah
  2241.   xor    ah,ah
  2242.   out    dx,ax
  2243.   out    dx,al
  2244.   mov    ah,al
  2245.   inc    dx
  2246.   in    al,dx
  2247.   dec    dx
  2248.   and    al,bh
  2249.   cmp    al,0
  2250.     @@noport:
  2251.   pop    ax
  2252.   out    dx,ax
  2253.   pop    bx
  2254.   ret
  2255. ENDP
  2256.  
  2257.  
  2258. PROC    _isport1    NEAR        ; check for valid I/O port
  2259.                     ; AL is bit mask
  2260.   mov    ah,al
  2261.   in    al,dx
  2262.   push    ax
  2263.   mov    al,ah
  2264.   out    dx,al
  2265.   in    al,dx
  2266.   and    al,ah
  2267.   cmp    al,ah
  2268.   jnz    @@noport
  2269.   xor    al,al
  2270.   out    dx,al
  2271.   in    al,dx
  2272.   and    al,ah
  2273.   cmp    al,0
  2274.     @@noport:
  2275.   pop    ax
  2276.   out    dx,al
  2277.   ret
  2278. ENDP
  2279.  
  2280.  
  2281. PROC    setMode    NEAR            ; Set 640x480x256
  2282.   cmp    [vesa],0
  2283.   jz    @@noVESA
  2284.   mov    bx,101h
  2285.   call    VESAset
  2286.   or    ax,ax                ; was function successful?
  2287. JUMPS
  2288.   jz    @@noSVGA            ; no, quit
  2289. NOJUMPS
  2290.   jmp    @@godo2
  2291.       @@noVESA:
  2292.   cmp    [compaq],0
  2293.   jz    @@noCompaq
  2294.   mov    [scanline],1024
  2295.   mov    ax,2Eh
  2296.   jmp    @@godo
  2297.     @@noCompaq:
  2298.   cmp    [genoa],0
  2299.   jz    @@noGenoa
  2300.   mov    ax,5Ch
  2301.   jmp    @@godo
  2302.     @@noGenoa:
  2303.   cmp    [ncr],0
  2304.   jz    @@noNCR
  2305.   mov    ax,5Fh
  2306.   jmp    @@godo
  2307.     @@noNCR:
  2308.   cmp    [oak067],0
  2309.   jz    @@noOak067
  2310.   mov    ax,53h
  2311.   jmp    @@godo
  2312.     @@noOak067:
  2313.   cmp    [aheada],0
  2314.   jnz    @@
  2315.   cmp    [aheadb],0
  2316.   jz    @@noAbove
  2317.     @@:
  2318.   mov    ax,61h
  2319.   jmp    @@godo
  2320.     @@noAbove:
  2321.   cmp    [everex],0
  2322.   jz    @@noEverex
  2323.   mov    ax,70h
  2324.   mov    bl,30h
  2325.   jmp    short @@godo
  2326.     @@noEverex:
  2327.   cmp    [ativga],0
  2328.   jz    @@noATI
  2329.   mov    ax,62h
  2330.   jmp    short @@godo
  2331.     @@noATI:
  2332.   cmp    [trident],0
  2333.   jz    @@noTrident
  2334.   mov    ax,5Dh
  2335.   jmp    short @@godo
  2336.     @@noTrident:
  2337.   cmp    [video7],0
  2338.   jz    @@noVideo7
  2339.   mov    ax,6F05h
  2340.   mov    bl,67h
  2341.   jmp    short @@godo
  2342.     @@noVideo7:
  2343.   cmp    [chipstech],0
  2344.   jz    @@noChipsTech
  2345.   mov    ax,79h
  2346.   jmp    short @@godo
  2347.     @@noChipsTech:
  2348.   cmp    [cirrus],0
  2349.   jz    @@noCirrus
  2350.   mov    ax,5Fh
  2351.   jmp    short    @@godo
  2352.       @@noCirrus:
  2353.   cmp    [acumos],0
  2354.   jnz    @@doParadise
  2355.   cmp    [paradise],0
  2356.   jz    @@noParadise
  2357.       @@doParadise:
  2358.   mov    ax,5Fh
  2359.   jmp    short    @@godo
  2360.     @@noParadise:
  2361.   cmp    [tseng],0
  2362.   jz    @@noSVGA
  2363.   mov    ax,2Eh
  2364.  
  2365.     @@godo:
  2366.   int    10h
  2367.       @@godo2:
  2368.   mov    [curBank],-1
  2369.   mov    ax,1                    ; return success code
  2370.   ret
  2371.  
  2372.     @@noSVGA:
  2373.   xor    ax,ax                ; return error code
  2374.   ret
  2375. ENDP
  2376.  
  2377.  
  2378. PROC    VESAset        NEAR
  2379.   push    di
  2380.  
  2381.   push    bx
  2382.   mov    ax,4F02h
  2383.   int    10h                   ; set the mode
  2384.   pop    cx
  2385.   or    ah,ah                ; was function successful?
  2386.   jz    @@noError            ; yes
  2387.   xor    ax,ax                ; set error code (for setMode)
  2388.   jmp    short    @@Exit
  2389.  
  2390.       @@noError:
  2391.   mov    ax,cs
  2392.   mov    es,ax
  2393.   mov    di,OFFSET modebuf
  2394.   mov    ax,4F01h
  2395.   int    10h                ; get the mode information
  2396.   mov    ax,[modebuf.WinSize]
  2397.   mov    [bksize],ax
  2398.   mov    ax,[modebuf.BytesPerLine]
  2399.   mov    [scanline],ax
  2400.   mov    ax,1                ; set success code (for setMode)
  2401.  
  2402.       @@Exit:
  2403.   pop    di
  2404.   ret
  2405. ENDP
  2406.  
  2407.  
  2408. PROC    makeAddrTable    NEAR
  2409.   LOCAL    temp:WORD
  2410.   push    si di
  2411.  
  2412.   mov    si,OFFSET lineOffs
  2413.   mov    di,OFFSET bankNum
  2414.   xor    bx,bx                ; current line number = 0
  2415.  
  2416.   mov    ax,[bksize]            ; separate process if bksize=64 K
  2417.   cmp    ax,64
  2418.   je    @@64kBnk
  2419.  
  2420.   mov    cl,10
  2421.   shl    ax,cl                ; AX = bank size in bytes
  2422.   dec    ax
  2423.   mov    [temp],ax            ; [temp] = banksize in bytes - 1
  2424.   mov    ax,[bksize]            ; AX = bank size in K
  2425.     @@shlp:
  2426.   inc    cl
  2427.   shr    ax,1
  2428.   jnz    @@shlp                ; loop until AX = 0
  2429.   dec    cx
  2430.  
  2431.   xor    ax,ax                ; AX = 0
  2432.   xor    dx,dx                ; DX = 0
  2433.     @@lp:
  2434.   push    ax                ; store AX
  2435.   shr    ax,cl
  2436.   add    dx,ax                ; update current bank number
  2437.   pop    ax                ; restore AX
  2438.   and    ax,[temp]            ; mask offset so it's < bank size
  2439.   mov    [cs:si],ax            ; save line offset
  2440.   add    si,2                ; update pointer
  2441.   mov    [cs:di],dx            ; save bank number
  2442.   add    di,2                ; update pointer
  2443.   add    ax,[scanline]            ; update offset
  2444.   inc    bx                ; update line number
  2445.   cmp    bx,SCREEN_DEEP
  2446.   jb    @@lp                ; loop until all lines done
  2447.   jmp    short    @@calcBankChange    ; calculate bank change table
  2448.  
  2449.     @@64kBnk:
  2450.   xor    ax,ax                ; AX = 0
  2451.   xor    dx,dx                ; DX = 0
  2452.   mov    cx,[scanline]            ; CX = width of line in bytes
  2453.       @@nlp:
  2454.   mov    [cs:si],ax            ; store line offset
  2455.   add    si,2                ; update pointer
  2456.   mov    [cs:di],dx            ; store bank number
  2457.   add    di,2                ; update pointer
  2458.   add    ax,cx                ; add another line width
  2459.   adc    dx,0                ; increase bank number if overflow
  2460.   inc    bx                ; update current line number
  2461.   cmp    bx,SCREEN_DEEP
  2462.   jb    @@nlp                ; jump until all lines done
  2463.  
  2464.       @@calcBankChange:
  2465.   mov    di,OFFSET bankChanges        ; initialize pointer
  2466.   xor    ax,ax                ; AX = current line
  2467.       @@bankChangeLoop:
  2468.   mov    bx,ax                ; BX = current line
  2469.   shl    bx,1                ; to access a table of words
  2470.   mov    dx,[cs:bankNum+bx]        ; DX = bank at start of current line
  2471.   mov    bx,ax                ; BX = current line
  2472.   inc    bx                ; BX = next line
  2473.   shl    bx,1                ; to access a table of words
  2474.   mov    cx,[cs:bankNum+bx]        ; CX = bank at start of next line
  2475.   mov    si,[cs:lineOffs+bx]        ; SI = offset at start of next line
  2476.   or    si,si                ; is SI=0?
  2477.   jz    @@L1                ; yes, jump
  2478.   dec    cx                ; CX = bank at end of current line
  2479.       @@L1:
  2480.   cmp    cx,dx                ; are start and end banks the same?
  2481.   jne    @@newBank            ; bank changed, jump
  2482.   mov    [word ptr cs:di],1        ; store bank changed flag
  2483.   jmp    short    @@L2            ; jump
  2484.       @@newBank:
  2485.   mov    [word ptr cs:di],0        ; store bank same flag
  2486.       @@L2:
  2487.   add    di,2                ; update pointer
  2488.   inc    ax                ; update current line number
  2489.   cmp    ax,SCREEN_DEEP
  2490.   jb    @@bankChangeLoop        ; loop until all lines done
  2491.  
  2492.   pop    di si
  2493.   ret
  2494. ENDP
  2495.  
  2496.  
  2497.     ENDS
  2498.  
  2499. END
  2500.