home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 21 / CD_ASCQ_21_040595.iso / dos / prg / c / xlib612 / source / xmain.asm < prev    next >
Assembly Source File  |  1994-12-02  |  47KB  |  1,543 lines

  1. ;-----------------------------------------------------------------------
  2. ; MODULE XMAIN
  3. ;
  4. ; Initialization, panning and split screen functions for all MODE X 256
  5. ; Color resolutions
  6. ;
  7. ; Compile with Tasm.
  8. ; C callable.
  9. ;
  10. ;
  11. ; ****** XLIB - Mode X graphics library                ****************
  12. ; ******                                               ****************
  13. ; ****** Written By Themie Gouthas                     ****************
  14. ;
  15. ; egg@dstos3.dsto.gov.au
  16. ; teg@bart.dsto.gov.au
  17. ;
  18. ; MODIFICATIONS:
  19. ;  26-9-92:          Pel panning code added
  20. ;  Dates forgotten:  Numerous ;^)
  21. ;  05-10-93:         Timer synchronized vsync handling extensions
  22. ;                      and tripple buffering - Tore Jahn Bastiansen
  23. ;                      (toreba@ifi.uio.no) for the
  24. ;-----------------------------------------------------------------------
  25.  
  26.  
  27. include xlib.inc
  28. include xmain.inc
  29.  
  30.  
  31.     .data
  32.  
  33.  
  34. ; Mode X CRTC register tweaks for various resolutions
  35.  
  36.  
  37. LABEL X256Y200 word
  38.         db      0e3h    ; dot clock
  39.         db      8       ; Number of CRTC Registers to update
  40.     dw      05f00h  ; horz total
  41.     dw      03f01h  ; horz displayed
  42.     dw      04202h  ; start horz blanking
  43.     dw      09f03h  ; end horz blanking
  44.     dw      04c04h  ; start h sync
  45.     dw      00005h  ; end h sync
  46.     dw      00014h  ; turn off dword mode
  47.     dw      0e317h  ; turn on byte mode
  48.     dw      256
  49.     dw      200
  50.  
  51.  
  52. LABEL X256Y240 word
  53.     db      0e3h    ; dot clock
  54.     db      16      ; Number of CRTC Registers to update
  55.     dw      05f00h  ; horz total
  56.     dw      03f01h  ; horz displayed
  57.     dw      04202h  ; start horz blanking
  58.     dw      09f03h  ; end horz blanking
  59.     dw      04c04h  ; start h sync
  60.     dw      00005h  ; end h sync
  61.     dw      00d06h  ; vertical total
  62.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  63.     dw      04109h  ; cell height (2 to double-scan)
  64.     dw      0ea10h  ; v sync start
  65.     dw      0ac11h  ; v sync end and protect cr0-cr7
  66.     dw      0df12h  ; vertical displayed
  67.     dw      00014h  ; turn off dword mode
  68.     dw      0e715h  ; v blank start
  69.     dw      00616h  ; v blank end
  70.     dw      0e317h  ; turn on byte mode
  71.     dw      256
  72.         dw      240
  73.  
  74.  
  75. X320Y200 label  word
  76.     db      00      ; 0e3h    ; dot clock
  77.     db      02      ; Number of CRTC Registers to update
  78.     dw      00014h  ; turn off dword mode
  79.     dw      0e317h  ; turn on byte mode
  80.     dw      320     ; width
  81.     dw      200     ; height
  82.  
  83. X320Y240 label  word
  84.     db      0e3h    ; dot clock
  85.     db      10      ; Number of CRTC Registers to update
  86.     dw      00d06h  ; vertical total
  87.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  88.     dw      04109h  ; cell height (2 to double-scan)
  89.     dw      0ea10h  ; v sync start
  90.     dw      0ac11h  ; v sync end and protect cr0-cr7
  91.     dw      0df12h  ; vertical displayed
  92.     dw      00014h  ; turn off dword mode
  93.     dw      0e715h  ; v blank start
  94.     dw      00616h  ; v blank end
  95.     dw      0e317h  ; turn on byte mode
  96.     dw      320     ; width
  97.     dw      240     ; height
  98.  
  99. X360Y200 label  word
  100.     db      0e7h    ; dot clock
  101.     db      08      ; Number of CRTC Registers to update
  102.     dw      06b00h  ; horz total
  103.     dw      05901h  ; horz displayed
  104.     dw      05a02h  ; start horz blanking
  105.     dw      08e03h  ; end horz blanking
  106.     dw      05e04h  ; start h sync
  107.     dw      08a05h  ; end h sync
  108.     dw      00014h  ; turn off dword mode
  109.     dw      0e317h  ; turn on byte mode
  110.     dw      360     ; width
  111.     dw      200     ; height
  112.  
  113. X360Y240  label word
  114.     db      0e7h    ; dot clock
  115.     db      17      ; Number of CRTC Registers to update
  116.     dw      06b00h  ; horz total
  117.     dw      05901h  ; horz displayed
  118.     dw      05a02h  ; start horz blanking
  119.     dw      08e03h  ; end horz blanking
  120.     dw      05e04h  ; start h sync
  121.     dw      08a05h  ; end h sync
  122.     dw      00d06h  ; vertical total
  123.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  124.     dw      04109h  ; cell height (2 to double-scan)
  125.     dw      0ea10h  ; v sync start
  126.     dw      0ac11h  ; v sync end and protect cr0-cr7
  127.     dw      0df12h  ; vertical displayed
  128.     dw      02d13h  ; offset;
  129.     dw      00014h  ; turn off dword mode
  130.     dw      0e715h  ; v blank start
  131.     dw      00616h  ; v blank end
  132.     dw      0e317h  ; turn on byte mode
  133.     dw      360
  134.     dw      240
  135.  
  136. X376Y282 label word
  137.     db      0e7h
  138.     db      18
  139.     dw      06e00h  ; horz total
  140.     dw      05d01h  ; horz displayed
  141.     dw      05e02h  ; start horz blanking
  142.     dw      09103h  ; end horz blanking
  143.     dw      06204h  ; start h sync
  144.     dw      08f05h  ; end h sync
  145.     dw      06206h  ; vertical total
  146.     dw      0f007h  ; overflow
  147.     dw      06109h  ; cell height
  148.     dw      0310fh  ;
  149.     dw      03710h  ; v sync start
  150.     dw      08911h  ; v sync end and protect cr0-cr7
  151.     dw      03312h  ; vertical displayed
  152.     dw      02f13h  ; offset
  153.     dw      00014h  ; turn off dword mode
  154.     dw      03c15h  ; v blank start
  155.     dw      05c16h  ; v blank end
  156.     dw      0e317h  ; turn on byte mode
  157.     dw      376
  158.     dw      282
  159.  
  160. LABEL X256Y400 word
  161.     db      0e3h    ; dot clock
  162.     db      8       ; Number of CRTC Registers to update
  163.     dw      05f00h  ; horz total
  164.     dw      03f01h  ; horz displayed
  165.     dw      04202h  ; start horz blanking
  166.     dw      09f03h  ; end horz blanking
  167.     dw      04c04h  ; start h sync
  168.     dw      00005h  ; end h sync
  169.     dw      04009h  ; cell height
  170.     dw      00014h  ; turn off dword mode
  171.     dw      0e317h  ; turn on byte mode
  172.     dw      256
  173.     dw      400
  174.  
  175.  
  176. LABEL X256Y480 word
  177.     db      0e3h    ; dot clock
  178.     db      16      ; Number of CRTC Registers to update
  179.         dw      05f00h  ; horz total
  180.         dw      03f01h  ; horz displayed
  181.     dw      04202h  ; start horz blanking
  182.     dw      09f03h  ; end horz blanking
  183.     dw      04c04h  ; start h sync
  184.     dw      00005h  ; end h sync
  185.     dw      00d06h  ; vertical total
  186.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  187.     dw      04009h  ; cell height (2 to double-scan)
  188.     dw      0ea10h  ; v sync start
  189.     dw      0ac11h  ; v sync end and protect cr0-cr7
  190.     dw      0df12h  ; vertical displayed
  191.     dw      00014h  ; turn off dword mode
  192.     dw      0e715h  ; v blank start
  193.     dw      00616h  ; v blank end
  194.     dw      0e317h  ; turn on byte mode
  195.     dw      256
  196.     dw      480
  197.  
  198.  
  199.  
  200. X320Y400 label  word
  201.     db      0e3h    ; dot clock
  202.     db      03      ; Number of CRTC Registers to update
  203.     dw      04009h  ; cell height
  204.     dw      00014h  ; turn off dword mode
  205.     dw      0e317h  ; turn on byte mode
  206.     dw      320     ; width
  207.     dw      400     ; height
  208.  
  209. X320Y480 label  word
  210.     db      0e3h    ; dotclock
  211.     db      10      ; Number of CRTC Registers to update
  212.     dw      00d06h  ; vertical total
  213.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  214.     dw      04009h  ; cell height (2 to double-scan)
  215.     dw      0ea10h  ; v sync start
  216.     dw      0ac11h  ; v sync end and protect cr0-cr7
  217.     dw      0df12h  ; vertical displayed
  218.     dw      00014h  ; turn off dword mode
  219.     dw      0e715h  ; v blank start
  220.     dw      00616h  ; v blank end
  221.     dw      0e317h  ; turn on byte mode
  222.     dw      320     ; width
  223.     dw      480     ; height
  224.  
  225. X360Y400 label  word
  226.     db      0e7h    ; dot clock
  227.     db      09      ; Number of CRTC Registers to update
  228.     dw      06b00h  ; horz total
  229.     dw      05901h  ; horz displayed
  230.     dw      05a02h  ; start horz blanking
  231.     dw      08e03h  ; end horz blanking
  232.     dw      05e04h  ; start h sync
  233.     dw      08a05h  ; end h sync
  234.     dw      04009h  ; cell height
  235.     dw      00014h  ; turn off dword mode
  236.     dw      0e317h  ; turn on byte mode
  237.     dw      360     ; width
  238.     dw      400     ; height
  239.  
  240.  
  241.  
  242. X360Y480  label word
  243.     db      0e7h
  244.     db      17
  245.     dw      06b00h  ; horz total
  246.     dw      05901h  ; horz displayed
  247.     dw      05a02h  ; start horz blanking
  248.     dw      08e03h  ; end horz blanking
  249.     dw      05e04h  ; start h sync
  250.     dw      08a05h  ; end h sync
  251.     dw      00d06h  ; vertical total
  252.     dw      03e07h  ; overflow
  253.     dw      04009h  ; cell height
  254.     dw      0ea10h  ; v sync start
  255.     dw      0ac11h  ; v sync end and protect cr0-cr7
  256.     dw      0df12h  ; vertical displayed
  257.     dw      02d13h  ; offset
  258.     dw      00014h  ; turn off dword mode
  259.     dw      0e715h  ; v blank start
  260.     dw      00616h  ; v blank end
  261.     dw      0e317h  ; turn on byte mode
  262.     dw      360
  263.     dw      480
  264.  
  265. X360Y360  label word
  266.     db      0e7h
  267.     db      15
  268.     dw      06b00h  ; horz total
  269.     dw      05901h  ; horz displayed
  270.     dw      05a02h  ; start horz blanking
  271.     dw      08e03h  ; end horz blanking
  272.     dw      05e04h  ; start h sync
  273.     dw      08a05h  ; end h sync
  274.     dw      04009h  ; cell height
  275.     dw      08810h  ; v sync start
  276.     dw      08511h  ; v sync end and protect cr0-cr7
  277.     dw      06712h  ; vertical displayed
  278.     dw      02d13h  ; offset
  279.     dw      00014h  ; turn off dword mode
  280.     dw      06d15h  ; v blank start
  281.     dw      0ba16h  ; v blank end
  282.     dw      0e317h  ; turn on byte mode
  283.     dw      360
  284.     dw      360
  285.  
  286.  
  287. X376Y308 label word
  288.     db      0e7h
  289.     db      18
  290.     dw      06e00h  ; horz total
  291.     dw      05d01h  ; horz displayed
  292.     dw      05e02h  ; start horz blanking
  293.     dw      09103h  ; end horz blanking
  294.     dw      06204h  ; start h sync
  295.     dw      08f05h  ; end h sync
  296.     dw      06206h  ; vertical total
  297.     dw      00f07h  ; overflow
  298.     dw      04009h  ;
  299.     dw      0310fh  ;
  300.     dw      03710h  ; v sync start
  301.     dw      08911h  ; v sync end and protect cr0-cr7
  302.     dw      03312h  ; vertical displayed
  303.     dw      02f13h  ; offset
  304.     dw      00014h  ; turn off dword mode
  305.     dw      03c15h  ; v blank start
  306.     dw      05c16h  ; v blank end
  307.     dw      0e317h  ; turn on byte mode
  308.     dw      376
  309.     dw      308
  310.  
  311. X376Y564 label word
  312.     db      0e7h
  313.     db      18
  314.     dw      06e00h  ; horz total
  315.     dw      05d01h  ; horz displayed
  316.     dw      05e02h  ; start horz blanking
  317.     dw      09103h  ; end horz blanking
  318.     dw      06204h  ; start h sync
  319.     dw      08f05h  ; end h sync
  320.     dw      06206h  ; vertical total
  321.     dw      0f007h  ; overflow
  322.     dw      06009h  ;
  323.     dw      0310fh  ;
  324.     dw      03710h  ; v sync start
  325.     dw      08911h  ; v sync end and protect cr0-cr7
  326.     dw      03312h  ; vertical displayed
  327.     dw      02f13h  ; offset
  328.     dw      00014h  ; turn off dword mode
  329.     dw      03c15h  ; v blank start
  330.     dw      05c16h  ; v blank end
  331.     dw      0e317h  ; turn on byte mode
  332.     dw      376
  333.     dw      564
  334.  
  335. LAST_X_MODE         equ    13
  336. ModeTable label word    ; Mode X tweak table
  337.     dw      offset X320Y200
  338.     dw      offset X320Y240
  339.     dw      offset X360Y200
  340.     dw      offset X360Y240
  341.     dw      offset X376Y282
  342.     dw      offset X320Y400
  343.     dw      offset X320Y480
  344.     dw      offset X360Y400
  345.     dw      offset X360Y480
  346.     dw      offset X360Y360
  347.     dw      offset X376Y308
  348.     dw      offset X376Y564
  349.     dw      offset X256Y200
  350.     dw      offset X256Y240
  351.  
  352.  
  353. PARAMS label byte
  354.  
  355.     _CurrXMode               dw 0   ; Current graphics mode index
  356.     _InGraphics              db 0   ; Flag indicating graphics activity
  357.     _ScrnPhysicalByteWidth   dw 0   ; Physical width in bytes of screen
  358.     _ScrnPhysicalPixelWidth  dw 0   ; Physical width in pixels of screen
  359.     _ScrnPhysicalHeight      dw 0   ; Physical Height of screen
  360.     _ErrorValue              db 0   ; Set after function calls
  361.  
  362.  
  363.     _SplitScrnActive         db 0   ; Flag indicating Split scrn activity
  364.     _DoubleBufferActive      dw 0   ; Flag indicating double buffering
  365.     _TrippleBufferActive     dw 0   ; Flag indicating tripple buffering
  366.  
  367.     _SplitScrnScanLine       dw 0   ; Split Screen's starting scan line
  368.     _SplitScrnVisibleHeight  dw 0   ; Split Screen's height on screen
  369.  
  370.     _SplitScrnOffs           dw 0   ; Offset in video ram of Split Screen
  371.                     ; always = 0
  372.     _Page0_Offs              dw 0   ; Ofset in video ram of Main virtual
  373.                     ; screen ( = 0 if no split screen
  374.                     ; otherwise = offset of first byte
  375.                     ; after split screen
  376.     _Page1_Offs              dw 0   ; Ofset in video ram of Second virtual
  377.                     ; screen ( = 0 if no split screen
  378.                     ; otherwise = offset of first byte
  379.                     ; after split screen
  380.                     ; = Page0_Offs if Doubble buffering
  381.                     ; not enabled
  382.     _Page2_Offs              dw 0
  383.  
  384.     _NonVisual_Offs          dw 0   ; Ofset in video ram of first byte
  385.                     ; of non visible ram
  386.     _ScrnLogicalByteWidth    dw 0   ; Logical width in bytes of screen
  387.     _ScrnLogicalPixelWidth   dw 0   ; Logical width in pixels of screen
  388.     _ScrnLogicalHeight       dw 0   ; Logical Height of screen
  389.  
  390.     _MaxScrollX              dw 0   ; Max X start position of Physical
  391.                     ; screen within virtual screen (in
  392.                     ; bytes)
  393.     _MaxScrollY              dw 0   ; Max Y start position of Physical
  394.                     ; screen within virtual screen
  395.  
  396.     _VisiblePageIdx          dw 0   ; Index of currently visible D.B.
  397.                     ; page
  398.  
  399.     PageAddrTable label word
  400.     _VisiblePageOffs         dw 0   ; Table containing starting offsets
  401.     _HiddenPageOffs          dw 0   ; of the double buffer pages
  402.     _WaitingPageOffs                 dw 0
  403.  
  404.     _TopClip                 dw 0   ; Clipping Rectangle
  405.     _BottomClip              dw 0   ;
  406.     _LeftClip                dw 0   ; Left/Right coordinates in bytes
  407.     _RightClip               dw 0   ;
  408.     _PhysicalStartByteX      dw 0   ; X byte coord of physical screen
  409.                     ; relative to virtual virtual screen
  410.     _PhysicalStartPixelX     dw 0   ; X pixel coord of physical screen
  411.                     ; relative to virtual screen
  412.     _PhysicalStartY          dw 0   ; Y pixel coord of physical screen
  413.                     ; relative to virtual screen
  414.  
  415. ; NEW
  416.     _VsyncHandlerActive     dw      0
  417.     _MouseRefreshFlag       dw      0
  418.     _MouseVsyncHandler      dd      0
  419.     _StartAddressFlag       dw      0
  420.     _WaitingStartLow        dw      0
  421.     _WaitingStartHigh       dw      0
  422.     _WaitingPelPan          dw      0
  423.     _VsyncPaletteStart      dw      0
  424.     _VsyncPaletteCount      dw      0
  425.     _VsyncPaletteBuffer     label  byte
  426.                 db  768  dup(?)
  427.  
  428.  
  429. PARAMS_END label byte
  430.  
  431. PARAM_COUNT equ ($-PARAMS)
  432.  
  433. ;The screen segment default value, should be reset when using a Windoze program
  434.     _SCREEN_SEG                dw    0a000h
  435.  
  436.  
  437. ; Index/data pairs for CRT Controller registers that differ between
  438. ; mode 13h and mode X.
  439.  
  440.     ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively
  441.     PelPanMask              db      000h,002h,004h,006h
  442.  
  443. DoubleScanFlag db ?     ; Flag to indicate double scanned mode
  444.  
  445.     .code
  446.  
  447. ;-------------------------------------------------------------------------
  448. ; Local Logical Screen Width setting function
  449. ; cx = Requitrd Logical Width
  450. ;
  451. ; WARNING: no registers are preserved
  452.  
  453. SetLogicalScrWidth proc
  454.     mov   dx,CRTC_INDEX
  455.     mov   al,CRTC_OFFSET
  456.     out   dx,al
  457.     inc   dx
  458.  
  459.     mov   ax,cx
  460.     cmp   ax,[_ScrnPhysicalPixelWidth]; Is logical width >= physical width
  461.     jge   @@ValidLogicalWidth          ; yes - continue
  462.     mov   ax,bx                        ; no - set logical width = physical
  463.  
  464. @@ValidLogicalWidth:
  465.     shr   ax,3
  466.     out   dx,al
  467.  
  468.     ; The EXACT logical pixel width may not have been possible since
  469.     ; it should be divisible by 8. Round down to the closest possible
  470.     ; width and update the status variables
  471.  
  472.     shl   ax,1
  473.     mov   bx,ax
  474.     mov   [_ScrnLogicalByteWidth],ax  ; Store the byte width of virtual
  475.     mov   [_RightClip],ax             ; Set default Right clip column
  476.                       ; screen
  477.     sub   ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position
  478.     shl   ax,2                        ; of physical screen in virtual
  479.     mov   [_MaxScrollX],ax            ; screen in pixels
  480.     mov   ax,bx                       ; set ax to byte width of virt scrn
  481.     shl   ax,2                        ; convert to pixels
  482.     mov   [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width
  483.     mov   cx,ax                       ; save ax (return value)
  484.  
  485.     ; calculate no. non split screen rows in video ram
  486.  
  487.     mov   ax,0ffffh                ; cx = Maximum video ram offset
  488.     sub   dx,dx                    ; DX:AX is divide operand,  set DX = 0
  489.     div   bx                       ; divide ax by ScrnLogicalByteWidth
  490.     mov   [_ScrnLogicalHeight],ax  ; Save Screen Logical Height
  491.     mov   [_BottomClip],ax         ; Set default bottom clip row
  492.     sub   ax,[_ScrnPhysicalHeight] ; Update the maximum Y position of
  493.     mov   [_MaxScrollY],ax         ; Physical screen in logical screen
  494.     mov   ax,cx                    ; restore ax (return value)
  495.  
  496.     ; calculate initial NonVisual
  497.     mov  ax,[_ScrnLogicalByteWidth]
  498.     mul  [_ScrnPhysicalHeight]
  499.     mov  [_NonVisual_Offs],ax
  500.  
  501. @@Done: ret
  502. SetLogicalScrWidth endp
  503.  
  504. clear_vram proc
  505.         push  di
  506.     mov   dx,SC_INDEX
  507.     mov   ax,0f02h
  508.     out   dx,ax               ; enable writes to all four planes
  509.     mov   ax,_SCREEN_SEG       ; now clear all display memory, 8 pixels
  510.     mov   es,ax               ; at a time
  511.     sub   di,di               ; point ES:DI to display memory
  512.  
  513.     WaitVsyncEnd
  514.  
  515.     sub   ax,ax               ; clear to zero-value pixels
  516.     mov   cx,0FFFFh           ; # of words in display memory
  517.     rep   stosw               ; clear all of display memory
  518.         pop   di
  519.     ret
  520. clear_vram endp
  521.  
  522.  
  523.  
  524. ;-----------------------------------------------------------------------
  525. ; Mode X graphics mode set with a virtual screen
  526. ;   logical screen width.
  527. ; C near-callable as:
  528. ;
  529. ;    int x_set_mode(unsigned int mode,unsigned int WidthInPixels);
  530. ;
  531. ; returns the actual width of the allocated virtual screen in pixels
  532. ; if a valid mode was selected otherwise returns -1
  533. ;
  534. ; Saves virtual screen pixel width in _ScrnLogicalPixelWidth.
  535. ; Saves virtual screen byte  width in _ScrnLogicalByteWidth.
  536. ; Physical screen dimensions are set in _ScrnPhysicalPixelWidth,
  537. ; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight
  538. ;
  539. ;
  540. ; Modes:  0  = 320 x 200  (256 color)  NOTE: Some of these modes require
  541. ;         1  = 320 x 240  (256 color)     vertical size adjustment.
  542. ;         2  = 360 x 200  (256 color)
  543. ;         3  = 360 x 240  (256 color)
  544. ;         4  = 320 x 400  (256 color)
  545. ;         5  = 320 x 480  (256 color)
  546. ;         6  = 360 x 200  (256 color)
  547. ;         7  = 360 x 480  (256 color)
  548. ;         8  = 360 x 360  (256 color)
  549. ;         9  = 376 x 308  (256 color)
  550. ;         10 = 376 x 564  (256 color)
  551. ;
  552. ; Written by Themie Gouthas,
  553. ; parts adapted from M. Abrash code.
  554. ;------------------------------------------------------------------------
  555. _x_set_mode proc
  556.     ARG   mode:word,logicalscrwidth:word
  557.     push  bp      ;preserve caller's stack frame
  558.     mov   bp,sp
  559.  
  560.     push  si      ;preserve C register vars
  561.     push  di      ; (don't count on BIOS preserving anything)
  562.  
  563.     cld
  564.     mov   ax,ds
  565.     mov   es,ax
  566.     mov   di,offset PARAMS
  567.     xor   ax,ax
  568.     mov   cx,PARAM_COUNT
  569.     rep   stosb
  570.  
  571.     mov   cx,[mode]
  572.     cmp   cx,LAST_X_MODE        ; have we selected a valid mode
  573.     jle   @@ValidMode           ; Yes !
  574.  
  575.     mov   [_InGraphics],FALSE   ; No return -1
  576.     mov   ax,-1
  577.     pop   di
  578.     pop   si
  579.     pop   bp
  580.     ret
  581.  
  582. @@ValidMode:
  583.  
  584.     mov   [_CurrXMode],cx
  585.     mov   [_InGraphics],TRUE
  586.  
  587.     xor   al,al
  588.     cmp   cx,3
  589.     jg    @@SetDoubleScanFlag
  590.     mov   al,TRUE
  591. @@SetDoubleScanFlag:
  592.     mov   [DoubleScanFlag],al
  593.     push  cx                    ; some bios's dont preserve cx
  594.  
  595.     call  clear_vram
  596.  
  597.     mov   ax,13h                ; let the BIOS set standard 256-color
  598.     int   10h                   ;  mode (320x200 linear)
  599.  
  600.  
  601.     pop   cx
  602.  
  603.     mov   dx,SC_INDEX
  604.     mov   ax,0604h
  605.     out   dx,ax                 ; disable chain4 mode
  606.     mov   ax,0100h
  607.     out   dx,ax                 ; synchronous reset while setting Misc
  608.                     ;  Output for safety, even though clock
  609.                     ;  unchanged
  610.  
  611.     mov   bx,offset ModeTable
  612.     shl   cx,1
  613.     add   bx,cx
  614.     mov   si, word ptr [bx]
  615.     lodsb
  616.  
  617.     or    al,al
  618.     jz    @@DontSetDot
  619.     mov   dx,MISC_OUTPUT
  620.     out   dx,al               ; select the dot clock and Horiz
  621.                   ;  scanning rate
  622. @@DontSetDot:
  623.     mov   dx,SC_INDEX
  624.     mov   ax,0300h
  625.     out   dx,ax               ; undo reset (restart sequencer)
  626.  
  627.  
  628.     mov   dx,CRTC_INDEX       ; reprogram the CRT Controller
  629.     mov   al,11h              ; VSync End reg contains register write
  630.     out   dx,al               ; protect bit
  631.     inc   dx                  ; CRT Controller Data register
  632.     in    al,dx               ; get current VSync End register setting
  633.     and   al,07fh             ; remove write protect on various
  634.     out   dx,al               ; CRTC registers
  635.     dec   dx                  ; CRT Controller Index
  636.     cld
  637.     xor   cx,cx
  638.     lodsb
  639.     mov   cl,al
  640.  
  641. @@SetCRTParmsLoop:
  642.     lodsw                     ; get the next CRT Index/Data pair
  643.     out   dx,ax               ; set the next CRT Index/Data pair
  644.     loop  @@SetCRTParmsLoop
  645.  
  646.     mov   dx,SC_INDEX
  647.     mov   ax,0f02h
  648.     out   dx,ax               ; enable writes to all four planes
  649.     mov   ax,_SCREEN_SEG       ; now clear all display memory, 8 pixels
  650.     mov   es,ax               ; at a time
  651.     sub   di,di               ; point ES:DI to display memory
  652.     sub   ax,ax               ; clear to zero-value pixels
  653.     mov   cx,8000h            ; # of words in display memory
  654.     rep   stosw               ; clear all of display memory
  655.  
  656.     ;  Set pysical screen dimensions
  657.  
  658.     lodsw                               ; Load scrn pixel width
  659.     mov   [_ScrnPhysicalPixelWidth],ax  ;  from tweak table and store
  660.     mov   [_SplitScrnScanLine],ax       ; No splitscrn ==
  661.                         ; splitscrn=PhysicalscrnHeight
  662.     mov   bx,ax                         ; Copy width for later use
  663.     shr   ax,2                          ; Convert to byte width
  664.     mov   [_ScrnPhysicalByteWidth],ax   ; Store for later use
  665.     lodsw                               ; Load Screen Phys. Height
  666.     mov   [_ScrnPhysicalHeight],ax      ; Store for later use
  667.  
  668.  
  669.     ;  Mode X is set, now set the required logical page width.
  670.  
  671.     mov     cx,[logicalscrwidth]
  672.  
  673.     call    SetLogicalScrWidth
  674.  
  675.     pop     di      ;restore C register vars
  676.     pop     si
  677.     pop     bp      ;restore caller's stack frame
  678.     ret
  679. _x_set_mode endp
  680.  
  681. ;----------------------------------------------------------------------
  682. ; Mode X (256 color mode) set default access video plane
  683. ;
  684. ; C near-callable as:
  685. ;    void x_select_default_plane(unsigned char plane);
  686. ;
  687. ; Enables Read/Write access to a plane using general memory access
  688. ; methods
  689. ;
  690. ; Written by Themie Gouthas
  691. ;----------------------------------------------------------------------
  692. _x_select_default_plane proc
  693. ARG Plane:byte
  694.     push bp
  695.     mov  bp,sp       ; set up stack frame
  696.     mov  cl,byte ptr [Plane]
  697.  
  698.     ; SELECT WRITE PLANE
  699.     and  cl,011b              ;CL = plane
  700.     mov  ax,0100h + MAP_MASK  ;AL = index in SC of Map Mask reg
  701.     shl  ah,cl                ;set only the bit for the required
  702.                   ; plane to 1
  703.     mov  dx,SC_INDEX          ;set the Map Mask to enable only the
  704.     out  dx,ax                ; pixel's plane
  705.  
  706.     ; SELECT READ PLANE
  707.     mov  ah,cl                ;AH = plane
  708.     mov  al,READ_MAP          ;AL = index in GC of the Read Map reg
  709.     mov  dx,GC_INDEX          ;set the Read Map to read the pixel's
  710.     out  dx,ax                ; plane
  711.  
  712.     pop  bp
  713.     ret
  714. _x_select_default_plane endp
  715.  
  716.  
  717. ;----------------------------------------------------------------------
  718. ; Mode X (256 color mode) Set Mode X split screen starting row
  719. ; The split screen resides on the bottom half of the screen and has a
  720. ; starting address of A000:0000
  721. ;
  722. ; C near-callable as:
  723. ;    void x_set_splitscreen(unsigned int line);
  724. ;
  725. ; Updates _Page0_Offs to reflect the existence of the split screen region
  726. ; ie _MainScrnOffset is set to the offset of the first pixel beyond the split
  727. ; screen region
  728. ;
  729. ; Written by Themie Gouthas
  730. ;----------------------------------------------------------------------
  731.  
  732. _x_set_splitscreen proc
  733.     ARG Line:word
  734.     push bp
  735.     mov  bp,sp       ; set up stack frame
  736.     push si
  737.  
  738.     xor  si,si       ; si=0 -> x virtual page start coord
  739.  
  740.     cmp  [_DoubleBufferActive],0
  741.     jne   @@error
  742.  
  743.     cmp  [_SplitScrnActive],0
  744.     je   @@NotPreviouslyCalled
  745.  
  746. @@error:
  747.     mov  [_ErrorValue],ERROR
  748.     pop  si
  749.     pop  bp          ; Return if previously called
  750.     ret
  751.  
  752. @@NotPreviouslyCalled:
  753.  
  754.     ; Turn on split screen pal pen suppression, so the split screen
  755.     ; wo'nt be subject to pel panning as is the non split screen portion.
  756.  
  757.     mov  dx,INPUT_STATUS_0
  758.     in   al,dx                  ; Reset the AC Index/Data toggle to
  759.                     ;  index state
  760.     mov  al,AC_MODE_CONTROL+20h ; Bit 5 set to prevent screen blanking
  761.     mov  dx,AC_INDEX            ; Point AC to Index/Data register
  762.     out  dx,al
  763.     inc  dx                     ; Point to AC Data reg (for reads only)
  764.     in   al,dx                  ; Get the current AC Mode Control reg
  765.     or   al,20h                 ; Enable split scrn Pel panning suppress.
  766.     dec  dx                     ; Point to AC Index/Data reg (for writes only)
  767.     out  dx,al                  ; Write the new AC Mode Control setting
  768.                     ;  with split screen pel panning
  769.                     ;  suppression turned on
  770.  
  771.     mov  [_PhysicalStartByteX],ax   ; Set the Phisical screen start
  772.     mov  [_PhysicalStartPixelX],ax  ; offset within virtual screen
  773.     mov  [_PhysicalStartY],ax
  774.     mov  [_SplitScrnActive],TRUE
  775.     mov  ax,[Line]
  776.     jns  @@NotNeg    ; Check that Split Scrn start scan line is +ve
  777.  
  778.     mov  ax,0        ; Since -ve set to 0
  779.  
  780. @@NotNeg:
  781.     mov  [_SplitScrnScanLine],ax   ; save the scanline
  782.  
  783.  
  784.  
  785.     or    [DoubleScanFlag],0
  786.     jz    @@NotDoubleScanned
  787.     shl   ax,1
  788.     dec   ax
  789. @@NotDoubleScanned:
  790.     ;mov  cl,[DoubleScanFlag]
  791.     ;shl  ax,cl            ; Mode X 200 and 240 line modes are actually
  792.                   ; 400 and 480 lines that are double scanned
  793.                   ; so for start scanline multiply required ModeX
  794.                   ; scan line by 2 if its a double scanned mode
  795.  
  796.  
  797.     mov  bx,ax            ; save the scanline
  798.  
  799.  
  800.     WaitVsyncStart        ; wait for vertical retrace
  801.  
  802.     cli                   ; Dont allow register setting to be interrupted
  803.     mov  dx,CRTC_INDEX
  804.     mov  ah,bl
  805.     mov  al,LINE_COMPARE
  806.     out  dx,ax            ; Bits 7-0 of the split screen scan line
  807.  
  808.     mov  ah,bh
  809.     and  ah,1
  810.     shl  ah,4
  811.     mov  al,OVERFLOW     ; Bit 4 of overflow register = Bit 8 of split
  812.     out  dx,al           ; screen scan line,
  813.     inc  dx              ; So using readability of VGA registers
  814.     in   al,dx           ; Read the OVERFLOW register, and set the
  815.     and  al, not 10h     ; bit corresponding to Bit 8 (above)
  816.     or   al,ah
  817.     out  dx,al
  818.  
  819.     dec  dx
  820.     mov  ah,bh
  821.     and  ah,2
  822.     ror  ah,3
  823.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  824.     out  dx,al             ; Bit 9 of split screen scan line
  825.     inc  dx                ; As we did before, update the apropriate
  826.     in   al,dx             ; bit without disturbing the rest
  827.     and  al, not 40h
  828.     or   al,ah
  829.     out  dx,al
  830.     sti                    ; Registers are set, so interrupts are safe
  831.  
  832.     mov  ax,[_ScrnPhysicalHeight]     ; Determine where the first byte
  833.     sub  ax,[_SplitScrnScanLine]      ; of the non split screen video ram
  834.     mov  [_SplitScrnVisibleHeight],ax ; starts and store it for reference
  835.  
  836.     mov  bx,[_ScrnLogicalByteWidth]
  837.     mul  bx
  838.     mov  [_Page0_Offs],ax
  839.     mov  [_Page1_Offs],ax
  840.     mov  [_Page2_Offs],ax
  841.  
  842.     ; calculate no. non split screen rows in video ram
  843.     mov  cx,0ffffh             ; cx = Maximum video ram offset
  844.     sub  cx,ax                 ; cx = cx - _Page0_Offs
  845.     xchg cx,ax                 ; swap cx and ax
  846.     sub  dx,dx                 ; DX:AX is divide operand,  set DX = 0
  847.     div  bx                    ; divide ax (prev cx) by
  848.                    ; ScrnLogicalByteWidth
  849.  
  850.     mov  [_ScrnLogicalHeight],ax     ; Save Screen Logical Height
  851.     cmp   ax,[_BottomClip]
  852.     jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary
  853.     mov   [_BottomClip],ax
  854. @@BottomClipOK:
  855.     sub  ax,[_SplitScrnScanLine]     ; Update the maximum Y position of
  856.     mov  [_MaxScrollY],ax            ; Physical screen in logical screen
  857.  
  858.     xchg cx,ax                       ; restore original ax (MainScrnOfs)
  859.     mov  bh,al                       ; Set the visible screen start address
  860.     mov  ch,ah                       ; to the top left corner of the virtual
  861.     jmp  StartAddrEntry              ; screen
  862. _x_set_splitscreen      endp
  863.  
  864.  
  865. ;-----------------------------------------------------------------------
  866. ; Mode X (256 color mode) Page flip primer
  867. ; No clipping is performed.
  868. ; C near-callable as:
  869. ;
  870. ;    void x_page_flip(unsigned int x, unsigned int y);
  871. ;
  872. ; Swaps visible and hidden page offsets and then executes the SetStartAddr
  873. ; to achieve a page flip.
  874. ;
  875. ; SEE x_set_start_addr below
  876. ;
  877. ; Written by Themie Gouthas
  878. ;------------------------------------------------------------------------
  879.  
  880. _x_page_flip proc
  881.     ARG x:word,y:word
  882.     push  bp                  ;preserve caller's stack frame
  883.     mov   bp,sp               ;point to local stack frame
  884.     push  si
  885.  
  886.     mov  si,[x]
  887.     mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
  888.     mov  cx,[y]
  889.     mul  cx                             ; for Y
  890.     cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
  891.     je   @@DoubleBuffer
  892.     cmp  [_TrippleBufferActive],TRUE
  893.     jne   PageFlipEntry1
  894.  
  895. ; TrippleBuffer
  896.     mov  bx,[_HiddenPageOffs]
  897.     xchg bx,[_VisiblePageOffs]
  898.     xchg bx,[_WaitingPageOffs]
  899.     mov  [_HiddenPageOffs],bx
  900.     mov  bx,[_VisiblePageIdx]
  901.     inc  bx
  902.     cmp  bx,3
  903.     jne  @@IdxOk
  904.     xor  bx,bx
  905. @@IdxOk:
  906.     mov  [_VisiblePageIdx],bx
  907.     jmp  short PageFlipEntry2
  908. @@DoubleBuffer:
  909.     mov  bx,[_HiddenPageOffs]
  910.     xchg bx,[_VisiblePageOffs]          ; Swap the Page Offsete
  911.     xchg [_HiddenPageOffs],bx
  912.     xor  [_VisiblePageIdx],01h          ; Set the Visible page index
  913.     jmp  short PageFlipEntry2
  914. _x_page_flip endp
  915.  
  916.  
  917. ;-----------------------------------------------------------------------
  918. ; Mode X (256 color mode) Set Mode X non split screen start address
  919. ;   of logical screen.
  920. ; C near-callable as:
  921. ;
  922. ;    void x_set_start_addr(unsigned int x, unsigned int y);
  923. ;
  924. ; Params: StartOffset is offset of first byte of logical screen ram
  925. ;           (Useful if you want to double buffer by splitting your non
  926. ;            split screen video ram into 2 pages)
  927. ;        X,Y coordinates of the top left hand corner of the physical screen
  928. ;           within the logical screen
  929. ;           X must not exceed (Logical screen width - Physical screen width)
  930. ;           Y must not exceed (Logical screen height - Physical screen height)
  931. ;
  932. ;
  933. ; Written by Themie Gouthas,
  934. ; Parts addapted from M. Abrash code published in DDJ Mag.
  935. ;------------------------------------------------------------------------
  936. _x_set_start_addr proc
  937.     ARG x:word,y:word
  938.     push bp
  939.     mov  bp,sp
  940.     push si
  941.  
  942.     mov  si,[x]
  943.     mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
  944.     mov  cx,[y]                         ; for Y
  945.     mul  cx
  946.     cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
  947.     je   @@PageResolution
  948.     cmp  [_TrippleBufferActive],TRUE
  949.     je   @@PageResolution
  950. PageFlipEntry1:
  951.     add  ax,[_Page0_Offs]               ; no - add page 0 offset
  952.     jmp  short @@AddColumn
  953.  
  954. PageFlipEntry2:
  955.  
  956.     mov  [_PhysicalStartPixelX],si
  957.     mov  [_PhysicalStartY],cx
  958.  
  959. @@PageResolution:
  960.     add  ax,[_VisiblePageOffs]          ; Add visible page offset
  961.  
  962. @@AddColumn:
  963.     mov  cx,si
  964.     shr  cx,2
  965.     mov  [_PhysicalStartByteX],cx
  966.     add  ax,cx                          ; add the column offset for X
  967.     mov  bh,al                          ; setup CRTC start addr regs and
  968.                         ; values in word registers for
  969.     mov  ch,ah                          ; fast word outs
  970.  
  971. StartAddrEntry:
  972.     mov  bl,ADDR_LOW
  973.     mov  cl,ADDR_HIGH
  974.     and  si,0003h             ; select pel pan register value for the
  975.     mov  ah,PelPanMask[si]    ; required x coordinate
  976.     mov  al,PEL_PANNING+20h
  977.     mov  si,ax
  978.  
  979.     cmp  [_VsyncHandlerActive],TRUE
  980.     jne   @@NoVsyncHandler
  981. ; NEW STUFF
  982. @@WaitLast:
  983.     cmp   [_StartAddressFlag],0
  984.     jne   @@WaitLast
  985.     cli
  986.     mov  [_WaitingStartLow],bx
  987.     mov  [_WaitingStartHigh],cx
  988.     mov  [_WaitingPelPan],si
  989.     mov  [_StartAddressFlag],1
  990.     sti
  991.     jmp  short @@Return
  992.  
  993. @@NoVsyncHandler:
  994.     mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse
  995. @@WaitDE:
  996.     in   al,dx
  997.     test al,01h
  998.     jnz  @@WaitDE            ;display enable is active low (0 = active)
  999.  
  1000.     mov  dx,CRTC_INDEX
  1001.     mov  ax,bx
  1002.     cli
  1003.     out  dx,ax               ;start address low
  1004.     mov  ax,cx
  1005.     out  dx,ax               ;start address high
  1006.     sti
  1007.  
  1008. ; Now wait for vertical sync, so the other page will be invisible when
  1009. ; we start drawing to it.
  1010.     mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse
  1011. @@WaitVS:
  1012.     in   al,dx
  1013.     test al,08h
  1014.     jz @@WaitVS           ;display enable is active low (0 = active)
  1015.  
  1016.  
  1017.     mov  dx,AC_INDEX
  1018.     mov  ax,si                ; Point the attribute controller to pel pan
  1019.     cli
  1020.     out  dx,al                ; reg. Bit 5 also set to prevent blanking
  1021.     mov  al,ah
  1022.     out  dx,al                ; load new Pel Pan setting.
  1023.     sti
  1024.  
  1025. @@Return:
  1026.     mov  [_ErrorValue],OK
  1027.     pop  si
  1028.     pop  bp
  1029.     ret
  1030. _x_set_start_addr  endp
  1031.  
  1032.  
  1033. ;-----------------------------------------------------------------------
  1034. ; Mode X (256 color mode) Mode X split screen hide
  1035. ; C near-callable as:
  1036. ;
  1037. ;    void x_hide_splitscreen()
  1038. ;
  1039. ; Hides an existing split screen by setting its starting scan line to
  1040. ; the last physical screen scan line
  1041. ;
  1042. ; WARNING: Only to be used if SplitScrnLine has been previously called
  1043. ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
  1044. ;          the initial split screen is reserved and the size limitations
  1045. ;          of these modes means any change in the split screen scan line
  1046. ;          will encroach on the split screen ram
  1047. ;
  1048. ; Written by Themie Gouthas
  1049. ;------------------------------------------------------------------------
  1050.  
  1051. _x_hide_splitscreen proc
  1052.     push bp
  1053.     mov  bp,sp
  1054.  
  1055.     cmp  [_SplitScrnActive],TRUE
  1056.     je   @@SplitScreenEnabled
  1057.  
  1058. @@error:
  1059.     mov  [_ErrorValue],ERROR
  1060.     pop  bp
  1061.     ret
  1062.  
  1063. @@SplitScreenEnabled:
  1064.     cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
  1065.     jg   @@error
  1066.     mov  bx,[_ScrnPhysicalHeight]
  1067.  
  1068.     mov  ax,[_ScrnLogicalHeight]
  1069.     sub  ax,bx
  1070.     mov  [_MaxScrollY],ax
  1071.     xor  ax,ax
  1072.     mov  [_SplitScrnVisibleHeight],ax
  1073.  
  1074.     or    [DoubleScanFlag],0
  1075.     jz    @@NotDoubleScanned
  1076.     shl   bx,1
  1077.     dec   bx
  1078. @@NotDoubleScanned:
  1079.     ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes
  1080.     ;shl  bx,cl
  1081.  
  1082.     WaitVsyncStart               ; wait for vertical retrace
  1083.  
  1084.     cli                 ; Dont allow register setting to be interrupted
  1085.     mov  dx,CRTC_INDEX
  1086.     mov  ah,bl
  1087.     mov  al,LINE_COMPARE
  1088.     out  dx,ax          ; Bits 7-0 of the split screen scan line
  1089.  
  1090.     mov  ah,bh
  1091.     and  ah,1
  1092.     shl  ah,4
  1093.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  1094.     out  dx,al        ; screen scan line,
  1095.     inc  dx           ; So using readability of VGA registers
  1096.     in   al,dx        ; Read the OVERFLOW register, and set the
  1097.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  1098.     or   al,ah
  1099.     out  dx,al
  1100.  
  1101.     dec  dx
  1102.     mov  ah,bh
  1103.     and  ah,2
  1104.     ror  ah,3
  1105.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  1106.     out  dx,al             ; Bit 9 of split screen scan line
  1107.     inc  dx                ; As we did before, update the apropriate
  1108.     in   al,dx             ; bit without disturbing the rest
  1109.     and  al, not 40h
  1110.     or   al,ah
  1111.     out  dx,al
  1112.     sti                  ; Registers are set, so interrupts are safe
  1113.  
  1114. @@done:
  1115.  
  1116.     mov  [_ErrorValue],OK
  1117.     pop  bp
  1118.     ret
  1119. _x_hide_splitscreen endp
  1120.  
  1121. ;-----------------------------------------------------------------------
  1122. ; Mode X (256 color mode) Mode X split screen show
  1123. ; C near-callable as:
  1124. ;
  1125. ;    void x_show_splitscreen()
  1126. ;
  1127. ; Restores split screen start scan line to the initial split screen
  1128. ; starting scan line as set by SplitScrnLine.
  1129. ;
  1130. ; WARNING: Only to be used if SplitScrnLine has been previously called
  1131. ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
  1132. ;          the initial split screen is reserved and the size limitations
  1133. ;          of these modes means any change in the split screen scan line
  1134. ;          will encroach on the split screen ram
  1135. ;          Update: Now disabled for these modes
  1136. ;
  1137. ; Written by Themie Gouthas
  1138. ;------------------------------------------------------------------------
  1139.  
  1140.  
  1141. _x_show_splitscreen proc
  1142.     push bp
  1143.     mov  bp,sp
  1144.  
  1145.     cmp  [_SplitScrnActive],TRUE
  1146.     je   @@SplitScreenEnabled
  1147.  
  1148. @@error:
  1149.     mov  [_ErrorValue],ERROR
  1150.     pop  bp
  1151.     ret
  1152.  
  1153. @@SplitScreenEnabled:
  1154.     cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
  1155.     jg   @@error
  1156.  
  1157.     mov  bx,[_SplitScrnScanLine]
  1158.     mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
  1159.     sub  ax,bx
  1160.     mov  [_MaxScrollY],ax
  1161.  
  1162.     mov  ax,[_ScrnPhysicalHeight]
  1163.     sub  ax,bx
  1164.     mov  [_SplitScrnVisibleHeight],ax
  1165.  
  1166.     or    [DoubleScanFlag],0
  1167.     jz    @@NotDoubleScanned
  1168.     shl   bx,1
  1169.     dec   bx
  1170. @@NotDoubleScanned:
  1171.     ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes
  1172.     ;shl  bx,cl
  1173.     WaitVsyncStart               ; wait for vertical retrace
  1174.  
  1175.     cli                          ; Dont allow register setting to be interrupted
  1176.     mov  dx,CRTC_INDEX
  1177.     mov  ah,bl
  1178.     mov  al,LINE_COMPARE
  1179.     out  dx,ax                  ; Bits 7-0 of the split screen scan line
  1180.  
  1181.     mov  ah,bh
  1182.     and  ah,1
  1183.     shl  ah,4
  1184.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  1185.     out  dx,al        ; screen scan line,
  1186.     inc  dx           ; So using readability of VGA registers
  1187.     in   al,dx        ; Read the OVERFLOW register, and set the
  1188.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  1189.     or   al,ah
  1190.     out  dx,al
  1191.  
  1192.     dec  dx
  1193.     mov  ah,bh
  1194.     and  ah,2
  1195.     ror  ah,3
  1196.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  1197.     out  dx,al             ; Bit 9 of split screen scan line
  1198.     inc  dx                ; As we did before, update the apropriate
  1199.     in   al,dx             ; bit without disturbing the rest
  1200.     and  al, not 40h
  1201.     or   al,ah
  1202.     out  dx,al
  1203.     sti                  ; Registers are set, so interrupts are safe
  1204.  
  1205. @@Done:
  1206.     mov  [_ErrorValue],0
  1207.     pop  bp
  1208.     ret
  1209. _x_show_splitscreen endp
  1210.  
  1211.  
  1212. ;-----------------------------------------------------------------------
  1213. ; Mode X (256 color mode) Modify Mode X split screen starting scan line
  1214. ; C near-callable as:
  1215. ;
  1216. ;    void x_adjust_splitscreen(unsigned int ScanLine)
  1217. ;
  1218. ; Sets the split screen start scan line to a new scan line. Valid scan lines
  1219. ; are between the initial split screen starting scan line and the last
  1220. ; physical screen scan line.
  1221. ;
  1222. ; WARNING: Only to be used if SplitScrnLine has been previously called
  1223. ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
  1224. ;          the initial split screen is reserved and the size limitations
  1225. ;          of these modes means any change in the split screen scan line
  1226. ;          will encroach on the split screen ram
  1227. ;          Update: Now disabled for these modes
  1228. ;
  1229. ;
  1230. ; Written by Themie Gouthas
  1231. ;------------------------------------------------------------------------
  1232.  
  1233.  
  1234. _x_adjust_splitscreen proc
  1235.     ARG   ScanLine
  1236.     push bp
  1237.     mov  bp,sp
  1238.  
  1239.     cmp  [_SplitScrnActive],TRUE
  1240.     je   @@SplitScreenEnabled
  1241.  
  1242. @@error:
  1243.     mov  [_ErrorValue],ERROR
  1244.     pop  bp
  1245.     ret
  1246.  
  1247. @@SplitScreenEnabled:
  1248.     cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
  1249.     jg   @@error
  1250.     mov  bx,[ScanLine]            ; Is the required starting scan line
  1251.     cmp  bx,[_SplitScrnScanLine]  ; valid ?
  1252.     js   @@Done                   ; No - Then do nothing
  1253.  
  1254. @@ValidScanLine:
  1255.  
  1256.     mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
  1257.     sub  ax,bx
  1258.     mov  [_MaxScrollY],ax
  1259.  
  1260.     mov  ax,[_ScrnPhysicalHeight]
  1261.     sub  ax,bx
  1262.     mov  [_SplitScrnVisibleHeight],ax
  1263.  
  1264.     or    [DoubleScanFlag],0
  1265.     jz    @@NotDoubleScanned
  1266.     shl   bx,1
  1267.     dec   bx
  1268. @@NotDoubleScanned:
  1269.     ;mov  cl,[DoubleScanFlag]   ; Compensate for double scanned modes
  1270.     ;shl  bx,cl
  1271.  
  1272.     WaitVsyncStart      ; wait for vertical retrace
  1273.  
  1274.     cli                 ; Dont allow register setting to be interrupted
  1275.  
  1276.     mov  dx,CRTC_INDEX
  1277.     mov  ah,bl
  1278.     mov  al,LINE_COMPARE
  1279.     out  dx,ax          ; Bits 7-0 of the split screen scan line
  1280.  
  1281.     mov  ah,bh
  1282.     and  ah,1
  1283.     shl  ah,4
  1284.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  1285.     out  dx,al        ; screen scan line,
  1286.     inc  dx           ; So using readability of VGA registers
  1287.     in   al,dx        ; Read the OVERFLOW register, and set the
  1288.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  1289.     or   al,ah
  1290.     out  dx,al
  1291.  
  1292.     dec  dx
  1293.     mov  ah,bh
  1294.     and  ah,2
  1295.     ror  ah,3
  1296.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  1297.     out  dx,al             ; Bit 9 of split screen scan line
  1298.     inc  dx                ; As we did before, update the apropriate
  1299.     in   al,dx             ; bit without disturbing the rest
  1300.     and  al, not 40h
  1301.     or   al,ah
  1302.     out  dx,al
  1303.     sti                    ; Registers are set, so interrupts are safe
  1304. @@Done:
  1305.     mov  [_ErrorValue],OK
  1306.     pop   bp
  1307.     ret
  1308. _x_adjust_splitscreen endp
  1309.  
  1310.  
  1311.  
  1312. ;-----------------------------------------------------------------------
  1313. ; Mode X (256 color mode) Enable DoubleBuffering on non split screen area
  1314. ; C near-callable as:
  1315. ;
  1316. ;    int x_set_doublebuffer(unsigned int PageHeight);
  1317. ;
  1318. ; Params: PageHeight is the height of the virtual screen to double buffer
  1319. ;         Returns the closest possible height to the specified.
  1320. ;
  1321. ; Sets up two double buffering virtual pages
  1322. ; GLOBAL variables set:
  1323. ;
  1324. ;      _Page1_Offs              Offset of second virtual page
  1325. ;      _NonVisual_Offs          Offset of first non visible video ram byte
  1326. ;      _DoubleBufferActive      Flag
  1327. ;      _PageAddrTable           Table of Double buffering pages start offsets
  1328. ;      _ScrnLogicalHeight       Logical height of the double buffering pages
  1329. ;
  1330. ;
  1331. ; Written by Themie Gouthas
  1332. ;------------------------------------------------------------------------
  1333.  
  1334.  
  1335. _x_set_doublebuffer proc
  1336.        ARG PageHeight:word
  1337.        push  bp
  1338.        mov   bp,sp
  1339.  
  1340.        cmp   [_DoubleBufferActive],0
  1341.        je    @@OkToContinue
  1342. @error:
  1343.        mov   [_ErrorValue],ERROR
  1344.        pop   bp
  1345.        ret
  1346.  
  1347. @@OkToContinue:
  1348.        mov   [_VisiblePageIdx],0     ; Set visible Page to 0
  1349.        mov   ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to
  1350.        shr   ax,1                    ;   _ScrnLogicalHeight / 2
  1351.  
  1352.        mov   bx,[PageHeight]         ; Is the require D.B. Page Height
  1353.        cmp   ax,bx                   ;  > the Maximum  D.B. Page Height ?
  1354.  
  1355.        js    @@InvalidHeight         ; no  - jump
  1356.        mov   ax,bx                   ; yes - Set the D.B. Page height to
  1357.                      ;       to the maximum allowed.
  1358.  
  1359. @@InvalidHeight:
  1360.        mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to
  1361.                     ;  reflect the height of a D.B. page
  1362.        cmp   ax,[_BottomClip]
  1363.        jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary
  1364.        mov   [_BottomClip],ax
  1365. @@BottomClipOK:
  1366.        push  ax
  1367.        mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second
  1368.        mov   cx,ax                      ;  D.B. Page in video ram
  1369.        mov   bx,[_Page0_Offs]
  1370.        mov   [_VisiblePageOffs],bx
  1371.  
  1372.        add   ax,bx
  1373.        mov   [_Page1_Offs],ax           ; Save it
  1374.        mov   [_HiddenPageOffs],ax
  1375.  
  1376.        add   ax,cx                      ; Calculate the offset of first byte
  1377.        mov   [_NonVisual_Offs],ax       ;  beyond the D.B. pages and save it
  1378.        mov   [_DoubleBufferActive],TRUE ; Set flag indicating D.B'ing mode on
  1379.  
  1380.        pop   ax
  1381.        sub   ax,[_ScrnPhysicalHeight]
  1382.        add   ax,[_SplitScrnVisibleHeight]
  1383.        mov   [_MaxScrollY],ax
  1384.  
  1385.        mov   ax,dx                      ; return the D.B. pages' height
  1386.        mov   [_ErrorValue],OK
  1387.        pop   bp
  1388.        ret
  1389. _x_set_doublebuffer endp
  1390.  
  1391.  
  1392. ;-----------------------------------------------------------------------
  1393. ; Mode X (256 color mode) Enable TrippleBuffering on non split screen area
  1394. ; C near-callable as:
  1395. ;
  1396. ;    int x_set_tripplebuffer(unsigned int PageHeight);
  1397. ;
  1398. ; Params: PageHeight is the height of the virtual screen to tripple buffer
  1399. ;         Returns the closest possible height to the specified.
  1400. ;
  1401. ; Sets up two tripple buffering virtual pages
  1402. ; GLOBAL variables set:
  1403. ;
  1404. ;      _Page1_Offs              Offset of second virtual page
  1405. ;      _Page2_Offs              Offset of third virtual page
  1406. ;      _NonVisual_Offs          Offset of first non visible video ram byte
  1407. ;      _DoubleBufferActive      Flag
  1408. ;      _PageAddrTable           Table of Double buffering pages start offsets
  1409. ;      _ScrnLogicalHeight       Logical height of the double buffering pages
  1410. ;
  1411. ;
  1412. ; Almost written by Tore Bastiansen (cut & paste from _x_set_doublebuffer)
  1413. ;------------------------------------------------------------------------
  1414.  
  1415. _x_set_tripplebuffer proc
  1416.        ARG PageHeight:word
  1417.        push  bp
  1418.        mov   bp,sp
  1419.  
  1420.        cmp   [_DoubleBufferActive],0
  1421.        jne   @@Error
  1422.        cmp   [_TrippleBufferActive],0
  1423.        je    @@OkToContinue
  1424. @@Error:
  1425.        mov   [_ErrorValue],ERROR
  1426.        pop   bp
  1427.        ret
  1428.  
  1429. @@OkToContinue:
  1430.        mov   [_VisiblePageIdx],0     ; Set visible Page to 0
  1431.        mov   ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to
  1432.        mov   bx,3
  1433.        xor   dx,dx
  1434.        idiv  bx                      ;   _ScrnLogicalHeight / 3
  1435.  
  1436.        mov   bx,[PageHeight]         ; Is the require T.B. Page Height
  1437.        cmp   ax,bx                   ;  > the Maximum  T.B. Page Height ?
  1438.  
  1439.        js    @@InvalidHeight         ; no  - jump
  1440.        mov   ax,bx                   ; yes - Set the T.B. Page height to
  1441.                                      ;       to the maximum allowed.
  1442.  
  1443. @@InvalidHeight:
  1444.        mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to
  1445.                                         ;  reflect the height of a T.B. page
  1446.        cmp   ax,[_BottomClip]
  1447.        jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary
  1448.        mov   [_BottomClip],ax
  1449. @@BottomClipOK:
  1450.        push  ax
  1451.        mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second
  1452.        mov   cx,ax                      ;  D.B. Page in video ram
  1453.        mov   bx,[_Page0_Offs]
  1454.        mov   [_VisiblePageOffs],bx
  1455.  
  1456.        add   ax,bx
  1457.        mov   [_Page1_Offs],ax           ; Save it
  1458.        mov   [_HiddenPageOffs],ax
  1459.  
  1460.        add   ax,cx
  1461.        mov   [_Page2_Offs],ax            ; Save the other it ?
  1462.        mov   [_WaitingPageOffs],ax
  1463.  
  1464.        add   ax,cx                       ; Calculate the offset of first byte
  1465.        mov   [_NonVisual_Offs],ax        ;  beyond the D.B. pages and save it
  1466.        mov   [_TrippleBufferActive],TRUE ; Set flag indicating T.B'ing mode on
  1467.  
  1468.        pop   ax
  1469.        sub   ax,[_ScrnPhysicalHeight]
  1470.        add   ax,[_SplitScrnVisibleHeight]
  1471.        mov   [_MaxScrollY],ax
  1472.  
  1473.        mov   ax,dx                      ; return the D.B. pages' height
  1474.        mov   [_ErrorValue],OK
  1475.        pop   bp
  1476.        ret
  1477. _x_set_tripplebuffer endp
  1478.  
  1479.  
  1480. ;-----------------------------------------------------------------------
  1481. ; Set Clipping rectangle
  1482. ; C callable as:
  1483. ;
  1484. ;
  1485. ;    int x_set_cliprect(WORD left,WORD top, WORD right, WORD bottom);
  1486. ;
  1487. ;
  1488. ; NOTE clipping is byte oriented. "left" and "right" are in bytes not pixels.
  1489. ;    Only selected functions perform any clipping at all.
  1490. ;
  1491. ; Written by Themie Gouthas
  1492. ;------------------------------------------------------------------------
  1493.  
  1494. _x_set_cliprect proc
  1495. ARG left:word,top:word,right:word,bottom:word
  1496.        push  bp
  1497.        mov   bp,sp
  1498.        mov   ax,[left]
  1499.        mov   bx,[right]
  1500.        cmp   bx,ax
  1501.        jns   @@CorrectXOrder
  1502.        xchg  bx,ax
  1503. @@CorrectXOrder:
  1504.        mov   [_LeftClip],ax
  1505.        mov   [_RightClip],bx
  1506.        mov   ax,[top]
  1507.        mov   bx,[bottom]
  1508.        cmp   bx,ax
  1509.        jns   @@CorrectYOrder
  1510.        xchg  bx,ax
  1511. @@CorrectYOrder:
  1512.        mov   [_TopClip],ax
  1513.        mov   [_BottomClip],bx
  1514.        pop   bp
  1515.        ret
  1516. _x_set_cliprect endp
  1517.  
  1518.  
  1519. ;----------------------------------------------------------------------
  1520. ; Return to text mode
  1521. ;
  1522. _x_text_mode proc
  1523.        push  bp
  1524.        call  clear_vram
  1525.        mov   ax,03h        ; Restore Text Mode
  1526.        int   10h
  1527.  
  1528.        pop   bp
  1529.        ret
  1530. _x_text_mode endp
  1531.  
  1532. ;-----------------------------------------------------------------------
  1533. ; Wait for Vertical sync
  1534. _x_wait_vsync proc
  1535.     push  bp
  1536.     WaitVsyncStart
  1537.     pop   bp
  1538.     ret
  1539. _x_wait_vsync endp
  1540.  
  1541.  
  1542.     end
  1543.