]> 4ch.mooo.com Git - 16.git/blob - 16/xlib/xmain.asm
wwww
[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 include xlib.inc\r
26 include xmain.inc\r
27 \r
28 \r
29         _DATA           SEGMENT WORD PUBLIC USE16 'DATA'\r
30 ;.data\r
31 \r
32 \r
33 ; Mode X CRTC register tweaks for various resolutions\r
34 \r
35 \r
36 X256Y200 LABEL word\r
37                 db      0e3h    ; dot clock\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
47         dw      256\r
48         dw      200\r
49 \r
50 \r
51 X256Y240 label word\r
52         db      0e3h    ; dot clock\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
70         dw      256\r
71                 dw      240\r
72 \r
73 \r
74 X320Y200 label  word\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
79         dw      320     ; width\r
80         dw      200     ; height\r
81 \r
82 X320Y240 label  word\r
83         db      0e3h    ; dot clock\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
95         dw      320     ; width\r
96         dw      240     ; height\r
97 \r
98 X360Y200 label  word\r
99         db      0e7h    ; dot clock\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
109         dw      360     ; width\r
110         dw      200     ; height\r
111 \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
132         dw      360\r
133         dw      240\r
134 \r
135 X376Y282 label word\r
136         db      0e7h\r
137         db      18\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
147         dw      0310fh  ;\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
151         dw      02f13h  ; offset\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
156         dw      376\r
157         dw      282\r
158 \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
171         dw      256\r
172         dw      400\r
173 \r
174 \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
194         dw      256\r
195         dw      480\r
196 \r
197 \r
198 \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
205         dw      320     ; width\r
206         dw      400     ; height\r
207 \r
208 X320Y480 label  word\r
209         db      0e3h    ; dotclock\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
221         dw      320     ; width\r
222         dw      480     ; height\r
223 \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
236         dw      360     ; width\r
237         dw      400     ; height\r
238 \r
239 \r
240 \r
241 X360Y480  label word\r
242         db      0e7h\r
243         db      17\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
256         dw      02d13h  ; offset\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
261         dw      360\r
262         dw      480\r
263 \r
264 X360Y360  label word\r
265         db      0e7h\r
266         db      15\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
277         dw      02d13h  ; offset\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
282         dw      360\r
283         dw      360\r
284 \r
285 \r
286 X376Y308 label word\r
287         db      0e7h\r
288         db      18\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
297         dw      04009h  ;\r
298         dw      0310fh  ;\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
302         dw      02f13h  ; offset\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
307         dw      376\r
308         dw      308\r
309 \r
310 X376Y564 label word\r
311         db      0e7h\r
312         db      18\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
321         dw      06009h  ;\r
322         dw      0310fh  ;\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
326         dw      02f13h  ; offset\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
331         dw      376\r
332         dw      564\r
333 \r
334 LAST_X_MODE         equ    13\r
335 ModeTable label word    ; Mode X tweak table\r
336         dw      offset X320Y200\r
337         dw      offset X320Y240\r
338         dw      offset X360Y200\r
339         dw      offset X360Y240\r
340         dw      offset X376Y282\r
341         dw      offset X320Y400\r
342         dw      offset X320Y480\r
343         dw      offset X360Y400\r
344         dw      offset X360Y480\r
345         dw      offset X360Y360\r
346         dw      offset X376Y308\r
347         dw      offset X376Y564\r
348         dw      offset X256Y200\r
349         dw      offset X256Y240\r
350 \r
351 \r
352 PARAMS label byte\r
353 \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
360 \r
361 \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
365 \r
366         _SplitScrnScanLine       dw 0   ; Split Screen's starting scan line\r
367         _SplitScrnVisibleHeight  dw 0   ; Split Screen's height on screen\r
368 \r
369         _SplitScrnOffs           dw 0   ; Offset in video ram of Split Screen\r
370                                         ; always = 0\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
380                                         ; not enabled\r
381         _Page2_Offs              dw 0\r
382 \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
388 \r
389         _MaxScrollX              dw 0   ; Max X start position of Physical\r
390                                         ; screen within virtual screen (in\r
391                                         ; bytes)\r
392         _MaxScrollY              dw 0   ; Max Y start position of Physical\r
393                                         ; screen within virtual screen\r
394 \r
395         _VisiblePageIdx          dw 0   ; Index of currently visible D.B.\r
396                                         ; page\r
397 \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
402 \r
403         _TopClip                 dw 0   ; Clipping Rectangle\r
404         _BottomClip              dw 0   ;\r
405         _LeftClip                dw 0   ; Left/Right coordinates in bytes\r
406         _RightClip               dw 0   ;\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
413 \r
414 ; NEW\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
425                                 db  768  dup(?)\r
426 \r
427 \r
428 PARAMS_END label byte\r
429 \r
430 PARAM_COUNT equ ($-PARAMS)\r
431 \r
432 \r
433 ; Index/data pairs for CRT Controller registers that differ between\r
434 ; mode 13h and mode X.\r
435 \r
436         ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively\r
437         PelPanMask              db      000h,002h,004h,006h\r
438 \r
439 DoubleScanFlag db ?     ; Flag to indicate double scanned mode\r
440 \r
441 _DATA           ENDS\r
442 \r
443 \r
444         .code\r
445 \r
446 ;-------------------------------------------------------------------------\r
447 ; Local Logical Screen Width setting function\r
448 ; cx = Requitrd Logical Width\r
449 ;\r
450 ; WARNING: no registers are preserved\r
451 \r
452 SetLogicalScrWidth proc\r
453         mov   dx,CRTC_INDEX\r
454         mov   al,CRTC_OFFSET\r
455         out   dx,al\r
456         inc   dx\r
457 \r
458         mov   ax,cx\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
462 \r
463 @@ValidLogicalWidth:\r
464         shr   ax,1\r
465         shr   ax,1\r
466         shr   ax,1\r
467         out   dx,al\r
468 \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
472 \r
473         shl   ax,1\r
474         mov   bx,ax\r
475         mov   [_ScrnLogicalByteWidth],ax  ; Store the byte width of virtual\r
476         mov   [_RightClip],ax             ; Set default Right clip column\r
477                                           ; screen\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
487 \r
488         ; calculate no. non split screen rows in video ram\r
489 \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
498 \r
499         ; calculate initial NonVisual\r
500         mov  ax,[_ScrnLogicalByteWidth]\r
501         mul  [_ScrnPhysicalHeight]\r
502         mov  [_NonVisual_Offs],ax\r
503 \r
504 @@Done: ret\r
505 SetLogicalScrWidth endp\r
506 \r
507 clear_vram proc\r
508                 push  di\r
509         mov   dx,SC_INDEX\r
510         mov   ax,0f02h\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
515 \r
516         WaitVsyncEnd\r
517 \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
521                 pop   di\r
522         ret\r
523 clear_vram endp\r
524 \r
525 \r
526 \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
531 ;\r
532 ;    int x_set_mode(unsigned int mode,unsigned int WidthInPixels);\r
533 ;\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
536 ;\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
541 ;\r
542 ;\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
554 ;\r
555 ; Written by Themie Gouthas,\r
556 ; parts adapted from M. Abrash code.\r
557 ;------------------------------------------------------------------------\r
558 _x_set_mode proc\r
559         ;;arg   mode:word,logicalscrwidth:word\r
560         push  bp      ;preserve caller's stack frame\r
561         mov   bp,sp\r
562 \r
563         push  si      ;preserve C register vars\r
564         push  di      ; (don't count on BIOS preserving anything)\r
565 \r
566         cld\r
567         mov   ax,ds\r
568         mov   es,ax\r
569         mov   di,offset PARAMS\r
570         xor   ax,ax\r
571         mov   cx,PARAM_COUNT\r
572         rep   stosb\r
573 \r
574         mov   cx,[BP+4]\r
575         cmp   cx,LAST_X_MODE        ; have we selected a valid mode\r
576         jle   @@ValidMode           ; Yes !\r
577 \r
578         mov   [_InGraphics],FALSE   ; No return -1\r
579         mov   ax,-1\r
580         pop   di\r
581         pop   si\r
582         pop   bp\r
583         ret\r
584 \r
585 @@ValidMode:\r
586 \r
587         mov   [_CurrXMode],cx\r
588         mov   [_InGraphics],TRUE\r
589 \r
590         xor   al,al\r
591         cmp   cx,3\r
592         jg    @@SetDoubleScanFlag\r
593         mov   al,TRUE\r
594 @@SetDoubleScanFlag:\r
595         mov   [DoubleScanFlag],al\r
596         push  cx                    ; some bios's dont preserve cx\r
597 \r
598         call  clear_vram\r
599 \r
600         mov   ax,13h                ; let the BIOS set standard 256-color\r
601         int   10h                   ;  mode (320x200 linear)\r
602 \r
603 \r
604         pop   cx\r
605 \r
606         mov   dx,SC_INDEX\r
607         mov   ax,0604h\r
608         out   dx,ax                 ; disable chain4 mode\r
609         mov   ax,0100h\r
610         out   dx,ax                 ; synchronous reset while setting Misc\r
611                                     ;  Output for safety, even though clock\r
612                                     ;  unchanged\r
613 \r
614         mov   bx,offset ModeTable\r
615         shl   cx,1\r
616         add   bx,cx\r
617         mov   si, word ptr [bx]\r
618         lodsb\r
619 \r
620         or    al,al\r
621         jz    @@DontSetDot\r
622         mov   dx,MISC_OUTPUT\r
623         out   dx,al               ; select the dot clock and Horiz\r
624                                   ;  scanning rate\r
625 @@DontSetDot:\r
626         mov   dx,SC_INDEX\r
627         mov   ax,0300h\r
628         out   dx,ax               ; undo reset (restart sequencer)\r
629 \r
630 \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
639         cld\r
640         xor   cx,cx\r
641         lodsb\r
642         mov   cl,al\r
643 \r
644 @@SetCRTParmsLoop:\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
648 \r
649         mov   dx,SC_INDEX\r
650         mov   ax,0f02h\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
658 \r
659         ;  Set pysical screen dimensions\r
660 \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
671 \r
672 \r
673         ;  Mode X is set, now set the required logical page width.\r
674 \r
675         mov     cx,[BP+6]\r
676 \r
677         call    SetLogicalScrWidth\r
678 \r
679         pop     di      ;restore C register vars\r
680         pop     si\r
681         pop     bp      ;restore caller's stack frame\r
682         ret\r
683 _x_set_mode endp\r
684 \r
685 ;----------------------------------------------------------------------\r
686 ; Mode X (256 color mode) set default access video plane\r
687 ;\r
688 ; C near-callable as:\r
689 ;    void x_select_default_plane(unsigned char plane);\r
690 ;\r
691 ; Enables Read/Write access to a plane using general memory access\r
692 ; methods\r
693 ;\r
694 ; Written by Themie Gouthas\r
695 ;----------------------------------------------------------------------\r
696 _x_select_default_plane proc\r
697         ;arg Plane:byte\r
698         push bp\r
699         mov  bp,sp       ; set up stack frame\r
700         mov  cl,byte ptr [bp+4]\r
701 \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
706                                   ; plane to 1\r
707         mov  dx,SC_INDEX          ;set the Map Mask to enable only the\r
708         out  dx,ax                ; pixel's plane\r
709 \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
714         out  dx,ax                ; plane\r
715 \r
716         pop  bp\r
717         ret\r
718 _x_select_default_plane endp\r
719 \r
720 \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
725 ;\r
726 ; C near-callable as:\r
727 ;    void x_set_splitscreen(unsigned int line);\r
728 ;\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
731 ; screen region\r
732 ;\r
733 ; Written by Themie Gouthas\r
734 ;----------------------------------------------------------------------\r
735 \r
736 _x_set_splitscreen proc\r
737         ;arg Line:word\r
738         push bp\r
739         mov  bp,sp       ; set up stack frame\r
740         push si\r
741 \r
742         xor  si,si       ; si=0 -> x virtual page start coord\r
743 \r
744         cmp  [_DoubleBufferActive],0\r
745         jne   @@error\r
746 \r
747         cmp  [_SplitScrnActive],0\r
748         je   @@NotPreviouslyCalled\r
749 \r
750 @@error:\r
751         mov  [_ErrorValue],ERROR\r
752         pop  si\r
753         pop  bp          ; Return if previously called\r
754         ret\r
755 \r
756 @@NotPreviouslyCalled:\r
757 \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
760 \r
761         mov  dx,INPUT_STATUS_0\r
762         in   al,dx                  ; Reset the AC Index/Data toggle to\r
763                                         ;  index state\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
766         out  dx,al\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
774 \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
779         mov  ax,[bp+4]\r
780         jns  @@NotNeg    ; Check that Split Scrn start scan line is +ve\r
781 \r
782         mov  ax,0        ; Since -ve set to 0\r
783 \r
784 @@NotNeg:\r
785         mov  [_SplitScrnScanLine],ax   ; save the scanline\r
786 \r
787 \r
788 \r
789         or    [DoubleScanFlag],0\r
790         jz    @@NotDoubleScanned\r
791         shl   ax,1\r
792         dec   ax\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
799 \r
800 \r
801         mov  bx,ax            ; save the scanline\r
802 \r
803 \r
804         WaitVsyncStart        ; wait for vertical retrace\r
805 \r
806         cli                   ; Dont allow register setting to be interrupted\r
807         mov  dx,CRTC_INDEX\r
808         mov  ah,bl\r
809         mov  al,LINE_COMPARE\r
810         out  dx,ax            ; Bits 7-0 of the split screen scan line\r
811 \r
812         mov  ah,bh\r
813         and  ah,1\r
814         shl  ah,1\r
815         shl  ah,1\r
816         shl  ah,1\r
817         shl  ah,1\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
823         or   al,ah\r
824         out  dx,al\r
825 \r
826         dec  dx\r
827         mov  ah,bh\r
828         and  ah,2\r
829         ror  ah,1\r
830         ror  ah,1\r
831         ror  ah,1\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
836         and  al, not 40h\r
837         or   al,ah\r
838         out  dx,al\r
839         sti                    ; Registers are set, so interrupts are safe\r
840 \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
844 \r
845         mov  bx,[_ScrnLogicalByteWidth]\r
846         mul  bx\r
847         mov  [_Page0_Offs],ax\r
848         mov  [_Page1_Offs],ax\r
849         mov  [_Page2_Offs],ax\r
850 \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
858 \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
863 @@BottomClipOK2:\r
864         sub  ax,[_SplitScrnScanLine]     ; Update the maximum Y position of\r
865         mov  [_MaxScrollY],ax            ; Physical screen in logical screen\r
866 \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
872 \r
873 \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
878 ;\r
879 ;    void x_page_flip(unsigned int x, unsigned int y);\r
880 ;\r
881 ; Swaps visible and hidden page offsets and then executes the SetStartAddr\r
882 ; to achieve a page flip.\r
883 ;\r
884 ; SEE x_set_start_addr below\r
885 ;\r
886 ; Written by Themie Gouthas\r
887 ;------------------------------------------------------------------------\r
888 \r
889 _x_page_flip proc\r
890         ;arg x:word,y:word\r
891         push  bp                  ;preserve caller's stack frame\r
892         mov   bp,sp               ;point to local stack frame\r
893         push  si\r
894 \r
895         mov  si,[bp+4]\r
896         mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment\r
897         mov  cx,[bp+6]\r
898         mul  cx                             ; for Y\r
899         cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?\r
900         je   @@DoubleBuffer\r
901         cmp  [_TrippleBufferActive],TRUE\r
902         jne   PageFlipEntry1\r
903 \r
904 ; TrippleBuffer\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
910         inc  bx\r
911         cmp  bx,3\r
912         jne  @@IdxOk\r
913         xor  bx,bx\r
914 @@IdxOk:\r
915         mov  [_VisiblePageIdx],bx\r
916         jmp  short PageFlipEntry2\r
917 @@DoubleBuffer:\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
923 _x_page_flip endp\r
924 \r
925 \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
930 ;\r
931 ;    void x_set_start_addr(unsigned int x, unsigned int y);\r
932 ;\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
940 ;\r
941 ;\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
946         ;arg x:word,y:word\r
947         push bp\r
948         mov  bp,sp\r
949         push si\r
950 \r
951         mov  si,[bp+4]\r
952         mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment\r
953         mov  cx,[bp+6]                         ; for Y\r
954         mul  cx\r
955         cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?\r
956         je   @@PageResolution\r
957         cmp  [_TrippleBufferActive],TRUE\r
958         je   @@PageResolution\r
959 PageFlipEntry1:\r
960         add  ax,[_Page0_Offs]               ; no - add page 0 offset\r
961         jmp  short @@AddColumn\r
962 \r
963 PageFlipEntry2:\r
964 \r
965         mov  [_PhysicalStartPixelX],si\r
966         mov  [_PhysicalStartY],cx\r
967 \r
968 @@PageResolution:\r
969         add  ax,[_VisiblePageOffs]          ; Add visible page offset\r
970 \r
971 @@AddColumn:\r
972         mov  cx,si\r
973         shr  cx,1\r
974         shr  cx,1\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
980 \r
981 StartAddrEntry:\r
982         mov  bl,ADDR_LOW\r
983         mov  cl,ADDR_HIGH\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
987         mov  si,ax\r
988 \r
989         cmp  [_VsyncHandlerActive],TRUE\r
990         jne   @@NoVsyncHandler\r
991 ; NEW STUFF\r
992 @@WaitLast:\r
993         cmp   [_StartAddressFlag],0\r
994         jne   @@WaitLast\r
995         cli\r
996         mov  [_WaitingStartLow],bx\r
997         mov  [_WaitingStartHigh],cx\r
998         mov  [_WaitingPelPan],si\r
999         mov  [_StartAddressFlag],1\r
1000         sti\r
1001         jmp  short @@Return\r
1002 \r
1003 @@NoVsyncHandler:\r
1004         mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse\r
1005 @@WaitDE:\r
1006         in   al,dx\r
1007         test al,01h\r
1008         jnz  @@WaitDE            ;display enable is active low (0 = active)\r
1009 \r
1010         mov  dx,CRTC_INDEX\r
1011         mov  ax,bx\r
1012         cli\r
1013         out  dx,ax               ;start address low\r
1014         mov  ax,cx\r
1015         out  dx,ax               ;start address high\r
1016         sti\r
1017 \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
1021 @@WaitVS:\r
1022         in   al,dx\r
1023         test al,08h\r
1024         jz @@WaitVS           ;display enable is active low (0 = active)\r
1025 \r
1026 \r
1027         mov  dx,AC_INDEX\r
1028         mov  ax,si                ; Point the attribute controller to pel pan\r
1029         cli\r
1030         out  dx,al                ; reg. Bit 5 also set to prevent blanking\r
1031         mov  al,ah\r
1032         out  dx,al                ; load new Pel Pan setting.\r
1033         sti\r
1034 \r
1035 @@Return:\r
1036         mov  [_ErrorValue],OK\r
1037         pop  si\r
1038         pop  bp\r
1039         ret\r
1040 _x_set_start_addr  endp\r
1041 \r
1042 \r
1043 ;-----------------------------------------------------------------------\r
1044 ; Mode X (256 color mode) Mode X split screen hide\r
1045 ; C near-callable as:\r
1046 ;\r
1047 ;    void x_hide_splitscreen()\r
1048 ;\r
1049 ; Hides an existing split screen by setting its starting scan line to\r
1050 ; the last physical screen scan line\r
1051 ;\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
1057 ;\r
1058 ; Written by Themie Gouthas\r
1059 ;------------------------------------------------------------------------\r
1060 \r
1061 _x_hide_splitscreen proc\r
1062         push bp\r
1063         mov  bp,sp\r
1064 \r
1065         cmp  [_SplitScrnActive],TRUE\r
1066         je   @@SplitScreenEnabled\r
1067 \r
1068 @@error0:\r
1069         mov  [_ErrorValue],ERROR\r
1070         pop  bp\r
1071         ret\r
1072 \r
1073 @@SplitScreenEnabled:\r
1074         cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
1075         jg   @@error0\r
1076         mov  bx,[_ScrnPhysicalHeight]\r
1077 \r
1078         mov  ax,[_ScrnLogicalHeight]\r
1079         sub  ax,bx\r
1080         mov  [_MaxScrollY],ax\r
1081         xor  ax,ax\r
1082         mov  [_SplitScrnVisibleHeight],ax\r
1083 \r
1084         or    [DoubleScanFlag],0\r
1085         jz    @@NotDoubleScanned0\r
1086         shl   bx,1\r
1087         dec   bx\r
1088 @@NotDoubleScanned0:\r
1089         ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes\r
1090         ;shl  bx,cl\r
1091 \r
1092         WaitVsyncStart               ; wait for vertical retrace\r
1093 \r
1094         cli                 ; Dont allow register setting to be interrupted\r
1095         mov  dx,CRTC_INDEX\r
1096         mov  ah,bl\r
1097         mov  al,LINE_COMPARE\r
1098         out  dx,ax          ; Bits 7-0 of the split screen scan line\r
1099 \r
1100         mov  ah,bh\r
1101         and  ah,1\r
1102         shl  ah,1\r
1103         shl  ah,1\r
1104         shl  ah,1\r
1105         shl  ah,1\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
1111         or   al,ah\r
1112         out  dx,al\r
1113 \r
1114         dec  dx\r
1115         mov  ah,bh\r
1116         and  ah,2\r
1117         ror  ah,1\r
1118         ror  ah,1\r
1119         ror  ah,1\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
1124         and  al, not 40h\r
1125         or   al,ah\r
1126         out  dx,al\r
1127         sti                  ; Registers are set, so interrupts are safe\r
1128 \r
1129 @@done0:\r
1130 \r
1131         mov  [_ErrorValue],OK\r
1132         pop  bp\r
1133         ret\r
1134 _x_hide_splitscreen endp\r
1135 \r
1136 ;-----------------------------------------------------------------------\r
1137 ; Mode X (256 color mode) Mode X split screen show\r
1138 ; C near-callable as:\r
1139 ;\r
1140 ;    void x_show_splitscreen()\r
1141 ;\r
1142 ; Restores split screen start scan line to the initial split screen\r
1143 ; starting scan line as set by SplitScrnLine.\r
1144 ;\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
1151 ;\r
1152 ; Written by Themie Gouthas\r
1153 ;------------------------------------------------------------------------\r
1154 \r
1155 \r
1156 _x_show_splitscreen proc\r
1157         push bp\r
1158         mov  bp,sp\r
1159 \r
1160         cmp  [_SplitScrnActive],TRUE\r
1161         je   @@SplitScreenEnabled0\r
1162 \r
1163 @@error1:\r
1164         mov  [_ErrorValue],ERROR\r
1165         pop  bp\r
1166         ret\r
1167 \r
1168 @@SplitScreenEnabled0:\r
1169         cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
1170         jg   @@error1\r
1171 \r
1172         mov  bx,[_SplitScrnScanLine]\r
1173         mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
1174         sub  ax,bx\r
1175         mov  [_MaxScrollY],ax\r
1176 \r
1177         mov  ax,[_ScrnPhysicalHeight]\r
1178         sub  ax,bx\r
1179         mov  [_SplitScrnVisibleHeight],ax\r
1180 \r
1181         or    [DoubleScanFlag],0\r
1182         jz    @@NotDoubleScanned1\r
1183         shl   bx,1\r
1184         dec   bx\r
1185 @@NotDoubleScanned1:\r
1186         ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes\r
1187         ;shl  bx,cl\r
1188         WaitVsyncStart               ; wait for vertical retrace\r
1189 \r
1190         cli                          ; Dont allow register setting to be interrupted\r
1191         mov  dx,CRTC_INDEX\r
1192         mov  ah,bl\r
1193         mov  al,LINE_COMPARE\r
1194         out  dx,ax                  ; Bits 7-0 of the split screen scan line\r
1195 \r
1196         mov  ah,bh\r
1197         and  ah,1\r
1198         shl  ah,1\r
1199         shl  ah,1\r
1200         shl  ah,1\r
1201         shl  ah,1\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
1207         or   al,ah\r
1208         out  dx,al\r
1209 \r
1210         dec  dx\r
1211         mov  ah,bh\r
1212         and  ah,2\r
1213         ror  ah,1\r
1214         ror  ah,1\r
1215         ror  ah,1\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
1220         and  al, not 40h\r
1221         or   al,ah\r
1222         out  dx,al\r
1223         sti                  ; Registers are set, so interrupts are safe\r
1224 \r
1225 @@Done1:\r
1226         mov  [_ErrorValue],0\r
1227         pop  bp\r
1228         ret\r
1229 _x_show_splitscreen endp\r
1230 \r
1231 \r
1232 ;-----------------------------------------------------------------------\r
1233 ; Mode X (256 color mode) Modify Mode X split screen starting scan line\r
1234 ; C near-callable as:\r
1235 ;\r
1236 ;    void x_adjust_splitscreen(unsigned int ScanLine)\r
1237 ;\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
1241 ;\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
1248 ;\r
1249 ;\r
1250 ; Written by Themie Gouthas\r
1251 ;------------------------------------------------------------------------\r
1252 \r
1253 \r
1254 _x_adjust_splitscreen proc\r
1255         ;arg   ScanLine\r
1256         push bp\r
1257         mov  bp,sp\r
1258 \r
1259         cmp  [_SplitScrnActive],TRUE\r
1260         je   @@SplitScreenEnabled1\r
1261 \r
1262 @@error2:\r
1263         mov  [_ErrorValue],ERROR\r
1264         pop  bp\r
1265         ret\r
1266 \r
1267 @@SplitScreenEnabled1:\r
1268         cmp  [_CurrXMode],4          ; Do nothing for Modes > 2\r
1269         jg   @@error2\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
1273 \r
1274 @@ValidScanLine:\r
1275 \r
1276         mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y\r
1277         sub  ax,bx\r
1278         mov  [_MaxScrollY],ax\r
1279 \r
1280         mov  ax,[_ScrnPhysicalHeight]\r
1281         sub  ax,bx\r
1282         mov  [_SplitScrnVisibleHeight],ax\r
1283 \r
1284         or    [DoubleScanFlag],0\r
1285         jz    @@NotDoubleScanned2\r
1286         shl   bx,1\r
1287         dec   bx\r
1288 @@NotDoubleScanned2:\r
1289         ;mov  cl,[DoubleScanFlag]   ; Compensate for double scanned modes\r
1290         ;shl  bx,cl\r
1291 \r
1292         WaitVsyncStart      ; wait for vertical retrace\r
1293 \r
1294         cli                 ; Dont allow register setting to be interrupted\r
1295 \r
1296         mov  dx,CRTC_INDEX\r
1297         mov  ah,bl\r
1298         mov  al,LINE_COMPARE\r
1299         out  dx,ax          ; Bits 7-0 of the split screen scan line\r
1300 \r
1301         mov  ah,bh\r
1302         and  ah,1\r
1303         shl  ah,1\r
1304         shl  ah,1\r
1305         shl  ah,1\r
1306         shl  ah,1\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
1312         or   al,ah\r
1313         out  dx,al\r
1314 \r
1315         dec  dx\r
1316         mov  ah,bh\r
1317         and  ah,2\r
1318         ror  ah,1\r
1319         ror  ah,1\r
1320         ror  ah,1\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
1325         and  al, not 40h\r
1326         or   al,ah\r
1327         out  dx,al\r
1328         sti                    ; Registers are set, so interrupts are safe\r
1329 @@Done2:\r
1330         mov  [_ErrorValue],OK\r
1331         pop   bp\r
1332         ret\r
1333 _x_adjust_splitscreen endp\r
1334 \r
1335 \r
1336 \r
1337 ;-----------------------------------------------------------------------\r
1338 ; Mode X (256 color mode) Enable DoubleBuffering on non split screen area\r
1339 ; C near-callable as:\r
1340 ;\r
1341 ;    int x_set_doublebuffer(unsigned int PageHeight);\r
1342 ;\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
1345 ;\r
1346 ; Sets up two double buffering virtual pages\r
1347 ; GLOBAL variables set:\r
1348 ;\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
1354 ;\r
1355 ;\r
1356 ; Written by Themie Gouthas\r
1357 ;------------------------------------------------------------------------\r
1358 \r
1359 \r
1360 _x_set_doublebuffer proc\r
1361            ;arg PageHeight:word\r
1362            push  bp\r
1363            mov   bp,sp\r
1364 \r
1365            cmp   [_DoubleBufferActive],0\r
1366            je    @@OkToContinue\r
1367 @error:\r
1368            mov   [_ErrorValue],ERROR\r
1369            pop   bp\r
1370            ret\r
1371 \r
1372 @@OkToContinue:\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
1376 \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
1379 \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
1383 \r
1384 @@InvalidHeight:\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
1390 @@BottomClipOK0:\r
1391            push  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
1396 \r
1397            add   ax,bx\r
1398            mov   [_Page1_Offs],ax           ; Save it\r
1399            mov   [_HiddenPageOffs],ax\r
1400 \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
1404 \r
1405            pop   ax\r
1406            sub   ax,[_ScrnPhysicalHeight]\r
1407            add   ax,[_SplitScrnVisibleHeight]\r
1408            mov   [_MaxScrollY],ax\r
1409 \r
1410            mov   ax,dx                      ; return the D.B. pages' height\r
1411            mov   [_ErrorValue],OK\r
1412            pop   bp\r
1413            ret\r
1414 _x_set_doublebuffer endp\r
1415 \r
1416 \r
1417 ;-----------------------------------------------------------------------\r
1418 ; Mode X (256 color mode) Enable TrippleBuffering on non split screen area\r
1419 ; C near-callable as:\r
1420 ;\r
1421 ;    int x_set_tripplebuffer(unsigned int PageHeight);\r
1422 ;\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
1425 ;\r
1426 ; Sets up two tripple buffering virtual pages\r
1427 ; GLOBAL variables set:\r
1428 ;\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
1435 ;\r
1436 ;\r
1437 ; Almost written by Tore Bastiansen (cut & paste from _x_set_doublebuffer)\r
1438 ;------------------------------------------------------------------------\r
1439 \r
1440 _x_set_tripplebuffer proc\r
1441            ;arg PageHeight:word\r
1442            push  bp\r
1443            mov   bp,sp\r
1444 \r
1445            cmp   [_DoubleBufferActive],0\r
1446            jne   @@Error3\r
1447            cmp   [_TrippleBufferActive],0\r
1448            je    @@OkToContinue3\r
1449 @@Error3:\r
1450            mov   [_ErrorValue],ERROR\r
1451            pop   bp\r
1452            ret\r
1453 \r
1454 @@OkToContinue3:\r
1455            mov   [_VisiblePageIdx],0     ; Set visible Page to 0\r
1456            mov   ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to\r
1457            mov   bx,3\r
1458            xor   dx,dx\r
1459            idiv  bx                      ;   _ScrnLogicalHeight / 3\r
1460 \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
1463 \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
1467 \r
1468 @@InvalidHeight0:\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
1474 @@BottomClipOK1:\r
1475            push  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
1480 \r
1481            add   ax,bx\r
1482            mov   [_Page1_Offs],ax           ; Save it\r
1483            mov   [_HiddenPageOffs],ax\r
1484 \r
1485            add   ax,cx\r
1486            mov   [_Page2_Offs],ax            ; Save the other it ?\r
1487            mov   [_WaitingPageOffs],ax\r
1488 \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
1492 \r
1493            pop   ax\r
1494            sub   ax,[_ScrnPhysicalHeight]\r
1495            add   ax,[_SplitScrnVisibleHeight]\r
1496            mov   [_MaxScrollY],ax\r
1497 \r
1498            mov   ax,dx                      ; return the D.B. pages' height\r
1499            mov   [_ErrorValue],OK\r
1500            pop   bp\r
1501            ret\r
1502 _x_set_tripplebuffer endp\r
1503 \r
1504 \r
1505 ;-----------------------------------------------------------------------\r
1506 ; Set Clipping rectangle\r
1507 ; C callable as:\r
1508 ;\r
1509 ;\r
1510 ;    int x_set_cliprect(WORD left,WORD top, WORD right, WORD bottom);\r
1511 ;\r
1512 ;\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
1515 ;\r
1516 ; Written by Themie Gouthas\r
1517 ;------------------------------------------------------------------------\r
1518 \r
1519 _x_set_cliprect proc\r
1520 ;arg left:word,top:word,right:word,bottom:word\r
1521        push  bp\r
1522        mov   bp,sp\r
1523        mov   ax,[bp+4]\r
1524        mov   bx,[bp+8]\r
1525        cmp   bx,ax\r
1526        jns   @@CorrectXOrder\r
1527        xchg  bx,ax\r
1528 @@CorrectXOrder:\r
1529        mov   [_LeftClip],ax\r
1530        mov   [_RightClip],bx\r
1531            mov   ax,[bp+6]\r
1532        mov   bx,[bp+10]\r
1533        cmp   bx,ax\r
1534            jns   @@CorrectYOrder\r
1535        xchg  bx,ax\r
1536 @@CorrectYOrder:\r
1537        mov   [_TopClip],ax\r
1538        mov   [_BottomClip],bx\r
1539        pop   bp\r
1540        ret\r
1541 _x_set_cliprect endp\r
1542 \r
1543 \r
1544 ;----------------------------------------------------------------------\r
1545 ; Return to text mode\r
1546 ;\r
1547 _x_text_mode proc\r
1548        push  bp\r
1549        call  clear_vram\r
1550        mov   ax,03h        ; Restore Text Mode\r
1551        int   10h\r
1552 \r
1553        pop   bp\r
1554        ret\r
1555 _x_text_mode endp\r
1556 \r
1557 ;-----------------------------------------------------------------------\r
1558 ; Wait for Vertical sync\r
1559 _x_wait_vsync proc\r
1560         push  bp\r
1561         WaitVsyncStart\r
1562         pop   bp\r
1563         ret\r
1564 _x_wait_vsync endp\r
1565 \r
1566 \r
1567 end\r