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