1 ;-----------------------------------------------------------------------
\r
4 ; Initialization, panning and split screen functions for all MODE X 256
\r
11 ; ****** XLIB - Mode X graphics library ****************
\r
12 ; ****** ****************
\r
13 ; ****** Written By Themie Gouthas ****************
\r
15 ; egg@dstos3.dsto.gov.au
\r
16 ; teg@bart.dsto.gov.au
\r
19 ; 26-9-92: Pel panning code added
\r
20 ; Dates forgotten: Numerous ;^)
\r
21 ; 05-10-93: Timer synchronized vsync handling extensions
\r
22 ; and tripple buffering - Tore Jahn Bastiansen
\r
23 ; (toreba@ifi.uio.no) for the
\r
24 ;-----------------------------------------------------------------------
\r
29 _DATA SEGMENT WORD PUBLIC USE16 'DATA'
\r
33 ; Mode X CRTC register tweaks for various resolutions
\r
38 db 8 ; Number of CRTC Registers to update
\r
39 dw 05f00h ; horz total
\r
40 dw 03f01h ; horz displayed
\r
41 dw 04202h ; start horz blanking
\r
42 dw 09f03h ; end horz blanking
\r
43 dw 04c04h ; start h sync
\r
44 dw 00005h ; end h sync
\r
45 dw 00014h ; turn off dword mode
\r
46 dw 0e317h ; turn on byte mode
\r
53 db 16 ; Number of CRTC Registers to update
\r
54 dw 05f00h ; horz total
\r
55 dw 03f01h ; horz displayed
\r
56 dw 04202h ; start horz blanking
\r
57 dw 09f03h ; end horz blanking
\r
58 dw 04c04h ; start h sync
\r
59 dw 00005h ; end h sync
\r
60 dw 00d06h ; vertical total
\r
61 dw 03e07h ; overflow (bit 8 of vertical counts)
\r
62 dw 04109h ; cell height (2 to double-scan)
\r
63 dw 0ea10h ; v sync start
\r
64 dw 0ac11h ; v sync end and protect cr0-cr7
\r
65 dw 0df12h ; vertical displayed
\r
66 dw 00014h ; turn off dword mode
\r
67 dw 0e715h ; v blank start
\r
68 dw 00616h ; v blank end
\r
69 dw 0e317h ; turn on byte mode
\r
75 db 00 ; 0e3h ; dot clock
\r
76 db 02 ; Number of CRTC Registers to update
\r
77 dw 00014h ; turn off dword mode
\r
78 dw 0e317h ; turn on byte mode
\r
84 db 10 ; Number of CRTC Registers to update
\r
85 dw 00d06h ; vertical total
\r
86 dw 03e07h ; overflow (bit 8 of vertical counts)
\r
87 dw 04109h ; cell height (2 to double-scan)
\r
88 dw 0ea10h ; v sync start
\r
89 dw 0ac11h ; v sync end and protect cr0-cr7
\r
90 dw 0df12h ; vertical displayed
\r
91 dw 00014h ; turn off dword mode
\r
92 dw 0e715h ; v blank start
\r
93 dw 00616h ; v blank end
\r
94 dw 0e317h ; turn on byte mode
\r
100 db 08 ; Number of CRTC Registers to update
\r
101 dw 06b00h ; horz total
\r
102 dw 05901h ; horz displayed
\r
103 dw 05a02h ; start horz blanking
\r
104 dw 08e03h ; end horz blanking
\r
105 dw 05e04h ; start h sync
\r
106 dw 08a05h ; end h sync
\r
107 dw 00014h ; turn off dword mode
\r
108 dw 0e317h ; turn on byte mode
\r
112 X360Y240 label word
\r
113 db 0e7h ; dot clock
\r
114 db 17 ; Number of CRTC Registers to update
\r
115 dw 06b00h ; horz total
\r
116 dw 05901h ; horz displayed
\r
117 dw 05a02h ; start horz blanking
\r
118 dw 08e03h ; end horz blanking
\r
119 dw 05e04h ; start h sync
\r
120 dw 08a05h ; end h sync
\r
121 dw 00d06h ; vertical total
\r
122 dw 03e07h ; overflow (bit 8 of vertical counts)
\r
123 dw 04109h ; cell height (2 to double-scan)
\r
124 dw 0ea10h ; v sync start
\r
125 dw 0ac11h ; v sync end and protect cr0-cr7
\r
126 dw 0df12h ; vertical displayed
\r
127 dw 02d13h ; offset;
\r
128 dw 00014h ; turn off dword mode
\r
129 dw 0e715h ; v blank start
\r
130 dw 00616h ; v blank end
\r
131 dw 0e317h ; turn on byte mode
\r
135 X376Y282 label word
\r
138 dw 06e00h ; horz total
\r
139 dw 05d01h ; horz displayed
\r
140 dw 05e02h ; start horz blanking
\r
141 dw 09103h ; end horz blanking
\r
142 dw 06204h ; start h sync
\r
143 dw 08f05h ; end h sync
\r
144 dw 06206h ; vertical total
\r
145 dw 0f007h ; overflow
\r
146 dw 06109h ; cell height
\r
148 dw 03710h ; v sync start
\r
149 dw 08911h ; v sync end and protect cr0-cr7
\r
150 dw 03312h ; vertical displayed
\r
152 dw 00014h ; turn off dword mode
\r
153 dw 03c15h ; v blank start
\r
154 dw 05c16h ; v blank end
\r
155 dw 0e317h ; turn on byte mode
\r
159 X256Y400 label word
\r
160 db 0e3h ; dot clock
\r
161 db 8 ; Number of CRTC Registers to update
\r
162 dw 05f00h ; horz total
\r
163 dw 03f01h ; horz displayed
\r
164 dw 04202h ; start horz blanking
\r
165 dw 09f03h ; end horz blanking
\r
166 dw 04c04h ; start h sync
\r
167 dw 00005h ; end h sync
\r
168 dw 04009h ; cell height
\r
169 dw 00014h ; turn off dword mode
\r
170 dw 0e317h ; turn on byte mode
\r
175 X256Y480 label word
\r
176 db 0e3h ; dot clock
\r
177 db 16 ; Number of CRTC Registers to update
\r
178 dw 05f00h ; horz total
\r
179 dw 03f01h ; horz displayed
\r
180 dw 04202h ; start horz blanking
\r
181 dw 09f03h ; end horz blanking
\r
182 dw 04c04h ; start h sync
\r
183 dw 00005h ; end h sync
\r
184 dw 00d06h ; vertical total
\r
185 dw 03e07h ; overflow (bit 8 of vertical counts)
\r
186 dw 04009h ; cell height (2 to double-scan)
\r
187 dw 0ea10h ; v sync start
\r
188 dw 0ac11h ; v sync end and protect cr0-cr7
\r
189 dw 0df12h ; vertical displayed
\r
190 dw 00014h ; turn off dword mode
\r
191 dw 0e715h ; v blank start
\r
192 dw 00616h ; v blank end
\r
193 dw 0e317h ; turn on byte mode
\r
199 X320Y400 label word
\r
200 db 0e3h ; dot clock
\r
201 db 03 ; Number of CRTC Registers to update
\r
202 dw 04009h ; cell height
\r
203 dw 00014h ; turn off dword mode
\r
204 dw 0e317h ; turn on byte mode
\r
208 X320Y480 label word
\r
210 db 10 ; Number of CRTC Registers to update
\r
211 dw 00d06h ; vertical total
\r
212 dw 03e07h ; overflow (bit 8 of vertical counts)
\r
213 dw 04009h ; cell height (2 to double-scan)
\r
214 dw 0ea10h ; v sync start
\r
215 dw 0ac11h ; v sync end and protect cr0-cr7
\r
216 dw 0df12h ; vertical displayed
\r
217 dw 00014h ; turn off dword mode
\r
218 dw 0e715h ; v blank start
\r
219 dw 00616h ; v blank end
\r
220 dw 0e317h ; turn on byte mode
\r
224 X360Y400 label word
\r
225 db 0e7h ; dot clock
\r
226 db 09 ; Number of CRTC Registers to update
\r
227 dw 06b00h ; horz total
\r
228 dw 05901h ; horz displayed
\r
229 dw 05a02h ; start horz blanking
\r
230 dw 08e03h ; end horz blanking
\r
231 dw 05e04h ; start h sync
\r
232 dw 08a05h ; end h sync
\r
233 dw 04009h ; cell height
\r
234 dw 00014h ; turn off dword mode
\r
235 dw 0e317h ; turn on byte mode
\r
241 X360Y480 label word
\r
244 dw 06b00h ; horz total
\r
245 dw 05901h ; horz displayed
\r
246 dw 05a02h ; start horz blanking
\r
247 dw 08e03h ; end horz blanking
\r
248 dw 05e04h ; start h sync
\r
249 dw 08a05h ; end h sync
\r
250 dw 00d06h ; vertical total
\r
251 dw 03e07h ; overflow
\r
252 dw 04009h ; cell height
\r
253 dw 0ea10h ; v sync start
\r
254 dw 0ac11h ; v sync end and protect cr0-cr7
\r
255 dw 0df12h ; vertical displayed
\r
257 dw 00014h ; turn off dword mode
\r
258 dw 0e715h ; v blank start
\r
259 dw 00616h ; v blank end
\r
260 dw 0e317h ; turn on byte mode
\r
264 X360Y360 label word
\r
267 dw 06b00h ; horz total
\r
268 dw 05901h ; horz displayed
\r
269 dw 05a02h ; start horz blanking
\r
270 dw 08e03h ; end horz blanking
\r
271 dw 05e04h ; start h sync
\r
272 dw 08a05h ; end h sync
\r
273 dw 04009h ; cell height
\r
274 dw 08810h ; v sync start
\r
275 dw 08511h ; v sync end and protect cr0-cr7
\r
276 dw 06712h ; vertical displayed
\r
278 dw 00014h ; turn off dword mode
\r
279 dw 06d15h ; v blank start
\r
280 dw 0ba16h ; v blank end
\r
281 dw 0e317h ; turn on byte mode
\r
286 X376Y308 label word
\r
289 dw 06e00h ; horz total
\r
290 dw 05d01h ; horz displayed
\r
291 dw 05e02h ; start horz blanking
\r
292 dw 09103h ; end horz blanking
\r
293 dw 06204h ; start h sync
\r
294 dw 08f05h ; end h sync
\r
295 dw 06206h ; vertical total
\r
296 dw 00f07h ; overflow
\r
299 dw 03710h ; v sync start
\r
300 dw 08911h ; v sync end and protect cr0-cr7
\r
301 dw 03312h ; vertical displayed
\r
303 dw 00014h ; turn off dword mode
\r
304 dw 03c15h ; v blank start
\r
305 dw 05c16h ; v blank end
\r
306 dw 0e317h ; turn on byte mode
\r
310 X376Y564 label word
\r
313 dw 06e00h ; horz total
\r
314 dw 05d01h ; horz displayed
\r
315 dw 05e02h ; start horz blanking
\r
316 dw 09103h ; end horz blanking
\r
317 dw 06204h ; start h sync
\r
318 dw 08f05h ; end h sync
\r
319 dw 06206h ; vertical total
\r
320 dw 0f007h ; overflow
\r
323 dw 03710h ; v sync start
\r
324 dw 08911h ; v sync end and protect cr0-cr7
\r
325 dw 03312h ; vertical displayed
\r
327 dw 00014h ; turn off dword mode
\r
328 dw 03c15h ; v blank start
\r
329 dw 05c16h ; v blank end
\r
330 dw 0e317h ; turn on byte mode
\r
335 ModeTable label word ; Mode X tweak table
\r
354 _CurrXMode dw 0 ; Current graphics mode index
\r
355 _InGraphics db 0 ; Flag indicating graphics activity
\r
356 _ScrnPhysicalByteWidth dw 0 ; Physical width in bytes of screen
\r
357 _ScrnPhysicalPixelWidth dw 0 ; Physical width in pixels of screen
\r
358 _ScrnPhysicalHeight dw 0 ; Physical Height of screen
\r
359 _ErrorValue db 0 ; Set after function calls
\r
362 _SplitScrnActive db 0 ; Flag indicating Split scrn activity
\r
363 _DoubleBufferActive dw 0 ; Flag indicating double buffering
\r
364 _TrippleBufferActive dw 0 ; Flag indicating tripple buffering
\r
366 _SplitScrnScanLine dw 0 ; Split Screen's starting scan line
\r
367 _SplitScrnVisibleHeight dw 0 ; Split Screen's height on screen
\r
369 _SplitScrnOffs dw 0 ; Offset in video ram of Split Screen
\r
371 _Page0_Offs dw 0 ; Ofset in video ram of Main virtual
\r
372 ; screen ( = 0 if no split screen
\r
373 ; otherwise = offset of first byte
\r
374 ; after split screen
\r
375 _Page1_Offs dw 0 ; Ofset in video ram of Second virtual
\r
376 ; screen ( = 0 if no split screen
\r
377 ; otherwise = offset of first byte
\r
378 ; after split screen
\r
379 ; = Page0_Offs if Doubble buffering
\r
383 _NonVisual_Offs dw 0 ; Ofset in video ram of first byte
\r
384 ; of non visible ram
\r
385 _ScrnLogicalByteWidth dw 0 ; Logical width in bytes of screen
\r
386 _ScrnLogicalPixelWidth dw 0 ; Logical width in pixels of screen
\r
387 _ScrnLogicalHeight dw 0 ; Logical Height of screen
\r
389 _MaxScrollX dw 0 ; Max X start position of Physical
\r
390 ; screen within virtual screen (in
\r
392 _MaxScrollY dw 0 ; Max Y start position of Physical
\r
393 ; screen within virtual screen
\r
395 _VisiblePageIdx dw 0 ; Index of currently visible D.B.
\r
398 PageAddrTable label word
\r
399 _VisiblePageOffs dw 0 ; Table containing starting offsets
\r
400 _HiddenPageOffs dw 0 ; of the double buffer pages
\r
401 _WaitingPageOffs dw 0
\r
403 _TopClip dw 0 ; Clipping Rectangle
\r
405 _LeftClip dw 0 ; Left/Right coordinates in bytes
\r
407 _PhysicalStartByteX dw 0 ; X byte coord of physical screen
\r
408 ; relative to virtual virtual screen
\r
409 _PhysicalStartPixelX dw 0 ; X pixel coord of physical screen
\r
410 ; relative to virtual screen
\r
411 _PhysicalStartY dw 0 ; Y pixel coord of physical screen
\r
412 ; relative to virtual screen
\r
415 _VsyncHandlerActive dw 0
\r
416 _MouseRefreshFlag dw 0
\r
417 _MouseVsyncHandler dd 0
\r
418 _StartAddressFlag dw 0
\r
419 _WaitingStartLow dw 0
\r
420 _WaitingStartHigh dw 0
\r
421 _WaitingPelPan dw 0
\r
422 _VsyncPaletteStart dw 0
\r
423 _VsyncPaletteCount dw 0
\r
424 _VsyncPaletteBuffer label byte
\r
428 PARAMS_END label byte
\r
430 PARAM_COUNT equ ($-PARAMS)
\r
433 ; Index/data pairs for CRT Controller registers that differ between
\r
434 ; mode 13h and mode X.
\r
436 ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively
\r
437 PelPanMask db 000h,002h,004h,006h
\r
439 DoubleScanFlag db ? ; Flag to indicate double scanned mode
\r
446 ;-------------------------------------------------------------------------
\r
447 ; Local Logical Screen Width setting function
\r
448 ; cx = Requitrd Logical Width
\r
450 ; WARNING: no registers are preserved
\r
452 SetLogicalScrWidth proc
\r
459 cmp ax,[_ScrnPhysicalPixelWidth]; Is logical width >= physical width
\r
460 jge @@ValidLogicalWidth ; yes - continue
\r
461 mov ax,bx ; no - set logical width = physical
\r
463 @@ValidLogicalWidth:
\r
469 ; The EXACT logical pixel width may not have been possible since
\r
470 ; it should be divisible by 8. Round down to the closest possible
\r
471 ; width and update the status variables
\r
475 mov [_ScrnLogicalByteWidth],ax ; Store the byte width of virtual
\r
476 mov [_RightClip],ax ; Set default Right clip column
\r
478 sub ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position
\r
479 shl ax,1 ; of physical screen in virtual
\r
480 shl ax,1 ; of physical screen in virtual
\r
481 mov [_MaxScrollX],ax ; screen in pixels
\r
482 mov ax,bx ; set ax to byte width of virt scrn
\r
483 shl ax,1 ; convert to pixels
\r
484 shl ax,1 ; convert to pixels
\r
485 mov [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width
\r
486 mov cx,ax ; save ax (return value)
\r
488 ; calculate no. non split screen rows in video ram
\r
490 mov ax,0ffffh ; cx = Maximum video ram offset
\r
491 sub dx,dx ; DX:AX is divide operand, set DX = 0
\r
492 div bx ; divide ax by ScrnLogicalByteWidth
\r
493 mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height
\r
494 mov [_BottomClip],ax ; Set default bottom clip row
\r
495 sub ax,[_ScrnPhysicalHeight] ; Update the maximum Y position of
\r
496 mov [_MaxScrollY],ax ; Physical screen in logical screen
\r
497 mov ax,cx ; restore ax (return value)
\r
499 ; calculate initial NonVisual
\r
500 mov ax,[_ScrnLogicalByteWidth]
\r
501 mul [_ScrnPhysicalHeight]
\r
502 mov [_NonVisual_Offs],ax
\r
505 SetLogicalScrWidth endp
\r
511 out dx,ax ; enable writes to all four planes
\r
512 mov ax,SCREEN_SEG ; now clear all display memory, 8 pixels
\r
513 mov es,ax ; at a time
\r
514 sub di,di ; point ES:DI to display memory
\r
518 sub ax,ax ; clear to zero-value pixels
\r
519 mov cx,0FFFFh ; # of words in display memory
\r
520 rep stosw ; clear all of display memory
\r
527 ;-----------------------------------------------------------------------
\r
528 ; Mode X graphics mode set with a virtual screen
\r
529 ; logical screen width.
\r
530 ; C near-callable as:
\r
532 ; int x_set_mode(unsigned int mode,unsigned int WidthInPixels);
\r
534 ; returns the actual width of the allocated virtual screen in pixels
\r
535 ; if a valid mode was selected otherwise returns -1
\r
537 ; Saves virtual screen pixel width in _ScrnLogicalPixelWidth.
\r
538 ; Saves virtual screen byte width in _ScrnLogicalByteWidth.
\r
539 ; Physical screen dimensions are set in _ScrnPhysicalPixelWidth,
\r
540 ; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight
\r
543 ; Modes: 0 = 320 x 200 (256 color) NOTE: Some of these modes require
\r
544 ; 1 = 320 x 240 (256 color) vertical size adjustment.
\r
545 ; 2 = 360 x 200 (256 color)
\r
546 ; 3 = 360 x 240 (256 color)
\r
547 ; 4 = 320 x 400 (256 color)
\r
548 ; 5 = 320 x 480 (256 color)
\r
549 ; 6 = 360 x 200 (256 color)
\r
550 ; 7 = 360 x 480 (256 color)
\r
551 ; 8 = 360 x 360 (256 color)
\r
552 ; 9 = 376 x 308 (256 color)
\r
553 ; 10 = 376 x 564 (256 color)
\r
555 ; Written by Themie Gouthas,
\r
556 ; parts adapted from M. Abrash code.
\r
557 ;------------------------------------------------------------------------
\r
559 ;;arg mode:word,logicalscrwidth:word
\r
560 push bp ;preserve caller's stack frame
\r
563 push si ;preserve C register vars
\r
564 push di ; (don't count on BIOS preserving anything)
\r
569 mov di,offset PARAMS
\r
575 cmp cx,LAST_X_MODE ; have we selected a valid mode
\r
576 jle @@ValidMode ; Yes !
\r
578 mov [_InGraphics],FALSE ; No return -1
\r
587 mov [_CurrXMode],cx
\r
588 mov [_InGraphics],TRUE
\r
592 jg @@SetDoubleScanFlag
\r
594 @@SetDoubleScanFlag:
\r
595 mov [DoubleScanFlag],al
\r
596 push cx ; some bios's dont preserve cx
\r
600 mov ax,13h ; let the BIOS set standard 256-color
\r
601 int 10h ; mode (320x200 linear)
\r
608 out dx,ax ; disable chain4 mode
\r
610 out dx,ax ; synchronous reset while setting Misc
\r
611 ; Output for safety, even though clock
\r
614 mov bx,offset ModeTable
\r
617 mov si, word ptr [bx]
\r
623 out dx,al ; select the dot clock and Horiz
\r
628 out dx,ax ; undo reset (restart sequencer)
\r
631 mov dx,CRTC_INDEX ; reprogram the CRT Controller
\r
632 mov al,11h ; VSync End reg contains register write
\r
633 out dx,al ; protect bit
\r
634 inc dx ; CRT Controller Data register
\r
635 in al,dx ; get current VSync End register setting
\r
636 and al,07fh ; remove write protect on various
\r
637 out dx,al ; CRTC registers
\r
638 dec dx ; CRT Controller Index
\r
645 lodsw ; get the next CRT Index/Data pair
\r
646 out dx,ax ; set the next CRT Index/Data pair
\r
647 loop @@SetCRTParmsLoop
\r
651 out dx,ax ; enable writes to all four planes
\r
652 mov ax,SCREEN_SEG ; now clear all display memory, 8 pixels
\r
653 mov es,ax ; at a time
\r
654 sub di,di ; point ES:DI to display memory
\r
655 sub ax,ax ; clear to zero-value pixels
\r
656 mov cx,8000h ; # of words in display memory
\r
657 rep stosw ; clear all of display memory
\r
659 ; Set pysical screen dimensions
\r
661 lodsw ; Load scrn pixel width
\r
662 mov [_ScrnPhysicalPixelWidth],ax ; from tweak table and store
\r
663 mov [_SplitScrnScanLine],ax ; No splitscrn ==
\r
664 ; splitscrn=PhysicalscrnHeight
\r
665 mov bx,ax ; Copy width for later use
\r
666 shr ax,1 ; Convert to byte width
\r
667 shr ax,1 ; Convert to byte width
\r
668 mov [_ScrnPhysicalByteWidth],ax ; Store for later use
\r
669 lodsw ; Load Screen Phys. Height
\r
670 mov [_ScrnPhysicalHeight],ax ; Store for later use
\r
673 ; Mode X is set, now set the required logical page width.
\r
677 call SetLogicalScrWidth
\r
679 pop di ;restore C register vars
\r
681 pop bp ;restore caller's stack frame
\r
685 ;----------------------------------------------------------------------
\r
686 ; Mode X (256 color mode) set default access video plane
\r
688 ; C near-callable as:
\r
689 ; void x_select_default_plane(unsigned char plane);
\r
691 ; Enables Read/Write access to a plane using general memory access
\r
694 ; Written by Themie Gouthas
\r
695 ;----------------------------------------------------------------------
\r
696 _x_select_default_plane proc
\r
699 mov bp,sp ; set up stack frame
\r
700 mov cl,byte ptr [bp+4]
\r
702 ; SELECT WRITE PLANE
\r
703 and cl,011b ;CL = plane
\r
704 mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg
\r
705 shl ah,cl ;set only the bit for the required
\r
707 mov dx,SC_INDEX ;set the Map Mask to enable only the
\r
708 out dx,ax ; pixel's plane
\r
710 ; SELECT READ PLANE
\r
711 mov ah,cl ;AH = plane
\r
712 mov al,READ_MAP ;AL = index in GC of the Read Map reg
\r
713 mov dx,GC_INDEX ;set the Read Map to read the pixel's
\r
718 _x_select_default_plane endp
\r
721 ;----------------------------------------------------------------------
\r
722 ; Mode X (256 color mode) Set Mode X split screen starting row
\r
723 ; The split screen resides on the bottom half of the screen and has a
\r
724 ; starting address of A000:0000
\r
726 ; C near-callable as:
\r
727 ; void x_set_splitscreen(unsigned int line);
\r
729 ; Updates _Page0_Offs to reflect the existence of the split screen region
\r
730 ; ie _MainScrnOffset is set to the offset of the first pixel beyond the split
\r
733 ; Written by Themie Gouthas
\r
734 ;----------------------------------------------------------------------
\r
736 _x_set_splitscreen proc
\r
739 mov bp,sp ; set up stack frame
\r
742 xor si,si ; si=0 -> x virtual page start coord
\r
744 cmp [_DoubleBufferActive],0
\r
747 cmp [_SplitScrnActive],0
\r
748 je @@NotPreviouslyCalled
\r
751 mov [_ErrorValue],ERROR
\r
753 pop bp ; Return if previously called
\r
756 @@NotPreviouslyCalled:
\r
758 ; Turn on split screen pal pen suppression, so the split screen
\r
759 ; wo'nt be subject to pel panning as is the non split screen portion.
\r
761 mov dx,INPUT_STATUS_0
\r
762 in al,dx ; Reset the AC Index/Data toggle to
\r
764 mov al,AC_MODE_CONTROL+20h ; Bit 5 set to prevent screen blanking
\r
765 mov dx,AC_INDEX ; Point AC to Index/Data register
\r
767 inc dx ; Point to AC Data reg (for reads only)
\r
768 in al,dx ; Get the current AC Mode Control reg
\r
769 or al,20h ; Enable split scrn Pel panning suppress.
\r
770 dec dx ; Point to AC Index/Data reg (for writes only)
\r
771 out dx,al ; Write the new AC Mode Control setting
\r
772 ; with split screen pel panning
\r
773 ; suppression turned on
\r
775 mov [_PhysicalStartByteX],ax ; Set the Phisical screen start
\r
776 mov [_PhysicalStartPixelX],ax ; offset within virtual screen
\r
777 mov [_PhysicalStartY],ax
\r
778 mov [_SplitScrnActive],TRUE
\r
780 jns @@NotNeg ; Check that Split Scrn start scan line is +ve
\r
782 mov ax,0 ; Since -ve set to 0
\r
785 mov [_SplitScrnScanLine],ax ; save the scanline
\r
789 or [DoubleScanFlag],0
\r
790 jz @@NotDoubleScanned
\r
793 @@NotDoubleScanned:
\r
794 ;mov cl,[DoubleScanFlag]
\r
795 ;shl ax,cl ; Mode X 200 and 240 line modes are actually
\r
796 ; 400 and 480 lines that are double scanned
\r
797 ; so for start scanline multiply required ModeX
\r
798 ; scan line by 2 if its a double scanned mode
\r
801 mov bx,ax ; save the scanline
\r
804 WaitVsyncStart ; wait for vertical retrace
\r
806 cli ; Dont allow register setting to be interrupted
\r
809 mov al,LINE_COMPARE
\r
810 out dx,ax ; Bits 7-0 of the split screen scan line
\r
818 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split
\r
819 out dx,al ; screen scan line,
\r
820 inc dx ; So using readability of VGA registers
\r
821 in al,dx ; Read the OVERFLOW register, and set the
\r
822 and al, not 10h ; bit corresponding to Bit 8 (above)
\r
832 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =
\r
833 out dx,al ; Bit 9 of split screen scan line
\r
834 inc dx ; As we did before, update the apropriate
\r
835 in al,dx ; bit without disturbing the rest
\r
839 sti ; Registers are set, so interrupts are safe
\r
841 mov ax,[_ScrnPhysicalHeight] ; Determine where the first byte
\r
842 sub ax,[_SplitScrnScanLine] ; of the non split screen video ram
\r
843 mov [_SplitScrnVisibleHeight],ax ; starts and store it for reference
\r
845 mov bx,[_ScrnLogicalByteWidth]
\r
847 mov [_Page0_Offs],ax
\r
848 mov [_Page1_Offs],ax
\r
849 mov [_Page2_Offs],ax
\r
851 ; calculate no. non split screen rows in video ram
\r
852 mov cx,0ffffh ; cx = Maximum video ram offset
\r
853 sub cx,ax ; cx = cx - _Page0_Offs
\r
854 xchg cx,ax ; swap cx and ax
\r
855 sub dx,dx ; DX:AX is divide operand, set DX = 0
\r
856 div bx ; divide ax (prev cx) by
\r
857 ; ScrnLogicalByteWidth
\r
859 mov [_ScrnLogicalHeight],ax ; Save Screen Logical Height
\r
860 cmp ax,[_BottomClip]
\r
861 jle @@BottomClipOK2 ; Adjust Clip Rectangle if necessary
\r
862 mov [_BottomClip],ax
\r
864 sub ax,[_SplitScrnScanLine] ; Update the maximum Y position of
\r
865 mov [_MaxScrollY],ax ; Physical screen in logical screen
\r
867 xchg cx,ax ; restore original ax (MainScrnOfs)
\r
868 mov bh,al ; Set the visible screen start address
\r
869 mov ch,ah ; to the top left corner of the virtual
\r
870 jmp StartAddrEntry ; screen
\r
871 _x_set_splitscreen endp
\r
874 ;-----------------------------------------------------------------------
\r
875 ; Mode X (256 color mode) Page flip primer
\r
876 ; No clipping is performed.
\r
877 ; C near-callable as:
\r
879 ; void x_page_flip(unsigned int x, unsigned int y);
\r
881 ; Swaps visible and hidden page offsets and then executes the SetStartAddr
\r
882 ; to achieve a page flip.
\r
884 ; SEE x_set_start_addr below
\r
886 ; Written by Themie Gouthas
\r
887 ;------------------------------------------------------------------------
\r
891 push bp ;preserve caller's stack frame
\r
892 mov bp,sp ;point to local stack frame
\r
896 mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment
\r
899 cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ?
\r
901 cmp [_TrippleBufferActive],TRUE
\r
905 mov bx,[_HiddenPageOffs]
\r
906 xchg bx,[_VisiblePageOffs]
\r
907 xchg bx,[_WaitingPageOffs]
\r
908 mov [_HiddenPageOffs],bx
\r
909 mov bx,[_VisiblePageIdx]
\r
915 mov [_VisiblePageIdx],bx
\r
916 jmp short PageFlipEntry2
\r
918 mov bx,[_HiddenPageOffs]
\r
919 xchg bx,[_VisiblePageOffs] ; Swap the Page Offsete
\r
920 xchg [_HiddenPageOffs],bx
\r
921 xor [_VisiblePageIdx],01h ; Set the Visible page index
\r
922 jmp short PageFlipEntry2
\r
926 ;-----------------------------------------------------------------------
\r
927 ; Mode X (256 color mode) Set Mode X non split screen start address
\r
928 ; of logical screen.
\r
929 ; C near-callable as:
\r
931 ; void x_set_start_addr(unsigned int x, unsigned int y);
\r
933 ; Params: StartOffset is offset of first byte of logical screen ram
\r
934 ; (Useful if you want to double buffer by splitting your non
\r
935 ; split screen video ram into 2 pages)
\r
936 ; X,Y coordinates of the top left hand corner of the physical screen
\r
937 ; within the logical screen
\r
938 ; X must not exceed (Logical screen width - Physical screen width)
\r
939 ; Y must not exceed (Logical screen height - Physical screen height)
\r
942 ; Written by Themie Gouthas,
\r
943 ; Parts addapted from M. Abrash code published in DDJ Mag.
\r
944 ;------------------------------------------------------------------------
\r
945 _x_set_start_addr proc
\r
952 mov ax,[_ScrnLogicalByteWidth] ; Calculate Offset increment
\r
953 mov cx,[bp+6] ; for Y
\r
955 cmp [_DoubleBufferActive],TRUE ; Do we have double buffering ?
\r
956 je @@PageResolution
\r
957 cmp [_TrippleBufferActive],TRUE
\r
958 je @@PageResolution
\r
960 add ax,[_Page0_Offs] ; no - add page 0 offset
\r
961 jmp short @@AddColumn
\r
965 mov [_PhysicalStartPixelX],si
\r
966 mov [_PhysicalStartY],cx
\r
969 add ax,[_VisiblePageOffs] ; Add visible page offset
\r
975 mov [_PhysicalStartByteX],cx
\r
976 add ax,cx ; add the column offset for X
\r
977 mov bh,al ; setup CRTC start addr regs and
\r
978 ; values in word registers for
\r
979 mov ch,ah ; fast word outs
\r
984 and si,0003h ; select pel pan register value for the
\r
985 mov ah,PelPanMask[si] ; required x coordinate
\r
986 mov al,PEL_PANNING+20h
\r
989 cmp [_VsyncHandlerActive],TRUE
\r
990 jne @@NoVsyncHandler
\r
993 cmp [_StartAddressFlag],0
\r
996 mov [_WaitingStartLow],bx
\r
997 mov [_WaitingStartHigh],cx
\r
998 mov [_WaitingPelPan],si
\r
999 mov [_StartAddressFlag],1
\r
1001 jmp short @@Return
\r
1004 mov dx,INPUT_STATUS_0 ;Wait for trailing edge of Vsync pulse
\r
1008 jnz @@WaitDE ;display enable is active low (0 = active)
\r
1013 out dx,ax ;start address low
\r
1015 out dx,ax ;start address high
\r
1018 ; Now wait for vertical sync, so the other page will be invisible when
\r
1019 ; we start drawing to it.
\r
1020 mov dx,INPUT_STATUS_0 ;Wait for trailing edge of Vsync pulse
\r
1024 jz @@WaitVS ;display enable is active low (0 = active)
\r
1028 mov ax,si ; Point the attribute controller to pel pan
\r
1030 out dx,al ; reg. Bit 5 also set to prevent blanking
\r
1032 out dx,al ; load new Pel Pan setting.
\r
1036 mov [_ErrorValue],OK
\r
1040 _x_set_start_addr endp
\r
1043 ;-----------------------------------------------------------------------
\r
1044 ; Mode X (256 color mode) Mode X split screen hide
\r
1045 ; C near-callable as:
\r
1047 ; void x_hide_splitscreen()
\r
1049 ; Hides an existing split screen by setting its starting scan line to
\r
1050 ; the last physical screen scan line
\r
1052 ; WARNING: Only to be used if SplitScrnLine has been previously called
\r
1053 ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
\r
1054 ; the initial split screen is reserved and the size limitations
\r
1055 ; of these modes means any change in the split screen scan line
\r
1056 ; will encroach on the split screen ram
\r
1058 ; Written by Themie Gouthas
\r
1059 ;------------------------------------------------------------------------
\r
1061 _x_hide_splitscreen proc
\r
1065 cmp [_SplitScrnActive],TRUE
\r
1066 je @@SplitScreenEnabled
\r
1069 mov [_ErrorValue],ERROR
\r
1073 @@SplitScreenEnabled:
\r
1074 cmp [_CurrXMode],4 ; Do nothing for Modes > 2
\r
1076 mov bx,[_ScrnPhysicalHeight]
\r
1078 mov ax,[_ScrnLogicalHeight]
\r
1080 mov [_MaxScrollY],ax
\r
1082 mov [_SplitScrnVisibleHeight],ax
\r
1084 or [DoubleScanFlag],0
\r
1085 jz @@NotDoubleScanned0
\r
1088 @@NotDoubleScanned0:
\r
1089 ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes
\r
1092 WaitVsyncStart ; wait for vertical retrace
\r
1094 cli ; Dont allow register setting to be interrupted
\r
1097 mov al,LINE_COMPARE
\r
1098 out dx,ax ; Bits 7-0 of the split screen scan line
\r
1106 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split
\r
1107 out dx,al ; screen scan line,
\r
1108 inc dx ; So using readability of VGA registers
\r
1109 in al,dx ; Read the OVERFLOW register, and set the
\r
1110 and al, not 10h ; bit corresponding to Bit 8 (above)
\r
1120 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =
\r
1121 out dx,al ; Bit 9 of split screen scan line
\r
1122 inc dx ; As we did before, update the apropriate
\r
1123 in al,dx ; bit without disturbing the rest
\r
1127 sti ; Registers are set, so interrupts are safe
\r
1131 mov [_ErrorValue],OK
\r
1134 _x_hide_splitscreen endp
\r
1136 ;-----------------------------------------------------------------------
\r
1137 ; Mode X (256 color mode) Mode X split screen show
\r
1138 ; C near-callable as:
\r
1140 ; void x_show_splitscreen()
\r
1142 ; Restores split screen start scan line to the initial split screen
\r
1143 ; starting scan line as set by SplitScrnLine.
\r
1145 ; WARNING: Only to be used if SplitScrnLine has been previously called
\r
1146 ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
\r
1147 ; the initial split screen is reserved and the size limitations
\r
1148 ; of these modes means any change in the split screen scan line
\r
1149 ; will encroach on the split screen ram
\r
1150 ; Update: Now disabled for these modes
\r
1152 ; Written by Themie Gouthas
\r
1153 ;------------------------------------------------------------------------
\r
1156 _x_show_splitscreen proc
\r
1160 cmp [_SplitScrnActive],TRUE
\r
1161 je @@SplitScreenEnabled0
\r
1164 mov [_ErrorValue],ERROR
\r
1168 @@SplitScreenEnabled0:
\r
1169 cmp [_CurrXMode],4 ; Do nothing for Modes > 2
\r
1172 mov bx,[_SplitScrnScanLine]
\r
1173 mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
\r
1175 mov [_MaxScrollY],ax
\r
1177 mov ax,[_ScrnPhysicalHeight]
\r
1179 mov [_SplitScrnVisibleHeight],ax
\r
1181 or [DoubleScanFlag],0
\r
1182 jz @@NotDoubleScanned1
\r
1185 @@NotDoubleScanned1:
\r
1186 ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes
\r
1188 WaitVsyncStart ; wait for vertical retrace
\r
1190 cli ; Dont allow register setting to be interrupted
\r
1193 mov al,LINE_COMPARE
\r
1194 out dx,ax ; Bits 7-0 of the split screen scan line
\r
1202 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split
\r
1203 out dx,al ; screen scan line,
\r
1204 inc dx ; So using readability of VGA registers
\r
1205 in al,dx ; Read the OVERFLOW register, and set the
\r
1206 and al, not 10h ; bit corresponding to Bit 8 (above)
\r
1216 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =
\r
1217 out dx,al ; Bit 9 of split screen scan line
\r
1218 inc dx ; As we did before, update the apropriate
\r
1219 in al,dx ; bit without disturbing the rest
\r
1223 sti ; Registers are set, so interrupts are safe
\r
1226 mov [_ErrorValue],0
\r
1229 _x_show_splitscreen endp
\r
1232 ;-----------------------------------------------------------------------
\r
1233 ; Mode X (256 color mode) Modify Mode X split screen starting scan line
\r
1234 ; C near-callable as:
\r
1236 ; void x_adjust_splitscreen(unsigned int ScanLine)
\r
1238 ; Sets the split screen start scan line to a new scan line. Valid scan lines
\r
1239 ; are between the initial split screen starting scan line and the last
\r
1240 ; physical screen scan line.
\r
1242 ; WARNING: Only to be used if SplitScrnLine has been previously called
\r
1243 ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
\r
1244 ; the initial split screen is reserved and the size limitations
\r
1245 ; of these modes means any change in the split screen scan line
\r
1246 ; will encroach on the split screen ram
\r
1247 ; Update: Now disabled for these modes
\r
1250 ; Written by Themie Gouthas
\r
1251 ;------------------------------------------------------------------------
\r
1254 _x_adjust_splitscreen proc
\r
1259 cmp [_SplitScrnActive],TRUE
\r
1260 je @@SplitScreenEnabled1
\r
1263 mov [_ErrorValue],ERROR
\r
1267 @@SplitScreenEnabled1:
\r
1268 cmp [_CurrXMode],4 ; Do nothing for Modes > 2
\r
1270 mov bx,[bp+4] ; Is the required starting scan line
\r
1271 cmp bx,[_SplitScrnScanLine] ; valid ?
\r
1272 js @@Done2 ; No - Then do nothing
\r
1276 mov ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
\r
1278 mov [_MaxScrollY],ax
\r
1280 mov ax,[_ScrnPhysicalHeight]
\r
1282 mov [_SplitScrnVisibleHeight],ax
\r
1284 or [DoubleScanFlag],0
\r
1285 jz @@NotDoubleScanned2
\r
1288 @@NotDoubleScanned2:
\r
1289 ;mov cl,[DoubleScanFlag] ; Compensate for double scanned modes
\r
1292 WaitVsyncStart ; wait for vertical retrace
\r
1294 cli ; Dont allow register setting to be interrupted
\r
1298 mov al,LINE_COMPARE
\r
1299 out dx,ax ; Bits 7-0 of the split screen scan line
\r
1307 mov al,OVERFLOW ; Bit 4 of overflow register = Bit 8 of split
\r
1308 out dx,al ; screen scan line,
\r
1309 inc dx ; So using readability of VGA registers
\r
1310 in al,dx ; Read the OVERFLOW register, and set the
\r
1311 and al, not 10h ; bit corresponding to Bit 8 (above)
\r
1321 mov al,MAX_SCAN_LINE ; Bit 6 of max scan line register =
\r
1322 out dx,al ; Bit 9 of split screen scan line
\r
1323 inc dx ; As we did before, update the apropriate
\r
1324 in al,dx ; bit without disturbing the rest
\r
1328 sti ; Registers are set, so interrupts are safe
\r
1330 mov [_ErrorValue],OK
\r
1333 _x_adjust_splitscreen endp
\r
1337 ;-----------------------------------------------------------------------
\r
1338 ; Mode X (256 color mode) Enable DoubleBuffering on non split screen area
\r
1339 ; C near-callable as:
\r
1341 ; int x_set_doublebuffer(unsigned int PageHeight);
\r
1343 ; Params: PageHeight is the height of the virtual screen to double buffer
\r
1344 ; Returns the closest possible height to the specified.
\r
1346 ; Sets up two double buffering virtual pages
\r
1347 ; GLOBAL variables set:
\r
1349 ; _Page1_Offs Offset of second virtual page
\r
1350 ; _NonVisual_Offs Offset of first non visible video ram byte
\r
1351 ; _DoubleBufferActive Flag
\r
1352 ; _PageAddrTable Table of Double buffering pages start offsets
\r
1353 ; _ScrnLogicalHeight Logical height of the double buffering pages
\r
1356 ; Written by Themie Gouthas
\r
1357 ;------------------------------------------------------------------------
\r
1360 _x_set_doublebuffer proc
\r
1361 ;arg PageHeight:word
\r
1365 cmp [_DoubleBufferActive],0
\r
1368 mov [_ErrorValue],ERROR
\r
1373 mov [_VisiblePageIdx],0 ; Set visible Page to 0
\r
1374 mov ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to
\r
1375 shr ax,1 ; _ScrnLogicalHeight / 2
\r
1377 mov bx,[bp+4] ; Is the require D.B. Page Height
\r
1378 cmp ax,bx ; > the Maximum D.B. Page Height ?
\r
1380 js @@InvalidHeight ; no - jump
\r
1381 mov ax,bx ; yes - Set the D.B. Page height to
\r
1382 ; to the maximum allowed.
\r
1385 mov [_ScrnLogicalHeight],ax ; Update logical screen height to
\r
1386 ; reflect the height of a D.B. page
\r
1387 cmp ax,[_BottomClip]
\r
1388 jle @@BottomClipOK0 ; Adjust Clip Rectangle if necessary
\r
1389 mov [_BottomClip],ax
\r
1392 mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second
\r
1393 mov cx,ax ; D.B. Page in video ram
\r
1394 mov bx,[_Page0_Offs]
\r
1395 mov [_VisiblePageOffs],bx
\r
1398 mov [_Page1_Offs],ax ; Save it
\r
1399 mov [_HiddenPageOffs],ax
\r
1401 add ax,cx ; Calculate the offset of first byte
\r
1402 mov [_NonVisual_Offs],ax ; beyond the D.B. pages and save it
\r
1403 mov [_DoubleBufferActive],TRUE ; Set flag indicating D.B'ing mode on
\r
1406 sub ax,[_ScrnPhysicalHeight]
\r
1407 add ax,[_SplitScrnVisibleHeight]
\r
1408 mov [_MaxScrollY],ax
\r
1410 mov ax,dx ; return the D.B. pages' height
\r
1411 mov [_ErrorValue],OK
\r
1414 _x_set_doublebuffer endp
\r
1417 ;-----------------------------------------------------------------------
\r
1418 ; Mode X (256 color mode) Enable TrippleBuffering on non split screen area
\r
1419 ; C near-callable as:
\r
1421 ; int x_set_tripplebuffer(unsigned int PageHeight);
\r
1423 ; Params: PageHeight is the height of the virtual screen to tripple buffer
\r
1424 ; Returns the closest possible height to the specified.
\r
1426 ; Sets up two tripple buffering virtual pages
\r
1427 ; GLOBAL variables set:
\r
1429 ; _Page1_Offs Offset of second virtual page
\r
1430 ; _Page2_Offs Offset of third virtual page
\r
1431 ; _NonVisual_Offs Offset of first non visible video ram byte
\r
1432 ; _DoubleBufferActive Flag
\r
1433 ; _PageAddrTable Table of Double buffering pages start offsets
\r
1434 ; _ScrnLogicalHeight Logical height of the double buffering pages
\r
1437 ; Almost written by Tore Bastiansen (cut & paste from _x_set_doublebuffer)
\r
1438 ;------------------------------------------------------------------------
\r
1440 _x_set_tripplebuffer proc
\r
1441 ;arg PageHeight:word
\r
1445 cmp [_DoubleBufferActive],0
\r
1447 cmp [_TrippleBufferActive],0
\r
1448 je @@OkToContinue3
\r
1450 mov [_ErrorValue],ERROR
\r
1455 mov [_VisiblePageIdx],0 ; Set visible Page to 0
\r
1456 mov ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to
\r
1459 idiv bx ; _ScrnLogicalHeight / 3
\r
1461 mov bx,[bp+4] ; Is the require T.B. Page Height
\r
1462 cmp ax,bx ; > the Maximum T.B. Page Height ?
\r
1464 js @@InvalidHeight0 ; no - jump
\r
1465 mov ax,bx ; yes - Set the T.B. Page height to
\r
1466 ; to the maximum allowed.
\r
1469 mov [_ScrnLogicalHeight],ax ; Update logical screen height to
\r
1470 ; reflect the height of a T.B. page
\r
1471 cmp ax,[_BottomClip]
\r
1472 jle @@BottomClipOK1 ; Adjust Clip Rectangle if necessary
\r
1473 mov [_BottomClip],ax
\r
1476 mul [_ScrnLogicalByteWidth] ; Calculate the offset of the second
\r
1477 mov cx,ax ; D.B. Page in video ram
\r
1478 mov bx,[_Page0_Offs]
\r
1479 mov [_VisiblePageOffs],bx
\r
1482 mov [_Page1_Offs],ax ; Save it
\r
1483 mov [_HiddenPageOffs],ax
\r
1486 mov [_Page2_Offs],ax ; Save the other it ?
\r
1487 mov [_WaitingPageOffs],ax
\r
1489 add ax,cx ; Calculate the offset of first byte
\r
1490 mov [_NonVisual_Offs],ax ; beyond the D.B. pages and save it
\r
1491 mov [_TrippleBufferActive],TRUE ; Set flag indicating T.B'ing mode on
\r
1494 sub ax,[_ScrnPhysicalHeight]
\r
1495 add ax,[_SplitScrnVisibleHeight]
\r
1496 mov [_MaxScrollY],ax
\r
1498 mov ax,dx ; return the D.B. pages' height
\r
1499 mov [_ErrorValue],OK
\r
1502 _x_set_tripplebuffer endp
\r
1505 ;-----------------------------------------------------------------------
\r
1506 ; Set Clipping rectangle
\r
1510 ; int x_set_cliprect(WORD left,WORD top, WORD right, WORD bottom);
\r
1513 ; NOTE clipping is byte oriented. "left" and "right" are in bytes not pixels.
\r
1514 ; Only selected functions perform any clipping at all.
\r
1516 ; Written by Themie Gouthas
\r
1517 ;------------------------------------------------------------------------
\r
1519 _x_set_cliprect proc
\r
1520 ;arg left:word,top:word,right:word,bottom:word
\r
1526 jns @@CorrectXOrder
\r
1529 mov [_LeftClip],ax
\r
1530 mov [_RightClip],bx
\r
1534 jns @@CorrectYOrder
\r
1538 mov [_BottomClip],bx
\r
1541 _x_set_cliprect endp
\r
1544 ;----------------------------------------------------------------------
\r
1545 ; Return to text mode
\r
1550 mov ax,03h ; Restore Text Mode
\r
1557 ;-----------------------------------------------------------------------
\r
1558 ; Wait for Vertical sync
\r
1559 _x_wait_vsync proc
\r
1564 _x_wait_vsync endp
\r