]> 4ch.mooo.com Git - 16.git/blob - 16/x/mxsm.asm
push
[16.git] / 16 / x / mxsm.asm
1 ;-----------------------------------------------------------\r
2 ;\r
3 ; MXSM.ASM - Set/change mode functions\r
4 ; Copyright (c) 1993,1994 by Alessandro Scotti\r
5 ;\r
6 ;-----------------------------------------------------------\r
7 WARN    PRO\r
8 INCLUDE MODEX.DEF\r
9 \r
10 PUBLIC  mxChangeMode\r
11 PUBLIC  mxGetAspect\r
12 PUBLIC  mxGetScreenSize\r
13 PUBLIC  mxSetMode\r
14 \r
15 PUBLIC  mx_ScreenWidth\r
16 PUBLIC  mx_ScreenHeight\r
17 PUBLIC  mx_BytesPerLine\r
18 \r
19 MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
20                 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
21 \r
22 EXTRN   mxSetSysClipRegion      : FAR\r
23 \r
24 EXTRN   mx_VideoSegment : WORD\r
25 EXTRN   mx_CodeSegment  : WORD\r
26 \r
27 mx_ScreenWidth  DW      ?               ; Current screen width\r
28 mx_ScreenHeight DW      ?\r
29 mx_AspectX      DW      ?               ; Aspect ratio for current mode\r
30 mx_AspectY      DW      ?\r
31 mx_BytesPerLine DW      0               ; Bytes per line\r
32 \r
33 ;\r
34 ; Tables for setting video modes, sources:\r
35 ; - MODEX.ASM, Matt Pritchard\r
36 ; - Dr. Dobb's Journal, Michael Abrash\r
37 ; - Fractint VIDEO.ASM module\r
38 ;\r
39 TBL_SingleLine  LABEL   WORD            ; CRTC\r
40         DW      04009h                  ; Cell height: 1 scan line\r
41         DW      00014h                  ; Double word mode off\r
42         DW      0E317h                  ; Byte mode on\r
43         DW      0\r
44 TBL_DoubleLine  LABEL   WORD            ; CRTC\r
45         DW      04109h                  ; Cell height: 2 scan lines\r
46         DW      00014h\r
47         DW      0E317h\r
48         DW      0\r
49 TBL_Width320    LABEL   WORD            ; CRTC\r
50         DW      05F00h                  ; Horizontal total\r
51         DW      04F01h                  ; Horizontal displayed\r
52         DW      05002h                  ; Start horizontal blanking\r
53         DW      08203h                  ; End horizontal blanking\r
54         DW      05404h                  ; Start horizontal sync\r
55         DW      08005h                  ; End horizontal sync\r
56         DW      02813h                  ; Row address\r
57         DW      0\r
58 TBL_Width360    LABEL   WORD            ; CRTC\r
59         DW      06B00h                  ; Horizontal total\r
60         DW      05901h                  ; Horizontal displayed\r
61         DW      05A02h                  ; Start horizontal blanking\r
62         DW      08E03h                  ; End horizontal blanking\r
63         DW      05E04h                  ; Start horizontal sync\r
64         DW      08A05h                  ; End horizontal sync\r
65         DW      02D13h                  ; Row address\r
66         DW      0\r
67 TBL_Height175   LABEL   WORD            ; CRTC\r
68         DW      0BF06h                  ; Vertical total\r
69         DW      01F07h                  ; Overflow\r
70         DW      08310h                  ; Start vertical sync\r
71         DW      08511h                  ; End vertical sync\r
72         DW      05D12h                  ; Vertical displayed\r
73         DW      06315h                  ; Start vertical blanking\r
74         DW      0BA16h                  ; End vertical blanking\r
75         DW      0\r
76 TBL_Height200   LABEL   WORD            ; CRTC\r
77         DW      0BF06h                  ; Vertical total\r
78         DW      01F07h                  ; Overflow\r
79         DW      09C10h                  ; Start vertical sync\r
80         DW      08E11h                  ; End vertical sync\r
81         DW      08F12h                  ; Vertical displayed\r
82         DW      09615h                  ; Start vertical blanking\r
83         DW      0B916h                  ; End vertical blanking\r
84         DW      0\r
85 TBL_Height240   LABEL   WORD            ; CRTC\r
86         DW      00D06h                  ; Vertical total\r
87         DW      03E07h                  ; Overflow\r
88         DW      0EA10h                  ; Start vertical sync\r
89         DW      08C11h                  ; End vertical sync\r
90         DW      0DF12h                  ; Vertical displayed\r
91         DW      0E715h                  ; Start vertical blanking\r
92         DW      00616h                  ; End vertical blanking\r
93         DW      0\r
94 TBL_Tweak400x600:\r
95         DW      07400h\r
96         DW      06301h\r
97         DW      06402h\r
98         DW      09703h\r
99         DW      06804h\r
100         DW      09505h\r
101         DW      08606h\r
102         DW      0F007h\r
103         DW      06009h\r
104         DW      0310Fh\r
105         DW      05B10h\r
106         DW      08D11h\r
107         DW      05712h\r
108         DW      03213h\r
109         DW      00014h\r
110         DW      06015h\r
111         DW      08016h\r
112         DW      0E317h\r
113         DW      0\r
114 \r
115 TBL_320x200:\r
116         DB      63h                     ; 400 scan lines, 25 MHz clock\r
117         DW      6, 5                    ; Aspect: 6/5 = 1.2:1\r
118         DW      320, 200                ; Size\r
119         DW      TBL_Width320, TBL_Height200, TBL_DoubleLine, 0\r
120         DW      819                     ; Max height\r
121 TBL_320x240:\r
122         DB      0E3h                    ; 400 scan lines, 25 MHz clock\r
123         DW      1, 1                    ; Aspect: 1/1 = 1:1\r
124         DW      320, 240                ; Size\r
125         DW      TBL_Width320, TBL_Height240, TBL_DoubleLine, 0\r
126         DW      819                     ; Max height\r
127 TBL_320x400:\r
128         DB      63h                     ; 480 scan lines, 25 MHz clock\r
129         DW      6, 10                   ; Aspect: 6/10 = 0.6:1\r
130         DW      320, 400                ; Size\r
131         DW      TBL_Width320, TBL_Height200, TBL_SingleLine, 0\r
132         DW      819                     ; Max height\r
133 TBL_320x480:\r
134         DB      0E3h                    ; 480 scan lines, 25 MHz clock\r
135         DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
136         DW      320, 480                ; Size\r
137         DW      TBL_Width320, TBL_Height240, TBL_SingleLine, 0\r
138         DW      819                     ; Max height\r
139 TBL_360x200:\r
140         DB      067h                    ; 400 scan lines, 28 MHz clock\r
141         DW      27, 20                  ; Aspect: 27/20 = 1.35:1\r
142         DW      360, 200                ; Size\r
143         DW      TBL_Width360, TBL_Height200, TBL_DoubleLine, 0\r
144         DW      728                     ; Max height\r
145 TBL_360x240:\r
146         DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
147         DW      9, 8                    ; Aspect: 9/8 = 1.125:1\r
148         DW      360, 240                ; Size\r
149         DW      TBL_Width360, TBL_Height240, TBL_DoubleLine, 0\r
150         DW      728                     ; Max height\r
151 TBL_360x400:\r
152         DB      067h                    ; 400 scan lines, 28 MHz clock\r
153         DW      27, 40                  ; Aspect: 27/40 = 0.675:1\r
154         DW      360, 400                ; Size\r
155         DW      TBL_Width360, TBL_Height200, TBL_SingleLine, 0\r
156         DW      728                     ; Max height\r
157 TBL_360x480:\r
158         DB      0E7h                    ; 480 scan lines, 28 MHz clock\r
159         DW      9, 16                   ; Aspect: 9/16 = 0.5625:1\r
160         DW      360, 480                ; Size\r
161         DW      TBL_Width360, TBL_Height240, TBL_SingleLine, 0\r
162         DW      728                     ; Max height\r
163 TBL_320x175:\r
164         DB      0A3h\r
165         DW      0, 0                    ; Aspect:\r
166         DW      320, 175\r
167         DW      TBL_Width320, TBL_Height175, TBL_DoubleLine, 0\r
168         DW      819\r
169 TBL_320x350:\r
170         DB      0A3h\r
171         DW      0, 0                    ; Aspect:\r
172         DW      320, 175\r
173         DW      TBL_Width320, TBL_Height175, TBL_SingleLine, 0\r
174         DW      819\r
175 TBL_360x175:\r
176         DB      0A7h\r
177         DW      0, 0                    ; Aspect:\r
178         DW      360, 480                ; Size\r
179         DW      TBL_Width360, TBL_Height175, TBL_DoubleLine, 0\r
180         DW      728                     ; Max height\r
181 TBL_360x350:\r
182         DB      0A7h\r
183         DW      0, 0                    ; Aspect:\r
184         DW      360, 480                ; Size\r
185         DW      TBL_Width360, TBL_Height175, TBL_SingleLine, 0\r
186         DW      728                     ; Max height\r
187 TBL_400x600:\r
188         DB      0E7h                    ; 28 MHz clock\r
189         DW      1, 2                    ; Aspect: 1/2 = 0.5:1\r
190         DW      400, 600                ; Size\r
191         DW      TBL_Tweak400x600, 0\r
192         DW      655                     ; Max height\r
193 \r
194 TBL_Mode        LABEL   WORD\r
195         DW      TBL_320x175\r
196         DW      TBL_320x200\r
197         DW      TBL_320x240\r
198         DW      TBL_320x350\r
199         DW      TBL_320x400\r
200         DW      TBL_320x480\r
201         DW      TBL_360x175\r
202         DW      TBL_360x200\r
203         DW      TBL_360x240\r
204         DW      TBL_360x350\r
205         DW      TBL_360x400\r
206         DW      TBL_360x480\r
207         DW      TBL_400x600\r
208 \r
209 MAXVMODE        EQU     ($-OFFSET TBL_Mode) / 2\r
210 \r
211 ;-----------------------------------------------------------\r
212 ;\r
213 ; Enables 80x25 color text mode\r
214 ;\r
215 subText         PROC    NEAR\r
216         ASSUME  ds:MX_TEXT\r
217         mov     ax, 0003h\r
218         int     10h                     ; Call BIOS set mode\r
219 \r
220         mov     [mx_ScreenHeight], 0\r
221         mov     [mx_BytesPerLine], 0\r
222         ret\r
223 subText         ENDP\r
224 \r
225 ;-----------------------------------------------------------\r
226 ;\r
227 ; Enables the selected graphics mode.\r
228 ;\r
229 ; Input:\r
230 ;       Mode    = mode to select (MX_???x???)\r
231 ; Output:\r
232 ;       none\r
233 ;\r
234 mxSetMode       PROC    FAR\r
235         ARG     Mode:WORD       = ARG_SIZE\r
236         ASSUME  ds:NOTHING\r
237         .enter  0\r
238         .push   ds, si, es, di\r
239 \r
240 ; Set DS to code segment alias\r
241         mov     ds, [mx_CodeSegment]\r
242         ASSUME  ds:MX_TEXT\r
243 \r
244         mov     si, [Mode]\r
245         cmp     si, MAXVMODE            ; Is it a valid mode?\r
246         ja      @@Exit                  ; No, exit\r
247         test    si, si                  ; Text mode?\r
248         jnz     @@Set                   ; No, handle it\r
249 \r
250         call    subText                 ; Back to text mode\r
251         jmp     @@Exit                  ; Exit now\r
252 \r
253 ; Set video mode\r
254 @@Set:\r
255         dec     si                      ; Skip text mode\r
256         shl     si, 1\r
257         mov     si, TBL_Mode[si]\r
258         cld\r
259 \r
260 ; Use BIOS to set 320x200x256 linear mode\r
261         push    si                      ; Save SI\r
262         mov     ax, 0013h\r
263         int     10h                     ; Use BIOS to set 320x200 linear mode\r
264         pop     si                      ; Restore SI\r
265 \r
266         mov     dx, TS\r
267         mov     ax, 0604h\r
268         out     dx, ax                  ; Disable chain-4 mode\r
269         mov     ax, 0100h\r
270         out     dx, ax                  ; Reset\r
271         mov     dx, MISC\r
272         lodsb\r
273         out     dx, al                  ; New timing/size\r
274         mov     dx, TS\r
275         mov     ax, 0300h\r
276         out     dx, ax                  ; Restart sequencer\r
277 \r
278 ; Unlock CRTC registers 0-7\r
279         mov     dx, CRTC\r
280         mov     al, 11h\r
281         out     dx, al                  ; Vertical sync end register\r
282         inc     dx\r
283         in      al, dx\r
284         and     al, 7Fh                 ; Clear write protect bit\r
285         out     dx, al\r
286 \r
287         lodsw                           ; Get X aspect\r
288         mov     [mx_AspectX], ax\r
289         lodsw                           ; Get Y aspect\r
290         mov     [mx_AspectY], ax\r
291         lodsw                           ; Get screen width\r
292         mov     [mx_ScreenWidth], ax\r
293         shr     ax, 1\r
294         shr     ax, 1                   ; Divide by four to get bytes per line\r
295         mov     [mx_BytesPerLine], ax\r
296         lodsw                           ; Get screen height\r
297         mov     [mx_ScreenHeight], ax\r
298 \r
299 ; Set CRTC registers\r
300         mov     bx, si\r
301         mov     dx, CRTC\r
302 @@TableLoop:\r
303         mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
304         inc     bx\r
305         inc     bx                      ; DS:BX -> offset of next table\r
306         test    si, si                  ; Last table?\r
307         jz      @@EndLoop               ; Yes, exit loop\r
308 @@Loop:\r
309         lodsw                           ; Get CRTC register index and value\r
310         test    ax, ax                  ; End of table?\r
311         jz      @@TableLoop             ; Yes, go to next table\r
312         out     dx, ax                  ; Set register AL to value AH\r
313         jmp     @@Loop                  ; Get next register/value\r
314 @@EndLoop:\r
315 \r
316 ; Set virtual screen and system clip region\r
317         push    [mx_ScreenWidth]\r
318         push    WORD PTR ds:[bx]\r
319         call    mxSetSysClipRegion\r
320 \r
321 ; Clear video memory\r
322         mov     dx, TS\r
323         mov     ax, 0F02h\r
324         out     dx, ax                  ; Enable all planes\r
325         mov     es, [mx_VideoSegment]\r
326         xor     di, di\r
327         mov     cx, 8000h\r
328         xor     ax, ax\r
329         rep     stosw\r
330 \r
331 @@Done:\r
332 ; Lock CRTC registers 0-7 (some cards need this)\r
333         mov     dx, CRTC\r
334         mov     al, 11h\r
335         out     dx, al                  ; Vertical sync end register\r
336         inc     dx\r
337         in      al, dx\r
338         or      al, 80h                 ; Set write protect bit\r
339         out     dx, al\r
340 \r
341 @@Exit:\r
342         xor     ax, ax\r
343         mov     ax, [mx_ScreenWidth]\r
344         .pop    ds, si, es, di\r
345         .leave  ARG_SIZE\r
346 mxSetMode       ENDP\r
347 \r
348 ;-----------------------------------------------------------\r
349 ;\r
350 ; Changes from the current mode the selected graphics mode.\r
351 ;\r
352 ; Input:\r
353 ;       Mode    = mode to select (MX_???x???)\r
354 ; Output:\r
355 ;       none\r
356 ; Notes:\r
357 ;       this function assumes that mxSetMode and mxSetVirtualScreen\r
358 ;       have been called first. View size is rearranged to match the\r
359 ;       specified mode, but video memory is not cleared.\r
360 ;       Differences from mxSetMode:\r
361 ;       - video BIOS is not called to initialize graphics;\r
362 ;       - row address register is not modified;\r
363 ;       - video memory is not cleared;\r
364 ;       - mx_BytesPerLine is not modified;\r
365 ;       - system clip region is not modified.\r
366 ;\r
367 mxChangeMode    PROC    FAR\r
368         ARG     Mode:WORD       = ARG_SIZE\r
369         ASSUME  ds:NOTHING\r
370         .enter  0\r
371         .push   ds, si, es, di\r
372 \r
373 ; Set DS to code segment alias\r
374         mov     ds, [mx_CodeSegment]\r
375         ASSUME  ds:MX_TEXT\r
376 \r
377         mov     si, [Mode]\r
378         cmp     si, MAXVMODE            ; Is it a valid mode?\r
379         ja      @@Exit                  ; No, exit\r
380         test    si, si                  ; Text mode?\r
381         jz      @@Exit                  ; Yes, exit\r
382 \r
383         dec     si                      ; Skip text mode\r
384         shl     si, 1\r
385         mov     si, TBL_Mode[si]\r
386         cld\r
387 \r
388         mov     dx, TS\r
389         mov     ax, 0604h\r
390         out     dx, ax                  ; Disable chain-4 mode\r
391         mov     ax, 0100h\r
392         out     dx, ax                  ; Reset\r
393         mov     dx, MISC\r
394         lodsb\r
395         out     dx, al                  ; New timing/size\r
396         mov     dx, TS\r
397         mov     ax, 0300h\r
398         out     dx, ax                  ; Restart sequencer\r
399 \r
400 ; Unlock CRTC registers 0-7\r
401         mov     dx, CRTC\r
402         mov     al, 11h\r
403         out     dx, al                  ; Vertical sync end register\r
404         inc     dx\r
405         in      al, dx\r
406         and     al, 7Fh                 ; Clear write protect bit\r
407         out     dx, al\r
408 \r
409         lodsw                           ; Get X aspect\r
410         mov     [mx_AspectX], ax\r
411         lodsw                           ; Get Y aspect\r
412         mov     [mx_AspectY], ax\r
413         lodsw                           ; Get screen width\r
414         mov     [mx_ScreenWidth], ax\r
415         lodsw                           ; Get screen height\r
416         mov     [mx_ScreenHeight], ax\r
417 \r
418 ; Set CRTC registers\r
419         mov     bx, si\r
420         mov     dx, CRTC\r
421 @@TableLoop:\r
422         mov     si, ds:[bx]             ; DS:SI -> table of CRTC registers\r
423         inc     bx\r
424         inc     bx                      ; DS:BX -> offset of next table\r
425         test    si, si                  ; Last table?\r
426         jz      @@EndLoop               ; Yes, exit loop\r
427 @@Loop:\r
428         lodsw                           ; Get CRTC register index and value\r
429         test    ax, ax                  ; End of table?\r
430         jz      @@TableLoop             ; Yes, go to next table\r
431         cmp     al, 13h                 ; Row address register?\r
432         je      @@Loop                  ; Yes, ignore it\r
433         out     dx, ax                  ; Set register AL to value AH\r
434         jmp     @@Loop                  ; Get next register/value\r
435 @@EndLoop:\r
436 \r
437 ; Lock CRTC registers 0-7 (some cards need this)\r
438         mov     dx, CRTC\r
439         mov     al, 11h\r
440         out     dx, al                  ; Vertical sync end register\r
441         inc     dx\r
442         in      al, dx\r
443         or      al, 80h                 ; Set write protect bit\r
444         out     dx, al\r
445 \r
446 @@Exit:\r
447         xor     ax, ax\r
448         mov     ax, [mx_ScreenWidth]\r
449         .pop    ds, si, es, di\r
450         .leave  ARG_SIZE\r
451 mxChangeMode    ENDP\r
452 \r
453 ;-----------------------------------------------------------\r
454 ;\r
455 ; Returns the aspect ratio for the current mode.\r
456 ;\r
457 ; Input:\r
458 ;       AspectX = pointer to aspect X\r
459 ;       AspectY = pointer to aspect Y\r
460 ;\r
461 ; A rectangle of width AspectX and height AspectY looks like a square.\r
462 ;\r
463 mxGetAspect     PROC FAR\r
464         ARG     AspectY:DWORD,  \\r
465                 AspectX:DWORD   = ARG_SIZE\r
466         .enter  0\r
467         .push   ds, si\r
468         ASSUME  ds:NOTHING\r
469 \r
470         lds     si, [AspectX]\r
471         mov     ax, [mx_AspectX]\r
472         mov     ds:[si], ax\r
473         lds     si, [AspectY]\r
474         mov     ax, [mx_AspectY]\r
475         mov     ds:[si], ax\r
476 \r
477         .pop    ds, si\r
478         .leave  ARG_SIZE\r
479 mxGetAspect     ENDP\r
480 \r
481 ;-----------------------------------------------------------\r
482 ;\r
483 ; Returns the current screen size.\r
484 ;\r
485 ; Input:\r
486 ;       Width   = pointer to screen width\r
487 ;       Height  = pointer to screen height\r
488 ;\r
489 mxGetScreenSize PROC FAR\r
490         ARG     SizeY:DWORD,    \\r
491                 SizeX:DWORD     = ARG_SIZE\r
492         .enter  0\r
493         .push   ds, si\r
494         ASSUME  ds:NOTHING\r
495 \r
496         lds     si, [SizeX]\r
497         mov     ax, [mx_ScreenWidth]\r
498         mov     ds:[si], ax\r
499         lds     si, [SizeY]\r
500         mov     ax, [mx_ScreenHeight]\r
501         mov     ds:[si], ax\r
502 \r
503         .pop    ds, si\r
504         .leave  ARG_SIZE\r
505 mxGetScreenSize ENDP\r
506 \r
507 MX_TEXT         ENDS\r
508 END\r