]> 4ch.mooo.com Git - 16.git/blobdiff - 16/xlib/XMAIN.ASM
added xlib to the project and i gotta convert the damn makefile -.-
[16.git] / 16 / xlib / XMAIN.ASM
diff --git a/16/xlib/XMAIN.ASM b/16/xlib/XMAIN.ASM
deleted file mode 100755 (executable)
index a8fd418..0000000
+++ /dev/null
@@ -1,1539 +0,0 @@
-;-----------------------------------------------------------------------\r
-; MODULE XMAIN\r
-;\r
-; Initialization, panning and split screen functions for all MODE X 256\r
-; Color resolutions\r
-;\r
-; Compile with Tasm.\r
-; C callable.\r
-;\r
-;\r
-; ****** XLIB - Mode X graphics library                ****************\r
-; ******                                               ****************\r
-; ****** Written By Themie Gouthas                     ****************\r
-;\r
-; egg@dstos3.dsto.gov.au\r
-; teg@bart.dsto.gov.au\r
-;\r
-; MODIFICATIONS:\r
-;  26-9-92:          Pel panning code added\r
-;  Dates forgotten:  Numerous ;^)\r
-;  05-10-93:         Timer synchronized vsync handling extensions\r
-;                      and tripple buffering - Tore Jahn Bastiansen\r
-;                      (toreba@ifi.uio.no) for the\r
-;-----------------------------------------------------------------------\r
-\r
-\r
-include xlib.inc\r
-include xmain.inc\r
-\r
-\r
-       .data\r
-\r
-\r
-; Mode X CRTC register tweaks for various resolutions\r
-\r
-\r
-LABEL X256Y200 word\r
-               db      0e3h    ; dot clock\r
-               db      8       ; Number of CRTC Registers to update\r
-       dw      05f00h  ; horz total\r
-       dw      03f01h  ; horz displayed\r
-       dw      04202h  ; start horz blanking\r
-       dw      09f03h  ; end horz blanking\r
-       dw      04c04h  ; start h sync\r
-       dw      00005h  ; end h sync\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      256\r
-       dw      200\r
-\r
-\r
-LABEL X256Y240 word\r
-       db      0e3h    ; dot clock\r
-       db      16      ; Number of CRTC Registers to update\r
-       dw      05f00h  ; horz total\r
-       dw      03f01h  ; horz displayed\r
-       dw      04202h  ; start horz blanking\r
-       dw      09f03h  ; end horz blanking\r
-       dw      04c04h  ; start h sync\r
-       dw      00005h  ; end h sync\r
-       dw      00d06h  ; vertical total\r
-       dw      03e07h  ; overflow (bit 8 of vertical counts)\r
-       dw      04109h  ; cell height (2 to double-scan)\r
-       dw      0ea10h  ; v sync start\r
-       dw      0ac11h  ; v sync end and protect cr0-cr7\r
-       dw      0df12h  ; vertical displayed\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e715h  ; v blank start\r
-       dw      00616h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      256\r
-               dw      240\r
-\r
-\r
-X320Y200 label  word\r
-       db      00      ; 0e3h    ; dot clock\r
-       db      02      ; Number of CRTC Registers to update\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      320     ; width\r
-       dw      200     ; height\r
-\r
-X320Y240 label  word\r
-       db      0e3h    ; dot clock\r
-       db      10      ; Number of CRTC Registers to update\r
-       dw      00d06h  ; vertical total\r
-       dw      03e07h  ; overflow (bit 8 of vertical counts)\r
-       dw      04109h  ; cell height (2 to double-scan)\r
-       dw      0ea10h  ; v sync start\r
-       dw      0ac11h  ; v sync end and protect cr0-cr7\r
-       dw      0df12h  ; vertical displayed\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e715h  ; v blank start\r
-       dw      00616h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      320     ; width\r
-       dw      240     ; height\r
-\r
-X360Y200 label  word\r
-       db      0e7h    ; dot clock\r
-       db      08      ; Number of CRTC Registers to update\r
-       dw      06b00h  ; horz total\r
-       dw      05901h  ; horz displayed\r
-       dw      05a02h  ; start horz blanking\r
-       dw      08e03h  ; end horz blanking\r
-       dw      05e04h  ; start h sync\r
-       dw      08a05h  ; end h sync\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      360     ; width\r
-       dw      200     ; height\r
-\r
-X360Y240  label word\r
-       db      0e7h    ; dot clock\r
-       db      17      ; Number of CRTC Registers to update\r
-       dw      06b00h  ; horz total\r
-       dw      05901h  ; horz displayed\r
-       dw      05a02h  ; start horz blanking\r
-       dw      08e03h  ; end horz blanking\r
-       dw      05e04h  ; start h sync\r
-       dw      08a05h  ; end h sync\r
-       dw      00d06h  ; vertical total\r
-       dw      03e07h  ; overflow (bit 8 of vertical counts)\r
-       dw      04109h  ; cell height (2 to double-scan)\r
-       dw      0ea10h  ; v sync start\r
-       dw      0ac11h  ; v sync end and protect cr0-cr7\r
-       dw      0df12h  ; vertical displayed\r
-       dw      02d13h  ; offset;\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e715h  ; v blank start\r
-       dw      00616h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      360\r
-       dw      240\r
-\r
-X376Y282 label word\r
-       db      0e7h\r
-       db      18\r
-       dw      06e00h  ; horz total\r
-       dw      05d01h  ; horz displayed\r
-       dw      05e02h  ; start horz blanking\r
-       dw      09103h  ; end horz blanking\r
-       dw      06204h  ; start h sync\r
-       dw      08f05h  ; end h sync\r
-       dw      06206h  ; vertical total\r
-       dw      0f007h  ; overflow\r
-       dw      06109h  ; cell height\r
-       dw      0310fh  ;\r
-       dw      03710h  ; v sync start\r
-       dw      08911h  ; v sync end and protect cr0-cr7\r
-       dw      03312h  ; vertical displayed\r
-       dw      02f13h  ; offset\r
-       dw      00014h  ; turn off dword mode\r
-       dw      03c15h  ; v blank start\r
-       dw      05c16h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      376\r
-       dw      282\r
-\r
-LABEL X256Y400 word\r
-       db      0e3h    ; dot clock\r
-       db      8       ; Number of CRTC Registers to update\r
-       dw      05f00h  ; horz total\r
-       dw      03f01h  ; horz displayed\r
-       dw      04202h  ; start horz blanking\r
-       dw      09f03h  ; end horz blanking\r
-       dw      04c04h  ; start h sync\r
-       dw      00005h  ; end h sync\r
-       dw      04009h  ; cell height\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      256\r
-       dw      400\r
-\r
-\r
-LABEL X256Y480 word\r
-       db      0e3h    ; dot clock\r
-       db      16      ; Number of CRTC Registers to update\r
-               dw      05f00h  ; horz total\r
-               dw      03f01h  ; horz displayed\r
-       dw      04202h  ; start horz blanking\r
-       dw      09f03h  ; end horz blanking\r
-       dw      04c04h  ; start h sync\r
-       dw      00005h  ; end h sync\r
-       dw      00d06h  ; vertical total\r
-       dw      03e07h  ; overflow (bit 8 of vertical counts)\r
-       dw      04009h  ; cell height (2 to double-scan)\r
-       dw      0ea10h  ; v sync start\r
-       dw      0ac11h  ; v sync end and protect cr0-cr7\r
-       dw      0df12h  ; vertical displayed\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e715h  ; v blank start\r
-       dw      00616h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      256\r
-       dw      480\r
-\r
-\r
-\r
-X320Y400 label  word\r
-       db      0e3h    ; dot clock\r
-       db      03      ; Number of CRTC Registers to update\r
-       dw      04009h  ; cell height\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      320     ; width\r
-       dw      400     ; height\r
-\r
-X320Y480 label  word\r
-       db      0e3h    ; dotclock\r
-       db      10      ; Number of CRTC Registers to update\r
-       dw      00d06h  ; vertical total\r
-       dw      03e07h  ; overflow (bit 8 of vertical counts)\r
-       dw      04009h  ; cell height (2 to double-scan)\r
-       dw      0ea10h  ; v sync start\r
-       dw      0ac11h  ; v sync end and protect cr0-cr7\r
-       dw      0df12h  ; vertical displayed\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e715h  ; v blank start\r
-       dw      00616h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      320     ; width\r
-       dw      480     ; height\r
-\r
-X360Y400 label  word\r
-       db      0e7h    ; dot clock\r
-       db      09      ; Number of CRTC Registers to update\r
-       dw      06b00h  ; horz total\r
-       dw      05901h  ; horz displayed\r
-       dw      05a02h  ; start horz blanking\r
-       dw      08e03h  ; end horz blanking\r
-       dw      05e04h  ; start h sync\r
-       dw      08a05h  ; end h sync\r
-       dw      04009h  ; cell height\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      360     ; width\r
-       dw      400     ; height\r
-\r
-\r
-\r
-X360Y480  label word\r
-       db      0e7h\r
-       db      17\r
-       dw      06b00h  ; horz total\r
-       dw      05901h  ; horz displayed\r
-       dw      05a02h  ; start horz blanking\r
-       dw      08e03h  ; end horz blanking\r
-       dw      05e04h  ; start h sync\r
-       dw      08a05h  ; end h sync\r
-       dw      00d06h  ; vertical total\r
-       dw      03e07h  ; overflow\r
-       dw      04009h  ; cell height\r
-       dw      0ea10h  ; v sync start\r
-       dw      0ac11h  ; v sync end and protect cr0-cr7\r
-       dw      0df12h  ; vertical displayed\r
-       dw      02d13h  ; offset\r
-       dw      00014h  ; turn off dword mode\r
-       dw      0e715h  ; v blank start\r
-       dw      00616h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      360\r
-       dw      480\r
-\r
-X360Y360  label word\r
-       db      0e7h\r
-       db      15\r
-       dw      06b00h  ; horz total\r
-       dw      05901h  ; horz displayed\r
-       dw      05a02h  ; start horz blanking\r
-       dw      08e03h  ; end horz blanking\r
-       dw      05e04h  ; start h sync\r
-       dw      08a05h  ; end h sync\r
-       dw      04009h  ; cell height\r
-       dw      08810h  ; v sync start\r
-       dw      08511h  ; v sync end and protect cr0-cr7\r
-       dw      06712h  ; vertical displayed\r
-       dw      02d13h  ; offset\r
-       dw      00014h  ; turn off dword mode\r
-       dw      06d15h  ; v blank start\r
-       dw      0ba16h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      360\r
-       dw      360\r
-\r
-\r
-X376Y308 label word\r
-       db      0e7h\r
-       db      18\r
-       dw      06e00h  ; horz total\r
-       dw      05d01h  ; horz displayed\r
-       dw      05e02h  ; start horz blanking\r
-       dw      09103h  ; end horz blanking\r
-       dw      06204h  ; start h sync\r
-       dw      08f05h  ; end h sync\r
-       dw      06206h  ; vertical total\r
-       dw      00f07h  ; overflow\r
-       dw      04009h  ;\r
-       dw      0310fh  ;\r
-       dw      03710h  ; v sync start\r
-       dw      08911h  ; v sync end and protect cr0-cr7\r
-       dw      03312h  ; vertical displayed\r
-       dw      02f13h  ; offset\r
-       dw      00014h  ; turn off dword mode\r
-       dw      03c15h  ; v blank start\r
-       dw      05c16h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      376\r
-       dw      308\r
-\r
-X376Y564 label word\r
-       db      0e7h\r
-       db      18\r
-       dw      06e00h  ; horz total\r
-       dw      05d01h  ; horz displayed\r
-       dw      05e02h  ; start horz blanking\r
-       dw      09103h  ; end horz blanking\r
-       dw      06204h  ; start h sync\r
-       dw      08f05h  ; end h sync\r
-       dw      06206h  ; vertical total\r
-       dw      0f007h  ; overflow\r
-       dw      06009h  ;\r
-       dw      0310fh  ;\r
-       dw      03710h  ; v sync start\r
-       dw      08911h  ; v sync end and protect cr0-cr7\r
-       dw      03312h  ; vertical displayed\r
-       dw      02f13h  ; offset\r
-       dw      00014h  ; turn off dword mode\r
-       dw      03c15h  ; v blank start\r
-       dw      05c16h  ; v blank end\r
-       dw      0e317h  ; turn on byte mode\r
-       dw      376\r
-       dw      564\r
-\r
-LAST_X_MODE         equ    13\r
-ModeTable label word    ; Mode X tweak table\r
-       dw      offset X320Y200\r
-       dw      offset X320Y240\r
-       dw      offset X360Y200\r
-       dw      offset X360Y240\r
-       dw      offset X376Y282\r
-       dw      offset X320Y400\r
-       dw      offset X320Y480\r
-       dw      offset X360Y400\r
-       dw      offset X360Y480\r
-       dw      offset X360Y360\r
-       dw      offset X376Y308\r
-       dw      offset X376Y564\r
-       dw      offset X256Y200\r
-       dw      offset X256Y240\r
-\r
-\r
-PARAMS label byte\r
-\r
-       _CurrXMode               dw 0   ; Current graphics mode index\r
-       _InGraphics              db 0   ; Flag indicating graphics activity\r
-       _ScrnPhysicalByteWidth   dw 0   ; Physical width in bytes of screen\r
-       _ScrnPhysicalPixelWidth  dw 0   ; Physical width in pixels of screen\r
-       _ScrnPhysicalHeight      dw 0   ; Physical Height of screen\r
-       _ErrorValue              db 0   ; Set after function calls\r
-\r
-\r
-       _SplitScrnActive         db 0   ; Flag indicating Split scrn activity\r
-       _DoubleBufferActive      dw 0   ; Flag indicating double buffering\r
-       _TrippleBufferActive     dw 0   ; Flag indicating tripple buffering\r
-\r
-       _SplitScrnScanLine       dw 0   ; Split Screen's starting scan line\r
-       _SplitScrnVisibleHeight  dw 0   ; Split Screen's height on screen\r
-\r
-       _SplitScrnOffs           dw 0   ; Offset in video ram of Split Screen\r
-                                       ; always = 0\r
-       _Page0_Offs              dw 0   ; Ofset in video ram of Main virtual\r
-                                       ; screen ( = 0 if no split screen\r
-                                       ; otherwise = offset of first byte\r
-                                       ; after split screen\r
-       _Page1_Offs              dw 0   ; Ofset in video ram of Second virtual\r
-                                       ; screen ( = 0 if no split screen\r
-                                       ; otherwise = offset of first byte\r
-                                       ; after split screen\r
-                                       ; = Page0_Offs if Doubble buffering\r
-                                       ; not enabled\r
-       _Page2_Offs              dw 0\r
-\r
-       _NonVisual_Offs          dw 0   ; Ofset in video ram of first byte\r
-                                       ; of non visible ram\r
-       _ScrnLogicalByteWidth    dw 0   ; Logical width in bytes of screen\r
-       _ScrnLogicalPixelWidth   dw 0   ; Logical width in pixels of screen\r
-       _ScrnLogicalHeight       dw 0   ; Logical Height of screen\r
-\r
-       _MaxScrollX              dw 0   ; Max X start position of Physical\r
-                                       ; screen within virtual screen (in\r
-                                       ; bytes)\r
-       _MaxScrollY              dw 0   ; Max Y start position of Physical\r
-                                       ; screen within virtual screen\r
-\r
-       _VisiblePageIdx          dw 0   ; Index of currently visible D.B.\r
-                                       ; page\r
-\r
-       PageAddrTable label word\r
-       _VisiblePageOffs         dw 0   ; Table containing starting offsets\r
-       _HiddenPageOffs          dw 0   ; of the double buffer pages\r
-       _WaitingPageOffs                 dw 0\r
-\r
-       _TopClip                 dw 0   ; Clipping Rectangle\r
-       _BottomClip              dw 0   ;\r
-       _LeftClip                dw 0   ; Left/Right coordinates in bytes\r
-       _RightClip               dw 0   ;\r
-       _PhysicalStartByteX      dw 0   ; X byte coord of physical screen\r
-                                       ; relative to virtual virtual screen\r
-       _PhysicalStartPixelX     dw 0   ; X pixel coord of physical screen\r
-                                       ; relative to virtual screen\r
-       _PhysicalStartY          dw 0   ; Y pixel coord of physical screen\r
-                                       ; relative to virtual screen\r
-\r
-; NEW\r
-       _VsyncHandlerActive     dw      0\r
-       _MouseRefreshFlag       dw      0\r
-       _MouseVsyncHandler      dd      0\r
-       _StartAddressFlag       dw      0\r
-       _WaitingStartLow        dw      0\r
-       _WaitingStartHigh       dw      0\r
-       _WaitingPelPan          dw      0\r
-       _VsyncPaletteStart      dw      0\r
-       _VsyncPaletteCount      dw      0\r
-       _VsyncPaletteBuffer     label  byte\r
-                               db  768  dup(?)\r
-\r
-\r
-PARAMS_END label byte\r
-\r
-PARAM_COUNT equ ($-PARAMS)\r
-\r
-\r
-; Index/data pairs for CRT Controller registers that differ between\r
-; mode 13h and mode X.\r
-\r
-       ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively\r
-       PelPanMask              db      000h,002h,004h,006h\r
-\r
-DoubleScanFlag db ?     ; Flag to indicate double scanned mode\r
-\r
-       .code\r
-\r
-;-------------------------------------------------------------------------\r
-; Local Logical Screen Width setting function\r
-; cx = Requitrd Logical Width\r
-;\r
-; WARNING: no registers are preserved\r
-\r
-SetLogicalScrWidth proc\r
-       mov   dx,CRTC_INDEX\r
-       mov   al,CRTC_OFFSET\r
-       out   dx,al\r
-       inc   dx\r
-\r
-       mov   ax,cx\r
-       cmp   ax,[_ScrnPhysicalPixelWidth]; Is logical width >= physical width\r
-       jge   @@ValidLogicalWidth          ; yes - continue\r
-       mov   ax,bx                        ; no - set logical width = physical\r
-\r
-@@ValidLogicalWidth:\r
-       shr   ax,3\r
-       out   dx,al\r
-\r
-       ; The EXACT logical pixel width may not have been possible since\r
-       ; it should be divisible by 8. Round down to the closest possible\r
-       ; width and update the status variables\r
-\r
-       shl   ax,1\r
-       mov   bx,ax\r
-       mov   [_ScrnLogicalByteWidth],ax  ; Store the byte width of virtual\r
-       mov   [_RightClip],ax             ; Set default Right clip column\r
-                                         ; screen\r
-       sub   ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position\r
-       shl   ax,2                        ; of physical screen in virtual\r
-       mov   [_MaxScrollX],ax            ; screen in pixels\r
-       mov   ax,bx                       ; set ax to byte width of virt scrn\r
-       shl   ax,2                        ; convert to pixels\r
-       mov   [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width\r
-       mov   cx,ax                       ; save ax (return value)\r
-\r
-       ; calculate no. non split screen rows in video ram\r
-\r
-       mov   ax,0ffffh                ; cx = Maximum video ram offset\r
-       sub   dx,dx                    ; DX:AX is divide operand,  set DX = 0\r
-       div   bx                       ; divide ax by ScrnLogicalByteWidth\r
-       mov   [_ScrnLogicalHeight],ax  ; Save Screen Logical Height\r
-       mov   [_BottomClip],ax         ; Set default bottom clip row\r
-       sub   ax,[_ScrnPhysicalHeight] ; Update the maximum Y position of\r
-       mov   [_MaxScrollY],ax         ; Physical screen in logical screen\r
-       mov   ax,cx                    ; restore ax (return value)\r
-\r
-       ; calculate initial NonVisual\r
-       mov  ax,[_ScrnLogicalByteWidth]\r
-       mul  [_ScrnPhysicalHeight]\r
-       mov  [_NonVisual_Offs],ax\r
-\r
-@@Done: ret\r
-SetLogicalScrWidth endp\r
-\r
-clear_vram proc\r
-               push  di\r
-       mov   dx,SC_INDEX\r
-       mov   ax,0f02h\r
-       out   dx,ax               ; enable writes to all four planes\r
-       mov   ax,SCREEN_SEG       ; now clear all display memory, 8 pixels\r
-       mov   es,ax               ; at a time\r
-       sub   di,di               ; point ES:DI to display memory\r
-\r
-       WaitVsyncEnd\r
-\r
-       sub   ax,ax               ; clear to zero-value pixels\r
-       mov   cx,0FFFFh           ; # of words in display memory\r
-       rep   stosw               ; clear all of display memory\r
-               pop   di\r
-       ret\r
-clear_vram endp\r
-\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X graphics mode set with a virtual screen\r
-;   logical screen width.\r
-; C near-callable as:\r
-;\r
-;    int x_set_mode(unsigned int mode,unsigned int WidthInPixels);\r
-;\r
-; returns the actual width of the allocated virtual screen in pixels\r
-; if a valid mode was selected otherwise returns -1\r
-;\r
-; Saves virtual screen pixel width in _ScrnLogicalPixelWidth.\r
-; Saves virtual screen byte  width in _ScrnLogicalByteWidth.\r
-; Physical screen dimensions are set in _ScrnPhysicalPixelWidth,\r
-; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight\r
-;\r
-;\r
-; Modes:  0  = 320 x 200  (256 color)  NOTE: Some of these modes require\r
-;         1  = 320 x 240  (256 color)     vertical size adjustment.\r
-;         2  = 360 x 200  (256 color)\r
-;         3  = 360 x 240  (256 color)\r
-;         4  = 320 x 400  (256 color)\r
-;         5  = 320 x 480  (256 color)\r
-;         6  = 360 x 200  (256 color)\r
-;         7  = 360 x 480  (256 color)\r
-;         8  = 360 x 360  (256 color)\r
-;         9  = 376 x 308  (256 color)\r
-;         10 = 376 x 564  (256 color)\r
-;\r
-; Written by Themie Gouthas,\r
-; parts adapted from M. Abrash code.\r
-;------------------------------------------------------------------------\r
-_x_set_mode proc\r
-       ARG   mode:word,logicalscrwidth:word\r
-       push  bp      ;preserve caller's stack frame\r
-       mov   bp,sp\r
-\r
-       push  si      ;preserve C register vars\r
-       push  di      ; (don't count on BIOS preserving anything)\r
-\r
-       cld\r
-       mov   ax,ds\r
-       mov   es,ax\r
-       mov   di,offset PARAMS\r
-       xor   ax,ax\r
-       mov   cx,PARAM_COUNT\r
-       rep   stosb\r
-\r
-       mov   cx,[mode]\r
-       cmp   cx,LAST_X_MODE        ; have we selected a valid mode\r
-       jle   @@ValidMode           ; Yes !\r
-\r
-       mov   [_InGraphics],FALSE   ; No return -1\r
-       mov   ax,-1\r
-       pop   di\r
-       pop   si\r
-       pop   bp\r
-       ret\r
-\r
-@@ValidMode:\r
-\r
-       mov   [_CurrXMode],cx\r
-       mov   [_InGraphics],TRUE\r
-\r
-       xor   al,al\r
-       cmp   cx,3\r
-       jg    @@SetDoubleScanFlag\r
-       mov   al,TRUE\r
-@@SetDoubleScanFlag:\r
-       mov   [DoubleScanFlag],al\r
-       push  cx                    ; some bios's dont preserve cx\r
-\r
-       call  clear_vram\r
-\r
-       mov   ax,13h                ; let the BIOS set standard 256-color\r
-       int   10h                   ;  mode (320x200 linear)\r
-\r
-\r
-       pop   cx\r
-\r
-       mov   dx,SC_INDEX\r
-       mov   ax,0604h\r
-       out   dx,ax                 ; disable chain4 mode\r
-       mov   ax,0100h\r
-       out   dx,ax                 ; synchronous reset while setting Misc\r
-                                   ;  Output for safety, even though clock\r
-                                   ;  unchanged\r
-\r
-       mov   bx,offset ModeTable\r
-       shl   cx,1\r
-       add   bx,cx\r
-       mov   si, word ptr [bx]\r
-       lodsb\r
-\r
-       or    al,al\r
-       jz    @@DontSetDot\r
-       mov   dx,MISC_OUTPUT\r
-       out   dx,al               ; select the dot clock and Horiz\r
-                                 ;  scanning rate\r
-@@DontSetDot:\r
-       mov   dx,SC_INDEX\r
-       mov   ax,0300h\r
-       out   dx,ax               ; undo reset (restart sequencer)\r
-\r
-\r
-       mov   dx,CRTC_INDEX       ; reprogram the CRT Controller\r
-       mov   al,11h              ; VSync End reg contains register write\r
-       out   dx,al               ; protect bit\r
-       inc   dx                  ; CRT Controller Data register\r
-       in    al,dx               ; get current VSync End register setting\r
-       and   al,07fh             ; remove write protect on various\r
-       out   dx,al               ; CRTC registers\r
-       dec   dx                  ; CRT Controller Index\r
-       cld\r
-       xor   cx,cx\r
-       lodsb\r
-       mov   cl,al\r
-\r
-@@SetCRTParmsLoop:\r
-       lodsw                     ; get the next CRT Index/Data pair\r
-       out   dx,ax               ; set the next CRT Index/Data pair\r
-       loop  @@SetCRTParmsLoop\r
-\r
-       mov   dx,SC_INDEX\r
-       mov   ax,0f02h\r
-       out   dx,ax               ; enable writes to all four planes\r
-       mov   ax,SCREEN_SEG       ; now clear all display memory, 8 pixels\r
-       mov   es,ax               ; at a time\r
-       sub   di,di               ; point ES:DI to display memory\r
-       sub   ax,ax               ; clear to zero-value pixels\r
-       mov   cx,8000h            ; # of words in display memory\r
-       rep   stosw               ; clear all of display memory\r
-\r
-       ;  Set pysical screen dimensions\r
-\r
-       lodsw                               ; Load scrn pixel width\r
-       mov   [_ScrnPhysicalPixelWidth],ax  ;  from tweak table and store\r
-       mov   [_SplitScrnScanLine],ax       ; No splitscrn ==\r
-                                           ; splitscrn=PhysicalscrnHeight\r
-       mov   bx,ax                         ; Copy width for later use\r
-       shr   ax,2                          ; Convert to byte width\r
-       mov   [_ScrnPhysicalByteWidth],ax   ; Store for later use\r
-       lodsw                               ; Load Screen Phys. Height\r
-       mov   [_ScrnPhysicalHeight],ax      ; Store for later use\r
-\r
-\r
-       ;  Mode X is set, now set the required logical page width.\r
-\r
-       mov     cx,[logicalscrwidth]\r
-\r
-       call    SetLogicalScrWidth\r
-\r
-       pop     di      ;restore C register vars\r
-       pop     si\r
-       pop     bp      ;restore caller's stack frame\r
-       ret\r
-_x_set_mode endp\r
-\r
-;----------------------------------------------------------------------\r
-; Mode X (256 color mode) set default access video plane\r
-;\r
-; C near-callable as:\r
-;    void x_select_default_plane(unsigned char plane);\r
-;\r
-; Enables Read/Write access to a plane using general memory access\r
-; methods\r
-;\r
-; Written by Themie Gouthas\r
-;----------------------------------------------------------------------\r
-_x_select_default_plane proc\r
-ARG Plane:byte\r
-       push bp\r
-       mov  bp,sp       ; set up stack frame\r
-       mov  cl,byte ptr [Plane]\r
-\r
-       ; SELECT WRITE PLANE\r
-       and  cl,011b              ;CL = plane\r
-       mov  ax,0100h + MAP_MASK  ;AL = index in SC of Map Mask reg\r
-       shl  ah,cl                ;set only the bit for the required\r
-                                 ; plane to 1\r
-       mov  dx,SC_INDEX          ;set the Map Mask to enable only the\r
-       out  dx,ax                ; pixel's plane\r
-\r
-       ; SELECT READ PLANE\r
-       mov  ah,cl                ;AH = plane\r
-       mov  al,READ_MAP          ;AL = index in GC of the Read Map reg\r
-       mov  dx,GC_INDEX          ;set the Read Map to read the pixel's\r
-       out  dx,ax                ; plane\r
-\r
-       pop  bp\r
-       ret\r
-_x_select_default_plane endp\r
-\r
-\r
-;----------------------------------------------------------------------\r
-; Mode X (256 color mode) Set Mode X split screen starting row\r
-; The split screen resides on the bottom half of the screen and has a\r
-; starting address of A000:0000\r
-;\r
-; C near-callable as:\r
-;    void x_set_splitscreen(unsigned int line);\r
-;\r
-; Updates _Page0_Offs to reflect the existence of the split screen region\r
-; ie _MainScrnOffset is set to the offset of the first pixel beyond the split\r
-; screen region\r
-;\r
-; Written by Themie Gouthas\r
-;----------------------------------------------------------------------\r
-\r
-_x_set_splitscreen proc\r
-       ARG Line:word\r
-       push bp\r
-       mov  bp,sp       ; set up stack frame\r
-       push si\r
-\r
-       xor  si,si       ; si=0 -> x virtual page start coord\r
-\r
-       cmp  [_DoubleBufferActive],0\r
-       jne   @@error\r
-\r
-       cmp  [_SplitScrnActive],0\r
-       je   @@NotPreviouslyCalled\r
-\r
-@@error:\r
-       mov  [_ErrorValue],ERROR\r
-       pop  si\r
-       pop  bp          ; Return if previously called\r
-       ret\r
-\r
-@@NotPreviouslyCalled:\r
-\r
-       ; Turn on split screen pal pen suppression, so the split screen\r
-       ; wo'nt be subject to pel panning as is the non split screen portion.\r
-\r
-       mov  dx,INPUT_STATUS_0\r
-       in   al,dx                  ; Reset the AC Index/Data toggle to\r
-                                       ;  index state\r
-       mov  al,AC_MODE_CONTROL+20h ; Bit 5 set to prevent screen blanking\r
-       mov  dx,AC_INDEX            ; Point AC to Index/Data register\r
-       out  dx,al\r
-       inc  dx                     ; Point to AC Data reg (for reads only)\r
-       in   al,dx                  ; Get the current AC Mode Control reg\r
-       or   al,20h                 ; Enable split scrn Pel panning suppress.\r
-       dec  dx                     ; Point to AC Index/Data reg (for writes only)\r
-       out  dx,al                  ; Write the new AC Mode Control setting\r
-                                       ;  with split screen pel panning\r
-                                       ;  suppression turned on\r
-\r
-       mov  [_PhysicalStartByteX],ax   ; Set the Phisical screen start\r
-       mov  [_PhysicalStartPixelX],ax  ; offset within virtual screen\r
-       mov  [_PhysicalStartY],ax\r
-       mov  [_SplitScrnActive],TRUE\r
-       mov  ax,[Line]\r
-       jns  @@NotNeg    ; Check that Split Scrn start scan line is +ve\r
-\r
-       mov  ax,0        ; Since -ve set to 0\r
-\r
-@@NotNeg:\r
-       mov  [_SplitScrnScanLine],ax   ; save the scanline\r
-\r
-\r
-\r
-       or    [DoubleScanFlag],0\r
-       jz    @@NotDoubleScanned\r
-       shl   ax,1\r
-       dec   ax\r
-@@NotDoubleScanned:\r
-       ;mov  cl,[DoubleScanFlag]\r
-       ;shl  ax,cl            ; Mode X 200 and 240 line modes are actually\r
-                                 ; 400 and 480 lines that are double scanned\r
-                                 ; so for start scanline multiply required ModeX\r
-                                 ; scan line by 2 if its a double scanned mode\r
-\r
-\r
-       mov  bx,ax            ; save the scanline\r
-\r
-\r
-       WaitVsyncStart        ; wait for vertical retrace\r
-\r
-       cli                   ; Dont allow register setting to be interrupted\r
-       mov  dx,CRTC_INDEX\r
-       mov  ah,bl\r
-       mov  al,LINE_COMPARE\r
-       out  dx,ax            ; Bits 7-0 of the split screen scan line\r
-\r
-       mov  ah,bh\r
-       and  ah,1\r
-       shl  ah,4\r
-       mov  al,OVERFLOW     ; Bit 4 of overflow register = Bit 8 of split\r
-       out  dx,al           ; screen scan line,\r
-       inc  dx              ; So using readability of VGA registers\r
-       in   al,dx           ; Read the OVERFLOW register, and set the\r
-       and  al, not 10h     ; bit corresponding to Bit 8 (above)\r
-       or   al,ah\r
-       out  dx,al\r
-\r
-       dec  dx\r
-       mov  ah,bh\r
-       and  ah,2\r
-       ror  ah,3\r
-       mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
-       out  dx,al             ; Bit 9 of split screen scan line\r
-       inc  dx                ; As we did before, update the apropriate\r
-       in   al,dx             ; bit without disturbing the rest\r
-       and  al, not 40h\r
-       or   al,ah\r
-       out  dx,al\r
-       sti                    ; Registers are set, so interrupts are safe\r
-\r
-       mov  ax,[_ScrnPhysicalHeight]     ; Determine where the first byte\r
-       sub  ax,[_SplitScrnScanLine]      ; of the non split screen video ram\r
-       mov  [_SplitScrnVisibleHeight],ax ; starts and store it for reference\r
-\r
-       mov  bx,[_ScrnLogicalByteWidth]\r
-       mul  bx\r
-       mov  [_Page0_Offs],ax\r
-       mov  [_Page1_Offs],ax\r
-       mov  [_Page2_Offs],ax\r
-\r
-       ; calculate no. non split screen rows in video ram\r
-       mov  cx,0ffffh             ; cx = Maximum video ram offset\r
-       sub  cx,ax                 ; cx = cx - _Page0_Offs\r
-       xchg cx,ax                 ; swap cx and ax\r
-       sub  dx,dx                 ; DX:AX is divide operand,  set DX = 0\r
-       div  bx                    ; divide ax (prev cx) by\r
-                                  ; ScrnLogicalByteWidth\r
-\r
-       mov  [_ScrnLogicalHeight],ax     ; Save Screen Logical Height\r
-       cmp   ax,[_BottomClip]\r
-       jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary\r
-       mov   [_BottomClip],ax\r
-@@BottomClipOK:\r
-       sub  ax,[_SplitScrnScanLine]     ; Update the maximum Y position of\r
-       mov  [_MaxScrollY],ax            ; Physical screen in logical screen\r
-\r
-       xchg cx,ax                       ; restore original ax (MainScrnOfs)\r
-       mov  bh,al                       ; Set the visible screen start address\r
-       mov  ch,ah                       ; to the top left corner of the virtual\r
-       jmp  StartAddrEntry              ; screen\r
-_x_set_splitscreen      endp\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X (256 color mode) Page flip primer\r
-; No clipping is performed.\r
-; C near-callable as:\r
-;\r
-;    void x_page_flip(unsigned int x, unsigned int y);\r
-;\r
-; Swaps visible and hidden page offsets and then executes the SetStartAddr\r
-; to achieve a page flip.\r
-;\r
-; SEE x_set_start_addr below\r
-;\r
-; Written by Themie Gouthas\r
-;------------------------------------------------------------------------\r
-\r
-_x_page_flip proc\r
-       ARG x:word,y:word\r
-       push  bp                  ;preserve caller's stack frame\r
-       mov   bp,sp               ;point to local stack frame\r
-       push  si\r
-\r
-       mov  si,[x]\r
-       mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment\r
-       mov  cx,[y]\r
-       mul  cx                             ; for Y\r
-       cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?\r
-       je   @@DoubleBuffer\r
-       cmp  [_TrippleBufferActive],TRUE\r
-       jne   PageFlipEntry1\r
-\r
-; TrippleBuffer\r
-       mov  bx,[_HiddenPageOffs]\r
-       xchg bx,[_VisiblePageOffs]\r
-       xchg bx,[_WaitingPageOffs]\r
-       mov  [_HiddenPageOffs],bx\r
-       mov  bx,[_VisiblePageIdx]\r
-       inc  bx\r
-       cmp  bx,3\r
-       jne  @@IdxOk\r
-       xor  bx,bx\r
-@@IdxOk:\r
-       mov  [_VisiblePageIdx],bx\r
-       jmp  short PageFlipEntry2\r
-@@DoubleBuffer:\r
-       mov  bx,[_HiddenPageOffs]\r
-       xchg bx,[_VisiblePageOffs]          ; Swap the Page Offsete\r
-       xchg [_HiddenPageOffs],bx\r
-       xor  [_VisiblePageIdx],01h          ; Set the Visible page index\r
-       jmp  short PageFlipEntry2\r
-_x_page_flip endp\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X (256 color mode) Set Mode X non split screen start address\r
-;   of logical screen.\r
-; C near-callable as:\r
-;\r
-;    void x_set_start_addr(unsigned int x, unsigned int y);\r
-;\r
-; Params: StartOffset is offset of first byte of logical screen ram\r
-;           (Useful if you want to double buffer by splitting your non\r
-;            split screen video ram into 2 pages)\r
-;        X,Y coordinates of the top left hand corner of the physical screen\r
-;           within the logical screen\r
-;           X must not exceed (Logical screen width - Physical screen width)\r
-;           Y must not exceed (Logical screen height - Physical screen height)\r
-;\r
-;\r
-; Written by Themie Gouthas,\r
-; Parts addapted from M. Abrash code published in DDJ Mag.\r
-;------------------------------------------------------------------------\r
-_x_set_start_addr proc\r
-       ARG x:word,y:word\r
-       push bp\r
-       mov  bp,sp\r
-       push si\r
-\r
-       mov  si,[x]\r
-       mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment\r
-       mov  cx,[y]                         ; for Y\r
-       mul  cx\r
-       cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?\r
-       je   @@PageResolution\r
-       cmp  [_TrippleBufferActive],TRUE\r
-       je   @@PageResolution\r
-PageFlipEntry1:\r
-       add  ax,[_Page0_Offs]               ; no - add page 0 offset\r
-       jmp  short @@AddColumn\r
-\r
-PageFlipEntry2:\r
-\r
-       mov  [_PhysicalStartPixelX],si\r
-       mov  [_PhysicalStartY],cx\r
-\r
-@@PageResolution:\r
-       add  ax,[_VisiblePageOffs]          ; Add visible page offset\r
-\r
-@@AddColumn:\r
-       mov  cx,si\r
-       shr  cx,2\r
-       mov  [_PhysicalStartByteX],cx\r
-       add  ax,cx                          ; add the column offset for X\r
-       mov  bh,al                          ; setup CRTC start addr regs and\r
-                                               ; values in word registers for\r
-       mov  ch,ah                          ; fast word outs\r
-\r
-StartAddrEntry:\r
-       mov  bl,ADDR_LOW\r
-       mov  cl,ADDR_HIGH\r
-       and  si,0003h             ; select pel pan register value for the\r
-       mov  ah,PelPanMask[si]    ; required x coordinate\r
-       mov  al,PEL_PANNING+20h\r
-       mov  si,ax\r
-\r
-       cmp  [_VsyncHandlerActive],TRUE\r
-       jne   @@NoVsyncHandler\r
-; NEW STUFF\r
-@@WaitLast:\r
-       cmp   [_StartAddressFlag],0\r
-       jne   @@WaitLast\r
-       cli\r
-       mov  [_WaitingStartLow],bx\r
-       mov  [_WaitingStartHigh],cx\r
-       mov  [_WaitingPelPan],si\r
-       mov  [_StartAddressFlag],1\r
-       sti\r
-       jmp  short @@Return\r
-\r
-@@NoVsyncHandler:\r
-       mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse\r
-@@WaitDE:\r
-       in   al,dx\r
-       test al,01h\r
-       jnz  @@WaitDE            ;display enable is active low (0 = active)\r
-\r
-       mov  dx,CRTC_INDEX\r
-       mov  ax,bx\r
-       cli\r
-       out  dx,ax               ;start address low\r
-       mov  ax,cx\r
-       out  dx,ax               ;start address high\r
-       sti\r
-\r
-; Now wait for vertical sync, so the other page will be invisible when\r
-; we start drawing to it.\r
-       mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse\r
-@@WaitVS:\r
-       in   al,dx\r
-       test al,08h\r
-       jz @@WaitVS           ;display enable is active low (0 = active)\r
-\r
-\r
-       mov  dx,AC_INDEX\r
-       mov  ax,si                ; Point the attribute controller to pel pan\r
-       cli\r
-       out  dx,al                ; reg. Bit 5 also set to prevent blanking\r
-       mov  al,ah\r
-       out  dx,al                ; load new Pel Pan setting.\r
-       sti\r
-\r
-@@Return:\r
-       mov  [_ErrorValue],OK\r
-       pop  si\r
-       pop  bp\r
-       ret\r
-_x_set_start_addr  endp\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X (256 color mode) Mode X split screen hide\r
-; C near-callable as:\r
-;\r
-;    void x_hide_splitscreen()\r
-;\r
-; Hides an existing split screen by setting its starting scan line to\r
-; the last physical screen scan line\r
-;\r
-; WARNING: Only to be used if SplitScrnLine has been previously called\r
-; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for\r
-;          the initial split screen is reserved and the size limitations\r
-;          of these modes means any change in the split screen scan line\r
-;          will encroach on the split screen ram\r
-;\r
-; Written by Themie Gouthas\r
-;------------------------------------------------------------------------\r
-\r
-_x_hide_splitscreen proc\r
-       push bp\r
-       mov  bp,sp\r
-\r
-       cmp  [_SplitScrnActive],TRUE\r
-       je   @@SplitScreenEnabled\r
-\r
-@@error:\r
-       mov  [_ErrorValue],ERROR\r
-       pop  bp\r
-       ret\r
-\r
-@@SplitScreenEnabled:\r
-       cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
-       jg   @@error\r
-       mov  bx,[_ScrnPhysicalHeight]\r
-\r
-       mov  ax,[_ScrnLogicalHeight]\r
-       sub  ax,bx\r
-       mov  [_MaxScrollY],ax\r
-       xor  ax,ax\r
-       mov  [_SplitScrnVisibleHeight],ax\r
-\r
-       or    [DoubleScanFlag],0\r
-       jz    @@NotDoubleScanned\r
-       shl   bx,1\r
-       dec   bx\r
-@@NotDoubleScanned:\r
-       ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes\r
-       ;shl  bx,cl\r
-\r
-       WaitVsyncStart               ; wait for vertical retrace\r
-\r
-       cli                 ; Dont allow register setting to be interrupted\r
-       mov  dx,CRTC_INDEX\r
-       mov  ah,bl\r
-       mov  al,LINE_COMPARE\r
-       out  dx,ax          ; Bits 7-0 of the split screen scan line\r
-\r
-       mov  ah,bh\r
-       and  ah,1\r
-       shl  ah,4\r
-       mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split\r
-       out  dx,al        ; screen scan line,\r
-       inc  dx           ; So using readability of VGA registers\r
-       in   al,dx        ; Read the OVERFLOW register, and set the\r
-       and  al, not 10h  ; bit corresponding to Bit 8 (above)\r
-       or   al,ah\r
-       out  dx,al\r
-\r
-       dec  dx\r
-       mov  ah,bh\r
-       and  ah,2\r
-       ror  ah,3\r
-       mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
-       out  dx,al             ; Bit 9 of split screen scan line\r
-       inc  dx                ; As we did before, update the apropriate\r
-       in   al,dx             ; bit without disturbing the rest\r
-       and  al, not 40h\r
-       or   al,ah\r
-       out  dx,al\r
-       sti                  ; Registers are set, so interrupts are safe\r
-\r
-@@done:\r
-\r
-       mov  [_ErrorValue],OK\r
-       pop  bp\r
-       ret\r
-_x_hide_splitscreen endp\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X (256 color mode) Mode X split screen show\r
-; C near-callable as:\r
-;\r
-;    void x_show_splitscreen()\r
-;\r
-; Restores split screen start scan line to the initial split screen\r
-; starting scan line as set by SplitScrnLine.\r
-;\r
-; WARNING: Only to be used if SplitScrnLine has been previously called\r
-; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for\r
-;          the initial split screen is reserved and the size limitations\r
-;          of these modes means any change in the split screen scan line\r
-;          will encroach on the split screen ram\r
-;          Update: Now disabled for these modes\r
-;\r
-; Written by Themie Gouthas\r
-;------------------------------------------------------------------------\r
-\r
-\r
-_x_show_splitscreen proc\r
-       push bp\r
-       mov  bp,sp\r
-\r
-       cmp  [_SplitScrnActive],TRUE\r
-       je   @@SplitScreenEnabled\r
-\r
-@@error:\r
-       mov  [_ErrorValue],ERROR\r
-       pop  bp\r
-       ret\r
-\r
-@@SplitScreenEnabled:\r
-       cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
-       jg   @@error\r
-\r
-       mov  bx,[_SplitScrnScanLine]\r
-       mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
-       sub  ax,bx\r
-       mov  [_MaxScrollY],ax\r
-\r
-       mov  ax,[_ScrnPhysicalHeight]\r
-       sub  ax,bx\r
-       mov  [_SplitScrnVisibleHeight],ax\r
-\r
-       or    [DoubleScanFlag],0\r
-       jz    @@NotDoubleScanned\r
-       shl   bx,1\r
-       dec   bx\r
-@@NotDoubleScanned:\r
-       ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes\r
-       ;shl  bx,cl\r
-       WaitVsyncStart               ; wait for vertical retrace\r
-\r
-       cli                          ; Dont allow register setting to be interrupted\r
-       mov  dx,CRTC_INDEX\r
-       mov  ah,bl\r
-       mov  al,LINE_COMPARE\r
-       out  dx,ax                  ; Bits 7-0 of the split screen scan line\r
-\r
-       mov  ah,bh\r
-       and  ah,1\r
-       shl  ah,4\r
-       mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split\r
-       out  dx,al        ; screen scan line,\r
-       inc  dx           ; So using readability of VGA registers\r
-       in   al,dx        ; Read the OVERFLOW register, and set the\r
-       and  al, not 10h  ; bit corresponding to Bit 8 (above)\r
-       or   al,ah\r
-       out  dx,al\r
-\r
-       dec  dx\r
-       mov  ah,bh\r
-       and  ah,2\r
-       ror  ah,3\r
-       mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
-       out  dx,al             ; Bit 9 of split screen scan line\r
-       inc  dx                ; As we did before, update the apropriate\r
-       in   al,dx             ; bit without disturbing the rest\r
-       and  al, not 40h\r
-       or   al,ah\r
-       out  dx,al\r
-       sti                  ; Registers are set, so interrupts are safe\r
-\r
-@@Done:\r
-       mov  [_ErrorValue],0\r
-       pop  bp\r
-       ret\r
-_x_show_splitscreen endp\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X (256 color mode) Modify Mode X split screen starting scan line\r
-; C near-callable as:\r
-;\r
-;    void x_adjust_splitscreen(unsigned int ScanLine)\r
-;\r
-; Sets the split screen start scan line to a new scan line. Valid scan lines\r
-; are between the initial split screen starting scan line and the last\r
-; physical screen scan line.\r
-;\r
-; WARNING: Only to be used if SplitScrnLine has been previously called\r
-; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for\r
-;          the initial split screen is reserved and the size limitations\r
-;          of these modes means any change in the split screen scan line\r
-;          will encroach on the split screen ram\r
-;          Update: Now disabled for these modes\r
-;\r
-;\r
-; Written by Themie Gouthas\r
-;------------------------------------------------------------------------\r
-\r
-\r
-_x_adjust_splitscreen proc\r
-       ARG   ScanLine\r
-       push bp\r
-       mov  bp,sp\r
-\r
-       cmp  [_SplitScrnActive],TRUE\r
-       je   @@SplitScreenEnabled\r
-\r
-@@error:\r
-       mov  [_ErrorValue],ERROR\r
-       pop  bp\r
-       ret\r
-\r
-@@SplitScreenEnabled:\r
-       cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
-       jg   @@error\r
-       mov  bx,[ScanLine]            ; Is the required starting scan line\r
-       cmp  bx,[_SplitScrnScanLine]  ; valid ?\r
-       js   @@Done                   ; No - Then do nothing\r
-\r
-@@ValidScanLine:\r
-\r
-       mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
-       sub  ax,bx\r
-       mov  [_MaxScrollY],ax\r
-\r
-       mov  ax,[_ScrnPhysicalHeight]\r
-       sub  ax,bx\r
-       mov  [_SplitScrnVisibleHeight],ax\r
-\r
-       or    [DoubleScanFlag],0\r
-       jz    @@NotDoubleScanned\r
-       shl   bx,1\r
-       dec   bx\r
-@@NotDoubleScanned:\r
-       ;mov  cl,[DoubleScanFlag]   ; Compensate for double scanned modes\r
-       ;shl  bx,cl\r
-\r
-       WaitVsyncStart      ; wait for vertical retrace\r
-\r
-       cli                 ; Dont allow register setting to be interrupted\r
-\r
-       mov  dx,CRTC_INDEX\r
-       mov  ah,bl\r
-       mov  al,LINE_COMPARE\r
-       out  dx,ax          ; Bits 7-0 of the split screen scan line\r
-\r
-       mov  ah,bh\r
-       and  ah,1\r
-       shl  ah,4\r
-       mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split\r
-       out  dx,al        ; screen scan line,\r
-       inc  dx           ; So using readability of VGA registers\r
-       in   al,dx        ; Read the OVERFLOW register, and set the\r
-       and  al, not 10h  ; bit corresponding to Bit 8 (above)\r
-       or   al,ah\r
-       out  dx,al\r
-\r
-       dec  dx\r
-       mov  ah,bh\r
-       and  ah,2\r
-       ror  ah,3\r
-       mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =\r
-       out  dx,al             ; Bit 9 of split screen scan line\r
-       inc  dx                ; As we did before, update the apropriate\r
-       in   al,dx             ; bit without disturbing the rest\r
-       and  al, not 40h\r
-       or   al,ah\r
-       out  dx,al\r
-       sti                    ; Registers are set, so interrupts are safe\r
-@@Done:\r
-       mov  [_ErrorValue],OK\r
-       pop   bp\r
-       ret\r
-_x_adjust_splitscreen endp\r
-\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X (256 color mode) Enable DoubleBuffering on non split screen area\r
-; C near-callable as:\r
-;\r
-;    int x_set_doublebuffer(unsigned int PageHeight);\r
-;\r
-; Params: PageHeight is the height of the virtual screen to double buffer\r
-;         Returns the closest possible height to the specified.\r
-;\r
-; Sets up two double buffering virtual pages\r
-; GLOBAL variables set:\r
-;\r
-;      _Page1_Offs              Offset of second virtual page\r
-;      _NonVisual_Offs          Offset of first non visible video ram byte\r
-;      _DoubleBufferActive      Flag\r
-;      _PageAddrTable           Table of Double buffering pages start offsets\r
-;      _ScrnLogicalHeight       Logical height of the double buffering pages\r
-;\r
-;\r
-; Written by Themie Gouthas\r
-;------------------------------------------------------------------------\r
-\r
-\r
-_x_set_doublebuffer proc\r
-          ARG PageHeight:word\r
-          push  bp\r
-          mov   bp,sp\r
-\r
-          cmp   [_DoubleBufferActive],0\r
-          je    @@OkToContinue\r
-@error:\r
-          mov   [_ErrorValue],ERROR\r
-          pop   bp\r
-          ret\r
-\r
-@@OkToContinue:\r
-          mov   [_VisiblePageIdx],0     ; Set visible Page to 0\r
-          mov   ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to\r
-          shr   ax,1                    ;   _ScrnLogicalHeight / 2\r
-\r
-          mov   bx,[PageHeight]         ; Is the require D.B. Page Height\r
-          cmp   ax,bx                   ;  > the Maximum  D.B. Page Height ?\r
-\r
-          js    @@InvalidHeight         ; no  - jump\r
-          mov   ax,bx                   ; yes - Set the D.B. Page height to\r
-                                        ;       to the maximum allowed.\r
-\r
-@@InvalidHeight:\r
-          mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to\r
-                                       ;  reflect the height of a D.B. page\r
-          cmp   ax,[_BottomClip]\r
-          jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary\r
-          mov   [_BottomClip],ax\r
-@@BottomClipOK:\r
-          push  ax\r
-          mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second\r
-          mov   cx,ax                      ;  D.B. Page in video ram\r
-          mov   bx,[_Page0_Offs]\r
-          mov   [_VisiblePageOffs],bx\r
-\r
-          add   ax,bx\r
-          mov   [_Page1_Offs],ax           ; Save it\r
-          mov   [_HiddenPageOffs],ax\r
-\r
-          add   ax,cx                      ; Calculate the offset of first byte\r
-          mov   [_NonVisual_Offs],ax       ;  beyond the D.B. pages and save it\r
-          mov   [_DoubleBufferActive],TRUE ; Set flag indicating D.B'ing mode on\r
-\r
-          pop   ax\r
-          sub   ax,[_ScrnPhysicalHeight]\r
-          add   ax,[_SplitScrnVisibleHeight]\r
-          mov   [_MaxScrollY],ax\r
-\r
-          mov   ax,dx                      ; return the D.B. pages' height\r
-          mov   [_ErrorValue],OK\r
-          pop   bp\r
-          ret\r
-_x_set_doublebuffer endp\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Mode X (256 color mode) Enable TrippleBuffering on non split screen area\r
-; C near-callable as:\r
-;\r
-;    int x_set_tripplebuffer(unsigned int PageHeight);\r
-;\r
-; Params: PageHeight is the height of the virtual screen to tripple buffer\r
-;         Returns the closest possible height to the specified.\r
-;\r
-; Sets up two tripple buffering virtual pages\r
-; GLOBAL variables set:\r
-;\r
-;      _Page1_Offs              Offset of second virtual page\r
-;      _Page2_Offs              Offset of third virtual page\r
-;      _NonVisual_Offs          Offset of first non visible video ram byte\r
-;      _DoubleBufferActive      Flag\r
-;      _PageAddrTable           Table of Double buffering pages start offsets\r
-;      _ScrnLogicalHeight       Logical height of the double buffering pages\r
-;\r
-;\r
-; Almost written by Tore Bastiansen (cut & paste from _x_set_doublebuffer)\r
-;------------------------------------------------------------------------\r
-\r
-_x_set_tripplebuffer proc\r
-          ARG PageHeight:word\r
-          push  bp\r
-          mov   bp,sp\r
-\r
-          cmp   [_DoubleBufferActive],0\r
-          jne   @@Error\r
-          cmp   [_TrippleBufferActive],0\r
-          je    @@OkToContinue\r
-@@Error:\r
-          mov   [_ErrorValue],ERROR\r
-          pop   bp\r
-          ret\r
-\r
-@@OkToContinue:\r
-          mov   [_VisiblePageIdx],0     ; Set visible Page to 0\r
-          mov   ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to\r
-          mov   bx,3\r
-          xor   dx,dx\r
-          idiv  bx                      ;   _ScrnLogicalHeight / 3\r
-\r
-          mov   bx,[PageHeight]         ; Is the require T.B. Page Height\r
-          cmp   ax,bx                   ;  > the Maximum  T.B. Page Height ?\r
-\r
-          js    @@InvalidHeight         ; no  - jump\r
-          mov   ax,bx                   ; yes - Set the T.B. Page height to\r
-                                                                        ;       to the maximum allowed.\r
-\r
-@@InvalidHeight:\r
-          mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to\r
-                                                                               ;  reflect the height of a T.B. page\r
-          cmp   ax,[_BottomClip]\r
-          jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary\r
-          mov   [_BottomClip],ax\r
-@@BottomClipOK:\r
-          push  ax\r
-          mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second\r
-          mov   cx,ax                      ;  D.B. Page in video ram\r
-          mov   bx,[_Page0_Offs]\r
-          mov   [_VisiblePageOffs],bx\r
-\r
-          add   ax,bx\r
-          mov   [_Page1_Offs],ax           ; Save it\r
-          mov   [_HiddenPageOffs],ax\r
-\r
-          add   ax,cx\r
-          mov   [_Page2_Offs],ax            ; Save the other it ?\r
-          mov   [_WaitingPageOffs],ax\r
-\r
-          add   ax,cx                       ; Calculate the offset of first byte\r
-          mov   [_NonVisual_Offs],ax        ;  beyond the D.B. pages and save it\r
-          mov   [_TrippleBufferActive],TRUE ; Set flag indicating T.B'ing mode on\r
-\r
-          pop   ax\r
-          sub   ax,[_ScrnPhysicalHeight]\r
-          add   ax,[_SplitScrnVisibleHeight]\r
-          mov   [_MaxScrollY],ax\r
-\r
-          mov   ax,dx                      ; return the D.B. pages' height\r
-          mov   [_ErrorValue],OK\r
-          pop   bp\r
-          ret\r
-_x_set_tripplebuffer endp\r
-\r
-\r
-;-----------------------------------------------------------------------\r
-; Set Clipping rectangle\r
-; C callable as:\r
-;\r
-;\r
-;    int x_set_cliprect(WORD left,WORD top, WORD right, WORD bottom);\r
-;\r
-;\r
-; NOTE clipping is byte oriented. "left" and "right" are in bytes not pixels.\r
-;    Only selected functions perform any clipping at all.\r
-;\r
-; Written by Themie Gouthas\r
-;------------------------------------------------------------------------\r
-\r
-_x_set_cliprect proc\r
-ARG left:word,top:word,right:word,bottom:word\r
-       push  bp\r
-       mov   bp,sp\r
-       mov   ax,[left]\r
-       mov   bx,[right]\r
-       cmp   bx,ax\r
-       jns   @@CorrectXOrder\r
-       xchg  bx,ax\r
-@@CorrectXOrder:\r
-       mov   [_LeftClip],ax\r
-       mov   [_RightClip],bx\r
-          mov   ax,[top]\r
-       mov   bx,[bottom]\r
-       cmp   bx,ax\r
-          jns   @@CorrectYOrder\r
-       xchg  bx,ax\r
-@@CorrectYOrder:\r
-       mov   [_TopClip],ax\r
-       mov   [_BottomClip],bx\r
-       pop   bp\r
-       ret\r
-_x_set_cliprect endp\r
-\r
-\r
-;----------------------------------------------------------------------\r
-; Return to text mode\r
-;\r
-_x_text_mode proc\r
-       push  bp\r
-       call  clear_vram\r
-       mov   ax,03h        ; Restore Text Mode\r
-       int   10h\r
-\r
-       pop   bp\r
-       ret\r
-_x_text_mode endp\r
-\r
-;-----------------------------------------------------------------------\r
-; Wait for Vertical sync\r
-_x_wait_vsync proc\r
-       push  bp\r
-       WaitVsyncStart\r
-       pop   bp\r
-       ret\r
-_x_wait_vsync endp\r
-\r
-\r
-       end\r