1 ;-----------------------------------------------------------
\r
3 ; MXSM.ASM - Set/change mode functions
\r
4 ; Copyright (c) 1993,1994 by Alessandro Scotti
\r
6 ;-----------------------------------------------------------
\r
12 PUBLIC mxGetScreenSize
\r
15 PUBLIC mx_ScreenWidth
\r
16 PUBLIC mx_ScreenHeight
\r
17 PUBLIC mx_BytesPerLine
\r
19 MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'
\r
20 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING
\r
22 EXTRN mxSetSysClipRegion : FAR
\r
24 EXTRN mx_VideoSegment : WORD
\r
25 EXTRN mx_CodeSegment : WORD
\r
27 mx_ScreenWidth DW ? ; Current screen width
\r
28 mx_ScreenHeight DW ?
\r
29 mx_AspectX DW ? ; Aspect ratio for current mode
\r
31 mx_BytesPerLine DW 0 ; Bytes per line
\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
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
44 TBL_DoubleLine LABEL WORD ; CRTC
\r
45 DW 04109h ; Cell height: 2 scan lines
\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
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
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
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
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
116 DB 63h ; 400 scan lines, 25 MHz clock
\r
117 DW 6, 5 ; Aspect: 6/5 = 1.2:1
\r
119 DW TBL_Width320, TBL_Height200, TBL_DoubleLine, 0
\r
120 DW 819 ; Max height
\r
122 DB 0E3h ; 400 scan lines, 25 MHz clock
\r
123 DW 1, 1 ; Aspect: 1/1 = 1:1
\r
125 DW TBL_Width320, TBL_Height240, TBL_DoubleLine, 0
\r
126 DW 819 ; Max height
\r
128 DB 63h ; 480 scan lines, 25 MHz clock
\r
129 DW 6, 10 ; Aspect: 6/10 = 0.6:1
\r
131 DW TBL_Width320, TBL_Height200, TBL_SingleLine, 0
\r
132 DW 819 ; Max height
\r
134 DB 0E3h ; 480 scan lines, 25 MHz clock
\r
135 DW 1, 2 ; Aspect: 1/2 = 0.5:1
\r
137 DW TBL_Width320, TBL_Height240, TBL_SingleLine, 0
\r
138 DW 819 ; Max height
\r
140 DB 067h ; 400 scan lines, 28 MHz clock
\r
141 DW 27, 20 ; Aspect: 27/20 = 1.35:1
\r
143 DW TBL_Width360, TBL_Height200, TBL_DoubleLine, 0
\r
144 DW 728 ; Max height
\r
146 DB 0E7h ; 480 scan lines, 28 MHz clock
\r
147 DW 9, 8 ; Aspect: 9/8 = 1.125:1
\r
149 DW TBL_Width360, TBL_Height240, TBL_DoubleLine, 0
\r
150 DW 728 ; Max height
\r
152 DB 067h ; 400 scan lines, 28 MHz clock
\r
153 DW 27, 40 ; Aspect: 27/40 = 0.675:1
\r
155 DW TBL_Width360, TBL_Height200, TBL_SingleLine, 0
\r
156 DW 728 ; Max height
\r
158 DB 0E7h ; 480 scan lines, 28 MHz clock
\r
159 DW 9, 16 ; Aspect: 9/16 = 0.5625:1
\r
161 DW TBL_Width360, TBL_Height240, TBL_SingleLine, 0
\r
162 DW 728 ; Max height
\r
167 DW TBL_Width320, TBL_Height175, TBL_DoubleLine, 0
\r
173 DW TBL_Width320, TBL_Height175, TBL_SingleLine, 0
\r
179 DW TBL_Width360, TBL_Height175, TBL_DoubleLine, 0
\r
180 DW 728 ; Max height
\r
185 DW TBL_Width360, TBL_Height175, TBL_SingleLine, 0
\r
186 DW 728 ; Max height
\r
188 DB 0E7h ; 28 MHz clock
\r
189 DW 1, 2 ; Aspect: 1/2 = 0.5:1
\r
191 DW TBL_Tweak400x600, 0
\r
192 DW 655 ; Max height
\r
194 TBL_Mode LABEL WORD
\r
209 MAXVMODE EQU ($-OFFSET TBL_Mode) / 2
\r
211 ;-----------------------------------------------------------
\r
213 ; Enables 80x25 color text mode
\r
218 int 10h ; Call BIOS set mode
\r
220 mov [mx_ScreenHeight], 0
\r
221 mov [mx_BytesPerLine], 0
\r
225 ;-----------------------------------------------------------
\r
227 ; Enables the selected graphics mode.
\r
230 ; Mode = mode to select (MX_???x???)
\r
235 ARG Mode:WORD = ARG_SIZE
\r
238 .push ds, si, es, di
\r
240 ; Set DS to code segment alias
\r
241 mov ds, [mx_CodeSegment]
\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
250 call subText ; Back to text mode
\r
251 jmp @@Exit ; Exit now
\r
255 dec si ; Skip text mode
\r
257 mov si, TBL_Mode[si]
\r
260 ; Use BIOS to set 320x200x256 linear mode
\r
263 int 10h ; Use BIOS to set 320x200 linear mode
\r
264 pop si ; Restore SI
\r
268 out dx, ax ; Disable chain-4 mode
\r
273 out dx, al ; New timing/size
\r
276 out dx, ax ; Restart sequencer
\r
278 ; Unlock CRTC registers 0-7
\r
281 out dx, al ; Vertical sync end register
\r
284 and al, 7Fh ; Clear write protect bit
\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
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
299 ; Set CRTC registers
\r
303 mov si, ds:[bx] ; DS:SI -> table of CRTC registers
\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
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
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
321 ; Clear video memory
\r
324 out dx, ax ; Enable all planes
\r
325 mov es, [mx_VideoSegment]
\r
332 ; Lock CRTC registers 0-7 (some cards need this)
\r
335 out dx, al ; Vertical sync end register
\r
338 or al, 80h ; Set write protect bit
\r
343 mov ax, [mx_ScreenWidth]
\r
344 .pop ds, si, es, di
\r
348 ;-----------------------------------------------------------
\r
350 ; Changes from the current mode the selected graphics mode.
\r
353 ; Mode = mode to select (MX_???x???)
\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
367 mxChangeMode PROC FAR
\r
368 ARG Mode:WORD = ARG_SIZE
\r
371 .push ds, si, es, di
\r
373 ; Set DS to code segment alias
\r
374 mov ds, [mx_CodeSegment]
\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
383 dec si ; Skip text mode
\r
385 mov si, TBL_Mode[si]
\r
390 out dx, ax ; Disable chain-4 mode
\r
395 out dx, al ; New timing/size
\r
398 out dx, ax ; Restart sequencer
\r
400 ; Unlock CRTC registers 0-7
\r
403 out dx, al ; Vertical sync end register
\r
406 and al, 7Fh ; Clear write protect bit
\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
418 ; Set CRTC registers
\r
422 mov si, ds:[bx] ; DS:SI -> table of CRTC registers
\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
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
437 ; Lock CRTC registers 0-7 (some cards need this)
\r
440 out dx, al ; Vertical sync end register
\r
443 or al, 80h ; Set write protect bit
\r
448 mov ax, [mx_ScreenWidth]
\r
449 .pop ds, si, es, di
\r
453 ;-----------------------------------------------------------
\r
455 ; Returns the aspect ratio for the current mode.
\r
458 ; AspectX = pointer to aspect X
\r
459 ; AspectY = pointer to aspect Y
\r
461 ; A rectangle of width AspectX and height AspectY looks like a square.
\r
463 mxGetAspect PROC FAR
\r
464 ARG AspectY:DWORD, \
\r
465 AspectX:DWORD = ARG_SIZE
\r
471 mov ax, [mx_AspectX]
\r
474 mov ax, [mx_AspectY]
\r
481 ;-----------------------------------------------------------
\r
483 ; Returns the current screen size.
\r
486 ; Width = pointer to screen width
\r
487 ; Height = pointer to screen height
\r
489 mxGetScreenSize PROC FAR
\r
491 SizeX:DWORD = ARG_SIZE
\r
497 mov ax, [mx_ScreenWidth]
\r
500 mov ax, [mx_ScreenHeight]
\r
505 mxGetScreenSize ENDP
\r