File: dos\video.asm
1 ; Generic assembler routines having to do with video adapter
2 ;
3 ; ---- Video Routines
4 ;
5 ; setvideomode()
6 ; setvideotext()
7 ; getcolor()
8 ; putcolor_a()
9 ; gettruecolor()
10 ; puttruecolor()
11 ; rgb_to_dac()
12 ; dac_to_rgb()
13 ; out_line()
14 ; drawbox()
15 ; home()
16 ; movecursor()
17 ; keycursor()
18 ; putstring()
19 ; setattr()
20 ; scrollup()
21 ; scrolldown()
22 ; putstr()
23 ; loaddac()
24 ; spindac()
25 ; adapter_init
26 ; adapter_detect
27 ; setnullvideo
28 ; scroll_center()
29 ; scroll_relative()
30 ; scroll_state()
31 ;
32 ; ---- Help (Video) Support
33 ;
34 ; setfortext()
35 ; setforgraphics()
36 ; setclear()
37 ; findfont()
38 ;
39
40 ; required for compatibility if Turbo ASM
41 IFDEF ??version
42 MASM51
43 QUIRKS
44 ENDIF
45
46 .MODEL medium,c
47
48 .8086
49
50 ; these must NOT be in any segment!!
51 ; this get's rid of TURBO-C fixup errors
extrn startvideo:far ; start your-own-video routine
extrn readvideo:far ; read your-own-video routine
extrn writevideo:far ; write your-own-video routine
extrn endvideo:far ; end your-own-video routine
extrn readvideopalette:far ; read-your-own-palette routine
extrn writevideopalette:far ; write-your-own-palette routine
extrn startdisk:far ; start disk-video routine
extrn readdisk:far ; read disk-video routine
extrn writedisk:far ; write disk-video routine
extrn enddisk:far ; end disk-video routine
extrn buzzer:far ; nyaah, nyaah message
extrn getakey:far ; for keycursor routine
extrn keypressed:far ; ...
; TARGA 28 May 80 - j mclain
extrn StartTGA :far ; start TARGA
extrn ReadTGA :far ; read TARGA
extrn WriteTGA :far ; write TARGA
extrn EndTGA :far ; end TARGA
extrn ReopenTGA :far ; restart TARGA
; TARGA+ Mark Peterson 2-12-91
extrn MatchTPlusMode:far
extrn CheckForTPlus:far
extrn WriteTPlusBankedPixel:far
extrn ReadTPlusBankedPixel:far
extrn TPlusLUT:far
; 8514/A routines ; changed 8514/A routines to near JCO 4/11/92
; And back to far, JCO 4/13/97
extrn open8514 :far ; start 8514a
extrn reopen8514:far ; restart 8514a
extrn close8514 :far ; stop 8514a
extrn fr85wdot :far ; 8514a write dot
extrn fr85wbox :far ; 8514a write box
extrn fr85rdot :far ; 8514a read dot
extrn fr85rbox :far ; 8514a read box
extrn w8514pal :far ; 8514a pallete update
; HW Compatible 8514/A routines ; AW, made near JCO 4/11/92
; And back to far, JCO 4/13/97
extrn open8514hw :far ; start 8514a
extrn reopen8514hw:far ; restart 8514a
extrn close8514hw :far ; stop 8514a
extrn fr85hwwdot :far ; 8514a write dot
extrn fr85hwwbox :far ; 8514a write box
extrn fr85hwrdot :far ; 8514a read dot
extrn fr85hwrbox :far ; 8514a read box
extrn w8514hwpal :far ; 8514a pallete update
; Hercules Routines
extrn inithgc :far ; Initialize Hercules card graphics mode
extrn termhgc :far ; Terminate Hercules card graphics mode
extrn writehgc :far ; Hercules write dot
extrn readhgc :far ; Hercules read dot
; setforgraphics/setfortext textsafe=save
extrn savegraphics :far
extrn restoregraphics :far
.DATA
; ************************ External variables *****************************
extrn oktoprint: word ; flag: == 1 if printf() will work
extrn videoentry:byte ; video table entry flag
extrn dotmode: word ; video mode (see the comments
; in front of the internal video
; table for legal dot modes)
extrn textsafe2: word ; textsafe over-ride from videotable
extrn sxdots:word,sydots:word ; physical screen number of dots
extrn sxoffs:word,syoffs:word ; logical screen top left
extrn colors:word ; colors
extrn cyclelimit:word ; limiting factor for DAC-cycler
extrn debugflag:word ; for debugging purposes only
extrn boxcount:word ; (previous) box pt counter: 0 if none.
extrn cpu:word ; CPU type (86, 186, 286, or 386)
extrn extraseg:word ; location of the EXTRA segment
extrn suffix:word ; (safe place during video-mode switches)
extrn swaplength:word ; savegraphics/restoregraphics stuff
extrn swapoffset:dword ; ...
extrn swapvidbuf:dword ; ...
extrn swaptotlen:dword ; ...
extrn rotate_lo:word, rotate_hi:word
extrn bios_palette:word
extrn paldata:byte
extrn realcoloriter:dword
extrn coloriter:dword
extrn truemode:word
extrn xdots:word
extrn ydots:word
extrn colors:word
extrn NonInterlaced:word
extrn PixelZoom:word
extrn MaxColorRes:word
extrn TPlusFlag:WORD ; TARGA+ Mark Peterson 2-12-91
extrn ai_8514:byte ;flag for 8514a afi JCO 4/11/92
; ************************ Public variables *****************************
public andcolor ; used by 'calcmand'
public videotable
public loadPalette ; flag for loading VGA/TARGA palette from disk
public dacbox ; GIF saves use this
public daclearn, daccount ; Rotate may want to use this
public rowcount ; row-counter for decoder and out_line
public gotrealdac ; loaddac worked, really got a dac
public reallyega ; "really an EGA" (faking a VGA) flag
public diskflag ; disk video active flag
public video_type ; video adapter type
public svga_type ; SuperVGA video adapter type
public mode7text ; for egamono and hgc
public textaddr ; text segment
public textsafe ; setfortext/setforgraphics logic
public goodmode ; video mode ok?
public text_type ; current mode's type of text
52 public textrow ; current row in text mode
53 public textcol ; current column in text mode
54 public textrbase ; textrow is relative to this
55 public textcbase ; textcol is relative to this
56
57 public color_dark ; darkest color in palette
58 public color_bright ; brightest color in palette
59 public color_medium ; nearest to medbright grey in palette
60
61 public swapsetup ; for savegraphics/restoregraphics
62
63 public TPlusInstalled
64
65 public vesa_detect ; set to 0 to disable VESA-detection
66 public vesa_xres ; real screen width
67 public vesa_yres ; real screen height
68
69 public vxdots ; virtual scan line length
70 public video_scroll ; is-scrolling-on? flag
71 public video_startx ; scrolled horizontaly this far
72 public video_starty ; scrolled verticaly this far
73 public video_vram ; VRAM size
74 public virtual ; enable/disable virtual screen mode
75 public chkd_vvs ; we've run VESAvirtscan once
public istruecolor ; 1 if VESA truecolor mode, 0 otherwise
; arrays declared here, used elsewhere
; arrays not used simultaneously are deliberately overlapped
; ************************ Internal variables *****************************
vxdots dw 0 ; virtual scan line length (bytes)
video_scroll dw 0 ; is-scrolling-on? flag
video_vram dw 0 ; VRAM size
virtual dw 1 ; enable/disable virtual screen mode
video_startx dw 0 ; scrolled horizontaly this far
video_starty dw 0 ; scrolled verticaly this far
video_cofs_x dw 0 ; half of the physical screen width
video_cofs_y dw 0 ; half of the physical screen height
video_slim_x dw 0 ; left-col limit for scrolling right
video_slim_y dw 0 ; top-line limit for scrolling down
scroll_savex dw 0 ; for restoring screen center position
scroll_savey dw 0 ; when unstacking the scrolled screen
wait_retrace dw 0 ; wait for retrace (80h) or not (00h)?
goodmode dw 0 ; if non-zero, OK to read/write pixels
dotwrite dw 0 ; write-a-dot routine: mode-specific
dotread dw 0 ; read-a-dot routine: mode-specific
linewrite dw 0 ; write-a-line routine: mode-specific
lineread dw 0 ; read-a-line routine: mode-specific
swapsetup dd 0 ; setfortext/graphics setup routine
andcolor dw 0 ; "and" value used for color selection
color db 0 ; the color to set a pixel
videoflag db 0 ; special "your-own-video" flag
tgaflag db 0 ; TARGA 28 May 89 - j mclain
loadPalette db 0 ; TARGA/VGA load palette from disk
f85flag db 0 ;flag for 8514a
HGCflag db 0 ;flag for Hercules Graphics Adapter
TPlusInstalled dw 0
xga_pos_base dw 0 ; MCA Pos Base value
xga_cardid dw 0 ; MCA Card ID value
xga_reg_base dw -1 ; XGA IO Reg Base (-1 means dunno yet)
xga_1mb dd 0 ; XGA 1MB aperture address
xga_4mb dd 0 ; XGA 4MB aperture address
xga_result dw 0 ; XGA_detect result code
xga_isinmode dw 0 ; XGA is in this mode right now
xga_iscolors dw 0 ; XGA using this many colors (0=64K)
xga_clearvideo db 0 ; set to 80h to prevent video-clearing
xga_loaddac db 0 ; set to 1 to load 'dacbox' on modesw
xga_xdots dw 0 ; pixels per scan line
align 2
tmpbufptr dd 0
color_dark dw 0 ; darkest color in palette
color_bright dw 0 ; brightest color in palette
color_medium dw 0 ; nearest to medbright grey in palette
; ; Zoom-Box values (2K x 2K screens max)
reallyega dw 0 ; 1 if its an EGA posing as a VGA
gotrealdac dw 0 ; 1 if loaddac has a dacbox
diskflag dw 0 ; special "disk-video" flag
palettega db 17 dup(0) ; EGA palette registers go here
dacnorm db 0 ; 0 if "normal" DAC update
daclearn dw 0 ; 0 if "learning" DAC speed
daccount dw 0 ; DAC registers to update in 1 pass
dacbox db 773 dup(0) ; DAC goes here
;;saved_dacreg dw 0ffffh,0,0,0 ; saved DAC register goes here
orvideo db 0 ; "or" value for setvideo
align 2
rowcount dw 0 ; row-counter for decoder and out_line
videomem dw 0a000h ; VGA videomemory
videoax dw 0 ; graphics mode values: ax
videobx dw 0 ; graphics mode values: bx
videocx dw 0 ; graphics mode values: cx
videodx dw 0 ; graphics mode values: dx
video_type dw 0 ; actual video adapter type:
; 0 = type not yet determined
; 1 = Hercules
; 2 = CGA (assumed if nothing else)
; 3 = EGA
; 4 = MCGA
; 5 = VGA
; 6 = VESA (not yet checked)
; 11 = 8514/A (not yet checked)
; 12 = TIGA (not yet checked)
; 13 = TARGA (not yet checked)
svga_type dw 0 ; (forced) SVGA type
; 1 = ahead "A" type
; 2 = ATI
; 3 = C&T
; 4 = Everex
; 5 = Genoa
; 6 = Ncr
; 7 = Oak-Tech
; 8 = Paradise
; 9 = Trident
; 10 = Tseng 3000
; 11 = Tseng 4000
; 12 = Video-7
; 13 = ahead "B" type
; 14 = "null" type (for testing only)
mode7text dw 0 ; nonzero for egamono and hgc
textaddr dw 0b800h ; b800 for mode 3, b000 for mode 7
textsafe dw 0 ; 0 = default, runup chgs to 1
; 1 = yes
; 2 = no, use 640x200
; 3 = bios, yes plus use int 10h-1Ch
; 4 = save, save entire image
text_type dw 0 ; current mode's type of text:
76 ; 0 = real text, mode 3 (or 7)
77 ; 1 = 640x200x2, mode 6
78 ; 2 = some other mode, graphics
79 video_entries dw 0 ; offset into video_entries table
80 video_bankadr dw 0 ; offset of video_banking routine
81 video_bankseg dw 0 ; segment of video_banking routine
82
83 textrow dw 0 ; for putstring(-1,...)
84 textcol dw 0 ; for putstring(..,-1,...)
85 textrbase dw 0 ; textrow is relative to this
86 textcbase dw 0 ; textcol is relative to this
87 cursortyp dw 0
88
89 tandyseg dw ? ;Tandy 1000 video segment address
90 tandyofs dw ? ;Tandy 1000 Offset into video buffer
91 tandyscan dw ? ;Tandy 1000 scan line address pointer
92
93
94 ; ******************* "Tweaked" VGA mode variables ************************
95
96 ; 704 x 528 mode
97 x704y528 db 704/8 ; number of screen columns
98 db 528/16 ; number of screen rows
99 db 68h, 57h, 58h, 8Bh ; CRTC Registers
100 db 59h, 86h, 3EH,0F0h
101 db 0h, 60h, 0h, 0h
102 db 0h, 0h, 2h, 3Dh
103 db 19h, 8Bh, 0Fh, 2Ch
104 db 0h, 18h, 38h,0E3h
105 db 0FFh
106 ; 720 x 540 mode
107 x720y540 db 720/8 ; number of screen columns
108 db 540/16 ; number of screen rows
109 db 6Ah, 59h, 5Ah, 8Dh ; CRTC Registers
110 db 5Eh, 8Bh, 4AH,0F0h
111 db 0h, 60h, 0h, 0h
112 db 0h, 0h, 2h, 49h
113 db 24h, 86h, 1Bh, 2Dh
114 db 0h, 24h, 44h,0E3h
115 db 0FFh
116 ; 736 x 552 mode
117 x736y552 db 736/8 ; number of screen columns
118 db 552/16 ; number of screen rows
119 db 6Ch, 5Bh, 5Ch, 8Fh ; CRTC Registers
120 db 5Fh, 8Ch, 56H,0F0h
121 db 0h, 60h, 0h, 0h
122 db 0h, 0h, 2h, 55h
123 db 2Bh, 8Dh, 27h, 2Eh
124 db 0h, 30h, 50h,0E3h
125 db 0FFh
126 ; 752 x 564 mode
127 x752y564 db 752/8 ; number of screen columns
128 db 564/16 ; number of screen rows
129 db 6Eh, 5Dh, 5Eh, 91h ; CRTC Registers
130 db 62h, 8Fh, 62H,0F0h
131 db 0h, 60h, 0h, 0h
132 db 0h, 0h, 2h, 61h
133 db 37h, 89h, 33h, 2Fh
134 db 0h, 3Ch, 5Ch,0E3h
135 db 0FFh
136 ; 768 x 576 mode
137 x768y576 db 768/8 ; number of screen columns
138 db 576/16 ; number of screen rows
139 db 70h, 5Fh, 60h, 93h ; CRTC Registers
140 db 66h, 93h, 6EH,0F0h
141 db 0h, 60h, 0h, 0h
142 db 0h, 0h, 2h, 6Dh
143 db 43h, 85h, 3Fh, 30h
144 db 0h, 48h, 68h,0E3h
145 db 0FFh
146 ; 784 x 588 mode
147 x784y588 db 784/8 ; number of screen columns
148 db 588/16 ; number of screen rows
149 db 72h, 61h, 62h, 95h ; CRTC Registers
150 db 69h, 96h, 7AH,0F0h
151 db 0h, 60h, 0h, 0h
152 db 0h, 0h, 2h, 79h
153 db 4Fh, 81h, 4Bh, 31h
154 db 0h, 54h, 74h,0E3h
155 db 0FFh
156 ; 800 x 600 mode
157 x800y600 db 800/8 ; number of screen columns
158 db 600/16 ; number of screen rows
159 db 74h, 63h, 64h, 97h ; CRTC Registers
160 db 68h, 95h, 86H,0F0h
161 db 0h, 60h, 0h, 0h
162 db 0h, 0h, 2h, 85h
163 db 5Bh, 8Dh, 57h, 32h
164 db 0h, 60h, 80h,0E3h
165 db 0FFh
166
167 x360y480 db 360/8 ; number of screen columns
168 db 480/16 ; number of screen rows
169 db 6bh, 59h, 5ah, 8eh ; CRTC Registers
170 db 5eh, 8ah, 0DH,03Eh
171 db 0h, 40h, 00h, 0h
172 db 0h, 0h, 0h, 31h
173 db 0EAh, 0ACh, 0DFh, 2Dh
174 db 0h,0E7h, 06h,0E3h
175 db 0FFh
176
177 x320y480 db 320/8 ; number of screen columns
178 db 480/16 ; number of screen rows
179 db 5fh, 4fh, 50h, 82h ; CRTC Registers
180 db 54h, 80h, 0DH,03Eh
181 db 0h, 40h, 00h, 0h
182 db 0h, 0h, 0h, 0h
183 db 0EAh, 0AEh, 0DFh, 28h
184 db 0h,0E7h, 006h,0E3h
185 db 0FFh
186
187 ; mode x from Michael Abrash
188 x320y240 db 320/8 ; number of screen columns
189 db 240/16 ; number of screen rows
190 db 05fh, 04fh, 050h, 082h
191 db 054h, 080h, 0dh, 03eh
192 db 00h, 041h, 00h, 00h
193 db 00h, 00h, 00h, 00h
194 db 0eah, 0ach, 0dfh, 028h
195 db 00h, 0e7h, 06h, 0e3h
196 db 0ffh
197
198 x320y400 db 320/8 ; number of screen columns
199 db 400/16 ; number of screen rows
200 db 5fh, 4fh, 50h, 82h ; CRTC Registers
201 db 54h, 80h,0bfh, 1fh
202 db 00h, 40h, 00h, 00h
203 db 00h, 00h, 00h, 00h
204 db 9ch, 8eh, 8fh, 28h
205 db 00h, 96h,0b9h,0E3h
206 db 0FFh
207
208 x640y400 db 640/8 ; number of screen columns
209 db 400/16 ; number of screen rows
210 db 5eh, 4fh, 50h, 01h ; CRTC Registers
211 db 54h, 9fh,0c0h, 1fh
212 db 00h, 40h, 00h, 00h
213 db 00h, 00h, 00h, 00h
214 db 9ch,08eh, 8fh, 28h
215 db 00h, 95h,0bch,0c3h
216 db 0ffh
217 ;for VGA
218 x400y600 db 400/8
219 db 600/16
220 db 74h,63h,64h,97h
221 db 68h,95h,86h,0F0h
222 db 00h,60h,00h,00h
223 db 00h,00h,00h,31h
224 db 5Bh,8Dh,57h,32h
225 db 0h,60h,80h,0E3h
226 db 0FFh
227 ;for VGA
228 x376y564 db 376/8
229 db 564/16
230 db 6eh,5dh,5eh,91h
231 db 62h,8fh,62h,0F0h
232 db 00h,60h,00h,00h
233 db 00h,00h,00h,31h
234 db 37h,89h,33h,2fh
235 db 0h,3ch,5ch,0E3h
236 db 0FFh
237 ;for VGA
238 x400y564 db 400/8
239 db 564/16
240 db 74h,63h,64h,97h
241 db 68h,95h,62h,0F0h
242 db 00h,60h,00h,00h
243 db 00h,00h,00h,31h
244 db 37h,89h,33h,32h
245 db 0h,3ch,5ch,0E3h
246 db 0FFh
247
248 testati db 832/8
249 db 612/16
250 db 7dh,65h,68h,9fh
251 db 69h,92h,44h,1Fh
252 db 00h,00h,00h,00h
253 db 00h,00h,00h,00h
254 db 34h,86h,37h,34h
255 db 0fh,34h,40h,0E7h
256 db 0FFh
257
258 align 2
259
260 tweaks dw offset x704y528 ; tweak table
261 dw offset x704y528
262 dw offset x720y540
263 dw offset x736y552
264 dw offset x752y564
265 dw offset x768y576
266 dw offset x784y588
267 dw offset x800y600
268 dw offset x360y480
269 dw offset x320y400
270 dw offset x640y400 ; Tseng Super VGA
271 dw offset x400y600 ; new tweak (VGA)
272 dw offset x376y564 ; new tweak (VGA)
273 dw offset x400y564 ; new tweak (VGA)
274 dw offset x720y540 ; ATI Tweak
275 dw offset x736y552 ; ATI Tweak
276 dw offset x752y564 ; ATI Tweak
277 dw offset testati ; ATI 832x816 (works!)
278 dw offset x320y480
279 dw offset x320y240
280
281 tweakflag dw 0 ; tweak mode active flag
282 tweaktype dw 0 ; 8 or 9 (320x400 or 360x480)
283
284 bios_vidsave dw 0 ; for setfortext/graphics
285 setting_text dw 0 ; flag for setting text mode
286 chkd_vvs dw 0 ; we checked VESAvirtscan
287
288 .CODE
289
290 FRAME MACRO regs
291 push bp
292 mov bp, sp
293 IRP reg,
294 push reg
295 ENDM
296 ENDM
297
298 UNFRAME MACRO regs
299 IRP reg,
300 pop reg
301 ENDM
302 pop bp
303 ENDM
304
305
306 ; Video Table Entries
307 ;
308 ; The Video Table has been moved to a FARDATA segment to relieve
309 ; some of the pressure on the poor little overloaded 64K DATA segment.
310
311 .code
312
313 video_requirements dw 0 ; minimal video_type req'd
dw 1, 3, 4, 5, 5, 5, 5, 5, 1, 1 ; dotmodes 1 - 10
dw 1, 5, 2, 1, 5, 5, 5, 5, 1, 5 ; dotmodes 11 - 20
dw 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ; dotmodes 21 - 30
videotable label byte ; video table actually starts on the NEXT byte
; Feel free to add your favorite video adapter to FRACTINT.CFG.
; The entries hard coded here are repeated from fractint.cfg in case
; it gets lost/destroyed, so a user can still have some modes.
; Currently available Video Modes are (use the BIOS as a last resort)
; 1) use the BIOS (INT 10H, AH=12/13, AL=color) ((SLOW))
; 2) pretend it's a (perhaps super-res) EGA/VGA
314 ; 3) pretend it's an MCGA
; 4) SuperVGA 256-Color mode using the Tseng Labs Chipset
; 5) SuperVGA 256-Color mode using the Paradise Chipset
; 6) SuperVGA 256-Color mode using the Video-7 Chipset
; 7) Non-Standard IBM VGA 360 x 480 x 256-Color mode
; 8) SuperVGA 1024x768x16 mode for the Everex Chipset
; 9) TARGA video modes
; 10) HERCULES video mode
; 11) Non-Video [disk or RAM] "video"
; 12) 8514/A video modes
; 13) CGA 320x200x4-color and 640x200x2-color modes
; 14) Tandy 1000 video modes
; 15) SuperVGA 256-Color mode using the Trident Chipset
; 16) SuperVGA 256-Color mode using the Chips & Tech Chipset
; 17) SuperVGA 256-Color mode using the ATI VGA Wonder Chipset
; 18) SuperVGA 256-Color mode using the Everex Chipset
; 19) Roll-Your-Own video, as defined in YOURVID.C
; 20) SuperVGA 1024x768x16 mode for the ATI VGA Wonder Chipset
; 21) SuperVGA 1024x768x16 mode for the Tseng Labs Chipset
; 22) SuperVGA 1024x768x16 mode for the Trident Chipset
; 23) SuperVGA 1024x768x16 mode for the Video 7 Chipset
; 24) SuperVGA 1024x768x16 mode for the Paradise Chipset
; 25) SuperVGA 1024x768x16 mode for the Chips & Tech Chipset
; 26) SuperVGA 1024x768x16 mode for the Everex Chipset
; 27) SuperVGA Auto-Detect mode
; 28) VESA modes
; 29) True Color Auto-Detect
; (Several entries have been commented out - they should/did work,
; but are handled by alternative entries. Where multiple SuperVGA
; entries are covered by a single SuperVGA Autodetect mode, the
; individual modes have been commented out. Where a SuperVGA
; Autodetect mode covers only one brand of adapter, the Autodetect
; mode has been commented out to avoid confusion.)
; |--Adapter/Mode-Name------|-------Comments-----------|
; |------INT 10H------|Dot-|--Resolution---|
; |key|--AX---BX---CX---DX|Mode|--X-|--Y-|Color|
db "IBM 16-Color EGA ",0,"Standard EGA hi-res mode ",0
dw 1060, 10h, 0, 0, 0, 2, 640, 350, 16
db "IBM 256-Color VGA/MCGA ",0,"Quick and LOTS of colors ",0
dw 1061, 13h, 0, 0, 0, 3, 320, 200, 256
db "IBM 16-Color VGA ",0,"Nice high resolution ",0
dw 1062, 12h, 0, 0, 0, 2, 640, 480, 16
db "IBM 4-Color CGA ",0,"(Ugh - Yuck - Bleah) ",0
dw 1063, 4h, 0, 0, 0, 13, 320, 200, 4
db "IBM Hi-Rez B&W CGA ",0,"('Hi-Rez' Ugh - Yuck) ",0
dw 1064, 6h, 0, 0, 0, 13, 640, 200, 2
db "IBM B&W EGA ",0,"(Monochrome EGA) ",0
dw 1065, 0fh, 0, 0, 0, 2, 640, 350, 2
db "IBM B&W VGA ",0,"(Monochrome VGA) ",0
dw 1066, 11h, 0, 0, 0, 2, 640, 480, 2
db "IBM Low-Rez EGA ",0,"Quick but chunky ",0
dw 1067, 0dh, 0, 0, 0, 2, 320, 200, 16
db "IBM VGA (non-std) ",0,"Register Compatibles ONLY",0
dw 1068, 0h, 0, 0, 9, 7, 320, 400, 256
db "IBM VGA (non-std) ",0,"Register Compatibles ONLY",0
dw 1084, 0h, 0, 0, 8, 7, 360, 480, 256
db "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
dw 1085, 0, 0, 0, 0, 27, 800, 600, 16
db "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
dw 1086, 0, 0, 0, 0, 27,1024, 768, 16
db "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
dw 1087, 0, 0, 0, 0, 27, 640, 400, 256
db "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
dw 1088, 0, 0, 0, 0, 27, 640, 480, 256
db "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
dw 1089, 0, 0, 0, 0, 27, 800, 600, 256
db "SuperVGA/VESA Autodetect ",0,"Works with most SuperVGA ",0
dw 1090, 0, 0, 0, 0, 27,1024, 768, 256
db "VESA Standard interface ",0,"OK: Andy Fu - Chips&Tech ",0
dw 1091,4f02h,106h, 0, 0, 28,1280,1024, 16
db "VESA Standard interface ",0,"OK: Andy Fu - Chips&Tech ",0
dw 1092,4f02h,107h, 0, 0, 28,1280,1024, 256
db "8514/A Low Res ",0,"HW/AI (AI Reqs HDILOAD) ",0
dw 1093, 3h, 0, 0, 1, 12, 640, 480, 256
db "8514/A High Res ",0,"HW/AI (AI Reqs HDILOAD) ",0
dw 1094, 3h, 0, 0, 1, 12,1024, 768, 256
db "8514/A Low W/Border ",0,"HW/AI (AI Reqs HDILOAD) ",0
dw 1095, 3h, 0, 0, 1, 12, 632, 474, 256
db "8514/A High W/Border ",0,"HW/AI (AI Reqs HDILOAD) ",0
dw 1096, 3h, 0, 0, 1, 12,1016, 762, 256
db "IBM Med-Rez EGA ",0,"(Silly but it's there!) ",0
315 dw 1097, 0eh, 0, 0, 0, 2, 640, 200, 16
316 db "IBM VGA (non-std) ",0,"Register Compatibles ONLY",0
317 dw 1098, 0h, 0, 0, 18, 7, 320, 480, 256
318 db "Hercules Graphics ",0,"OK: Timothy Wegner ",0
319 dw 1099, 8h, 0, 0, 0, 10, 720, 348, 2
320 db "Tandy 1000 ",0,"OK: Joseph Albrecht ",0
321 dw 1100, 9h, 0, 0, 0, 14, 320, 200, 16
322 db "Pdise/AST/COMPAQ VGA ",0,"OK: Phil Wilson ",0
323 dw 1101, 59h, 0, 0, 0, 1, 800, 600, 2
324 db 140 dup(0) ; 2 unused slots here default table
325 db "Disk/RAM 'Video' ",0,"Full-Page L-Jet @ 75DPI ",0
326 dw 1104, 3h, 0, 0, 0, 11, 800, 600, 2
327 db "Disk/RAM 'Video' ",0,"Full-Page L-Jet @ 150DPI ",0
328 dw 1105, 3h, 0, 0, 0, 11,1600,1200, 2
329 db "Disk/RAM 'Video' ",0,"Full-Page Epson @ 120DPI ",0
330 dw 1106, 3h, 0, 0, 0, 11, 768, 960, 2
331 db "Disk/RAM 'Video' ",0,"Full-Page Paintjet 90DPI ",0
332 dw 1107, 3h, 0, 0, 0, 11, 960, 720, 256
333 db "Disk/RAM 'Video' ",0,"For Background Fractals ",0
334 dw 1108, 3h, 0, 0, 0, 11, 800, 600, 256
335 db "Disk/RAM 'Video' ",0,"For Background Fractals ",0
336 dw 1109, 3h, 0, 0, 0, 11,2048,2048, 256
337 db 280 dup(0) ; 4 unused slots here default table
338 db 70 dup(0) ; 1 slot reserved for unassigned current mode
339
340
341 bios_savebuf db 256 dup(0) ; enough for 4 blocks (64 bytes/block)
342
343 .code
344
345 ; XGA Graphics mode setup values
346 ; (the first two entries in each line
347 ; indicate where the table values are to be stored)
348 ;
349 ; 1024x768x256 vvv
350 ; 1024x768x16 -----vvvv
351 ; 640x480x256 -----------vvvv
352 ; 640x480x65536 ----------------vvvv
353 ; 800x600x16 -----------------------vvvv
354 ; 800x600x256 -----------------------------vvvv
355 ; 800x600x65536 ----------------------------------vvvv
356
357 xga_twidth dw 9 ; width of these tables
358
359 xga_requir dw 0, 0, 0dh, 05h, 01h, 09h, 01h, 01h, 09h ; adapter requirements
360 xga_colors dw 0, 0, 256, 16, 256, 0, 16, 256, 0 ; 0 means 64K colors
361 xga_swidth dw 0, 0, 1024, 512, 640, 1280, 400, 800, 1600 ; bytes / scan line
362
363 xga_val db 004h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; interrupt enable
364 db 005h, 000h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh ; interrupt status
365 db 000h, 000h, 004h, 004h, 004h, 004h, 004h, 004h, 004h ; operating mode
366 db 00ah, 064h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; palette mask
367 db 001h, 000h, 001h, 001h, 001h, 001h, 001h, 001h, 001h ; vid mem aper cntl
368 db 008h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; vid mem aper indx
369 db 006h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; virt mem ctl
370 db 009h, 000h, 003h, 002h, 003h, 004h, 002h, 003h, 004h ; mem access mode
371 db 00ah, 050h, 001h, 001h, 001h, 001h, 001h, 001h, 001h ; disp mode 1
372 db 00ah, 050h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; disp mode 1
373 db 00ah, 010h, 09dh, 09dh, 063h, 063h, 088h, 088h, 088h ; horiz tot lo.
374 db 00ah, 011h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; horiz tot hi.
375 db 00ah, 012h, 07fh, 07fh, 04fh, 04fh, 063h, 063h, 063h ; hor disp end lo
376 db 00ah, 013h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; hor disp end hi
377 db 00ah, 014h, 080h, 080h, 050h, 050h, 064h, 064h, 064h ; hor blank start lo
378 db 00ah, 015h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; hor blank start hi
379 db 00ah, 016h, 09ch, 09ch, 062h, 062h, 087h, 087h, 087h ; hor blank end lo
380 db 00ah, 017h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; hor blank end hi
381 db 00ah, 018h, 087h, 087h, 055h, 055h, 06ah, 06ah, 06ah ; hor sync start lo
382 db 00ah, 019h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; hor sync start hi
383 db 00ah, 01ah, 09ch, 09ch, 061h, 061h, 084h, 084h, 084h ; hor sync end lo
384 db 00ah, 01bh, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; hor sync end hi
385 db 00ah, 01ch, 040h, 040h, 000h, 000h, 000h, 000h, 000h ; hor sync pos
386 db 00ah, 01eh, 004h, 004h, 000h, 000h, 000h, 000h, 000h ; hor sync pos
387 db 00ah, 020h, 030h, 030h, 00ch, 00ch, 086h, 086h, 086h ; vert tot lo
388 db 00ah, 021h, 003h, 003h, 002h, 002h, 002h, 002h, 002h ; vert tot hi
389 db 00ah, 022h, 0ffh, 0ffh, 0dfh, 0dfh, 057h, 057h, 057h ; vert disp end lo
390 db 00ah, 023h, 002h, 002h, 001h, 001h, 002h, 002h, 002h ; vert disp end hi
391 db 00ah, 024h, 000h, 000h, 0e0h, 0e0h, 058h, 058h, 058h ; vert blank start lo
392 db 00ah, 025h, 003h, 003h, 001h, 001h, 002h, 002h, 002h ; vert blank start hi
393 db 00ah, 026h, 02fh, 02fh, 00bh, 00bh, 085h, 085h, 085h ; vert blank end lo
394 db 00ah, 027h, 003h, 003h, 002h, 002h, 002h, 002h, 002h ; vert blank end hi
395 db 00ah, 028h, 000h, 000h, 0eah, 0eah, 058h, 058h, 058h ; vert sync start lo
396 db 00ah, 029h, 003h, 003h, 001h, 001h, 002h, 002h, 002h ; vert sync start hi
397 db 00ah, 02ah, 008h, 008h, 0ech, 0ech, 06eh, 06eh, 06eh ; vert sync end
398 db 00ah, 02ch, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh ; vert line comp lo
399 db 00ah, 02dh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh ; vert line comp hi
400 db 00ah, 036h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; sprite cntl
401 db 00ah, 040h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; start addr lo
402 db 00ah, 041h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; start addr me
403 db 00ah, 042h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; start addr hi
404 db 00ah, 043h, 080h, 040h, 050h, 0a0h, 032h, 064h, 0c8h ; pixel map width lo
405 db 00ah, 044h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; pixel map width hi
406 db 00ah, 054h, 00dh, 00dh, 000h, 000h, 001h, 001h, 001h ; clock sel
407 db 00ah, 051h, 003h, 002h, 003h, 004h, 002h, 003h, 004h ; display mode 2
408 db 00ah, 070h, 000h, 000h, 000h, 000h, 080h, 080h, 080h ; ext clock sel
409 db 00ah, 050h, 00fh, 00fh, 0c7h, 0c7h, 007h, 007h, 007h ; display mode 1
410 db 00ah, 055h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; Border Color
411 db 00ah, 060h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; Sprite Pal Lo
412 db 00ah, 061h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; Sprite Pal hi
413 db 00ah, 062h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; Sprite Pre Lo
414 db 00ah, 063h, 000h, 000h, 000h, 000h, 000h, 000h, 000h ; Sprite Pre hi
415 db 00ah, 064h, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh ; Palette Mask
416 db 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh, 0ffh ; end of the list
417
418
419 xga_newbank proc ; XGA-specific bank-switching routine
420 cmp xga_isinmode,2 ; are we in an XGA-specific mode?
421 jl return ; nope. bail out.
422 mov curbk,ax ; save the new current bank value
423 mov dx,xga_reg_base ; Select Page
424 add dx,08h
425 out dx,al ; assumes bank number is in al
426 return: ret
427 xga_newbank endp
428
429 xga_16linewrite proc near ; 16-color Line Write
430 mov bx,ax ; calculate the # of columns
431 sub bx,cx
432 mov ax,xga_xdots ; this many dots / line
433 mul dx ; times this many lines - ans in dx:ax
434 push cx ; save the X-value for a tad
435 shr cx,1 ; and adjust for two bits per pixel
436 add ax,cx ; plus this many x-dots
437 adc dx,0 ; answer in dx:ax - dl=bank, ax=offset
438 mov di,ax ; save offset in DI
439 pop cx ; restore the X-value
440 mov ax,dx ; xga_newbank expects bank in al
441 new_bank:
442 call far ptr xga_newbank
443 same_bank:
444 mov ah,es:[di] ; grab the old byte value
445 mov al,[si] ; and the new color value
446 and al,0fh ; isolate the bits we want
447 test cx,1 ; odd pixel address?
448 jnz xga_sk1 ; yup
449 and ah,0f0h ; isolate the low-order
450 jmp short xga_sk2
451 xga_sk1:and ah,0fh ; isolate the high-order
452 shl al,1
453 shl al,1
454 shl al,1
455 shl al,1
456 xga_sk2:or al,ah ; combine the two nibbles
457 mov es:[di],al ; write the dot
458 inc si ; increment the source addr
459 dec bx ; more to go?
460 jz done ; nope
461 inc cx ; next pixel
462 test cx,1 ; odd pixel?
463 jnz same_bank ; yup
464 inc di ; increment the destination
465 cmp di,0 ; segment wrap?
466 jnz same_bank ; nope
467 mov ax,curbk ; update the bank cvalue
468 inc ax
469 jmp new_bank
470 done: ret
471 xga_16linewrite endp
472
473 xga_super16addr proc near ; can be put in-line but shared by
474 ; read and write routines
475 clc ; clear carry flag
476 push ax ; save this for a tad
477 mov ax,xga_xdots ; this many dots / line
478 mul dx ; times this many lines - ans in dx:ax
479 push cx ; save the X-value for a tad
480 shr cx,1 ; and adjust for two bits per pixel
481 add ax,cx ; plus this many x-dots
482 adc dx,0 ; answer in dx:ax - dl=bank, ax=offset
483 pop cx ; restore the X-value
484 mov bx,ax ; save this in BX
485 cmp dx,curbk ; see if bank changed
486 je same_bank ; jump if old bank ok
487 mov ax,dx ; xga_newbank expects bank in al
488 call far ptr xga_newbank
489 same_bank:
490 pop ax ; restore AX
491 ret
492 xga_super16addr endp
493
494 xga_16write proc near ; XGA 256 colors write-a-dot
495 call xga_super16addr ; calculate address and switch banks
496 mov ah,es:[bx] ; grab the old byte value
497 and al,0fh ; isolate the bits we want
498 test cx,1 ; odd pixel address?
499 jnz xga_sk1 ; yup
500 and ah,0f0h ; isolate the low-order
501 jmp short xga_sk2
502 xga_sk1:and ah,0fh ; isolate the high-order
503 shl al,1
504 shl al,1
505 shl al,1
506 shl al,1
507 xga_sk2:or al,ah ; combine the two nibbles
508 mov es:[bx],al ; write the dot
509 ret ; we done.
510 xga_16write endp
511
512 xga_16read proc near ; XGA 256 colors read-a-dot
513 call xga_super16addr ; calculate address and switch banks
514 mov al,es:[bx] ; read the dot
515 test cx,1 ; odd number of pixels?
516 jz xga_sk1 ; nope
517 shr ax,1 ; adjust for odd pixel count
518 shr ax,1
519 shr ax,1
520 shr ax,1
521 xga_sk1:and ax,0fh ; isolate the byte value
522 ret ; we done.
523 xga_16read endp
524
525 xga_clear proc uses es si di ; clear the XGA memory
526 cmp xga_clearvideo,0 ; should we really do this?
527 jne return ; nope. skip it.
528 mov bx,xga_result ; find out how much memory we have
529 and bx,08h ; in 64K pages
530 add bx,08h
531 mov ax,0a000h ; set up to clear 0a0000-0affff
532 push ax
533 pop es
534 xloop: mov ax,bx ; initialize the bank addr
535 call xga_newbank
536 mov ax,0
537 mov cx,16384 ; clear out 32K
538 mov di,0
539 rep stosw
540 mov cx,16384 ; clear out 32K
541 rep stosw
542 dec bx ; another page?
543 cmp bx,0
544 jge xloop
545 return: ret
546 xga_clear endp
547
548 xga_setpalette proc uses es si di, palette:word ; set the XGA palette
549 cmp xga_isinmode,2 ; are we in an XGA graphics mode?
550 jl return ; nope
551
552 mov dx,xga_reg_base ; wait for a retrace
553 add dx,5
554 mov al,1 ; clear the start-of-blanking
555 out dx,al
556 bloop: in al,dx
557 test al,01h ; blanking started?
558 jz bloop ; nope - try again
559
560 mov dx,xga_reg_base ; set up for a palette load
561 add dx,0ah
562 mov ax,0064h ; make invisible
563 out dx,ax
564 mov ax,0055h ; border color
565 out dx,ax
566 mov ax,0066h ; palette mode
567 out dx,ax
568 mov ax,0060h ; start at palette 0
569 out dx,ax
570 mov ax,0061h
571 out dx,ax
572
573 mov si,palette
574 mov cx,768
575 mov ax,065h ; palette update
576 out dx,al
577 inc dx ; palette data
578 .186
579 rep outsb
580 .8086
581 dec dx
582
583 mov ax,0ff64h ; make visible
584 out dx,ax
585
586 return: ret
587 xga_setpalette endp
588
589 xga_detect proc uses es di si
590
591 cmp xga_reg_base,-2 ; has the XGA detector already failed?
592 jne xga_sk1 ; ne = not yet
593 jmp xga_notfound ; e = yes, fail again
594 xga_sk1:cmp xga_reg_base,-1 ; have we already found the XGA?
595 je xga_loc ; e = no
596 jmp xga_found ; yes, process it
597
598 xga_loc:push bp ; save around int 10H calls
599 mov ax,1f00h ; XGA-2 detect:
600 int 10h ; get DMQS length
601 pop bp ; restore BP
602 cmp al,1fh ; did this work?
603 jne xga_man ; nope - try the older, manual approach
604 cmp bx,768 ; room for the results?
605 ja xga_man ; no?!? try the older approach
606 mov ax,1f01h ; get DMQS info
607 push ds ; into here
608 pop es ; ...
609 mov di, offset dacbox ; ...
610 int 10h ; ...
611 cmp al,1fh ; safety first
612 jne xga_man ; ?? try the older approach
613 mov bx, word ptr dacbox+09h ; get the register base
614 mov xga_reg_base,bx ; save the results
615 mov xga_result,1 ; say we found an adapter
616 cmp byte ptr dacbox+15h,4 ; do we have 1MB of adapter RAM?
617 jb @F ; nope
618 or xga_result,8h ; yup - say so.
619 @@: mov bx, word ptr dacbox+13h ; get the composite monitor ID
620 and bx,0f00h ; high-rez-monitor?
621 cmp bx,0f00h ; ..
622 je @F ; nope
623 or xga_result,4 ; yup
624 @@: jmp xga_found ; say we found the adapter
625
626 xga_man:mov ah,35h ; DOS get interrupt vector
627 mov al,15h ; Int 15h
628 int 21h ; returns vector in es:bx
629 mov ax,es ; segment part
630 or ax,ax ; undefined vector?
631 jnz xga_sk2 ; nz = no, OK so far
632 jmp xga_notfound ; z = yes - not an MCA machine
633 xga_sk2:mov dx,-1 ; start with an invalid POS address
634 mov ax,0c400h ; look for POS base address
635 int 15h ; (Microchannel machines only)
636 jnc xga_sk3 ; nc = success
637 jmp xga_notfound ; error - not an MC machine
638 xga_sk3:mov xga_pos_base,dx ; save pos_base_address
639 xor cx,cx ; check all MCA slots & motherboard
640 cmp dx,-1 ; do we have a good POS?
641 jne xga_lp1 ; ne = yes, proceed with MCA checks
642 jmp xga_notfound ; no, fail
643 xga_lp1:cli ; no interrupts, please
644 cmp cx,0 ; treat the motherboard differently?
645 jne xga_sk4 ; ne = yes
646 mov al,0dfh ; enable the motherboard for setup
647 mov dx,94h
648 out dx,al
649 jmp short xga_sk5
650 xga_sk4:mov ax,0c401h ; enable an MCA slot for setup
651 mov bx,cx ; this slot
652 int 15h
653 xga_sk5:mov dx,xga_pos_base ; get pos record for the slot ID
654 in ax,dx
655 mov xga_cardid,ax
656 add dx,2 ; compute IO Res Base
657 in al,dx ; get POS data byte1
658 mov byte ptr xga_1mb,al ; save it temporarily
659 inc dx ; switch to byte 2
660 in al,dx ; get POS data
661 mov byte ptr xga_1mb+1,al ; save it temporarily
662 inc dx ; switch to byte 3
663 in al,dx ; get POS data
664 mov byte ptr xga_1mb+2,al ; save it temporarily
665 inc dx ; switch to byte 4
666 in al,dx ; get POS data
667 mov byte ptr xga_1mb+3,al ; save it temporarily
668 cmp cx,0 ; treat the motherboard differently
669 jne xga_sk6 ; ne = yes
670 mov al,0ffh ; enable the motherboard for normal
671 out 094h,al
672 jmp short xga_sk7
673 xga_sk6:mov ax,0c402h ; enable the MCA slot for normal
674 mov bx,cx ; this slot
675 int 15h
676 xga_sk7:sti ; interrupts on again
677
678 mov ax,xga_cardid ; is an XGA adapter on this slot?
679 cmp ax,08fd8h
680 jae xga_sk8 ; ae = yes
681 jmp xga_lp2 ; try another slot
682 xga_sk8:cmp ax,08fdbh ; still within range?
683 jbe xga_sk9 ; be = yes
684 jmp xga_lp2 ; no, try another slot
685
686 xga_sk9:mov al,byte ptr xga_1mb ; restore POS data byte 1
687 and ax,0eh ; muck about with it to get reg base
688 shl ax,1
689 shl ax,1
690 shl ax,1
691 add ax,2100h
692 mov xga_reg_base,ax
693 mov dx,xga_reg_base ; is there a monitor on this slot?
694 add dx,0ah
695 mov al,052h
696 out dx,al
697 mov dx,xga_reg_base
698 add dx,0bh
699 in al,dx
700 and al,0fh
701 cmp al,00h ; illegal value, returned under Win 3.0
702 je xga_lp2
703 cmp al,0fh
704 jne xga_isthere ; ne = yes
705
706 xga_lp2:inc cx ; try another adapter?
707 cmp cx,9 ; done all slots?
708 ja xga_ska ; a = yes
709 jmp xga_lp1 ; no, try another slot
710
711 xga_ska:jmp xga_notfound ; forget it - no XGA here
712
713 xga_isthere:
714 and ax,06h ; strip off the low & high bit
715 xor ax,05h ; reverse the 3rd & low bits
716 mov xga_result,ax ; save the result flag
717
718 mov dx,xga_reg_base ; is this XGA in VGA mode?
719 in al,dx
720 test al,1
721 jnz xga_skb ; nz = yes - single-monitor setup
722 or xga_result,10h ; dual-monitor setup
723 xga_skb:
724
725 mov ah,byte ptr xga_1mb+2 ; retrieve POS data byte 3
726 and ax,0fe00h ; eliminate the low-order bits
727 mov bl,byte ptr xga_1mb ; retrieve POS data byte 1
728 and bx,0eh ; strip it down to the IODA
729 mov cx,5 ; shift it up 5 bits
730 shl bx,cl
731 or ax,bx ; compute the 4MB aperture value
732 mov word ptr xga_4mb+2,ax ; save the result
733
734 mov al, byte ptr xga_1mb+3 ; retrieve POS data byte 4
735 and ax,0fh ; select the 1MB aperture bits
736 mov cx,4 ; shift it up 4 bits
737 shl ax,cl
738 mov word ptr xga_1mb+2,ax ; save the result
739 mov ax,0
740 mov word ptr xga_1mb,ax
741
742 mov dx,xga_reg_base ; Interrupt Disable
743 add dx,4
744 xor al,al
745 out dx,al
746
747 mov dx,xga_reg_base ; Switch to Extended Mode
748 ;; add dx,00h
749 mov al,4
750 out dx,al
751
752 mov dx,xga_reg_base ; Aperture Control
753 add dx,01h
754 mov al,1
755 out dx,al
756
757 mov dx,xga_reg_base ; disable Palette Mask
758 add dx,0ah
759 mov ax,0064h
760 out dx,ax
761
762 mov xga_isinmode,2 ; pretend we're already in graphics
mov al,12 ; select page 12
call xga_newbank
push es ; see if this page has any memory
mov ax,0a000h
push ax
pop es
mov ah,000a5h
mov es:0,al
mov es:1,ah
cmp es:0,al
jne xga_512
add xga_result,8 ; 1MB RAM found
xga_512:pop es
mov al,0 ; select page 0
call xga_newbank
mov xga_isinmode,0 ; replace the "in-graphics" flag
mov dx,xga_reg_base ; Palette Mask
add dx,0ah
mov ax,0ff64h
out dx,ax
test xga_result,10h ; dual monitor setup?
jnz xga_found ; yup - don't restore as a VGA
763
764 mov dx,xga_reg_base ; Switch to VGA Mode
765 ;; add dx,00h
766 mov al,1
767 out dx,al
768
769 mov dx,03c3h ; Enable VGA Address Code
770 mov al,1
771 out dx,al
772
773 jmp short xga_found
774
775 xga_notfound:
776 mov xga_reg_base,-2 ; set failure flag
777 xga_found:
778 mov ax,xga_result ; return the result
779 ret
780
781 xga_detect endp
782
783 xga_mode proc uses es di si, mode:word
784
785 mov curbk,-1 ; preload impossible bank number
786
787 call xga_detect ; is an XGA adapter present?
788 cmp ax,0
789 jne whichmode
790 jmp nope ; nope
791 whichmode:
792 mov bx,mode
793 cmp bx,xga_twidth ; mode number out of range?
794 jb whichmode0
795 jmp nope ; yup - fail right now.
796 whichmode0:
797 cmp mode,0 ; 80-col VGA text mode?
798 jne whichmode1
799 jmp mode_0 ; yup
800 whichmode1:
801 cmp mode,1 ; 132-col VGA text mode?
802 jne whichmode2
803 jmp nope ; Fractint doesn't use this routine
whichmode2:
mov bx,mode ; locate the table entries
add bx,mode
mov dx,xga_requir[bx] ; does our setup support this mode?
and al,dl
cmp al,dl
je whichmode3
jmp nope ; nope
whichmode3:
mov ax,13h ; switch to 320x200x256 mode
call maybeor ; maybe or AL or (for Video-7s) BL
int 10h
push ds ; reset ES==DS
pop es
mov ax,1017h ; get the DAC values
mov bx,0
mov cx,256
mov dx,offset paldata ; a safe place when switching XGA modes
int 10h
cmp xga_loaddac,0 ; save the palette?
je paskip ; (yes, if we want to fake 'loaddac')
mov si, offset paldata
mov di, offset dacbox
mov cx,768/2
rep movsw
mov xga_loaddac,0 ; reset the toggle for next time
paskip:
mov bx,769 ; adjust the palette
paloop: dec bx
mov ah,paldata[bx]
shl ah,1
shl ah,1
mov paldata[bx],ah
cmp bx,0
jne paloop
mov dx,xga_reg_base ; Palette Mask
add dx,0ah
mov ax,00064h ; (Disable the XGA palette)
out dx,ax
mov dx,xga_swidth[bx] ; collect and save the scan-line length
mov xga_xdots,dx
mov dx,xga_colors[bx] ; how many colors do we have?
mov xga_iscolors,dx ; save this
mode_3: mov dx,03c3h ; Enable VGA Address Code
mov al,1
out dx,al
mov si,offset xga_val ; point to start of values table
mov bx,mode ; use mode as an offset
model1: mov dx,xga_reg_base ; get the base pointer
mov ah,0 ; get the increment
mov al,cs:0[si]
cmp al,0ffh ; end of the table?
je model2 ; yup
add dx,ax
cmp al,0ah ; check for access type
je modsk2
mov al,cs:0[si+bx] ; get the value and OUT it
out dx,al
jmp short modsk3
modsk2: mov al,cs:1[si] ; get the value and OUT it
mov ah,cs:0[si+bx]
out dx,ax
modsk3: add si,xga_twidth ; try another table entry
jmp short model1
model2:
mov xga_isinmode,2 ; pretend we're already in graphics
804 call xga_clear ; clear out the memory
805 mov curbk,-1 ; reset the bank counter
806
807 mov dx,xga_reg_base ; set up for final loads
808 add dx,0ah
809 mov bx,mode ; how many colors do we have?
810 add bx,mode
811 cmp xga_colors[bx],0 ; "true color" mode?
812 jne modsk4 ; nope - skip the funny palette load
813
814 mov ax,0064h ; make invisible
815 out dx,ax
816 mov ax,8055h ; border color
817 out dx,ax
818 mov ax,0066h ; palette mode
819 out dx,ax
820 mov ax,0060h ; start at palette 0
821 out dx,ax
822 mov ax,0061h ; ""
823 out dx,ax
824
825 mov cx,0 ; ready to update the palette
826 mov al,065h ; palette update
827 out dx,al
828 inc dx ; palette data
829 model3: mov al,0 ; zero out the...
830 out dx,al ; red value
831 out dx,al ; and the green value
832 mov al,cl ; klooge up the blue value
833 and al,1fh ; convert to 1,2,...1f
834 shl al,1 ; convert to 2,4,...3e
835 shl al,1 ; convert to 4,8,...7c
836 shl al,1 ; convert to 8,16,..fd
837 out dx,al ; blue value
838 inc cx ; another palette value to go?
839 cmp cx,128
840 jb model3
841 dec dx ; back to normal
842
843 mov ax,0ff64h ; make the palette visible
844 out dx,ax
845 jmp ok
846
847 modsk4: mov bx, offset paldata ; reset the palette
848 push bx
849 mov xga_isinmode,2
850 call xga_setpalette
851 pop bx
852 jmp ok
853
854 mode_0: ; Set 80 column mode
855 mov dx,xga_reg_base ; Aperture Control
856 add dx,01h
857 xor al,al ; (disable the XGA 64K aperture)
858 out dx,al
859
860 mov dx,xga_reg_base ; Interrupt Disable
861 add dx,4
862 xor al,al
863 out dx,al
864
865 mov dx,xga_reg_base ; Clear Interrupts
866 add dx,5
867 mov al,0ffh
868 out dx,al
869
870 test xga_result,10h ; dual monitor setup?
871 jz mode_0a
872 jmp nope ; yup - don't restore as a VGA
mode_0a:
mov dx,xga_reg_base ; Palette Mask
add dx,0ah
mov ax,0ff64h ; (Enable the XGA palette)
out dx,ax
mov dx,xga_reg_base ; Enable VFB, Prepare for Reset
add dx,0ah
mov ax,1550h
out dx,ax
mov dx,xga_reg_base ; Enable VFB, reset CRTC
add dx,0ah
mov ax,1450h
out dx,ax
mov dx,xga_reg_base ; Normal Scale Factors
add dx,0ah
mov ax,0051h
out dx,ax
mov dx,xga_reg_base ; Select VGA Oscillator
add dx,0ah
mov ax,0454h
out dx,ax
mov dx,xga_reg_base ; Ext Oscillator (VGA)
add dx,0ah
mov ax,7f70h
out dx,ax
mov dx,xga_reg_base ; Ensure no Vsynch Interrupts
add dx,0ah
mov ax,202ah
out dx,ax
mov dx,xga_reg_base ; Switch to VGA Mode
;; add dx,00h
mov al,1
out dx,al
mov dx,03c3h ; Enable VGA Address Code
mov al,1
out dx,al
mov ax,1202h ; select 400 scan lines
mov bl,30h
int 10h
mov ax,0+3 ; set video mode 3
or al,xga_clearvideo ; (might supress video-clearing)
cmp xga_clearvideo,0 ; clear the video option set?
je mode_0b
mov ax,08eh ; ugly klooge: VGA graphics, no clear
mode_0b:
int 10h
jmp ok ; we're done
873
874 nope:
875 mov xga_isinmode,0
876 mov ax,0 ; return failure
877 ret
878 ok:
879 mov ax,mode ; remember the mode we're in
mov xga_isinmode,ax
mov ax,1 ; return OK
ret
xga_mode endp
; **************** internal Read/Write-a-dot routines ***********************
;
; These Routines all assume the following register values:
;
; AL = The Color (returned on reads, sent on writes)
; CX = The X-Location of the Pixel
; DX = The Y-Location of the Pixel
nullwrite proc near ; "do-nothing" write
ret
nullwrite endp
nullread proc near ; "do-nothing" read
mov ax,0 ; "return" black pixels
ret
nullread endp
normalwrite proc near ; generic write-a-dot routine
mov ah,12 ; write the dot (al == color)
mov bx,0 ; this page
push bp ; some BIOS's don't save this
int 10h ; do it.
pop bp ; restore the saved register
ret ; we done.
normalwrite endp
normalread proc near ; generic read-a-dot routine
mov ah,13 ; read the dot (al == color)
mov bx,0 ; this page
push bp ; some BIOS's don't save this
int 10h ; do it.
pop bp ; restore the saved register
ret ; we done.
normalread endp
mcgawrite proc near ; MCGA 320*200, 246 colors
xchg dh,dl ; bx := 256*y
mov bx,cx ; bx := x
add bx,dx ; bx := 256*y + x
shr dx,1
shr dx,1 ; dx := 64*y
add bx,dx ; bx := 320*y + x
mov es:[bx],al ; write the dot
ret ; we done.
mcgawrite endp
mcgaread proc near ; MCGA 320*200, 246 colors
xchg dh,dl ; dx := 256*y
mov bx,cx ; bx := x
add bx,dx ; bx := 256*y + x
shr dx,1
shr dx,1 ; dx := 64*y
add bx,dx ; bx := 320*y + x
mov al,es:[bx] ; retrieve the previous value
ret ; we done.
mcgaread endp
; These routines are for bit-plane 16 color modes, including bank
; switched superVGA varieties such as the Tseng 1024x768x16 mode.
; Tim Wegner
;
vgawrite proc near ; bank-switched EGA/VGA write mode 0
mov bh,al ; save the color value for a bit
mov ax,vxdots ; this many dots / line
mul dx ; times this many lines
add ax,cx ; plus this many x-dots
adc dx,0 ; DX:AX now holds the pixel count
mov cx,ax ; save this for the bit mask
and cx,7 ; bit-mask shift calculation
xor cl,7 ; ...
mov si,ax ; set up for the address shift
shr dx,1 ; (ugly) 32-bit shift-by-3 logic
rcr si,1 ; ((works on ANY 80x6 processor))
shr dx,1 ; ...
rcr si,1 ; ...
shr dx,1 ; ...
rcr si,1 ; ...
cmp dx,curbk ; see if bank changed
je vgasame_bank ; jump if old bank ok
mov ax,dx ; newbank expects bank in al
call far ptr newbank ; switch banks
vgasame_bank:
mov dx,03ceh ; graphics controller address
mov ax,0108h ; set up controller bit mask register
shl ah,cl ; ...
out dx,ax ; ...
mov ah,bh ; set set/reset registers
mov al,0 ; ...
out dx,ax ; ...
mov ax,0f01h ; enable set/reset registers
out dx,ax ; ...
or es:[si],al ; update all bit planes
ret ; we done.
vgawrite endp
vgaread proc near ; bank-switched EGA/VGA read mode 0
mov ax,vxdots ; this many dots / line
mul dx ; times this many lines
add ax,cx ; plus this many x-dots
adc dx,0 ; DX:AX now holds the pixel count
mov cx,ax ; save this for the bit mask
and cx,7 ; bit-mask shift calculation
xor cl,7 ; ...
mov si,ax ; set up for the address shift
shr dx,1 ; (ugly) 32-bit shift-by-3 logic
rcr si,1 ; ((works on ANY 80x6 processor))
shr dx,1 ; ...
rcr si,1 ; ...
shr dx,1 ; ...
rcr si,1 ; ...
cmp dx,curbk ; see if bank changed
je vgasame_bank ; jump if old bank ok
mov ax,dx ; newbank expects bank in al
call far ptr newbank ; switch banks
vgasame_bank:
mov ch,01h ; bit mask to shift
shl ch,cl ; ...
mov bx,0 ; initialize bits-read value (none)
mov dx,03ceh ; graphics controller address
mov ax,0304h ; set up controller address register
vgareadloop:
out dx,ax ; do it
mov bh,es:[si] ; retrieve the old value
and bh,ch ; mask one bit
neg bh ; set bit 7 correctly
rol bx,1 ; rotate the bit into bl
dec ah ; go for another bit?
jge vgareadloop ; sure, why not.
mov al,bl ; returned pixel value
ret ; we done.
vgaread endp
outax8bit proc near ; convert OUT DX,AX to
push ax ; several OUT DX,ALs
out dx,al ; (leaving registers intact)
inc dx
mov al,ah
out dx,al
dec dx
pop ax
ret
outax8bit endp
; --------------------------------------------------------------------------
; new Tandy and CGA code from Joseph Albrecht
align 2
;Scan line address table for 16K video memory
scan16k dw 0000h,2000h,0050h,2050h,00A0h,20A0h,00F0h,20F0h
dw 0140h,2140h,0190h,2190h,01E0h,21E0h,0230h,2230h
dw 0280h,2280h,02D0h,22D0h,0320h,2320h,0370h,2370h
dw 03C0h,23C0h,0410h,2410h,0460h,2460h,04B0h,24B0h
dw 0500h,2500h,0550h,2550h,05A0h,25A0h,05F0h,25F0h
dw 0640h,2640h,0690h,2690h,06E0h,26E0h,0730h,2730h
dw 0780h,2780h,07D0h,27D0h,0820h,2820h,0870h,2870h
dw 08C0h,28C0h,0910h,2910h,0960h,2960h,09B0h,29B0h
dw 0A00h,2A00h,0A50h,2A50h,0AA0h,2AA0h,0AF0h,2AF0h
dw 0B40h,2B40h,0B90h,2B90h,0BE0h,2BE0h,0C30h,2C30h
dw 0C80h,2C80h,0CD0h,2CD0h,0D20h,2D20h,0D70h,2D70h
dw 0DC0h,2DC0h,0E10h,2E10h,0E60h,2E60h,0EB0h,2EB0h
dw 0F00h,2F00h,0F50h,2F50h,0FA0h,2FA0h,0FF0h,2FF0h
dw 1040h,3040h,1090h,3090h,10E0h,30E0h,1130h,3130h
dw 1180h,3180h,11D0h,31D0h,1220h,3220h,1270h,3270h
dw 12C0h,32C0h,1310h,3310h,1360h,3360h,13B0h,33B0h
dw 1400h,3400h,1450h,3450h,14A0h,34A0h,14F0h,34F0h
dw 1540h,3540h,1590h,3590h,15E0h,35E0h,1630h,3630h
dw 1680h,3680h,16D0h,36D0h,1720h,3720h,1770h,3770h
dw 17C0h,37C0h,1810h,3810h,1860h,3860h,18B0h,38B0h
dw 1900h,3900h,1950h,3950h,19A0h,39A0h,19F0h,39F0h
dw 1A40h,3A40h,1A90h,3A90h,1AE0h,3AE0h,1B30h,3B30h
dw 1B80h,3B80h,1BD0h,3BD0h,1C20h,3C20h,1C70h,3C70h
dw 1CC0h,3CC0h,1D10h,3D10h,1D60h,3D60h,1DB0h,3DB0h
dw 1E00h,3E00h,1E50h,3E50h,1EA0h,3EA0h,1EF0h,3EF0h
;Scan line address table for 32K video memory
scan32k dw 0000h,2000h,4000h,6000h,00a0h,20a0h,40a0h,60a0h
dw 0140h,2140h,4140h,6140h,01e0h,21e0h,41e0h,61e0h
dw 0280h,2280h,4280h,6280h,0320h,2320h,4320h,6320h
dw 03c0h,23c0h,43c0h,63c0h,0460h,2460h,4460h,6460h
dw 0500h,2500h,4500h,6500h,05a0h,25a0h,45a0h,65a0h
dw 0640h,2640h,4640h,6640h,06e0h,26e0h,46e0h,66e0h
dw 0780h,2780h,4780h,6780h,0820h,2820h,4820h,6820h
dw 08c0h,28c0h,48c0h,68c0h,0960h,2960h,4960h,6960h
dw 0a00h,2a00h,4a00h,6a00h,0aa0h,2aa0h,4aa0h,6aa0h
dw 0b40h,2b40h,4b40h,6b40h,0be0h,2be0h,4be0h,6be0h
dw 0c80h,2c80h,4c80h,6c80h,0d20h,2d20h,4d20h,6d20h
dw 0dc0h,2dc0h,4dc0h,6dc0h,0e60h,2e60h,4e60h,6e60h
dw 0f00h,2f00h,4f00h,6f00h,0fa0h,2fa0h,4fa0h,6fa0h
dw 1040h,3040h,5040h,7040h,10e0h,30e0h,50e0h,70e0h
dw 1180h,3180h,5180h,7180h,1220h,3220h,5220h,7220h
dw 12c0h,32c0h,52c0h,72c0h,1360h,3360h,5360h,7360h
dw 1400h,3400h,5400h,7400h,14a0h,34a0h,54a0h,74a0h
dw 1540h,3540h,5540h,7540h,15e0h,35e0h,55e0h,75e0h
dw 1680h,3680h,5680h,7680h,1720h,3720h,5720h,7720h
dw 17c0h,37c0h,57c0h,77c0h,1860h,3860h,5860h,7860h
dw 1900h,3900h,5900h,7900h,19a0h,39a0h,59a0h,79a0h
dw 1a40h,3a40h,5a40h,7a40h,1ae0h,3ae0h,5ae0h,7ae0h
dw 1b80h,3b80h,5b80h,7b80h,1c20h,3c20h,5c20h,7c20h
dw 1cc0h,3cc0h,5cc0h,7cc0h,1d60h,3d60h,5d60h,7d60h
dw 1e00h,3e00h,5e00h,7e00h,1ea0h,3ea0h,5ea0h,7ea0h
;Scan line address table for 64K video memory
scan64k dw 00000h,00140h,00280h,003c0h,00500h,00640h,00780h,008c0h
dw 00a00h,00b40h,00c80h,00dc0h,00f00h,01040h,01180h,012c0h
dw 01400h,01540h,01680h,017c0h,01900h,01a40h,01b80h,01cc0h
dw 01e00h,01f40h,02080h,021c0h,02300h,02440h,02580h,026c0h
dw 02800h,02940h,02a80h,02bc0h,02d00h,02e40h,02f80h,030c0h
dw 03200h,03340h,03480h,035c0h,03700h,03840h,03980h,03ac0h
dw 03c00h,03d40h,03e80h,03fc0h,04100h,04240h,04380h,044c0h
dw 04600h,04740h,04880h,049c0h,04b00h,04c40h,04d80h,04ec0h
dw 05000h,05140h,05280h,053c0h,05500h,05640h,05780h,058c0h
dw 05a00h,05b40h,05c80h,05dc0h,05f00h,06040h,06180h,062c0h
dw 06400h,06540h,06680h,067c0h,06900h,06a40h,06b80h,06cc0h
dw 06e00h,06f40h,07080h,071c0h,07300h,07440h,07580h,076c0h
dw 07800h,07940h,07a80h,07bc0h,07d00h,07e40h,07f80h,080c0h
dw 08200h,08340h,08480h,085c0h,08700h,08840h,08980h,08ac0h
dw 08c00h,08d40h,08e80h,08fc0h,09100h,09240h,09380h,094c0h
dw 09600h,09740h,09880h,099c0h,09b00h,09c40h,09d80h,09ec0h
dw 0a000h,0a140h,0a280h,0a3c0h,0a500h,0a640h,0a780h,0a8c0h
dw 0aa00h,0ab40h,0ac80h,0adc0h,0af00h,0b040h,0b180h,0b2c0h
dw 0b400h,0b540h,0b680h,0b7c0h,0b900h,0ba40h,0bb80h,0bcc0h
dw 0be00h,0bf40h,0c080h,0c1c0h,0c300h,0c440h,0c580h,0c6c0h
dw 0c800h,0c940h,0ca80h,0cbc0h,0cd00h,0ce40h,0cf80h,0d0c0h
dw 0d200h,0d340h,0d480h,0d5c0h,0d700h,0d840h,0d980h,0dac0h
dw 0dc00h,0dd40h,0de80h,0dfc0h,0e100h,0e240h,0e380h,0e4c0h
dw 0e600h,0e740h,0e880h,0e9c0h,0eb00h,0ec40h,0ed80h,0eec0h
dw 0f000h,0f140h,0f280h,0f3c0h,0f500h,0f640h,0f780h,0f8c0h
;
; ***** CGA Video Routines *****
;
;plot a point on 320x200x4 color graphics screen
plotcga4 proc near
mov bx,0b800h ;point es at video buffer
mov es,bx ; ..
mov bx,dx ;get scan line address
shl bx,1 ; ..
mov bx,cs:scan16k[bx] ; ..
mov ah,cl ;save low byte of column
shr cx,1 ;get column offset
shr cx,1 ; ..
add bx,cx ;add column offset to address
not ah ;get shift count
and ah,3 ; ..
shl ah,1 ; ..
mov cl,ah ; ..
and al,3 ;mask off unwanted bits
rol al,cl ;get or mask
mov ah,0fch ;get and mask
rol ah,cl ; ..
mov cl,es:[bx] ;plot the point
and cl,ah ; ..
or cl,al ; ..
mov es:[bx],cl ; ..
ret
plotcga4 endp
;return a point from 320x200x4 color graphics screen
getcga4 proc near
mov bx,0b800h ;point es at video buffer
mov es,bx ; ..
mov bx,dx ;get scan line address
shl bx,1 ; ..
mov bx,cs:scan16k[bx] ; ..
mov ax,cx ;save column
shr ax,1 ;get column offset
shr ax,1 ; ..
add bx,ax ;add column offset to address
not cl ;get shift count
and cl,3 ; ..
shl cl,1 ; ..
mov al,es:[bx] ;return the point
ror al,cl ; ..
and ax,3 ; ..
ret
getcga4 endp
;plot a point on 640x200x2 color graphics screen
plotcga2 proc near
mov bx,0b800h ;point es at video buffer
mov es,bx ; ..
mov bx,dx ;get scan line address
shl bx,1 ; ..
mov bx,cs:scan16k[bx] ; ..
mov ah,cl ;save low order byte of column
shr cx,1 ;get column offset
shr cx,1 ; ..
shr cx,1 ; ..
add bx,cx ;add column offset to address
not ah ;get shift count
and ah,7 ; ..
mov cl,ah ; ..
and al,1 ;mask off unwanted bits
rol al,cl ;get or mask
mov ah,0feh ;get and mask
rol ah,cl ; ..
mov cl,es:[bx] ;plot the point
and cl,ah ; ..
or cl,al ; ..
mov es:[bx],cl ; ..
ret
plotcga2 endp
;return a point from 640x200x2 color graphics screen
getcga2 proc near
mov bx,0b800h ;point es at video buffer
mov es,bx ; ..
mov bx,dx ;get scan line address
shl bx,1 ; ..
mov bx,cs:scan16k[bx] ; ..
mov ax,cx ;save column
shr ax,1 ;get column offset
shr ax,1 ; ..
shr ax,1 ; ..
add bx,ax ;add column offset to address
not cl ;get shift count
and cl,7 ; ..
mov al,es:[bx] ;return the point
ror al,cl ; ..
and ax,1 ; ..
ret
getcga2 endp
;
; ***** Tandy 1000 Video Routines *****
;
;plot a point on tandy 1000 640x200x4 color graphics screen
plottandy4 proc near
mov bx,0b800h ;point es at video segment
mov es,bx ; ..
mov bx,dx ;get scan line address
shl bx,1 ; ..
mov bx,cs:scan32k[bx] ; ..
mov dx,cx ;save column
shr dx,1 ;get column offset
shr dx,1 ; ..
and dl,0feh ; ..
add bx,dx ;add column offset to address
not cl ;get shift count
and cl,7 ; ..
mov ah,al ;get or mask
shr ah,1 ; ..
and ax,101h ; ..
rol ax,cl ; ..
mov dx,0fefeh ;get and mask
rol dx,cl ; ..
mov cx,es:[bx] ;plot the point
and cx,dx ; ..
or cx,ax ; ..
mov es:[bx],cx ; ..
ret
plottandy4 endp
;return a point from tandy 1000 640x200x4 color graphics screen
gettandy4 proc near
mov bx,0b800h ;point es at video segment
mov es,bx ; ..
mov bx,dx ;get scan line address
shl bx,1 ; ..
mov bx,cs:scan32k[bx] ; ..
mov ax,cx ;save column
shr ax,1 ;get column offset
shr ax,1 ; ..
and al,0feh ; ..
add bx,ax ;add column offset to address
not cl ;get shift count
and cl,7 ; ..
mov ax,es:[bx] ;return the point
ror ax,cl ; ..
and ax,101h ; ..
rol ah,1 ; ..
or al,ah ; ..
and ax,3 ; ..
ret
gettandy4 endp
;plot a point on tandy 1000 16 color graphics screen
plottandy16 proc near
mov es,tandyseg ;point es at video buffer
mov bx,dx ;get scan line address
shl bx,1 ; ..
add bx,tandyscan ; ..
mov bx,cs:[bx] ; ..
mov ah,0f0h ;set mask for odd pixel
mov dx,cx ;save x
shr dx,1 ;get column offset
jc plottandy16a ;check for odd/even pixel
not ah ;set mask for even pixel
mov cl,4 ;move color to proper pobxtion
shl al,cl ; ..
plottandy16a:
add bx,dx ;add column offset to address
mov dl,es:[bx] ;plot the point
and dl,ah ; ..
or dl,al ; ..
mov es:[bx],dl ; ..
ret
plottandy16 endp
;return a point from tandy 1000 16 color graphics mode
gettandy16 proc near
mov es,tandyseg ;point es at video buffer
mov bx,dx ;get scan line address
shl bx,1 ; ..
add bx,tandyscan ; ..
mov bx,cs:[bx] ; ..
mov dx,cx ;save x
shr cx,1 ;add column offset to address
add bx,cx ; ..
mov al,es:[bx] ;get pixel
test dl,1 ;check for odd/even pixel
jnz gettandy16a ; ..
mov cl,4 ;move color to proper position
shr al,cl ; ..
gettandy16a:
and ax,0fh ;mask off unwanted bits
ret
gettandy16 endp
;setup tandy 1000 640x200x16 color mode
tandysetup proc near
mov dx,03d4h ; write to this address
mov ax,07100h ; write to this register and value
call tandyport ; do it.
mov ax,05001h ; write to this register and value
call tandyport ; do it.
mov ax,05a02h ; write to this register and value
call tandyport ; do it.
mov ax,00e03h ; write to this register and value
call tandyport ; do it.
mov ax,0ff04h ; write to this register and value
call tandyport ; do it.
mov ax,00605h ; write to this register and value
call tandyport ; do it.
mov ax,0c806h ; write to this register and value
call tandyport ; do it.
mov ax,0e207h ; write to this register and value
call tandyport ; do it.
mov ax,00009h ; write to this register and value
call tandyport ; do it.
mov ax,0000ch ; write to this register and value
call tandyport ; do it.
mov ax,01810h ; write to this register and value
call tandyport ; do it.
mov ax,04612h ; write to this register and value
call tandyport ; do it.
mov dx,03d8h ; new port
mov al,01bh ; and value
out dx,al ; do it.
mov dx,03d9h ; new port
mov al,000h ; and value
out dx,al ; do it.
mov dx,03ddh ; new port
mov al,000h ; and value
out dx,al ; do it.
mov dx,03dfh ; new port
mov al,024h ; and value
out dx,al ; do it.
mov dx,03dah ; new port
mov al,001h ; and value
out dx,al ; do it.
mov dx,03deh ; new port
mov al,00fh ; and value
out dx,al ; do it.
mov dx,03dah ; new port
mov al,002h ; and value
out dx,al ; do it.
mov dx,03deh ; new port
mov al,000h ; and value
out dx,al ; do it.
mov dx,03dah ; new port
mov al,003h ; and value
out dx,al ; do it.
mov dx,03deh ; new port
mov al,010h ; and value
out dx,al ; do it.
mov dx,03dah ; new port
mov al,005h ; and value
out dx,al ; do it.
mov dx,03deh ; new port
mov al,001h ; and value
out dx,al ; do it.
mov dx,03dah ; new port
mov al,008h ; and value
out dx,al ; do it.
mov dx,03deh ; new port
mov al,002h ; and value
out dx,al ; do it.
;set color palette registers to default state
mov cx,16 ;reset colors 0-15 to default state
xor bh,bh ;set initial color
xor bl,bl ;set initial paletter register
mov di,2 ;reset border color
call settandypal ; ..
tandysetup1:
mov di,16 ;port offset for palette registers
call settandypal ;set palette register
inc bl ;bump up to next palette register
inc bh ;bump up to next color
loop tandysetup1 ;do remaining palette registers
cmp orvideo,0 ; are we supposed to clear RAM?
jne tandysetup2 ; (nope)
push es ; save ES for a tad
mov ax,0a000h ; clear the memory
mov es,ax ; ...
cld ; string ops forward
mov cx,07d00h ; this many words
mov di,0 ; starting here
mov ax,0 ; clear out to zero
rep stosw ; do it.
pop es ; restore ES
tandysetup2:
mov oktoprint,0 ; no printing in this mode
ret
tandysetup endp
;write data to 6845 registers
tandyport proc near
out dx,al ;write 6845 reg number to port 3d4
mov al,ah ;write 6845 reg data to port 3d5
inc dx ; ..
out dx,al ; ..
dec dx ;point back to port 3d4
ret
tandyport endp
;subroutine to set a Tandy 1000 palette register
settandypal proc near
mov dx,3dah ;address & status register
cli ;disable interrupts
settandypal2:
in al,dx ;get status register
and al,8 ;look for bit 3
jz settandypal2 ;wait for vertical retrace
mov al,bl ;get palette number
cbw ; ..
add ax,di ;add offset for palette register
out dx,al ;set palette
mov al,bh ;get color to store
mov dx,3deh ;palette data register
out dx,al ;set palette color
mov dx,3dah ;address & status register
xor ax,ax ;al = 0 to reset address register
out dx,al ;reset it
sti ;re-enable interrupts
ret
settandypal endp
; -----------------------------------------------------------------------------
; The 360x480 mode draws heavily on Michael Abrash's article in
880 ; the January/February 1989 "Programmer's Journal" and files uploaded
881 ; to Compuserv's PICS forum by Dr. Lawrence Gozum - integrated here
; by Timothy Wegner
; Michael Abrash equates. Not all used, but I'll leave for reference.
882
883 VGA_SEGMENT EQU 0A000h
884 SC_INDEX EQU 3C4h ;Sequence Controller Index register
885 GC_INDEX EQU 3CEh ;Graphics Controller Index register
886 CRTC_INDEX EQU 3D4h ;CRT Controller Index register
887 MAP_MASK EQU 2 ;Map Mask register index in SC
888 MEMORY_MODE EQU 4 ;Memory Mode register in SC
889 MAX_SCAN_LINE EQU 9 ;Maximum Scan Line reg index in CRTC
890 ;Use 9 for 2 pages of 320x400
891 ;MAX_SCAN_LINE EQU 1 ;Use 1 for 4 pages of 320x200
892 START_ADD_HIGH EQU 0Ch ;Start Address High reg index in CRTC
893 UNDERLINE EQU 14h ;Underline Location reg index in CRTC
894 MODE_CONTROL EQU 17h ;Mode Control reg index in CRTC
895 READ_MAP EQU 4 ;Read Mask register index in SC
896 GRAPHICS_MODE EQU 5 ;Graphics Mode register index in SC
897 MISC EQU 6 ;Miscellaneous register index in SC
898 WORD_OUTS_OK EQU 1 ;set to 0 to assemble for computers
899 ;that can't handle word outs to indexed
;VGA registers
;
;Macro to output a word value to a port
;
OUT_WORD MACRO
IF WORD_OUTS_OK
OUT DX,AX
ELSE
OUT DX,AL
INC DX
XCHG AH,AL
OUT DX,AL
DEC DX
XCHG AH,AL
ENDIF
ENDM
;Macro to ouput a constant value to an indexed VGA register
CONSTANT_TO_INDEXED_REGISTER MACRO ADDRESS,INDEX,VALUE
MOV DX,ADDRESS
MOV AX,(VALUE SHL 8)+INDEX
OUT_WORD
ENDM
tweak256read proc near uses si ; Tweaked-VGA ...x256 color mode
mov ax,vxdots
;; shr ax,1
;; shr ax,1 ; now ax = vxdots/4
mul dx ;Point to start of desired row
push cx ;Save X coordinate for later
shr cx,1 ;There are 4 pixels at each address
shr cx,1 ;so divide X by 4
add ax,cx ;Point to pixels address
mov si,ax
pop ax ;Retrieve X coordinate
and al,3 ;Get the plane number of the pixel
mov ah,al
mov al,READ_MAP
mov dx,GC_INDEX
OUT_WORD ;Set to write to the proper plane for the
;pixel
xor ax,ax
lods byte ptr es:[si] ;Read the pixel
ret
tweak256read endp
tweak256write proc near uses di ; Tweaked-VGA ...x256 color mode
mov bl,al ; color
mov ax,vxdots
;; shr ax, 1
;; shr ax, 1 ; now ax = vxdots/4
mul dx ;Point to start of desired row
push cx ;Save X coordinate for later
shr cx,1 ;There are 4 pixels at each address
shr cx,1 ;so divide X by 4
add ax,cx ;Point to pixels address
mov di,ax
pop cx ;Retrieve X coordinate
and cl,3 ;Get the plane number of the pixel
mov ah,1
shl ah,cl ;Set the bit corresponding to the plane
;the pixel is in
mov al,MAP_MASK
mov dx,SC_INDEX
OUT_WORD ;Set to write to the proper plane for the
;pixel
mov es:[di],bl ;Draw the pixel
ret
tweak256write endp
; The following ATI 1024x768x16 mode is courtesy of Mark Peterson
ati1024read proc near ; ATI 1024x768x16 read
call ati1024addr ; calculate the address
mov al,es:[bx] ; get the byte the pixel is in
cmp xga_isinmode,0 ; say, is this really XGA-style I/O?
je notxga ; nope
test cl,1 ; is X odd?
jnz atireadhigh ; Yup. Use the high bits
jmp short atireadlow ; else use the low bits
notxga:
test cl,1 ; is X odd?
jz atireadhigh ; Nope. Use the high bits
atireadlow:
and ax,0fh ; zero out the high-order bits
ret
atireadhigh:
and ax,0f0h ; zero out the low-order bits
mov cl,4 ; shift the results
shr al,cl ; ...
ret
ati1024read endp
ati1024write proc near ; ATI 1024x768x16 write
call ati1024addr ; calculate the address
mov dl,es:[bx] ; get the byte the pixel is in
and al,00fh ; zero out the high-order color bits
cmp xga_isinmode,0 ; say, is this really XGA-style I/O?
je notxga ; nope
test cl,1 ; is X odd?
jnz atiwritehigh ; Yup. Use the high bits
jmp short atiwritelow ; else use the low bits
notxga:
test cl,1 ; is X odd?
jz atiwritehigh ; Nope. Use the high bits
atiwritelow:
and dl,0f0h ; zero out the low-order video bits
or dl,al ; add the two together
mov es:[bx],dl ; and write the results
ret
atiwritehigh:
mov cl,4 ; shift the color bits
shl al,cl ; ...
and dl,0fh ; zero out the high-order video bits
or dl,al ; add the two together
mov es:[bx],dl ; and write the results
ret
ati1024write endp
ati1024addr proc near ; modification of TIW's Super256addr
900 clc ; clear carry flag
901 push ax ; save this for a tad
902 mov ax,vxdots ; this many dots / line
903 mul dx ; times this many lines - ans in dx:ax
904 add ax,cx ; plus this many x-dots
905 adc dx,0 ; answer in dx:ax
906 shr dx,1 ; shift the answer right one bit
907 rcr ax,1 ; .. in the 32-bit DX:AX combo
908 mov bx,ax ; save this in BX
909 cmp dx,curbk ; see if bank changed
910 je atisame_bank ; jump if old bank ok
911 mov ax,dx ; newbank expects bank in al
912 call far ptr newbank
913 atisame_bank:
914 pop ax ; restore AX
915 ret
916 ati1024addr endp
917
918 ;
919 ; VESA true-color routines
920
921 ; ************** Function dac_to_rgb() *******************
922
923 ; returns the rgb values (in bl, dh & dl) corresponding to the
924 ; color (passed in ax) entry in dacbox
925
926 ; dac_to_rgb -----------------------------------------------------------------
927 ; * changed to return dl=blue, dh=green (was dl=green, dh=blue) - bl=red stays
928 ; (is called only by VESAtruewrite, and videoram bgr layout needs this change)
929 ; ------------------------------------------------------------30-06-2002-ChCh-
930
931 dac_to_rgb proc uses di
932 cmp truemode,0
933 jne @f
934 mov bx,ax
935 add ax,bx
936 add ax,bx ; ax * 3
937 mov di,ax
938 mov bl,dacbox+0[di] ; red
939 mov dh,dacbox+1[di] ; green
940 mov dl,dacbox+2[di] ; blue
941 ret ; we done.
942 @@:
943 cmp truemode,1
944 jne @f
945 mov dx,word ptr realcoloriter
946 ; xchg dh,dl
947 mov ax,word ptr realcoloriter+2
948 mov bl,al ; red
949 ret ; we done.
950 @@: ; truemode = 2
951 cmp truemode,2
952 jne @f
953 mov dx,word ptr coloriter
954 ; xchg dh,dl
955 mov ax,word ptr coloriter+2
956 mov bl,al ; red
957 ret ; we done.
958 @@: ; truemode = 3
959 mov ax,word ptr coloriter
960 mov dl,al ; blue
961 mov cx,4
962 shl ax,cl
963 mov dh,ah ; green
964 ; mov ax,word ptr coloriter+2
965 neg ax
966 mov bl,ah ; red
967 ret ; we done.
968 dac_to_rgb endp
969
970 ; ************** Function rgb_to_dac() *******************
971
972 ; returns the dac index value (in al, ah=0) corresponding to the
973 ; rgb values (passed in bl, dh & dl)
974
975 ; rgb_to_dac -----------------------------------------------------------------
976 ; * changed to await dl=blue, dh=green (was dl=green, dh=blue) - bl=red stays
977 ; (is called only by VESAtrueread, and videoram bgr layout needs this change)
978 ; ------------------------------------------------------------30-06-2002-ChCh-
979
980 rgb_to_dac proc
981 LOCAL red:word, green:word, blue:word
982 xor bh,bh
983 mov red,bx
984 mov bl,dh
985 mov green,bx
986 mov bl,dl
987 mov blue,bx
988 mov si,0 ; look for the nearest DAC value
989 mov di,0 ; di = closest DAC
990 mov cx,65535 ; cx = closest squared error
991 nextentry:
992 ; mov bx,0 ; bx = this entry's squared error
mov ax,red ; ax = red portion
mov dh,0
mov dl,dacbox[si]
sub ax,dx ; ax = (color - DAC color)
mov dx,ax
imul dx ; ax = color squared error
mov bx,ax ; bx = total squared error
mov ax,green ; ax = green portion
mov dh,0
mov dl,dacbox+1[si]
sub ax,dx ; ax = (color - DAC color)
mov dx,ax
imul dx ; ax = color squared error
add bx,ax ; bx = total squared error
mov ax,blue ; ax = blue portion
mov dh,0
mov dl,dacbox+2[si]
sub ax,dx ; ax = (color - DAC color)
mov dx,ax
imul dx ; ax = color squared error
add bx,ax ; bx = total squared error
cmp bx,cx ; new closest value?
jae @f ; nope
mov di,si ; yes - save this entry
mov cx,bx ; and its error
@@: cmp cx,0 ; did we find a perfect match?
je @f ; yup - we're done!
993 add si,3 ; move to a new DAC entry
994 cmp si,256*3 ; are we out of entries?
995 jb nextentry ; nope
996 @@: mov ax,di ; convert DI back into a palette value
997 mov bx,3 ; by dividing by 3
998 div bl
999 mov ah,0
1000 ret ; we done.
1001 rgb_to_dac endp
1002
1003 ; VESAtruewrite --------------------------------------------------------------
1004 ; * the major change is calling VESAtrueaddr just once (was three times!)
1005 ; * this also frees use of some registers, so local variables are removed
1006 ; * a minor fix in unusual r-g-b layout (was b-g-b) does any card use it?
1007 ; ------------------------------------------------------------30-06-2002-ChCh-
1008
1009 VESAtruewrite proc near ; VESA true-color write-a-dot
1010 ; color index is passed in ax
1011 push ax
1012 call VESAtrueaddr ; calculate address and switch banks
1013 pop ax
1014 push dx ; bank needed later
1015 push bx ; offset as well
1016 call dac_to_rgb ; ax=color -> dx=gb, bl=r
1017 mov ax,vesa_winaseg ; VESA video starts here
1018 cmp vesa_bitsppixel,17 ; 8-8-8 and 8-8-8-8
1019 mov es,ax
1020 jnb over_hi
1021 mov cx,111111b ; mask
1022 mov al,dh ; green
1023 and dx,cx ; blue
1024 and bx,cx ; red
1025 and ax,cx
1026 mov cl,vesa_redpos
1027 cmp vesa_greensize,6 ; 5-5-5 or 5-6-5
1028 je got_6g
1029 shr ax,1
1030 got_6g:
1031 shr bx,1
1032 shr dx,1
1033 shl bx,cl
1034 mov cl,vesa_greenpos
1035 or dx,bx ; r-_-b
1036 shl ax,cl
1037 pop bx
1038 or dx,ax ; r-g-b
1039 pop ax
1040 mov word ptr es:[bx],dx ; write two bytes for the dot
1041 jmp short wedone
1042 over_hi: ; 8-8-8 or 8-8-8-8?
1043 mov cx,bx ; r
1044 shl dx,1 ; well, 6-6-6 is not true-true
1045 shl cx,1
1046 shl dx,1 ; b-g
1047 shl cx,1
1048 cmp vesa_redpos,0 ; common b-g-r model?
1049 jne doit_slow
1050 xchg dl,cl ; else turn to unusual r-g-b
1051 doit_slow:
1052 pop bx ; get offset
1053 pop ax ; get bank
1054 inc bx ; does a word fit to this bank?
1055 jz badbank1 ; no, switch one byte after
1056 mov word ptr es:[bx-1],dx ; else plot that word
1057 push cx ; hand it over to the switch
1058 inc bx ; bank-end?
1059 jz badbank2 ; yes, switch it
1060 mov es:[bx],cl ; else write the third byte
1061 pop cx ; wasn't needed - no switching
jmp short wedone
badbank1:
dec bx ; bx=0ffffh
mov es:[bx],dl ; plot the first byte
xchg dh,dl ; second color for badbank2
push dx ; hand it over
badbank2:
inc ax ; next bank needed
call far ptr newbank
pop ax ; get next color
inc bx ; badbank1 or badbank2?
mov es:[0],al ; plot that color
jnz wedone ; badbank2 - nothing more to do
mov es:[1],cl ; badbank1 - plot the last byte
wedone:
ret ; we done.
VESAtruewrite endp
; VESAtrueread ---------------------------------------------------------------
; * similar changes as in VESAtruewrite
; * hi-color-word rgb extraction quite shortened
; ------------------------------------------------------------30-06-2002-ChCh-
VESAtrueread proc near ; VESA true-color read-a-dot
; color index is returned in ax
call VESAtrueaddr ; calculate address and switch banks
mov ax,vesa_winaseg ; VESA video starts here
cmp vesa_bitsppixel,17 ; 8-8-8 and 8-8-8-8
mov es,ax
jnb over_hi
mov dx,word ptr es:[bx] ; read two bytes
mov cl,3
mov bx,dx
shl dx,cl
mov cl,vesa_redpos
shr dl,1
shr bx,cl
shr dl,1 ; blue in dl
cmp vesa_greensize,6
je got_6g
shl dh,1
got_6g:
shl bx,1 ; red in bl
and dh,111111b ; green in dh
jmp short wedone
over_hi: ; 8-8-8 or 8-8-8-8?
mov ax,dx ; newbank expects bank in ax
inc bx ; does a word fit to this bank?
jz badbank1 ; no, switch one byte after
mov dx,word ptr es:[bx-1] ; else read that word
inc bx ; bank-end?
jz badbank2 ; yes, switch it
mov bl,es:[bx] ; else read the third byte
jmp short colors_in
badbank1:
dec bx ; bx=0ffffh
mov dl,es:[bx] ; read the first byte
badbank2:
inc ax ; next bank needed
call far ptr newbank
inc bx ; badbank1 or badbank2?
mov bl,es:[0] ; read next color
jnz colors_in ; badbank2 - nothing more to do
mov dh,bl
mov bl,es:[1] ; badbank1 - read the last byte
colors_in:
and dx,0FCFCh ; mask-out 2 g & 2 b lsbs for shift
shr bl,1
shr dx,1
shr bl,1
shr dx,1
cmp vesa_redpos,0
jne wedone
xchg bl,dl
wedone:
call rgb_to_dac ; put dac index in ax
ret ; we done.
VESAtrueread endp
; VESAtrueaddr ---------------------------------------------------------------
; * changed to not to take into account vesabyteoffset
; ------------------------------------------------------------30-06-2002-ChCh-
VESAtrueaddr proc near
mov bx,cx ; adjust the pixel location
cmp vesa_bitsppixel,17 ; 2 bytes/pixel
jb depth_ok ; write a word at a time, no offset
shl bx,1 ; +x
cmp vesa_bitsppixel,25 ; 3 bytes/pixel
jb depth_ok ; else 4 bytes/pixel
add bx,cx ; +x
depth_ok:
mov ax,vxdots ; this many dots / line
add bx,cx ; +x
mul dx ; times this many lines - ans in dx:ax
add bx,ax ; plus this many x-dots
adc dx,0 ; answer in dx:ax - dl=bank, ax=offset
cmp dx,curbk ; see if bank changed
je same_bank ; jump if old bank not ok
mov ax,dx ; newbank expects bank in al
call far ptr newbank
same_bank:
ret ; we done.
VESAtrueaddr endp
;
; The following 'Super256' code is courtesy of Timothy Wegner.
;
super256write proc near ; super-VGA ...x256 colors write-a-dot
call super256addr ; calculate address and switch banks
mov es:[bx],al ; write the dot
ret ; we done.
super256write endp
super256read proc near ; super-VGA ...x256 colors read-a-dot
call super256addr ; calculate address and switch banks
mov al,es:[bx] ; read the dot
ret ; we done.
super256read endp
super256addr proc near ; can be put in-line but shared by
; read and write routines
clc ; clear carry flag
push ax ; save this for a tad
mov ax,vxdots ; this many dots / line
mul dx ; times this many lines - ans in dx:ax
add ax,cx ; plus this many x-dots
adc dx,0 ; answer in dx:ax - dl=bank, ax=offset
mov bx,ax ; save this in BX
cmp dx,curbk ; see if bank changed
je same_bank ; jump if old bank ok
mov ax,dx ; newbank expects bank in al
call far ptr newbank
same_bank:
pop ax ; restore AX
ret
super256addr endp
;
; BANKS.ASM was used verbatim except:
; 1) removed ".model small"
; 2) deleted "end"
; Integrated by Tim Wegner 8/15/89
; (switched to John's 9/7/89 version on 9/10/89 - Bert)
1062 ; (switched to John's 1/5/90 version on 1/9/90 - Bert)
; (switched to John's version 3 on 4/27/90 - Bert)
1063 ; (added logic for various resolution on 9/10/90 - Bert)
1064 ; (upgraded to John's version 3.5 on 5/14/91 - Bert)
;
; .MODEL medium,c
;
; Copyright 1988,89,90,91 John Bridges
; Free for use in commercial, shareware or freeware applications
;
; SVGAMODE.ASM
;
.data
OSEG equ SS: ;segment override for variable access
bankadr dw offset $nobank
if @CodeSize
bankseg dw seg $nobank
endif
vesa_bankswitch dd $vesa_nullbank ; initially, do-nothing
vesa_mapper dd $nobank
vesa_detect dw 1 ; set to 0 to disable VESA-detection
vesa_gran_offset dw 0
vesa_low_window dw 0
vesa_high_window dw 1
vesa_granularity db 0 ; BDT VESA Granularity value
istruecolor dw 0 ; set to 1 if VESA truecolor mode
align 2
; vesabytes db 0,0,0,0 ; our true-color pixel
; vesabyteoffset dw 0 ; used in true-color routines
; the first 40 bytes of the 256-byte VESA mode-info block
vesa_mode_info dw 0 ; mode info: attributes
vesa_winaattrib db 0 ; Win AA attribs
vesa_winbattrib db 0 ; Win BB attribs
vesa_wingran dw 0 ; window granularity
vesa_winsize dw 0 ; window size
vesa_winaseg dw 0 ; window AA segment
vesa_winbseg dw 0 ; window BB segment
vesa_funcptr dd 0 ; bank_switcher
vesa_bytespscan dw 0 ; bytes per scan line
vesa_xres dw 0 ; X-resolution
vesa_yres dw 0 ; Y-resolution
vesa_xcharsize db 0 ; X charsize
vesa_ycharsize db 0 ; Y charsize
vesa_numplanes db 0 ; number of planes
vesa_bitsppixel db 0 ; bits / pixel
vesa_numbanks db 0 ; number of banks
vesa_memmodel db 0 ; memory-model type
vesa_banksize db 0 ; bank size in KB
vesa_numpages db 0 ; number of complete images
vesa_rsvd db 0 ; reserved for page function
vesa_redsize db 0 ; red mask size
vesa_redpos db 0 ; red mask position
vesa_greensize db 0 ; green mask size
vesa_greenpos db 0 ; green mask position
vesa_bluesize db 0 ; blue mask size
vesa_bluepos db 0 ; blue mask position
vesa_rsvdsize db 0 ; reserved mask size
vesa_rsvdpos db 0 ; reserved mask position
vesa_directinfo db 0 ; direct-color-mode attributes
public curbk
align 2
curbk dw 0
vga512 dw 0
vga1024 dw 0
public supervga_list ; pointer to head of the SuperVGA list
supervga_list db "aheada"
aheada dw 0
db "ati "
ativga dw 0
db "chi "
chipstech dw 0
db "eve "
everex dw 0
db "gen "
genoa dw 0
db "ncr "
ncr dw 0
db "oak "
oaktech dw 0
db "par "
paradise dw 0
db "tri "
trident dw 0
db "tseng3"
tseng dw 0
db "tseng4"
tseng4 dw 0
db "vid "
video7 dw 0
db "aheadb"
aheadb dw 0
db "vesa "
vesa dw 0
db "cirrus"
cirrus dw 0
db "t8900 "
t8900 dw 0
db "compaq"
compaq dw 0
db "xga "
xga dw 0
db " " ; end-of-the-list
dw 0
done_detect dw 0 ;flag to call adapter_detect & whichvga once
; this part is new - Bert
.code
vesa_entries dw 0
dw 640, 400,256, 4f02h,100h
dw 640, 480,256, 4f02h,101h
dw 800, 600, 16, 4f02h,102h
dw 800, 600,256, 4f02h,103h
dw 1024, 768, 16, 4f02h,104h
dw 1024, 768,256, 4f02h,105h
dw 1280,1024, 16, 4f02h,106h
dw 1280,1024,256, 4f02h,107h
ahead_entries dw 0
dw 800, 600, 16, 06ah,0
dw 800, 600, 16, 071h,0
dw 1024, 768, 16, 074h,0
dw 640, 400,256, 060h,0
dw 640, 480,256, 061h,0
dw 800, 600,256, 062h,0
dw 1024, 768,256, 063h,0
ati_entries dw 0
dw 800, 600, 16, 054h,0
dw 1024, 768, 16, 065h,0ffh ; (non-standard mode flag)
; dw 1024, 768, 16, 055h,0
dw 640, 400,256, 061h,0
dw 640, 480,256, 062h,0
dw 800, 600,256, 063h,0
dw 1024, 768,256, 064h,0
chips_entries dw 0
dw 800, 600, 16, 070h,0
dw 1024, 768, 16, 072h,0
dw 640, 400,256, 078h,0
dw 640, 480,256, 079h,0
dw 800, 600,256, 07bh,0
compaq_entries dw 0
dw 640, 480,256, 02eh,0fdh ; (non-standard mode flag)
everex_entries dw 0
dw 752, 410, 16, 070h,01h
dw 800, 600, 16, 070h,02h
dw 1280, 350, 4, 070h,11h
dw 1280, 600, 4, 070h,12h
dw 640, 350,256, 070h,13h
dw 640, 400,256, 070h,14h
dw 512, 480,256, 070h,15h
dw 1024, 768, 16, 070h,20h
dw 640, 480,256, 070h,30h
dw 800, 600,256, 070h,31h
dw 1024, 768,256, 070h,32h
genoa_entries dw 0
dw 1024, 768, 4, 07fh,0
dw 720, 512, 16, 059h,0
dw 800, 600, 16, 079h,0
dw 1024, 768, 16, 05fh,0
dw 640, 350,256, 05bh,0
dw 640, 400,256, 07eh,0
dw 640, 480,256, 05ch,0
dw 720, 512,256, 05dh,0
dw 800, 600,256, 05eh,0
ncr_entries dw 0
dw 1024, 768, 2, 5ah,0
dw 800, 600, 16, 58h,0
dw 1024, 768, 16, 5dh,0
dw 640, 400,256, 5eh,0
dw 640, 480,256, 5fh,0
dw 800, 600,256, 5ch,0
; dw 0 ; this appears to be extra! JCO
oaktech_entries dw 0
dw 800, 600, 16, 52h,0
dw 640, 480,256, 53h,0
dw 800, 600,256, 54h,0
dw 1024, 768, 16, 56h,0
dw 1024, 768,256, 59h,0
dw 1280,1024, 16, 58h,0
; dw 0
paradise_entries dw 0
dw 800, 600, 2, 059h,0
dw 800, 600, 16, 058h,0
dw 640, 400,256, 05eh,0
dw 640, 480,256, 05fh,0
dw 1024, 768, 16, 05dh,0
dw 800, 600,256, 05ch,0 ; Chuck Ebbert, 910524
trident_entries dw 0
dw 1024, 768, 4, 060h,0
dw 800, 600, 16, 05bh,0
dw 1024, 768, 16, 05fh,0
dw 640, 400,256, 05ch,0
dw 640, 480,256, 05dh,0
dw 800, 600,256, 05eh,0
dw 1024, 768,256, 062h,0
tseng_entries dw 0
dw 800, 600, 16, 029h,0
dw 1024, 768, 16, 037h,0
dw 640, 350,256, 02dh,0
dw 640, 400,256, 0,0feh ; (non-standard mode flag)
dw 640, 480,256, 02eh,0
dw 720, 512,256, 02fh,0
dw 800, 600,256, 030h,0
dw 1024, 768,256, 038h,0
tseng4_entries dw 0
dw 800, 600, 16, 29h,0
dw 1024, 768, 16, 37h,0
dw 640, 350,256, 2dh,0
dw 640, 400,256, 2fh,0
dw 640, 480,256, 2eh,0
dw 800, 600,256, 30h,0
dw 1024, 768,256, 38h,0
video7_entries dw 0
dw 752, 410, 16, 6f05h,60h
dw 720, 540, 16, 6f05h,61h
dw 800, 600, 16, 6f05h,62h
dw 1024, 768, 2, 6f05h,63h
dw 1024, 768, 4, 6f05h,64h
dw 1024, 768, 16, 6f05h,65h
dw 640, 400,256, 6f05h,66h
dw 640, 480,256, 6f05h,67h
dw 720, 540,256, 6f05h,68h
dw 800, 600,256, 6f05h,69h
dw 1024, 768,256, 6f05h,6ah
xga_entries dw 0
dw 1024, 768,256,0ffffh,02h
dw 1024, 768, 16,0ffffh,03h
dw 640, 400,256,0ffffh,04h
dw 640, 480,256,0ffffh,04h
dw 800, 600, 16,0ffffh,06h
dw 800, 600,256,0ffffh,07h
no_entries dw 0
dw 320, 200,256, 13h,0
dw 640, 480, 16, 12h,0
dw 0
.code
newbank proc ;bank number is in AX
cli
mov OSEG[curbk],ax
if @CodeSize
call dword ptr OSEG[bankadr]
else
call word ptr OSEG[bankadr]
endif
ret
newbank endp
$tseng proc ;Tseng
push ax
push dx
and al,7
mov ah,al
shl al,1
shl al,1
shl al,1
or al,ah
or al,01000000b
mov dx,3cdh
out dx,al
sti
pop dx
pop ax
ret
$tseng endp
$tseng4 proc ;Tseng 4000 series
push ax
push dx
mov ah,al
mov dx,3bfh ;Enable access to extended registers
mov al,3
out dx,al
mov dl,0d8h
mov al,0a0h
out dx,al
and ah,15
mov al,ah
shl al,1
shl al,1
shl al,1
shl al,1
or al,ah
mov dl,0cdh
out dx,al
sti
pop dx
pop ax
ret
$tseng4 endp
$trident proc ;Trident
push ax
push dx
mov dx,3ceh ;set page size to 64k
mov al,6
out dx,al
inc dl
in al,dx
dec dl
or al,4
mov ah,al
mov al,6
out dx,ax
mov dl,0c4h ;switch to BPS mode
mov al,0bh
out dx,al
inc dl
in al,dx
dec dl
mov ah,byte ptr OSEG[curbk]
xor ah,2
mov dx,3c4h
mov al,0eh
out dx,ax
sti
pop dx
pop ax
ret
$trident endp
$video7 proc ;Video 7
push ax
push dx
push cx
; Video-7 1024x768x16 mode patch (thanks to Frank Lozier 11/8/89).
cmp colors,16
jne video7xx
shl ax,1
shl ax,1
video7xx:
and ax,15
mov ch,al
mov dx,3c4h
mov ax,0ea06h
out dx,ax
mov ah,ch
and ah,1
mov al,0f9h
out dx,ax
mov al,ch
and al,1100b
mov ah,al
shr ah,1
shr ah,1
or ah,al
mov al,0f6h
out dx,al
inc dx
in al,dx
dec dx
and al,not 1111b
or ah,al
mov al,0f6h
out dx,ax
mov ah,ch
mov cl,4
shl ah,cl
and ah,100000b
mov dl,0cch
in al,dx
mov dl,0c2h
and al,not 100000b
or al,ah
out dx,al
sti
pop cx
pop dx
pop ax
ret
$video7 endp
$paradise proc ;Paradise
push ax
push dx
mov dx,3ceh
mov ax,50fh ;turn off write protect on VGA registers
out dx,ax
mov ah,byte ptr OSEG[curbk]
shl ah,1
shl ah,1
shl ah,1
shl ah,1
mov al,9
out dx,ax
mov ax,000Fh ;reprotect registers, 910512
out dx,ax
sti
pop dx
pop ax
ret
$paradise endp
$chipstech proc ;Chips & Tech
push ax
push dx
mov dx,46e8h ;place chip in setup mode
mov ax,1eh
out dx,ax
mov dx,103h ;enable extended registers
mov ax,0080h ; (patched per JB's msg - Bert)
1065 out dx,ax
1066 mov dx,46e8h ;bring chip out of setup mode
1067 mov ax,0eh
1068 out dx,ax
1069 mov ah,byte ptr OSEG[curbk]
1070 shl ah,1 ;change 64k bank number into 16k bank number
1071 shl ah,1
1072 mov al,10h
1073 mov dx,3d6h
1074 out dx,ax
1075 sti
1076 pop dx
1077 pop ax
1078 ret
1079 $chipstech endp
1080
1081 $ativga proc ;ATI VGA Wonder
1082 push ax
1083 push dx
1084 mov ah,al
1085 mov dx,1ceh
1086 mov al,0b2h
1087 out dx,al
1088 inc dl
1089 in al,dx
1090 shl ah,1
1091 and al,0e1h
1092 or ah,al
1093 mov al,0b2h
1094 dec dl
1095 out dx,ax
1096 sti
1097 pop dx
1098 pop ax
1099 ret
1100 $ativga endp
1101
1102 $everex proc ;Everex
1103 push ax
1104 push dx
1105 push cx
1106 mov cl,al
1107 mov dx,3c4h
1108 mov al,8
1109 out dx,al
1110 inc dl
1111 in al,dx
1112 dec dl
1113 shl al,1
1114 shr cl,1
1115 rcr al,1
1116 mov ah,al
1117 mov al,8
1118 out dx,ax
1119 mov dl,0cch
1120 in al,dx
1121 mov dl,0c2h
1122 and al,0dfh
1123 shr cl,1
1124 jc nob2
1125 or al,20h
1126 nob2: out dx,al
1127 sti
1128 pop cx
1129 pop dx
1130 pop ax
1131 ret
1132 $everex endp
1133
1134 $aheada proc
1135 push ax
1136 push dx
1137 push cx
1138 mov ch,al
1139 mov dx,3ceh ;Enable extended registers
1140 mov ax,200fh
1141 out dx,ax
1142 mov dl,0cch ;bit 0
1143 in al,dx
1144 mov dl,0c2h
1145 and al,11011111b
1146 shr ch,1
1147 jnc temp_1
1148 or al,00100000b
1149 temp_1: out dx,al
1150 mov dl,0cfh ;bits 1,2,3
1151 mov al,0
1152 out dx,al
1153 inc dx
1154 in al,dx
1155 dec dx
1156 and al,11111000b
1157 or al,ch
1158 mov ah,al
1159 mov al,0
1160 out dx,ax
1161 sti
1162 pop cx
1163 pop dx
1164 pop ax
1165 ret
1166 $aheada endp
1167
1168 $aheadb proc
1169 push ax
1170 push dx
1171 push cx
1172 mov ch,al
1173 mov dx,3ceh ;Enable extended registers
1174 mov ax,200fh
1175 out dx,ax
1176 mov ah,ch
1177 mov cl,4
1178 shl ah,cl
1179 or ah,ch
1180 mov al,0dh
1181 out dx,ax
1182 sti
1183 pop cx
1184 pop dx
1185 pop ax
1186 ret
1187 $aheadb endp
1188
1189 $oaktech proc ;Oak Technology Inc OTI-067
1190 push ax
1191 push dx
1192 and al,15
1193 mov ah,al
1194 shl al,1
1195 shl al,1
1196 shl al,1
1197 shl al,1
1198 or ah,al
1199 mov al,11h
1200 mov dx,3deh
1201 out dx,ax
1202 sti
1203 pop dx
1204 pop ax
1205 ret
1206 $oaktech endp
1207
1208 $genoa proc ;GENOA GVGA
1209 push ax
1210 push dx
1211 mov ah,al
1212 shl al,1
1213 shl al,1
1214 shl al,1
1215 or ah,al
1216 mov al,6
1217 or ah,40h
1218 mov dx,3c4h
1219 out dx,ax
1220 sti
1221 pop dx
1222 pop ax
1223 ret
1224 $genoa endp
1225
1226 $ncr proc ;NCR 77C22E
1227 push ax
1228 push dx
1229 shl al,1 ;change 64k bank number into 16k bank number
1230 shl al,1
1231 mov ah,al
1232 mov al,18h
1233 mov dx,3c4h
1234 out dx,ax
1235 mov ax,19h
1236 out dx,ax
1237 sti
1238 pop dx
1239 pop ax
1240 ret
1241 $ncr endp
1242
1243 $compaq proc ;Compaq
1244 push ax
1245 push dx
1246 mov dx,3ceh
1247 mov ax,50fh ;unlock extended registers
1248 out dx,ax
1249 mov ah,byte ptr OSEG[curbk]
1250 shl ah,1 ;change 64k bank number into 4k bank number
1251 shl ah,1
1252 shl ah,1
1253 shl ah,1
1254 mov al,45h
1255 out dx,ax
1256 sti
1257 pop dx
1258 pop ax
1259 ret
1260 $compaq endp
1261
1262 ;
1263 ; Read/Write 64K pages
1264 ;
1265 $vesa1 proc ; VESA bank switching
1266 push ax
1267 push bx
1268 push dx
1269 mul vesa_granularity ; Adjust for the granularity factor
1270 mov dx,ax ; Select window position
1271 mov bx,0 ; select window (bank) sub-command
1272 call dword ptr vesa_bankswitch ; do it!
1273 pop dx
1274 pop bx
1275 pop ax
1276 sti
1277 ret
1278 $vesa1 endp
1279 ;
1280 ; Read-only/Write-only 64K pages
1281 ;
1282 $vesa2 proc ; VESA bank switching
1283 push ax
1284 push bx
1285 push dx
1286 mul vesa_granularity ; Adjust for the granularity factor
1287 mov dx,ax ; Select window position
1288 push dx
1289 mov bx,0 ; select window (bank) sub-command
1290 call dword ptr vesa_bankswitch ; do it!
1291 pop dx
1292 inc bx
1293 call dword ptr vesa_bankswitch
1294 pop dx
1295 pop bx
1296 pop ax
1297 sti
1298 ret
1299 $vesa2 endp
1300 ;
1301 ; Read/Write 32K pages
1302 ;
1303 $vesa3 proc ; VESA bank switching
1304 push ax
1305 push bx
1306 push dx
1307 mul vesa_granularity ; Adjust for the granularity factor
1308 mov dx,ax ; Select window position
1309 push dx
1310 mov bx,vesa_low_window ; select window (bank) sub-command
1311 call dword ptr vesa_bankswitch ; do it!
1312 pop dx
1313 add dx,vesa_gran_offset ; 2nd window is at 32K offset from 1st
1314 mov bx,vesa_high_window
1315 call dword ptr vesa_bankswitch
1316 pop dx
1317 pop bx
1318 pop ax
1319 sti
1320 ret
1321 $vesa3 endp
1322
1323 $vesa_nullbank proc ; null routine for vesa_bankswitch when unknown
1324 ret
1325 $vesa_nullbank endp
1326
1327 $nobank proc
1328 sti
1329 ret
1330 $nobank endp
1331
1332 bkadr macro flag,func,entries ; Bert
1333 mov video_entries, offset entries ; Bert
1334 mov [flag],1
1335 mov [bankadr],offset func
1336 if @CodeSize
1337 mov [bankseg],seg func
1338 endif
1339 endm
1340
1341 nojmp macro
1342 local lbl
1343 jmp lbl
1344 lbl:
1345 endm
1346
1347 whichvga proc near
1348 push bp ; save it around all the int 10s
1349
1350 cmp svga_type,0 ; was a SuperVGA adapter forced?
1351 jne type1_forced ; yup - wade through the options
1352 jmp not_forced ; nope - skip this section
1353 type1_forced:
1354 cmp svga_type,1
1355 jne type2_forced
1356 bkadr aheada,$aheada,ahead_entries
1357 type2_forced:
1358 cmp svga_type,2
1359 jne type3_forced
1360 bkadr ativga,$ativga,ati_entries
1361 type3_forced:
1362 cmp svga_type,3
1363 jne type4_forced
1364 bkadr chipstech,$chipstech,chips_entries
1365 type4_forced:
1366 cmp svga_type,4
1367 jne type5_forced
1368 bkadr everex,$everex,everex_entries
1369 type5_forced:
1370 cmp svga_type,5
1371 jne type6_forced
1372 bkadr genoa,$genoa,genoa_entries
1373 type6_forced:
1374 cmp svga_type,6
1375 jne type7_forced
1376 bkadr ncr,$ncr,ncr_entries
1377 type7_forced:
1378 cmp svga_type,7
1379 jne type8_forced
1380 bkadr oaktech,$oaktech,oaktech_entries
1381 type8_forced:
1382 cmp svga_type,8
1383 jne type9_forced
1384 bkadr paradise,$paradise,paradise_entries
1385 type9_forced:
1386 cmp svga_type,9
1387 jne type10_forced
1388 bkadr trident,$trident,trident_entries
1389 type10_forced:
1390 cmp svga_type,10
1391 jne type11_forced
1392 bkadr tseng,$tseng,tseng_entries
1393 type11_forced:
1394 cmp svga_type,11
1395 jne type12_forced
1396 bkadr tseng4,$tseng4,tseng4_entries
1397 type12_forced:
1398 cmp svga_type,12
1399 jne type13_forced
1400 bkadr video7,$video7,video7_entries
1401 type13_forced:
1402 cmp svga_type,13
1403 jne type14_forced
1404 bkadr aheadb,$aheadb,ahead_entries
1405 type14_forced:
1406 jmp fini
1407 not_forced:
1408
1409 cmp vesa_detect,0 ; is VESA-detection disabled?
1410 je notvesa ; yup - skip this
1411 mov ax,4f00h ; check for VESA adapter
1412 push ds ; set ES == DS
1413 pop es ; ...
1414 mov di, offset dacbox ; answer goes here (a safe place)
1415 int 10h ; do it.
1416 cmp ax,004fh ; successful response?
1417 jne notvesa ; nope. Not a VESA adapter
1418
1419 cmp byte ptr 0[di],'V' ; string == 'VESA'?
1420 jne notvesa ; nope. Not a VESA adapter
1421 cmp byte ptr 1[di],'E' ; string == 'VESA'?
1422 jne notvesa ; nope. Not a VESA adapter
1423 cmp byte ptr 2[di],'S' ; string == 'VESA'?
1424 jne notvesa ; nope. Not a VESA adapter
1425 cmp byte ptr 3[di],'A' ; string == 'VESA'?
1426 jne notvesa ; nope. Not a VESA adapter
1427 mov ax,word ptr 18[di]
1428 mov video_vram,ax ; store video memory size
1429 bkadr vesa,$vesa_nullbank, vesa_entries
1430 jmp fini
1431 notvesa:
1432
1433 call xga_detect ; XGA Adapter?
1434 cmp ax,0
1435 je notxga ; nope
1436 bkadr xga,xga_newbank, xga_entries
1437 jmp fini
1438 notxga:
1439
1440 mov si,1
1441 mov ax,0c000h
1442 mov es,ax
1443 cmp word ptr es:[40h],'13'
1444 jnz noati
1445 bkadr ativga,$ativga,ati_entries ; Bert
1446 mov dx,es:[10h] ; Get value of ATI extended register
1447 mov bl,es:[43h] ; Get value of ATI chip version
1448 cmp bl,'3'
1449 jae v6up ; Use different method to determine
1450 mov al,0bbh ; memory size of chip version is 3 or higher
1451 cli
1452 out dx,al
1453 inc dx
1454 in al,dx ; Get ramsize byte for chip versions 1 & 2
1455 sti
1456 test al,20h
1457 jz no512
1458 mov [vga512],1
1459 jmp short no512
1460
1461 v6up: mov al,0b0h ; Method used for newer ATI chip versions
1462 cli
1463 out dx,al
1464 inc dx
1465 in al,dx ; Get ramsize byte for versions 3-5
1466 sti
1467 test al,10h ; Check if ramsize byte indicates 256K or 512K bytes
1468 jz v7up
1469 mov [vga512],1
1470 v7up: cmp bl,'4' ; Check for ramsize for ATI chip versions 4 & 5
1471 jb no512
1472 test al,8 ; Check if version 5 ATI chip has 1024K
1473 jz no512
1474 mov [vga1024],1
1475 no512: jmp fini
1476
1477 noati: mov ax,7000h ;Test for Everex
1478 xor bx,bx
1479 cld
1480 int 10h
1481 cmp al,70h
1482 jnz noev
1483 bkadr everex,$everex, everex_entries ; Bert
1484 and ch,11000000b
1485 jz temp_2
1486 mov [vga512],1
1487 temp_2: and dx,0fff0h
1488 cmp dx,6780h
1489 jz yeste
1490 cmp dx,2360h
1491 jnz note
1492 yeste: bkadr trident,$trident, everex_entries ; Bert
1493 mov everex,0
1494 note: jmp fini
1495
1496 noev:
1497 mov ax,0bf03h ;Test for Compaq
1498 xor bx,bx
1499 mov cx,bx
1500 int 10h
1501 cmp ax,0bf03h
1502 jnz nocp
1503 test cl,40h ;is 640x480x256 available? ;(??)
1504 jz nocp
1505 bkadr compaq,$compaq,compaq_entries ; Bert
1506 mov [vga512],1
1507 jmp fini
1508
1509 nocp: mov dx,3c4h ;Test for NCR 77C22E
1510 mov ax,0ff05h
1511 call $isport2
1512 jnz noncr
1513 mov ax,5 ;Disable extended registers
1514 out dx,ax
1515 mov ax,0ff10h ;Try to write to extended register 10
1516 call $isport2 ;If it writes then not NCR
1517 jz noncr
1518 mov ax,105h ;Enable extended registers
1519 out dx,ax
1520 mov ax,0ff10h
1521 call $isport2
1522 jnz noncr ;If it does NOT write then not NCR
1523 bkadr ncr,$ncr,ncr_entries ; Bert
1524 mov [vga512],1
1525 jmp fini
1526
1527 noncr: mov dx,3c4h ;Test for Trident
1528 mov al,0bh
1529 out dx,al
1530 inc dl
1531 in al,dx
1532 and al,0fh
1533 cmp al,06h
1534 ja notri
1535 cmp al,2
1536 jb notri
1537 bkadr trident,$trident, trident_entries ; Bert
1538 cmp al,3
1539 jb no89
1540 mov [t8900],1
1541 mov dx,3d4h ; (was 3d5h in version 17.2)
1542 mov al,1fh
1543 out dx,al
1544 inc dx
1545 in al,dx
1546 and al,3
1547 cmp al,1
1548 jb notmem
1549 mov [vga512],1
1550 je notmem
1551 mov [vga1024],1
1552 notmem: jmp fini
1553
1554 no89: mov [vga512],1
1555 jmp fini
1556
1557 notri: mov ax,6f00h ;Test for Video 7
1558 xor bx,bx
1559 cld
1560 int 10h
1561 cmp bx,'V7'
1562 jnz nov7
1563 bkadr video7,$video7, video7_entries ; Bert
1564 mov ax,6f07h
1565 cld
1566 int 10h
1567 and ah,7fh
1568 cmp ah,1
1569 jbe temp_3
1570 mov [vga512],1
1571 temp_3: cmp ah,3
1572 jbe temp_4
1573 mov [vga1024],1
1574 temp_4: jmp fini
1575
1576 nov7: mov dx,3d4h ;Test for GENOA GVGA
1577 mov al,2eh ;check for Herchi Register top 6 bits
1578 out dx,al
1579 inc dx
1580 in al,dx
1581 dec dx
1582 test al,11111100b ;top 6 bits should be zero
1583 jnz nogn
1584 mov ax,032eh ;check for Herchi Register
1585 call $isport2
1586 jnz nogn
1587 mov dx,3c4h
1588 mov al,7
1589 out dx,al
1590 inc dx
1591 in al,dx
1592 dec dx
1593 test al,10001000b
1594 jnz nogn
1595 mov al,10h
1596 out dx,al
1597 inc dx
1598 in al,dx
1599 dec dx
1600 and al,00110000b
1601 cmp al,00100000b
1602 jnz nogn
1603 mov dx,3ceh
1604 mov ax,0ff0bh
1605 call $isport2
1606 jnz nogn
1607 mov dx,3c4h ;check for memory segment register
1608 mov ax,3f06h
1609 call $isport2
1610 jnz nogn
1611 mov dx,3ceh
1612 mov ax,0ff0ah
1613 call $isport2
1614 jnz nogn
1615 bkadr genoa,$genoa, genoa_entries ; Bert
1616 mov [vga512],1
1617 jmp fini
1618
1619 nogn: call $cirrus ;Test for Cirrus
1620 cmp [cirrus],0
1621 je noci
1622 jmp fini
1623
1624 noci: mov dx,3ceh ;Test for Paradise
1625 mov al,9 ;check Bank switch register
1626 out dx,al
1627 inc dx
1628 in al,dx
1629 dec dx
1630 or al,al
1631 jnz nopd
1632
1633 mov ax,50fh ;turn off write protect on VGA registers
1634 out dx,ax
1635 mov dx,offset $pdrsub
1636 mov cx,1
1637 call $chkbk
1638 jc nopd ;if bank 0 and 1 same not paradise
1639 bkadr paradise,$paradise, paradise_entries ; Bert
1640 mov dx,3ceh
1641 mov al,0bh ;512k detect from Bob Berry
1642 out dx,al
1643 inc dx
1644 in al,dx
1645 test al,80h ;if top bit set then 512k
1646 jz nop512
1647 test al,40h
1648 jz nop1024
1649 mov [vga1024],1
1650 jmp fini
1651 nop1024:
1652 mov [vga512],1
1653 nop512: jmp fini
1654
1655 nopd: mov ax,5f00h ;Test for Chips & Tech
1656 xor bx,bx
1657 cld
1658 int 10h
1659 cmp al,5fh
1660 jnz noct
1661 bkadr chipstech,$chipstech, chips_entries ; Bert
1662 cmp bh,1
1663 jb temp_5
1664 mov [vga512],1
1665 temp_5:
1666 jmp fini
1667
1668 noct: mov ch,0
1669 mov dx,3dah ;Test for Tseng 4000 & 3000
1670 in al,dx ;bit 8 is opposite of bit 4
1671 mov ah,al ;(vertical retrace bit)
1672 shr ah,1
1673 shr ah,1
1674 shr ah,1
1675 shr ah,1
1676 xor al,ah
1677 test al,00001000b
1678 ; jz nots
1679 jnz @F
1680 jmp nots
1681 @@:
1682 mov dx,3d4h ;check for Tseng 4000 series
1683 mov ax,0f33h
1684 call $isport2
1685 jnz not4
1686 mov ax,0ff33h ;top 4 bits should not be there
1687 call $isport2
1688 ; jz nots
1689 jnz @F
1690 jmp nots
1691 @@:
1692 mov ch,1
1693
1694 not4: mov dx,3bfh ;Enable access to extended registers
1695 mov al,3
1696 out dx,al
1697 mov dx,3d8h
1698 mov al,0a0h
1699 out dx,al
1700 cmp ch,0
1701 jnz yes4
1702
1703 mov dx,3d4h ;Test for Tseng 3000 or 4000
1704 mov ax,1f25h ;is the Overflow High register there?
1705 call $isport2
1706 jnz nots
1707 mov al,03fh ;bottom six bits only
1708 jmp short yes3
1709 yes4: mov al,0ffh
1710 yes3: mov dx,3cdh ;test bank switch register
1711 call $isport1
1712 jnz nots
1713 bkadr tseng,$tseng, tseng_entries ; Bert
1714 cmp ch,0
1715 jnz t4mem
1716 ; mov [vga512],1
1717 call $t3memchk
1718 jmp fini
1719
1720 t4mem: mov dx,3d4h ;Tseng 4000 memory detect 1meg
1721 mov al,37h
1722 out dx,al
1723 inc dx
1724 in al,dx
1725 test al,1000b ;if using 64kx4 RAMs then no more than 256k
1726 jz nomem
1727 and al,3
1728 cmp al,1 ;if 8 bit wide bus then only two 256kx4 RAMs
1729 jbe nomem
1730 mov [vga512],1
1731 cmp al,2 ;if 16 bit wide bus then four 256kx4 RAMs
1732 je nomem
1733 mov [vga1024],1 ;full meg with eight 256kx4 RAMs
1734 nomem: bkadr tseng4,$tseng4, tseng4_entries ; Bert
1735 jmp fini
1736
1737 nots:
1738 mov dx,3ceh ;Test for Above A or B chipsets
1739 mov ax,0ff0fh ;register should not be fully available
1740 call $isport2
1741 jz noab
1742 mov ax,200fh
1743 out dx,ax
1744 inc dx
1745 nojmp
1746 in al,dx
1747 cmp al,21h
1748 jz verb
1749 cmp al,20h
1750 jnz noab
1751 bkadr aheada,$aheada, ahead_entries ; Bert
1752 mov [vga512],1
1753 jmp short fini
1754
1755 verb: bkadr aheadb,$aheadb, ahead_entries ; Bert
1756 mov [vga512],1
1757 jmp short fini
1758
1759 noab: mov dx,3deh ;Test for Oak Technology
1760 mov ax,0ff11h ;look for bank switch register
1761 call $isport2
1762 jnz nooak
1763 bkadr oaktech,$oaktech, oaktech_entries ; Bert
1764 mov al,0dh
1765 out dx,al
1766 inc dx
1767 nojmp
1768 in al,dx
1769 test al,11000000b
1770 jz no4ram
1771 mov [vga512],1
1772 test al,01000000b
1773 jz no4ram
1774 mov [vga1024],1
1775 no4ram: jmp short fini
1776
1777 nooak: mov si,0
1778
1779 fini: mov ax,si
1780 pop bp
1781 ret
1782 whichvga endp
1783
1784
1785 ;Segment to access video buffer (based on GR[6])
1786 buftbl dw 0A000h,0A000h,0B000h,0B800h
1787
1788 $t3memchk proc near ;[Charles Marslett -- ET3000 memory ck]
1789 mov dx,3dah
1790 in al,dx ;Reset the attribute flop (read 0x3DA)
1791 mov dx,03c0h
1792 mov al,36h
1793 out dx,al
1794 inc dx
1795 in al,dx ;Save contents of ATTR[0x16]
1796 push ax
1797 or al,10h
1798 dec dx
1799 out dx,al
1800 mov dx,3ceh ;Find the RAM buffer...
1801 mov al,6
1802 out dx,al
1803 inc dx
1804 in al,dx
1805 and ax,000Ch
1806 shr ax,1
1807
1808 mov bx,ax
1809 push es
1810 mov es,cs:buftbl[bx]
1811 mov ax,09C65h
1812 mov bx,1
1813 mov es:[bx],ax
1814 mov es:[bx+2],ax
1815 inc bx
1816 mov ax,es:[bx]
1817 pop es
1818 cmp ax,0659Ch
1819 jne et3k_256
1820 mov [vga512],1
1821 et3k_256:
1822 mov dx,3c0h
1823 mov al,36h
1824 out dx,al
1825 pop ax
1826 out dx,al ;Restore ATTR[16h]
1827 ret
1828 $t3memchk endp
1829
1830
1831 $cirrus proc near
1832 mov dx,3d4h ; assume 3dx addressing
1833 mov al,0ch ; screen a start address hi
1834 out dx,al ; select index
1835 inc dx ; point to data
1836 mov ah,al ; save index in ah
1837 in al,dx ; get screen a start address hi
1838 xchg ah,al ; swap index and data
1839 push ax ; save old value
1840 push dx ; save crtc address
1841 xor al,al ; clear crc
1842 out dx,al ; and out to the crtc
1843
1844 mov al,1fh ; Eagle ID register
1845 dec dx ; back to index
1846 out dx,al ; select index
1847 inc dx ; point to data
1848 in al,dx ; read the id register
1849 mov bh,al ; and save it in bh
1850
1851 mov cl,4 ; nibble swap rotate count
1852 mov dx,3c4h ; sequencer/extensions
1853 mov bl,6 ; extensions enable register
1854
1855 ror bh,cl ; compute extensions disable value
1856 mov ax,bx ; extensions disable
1857 out dx,ax ; disable extensions
1858 inc dx ; point to data
1859 in al,dx ; read enable flag
1860 or al,al ; disabled ?
1861 jnz exit ; nope, not an cirrus
1862
1863 ror bh,cl ; compute extensions enable value
1864 dec dx ; point to index
1865 mov ax,bx ; extensions enable
1866 out dx,ax ; enable extensions
1867 inc dx ; point to data
1868 in al,dx ; read enable flag
1869 cmp al,1 ; enabled ?
1870 jne exit ; nope, not an cirrus
1871 mov [cirrus],1
1872 mov video_entries, offset no_entries ; Bert
1873 mov [bankadr],offset $nobank
1874 if @CodeSize
1875 mov [bankseg],seg $nobank
1876 endif
1877 exit: pop dx ; restore crtc address
1878 dec dx ; point to index
1879 pop ax ; recover crc index and data
1880 out dx,ax ; restore crc value
1881 ret
1882 $cirrus endp
1883
1884 $chkbk proc near ;paradise bank switch check
1885 mov di,0b800h
1886 mov es,di
1887 xor di,di
1888 mov bx,1234h
1889 call $gochk
1890 jnz nopd
1891 mov bx,4321h
1892 call $gochk
1893 jnz nopd
1894 clc
1895 ret
1896 nopd: stc
1897 ret
1898 $chkbk endp
1899
1900 $gochk proc near
1901 push si
1902 mov si,bx
1903
1904 mov al,cl
1905 call dx
1906 xchg bl,es:[di]
1907 mov al,ch
1908 call dx
1909 xchg bh,es:[di]
1910
1911 xchg si,bx
1912
1913 mov al,cl
1914 call dx
1915 xor bl,es:[di]
1916 mov al,ch
1917 call dx
1918 xor bh,es:[di]
1919
1920 xchg si,bx
1921
1922 mov al,ch
1923 call dx
1924 mov es:[di],bh
1925 mov al,cl
1926 call dx
1927 mov es:[di],bl
1928
1929 mov al,0
1930 call dx
1931 or si,si
1932 pop si
1933 ret
1934 $gochk endp
1935
1936
1937 $pdrsub proc near ;Paradise
1938 push dx
1939 mov ah,al
1940 mov dx,3ceh
1941 mov al,9
1942 out dx,ax
1943 pop dx
1944 ret
1945 $pdrsub endp
1946
1947 $isport2 proc near
1948 push bx
1949 mov bx,ax
1950 out dx,al
1951 mov ah,al
1952 inc dx
1953 in al,dx
1954 dec dx
1955 xchg al,ah
1956 push ax
1957 mov ax,bx
1958 out dx,ax
1959 out dx,al
1960 mov ah,al
1961 inc dx
1962 in al,dx
1963 dec dx
1964 and al,bh
1965 cmp al,bh
1966 jnz noport
1967 mov al,ah
1968 mov ah,0
1969 out dx,ax
1970 out dx,al
1971 mov ah,al
1972 inc dx
1973 in al,dx
1974 dec dx
1975 and al,bh
1976 cmp al,0
1977 noport: pop ax
1978 out dx,ax
1979 pop bx
1980 ret
1981 $isport2 endp
1982
1983 $isport1 proc near
1984 mov ah,al
1985 in al,dx
1986 push ax
1987 mov al,ah
1988 out dx,al
1989 in al,dx
1990 and al,ah
1991 cmp al,ah
1992 jnz noport
1993 mov al,0
1994 out dx,al
1995 in al,dx
1996 and al,ah
1997 cmp al,0
1998 noport: pop ax
1999 out dx,al
2000 ret
2001 $isport1 endp
2002
2003 videowrite proc near ; your-own-video write routine
2004 mov ah,0 ; clear the high-order color byte
2005 push ax ; colors parameter
2006 push dx ; 'y' parameter
2007 push cx ; 'x' parameter
2008 call far ptr writevideo ; let the external routine do it
2009 add sp,6 ; pop the parameters
2010 ret ; we done.
2011 videowrite endp
2012
2013 videoread proc near ; your-own-video read routine
2014 push dx ; 'y' parameter
2015 push cx ; 'x' parameter
2016 call far ptr readvideo ; let the external routine do it
2017 add sp,4 ; pop the parameters
2018 ret ; we done.
2019 videoread endp
2020
2021 diskwrite proc near ; disk-video write routine
2022 push ax ; colors parameter
2023 push dx ; 'y' parameter
2024 push cx ; 'x' parameter
2025 call far ptr writedisk ; let the external routine do it
2026 add sp,6 ; pop the parameters
2027 ret ; we done.
2028 diskwrite endp
2029
2030 diskread proc near ; disk-video read routine
2031 push dx ; 'y' parameter
2032 push cx ; 'x' parameter
2033 call far ptr readdisk ; let the external routine do it
2034 add sp,4 ; pop the parameters
2035 ret ; we done.
2036 diskread endp
2037
2038
2039 ; ***********************************************************************
2040 ;
2041 ; TARGA MODIFIED 1 JUNE 89 - j mclain
2042 ;
2043 tgawrite proc near
2044 push ax ; colors parameter
2045 push dx ; 'y' parameter
2046 push cx ; 'x' parameter
2047 call far ptr WriteTGA ; writeTGA( x, y, color )
2048 add sp,6 ; pop the parameters
2049 ret
2050 tgawrite endp
2051
2052 tgaread proc near
2053 push dx ; 'y' parameter
2054 push cx ; 'x' parameter
2055 call far ptr ReadTGA ; readTGA( x, y )
2056 add sp,4 ; pop the parameters
2057 ret
2058 tgaread endp
2059
2060
2061 ; TARGA+ Code 2-11-91, Mark Peterson
2062
2063 TPlusWrite PROC NEAR
2064 push ax
2065 push dx
2066 push cx
2067 call FAR PTR WriteTPlusBankedPixel
2068 add sp, 6
2069 ret
2070 TPlusWrite ENDP
2071
2072 TPlusRead PROC NEAR
2073 push dx
2074 push cx
2075 call FAR PTR ReadTPlusBankedPixel
2076 add sp, 4
2077 ret
2078 TPlusRead ENDP
2079
2080 ; 8514/a afi routines JCO, not needed, 4/11/92
2081 ;f85start proc near
2082 ; call far ptr open8514
2083 ; ret
2084 ;f85start endp
2085
2086 ;f85end proc near
2087 ; call far ptr close8514
2088 ; ret
2089 ;f85end endp
2090
2091 ; hardware
2092 f85hwwrite proc near
2093 call far ptr fr85hwwdot
2094 ret
2095 f85hwwrite endp
2096
2097 f85hwread proc near
2098 call far ptr fr85hwrdot
2099 ret
2100 f85hwread endp
2101
2102 f85hwline proc near
2103 call far ptr fr85hwwbox ;put out the box
2104 ret
2105 f85hwline endp
2106
2107 f85hwreadline proc near
2108 call far ptr fr85hwrbox ;read the box
2109 ret
2110 f85hwreadline endp
2111
2112 ; afi
2113 f85write proc near
2114 call far ptr fr85wdot
2115 ret
2116 f85write endp
2117
2118 f85read proc near
2119 call far ptr fr85rdot
2120 ret
2121 f85read endp
2122
2123 f85line proc near
2124 call far ptr fr85wbox ;put out the box
2125 ret
2126 f85line endp
2127
2128 f85readline proc near
2129 call far ptr fr85rbox ;read the box
2130 ret
2131 f85readline endp
2132
2133 hgcwrite proc near
2134 mov ah,0 ; clear the high-order color byte
2135 push ax ; colors parameter
2136 push dx ; 'y' parameter
2137 push cx ; 'x' parameter
2138 call far ptr writehgc ; let the Herc. Write dot routine do it
2139 add sp,6 ; pop the parameters
2140 ret
2141 hgcwrite endp
2142
2143 hgcread proc near
2144 push dx ; 'y' parameter
2145 push cx ; 'x' parameter
2146 call far ptr readhgc ; call the Hercules Read dot routine
2147 add sp,4 ; pop the parameters
2148 ret
2149 hgcread endp
2150
2151 hgcstart proc near ; hercules start routine
2152 call far ptr inithgc ; let the external routine do it
2153 ret ; we done.
2154 hgcstart endp
2155
2156 hgcend proc near ; hercules end routine
2157 call far ptr termhgc ; let the external routine do it
2158 ret ; we done.
2159 hgcend endp
2160
2161 ; **************** video adapter initialization *******************
2162 ;
2163 ; adapter_init:
2164 ; called from general.asm once per run
2165
2166 adapter_init proc far ; initialize the video adapter (to VGA)
2167 mov ax,[bankadr] ; Initialize the bank-switching
2168 mov video_bankadr,ax ; logic to the do-nothing routine
2169 mov ax,[bankseg] ; ...
2170 mov video_bankseg,ax ; ...
2171 mov bx,0 ; clear out all of the 256-mode flags
2172 mov tseng,bx ; ...
2173 mov trident,bx ; ...
2174 mov video7,bx ; ...
2175 mov paradise,bx ; ...
2176 mov chipstech,bx ; ...
2177 mov ativga,bx ; ...
2178 mov everex,bx ; ...
2179 mov cirrus,bx ; ...
2180 mov aheada,bx ; ...
2181 mov aheadb,bx ; ...
2182 mov tseng4,bx ; ...
2183 mov oaktech,bx ; ...
2184 mov [bankadr],offset $nobank
2185 mov [bankseg],seg $nobank
2186 mov video_entries, offset no_entries ; ...
2187 ret
2188 adapter_init endp
2189
2190 ; adapter_detect:
2191 ; This routine performs a few quick checks on the type of
2192 ; video adapter installed.
2193 ; It sets variables video_type and textsafe,
2194 ; and fills in a few bank-switching routines.
2195
2196 adapter_detect proc uses di si es
2197 push bp ; some bios's don't save during int 10h
2198 cmp done_detect,0 ; been called already?
2199 je adapter_detect2 ; nope
2200 jmp adapter_ret ; yup, do nothing
2201 adapter_detect2:
2202 inc done_detect ; don't get called again
cmp video_type,0 ; video_type preset by command line arg?
jne go_adapter_set ; yup, use what we're told
2203
2204 cmp TPlusFlag, 0
2205 je NotTPlus
2206 call far ptr CheckForTPlus
2207 or ax, ax
2208 jz NotTPlus
2209 mov TPlusInstalled, 1 ; flag it and check for primary adapter
2210
2211 NotTPlus:
2212 mov ax,1a00h ; start by trying int 10 func 1A
2213 int 10h ; ...
2214 cmp al,1ah ; was AL modified?
2215 je adapter_detect_4 ; yup. go decode what we got
2216 mov ax,1200h ; try this vga-only function
2217 mov bl,34h ; enable cursor emulation
2218 int 10h ; ...
2219 cmp al,12h ; did it work?
2220 je adapter_detect_vga ; yup, vga
2221 mov ah,12h ; look for an EGA
2222 mov bl,10h ; by using an EGA-specific call
2223 int 10h ; ...
2224 cmp bl,10h ; was BL modified?
2225 je adapter_detect_notega ; nope, < EGA
2226 mov video_type,3 ; set the video type: EGA
2227 cmp bh,1 ; monochrome monitor?
2228 jne go_adapter_set ; nope
2229 mov mode7text,1 ; yup, use mode 7 for text
2230 jmp short go_adapter_set ; We done.
2231 adapter_detect_4:
2232 cmp bl,1 ; =1?
2233 jne adapter_detect_4a ; nope
2234 jmp adapter_detect_hgc ; MDA, assume HGC (nothing else works)
2235 adapter_detect_4a:
2236 mov video_type,2 ; set the video type: CGA
2237 cmp bl,3 ; <=2?
2238 jb go_adapter_set ; exit with type CGA
2239 mov video_type,3 ; set the video type: EGA
2240 cmp bl,5 ; =5?
2241 jne adapter_detect_5 ; nope
2242 mov mode7text,1 ; yup, monochrome monitor, mode 7 text
2243 go_adapter_set:
2244 jmp adapter_set
2245 adapter_detect_5:
2246 cmp bl,6 ; <=5?
2247 jb go_adapter_set ; exit with type EGA
2248 cmp bl,10 ; <=9?
2249 jb adapter_detect_vga ; vga, go check which kind
2250 mov video_type,4 ; set the video type: MCGA
2251 cmp bl,13 ; <=12?
2252 jb go_adapter_set ; exit with type MCGA
2253 adapter_detect_vga:
2254 mov video_type,5 ; set the video type: VGA
2255 call whichvga ; autodetect which VGA is there
2256 mov ax,[bankadr] ; save the results
2257 mov video_bankadr,ax ; ...
2258 mov ax,[bankseg] ; ...
2259 mov video_bankseg,ax ; ...
2260 jmp adapter_set
2261 adapter_detect_notega:
2262 mov video_type,2 ; set the video type: CGA
2263 ; HGC detect code from book by Richard Wilton follows
2264 mov dx,3B4h ; check for MDA, use MDA CRTC address
2265 mov al,0Fh ; select 6845 reg 0Fh (Cursor Low)
2266 out dx,al
2267 inc dx
2268 in al,dx ; AL := current Cursor Low value
2269 mov ah,al ; preserve in AH
2270 mov al,66h ; AL := arbitrary value
2271 out dx,al ; try to write to 6845
2272 mov cx,200h
2273 mdalp: loop mdalp ; wait for 6845 to respond
2274 in al,dx ; read cursor low again
2275 xchg ah,al
2276 out dx,al ; restore original value
2277 cmp ah,66h ; test whether 6845 responded
2278 jne adapter_set ; nope, exit with type CGA
2279 mov dl,0BAh ; DX := 3BAh (status port)
2280 in al,dx
2281 and al,80h
2282 mov ah,al ; AH := bit 7 (vertical sync on HGC)
2283 mov cx,8000h ; do this 32768 times
2284 mdalp2: in al,dx
2285 and al,80h ; isolate bit 7
2286 cmp ah,al
2287 loope mdalp2 ; wait for bit 7 to change
2288 je adapter_set ; didn't change, exit with type CGA
;; in al,dx
;; and al,01100000b ; mask off bits 5 and 6
;; Next line probably backwards but doesn't matter, the test in this area
2289 ;; distinguishes HGC/HGC+/InColor, which we don't care about anyway.
;; jnz adapter_set ; not hgc/hgc+, exit with type CGA
adapter_detect_hgc:
mov video_type,1 ; HGC
mov mode7text,1 ; use mode 7 for text
adapter_set:
; ensure a nice safe standard state
mov ax,3 ; set 80x25x16 text mode, clear screen
cmp mode7text,0 ; use mode 7 for text?
je adapter_set2 ; nope
mov ax,7 ; set mono text mode, clear screen
adapter_set2:
int 10h ; set text mode
mov ax,0500h ; select display page zero
int 10h ; ...
; now the color text stuff
cmp textsafe,2 ; command line textsafe=no?
je adapter_go_ret ; yup, believe the user
cmp video_type,3 ; >= ega?
jae adapter_setup ; yup
mov textsafe,2 ; textsafe=no
adapter_go_ret: ; a label for some short jumps
jmp adapter_ret ; to the exit
adapter_setup:
; more standard state, ega and up stuff
mov ax,1003h ; top attribute bit means blink
mov bl,01h ; ...
int 10h ; ...
mov ax,1103h ; font block 0, 256 chars (not 512)
mov bl,00h ; ...
int 10h ; ...
mov ax,1202h ; 400 scan lines in text mode (vga)
mov bl,30h ; ...
int 10h ; ...
mov ax,1200h ; cga cursor emulation (vga)
mov bl,34h ; ...
int 10h ; ...
mov ax,1200h ; enable default palette loading
mov bl,31h ; ...
int 10h ; ...
cmp textsafe,0 ; were we told textsafe=yes|bios|save?
jne adapter_ret ; yup
mov textsafe,1 ; set textsafe=yes
adapter_ret:
cld ; some MSC 6.0 libraries assume this!
pop bp
ret
adapter_detect endp
; select_vga_plane:
; Call this routine with cx = plane number.
; It works for vga and for ega. (I hope.)
; It uses no local variables, caller may have ds register modified.
; On return from this routine, the requested vid mem plane is mapped
; to A0000; this means that the sequencer and graphics controller
; states are not very useful for further real work - before any further
; screen painting, better reset video mode.
select_vga_plane proc near ; cl = plane number
; some callers may have ds modified, use no variables in here!
mov dx,SC_INDEX ; sequencer controller
mov ax,0102h ; select plane
shl ah,cl ; bit for desired plane
out dx,ax ; ...
mov ax,0604h ; no chaining
out dx,ax ; ...
mov dx,GC_INDEX ; graphics controller
mov ax,0001h ; use processor data
out dx,ax ; ...
mov al, 04h ; select read plane
mov ah,cl ; desired plane
out dx,ax ; ...
mov ax,0005h ; no even/odd, write mode 0
out dx,ax ; ...
mov ax,0106h ; map to a000, no chain, graphics
out dx,ax ; ...
mov ax,0ff08h ; enable 8 bits per write
out dx,ax ; ...
ret ; all done
select_vga_plane endp
; **************** internal Read/Write-a-line routines *********************
;
; These routines are called by out_line(), put_line() and get_line().
; They assume the following register values:
;
; si = offset of array of colors for a row (write routines)
; di = offset of array of colors for a row (read routines)
;
; ax = stopping column
; bx =
; cx = starting column
; dx = row
;
; Note: so far have converted only normaline, normalineread, mcgaline,
; mcgareadline, super256line, super256readline -- Tim
normaline proc near ; Normal Line
normal_line1:
push ax ; save stop col
mov al,[si] ; retrieve the color
xor ah,ah ; MCP 6-7-91
push cx ; save the counter around the call
push dx ; save column around the call
push si ; save the pointer around the call also
call dotwrite ; write the dot via the approved method
pop si ; restore the pointer
pop dx ; restore the column
pop cx ; restore the counter
inc si ; bump it up
inc cx ; bump it up
pop ax ; retrieve number of dots
cmp cx,ax ; more to go?
jle normal_line1 ; yup. do it.
ret
normaline endp
normalineread proc near ; Normal Line
mov bx,videomem
mov es,bx
normal_lineread1:
push ax ; save stop col
push cx ; save the counter around the call
push dx ; save column around the call
push di ; save the pointer around the call also
call dotread ; read the dot via the approved method
pop di ; restore the pointer
pop dx ; restore the column
pop cx ; restore the counter
mov bx,di ; locate the actual pixel color
mov [bx],al ; retrieve the color
inc di ; bump it up
inc cx ; bump it up
pop ax ; retrieve number of dots
cmp cx,ax ; more to go?
jle normal_lineread1 ; yup. do it.
ret
normalineread endp
mcgaline proc near ; MCGA 320*200, 246 colors
sub ax,cx ; last col - first col
inc ax ; + 1
xchg dh,dl ; bx := 256*y
mov bx,cx ; bx := x
add bx,dx ; bx := 256*y + x
shr dx,1
shr dx,1 ; dx := 64*y
add bx,dx ; bx := 320*y + x
mov di,bx ; di = offset of row in video memory
mov cx,ax ; move this many bytes
rep movsb ; zap line into memory
ret
mcgaline endp
mcgareadline proc near ; MCGA 320*200, 246 colors
sub ax,cx ; last col - first col
inc ax ; + 1
xchg dh,dl ; bx := 256*y
mov bx,cx ; bx := x
add bx,dx ; bx := 256*y + x
shr dx,1
shr dx,1 ; dx := 64*y
add bx,dx ; bx := 320*y + x
mov si,bx ; di = offset of row in video memory
mov cx,ax ; move this many bytes
mov ax,ds ; copy data segment to ...
mov es,ax ; ... es
mov ax,videomem ; copy video segment to ...
mov ds,ax ; ... ds
rep movsb ; zap line into memory
mov ax,es
mov ds,ax ; restore data segement to ds
ret
mcgareadline endp
vgaline proc near ; Bank Switch EGA/VGA line write
push cx ; save a few registers
push ax ; ...
push dx ; ...
mov bx,dx ; save the rowcount
mov ax,vxdots ; compute # of dots / pass
shr ax,1 ; (given 8 passes)
shr ax,1 ; ...
shr ax,1 ; ...
mov di,ax
neg di ; temp: to see if line will overflow
mul bx ; now calc first video addr
cmp dx,curbk ; see if bank changed
jne bank_is_changing ; if bank change call normaline
cmp ax,di
ja bank_is_changing ; if bank WILL change, call normaline
mov di,cx ; compute the starting destination
shr di,1 ; divide by 8
shr di,1 ; ...
shr di,1 ; ...
add di,ax ; add the first pixel offset
mov dx,03ceh ; set up graphics cntrlr addr
mov ax,8008h ; set up for the bit mask
and cx,7 ; adjust for the first pixel offset
ror ah,cl ; ...
pop bx ; flush old DX value
pop bx ; flush old AX value
pop cx ; flush old CX value
sub bx,cx ; convert to a length value
add bx,si ; locate the last source locn
mov cx,ax ; save the bit mask
vgaline1:
out dx,ax ; set the graphics bit mask
push ax ; save registers for a tad
push si ; ...
push di ; ...
vgaline2:
mov ah,ds:[si] ; get the color
mov al,0 ; set set/reset registers
out dx,ax ; do it.
mov ax,0f01h ; enable set/reset registers
out dx,ax ; do it.
or es:[di],al ; update all bit planes
inc di ; set up the next video addr
add si,8 ; and the next source addr
cmp si,bx ; are we beyond the end?
jbe vgaline2 ; loop if more dots this pass
pop di ; restore the saved registers
pop si ; ...
pop ax ; ...
inc si ; offset the source 1 byte
cmp si,bx ; are we beyond the end?
ja vgaline4 ; stop if no more dots this pass
ror ah,1 ; alter bit mask value
cmp ah,80h ; time to update DI:
jne vgaline3 ; nope
inc di ; yup
vgaline3:
cmp ah,ch ; already done all 8 of them?
jne vgaline1 ; nope. do another one.
vgaline4:
;;; call videocleanup ; else cleanup time.
ret ; and we done.
bank_is_changing:
pop dx ; restore the registers
pop ax ; ...
pop cx ; ...
call normaline ; just calling newbank didn't quite
2290 ret ; work. This depends on no bank
2291 vgaline endp ; change mid line (ok for 1024 wide)
2292
2293 vgareadline proc near ; Bank Switch EGA/VGA line read
2294 push cx ; save a few registers
2295 push ax ; ...
2296 push dx ; ...
2297
2298 mov bx,dx ; save the rowcount
2299 mov ax,vxdots ; compute # of dots / pass
2300 shr ax,1 ; (given 8 passes)
2301 shr ax,1 ; ...
2302 shr ax,1 ; ...
2303 mul bx ; now calc first video addr
2304 cmp dx,curbk ; see if bank changed
2305 jne bank_is_changing ; if bank change call normaline
2306
2307 mov si,cx ; compute the starting destination
2308 shr si,1 ; divide by 8
2309 shr si,1 ; ...
2310 shr si,1 ; ...
2311 add si,ax ; add the first pixel offset
2312
2313 and cx,7 ; adjust for the first pixel offset
2314 mov ch,cl ; save the original offset value
2315
2316 pop bx ; flush old DX value
2317 pop bx ; flush old AX value
2318 pop ax ; flush old CX value
2319 sub bx,ax ; convert to a length value
2320 add bx,di ; locate the last dest locn
2321
2322 mov ax,0a000h ; EGA/VGA screen starts here
2323 mov es,ax ; ...
2324
2325 mov dx,03ceh ; set up graphics cntrlr addr
2326
2327 vgaline1:
2328 push bx ; save BX for a tad
2329 mov ch,80h ; bit mask to shift
2330 shr ch,cl ; ...
2331 mov bx,0 ; initialize bits-read value (none)
2332 mov ax,0304h ; set up controller address register
2333 vgareadloop:
2334 out dx,ax ; do it
2335 mov bh,es:[si] ; retrieve the old value
2336 and bh,ch ; mask one bit
2337 neg bh ; set bit 7 correctly
2338 rol bx,1 ; rotate the bit into bl
2339 dec ah ; go for another bit?
2340 jge vgareadloop ; sure, why not.
2341 mov ds:[di],bl ; returned pixel value
2342 pop bx ; restore BX
2343 inc di ; set up the next dest addr
2344 cmp di,bx ; are we beyond the end?
2345 ja vgaline3 ; yup. We done.
2346 inc cl ; alter bit mask value
2347 cmp cl,8 ; time to update SI:
2348 jne vgaline2 ; nope
2349 inc si ; yup
2350 mov cl,0 ; ...
2351 vgaline2:
2352 jmp short vgaline1 ; do another one.
2353
2354 vgaline3:
2355 ;;; call videocleanup ; else cleanup time.
2356 ret ; and we done.
2357
2358 bank_is_changing:
2359 pop dx ; restore the registers
2360 pop ax ; ...
2361 pop cx ; ...
2362 call normalineread ; just calling newbank didn't quite
ret ; work. This depends on no bank
vgareadline endp ; change mid line (ok for 1024 wide)
super256lineaddr proc near ; super VGA 256 colors
mov ax,vxdots ; this many dots / line
mov bx,dx ; rowcount
mul bx ; times this many lines
push ax ; save pixel address for later
cmp dx,curbk ; bank ok?
push dx ; save bank
je bank_is_ok ; jump if bank ok
mov al,dl ; newbank needs bank in al
call far ptr newbank
bank_is_ok:
inc bx ; next row
mov ax,vxdots ; this many dots / line
mul bx ; times this many lines
sub ax,1 ; back up some to the last pixel of the
sbb dx,0 ; previous line
pop bx ; bank at start of row
pop ax ; ax = offset of row in video memory
ret
super256lineaddr endp
super256line proc near ; super VGA 256 colors
push ax ; stop col
push dx ; row
call super256lineaddr ; ax=video,dl=newbank,bl=oldbank
mov di,ax ; video offset
cmp dl,bl ; did bank change?
pop dx ; row
pop ax ; stop col
jne bank_did_chg
add di,cx ; add start col to video address
sub ax,cx ; ax = stop - start
mov cx,ax ; + start column
inc cx ; number of bytes to move
rep movsb ; zap line into memory
jmp short linedone
bank_did_chg:
call normaline ; normaline can handle bank change
linedone:
ret
super256line endp
super256readline proc near ; super VGA 256 colors
push ax ; stop col
push dx ; row
call super256lineaddr ; ax=video,dl=newbank,bl=oldbank
mov si,ax ; video offset
cmp dl,bl ; did bank change?
pop dx ; row
pop ax ; stop col
jne bank_did_chg
add si,cx ; add start col to video address
sub ax,cx ; ax = stop - start
mov cx,ax ; + start column
inc cx ; number of bytes to move
mov ax,ds ; save data segment to es
mov es,ax
mov ax,videomem ; video segment to es
mov ds,ax
rep movsb ; zap line into memory
mov ax,es ; restore data segment to ds
mov ds,ax
jmp short linedone
bank_did_chg:
call normalineread ; normaline can handle bank change
linedone:
ret
super256readline endp
tweak256line proc near ; Normal Line: no assumptions
local plane:byte
mov bx,ax ; bx = stop col
sub bx,cx ; bx = stop-start
inc bx ; bx = how many pixels to write
cmp bx,3 ; less than four points?
jg nottoosmall ; algorithm won't work as written
2363 call normaline ; - give up and call normaline
2364 ret ; we done
2365 nottoosmall: ; at least four points - go for it!
2366 push bx ; save number of pixels
2367 and bx,3 ; pixels modulo 4 = no of extra pts
2368 mov ax,vxdots ; width of video row
2369 ;; shr ax, 1
2370 ;; shr ax, 1 ; now ax = vxdots/4
2371 mul dx ; ax points to start of desired row
2372 push cx ; Save starting column for later
2373 shr cx,1 ; There are 4 pixels at each address
2374 shr cx,1 ; so divide X by 4
2375 add ax,cx ; Point to pixel's address
mov di,ax ; video offset of first point
pop cx ; Retrieve starting column
and cl,3 ; Get the plane number of the pixel
mov ah,1
shl ah,cl ; Set the bit corresponding to the plane
; the pixel is in
mov plane,ah ; Save starting plane for ending test
mov al,MAP_MASK ;
mov dx,SC_INDEX
pop cx ; number of pixels to write
shr cx,1
shr cx,1 ; cx = number of pixels/4
cmp bx,0 ; extra pixels?
je tweak256line1 ; nope - don't add one
2376 inc cx ; yup - add one more pixel
2377 tweak256line1:
2378 OUT DX,AX ; set up VGA registers for plane
2379 push cx ; save registers changed by movsb
2380 push si ; ...
2381 push di ; ...
2382 tweak256line2:
2383 movsb ; move the next pixel
2384 add si,3 ; adjust the source addr (+4, not +1)
2385 loop tweak256line2 ; loop if more dots this pass
2386 pop di ; restore the saved registers
2387 pop si ; ...
2388 pop cx ; ...
2389 dec bx ; one less extra pixel
2390 cmp bx,0 ; out of extra pixels?
2391 jne noextra
2392 dec cx ; yup - next time one fewer to write
2393 noextra:
2394 inc si ; offset the source 1 byte
2395 shl ah,1 ; set up for the next video plane
2396 cmp ah,16 ; at last plane?
2397 jne notlastplane
2398 mov ah,1 ; start over with plane 0
2399 inc di ; bump up video memory
2400 notlastplane:
2401 cmp ah,plane ; back to first plane?
2402 jne tweak256line1 ; nope. perform another loop.
2403 ret
2404 tweak256line endp
2405
2406 tweak256readline proc near ; Normal Line: no assumptions
2407 local plane:byte
2408 mov bx,ax ; bx = stop col
2409 sub bx,cx ; bx = stop-start
2410 inc bx ; bx = how many pixels to write
2411 cmp bx,3 ; less than four points?
2412 jg nottoosmall ; algorithm won't work as written
call normalineread ; - give up and call normalineread
ret ; we done
nottoosmall: ; at least four points - go for it!
push bx ; save number of pixels
and bx,3 ; pixels modulo 4 = no of extra pts
mov ax,vxdots ; width of video row
;; shr ax, 1
;; shr ax, 1 ; now ax = vxdots/4
mul dx ; ax points to start of desired row
push cx ; Save starting column for later
shr cx,1 ; There are 4 pixels at each address
shr cx,1 ; so divide X by 4
add ax,cx ; Point to pixel's address
2413 mov si,ax
2414 pop cx ; Retrieve starting column
2415 and cl,3 ; Get the plane number of the pixel
2416 mov ah,cl
2417 mov plane,ah ; Save starting plane
2418 mov al,READ_MAP
2419 mov dx,GC_INDEX
2420 pop cx ; number of pixels to write
2421 shr cx,1
2422 shr cx,1 ; cx = number of pixels/4
2423 cmp bx,0 ; extra pixels?
2424 je tweak256line1 ; nope - don't add one
inc cx ; yup - add one more pixel
tweak256line1:
out dx,ax
push ax ; save registers
push cx ; ...
push di ; ...
push si ; ...
mov ax,ds ; copy data segment to es
mov es,ax ; ...
mov ax,videomem ; copy video segment to ds
mov ds,ax ; ...
tweak256line2:
movsb ; move the next pixel
add di,3 ; adjust the source addr (+4, not +1)
loop tweak256line2 ; loop if more dots this pass
mov ax,es
mov ds,ax ; restore data segement to ds
pop si ; restore the saved registers
pop di ; ...
pop cx ; ...
pop ax ; ...
dec bx ; one less extra pixel
cmp bx,0 ; out of extra pixels?
jne noextra
dec cx ; yup - next time one fewer to write
noextra:
inc di ; offset the source 1 byte
inc ah ; set up for the next video plane
and ah,3
cmp ah,0 ; at last plane?
jne notlastplane
inc si ; bump up video memory
notlastplane:
cmp ah,plane ; back to first plane?
jne tweak256line1 ; nope. perform another loop.
ret
tweak256readline endp
; ******************** Function videocleanup() **************************
; Called at the end of any assembler video read/writes to make
; the world safe for 'printf()'s.
; Currently, only ega/vga needs cleanup work, but who knows?
;
;;videocleanup proc near
;; mov ax,dotwrite ; check: were we in EGA/VGA mode?
;; cmp ax,offset vgawrite ; ...
;; jne short videocleanupdone ; nope. no adjustments
;; mov dx,03ceh ; graphics controller address
;; mov ax,0ff08h ; restore the default bit mask
;; out dx,ax ; ...
;; mov ax,0003h ; restore the function select
;; out dx,ax ; ...
;; mov ax,0001h ; restore the enable set/reset
;; out dx,ax ; ...
;;videocleanupdone:
;; ret
;;videocleanup endp
; ********************** Function setvideotext() ************************
; Sets video to text mode, using setvideomode to do the work.
setvideotext proc
sub ax,ax
mov dotmode,ax ; make this zero to avoid trouble
push ax
push ax
push ax
mov ax,3
push ax
call far ptr setvideomode ; (3,0,0,0)
add sp,8
ret
setvideotext endp
; **************** Function setvideomode(ax, bx, cx, dx) ****************
; This function sets the (alphanumeric or graphic) video mode
; of the monitor. Called with the proper values of AX thru DX.
; No returned values, as there is no particular standard to
; adhere to in this case.
; (SPECIAL "TWEAKED" VGA VALUES: if AX==BX==CX==0, assume we have a
; genuine VGA or register compatable adapter and program the registers
; directly using the coded value in DX)
setvideomode proc uses di si es,argax:word,argbx:word,argcx:word,argdx:word
mov ax,sxdots ; initially, set the virtual line
mov vxdots,ax ; to be the scan line length
xor ax,ax
mov istruecolor,ax ; assume not truecolor
mov vesa_xres,ax ; reset indicators used for
mov vesa_yres,ax ; virtual screen limits estimation
cmp dotmode,0
je its_text
mov setting_text,0 ; try to set virtual stuff
jmp short its_graphics
its_text:
mov setting_text,1 ; don't set virtual stuff
2425 its_graphics:
2426
2427 cmp dotmode, 29 ; Targa truecolor mode?
2428 jne NotTrueColorMode
2429 jmp TrueColorAuto ; yup.
2430 NotTrueColorMode:
2431 cmp diskflag,1 ; is disk video active?
2432 jne nodiskvideo ; nope.
2433 call far ptr enddisk ; yup, external disk-video end routine
2434 nodiskvideo:
2435 cmp videoflag,1 ; say, was the last video your-own?
2436 jne novideovideo ; nope.
2437 call far ptr endvideo ; yup, external your-own end routine
2438 mov videoflag,0 ; set flag: no your-own-video
2439 jmp short notarga
2440 novideovideo:
2441 cmp tgaflag,1 ; TARGA MODIFIED 2 June 89 j mclain
2442 jne notarga
2443 call far ptr EndTGA ; endTGA( void )
2444 mov tgaflag,0 ; set flag: targa cleaned up
2445 notarga:
2446
2447 cmp xga_isinmode,0 ; XGA in graphics mode?
2448 je noxga ; nope
2449 mov ax,0 ; pull it out of graphics mode
2450 push ax
2451 mov xga_clearvideo,al
2452 call far ptr xga_mode
2453 pop ax
2454 noxga:
2455
2456 cmp f85flag, 1 ; was the last video 8514?
2457 jne no8514 ; nope.
2458 cmp ai_8514, 0 ;check afi flag, JCO 4/11/92
2459 jne f85endafi
2460 call far ptr close8514hw ;use registers, JCO 4/11/92
2461 jmp f85enddone
2462 f85endafi:
2463 call far ptr close8514 ;use afi, JCO 4/11/92
2464 ; call f85end ;use afi
2465 f85enddone:
2466 mov f85flag, 0
2467 no8514:
2468 cmp HGCflag, 1 ; was last video Hercules
2469 jne noHGC ; nope
2470 call hgcend
2471 mov HGCflag, 0
2472 noHGC:
2473 mov oktoprint,1 ; say it's OK to use printf()
mov goodmode,1 ; assume a good video mode
mov xga_loaddac,1 ; tell the XGA to fake a 'loaddac'
mov ax,video_bankadr ; restore the results of 'whichvga()'
mov [bankadr],ax ; ...
mov ax,video_bankseg ; ...
mov [bankseg],ax ; ...
mov ax,argax ; load up for the interrupt call
mov bx,argbx ; ...
mov cx,argcx ; ...
mov dx,argdx ; ...
mov videoax,ax ; save the values for future use
mov videobx,bx ; ...
mov videocx,cx ; ...
mov videodx,dx ; ...
call setvideo ; call the internal routine first
cmp goodmode,0 ; is it still a good video mode?
jne videomodeisgood ; yup.
mov ax,offset nullwrite ; set up null write-a-dot routine
mov bx,offset mcgaread ; set up null read-a-dot routine
mov cx,offset normaline ; set up normal linewrite routine
mov dx,offset mcgareadline ; set up normal linewrite routine
mov si,offset swapnormread ; set up the normal swap routine
jmp videomode ; return to common code
videomodeisgood:
mov bx,dotmode ; set up for a video table jump
cmp bx,30 ; are we within the range of dotmodes?
jbe videomodesetup ; yup. all is OK
mov bx,0 ; nope. use dullnormalmode
videomodesetup:
shl bx,1 ; switch to a word offset
mov bx,cs:videomodetable[bx] ; get the next step
jmp bx ; and go there
videomodetable dw offset dullnormalmode ; mode 0
dw offset dullnormalmode ; mode 1
dw offset vgamode ; mode 2
dw offset mcgamode ; mode 3
dw offset tseng256mode ; mode 4
dw offset paradise256mode ; mode 5
dw offset video7256mode ; mode 6
dw offset tweak256mode ; mode 7
dw offset everex16mode ; mode 8
dw offset targaMode ; mode 9
dw offset hgcmode ; mode 10
dw offset diskmode ; mode 11
dw offset f8514mode ; mode 12
dw offset cgamode ; mode 13
dw offset tandymode ; mode 14
dw offset trident256mode ; mode 15
dw offset chipstech256mode ; mode 16
dw offset ati256mode ; mode 17
dw offset everex256mode ; mode 18
dw offset yourownmode ; mode 19
dw offset ati1024mode ; mode 20
dw offset tseng16mode ; mode 21
dw offset trident16mode ; mode 22
dw offset video716mode ; mode 23
dw offset paradise16mode ; mode 24
dw offset chipstech16mode ; mode 25
dw offset everex16mode ; mode 26
dw offset VGAautomode ; mode 27
dw offset VESAmode ; mode 28
dw offset TrueColorAuto ; mode 29
dw offset dullnormalmode ; mode 30
dw offset dullnormalmode ; mode 31
tandymode: ; from Joseph Albrecht
mov tandyseg,0b800h ; set video segment address
mov tandyofs,0 ; set video offset address
mov ax,offset plottandy16 ; set up write-a-dot
mov bx,offset gettandy16 ; set up read-a-dot
mov cx,offset normaline ; set up the normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swapnormread ; set up the normal swap routine
cmp videoax,8 ; check for 160x200x16 color mode
je tandy16low ; ..
cmp videoax,9 ; check for 320x200x16 color mode
je tandy16med ; ..
cmp videoax,0ah ; check for 640x200x4 color mode
je tandy4high ; ..
cmp videoax,0bh ; check for 640x200x16 color mode
je tandy16high ; ..
tandy16low:
mov tandyscan,offset scan16k; set scan line address table
jmp videomode ; return to common code
tandy16med:
mov tandyscan,offset scan32k; set scan line address table
jmp videomode ; return to common code
tandy4high:
mov ax,offset plottandy4 ; set up write-a-dot
mov bx,offset gettandy4 ; set up read-a-dot
jmp videomode ; return to common code
tandy16high:
mov tandyseg,0a000h ; set video segment address
mov tandyofs,8000h ; set video offset address
mov tandyscan,offset scan64k; set scan line address table
jmp videomode ; return to common code
dullnormalmode:
mov ax,offset normalwrite ; set up the BIOS write-a-dot routine
mov bx,offset normalread ; set up the BIOS read-a-dot routine
mov cx,offset normaline ; set up the normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swapnormread ; set up the normal swap routine
jmp videomode ; return to common code
mcgamode:
mov ax,offset mcgawrite ; set up MCGA write-a-dot routine
mov bx,offset mcgaread ; set up MCGA read-a-dot routine
mov cx,offset mcgaline ; set up the MCGA linewrite routine
mov dx,offset mcgareadline ; set up the MCGA lineread routine
mov si,offset swap256 ; set up the MCGA swap routine
jmp videomode ; return to common code
tseng16mode:
mov tseng,1 ; set chipset flag
mov [bankadr],offset $tseng
mov [bankseg],seg $tseng
jmp vgamode ; set ega/vga functions
trident16mode:
mov trident,1 ; set chipset flag
mov [bankadr],offset $trident
mov [bankseg],seg $trident
jmp vgamode
video716mode:
mov video7,1 ; set chipset flag
mov [bankadr],offset $video7
mov [bankseg],seg $video7
jmp vgamode
paradise16mode:
mov paradise,1 ; set chipset flag
mov [bankadr],offset $paradise
mov [bankseg],seg $paradise
jmp vgamode
chipstech16mode:
mov chipstech,1 ; set chipset flag
mov [bankadr],offset $chipstech
mov [bankseg],seg $chipstech
jmp vgamode
everex16mode:
mov everex,1 ; set chipset flag
mov [bankadr],offset $everex
mov [bankseg],seg $everex
jmp vgamode
VESAmode: ; set VESA 16-color mode
mov ax,word ptr vesa_mapper
mov [bankadr],ax
mov ax,word ptr vesa_mapper+2
mov [bankseg],ax
cmp vesa_bitsppixel,15
jae VESAtruecolormode
VGAautomode: ; set VGA auto-detect mode
cmp colors,256 ; 256 colors?
je VGAauto256mode ; just like SuperVGA
cmp xga_isinmode,0 ; in an XGA mode?
jne xgamode
cmp colors,16 ; 16 colors?
je vgamode ; just like a VGA
jmp dullnormalmode ; otherwise, use the BIOS
VESAtruecolormode:
mov istruecolor,1
mov ax, offset VESAtruewrite ; set up VESA true-color write-a-dot routine
mov bx, offset VESAtrueread ; set up VESA true-color read-a-dot routine
mov cx, offset normaline ; set up dullnormal linewrite routine
mov dx, offset normalineread ; set up dullnormal lineread routine
mov si,offset swap256 ; set up the swap routine
jmp videomode ; return to common code
xgamode:
mov ax,offset xga_16write ; set up XGA write-a-dot routine
mov bx,offset xga_16read ; set up XGA read-a-dot routine
mov cx,offset xga_16linewrite ; set up the XGA linewrite routine
mov dx,offset normalineread ; set up the XGA lineread routine
mov si,offset swap256 ; set up the swap routine
jmp videomode ; return to common code
VGAauto256mode:
jmp super256mode ; just like a SuperVGA
egamode:
vgamode:
;;; shr vxdots,1 ; scan line increment is in bytes...
;;; shr vxdots,1
;;; shr vxdots,1
mov ax,offset vgawrite ; set up EGA/VGA write-a-dot routine.
mov bx,offset vgaread ; set up EGA/VGA read-a-dot routine
mov cx,offset vgaline ; set up the EGA/VGA linewrite routine
mov dx,offset vgareadline ; set up the EGA/VGA lineread routine
mov si,offset swapvga ; set up the EGA/VGA swap routine
jmp videomode ; return to common code
tseng256mode:
mov tseng,1 ; set chipset flag
mov [bankadr],offset $tseng
mov [bankseg],seg $tseng
jmp super256mode ; set super VGA linear memory functions
paradise256mode:
mov paradise,1 ; set chipset flag
mov [bankadr],offset $paradise
mov [bankseg],seg $paradise
jmp super256mode ; set super VGA linear memory functions
video7256mode:
mov video7, 1 ; set chipset flag
mov [bankadr],offset $video7
mov [bankseg],seg $video7
jmp super256mode ; set super VGA linear memory functions
trident256mode:
mov trident,1 ; set chipset flag
mov [bankadr],offset $trident
mov [bankseg],seg $trident
jmp super256mode ; set super VGA linear memory functions
chipstech256mode:
mov chipstech,1 ; set chipset flag
mov [bankadr],offset $chipstech
mov [bankseg],seg $chipstech
jmp super256mode ; set super VGA linear memory functions
ati256mode:
mov ativga,1 ; set chipset flag
mov [bankadr],offset $ativga
mov [bankseg],seg $ativga
jmp super256mode ; set super VGA linear memory functions
everex256mode:
mov everex,1 ; set chipset flag
mov [bankadr],offset $everex
mov [bankseg],seg $everex
jmp super256mode ; set super VGA linear memory functions
VGA256automode: ; Auto-detect SuperVGA
jmp super256mode ; set super VGA linear memory functions
VESA256mode: ; set VESA 256-color mode
mov ax,word ptr vesa_mapper
mov [bankadr],ax
mov ax,word ptr vesa_mapper+2
mov [bankseg],ax
jmp super256mode ; set super VGA linear memory functions
super256mode:
mov ax,offset super256write ; set up superVGA write-a-dot routine
mov bx,offset super256read ; set up superVGA read-a-dot routine
mov cx,offset super256line ; set up the linewrite routine
mov dx,offset super256readline ; set up the normal lineread routine
mov si,offset swap256 ; set up the swap routine
jmp videomode ; return to common code
tweak256mode:
shr vxdots,1 ; scan line increment is in bytes...
shr vxdots,1
mov oktoprint,0 ; NOT OK to printf() in this mode
mov ax,offset tweak256write ; set up tweaked-256 write-a-dot
mov bx,offset tweak256read ; set up tweaked-256 read-a-dot
mov cx,offset tweak256line ; set up tweaked-256 read-a-line
mov dx,offset tweak256readline ; set up the normal lineread routine
mov si,offset swapvga ; set up the swap routine
jmp videomode ; return to common code
cgamode:
mov cx,offset normaline ; set up the normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swapnormread ; set up the normal swap routine
cmp videoax,4 ; check for 320x200x4 color mode
je cga4med ; ..
cmp videoax,5 ; ..
je cga4med ; ..
cmp videoax,6 ; check for 640x200x2 color mode
je cga2high ; ..
cga4med:
mov ax,offset plotcga4 ; set up CGA write-a-dot
mov bx,offset getcga4 ; set up CGA read-a-dot
jmp videomode ; return to common code
cga2high:
mov ax,offset plotcga2 ; set up CGA write-a-dot
mov bx,offset getcga2 ; set up CGA read-a-dot
jmp videomode ; return to common code
ati1024mode:
mov ativga,1 ; set ATI flag.
mov ax,offset ati1024write ; set up ATI1024 write-a-dot
mov bx,offset ati1024read ; set up ATI1024 read-a-dot
mov cx,offset normaline ; set up the normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swap256 ; set up the swap routine
jmp videomode ; return to common code
diskmode:
call far ptr startdisk ; external disk-video start routine
mov ax,offset diskwrite ; set up disk-vid write-a-dot routine
mov bx,offset diskread ; set up disk-vid read-a-dot routine
mov cx,offset normaline ; set up the normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swapnormread ; set up the normal swap routine
jmp videomode ; return to common code
yourownmode:
call far ptr startvideo ; external your-own start routine
mov ax,offset videowrite ; set up ur-own-vid write-a-dot routine
mov bx,offset videoread ; set up ur-own-vid read-a-dot routine
mov cx,offset normaline ; set up the normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swapnormread ; set up the normal swap routine
mov videoflag,1 ; flag "your-own-end" needed.
jmp videomode ; return to common code
targaMode: ; TARGA MODIFIED 2 June 89 - j mclain
call far ptr StartTGA
mov ax,offset tgawrite ;
mov bx,offset tgaread ;
mov cx,offset normaline ; set up the normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swapnormread ; set up the normal swap routine
mov tgaflag,1 ;
jmp videomode ; return to common code
f8514mode: ; 8514 modes
cmp ai_8514, 0 ; check if afi flag is set, JCO 4/11/92
jne f85afi ; yes, try afi
call far ptr open8514hw ; start the 8514a, try registers first JCO
jnc f85ok
mov ai_8514, 1 ; set afi flag
f85afi:
call far ptr open8514 ; start the 8514a, try afi
jnc f85ok
mov ai_8514, 0 ; clear afi flag, JCO 4/11/92
mov goodmode,0 ; oops - problems.
mov dotmode, 0 ; if problem starting use normal mode
jmp dullnormalmode
hgcmode:
mov oktoprint,0 ; NOT OK to printf() in this mode
call hgcstart ; Initialize the HGC card
mov ax,offset hgcwrite ; set up HGC write-a-dot routine
mov bx,offset hgcread ; set up HGC read-a-dot routine
mov cx,offset normaline ; set up normal linewrite routine
mov dx,offset normalineread ; set up the normal lineread routine
mov si,offset swapnormread ; set up the normal swap routine
mov HGCflag,1 ; flag "HGC-end" needed.
jmp videomode ; return to common code
f85ok:
cmp ai_8514, 0
jne f85okafi ; afi flag is set JCO 4/11/92
mov ax,offset f85hwwrite ;use register routines
mov bx,offset f85hwread ;changed to near calls
mov cx,offset f85hwline ;
mov dx,offset f85hwreadline ;
mov si,offset swapnormread ; set up the normal swap routine
mov f85flag,1 ;
mov oktoprint,0 ; NOT OK to printf() in this mode
jmp videomode ; return to common code
f85okafi:
mov ax,offset f85write ;use afi routines, JCO 4/11/92
mov bx,offset f85read ;changed to near calls
mov cx,offset f85line ;
mov dx,offset f85readline ;
mov si,offset swapnormread ; set up the normal swap routine
mov f85flag,1 ;
mov oktoprint,0 ; NOT OK to printf() in this mode
jmp videomode ; return to common code
TrueColorAuto:
cmp TPlusInstalled, 1
jne NoTPlus
push NonInterlaced
push PixelZoom
push MaxColorRes
push ydots
push xdots
call far ptr MatchTPlusMode
add sp, 10
or ax, ax
jz NoTrueColorCard
cmp ax, 1 ; Are we limited to 256 colors or less?
jne SetTPlusRoutines ; All right! True color mode!
mov cx, MaxColorRes ; Aw well, give'm what they want.
2474 shl ax, cl
2475 mov colors, ax
2476
2477 SetTPlusRoutines:
2478 mov goodmode, 1
2479 mov oktoprint, 1
2480 mov ax, offset TPlusWrite
2481 mov bx, offset TPlusRead
2482 mov cx, offset normaline
2483 mov dx, offset normalineread
2484 mov si, offset swapnormread
2485 jmp videomode
2486
2487 NoTPlus:
2488 NoTrueColorCard:
2489 mov goodmode, 0
2490 jmp videomode
2491
2492 videomode:
2493 mov dotwrite,ax ; save the results
2494 mov dotread,bx ; ...
2495 mov linewrite,cx ; ...
2496 mov lineread,dx ; ...
2497 mov word ptr swapsetup,si ; ...
2498 mov ax,cs ; ...
2499 mov word ptr swapsetup+2,ax ; ...
2500
2501 mov ax,colors ; calculate the "and" value
2502 dec ax ; to use for eventual color
2503 mov andcolor,ax ; selection
2504
2505 mov boxcount,0 ; clear the zoom-box counter
2506
2507 mov daclearn,0 ; set the DAC rotates to learn mode
2508 mov daccount,6 ; initialize the DAC counter
2509 cmp cpu,88 ; say, are we on a 186/286/386?
2510 jbe setvideoslow ; boo! hiss!
2511 mov daclearn,1 ; yup. bypass learn mode
2512 mov ax,cyclelimit ; and go as fast as he wants
2513 mov daccount,ax ; ...
2514 setvideoslow:
2515 call far ptr loaddac ; load the video dac, if we can
2516 ret
2517 setvideomode endp
2518
2519 set_vesa_mapping_func proc near
2520 mov cx, word ptr vesa_winaattrib ; puts vesa_winbattrib in ch
2521 and cx,0707h ; so we can check them together
2522 cmp cx,0305h
2523 je use_vesa2
2524 cmp cx,0503h
2525 je use_vesa2
2526 test ch,01h
2527 jz use_vesa1
2528 cmp vesa_winsize,32 ; None of the above -- 2 32K R/W?
2529 jne use_vesa1 ; if not, use original 1 64K R/W!
2530 mov word ptr vesa_mapper,offset $vesa3
2531 mov ax,32
2532 div vesa_wingran ; Get number of pages in 32K
2533 mov vesa_gran_offset,ax ; Save it for mapping function
2534 xor dx,dx
2535 mov ax,1
2536 test vesa_winaseg, 00800h
2537 jz low_high_seq
2538 xchg ax,dx
2539 low_high_seq:
2540 mov vesa_low_window,dx ; Window number at A000-A7FF
2541 mov vesa_high_window,ax ; Window number at A800-AFFF
2542 jmp short vesamapselected
2543 use_vesa2:
2544 mov word ptr vesa_mapper,offset $vesa2
2545 jmp short vesamapselected
2546 use_vesa1:
2547 mov word ptr vesa_mapper,offset $vesa1
2548 vesamapselected:
2549 mov word ptr vesa_mapper+2,seg $vesa1
2550 ret
2551 set_vesa_mapping_func endp
2552
2553 setnullvideo proc
2554 mov ax,offset nullwrite ; set up null write-a-dot routine
2555 mov dotwrite,ax ; ...
2556 mov ax,offset nullread ; set up null read-a-dot routine
2557 mov dotread,ax ; ...
2558 ret
2559 setnullvideo endp
2560
2561 setvideo proc near ; local set-video more
2562
2563 cmp xga_isinmode,0 ; XGA in graphics mode?
2564 je noxga ; nope
2565 push ax
2566 push bx
2567 push cx
2568 push dx
2569 mov ax,0 ; pull it out of graphics mode
2570 push ax
2571 mov xga_clearvideo,al
2572 call far ptr xga_mode
2573 pop ax
2574 pop dx
2575 pop cx
2576 pop bx
2577 pop ax
2578 noxga:
2579
2580 push bp ; save it around all the int 10s
2581 mov text_type,2 ; set to this for most exit paths
2582 mov si,offset $vesa_nullbank ; set to do nothing if mode not vesa
2583 mov word ptr vesa_bankswitch,si
2584 mov si,seg $vesa_nullbank
2585 mov word ptr vesa_bankswitch+2,si
2586 mov word ptr vesa_mapper,offset $nobank
2587 mov word ptr vesa_mapper+2,seg $nobank
2588 mov vesa_bitsppixel,8
2589 mov istruecolor,0
2590 ; mov vesabyteoffset,0
2591 mov tweakflag,0
2592
2593 cmp ax,0 ; TWEAK?: look for AX==BX==CX==0
2594 jne short setvideobios ; ...
2595 cmp bx,0 ; ...
2596 jne short setvideobios ; ...
2597 cmp cx,0 ; ...
2598 jne short setvideobios ; ...
2599
2600 cmp dotmode, 27 ; check for auto-detect modes
2601 je setvideoauto1
2602 cmp dotmode, 20 ; check for auto-detect modes
2603 je setvideoauto1
2604 cmp dotmode, 4 ; check for auto-detect modes
2605 je setvideoauto1
2606 cmp dotmode, 28 ; check for auto-detect modes
2607 je setvideoauto1
2608
2609 jmp setvideoregs ; anything else - assume register tweak
2610
2611 setvideoauto1:
2612 jmp setvideoauto ; stupid short 'je' instruction!!
2613
2614 setvideobios:
2615 mov text_type,0 ; if next branch taken this is true
2616 cmp ax,3 ; text mode?
2617 jne setvideobios2 ; nope
2618 mov textaddr,0b800h
2619 cmp mode7text,0 ; egamono/hgc?
2620 je setvideobios_doit ; nope. Just do it.
2621 mov textaddr,0b000h
2622 mov ax,7 ; use mode 7
2623 call maybeor ; maybe or AL or (for Video-7s) BL
2624 push bp ; weird but necessary, set mode twice
2625 int 10h ; get colors right on vga systems
2626 pop bp ; ..
2627 mov ax,7 ; for the 2nd hit
2628 jmp short setvideobios_doit
2629 setvideobios2:
2630 mov text_type,1 ; if next branch taken this is true
2631 cmp ax,6 ; 640x200x2 mode?
2632 je setvideobios_doit ; yup. Just do it.
2633 mov text_type,2 ; not mode 3 nor 6, so this is true
2634 mov si,dotmode ; compare the dotmode against
2635 mov di,video_type ; the video type
2636 add si,si ; (convert to a word pointer)
2637 cmp cs:video_requirements[si],di
2638 jbe setvideobios_doit ; ok
2639 jmp setvideoerror ; Error.
2640 setvideobios_doit:
2641 cmp dotmode,14 ; check for Tandy 1000 mode
2642 jne setvideobios_doit2 ; ..
2643 cmp ax,0ah ; check for Tandy 640x200x4 color mode
2644 jne setvideobios_doit1 ; ..
2645 push bp ; setup Tandy 640x200x4 color mode
2646 int 10h ; ..
2647 pop bp ; ..
2648 mov di,16 ;port offset for palette registers
2649 mov bx,0b01h ; remap colors for better display on
2650 call settandypal ; .. Tandy 640x200x4 color mode
2651 mov di,16 ;port offset for palette registers
2652 mov bx,0d02h ; ..
2653 call settandypal ; ..
2654 mov di,16 ;port offset for palette registers
2655 mov bx,0f03h ; ..
2656 call settandypal ; ..
2657 jmp setvideobios_worked
2658 setvideobios_doit1:
2659 cmp ax,0bh ; check for Tandy 640x200x16 color mode
2660 jne setvideobios_doit2 ; ..
2661 call tandysetup ; setup Tandy 640x200x16 color mode
2662 jmp setvideobios_worked
2663 setvideobios_doit2:
2664 call maybeor ; maybe or AL or (for Video-7s) BL
2665 push bp ; some BIOS's don't save this
2666 int 10h ; do it via the BIOS.
2667 pop bp ; restore the saved register
2668 cmp dotmode,28 ; VESA mode?
2669 ; jne setvideobios_worked ; Nope. Return.
2670 je over_setvideobios
2671 jmp setvideobios_worked ; Nope. Return.
2672 over_setvideobios:
2673 cmp ah,0 ; did it work?
2674 ; jne setvideoerror ; Nope. Failed.
2675 je over_setvideoerror
2676 jmp setvideoerror ; Nope. Failed.
2677 over_setvideoerror:
2678 mov vesa_granularity,1 ; say use 64K granules
2679 push es ; set ES == DS
2680 mov ax,ds ; ...
2681 mov es,ax ; ...
2682 mov ax,4f01h ; ask about this video mode
2683 mov cx,bx ; this mode
2684 and cx,07fffh ; (oops - correct for the high-bit)
2685 mov di, offset suffix ; (a safe spot for 256 bytes)
2686 int 10h ; do it
2687 cmp ax,004fh ; did the call work?
2688 je okaysofar
2689 jmp nogoodvesamode ; nope
2690 okaysofar:
2691 mov si, offset suffix ; save the first 40 bytes of the mode info
2692 mov di, offset vesa_mode_info ; (the truecolor routines need it)
2693 mov cx,40 ; but since we have them, we'll use
rep movsb ; the variables in the first 40 bytes
mov cx, vesa_mode_info ; get the attributes
test cx,1 ; available video mode?
jnz overnogood
jmp nogoodvesamode ; nope. skip some code
overnogood:
;;; A sanity check, which ATI cards don't pass. JCO 12 MAY 2001
2694 ;;; test cx,60h ; not vga compatible or not windowed
2695 ;;; jnz nogoodvesamode ; yup. skip some code
2696 call set_vesa_mapping_func
2697 mov cx, word ptr vesa_funcptr ; get the Bank-switching routine
2698 cmp cx,0 ; could make this use the bios, bailout for now JCO
2699 jz nogoodvesamode ; nope. skip some code
2700 mov word ptr vesa_bankswitch, cx ; ...
2701 mov cx, word ptr vesa_funcptr+2 ; ...
2702 mov word ptr vesa_bankswitch+2, cx ; ...
2703 mov cx, vesa_bytespscan ; get the bytes / scan line
2704 cmp cx,0 ; is this entry filled in?
2705 je skipvesafix ; nope
2706 ;;; cmp colors,256 ; 256-color mode?
2707 ;;; jne skipvesafix ; nope
2708 cmp vesa_numplanes,1
2709 jbe store_vesa_bytes
2710 shl cx,1 ; if a planar mode, bits are pixels
2711 shl cx,1 ; so we multiply bytes by 8
2712 shl cx,1
2713 store_vesa_bytes:
2714 mov vxdots,cx ; adjust the screen width accordingly XXX
2715 ; cmp cx,sxdots ; 8/93 JRS textsafe=save fix
2716 ; je skipvesafix
2717 ; mov ax,offset swapnormread ; use the slow swap routine
2718 ; mov word ptr swapsetup,ax ; ...
2719 skipvesafix:
2720 cmp virtual,0 ; virtual modes turned off
2721 jne check_next
2722 cmp video_scroll,0 ; not turned on
2723 je dont_go_there ; don't need next
mov ax,vesa_xres ; get the physical resolution
mov bx,vesa_yres
mov sxdots,ax
mov sydots,bx
check_next:
cmp setting_text,1 ; don't set virtual stuff
2724 je dont_go_there
2725 mov video_scroll,0 ; reset scrolling flag
2726 cmp dotmode,28
2727 jne dont_go_there
2728 call VESAvirtscan ; virtual scanline setup
2729 dont_go_there:
2730 mov cx, vesa_wingran ; get the granularity
2731 cmp cl,1 ; ensure the divide won't blow out
jb nogoodvesamode ; granularity == 0???
mov ax,64 ; ...
div cl ; divide 64K by granularity
mov vesa_granularity,al ; multiply the bank number by this
cmp vesa_bitsppixel,15 ; true-color mode?
jb nogoodvesamode
mov istruecolor,1 ; yup
nogoodvesamode:
pop es ; restore ES
mov ax,4f02h ; restore the original call
setvideobios_worked:
jmp setvideoreturn ; Return.
setvideoerror: ; oops. No match found.
mov goodmode,0 ; note that the video mode is bad
mov ax,3 ; switch to text mode
jmp setvideobios_doit
setvideoauto:
mov si, video_entries ; look for the correct resolution
sub si,8 ; get a running start
setvideoloop:
add si,10 ; get next entry
mov ax,cs:0[si] ; check X-res
cmp ax,0 ; anything there?
je setvideoerror ; nope. No match
cmp ax,sxdots
jne setvideoloop
mov ax,cs:2[si] ; check Y-res
cmp ax,sydots
jne setvideoloop
mov ax,cs:4[si] ; check Colors
cmp ax,colors
jne setvideoloop
mov ax,cs:6[si] ; got one! Load AX
mov bx,cs:8[si] ; Load BX
cmp ax,0ffffh ; XGA special?
jne notxgamode
mov al,orvideo
mov xga_clearvideo,al
cmp al,0 ; clearing the video?
jne xgask1 ; yup
mov ax,03h ; switch to text mode (briefly)
int 10h
xgask1:
push bx
call far ptr xga_mode
pop bx
cmp ax,0
je setvideoloop
jmp setvideoreturn
notxgamode:
cmp bx,0ffh ; ATI 1024x768x16 special?
jne notatimode
mov dotmode,20 ; Convert to ATI specs
mov al,65h
mov bx,0
jmp setvideobios
notatimode:
cmp bx,0feh ; Tseng 640x400x256 special?
jne nottsengmode
mov ax,0 ; convert to Tseng specs
mov bx,0
mov cx,0
mov dx,10
mov dotmode,4
jmp setvideoregs
nottsengmode:
cmp bx,0fdh ; Compaq 640x480x256 special?
jne notcompaqmode
mov vxdots,1024 ; (compaq uses 1024-byte scanlines)
mov bx,offset swapnormread ; use the slow swap routine
mov word ptr swapsetup,bx ; ...
mov bx,0
jmp setvideobios
notcompaqmode:
cmp ax,4f02h ; VESA mode?
jne notvesamode
mov dotmode,28 ; convert to VESA specs
notvesamode:
jmp setvideobios
setvideoregs: ; assume genuine VGA and program regs
mov si, dotmode ; compare the dotmode against
mov di,video_type ; the video type
add si,si ; (convert to a word pointer)
cmp cs:video_requirements[si],di
jbe setvideoregs_doit ; good value. Do it.
jmp setvideoerror ; bad value. Error.
setvideoregs_doit:
mov si,dx ; get the video table offset
shl si,1 ; ...
mov si,word ptr tweaks[si] ; ...
mov tweaktype, dx ; save tweaktype
cmp dx,8 ; 360x480 tweak256mode?
je isatweaktype ; yup
cmp dx,9 ; 320x400 tweak256mode?
je isatweaktype ; yup
cmp dx,18 ; 320x480 tweak256mode?
je isatweaktype ; yup
cmp dx,19 ; 320x240 tweak256mode?
je isatweaktype ; yup
cmp dx,10 ; Tseng tweak?
je tsengtweak ; yup
;Patch - Michael D. Burkey (5/22/90)
cmp dx,14 ; ATI Mode Support
je ATItweak
cmp dx,15
je ATItweak
cmp dx,16
je ATItweak
cmp dx,17
je ATItweak2 ; ATI 832x616 mode
cmp dx,11 ; tweak256mode? (11 & up)
jae isatweaktype ; yup
;End Patch
jmp not256 ; nope none of the above
tsengtweak:
mov ax,46 ; start with S-VGA mode 2eh
call maybeor ; maybe don't clear the video memory
2732 int 10h ; let the bios clear the video memory
2733 mov dx,3c2h ; misc output
2734 mov al,063h ; dot clock
2735 out dx,al ; select it
2736 mov dx,3c4h ; sequencer again
2737 mov ax,0300h ; restart sequencer
2738 out dx,ax ; running again
2739 jmp is256;
2740 ATItweak:
2741 mov ax,62h
2742 ;; pb, why no maybeor call here?
2743 int 10h
2744 mov dx,3c2h
2745 mov al,0e3h
2746 out dx,al
2747 mov dx,3c4h
2748 mov ax,0300h
2749 out dx,ax
2750 jmp is256
2751
2752 ATItweak2:
2753 mov ax,63h
2754 ;; pb, why no maybeor call here?
2755 int 10h
2756 mov dx,3c4h
2757 mov ax,0300h
2758 out dx,ax
2759 jmp is256
2760
2761 isatweaktype:
2762 mov tweakflag,1
2763 mov ax,0013h ; invoke video mode 13h
2764 call maybeor ; maybe or AL or (for Video-7s) BL
2765 int 10h ; do it
2766
2767 mov dx,3c4h ; alter sequencer registers
2768 mov ax,0604h ; disable chain 4
2769 out dx,ax
2770
2771 cmp orvideo,0 ; are we supposed to clear RAM?
2772 jne noclear256 ; (nope)
2773
2774 mov dx,03c4h ; alter sequencer registers
2775 mov ax,0f02h ; enable writes to all planes
2776 OUT_WORD
2777
2778 push es ; save ES for a tad
2779 mov ax,VGA_SEGMENT ; clear out all 256K of
2780 mov es,ax ; video memory
2781 sub di,di ; (64K at a time, but with
2782 mov ax,di ; all planes enabled)
2783 mov cx,8000h ;# of words in 64K
2784 cld
2785 rep stosw ;clear all of display memory
2786 pop es ; restore ES
2787
2788 noclear256:
2789 mov dx,3c4h ; alter sequencer registers
2790 mov ax,0604h ; disable chain 4
2791 out dx,ax
2792
2793 jmp short is256 ; forget the ROM characters
2794
2795 not256:
2796
2797 mov ax,0012h ; invoke video mode 12h
2798 call maybeor ; maybe or AL or (for Video-7s) BL
2799 int 10h ; do it.
2800
2801 is256: push es ; save ES for a tad
2802 mov ax,40h ; Video BIOS DATA area
2803 mov es,ax ; ...
2804
2805 mov dx,word ptr es:[63h] ; say, where's the 6845?
add dx,6 ; locate the status register
vrdly1: in al,dx ; loop until vertical retrace is off
test al,8 ; ...
jnz vrdly1 ; ...
vrdly2: in al,dx ; now loop until it's on!
2806 test al,8 ; ...
2807 jz vrdly2 ; ...
2808
2809 cli ; turn off all interrupts
2810 mov dx,tweaktype
2811 cmp dx,9 ; 320x400 mode?
2812 je not256mode ; yup - skip this stuff
2813 cmp dx,10 ; Tseng tweak mode?
2814 je not256mode ; yup - skip this stuff
2815 ;patch #2 (M. Burkey 5/22/90)
2816 cmp dx,17 ; for 832x616 ATI Mode
2817 je not256mode
2818 ;patch end
2819 mov cl,0E7h ; value for misc output reg
2820 cmp dx,18 ; 320x480 mode?
2821 je setmisc320 ; nope, use above value
2822 cmp dx,19 ; 320x240 mode?
2823 jne setmiscoreg ; nope, use above value
2824 setmisc320:
2825 mov cl,0E3h ; value for misc output reg
2826 setmiscoreg:
2827 mov dx,03c4h ; Sequencer Synchronous reset
2828 mov ax,0100h ; set sequencer reset
2829 out dx,ax
2830 mov dx,03c2h ; Update Misc Output Reg
2831 mov al,cl
2832 out dx,al
2833 mov dx,03c4h ; Sequencer Synchronous reset
2834 mov ax,0300h ; clear sequencer reset
2835 out dx,ax
2836 not256mode:
2837 mov dx,word ptr es:[63h] ; say, where's the 6845?
add si,2 ; point SI to the CRTC registers table
mov al,11h ; deprotect registers 0-7
mov ah,byte ptr [si+11h]
and ah,7fh
out dx,ax
mov cx,18h ; update this many registers
mov bx,00 ; starting with this one.
crtcloop:
mov al,bl ; update this register
mov ah,byte ptr [bx+si] ; to this
out dx,ax
inc bx ; ready for the next register
loop crtcloop ; (if there is a next register)
sti ; restore interrupts
pop es ; restore ES
setvideoreturn:
mov curbk,0ffffh ; stuff impossible value into cur-bank
mov orvideo,0 ; reset the video to clobber memory
pop bp
ret
setvideo endp
maybeor proc near ; or AL or BL for mon-destr switch
cmp ah,4fh ; VESA special mode?
je maybeor2 ; yup. Do this one different
cmp ah,6fh ; video-7 special mode?
je maybeor1 ; yup. do this one different
or al,orvideo ; normal non-destructive switch
jmp short maybeor99 ; we done.
maybeor1:
or bl,orvideo ; video-7 switch
jmp short maybeor99
maybeor2:
or bh,orvideo ; VESA switch
maybeor99:
ret ; we done.
maybeor endp
; ************* function scroll_center(tocol, torow) *************************
; scroll_center --------------------------------------------------------------
; * this is meant to be an universal scrolling redirection routine
; (if scrolling will be coded for the other modes too, the VESAscroll
; call should be replaced by a preset variable (like in proc newbank))
; * arguments passed are the coords of the screen center because
; there is no universal way to determine physical screen resolution
; ------------------------------------------------------------12-08-2002-ChCh-
scroll_center proc tocol: word, torow: word
cmp video_scroll,0 ; is the scrolling on?
jne okletsmove ; ok, lets move
jmp staystill ; no, stay still
okletsmove:
mov cx,tocol ; send center-x to the routine
mov dx,torow ; send center-y to the routine
call VESAscroll ; replace this later with a variable
staystill:
ret
scroll_center endp
; ************* function scroll_relative(bycol, byrow) ***********************
; scroll_relative ------------------------------------------------------------
; * relative screen center scrolling, arguments passed are signed deltas
; ------------------------------------------------------------16-08-2002-ChCh-
scroll_relative proc bycol: word, byrow: word
cmp video_scroll,0 ; is the scrolling on?
jne okletsmove ; ok, lets move
jmp staystill ; no, stay still
okletsmove:
mov cx,video_startx ; where we already are..
mov dx,video_starty
add cx,video_cofs_x ; find the screen center
add dx,video_cofs_y
add cx,bycol ; add the relative shift
add dx,byrow
call VESAscroll ; replace this later with a variable
staystill:
ret
scroll_relative endp
; ************* function scroll_state(what) **********************************
; scroll_state ---------------------------------------------------------------
; * what == 0: saves the position of the scrolled screen center
; * what != 0: restores saved position and scrolls the screen
; ------------------------------------------------------------16-08-2002-ChCh-
scroll_state proc what: word
cmp what,0 ; save or restore?
jne restore
mov cx,video_startx ; where we already are..
mov dx,video_starty
add cx,video_cofs_x ; find the screen center
add dx,video_cofs_y
mov scroll_savex,cx ; save it for restoring
mov scroll_savey,dx
jmp wedone ; return
restore:
mov cx,scroll_savex ; get the saved coords
mov dx,scroll_savey
call VESAscroll ; scroll there
wedone:
ret
scroll_state endp
; VESAscroll ---------------------------------------------------------------
; * this does the scrolling of the screen center then (cx=to_col, dx=to_row)
; (first, it has to figure out the top-left corner coords)
; ------------------------------------------------------------12-08-2002-ChCh-
VESAscroll proc near
sub cx,video_cofs_x
js colbad ; to_col too small
cmp cx,video_slim_x
jna colok
mov cx,video_slim_x ; to_col too big
jmp short colok
colbad:
xor cx,cx
colok:
sub dx,video_cofs_y
js rowbad ; to_row too small
cmp dx,video_slim_y
jna rowok
mov dx,video_slim_y ; to_row too big
jmp short rowok
rowbad:
xor dx,dx
rowok:
cmp cx,video_startx ; moves left/right?
jne ok_letsmove
cmp dx,video_starty ; move up/down?
jne ok_letsmove
jmp short stay_still ; otherwise do nothing
ok_letsmove:
mov ax,4f07h ; fn set display start
; mov bx,0080h ; subfn 80 during the vertical retrace
; xor bx,bx ; subfn 0 instantly (if sf 80 doesn't work)
2838 mov bx,wait_retrace ; wait for retrace?
2839 int 10h ; move there the left-top corner
2840 mov video_startx,cx ; what was really set?
2841 mov video_starty,dx ; (save the result)
2842 stay_still:
2843 ret
2844 VESAscroll endp
2845
2846 ; VESAvirtscan ---------------------------------------------------------------
2847 ; * tests whether the virtual scanline is needed and tries to set it up;
2848 ; when nothing fails it sets the video_scroll flag to 1, else to 0
2849 ; * if sxdots is too small, vesa_xres is used instead to preserve nice
2850 ; current behavior (small window by small sx/ydots got from cfgfile)
2851 ; ------------------------------------------------------------12-08-2002-ChCh-
2852
2853 VESAvirtscan proc near
2854 xor ax,ax
2855 once_again:
2856 mov cx,sxdots ; this should be passed twice
2857 mov dx,sydots
2858 cmp cx,vesa_xres ; asked wider than screen x?
2859 ja setvirtscan
2860 cmp dx,vesa_yres ; asked higher than screen y?
2861 ja setvirtscan
2862 jmp wedone ; otherwise do nothing
2863 setvirtscan:
2864 cmp ax,004fh ; is this second pass?
2865 je secondpass
2866 mov chkd_vvs,1
2867 mov ax,4f06h ; VESA fn 6 scanline length
2868 mov bx,1 ; subfn 1 get line width
2869 int 10h
2870 cmp ax,004fh ; did that work?
2871 ;; jne bad_vesa ; bad vesa.. try it anyway
2872 je over_bailout
2873 jmp wedonebad ; bailout now
2874 over_bailout:
2875 mov ax,4f06h ; VESA fn 6 scanline length
2876 mov bx,3 ; subfn 3 get max line width
2877 int 10h
2878 cmp ax,004fh ; did that work?
2879 jne bad_vesa ; bad vesa.. try it anyway
2880 mov ax,4f06h
2881 mov cx,bx ; get the max width in bytes
2882 mov bx,2 ; subfn 2 set width in bytes
2883 and cx,0fff8h ; 8 bytes width align
2884 int 10h
2885 cmp ax,004fh ; did that work?
2886 jne bad_vesa ; bad vesa.. try it anyway
2887 cmp sxdots,cx ; max width in pixels in cx
2888 jae alreadyset ; can't set more
bad_vesa:
mov ax,4f06h
mov cx,sxdots
xor bx,bx ; subfn 0 set width in pixels
cmp cx,vesa_xres ; asked more than screen's width?
2889 jnb width_ok
2890 mov cx,vesa_xres ; can't set less
int 10h
cmp ax,004fh ; did that work?
je nofullscr ; don't update sxdots
2891 jmp wedonebad ; bad luck..
2892 width_ok:
2893 int 10h ; set the virtual scanline
2894 cmp ax,004fh ; did that work?
2895 je alreadyset
2896 jmp wedonebad ; bad luck..
2897 alreadyset:
2898 mov sxdots,cx ; update sxdots to what was set
2899 nofullscr:
2900 cmp sydots,dx ; enough lines available?
2901 jna once_more
2902 mov sydots,dx ; no, save the limit
2903 once_more:
2904 jmp once_again ; go compare the result
2905 secondpass:
2906 mov video_scroll,1 ; turn on the scroll flag
2907 mov vxdots,bx ; save the line byte size
2908 mov xdots,cx ; save it
2909 mov ydots,dx ; save it
2910 mov ax,vesa_xres ; get the physical resolution
2911 mov bx,vesa_yres
2912 sub cx,ax ; cx=sxdots-vesa_xres
2913 jns slimxok
2914 xor cx,cx ; line too short
2915 slimxok:
2916 sub dx,bx ; dx=sydots-vesa_yres
2917 jns slimyok
2918 xor dx,dx ; too few lines
2919 slimyok:
2920 mov video_slim_x,cx ; save scrolling limits
2921 mov video_slim_y,dx
2922 shr ax,1 ; the middle of the screen
2923 shr bx,1
2924 mov video_cofs_x,ax ; save screen center offset
2925 mov video_cofs_y,bx
2926 mov cx,sxdots ; get virtual resolution
2927 mov dx,sydots
2928 ;; xor ax,ax
2929 mov ax,1 ; try to move a tad
2930 shr cx,1 ; find the center of it
2931 shr dx,1
2932 dec cx ; zero-based coords
2933 dec dx ; (no sf, s?dots is always >= 2)
2934 mov video_startx,ax ; video didn't scroll yet
mov video_starty,ax
push dx ; store the center coords
push cx
mov wait_retrace,0080h ; wait for vertical retrace
call VESAscroll ; scroll there the screen
pop cx ; restore the center coords
pop dx
cmp ax,004fh ; did it scroll?
jne noretrace ; no, try it another way..
jmp short wedone
noretrace:
;; xor ax,ax
mov ax,2 ; try to move a tad
mov wait_retrace,0 ; don't wait for v. retrace
2935 mov video_startx,ax ; video didn't scroll yet
mov video_starty,ax
call VESAscroll ; try the instant scrolling
cmp ax,004fh ; did this scroll?
je wedone
bad_luck:
mov cx,vesa_xres ; VESA failed.. restore dimensions
mov dx,vesa_yres
cmp sxdots,cx ; asked wider than screen?
jna width_notbad
mov sxdots,cx ; correct it
width_notbad:
cmp sydots,dx ; asked higher than screen?
jna wedonebad
mov sydots,dx ; correct it
wedonebad:
mov video_scroll,0 ; no, disable the scrolling
wedone:
ret
VESAvirtscan endp
; ********* Functions setfortext() and setforgraphics() ************
; setfortext() resets the video for text mode and saves graphics data
; setforgraphics() restores the graphics mode and data
; setclear() clears the screen after setfortext()
monocolors db 0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
setfortext proc uses es si di
push bp ; save it around the int 10s
mov setting_text,1
cmp dotmode, 12 ;check for 8514
jne tnot8514
cmp f85flag, 0 ;check 8514 active flag
je go_dosettext
cmp ai_8514, 0 ;using registers? JCO 4/11/92
jne not85reg
call far ptr close8514hw ;close adapter if not, with registers
jmp done85close
not85reg:
call far ptr close8514 ;close adapter if not, with afi
done85close:
mov f85flag, 0
go_dosettext:
jmp dosettext ; safe to go to mode 3
tnot8514:
cmp dotmode,9 ; Targa?
je go_dosettext ; yup, leave it open & go to text
cmp xga_isinmode,0 ; XGA in graphics mode?
je noxga ; nope
mov ax,xga_isinmode ; remember if we were in XGA mode
mov xga_clearvideo,80h ; don't clear the video!
2936 mov ax,0 ; switch to VGA (graphics) mode
2937 push ax
2938 call far ptr xga_mode
2939 pop ax ; proceed on like nothing happened
2940 mov xga_clearvideo,0 ; reset the clear-video flag
2941 noxga:
2942
2943 cmp dotmode,14 ; (klooge for Tandy 640x200x16)
2944 je setfortextcga
2945 cmp videoax,0 ; check for CGA modes
2946 je go_setfortextnocga ; not this one
2947 cmp dotmode,10 ; Hercules?
2948 je setfortextcga ; yup
2949 cmp videoax,7 ; <= vid mode 7?
2950 jbe setfortextcga ; yup
2951 go_setfortextnocga:
2952 jmp setfortextnocga ; not this one
2953 setfortextcga: ; from mode ensures we can go to mode 3, so do it
2954 mov ax,extraseg ; set ES == Extra Segment
2955 add ax,1000h ; (plus 64K)
2956 mov es,ax ; ...
2957 mov di,4000h ; save the video data here
2958 mov ax,0b800h ; video data starts here
2959 mov si,0 ; ...
2960 cmp videoax,3 ; from mode 3?
2961 jne setfortextcga2 ; nope
2962 cmp mode7text,0 ; egamono/hgc?
2963 je setfortextcga2 ; nope
2964 mov ax,0b000h ; video data starts here
2965 setfortextcga2:
2966 mov cx,2000h ; save this many words
2967 cmp dotmode,10 ; Hercules?
2968 jne setfortextcganoherc ; nope
2969 mov di,0 ; (save 32K)
2970 mov ax,0b000h ; (from here)
2971 mov cx,4000h ; (save this many words)
2972 setfortextcganoherc:
2973 cmp dotmode,14 ; check for Tandy 1000 specific modes
2974 jne setfortextnotandy ; ..
2975 mov ax,tandyseg ; video data starts here
2976 mov si,tandyofs ; save video data here
2977 mov di,0 ; save the video data here
2978 mov cx,4000h ; save this many words
2979 setfortextnotandy:
2980 push ds ; save DS for a tad
2981 mov ds,ax ; reset DS
2982 cld ; clear the direction flag
2983 rep movsw ; save them.
2984 pop ds ; restore DS
2985 cmp dotmode,10 ; Hercules?
2986 jne dosettext ; nope
2987 cmp HGCflag, 0 ; check HGC active flag
2988 je dosettext
2989 call hgcend ; close adapter
2990 mov HGCflag, 0
2991 dosettext:
2992 mov ax,3 ; set up the text call
2993 mov bx,0 ; ...
2994 mov cx,0 ; ...
2995 mov dx,0 ; ...
2996 call setvideo ; set the video
2997 jmp setfortextreturn
2998 setfortextnocga:
2999 mov bios_vidsave,0 ; default, not using bios for state save
3000 mov ax,textsafe2 ; videotable override?
3001 cmp ax,0 ; ...
3002 jne setfortextsafe ; yup
3003 mov ax,textsafe ; nope, use general setting
3004 setfortextsafe:
3005 cmp ax,2 ; textsafe=no?
3006 jne setforcolortext ; nope
3007 jmp setfordummytext ; yup, use 640x200x2
3008 setforcolortext:
3009 ; must be ega, mcga, or vga, else we'd have set textsafe=no in runup
cmp ax,4 ; textsafe=save?
jne setforcolortext2 ; nope
mov ax,0 ; disable the video (I think)
call disablevideo ; ...
call far ptr savegraphics ; C rtn which uses swapsetup
call swapvga_reset ; some cleanup for swapvga case
mov orvideo,80h ; preserve memory, just for speed
cmp videoax,0fh ; ega 640x350x2?
jne dosettext ; nope, go call bios for mode 3
mov ax,83h ; I know this is silly! have to set
int 10h ; mode twice when coming from mode 0fh
jmp dosettext ; on some machines to get right colors
setforcolortext2:
cmp ax,3 ; textsafe=bios?
jne setforcolortext3 ; nope
cmp video_type,5 ; vga?
jl setforcolortext3 ; nope
mov ax,1c00h ; check size of reqd save area
mov cx,3 ; for hardware + bios states
int 10h ; ask...
cmp al,1ch ; function recognized?
jne setforcolortext3 ; nope
cmp bx,4 ; buffer big enough? (3 seems usual)
ja setforcolortext3 ; nope
mov bios_vidsave,1 ; using bios to save vid state
mov ax,cs ; ptr to save buffer
mov es,ax ; ...
mov bx,offset bios_savebuf ; ...
mov ax,1c01h ; save state
mov cx,3 ; hardware + bios
int 10h ; ...
setforcolortext3:
push ds ; save ds
mov ax,extraseg ; set ES == Extra Segment
add ax,1000h ; (plus 64K)
mov es,ax ; ...
cld
mov ax,0a000h ; video mem address
cmp video_type,4 ; mcga?
jne setfortextegavga ; nope
mov ds,ax ; set ds to video mem
xor di,di ; from vid offset 0
xor si,si ; to save offset 0
mov cx,1000h ; save 4k words
rep movsw ; font info
mov si,8000h ; from vid offset 8000h
mov cx,0800h ; save 2k words
rep movsw ; characters and attributes
pop ds ; restore ds
mov orvideo,80h ; set the video to preserve memory
jmp dosettext ; (else more than we saved gets cleared)
setfortextegavga:
sub ax,ax ; set bank just in case
call far ptr newbank
mov ax,8eh ; switch to a mode with known mapping
cmp videoax,0fh ; coming from ega 640x350x2?
jne sftknownmode ; nope
mov ax,8fh ; yup, stay in it but do the set mode
sftknownmode:
int 10h ; set the safe mode
mov ax,0 ; disable the video (I think)
call disablevideo ; ...
mov ax,0a000h ; video mem address
mov ds,ax ; set ds to video mem
xor di,di ; to offset 0 in save area
;; mov cx,0 ; set to plane 0
;; call select_vga_plane ; ...
;; mov cx,0800h ; save 2k words
;; xor si,si ; from offset 0 in vid mem
;; rep movsw ; save plane 0 2k bytes (char values)
mov cx,2 ; set to plane 2
call select_vga_plane ; ...
mov cx,1000h ; save 4k words
xor si,si ; from offset 0 in vid mem
rep movsw ; save plane 2 8k bytes (font)
;; mov cx,1 ; set to plane 1
;; call select_vga_plane ; ...
;; mov cx,0800h ; save 2k words
;; xor si,si ; from offset 0 in vid mem
;; rep movsw ; save plane 1 2k bytes (attributes)
;; push ds ; now zap attributes to zero to
;; pop es ; avoid flicker in the next stages
;; xor di,di ; ...
;; xor ax,ax ; ...
;; mov cx,0400h ; ...
;; rep stosw ; ...
pop ds ; restore ds
mov orvideo,80h ; set the video to preserve memory
mov ax,3 ; set up the text call
mov bx,0 ; ...
mov cx,0 ; ...
mov dx,0 ; ...
call setvideo ; set the video
push ds ; save ds
mov ax,extraseg ; set ES == Extra Segment
add ax,1000h ; (plus 64K)
mov es,ax ; ...
mov ax,textaddr
mov ds,ax
cld
xor si,si
mov di,2000h ; past the saved font info
mov cx,0800h ; 2k words (text & attrs)
rep movsw ; save them
pop ds
jmp setfortextreturn
setfordummytext: ; use 640x200x2 simulated text mode
mov ax,0 ; disable the video (I think)
call disablevideo ; ...
mov orvideo,80h ; set the video to preserve memory
mov ax,6 ; set up the text call
mov bx,0 ; ...
mov cx,0 ; ...
mov dx,0 ; ...
call setvideo ; set the video
mov ax,0 ; disable the video (I think)
call disablevideo ; ...
cld ; clear the direction flag
mov ax,extraseg ; set ES == Extra Segment
add ax,1000h ; (plus 64K)
mov es,ax ; ...
mov di,4000h ; save the video data here
mov ax,0b800h ; video data starts here
push ds ; save DS for a tad
mov ds,ax ; reset DS
mov si,0 ; ...
mov cx,4000 ; save this many words
rep movsw ; save them.
mov si,2000h ; ...
mov cx,4000 ; save this many words
rep movsw ; save them.
pop ds ; restore DS
mov ax,0b800h ; clear the video buffer
mov es,ax ; ...
mov di,0 ; ...
mov ax,0 ; to blanks
mov cx,4000 ; this many blanks
rep stosw ; do it.
mov di,2000h ; ...
mov cx,4000 ; this many blanks
rep stosw ; do it.
mov ax,20h ; enable the video (I think)
call disablevideo ; ...
mov bx,23 ; set mode 6 fgrd to grey
mov cx,2a2ah ; register 23, rgb white
mov dh,2ah ; ...
mov ax,1010h ; int 10 10-10 affects mcga,vga
int 10h ; ...
mov ax,cs ; do it again, another way
mov es,ax ; ...
mov dx,offset monocolors ; ...
mov ax,1002h ; int 10 10-02 handles pcjr,ega,vga
int 10h ; ...
setfortextreturn:
call far ptr setclear ; clear and home the cursor
pop bp
ret
setfortext endp
setforgraphics proc uses es si di
push bp ; save it around the int 10s
mov setting_text,0
cmp dotmode, 12 ;check for 8514
jne gnot8514
cmp f85flag, 0
jne go_graphicsreturn
cmp ai_8514, 0 ;check afi flag JCO 4/11/92
jne reopenafi
call far ptr reopen8514hw ;use registers
jmp reopen85done
reopenafi:
call far ptr reopen8514 ;use afi
reopen85done:
mov f85flag, 1
go_graphicsreturn:
jmp setforgraphicsreturn
gnot8514:
cmp dotmode,9 ; Targa?
jne gnottarga ; nope
call far ptr ReopenTGA
jmp short go_graphicsreturn
gnottarga:
cmp dotmode,14 ; check for Tandy 1000 specific modes
je setforgraphicscga ; yup
cmp videoax,0 ; check for CGA modes
je setforgraphicsnocga_x ; not this one
cmp dotmode,10 ; Hercules?
je setforgraphicscga ; yup
cmp videoax,7 ; vid mode <=7?
jbe setforgraphicscga ; CGA mode
setforgraphicsnocga_x:
jmp setforgraphicsnocga
setforgraphicscga:
cmp dotmode,10 ; Hercules?
jne tnotHGC2 ; (nope. dull-normal stuff)
call hgcstart ; Initialize the HGC card
mov HGCflag,1 ; flag "HGC-end" needed.
jmp short twasHGC2 ; bypass the normal setvideo call
tnotHGC2:
cmp dotmode,14 ; Tandy?
jne tnottandy1 ; nope
mov orvideo,80h ; set the video to preserve memory
tnottandy1:
mov ax,videoax ; set up the video call
mov bx,videobx ; ...
mov cx,videocx ; ...
mov dx,videodx ; ...
call setvideo ; do it.
twasHGC2:
mov bx,extraseg ; restore is from Extraseg
add bx,1000h ; (plus 64K)
mov si,4000h ; video data is saved here
mov ax,0b800h ; restore the video area
mov di,0 ; ...
cmp videoax,3 ; from mode 3?
jne setforgraphicscga2 ; nope
cmp mode7text,0 ; egamono/hgc?
je setforgraphicscga2 ; nope
mov ax,0b000h ; video data starts here
setforgraphicscga2:
mov cx,2000h ; restore this many words
cmp dotmode,10 ; Hercules?
jne setforgraphicscganoherc ; nope
mov si,0 ; (restore 32K)
mov ax,0b000h ; (to here)
mov cx,4000h ; (restore this many words)
setforgraphicscganoherc:
cmp dotmode,14 ; check for Tandy 1000 specific modes
jne tnottandy2 ; ..
mov ax,tandyseg ; video data starts here
mov di,tandyofs ; save video data here
mov si,0 ; video data is saved here
mov cx,4000h ; save this many words
tnottandy2:
push ds ; save DX for a tad
mov es,ax ; load the dest seg into ES
mov ds,bx ; restore it from the source seg
cld ; clear the direction flag
rep movsw ; restore them.
pop ds ; restore DS
jmp setforgraphicsreturn
setforgraphicsnocga:
mov ax,0 ; disable the video (I think)
call disablevideo ; ...
cld ; clear the direction flag
mov ax,textsafe2 ; videotable override?
cmp ax,0 ; ...
jne setforgraphicssafe ; yup
mov ax,textsafe ; nope, use general setting
setforgraphicssafe:
cmp ax,2 ; textsafe=no?
jne setforgraphicsnocga2
jmp setfordummygraphics ; yup, 640x200x2
setforgraphicsnocga2:
; must be ega, mcga, or vga, else we'd have set textsafe=no in runup
3010 cmp ax,4 ; textsafe=save?
3011 jne setforgraphicsnocga3 ; nope
3012 ;; pb, always clear video here:
3013 ;; need if for ega/vga with < 16 colors to clear unused planes
3014 ;; and, some bios's don't implement ah or'd with 80h?!?, dodge their bugs
;; cmp dotmode,2 ; ega/vga, <=16 colors?
;; jne setfgncfast ; nope
;; cmp colors,16 ; < 16 colors?
;; jae setfgncfast ; nope
;; jmp short setfgncsetvid ; special, need unused planes clear
;;setfgncfast:
;; mov orvideo,80h ; preserve memory (just to be fast)
;;setfgncsetvid:
mov orvideo,00h ; JRS ; preserve memory (just to be fast)
mov ax,videoax ; set up the video call
mov bx,videobx ; ...
mov cx,videocx ; ...
mov dx,videodx ; ...
call setvideo ; do it.
sub ax,ax ; disable the video (I think)
call disablevideo ; ...
call far ptr restoregraphics ; C rtn which uses swapsetup
call swapvga_reset ; some cleanup for swapvga case
mov ax,20h ; enable the video (I think)
call disablevideo ; ...
jmp setforgraphicsreturn
setforgraphicsnocga3:
push ds ; save ds
mov ax,0a000h ; set es to video mem
mov es,ax ; ...
cmp video_type,4 ; mcga?
jne setforgraphicsegavga ; nope
mov ax,extraseg ; set DS == Extra Segment
add ax,1000h ; (plus 64K)
mov ds,ax ; ...
xor si,si ; from save offset 0
xor di,di ; to vid offset 0
mov cx,1000h ; restore 4k words
rep movsw ; font info
mov di,8000h ; to vid offset 8000h
mov cx,0800h ; restore 2k words
rep movsw ; characters and attributes
jmp short setforgraphicsdoit
setforgraphicsegavga:
;; mov cx,0 ; set to plane 0
;; call select_vga_plane ; ...
;; mov ax,extraseg ; set DS == Extra Segment
;; add ax,1000h ; (plus 64K)
;; mov ds,ax ; ...
;; mov cx,0800h ; restore 2k words
;; xor si,si ; from offset 0 in save area
;; xor di,di ; to offset 0 in vid mem
;; rep movsw ; restore plane 0 2k bytes (char values)
mov ax,textaddr
mov es,ax
mov ax,extraseg ; set DS == Extra Segment
add ax,1000h ; (plus 64K)
mov ds,ax ; ...
cld
xor di,di
mov si,2000h ; past the saved font info
mov cx,0800h ; 2k words (text & attrs)
rep movsw ; restore them
pop ds
mov ax,8eh ; switch to a mode with known mapping
cmp videoax,0fh ; returning to ega 640x350x2?
jne sfgnotega ; nope
mov ax,8fh ; yup, go directly to it
sfgnotega:
int 10h ; set the safe mode
mov ax,0 ; disable the video (I think)
call disablevideo ; ...
mov cx,2 ; set to plane 2
call select_vga_plane ; ...
push ds
mov ax,0a000h ; set es to video mem
mov es,ax ; ...
mov ax,extraseg ; set DS == Extra Segment
add ax,1000h ; (plus 64K)
mov ds,ax ; ...
mov cx,1000h ; restore 4k words
xor di,di ; to offset 0 in vid mem
xor si,si ; from offset 0 in extraseg
rep movsw ; restore plane 2 8k bytes (font)
;; mov cx,1 ; set to plane 1
;; call select_vga_plane ; ...
;; mov cx,0800h ; restore 2k words
;; xor di,di ; to offset 0 in vid mem
;; rep movsw ; restore plane 1 2k bytes (attributes)
jmp short setforgraphicsdoit
setfordummygraphics:
push ds ; save ds
mov ax,0b800h ; restore the video area
mov es,ax ; ES == video addr
mov di,0 ; ...
mov ax,extraseg ; ...
add ax,1000h ; (plus 64K)
mov ds,ax ; ...
mov si,4000h ; video data is saved here
mov cx,4000 ; restore this many words
rep movsw ; restore them.
mov di,2000h
mov cx,4000 ; restore this many words
rep movsw ; restore them.
setforgraphicsdoit:
pop ds ; restore DS
cmp bios_vidsave,0 ; did setfortext use bios state save?
je setforgraphicssetvid ; nope
mov ax,cs ; ptr to save buffer
mov es,ax ; ...
mov bx,offset bios_savebuf ; ...
mov ax,1c02h ; restore state
mov cx,3 ; hardware + bios
int 10h ; ...
jmp short setforgraphicsreturn
setforgraphicssetvid:
mov orvideo,80h ; set the video to preserve memory
mov ax,videoax ; set up the video call
mov bx,videobx ; ...
mov cx,videocx ; ...
mov dx,videodx ; ...
call setvideo ; do it.
mov ax,20h ; enable the video (I think)
call disablevideo ; ...
setforgraphicsreturn:
mov curbk,0ffffh ; stuff impossible value into cur-bank
mov ax,1 ; set up call to spindac(0,1)
push ax ; ...
mov ax,0 ; ...
push ax ; ...
call far ptr spindac ; do it.
pop ax ; restore the registers
pop ax ; ...
pop bp
ret
setforgraphics endp
; swapxxx routines: indirect call via swapsetup, used by savegraphics
; and restoregraphics
swap256 proc uses es si di ; simple linear banks version
mov ax,word ptr swapoffset+2; high word of offset is bank
call far ptr newbank ; map in the bank
mov ax,0a000h ; high word of vid addr
mov word ptr swapvidbuf+2,ax; store it
mov ax,word ptr swapoffset ; offset in bank
mov word ptr swapvidbuf,ax ; store as low word of vid addr
neg ax ; 65536-offset
jz swap256ret ; offset 0
cmp ax,swaplength ; rest of bank smaller than req length?
jae swap256ret ; nope
mov swaplength,ax ; yup, reduce length to what's available
3015 swap256ret:
3016 ret
3017 swap256 endp
3018
3019 swapvga proc uses es si di ; 4 (or less) planes version
3020 xor si,si ; this will be plane number
3021 mov ax,word ptr swaptotlen ; dx,ax = total length
3022 mov dx,word ptr swaptotlen+2
3023 mov cx,word ptr swapoffset ; bx,cx = offset
3024 mov bx,word ptr swapoffset+2
3025 cmp colors,4 ; 4 or 2 color mode?
3026 jle swapvga_2 ; yup, no plane 2/3
3027 shr dx,1 ; 1/2 of total
3028 rcr ax,1 ; ...
3029 cmp dx,bx ; 1/2 total <= offset?
3030 jb swapvga_1 ; yup
3031 ja swapvga_2 ; nope
3032 cmp ax,cx ; ...
3033 ja swapvga_2 ; nope
3034 swapvga_1:
3035 mov si,2 ; plane 2
3036 sub cx,ax ; subtract 1/2 total from offset
3037 sbb bx,dx ; ...
3038 swapvga_2:
3039 cmp colors,2 ; 2 color mode?
3040 jle swapvga_4 ; yup, just plane 0
3041 shr dx,1 ; 1/4 of total (or 1/2 if 4 colors)
3042 rcr ax,1 ; ...
3043 cmp dx,bx ; 1/4 total <= remaining offset?
3044 jb swapvga_3 ; yup
3045 ja swapvga_4 ; nope
3046 cmp ax,cx ; ...
3047 ja swapvga_4 ; nope
3048 swapvga_3:
3049 inc si ; plane 1 or 3
3050 sub cx,ax ; subtract 1/4 total from offset
3051 sbb bx,dx ; ...
3052 swapvga_4:
3053 mov di,0 ; bank size (65536 actually)
3054 cmp bx,dx ; in last bank?
3055 jne swapvga_5 ; nope
3056 mov di,ax ; yup, note its size
3057 swapvga_5:
3058 mov ax,0a000h ; high word of vid addr
3059 mov word ptr swapvidbuf+2,ax; store it
3060 mov word ptr swapvidbuf,cx ; low word of vid addr (offset in bank)
3061 sub di,cx ; bank size - offset
3062 je swapvga_6 ; 0 implies bank = 65536
3063 cmp di,swaplength ; rest of bank smaller than req length?
3064 jae swapvga_6 ; nope
3065 mov swaplength,di ; yup, reduce length to what's available
swapvga_6:
push si ; remember plane
mov ax,bx ; top word of offset is bank
call far ptr newbank ; map in the bank
mov dx,03ceh ; graphics controller address
pop cx ; plane
mov ah,cl ; ...
mov al,04h ; set up controller address register
out dx,ax ; map the plane into memory for reads
mov ax,0001h ; set/reset enable - all bits processor
out dx,ax ; ...
mov ax,0ff08h ; bit mask - all bits processor
out dx,ax ; ...
mov dx,03c4h ; sequencer address
mov ah,1 ; 1 << plane number
shl ah,cl ; ...
mov al,02h ; sequencer plane write enable register
out dx,ax ; enable just this plane for writing
ret
swapvga endp
swapvga_reset proc near
cmp word ptr swapsetup,offset swapvga; swapvga being used?
jne swapvga_reset_ret
mov ax,0f02h ; write enable register, all planes
mov dx,03c4h ; sequencer address
out dx,ax
swapvga_reset_ret:
ret
swapvga_reset endp
swapnormread proc uses es si di ; the SLOW version
local xdot:word,ydot:word,bytesleft:word,bits:word,bitctr:word
local savebyte:byte
mov ax,swaplength ; bytes to save
mov bytesleft,ax ; ...
mov bits,8 ; bits/pixel
mov bx,word ptr swapoffset ; pixel offset to save
mov cx,word ptr swapoffset+2
mov ax,colors ; colors
swapnorm_bits:
cmp ax,256 ; accounted for 8 bits yet?
jae swapnorm_gotbits ; yup
shr bits,1 ; nope, halve the bits/pixel
shl bx,1 ; double the pixel offset
rcl cx,1 ; ...
mul ax ; square colors accounted for
jmp short swapnorm_bits ; check if enough yet
swapnorm_gotbits:
mov ax,bx ; pixel offset now in dx:ax
mov dx,cx ; ...
div sxdots ; translate pixel offset to row/col
mov ydot,ax ; ...
mov xdot,dx ; ...
mov ax,extraseg ; Extra Segment
add ax,1000h ; plus 64K
mov word ptr swapvidbuf+2,ax; temp buffer to return to caller
mov word ptr swapvidbuf,0 ; ...
mov word ptr tmpbufptr+2,ax ; running ptr for building buffer
mov word ptr tmpbufptr,0 ; ...
mov bitctr,0
swapnorm_loop:
mov ax,0a000h ; EGA, VGA, MCGA starts here
mov es,ax ; for dotread
mov cx,xdot ; load up the registers
mov dx,ydot ; for the video routine
call dotread ; read the dot via the approved method
mov cx,bits ; bits per pixel
cmp cx,8 ; 1 byte per pixel?
je swapnorm_store ; yup, go store a byte
add bitctr,cx ; nope, add how many we're storing
3066 mov bl,savebyte ; load the byte being built
3067 swapnorm_shift:
3068 shr al,1 ; shift pixel into byte
3069 rcr bl,1 ; ...
3070 loop swapnorm_shift ; for number of bits/pixel
3071 mov savebyte,bl ; save byte we're building
cmp bitctr,8 ; filled a byte yet?
jb swapnorm_nxt ; nope
mov al,bl ; yup, set up to store
mov bitctr,0 ; clear counter for next time
swapnorm_store:
les di,tmpbufptr ; buffer pointer
stosb ; store byte
dec bytesleft ; finished?
jz swapnorm_ret ; yup
mov word ptr tmpbufptr,di ; store incremented buffer pointer
swapnorm_nxt:
inc xdot ; for next dotread call
mov ax,xdot ; past row length?
cmp ax,sxdots ; ...
jb swapnorm_loop ; nope, go for next pixel
inc ydot ; yup, increment row
mov xdot,0 ; and reset column
jmp short swapnorm_loop ; go for next pixel
swapnorm_ret:
ret
swapnormread endp
swapnormwrite proc uses es si di ; the SLOW way
local xdot:word,ydot:word,bytesleft:word,bits:word,bitctr:word
local savebyte:byte
mov ax,swaplength ; bytes to restore
inc ax ; +1
mov bytesleft,ax ; save it
mov bits,8 ; bits/pixel
mov bx,word ptr swapoffset ; pixel offset to restore
mov cx,word ptr swapoffset+2; ...
mov ax,colors ; colors
swapnormw_bits:
cmp ax,256 ; accounted for 8 bits yet?
jae swapnormw_gotbits ; yup
shr bits,1 ; nope, halve the bits/pixel
shl bx,1 ; double the pixel offset
rcl cx,1 ; ...
mul ax ; square colors accounted for
jmp short swapnormw_bits ; check if enough yet
swapnormw_gotbits:
mov ax,bx ; pixel offset now in dx:ax
mov dx,cx ; ...
div sxdots ; translate pixel offset to row/col
mov ydot,ax ; ...
mov xdot,dx ; ...
mov dx,word ptr swapvidbuf+2; temp buffer from caller
mov ax,word ptr swapvidbuf ; ...
mov word ptr tmpbufptr+2,dx ; running ptr in buffer
mov word ptr tmpbufptr,ax ; ...
mov bitctr,0
swapnormw_loop:
mov cx,bits ; bits per pixel
sub bitctr,cx ; subtract a pixel from counter
jg swapnormw_extract ; got some left in savebyte
dec bytesleft ; all done?
jz swapnormw_ret ; yup
les si,tmpbufptr ; buffer pointer
mov dl,es:[si] ; next byte
inc word ptr tmpbufptr ; incr buffer pointer for next time
mov bitctr,8 ; reset unused bit count
cmp cx,8 ; 1 byte/pixel?
je swapnormw_store ; yup, go the fast way
mov bl,dl ; byte to extract from
jmp short swapnormw_extract2
swapnormw_extract:
mov bl,savebyte ; byte with bits left to use
mov dl,bl ; current pixel in bottom n bits
swapnormw_extract2:
shr bl,1 ; for next time
loop swapnormw_extract2 ; for bits per pixel
mov savebyte,bl ; save remaining bits
swapnormw_store:
mov ax,0a000h ; EGA, VGA, MCGA starts here
mov es,ax ; for dotread
mov al,dl ; color to write
and ax,andcolor ; ...
mov cx,xdot ; load up the registers
mov dx,ydot ; for the video routine
call dotwrite ; write the dot via the approved method
inc xdot ; for next dotread call
mov ax,xdot ; past row length?
cmp ax,sxdots ; ...
jb swapnormw_loop ; nope, go for next pixel
inc ydot ; yup, increment row
mov xdot,0 ; and reset column
jmp short swapnormw_loop ; go for next pixel
swapnormw_ret:
ret
swapnormwrite endp
; far move routine for savegraphics/restoregraphics
movewords proc uses es di si, len:word, fromptr:dword, toptr:dword
push ds ; save DS
mov cx,len ; words to move
les di,toptr ; destination buffer
lds si,fromptr ; source buffer
cld ; direction=forward
rep movsw ; do it.
pop ds ; restore DS
ret ; we done.
movewords endp
; clear text screen
setclear proc uses es si di ; clear the screen after setfortext
call far ptr home ; home the cursor
mov ax,textaddr
mov es,ax
xor di,di
cmp text_type,0 ; real text mode?
jne setcbw ; nope
mov ax,0720h ; blank with white attribute
mov cx,2000 ; 80x25
rep stosw ; clear it
jmp short setcdone
setcbw: xor ax,ax ; graphics text
mov cx,4000 ; 640x200x2 / 8
rep stosw ; clear it
mov di,2000h ; second part
mov cx,4000
rep stosw ; clear it
setcdone:
xor ax,ax ; zero
mov textrbase,ax ; clear this
mov textcbase,ax ; and this
ret ; we done.
setclear endp
disablevideo proc near ; wierd video trick to disable/enable
push dx ; save some registers
push ax ; ...
mov dx,03bah ; set attribute comtroller flip-flop
in al,dx ; regardless of video mode
mov dx,03dah ; ...
in al,dx ; ...
mov dx,03c0h ; attribute controller address
pop ax ; 00h = disable, 20h = enable
out dx,al ; trust me.
pop dx ; restore DX and we done.
ret
disablevideo endp
; ************** Function findfont(n) ******************************
; findfont(0) returns far pointer to 8x8 font table if it can
; find it, NULL otherwise;
; nonzero parameter reserved for future use
findfont proc uses es si di, fontparm:word
mov ax,fontparm ; to quiet warning
mov ax,01130h ; func 11, subfunc 30
mov bh,03h ; 8x8 font, bottom 128 chars
sub cx,cx ; so we can tell if anything happens
int 10h ; ask bios
sub ax,ax ; default return, NULL
sub dx,dx ; ...
or cx,cx ; did he set cx?
jz findfontret ; nope, return with NULL
mov dx,es ; yup, return far pointer
mov ax,bp ; ...
findfontret:
ret ; note that "uses" gets bp reset here
findfont endp
; **************** Function home() ********************************
; Home the cursor (called before printfs)
home proc
mov ax,0200h ; force the cursor
mov bx,0 ; in page 0
mov dx,0 ; to the home position
mov textrow,dx ; update our local values
mov textcol,dx ; ...
push bp ; some BIOS's don't save this
int 10h ; do it.
pop bp ; restore the saved register
ret
home endp
; **************** Function movecursor(row, col) **********************
; Move the cursor (called before printfs)
movecursor proc row:word, col:word
mov ax,row ; row specified?
cmp ax,-1 ; ...
je mccol ; nope, inherit it
mov textrow,ax ; yup, store it
mccol: mov ax,col ; col specified?
cmp ax,-1 ; ...
je mcdoit ; nope, inherit it
mov textcol,ax ; yup, store it
mcdoit: mov ax,0200h ; force the cursor
mov bx,0 ; in page 0
mov dh,byte ptr textrow ; move to this row
add dh,byte ptr textrbase ; ...
mov dl,byte ptr textcol ; move to this column
add dl,byte ptr textcbase ; ...
push bp ; some BIOS's don't save this
int 10h ; do it.
pop bp ; restore the saved register
ret
movecursor endp
; **************** Function keycursor(row, col) **********************
; Subroutine to wait cx ticks, or till keystroke pending
tickwait proc
FRAME ; std stack frame for TC++ overlays
tickloop1:
push cx ; save loop ctr
sub ax,ax ; set ES to BIOS data area
mov es,ax ; ...
mov bx,es:046ch ; obtain the current timer value
push bx
call far ptr keypressed ; check if keystroke pending
pop bx
pop cx ; restore loop ctr
cmp ax,0 ; keystroke?
jne tickret ; yup, return
tickloop2:
cmp bx,es:046ch ; a new clock tick started yet?
je tickloop2 ; nope
loop tickloop1 ; wait another tick?
xor ax,ax ; nope, exit no key, ticks done
tickret:
UNFRAME ; pop stack frame
ret
tickwait endp
; Show cursor, wait for a key, disable cursor, return key
keycursor proc uses es si di, row:word, col:word
mov cursortyp,0607h ; default cursor
mov ax,row ; row specified?
cmp ax,-1 ; ...
je ckcol ; nope, inherit it
test ax,08000h ; top bit on?
je ckrow ; nope
and ax,07fffh ; yup, clear it
mov cursortyp,0507h ; and use a bigger cursor
ckrow: mov textrow,ax ; store row
ckcol: mov ax,col ; col specified?
cmp ax,-1 ; ...
je ckmode ; nope, inherit it
mov textcol,ax ; yup, store it
ckmode: cmp text_type,1 ; are we in 640x200x2 mode?
jne ck_text ; nope. do it the easy way
ck_bwloop: ; 640x200x2 cursor loop
mov cx,3 ; wait 3 ticks for keystroke
call far ptr tickwait ; ...
cmp ax,0 ; got a keystroke?
je ckwait ; nope
jmp ck_get ; yup, fetch it and return
ckwait: mov ax,320 ; offset in vid mem of top row 1st byte:
mov bx,textrow ; row
add bx,textrbase ; ...
mul bx ; row*320 + col
add ax,textcol ; ...
add ax,textcbase ; ...
mov di,ax ; ...
mov ax,0b800h ; set es to vid memory
mov es,ax ; ...
mov ah,byte ptr es:00f0h[di]; row 6 of character
mov al,byte ptr es:20f0h[di]; row 7 of character
push ax ; save them
mov cx,8 ; count on bits in orig value
xor bx,bx ; ...
ckbits: shl al,1 ; ...
adc bx,0 ; ...
loop ckbits ; ...
mov al,0 ; black cursor
cmp bx,4 ; >= 4 on bits in orig value?
jge ckbwgo ; yup, use black cursor
not al ; nope, use white cursor
ckbwgo: mov byte ptr es:20f0h[di],al; turn on cursor, row 7
cmp cursortyp,0607h ; small cursor?
je ckbwwt ; yup
mov byte ptr es:00f0h[di],al; nope, turn on cursor row 6
ckbwwt: mov cx,3 ; wait 3 ticks for keystroke
call far ptr tickwait ; ...
pop bx ; saved orig value
mov byte ptr es:00f0h[di],bh; turn off cursor, row 6
mov byte ptr es:20f0h[di],bl; turn off cursor, row 7
cmp ax,0 ; got a keystroke?
jne ck_get ; yup, fetch it and return
jmp short ck_bwloop ; and keep waiting
ck_text:
cmp text_type,0 ; real text mode?
jne ckgetw ; nope, no cursor at all
push bp ; some bios's don't save this
mov ah,1 ; set cursor type
mov cx,cursortyp ; ...
int 10h ; ...
mov ah,02 ; move cursor
xor bx,bx ; page
mov dh,byte ptr textrow ; row
add dh,byte ptr textrbase ; ...
mov dl,byte ptr textcol ; col
add dh,byte ptr textcbase ; ...
int 10h ; ...
pop bp
ckgetw: call far ptr keypressed ; not getakey, help/tab mey be enabled
cmp ax,0 ; key available?
je ckgetw ; nope, keep waiting
ck_get: call far ptr getakey ; get the keystroke
cmp text_type,0 ; real text mode?
jne ck_ret ; nope, done
push bp ; some bios's don't save this
push ax ; save it
mov ah,1 ; make cursor normal size
mov cx,0607h ; ...
int 10h ; ...
mov ah,02 ; move cursor
xor bx,bx ; page
mov dx,1950h ; off the display
int 10h ; ...
pop ax ; keystroke value
pop bp
ck_ret:
ret
keycursor endp
; ************* Function scrollup(toprow, botrow) ******************
; Scroll the screen up (from toprow to botrow)
scrollup proc uses es, toprow:word, botrow:word
mov ax,0601h ; scroll up one line
mov bx,0700h ; new line is black
mov cx,toprow ; this row,
mov ch,cl ; ...
mov cl,0 ; first column
mov dx,botrow ; to this row,
mov dh,dl ; ...
mov dl,79 ; last column
push bp ; some BIOS's don't save this
int 10h ; do it.
pop bp ; restore the saved register
ret ; we done.
scrollup endp
; ************* Function scrolldown(toprow, botrow) ******************
; Scroll the screen down (from toprow to botrow)
scrolldown proc uses es, toprow:word, botrow:word
mov ax,0701h ; scroll down one line
mov bx,0700h ; new line is black
mov cx,toprow ; this row,
mov ch,cl ; ...
mov cl,0 ; first column
mov dx,botrow ; to this row,
mov dh,dl ; ...
mov dl,79 ; last column
push bp ; some BIOS's don't save this
int 10h ; do it.
pop bp ; restore the saved register
ret ; we done.
scrolldown endp
; **************** Function getcolor(xdot, ydot) *******************
; Return the color on the screen at the (xdot,ydot) point
getcolor proc uses di si es, xdot:word, ydot:word
mov ax,0a000h ; EGA, VGA, MCGA starts here
mov es,ax ; save it here during this routine
mov cx,xdot ; load up the registers
mov dx,ydot ; for the video routine
add cx,sxoffs ; ...
add dx,syoffs ; ...
call dotread ; read the dot via the approved method
mov ah,0 ; clear the high-order bits
ret ; we done.
getcolor endp
; ********* Function gettruecolor(xdot, ydot, &red, &green, &blue) **************
; Return the color on the screen at the (xdot,ydot) point
; gettruecolor ---------------------------------------------------------------
; * this is just version of VESAtrueread, so the changes are identical
; ------------------------------------------------------------30/06/2002/ChCh-
gettruecolor proc uses es, xdot:word, ydot:word, red:ptr word, green:ptr word, blue:ptr word
cmp istruecolor,1 ; are we in a truecolor mode?
je overdone
jmp wedone
overdone:
mov cx,xdot ; load up the registers
mov dx,ydot ; for the video routine
add cx,sxoffs ; add window offsets
add dx,syoffs ; (dotwrite does this for VESAtrueread)
call VESAtrueaddr ; calculate address and switch banks
mov ax,vesa_winaseg ; VESA video starts here
cmp vesa_bitsppixel,17
mov es,ax
jge over_hi
mov ax,word ptr es:[bx] ; read two bytes
mov cl,3
mov dx,ax
shl ax,cl
mov cl,vesa_redpos
shr al,1
shr dx,cl
shr al,1 ; blue in al
cmp vesa_greensize,6
je got_6g
shl ah,1
got_6g:
shl dx,1 ; red in dl
and ah,111111b ; green in ah
jmp short give_out
over_hi: ; 8-8-8 or 8-8-8-8?
inc bx ; does a word fit to this bank?
jz badbank1 ; no, switch one byte after
mov ax,word ptr es:[bx-1] ; else read that word
inc bx ; bank-end?
jz badbank2 ; yes, switch it
mov dl,es:[bx] ; else read the third byte
jmp short colors_in
badbank1:
dec bx ; bx=0ffffh
mov al,es:[bx] ; read the first byte
badbank2:
inc dx ; next bank needed
push ax
mov ax,dx ; newbank expects bank in ax
call far ptr newbank
pop ax
mov dl,es:[0] ; read next color
inc bx ; badbank1 or badbank2?
jnz colors_in ; badbank2 - nothing more to do
mov ah,dl
mov dl,es:[1] ; badbank1 - read the last byte
colors_in:
cmp vesa_redpos,0
jne layout_ok
xchg al,dl
layout_ok:
mov cl,2
xor dh,dh
and ax,0FCFCh ; mask-out 2 g & 2 b lsbs for shift
shr dx,cl
shr ax,cl
give_out: ; both for hi- & true- color,
mov bx,red
mov [bx],dx ; return red
mov bx,green
mov dl,ah
mov [bx],dx ; return green
mov bx,blue
mov dl,al
mov [bx],dx ; return blue
wedone:
ret ; we done.
gettruecolor endp
; Fastcall version, called when C programs are compiled by MSC 6.00A:
@getcolor proc FORTRAN ; ax=xdot, dx=ydot
push si ; preserve these
push di ; ...
mov cx,ax ; load up the registers
add cx,sxoffs ; ...
add dx,syoffs ; ...
mov ax,0a000h ; EGA, VGA, MCGA starts here
mov es,ax ; ...
call dotread ; read the dot via the approved method
xor ah,ah ; clear the high-order bits
pop di ; restore
pop si ; ...
ret ; we done.
@getcolor endp
; ************** Function putcolor_a(xdot, ydot, color) *******************
; write the color on the screen at the (xdot,ydot) point
putcolor_a proc uses di si es, xdot:word, ydot:word, xcolor:word
mov ax,0a000h ; EGA, VGA, MCGA starts here
mov es,ax ; save it here during this routine
mov cx,xdot ; load up the registers
mov dx,ydot ; for the video routine
add cx,sxoffs ; ...
add dx,syoffs ; ...
mov ax,xcolor ; ...
and ax,andcolor ; (ensure that 'color' is in the range)
call dotwrite ; write the dot via the approved method
;;; call videocleanup ; perform any video cleanup required
ret ; we done.
putcolor_a endp
; ******* Function puttruecolor(xdot, ydot, red, green, blue) *************
; write the color on the screen at the (xdot,ydot) point
; puttruecolor ---------------------------------------------------------------
; * this is just version of VESAtruewrite, so the changes are identical
; ------------------------------------------------------------30-06-2002-ChCh-
puttruecolor proc uses es, xdot:word, ydot:word, red:word, green:word, blue:word
cmp istruecolor,1 ; are we in a truecolor mode?
je overdone
jmp wedone
overdone:
mov cx,xdot ; load up the registers
mov dx,ydot ; for the video routine
add cx,sxoffs ; add window offsets
add dx,syoffs ; (dotwrite does this for VESAtruewrite)
call VESAtrueaddr ; calculate address and switch banks
mov ax,vesa_winaseg
cmp vesa_bitsppixel,17 ; 8-8-8 and 8-8-8-8
mov es,ax
jge over_hi
push bx
mov cx,111111b ; mask - possibly a public variable
mov dx,green
mov bx,red
mov ax,blue
and dx,cx
and bx,cx
and ax,cx
mov cl,vesa_redpos
cmp vesa_greensize,6 ; 5-5-5 or 5-6-5
je got_6g
shr dx,1
got_6g:
shr bx,1
shr ax,1
shl bx,cl
mov cl,vesa_greenpos
or ax,bx ; r-_-b
shl dx,cl
pop bx
or ax,dx ; r-g-b
mov word ptr es:[bx],ax ; write two bytes for the dot
jmp short wedone
over_hi:
mov al,byte ptr blue ; 8-8-8 (and 8-8-8-8) style
mov cx,red
mov ah,byte ptr green
shl cx,1 ; well, 6-6-6 is not true-true
shl ax,1
shl cx,1
shl ax,1
cmp vesa_redpos,0 ; common b-g-r model?
jne doit_slow
xchg al,cl ; else turn to unusual r-g-b
doit_slow:
inc bx ; does a word fit to the current bank?
jz badbank1 ; no, switch one byte after
mov word ptr es:[bx-1],ax ; else plot that word
push cx ; hand it over to the switch
inc bx ; bank-end?
jz badbank2 ; yes, switch it
mov es:[bx],cl ; else write the third byte
pop cx ; wasn't needed - no switching
3072 jmp short wedone
3073 badbank1:
3074 dec bx ; bx=0ffffh
3075 mov es:[bx],al ; plot the first byte
3076 xchg ah,al ; second color for badbank2
3077 push ax ; hand it over
3078 badbank2:
3079 inc dx ; next bank needed
3080 mov ax,dx ; newbank expects bank in ax
3081 call far ptr newbank
3082 pop ax ; get next color
3083 inc bx ; badbank1 or badbank2?
3084 mov es:[0],al ; plot that color
3085 jnz wedone ; badbank2 - nothing more to do
3086 mov es:[1],cl ; badbank1 - plot the last byte
3087 wedone:
3088 ret ; we done.
3089 puttruecolor endp
3090
3091 ; Fastcall version, called when C programs are compiled by MSC 6.00A:
3092
3093 @putcolor_a proc FORTRAN ; ax=xdot, dx=ydot, bx=color
3094 push si ; preserve these
3095 push di ; ...
3096 mov cx,ax ; load up the registers
3097 add cx,sxoffs ; ...
3098 add dx,syoffs ; ...
3099 mov ax,0a000h ; EGA, VGA, MCGA starts here
3100 mov es,ax ; ...
3101 mov ax,bx ; color
3102 and ax,andcolor ; ensure that 'color' is in range
3103 call dotwrite ; write the dot via the approved method
3104 ;;; call videocleanup ; perform any video cleanup required
3105 pop di ; restore
3106 pop si ; ...
3107 ret ; we done.
3108 @putcolor_a endp
3109
3110 ; ***************Function out_line(pixels,linelen) *********************
3111
3112 ; This routine is a 'line' analog of 'putcolor_a()', and sends an
3113 ; entire line of pixels to the screen (0 <= xdot < xdots) at a clip
3114 ; Called by the GIF decoder
3115
3116 out_line proc uses di si es, pixels:ptr byte, linelen:word
3117 mov cx,sxoffs ; start at left side of logical screen
3118 mov dx,rowcount ; sanity check: don't proceed
add dx,syoffs ; ...
cmp dx,sydots ; beyond the end of the screen
ja out_lineret ; ...
mov ax,0a000h ; EGA, VGA, MCGA starts here
mov es,ax ; save it here during this routine
mov ax, linelen ; last pixel column
add ax, sxoffs ; ...
dec ax ; ...
mov si,pixels ; get the color for dot 'x'
call linewrite ; mode-specific linewrite routine
inc rowcount ; next row
out_lineret:
xor ax,ax ; return 0
ret
out_line endp
; ***Function get_line(int row,int startcol,int stopcol, unsigned char *pixels) ***
; This routine is a 'line' analog of 'getcolor()', and gets a segment
; of a line from the screen and stores it in pixels[] at one byte per
; pixel
; Called by the GIF decoder
get_line proc uses di si es, row:word, startcol:word, stopcol:word, pixels:ptr byte
mov cx,startcol ; sanity check: don't proceed
3119 add cx,sxoffs ; ...
3120 cmp cx,sxdots ; beyond the right end of the screen
3121 ja get_lineret ; ...
3122 mov dx,row ; sanity check: don't proceed
add dx,syoffs ; ...
cmp dx,sydots ; beyond the bottom of the screen
ja get_lineret ; ...
mov ax, stopcol ; last pixel to read
add ax, sxoffs ; ...
mov di, pixels ; get the color for dot 'x'
call lineread ; mode-specific lineread routine
get_lineret:
xor ax,ax ; return 0
ret
get_line endp
; ***Function put_line(int row,int startcol,int stopcol, unsigned char *pixels) ***
; This routine is a 'line' analog of 'putcolor_a()', and puts a segment
; of a line from the screen and stores it in pixels[] at one byte per
; pixel
; Called by the GIF decoder
put_line proc uses di si es, row:word, startcol:word, stopcol:word, pixels:ptr byte
mov cx,startcol ; sanity check: don't proceed
3123 add cx,sxoffs ; ...
3124 cmp cx,sxdots ; beyond the right end of the screen
3125 ja put_lineret ; ...
3126 mov dx,row ; sanity check: don't proceed
add dx,syoffs ; ...
cmp dx,sydots ; beyond the bottom of the screen
ja put_lineret ; ...
mov ax,0a000h ; EGA, VGA, MCGA starts here
mov es,ax ; save it here during this routine
mov ax, stopcol ; last column
add ax, sxoffs; ; ...
cmp ax,sxdots ; beyond the right end of the screen?
ja put_lineret ; ...
mov si,pixels ; put the color for dot 'x'
call linewrite ; mode-specific linewrite routine
put_lineret:
xor ax,ax ; return 0
ret
put_line endp
;-----------------------------------------------------------------
; setattr(row, col, attr, count) where
; row, col = row and column to start printing.
; attr = color attribute.
; count = number of characters to set
; This routine works only in real color text mode.
setattr proc uses es di, row:word, col:word, attr:word, count:word
mov ax,row ; row specified?
cmp ax,-1 ; ...
je setac ; nope, inherit it
mov textrow,ax ; yup, store it
setac: mov ax,col ; col specified?
cmp ax,-1 ; ...
je setago ; nope, inherit it
mov textcol,ax ; yup, store it
setago: cmp text_type,0 ; real color text mode?
jne setax ; nope, do nothing
mov ax,textrow ; starting row
add ax,textrbase ; ...
mov cx,160 ; x 2 bytes/row (char & attr bytes)
imul cx
mov bx,textcol ; add starting column
add bx,textcbase ; ...
add ax,bx ; twice since 2 bytes/char
add ax,bx ; ...
mov di,ax ; di -> start location in Video segment
mov cx,count ; number of bytes to set
jcxz setax ; none?
mov ax,attr ; get color attributes in al
mov dx,0b800h ; set video pointer
cmp mode7text,0 ; egamono/hgc?
je setalstore ; nope
mov dx,0b000h ; mode 7 address
mov al,07h ; normal mda ttribute
cmp ah,0 ; inverse?
jge setalchkbright ; nope
mov al,70h ; yup
jmp short setalstore
setalchkbright:
test ah,40h ; bright?
jz setalstore ; nope
mov al,0Fh ; yup
setalstore:
mov es,dx ; ...
setalp: mov byte ptr es:1[di],al ; set attribute
add di,2 ; for next one
loop setalp ; do next char
setax: ret
setattr endp
;-----------------------------------------------------------------
; PUTSTR.asm puts a string directly to video display memory. Called from C by:
; putstring(row, col, attr, string) where
; row, col = row and column to start printing.
; attr = color attribute.
; string = far pointer to the null terminated string to print.
; Written for the A86 assembler (which has much less 'red tape' than MASM)
; by Bob Montgomery, Orlando, Fla. 7-11-88
; Adapted for MASM 5.1 by Tim Wegner 12-11-89
; Furthur mucked up to handle graphics
; video modes by Bert Tyler 1-07-90
; Reworked for: row,col update/inherit;
; 620x200x2 inverse video; far ptr to string;
; fix to avoid scrolling when last posn chgd;
; divider removed; newline ctl chars; PB 9-25-90
putstring proc uses es di si, row:word, col:word, attr:word, string:far ptr byte
mov ax,row ; row specified?
cmp ax,-1 ; ...
je putscol ; nope, inherit it
mov textrow,ax ; yup, store it
putscol:
mov ax,col ; col specified?
cmp ax,-1 ; ...
je putsmode ; nope, inherit it
mov textcol,ax ; yup, store it
putsmode:
les si,string ; load buffer pointer
cmp text_type,0 ; are we in color text mode?
jne short put_substring ; nope
jmp put_text ; yup
put_substring: ; graphics mode substring loop
push si ; save start pointer
push textcol ; save start column
put_loop:
mov al,byte ptr es:[si] ; get next char
cmp al,0 ; end of string?
je puts_chk_invert ; yup
cmp al,10 ; end of line?
je puts_chk_invert ; yup
push si ; save offset
push es ; save this
push bp ; and this
push ax ; and this last, needed soonest
mov ah,02h ; set up bios set cursor call
xor bh,bh ; page 0
mov dl,byte ptr textcol ; screen location
add dl,byte ptr textcbase ; ...
mov dh,byte ptr textrow ; ...
add dh,byte ptr textrbase ; ...
int 10h ; invoke the bios
pop ax ; the character to write
mov ah,09h ; set up the bios write char call
mov bx,7 ; page zero, color
mov cx,1 ; write 1 character
int 10h ; invoke the bios
pop bp ; restore
pop es ; restore
pop si ; restore
inc si ; on to the next character
inc textcol ; ...
jmp short put_loop ; ...
puts_chk_invert:
pop bx ; starting column number
pop dx ; restore start offset
cmp attr,0 ; top bit of attribute on?
jge short puts_endsubstr ; nope, nothing more to do
cmp text_type,1 ; 640x200x2 mode?
jne short puts_endsubstr ; nope, can't do anything more
3127 mov cx,si ; calc string length
3128 sub cx,dx ; ...
3129 jcxz short puts_endsubstr ; empty string?
3130 push ax ; remember terminating char
3131 push es ; and this
3132 ; make the string inverse video on display
3133 mov ax,320 ; offset in vid mem of 1st byte's top
mov di,textrow ; row*320 + col
add di,textrbase ; ...
mul di ; ...
add ax,bx ; ...
add ax,textcbase ; ...
mov di,ax ; ...
mov ax,0b800h ; set es to vid memory
mov es,ax ; ...
puts_invert:
not byte ptr es:0000h[di] ; invert the 8x8 making up a character
not byte ptr es:2000h[di]
not byte ptr es:0050h[di]
not byte ptr es:2050h[di]
not byte ptr es:00a0h[di]
not byte ptr es:20a0h[di]
not byte ptr es:00f0h[di]
not byte ptr es:20f0h[di]
inc di
loop puts_invert ; on to the next character
pop es ; restore
pop ax ; ...
puts_endsubstr:
cmp al,0 ; the very end?
je short putstring_ret ; we done.
inc si ; go past the newline char
mov textcol,0 ; do newline
inc textrow ; ...
jmp put_substring ; on to the next piece
put_text: ; text mode substring loop
mov ax,textrow ; starting row
add ax,textrbase ; ...
mov cx,160 ; x 2 bytes/row (char & attr bytes)
imul cx
mov bx,textcol ; add starting column
add bx,textcbase ; ...
add ax,bx ; twice since 2 bytes/char
add ax,bx ; ...
mov di,ax ; di -> start location in Video segment
mov ax,attr ; get color attributes in ah
cmp mode7text,0 ; egamono/hgc? (MDA)
je B0 ; nope, use color attr
mov al,07h ; default, white on blank
cmp ah,0 ; top bit of attr set?
jge mdachkbright ; nope
mov al,70h ; inverse video
jmp short B0
mdachkbright:
test ah,40h ; 2nd bit of attr set?
jz B0 ; nope
mov al,0Fh ; bright
B0: mov ah,al
B1: mov al,byte ptr es:[si] ; get a char in al
cmp al,0 ; end of string?
je putstring_ret ; yes, done
inc si ; bump for next time
cmp al,10 ; newline?
jne B2 ; nope
mov textcol,0 ; yup, do it
inc textrow ; ...
jmp short put_text ; on to the next substring
B2: push es ; No, store char & attribute
mov dx,textaddr ; ...
mov es,dx ; ...
stosw ; ...
pop es ; ...
inc textcol ; update local var
jmp short B1 ; do next char
putstring_ret:
ret
putstring endp
; **************** EGA Palette <==> VGA DAC Conversion Routines **********
; paltodac converts a 16-palette EGA value to a 256-color VGA
; value (duplicated 16 times)
; dactopal converts the first 16 VGA values to a 16-palette
; EGA value
; local routines called with register values
; BH = VGA Red Color xxRRRRRR
; BL = VGA Green Color xxGGGGGG
; CH = VGA Blue Color xxBBBBBB
; CL = EGA Palette xxrgbRGB
;
; palettetodac converts CL to BH/BL/CH
; dactopalette converte BH/BL/CH to CL
; *************************************************************************
palettetodac proc near
mov bx,0 ; initialize RGB values to 0
mov ch,0 ; ...
test cl,20h ; low-red high?
jz palettetodac1 ; nope
or bh,10h ; set it
palettetodac1:
test cl,10h ; low-green high?
jz palettetodac2 ; nope
or bl,10h ; set it
palettetodac2:
test cl,08h ; low-blue high?
jz palettetodac3 ; nope
or ch,10h ; set it
palettetodac3:
test cl,04h ; high-red high?
jz palettetodac4 ; nope
or bh,20h ; set it
palettetodac4:
test cl,02h ; high-green high?
jz palettetodac5 ; nope
or bl,20h ; set it
palettetodac5:
test cl,01h ; high-blue high?
jz palettetodac6 ; nope
or ch,20h ; set it
palettetodac6:
ret
palettetodac endp
dactopalette proc near
mov cl,0 ; initialize RGB values to 0
test bh,10h ; low-red high?
jz dactopalette1 ; nope
or cl,20h ; set it
dactopalette1:
test bl,10h ; low-green high?
jz dactopalette2 ; nope
or cl,10h ; set it
dactopalette2:
test ch,10h ; low-blue high?
jz dactopalette3 ; nope
or cl,08h ; set it
dactopalette3:
test bh,20h ; high-red high?
jz dactopalette4 ; nope
or cl,04h ; set it
dactopalette4:
test bl,20h ; high-green high?
jz dactopalette5 ; nope
or cl,02h ; set it
dactopalette5:
test ch,20h ; high-blue high?
jz dactopalette6 ; nope
or cl,01h ; set it
dactopalette6:
ret
dactopalette endp
paltodac proc uses es si di
mov si,0 ; initialize the loop values
mov di,0
paltodacloop:
mov cl,palettega[si] ; load up a single palette register
call palettetodac ; convert it to VGA colors
mov dacbox+0[di],bh ; save the red value
mov dacbox+1[di],bl ; and the green value
mov dacbox+2[di],ch ; and the blue value
inc si ; bump up the registers
add di,3 ; ...
cmp si,16 ; more to go?
jne paltodacloop ; yup.
push ds ; set ES to DS temporarily
pop es ; ...
mov ax,15 ; do this 15 times to get to 256
mov di,offset dacbox+48 ; set up the first destination
paltodacloop2:
mov cx,24 ; copy another block of 16 registers
mov si,offset dacbox ; set up for the copy
rep movsw ; do it
dec ax ; need to do another block?
jnz paltodacloop2 ; yup. do it.
ret ; we done.
paltodac endp
dactopal proc uses es si di
mov si,0 ; initialize the loop values
mov di,0
dactopalloop:
mov bh,dacbox+0[di] ; load up the VGA red value
mov bl,dacbox+1[di] ; and the green value
mov ch,dacbox+2[di] ; and the blue value
call dactopalette ; convert it to an EGA palette
mov palettega[si],cl ; save as a single palette register
inc si ; bump up the registers
add di,3 ; ...
cmp si,16 ; more to go?
jne dactopalloop ; yup.
mov cl,palettega ; copy palette 0
mov palettega+16,cl ; to the overscan register
ret ; we done.
dactopal endp
; *********************** Function loaddac() ****************************
; Function to Load the dacbox[][] array, if it can
; (sets gotrealdac to 0 if it can't, 1 if it can)
3134
3135 loaddac proc uses es
3136 cmp dotmode, 29 ; truecolor? MCP 5-29-91
3137 jne NotTPlusLoaddac
3138 mov ax,4402h
3139 push ax
3140 mov ax,256 * 3
3141 push ax
3142 xor ax,ax
3143 push ax
3144 push ds
3145 mov ax,OFFSET dacbox
3146 push ax
3147 call far ptr TPlusLUT
3148 add sp, 10
3149 or ax, ax
3150 jz NotTPlusLoaddac ; Didn't work, try a regular palette
jmp loaddacdone
NotTPlusLoaddac:
cmp dotmode,19 ; roll-your-own video mode?
jne loaddac_notyourown
call far ptr readvideopalette
cmp ax,-1 ; palette-write handled yet?
jne go_loaddacdone ; yup.
loaddac_notyourown:
mov reallyega,0 ; set flag: not an EGA posing as a VGA
cmp dotmode,9 ; TARGA 3 June 89 j mclain
je go_loaddacdone
cmp f85flag, 0
jne go_loaddacdone
cmp xga_isinmode,0 ; XGA graphics mode?
jne go_loaddacdone
cmp istruecolor,0 ; truecolor graphics mode?
jne go_loaddacdone
mov dacbox,255 ; a flag value to detect invalid DAC
cmp debugflag,16 ; pretend we're not a VGA?
3151 je loaddacdebug ; yup.
3152 push ds ; ...
3153 pop es ; ...
3154 mov ax,1017h ; get the old DAC values
3155 mov bx,0 ; (assuming, of course, they exist)
3156 mov cx,256 ; ...
3157 mov dx,offset dacbox ; ...
3158 push bp
3159 int 10h ; do it.
3160 pop bp
3161 loaddacdebug:
3162 cmp dacbox,255 ; did it work? do we have a VGA?
3163 je loaddacega ; nope, go check ega
3164 cmp colors,16 ; 16 color vga?
3165 jne go_loaddacdone ; nope, all done
3166 cld ; yup, must straighten out dacbox,
3167 push ds ; 16 color vga uses indirection thru
3168 pop es ; palette select
3169 mov si,offset dacbox+60 ; dac[20] is used for color 6 so
3170 mov di,offset dacbox+18 ; copy dacbox[20] to dacbox[6]
3171 mov cx,3 ; ...
3172 rep movsb ; ...
3173 mov si,offset dacbox+168 ; dac[56-63] are used for colors 8-15 so
3174 mov di,offset dacbox+24 ; copy dacbox[56-63] to dacbox[8-15]
3175 mov cx,24 ; ...
3176 rep movsb ; ...
3177 go_loaddacdone:
3178 jmp short loaddacdone
3179 loaddacega:
3180 cmp colors,16 ; are we using 16 or more colors?
3181 jb loaddacdone ; nope. forget it.
3182 ;; cmp sydots,350 ; 640x350 range?
3183 cmp video_type,3 ; EGA or better?
3184 jb loaddacdone ; nope. forget it.
3185 mov bx,offset palettega ; make up a dummy palette
3186 mov cx,3800h ; start with color 0 == black
3187 loaddacega1: ; and color 8 == low-white
3188 mov 0[bx],cl ; save one color
3189 mov 8[bx],ch ; and another color
3190 inc bx ; bump up the DAC
3191 add cx,0101h ; and the colors
3192 cmp cl,8 ; finished 8 colors?
3193 jne loaddacega1 ; nope. get more.
3194 mov reallyega,1 ; note that this is really an EGA
3195 call far ptr paltodac ; "convert" it to a VGA DAC
3196 mov daclearn,1 ; bypass learn mode
3197 mov ax,cyclelimit ; and spin as fast as he wants
3198 mov daccount,ax ; ...
3199 loaddacdone:
3200 cmp colors,16 ; 16 color mode?
3201 jne loaddacdone2 ; nope
3202 cld ; yup, clear the excess dacbox
3203 mov cx,360 ; entries to all zeros for editpal
3204 sub ax,ax
3205 push ds
3206 pop es
3207 mov di,offset dacbox+48
3208 rep stosw
3209 loaddacdone2:
3210 cld ; clear the top 8 entries in dacbox
3211 mov cx,12 ; bios doesn't reset them to 0's
3212 sub ax,ax
3213 push ds
3214 pop es
3215 mov di,offset dacbox+744
3216 rep stosw
3217 cmp tweakflag,0 ; tweaked mode?
3218 je loaddacdone3 ; nope
3219 mov dx,3c4h ; alter sequencer registers
3220 mov ax,0604h ; disable chain 4
3221 out dx,ax
3222 loaddacdone3:
3223 mov gotrealdac,1 ; flag for whether mode supports DAC
3224 cmp dacbox,255 ; did DAC get loaded or fudged?
3225 jne loaddacret ; yup
3226 mov gotrealdac,0 ; nope
3227 loaddacret:
3228 ret
3229 loaddac endp
3230
3231 ; *************** Function spindac(direction, rstep) ********************
3232
3233 ; Rotate the MCGA/VGA DAC in the (plus or minus) "direction"
3234 ; in "rstep" increments - or, if "direction" is 0, just replace it.
3235
3236 spindac proc uses di si es, direction:word, rstep:word
3237 cmp dotmode,9 ; TARGA 3 June 89 j mclain
3238 je spinbailout
3239 cmp dotmode,11 ; disk video mode?
3240 je spinbailout
3241 cmp istruecolor,1 ; truecolor mode:
3242 je spinbailout
3243 cmp gotrealdac,0 ; do we have DAC registers to spin?
3244 je spinbailout ; nope. bail out.
3245 cmp colors,16 ; at least 16 colors?
3246 jge spindacdoit ; yup. spin away.
3247 spinbailout:
3248 jmp spindacreturn ; nope. bail out.
3249
3250 spindacdoit:
3251 push ds ; need ES == DS here
3252 pop es ; ...
3253 cmp direction,0 ; just replace it?
3254 je newDAC ; yup.
3255
3256 mov cx, rstep ; loop through the rotate "rstep" times
3257 stepDAC:
3258 push cx ; save the loop counter for a tad
3259 mov si,offset dacbox
3260 mov di,si
3261 mov ax,rotate_lo ; calc low end of rotate range
3262 cmp ax,colors ; safety check for 16 color mode
3263 jae nextDAC ; out of range, none to rotate
3264 add si,ax
3265 add si,ax
3266 add si,ax
3267 mov ax,rotate_hi ; calc high end of rotate range
3268 cmp ax,colors ; safety check for 16 color mode
3269 jb stepDAC2 ; ok, in range
3270 mov ax,colors ; out of range, use colors-1
3271 dec ax ; ...
3272 stepDAC2:
3273 add di,ax
3274 add di,ax
3275 add di,ax
3276 mov cx,di ; size of rotate range - 1
3277 sub cx,si
3278 jcxz nextDAC ; do nothing if range 0
3279 cmp direction,1 ; rotate upwards?
3280 jne short downDAC ; nope. downwards
3281 mov bx,word ptr [si] ; save the first entry
3282 mov dl,byte ptr [si+2] ; ...
3283 cld ; set the direction
3284 mov di,si ; set up the rotate
3285 add si,3 ; ...
3286 rep movsb ; rotate it
3287 mov word ptr [di],bx ; store the last entry
3288 mov byte ptr [di+2],dl ; ...
3289 jmp short nextDAC ; set the new DAC
3290 downDAC:
3291 std ; set the direction
3292 mov bx,word ptr [di] ; save the last entry
3293 mov dl,byte ptr [di+2] ; ...
3294 mov si,di ; set up the rotate
3295 dec si ; ...
3296 add di,2 ; ...
3297 rep movsb ; rotate it
3298 mov word ptr [si+1],bx ; store the first entry
3299 mov byte ptr [si+3],dl ; ...
3300 cld ; reset the direction
3301 nextDAC:
3302 pop cx ; restore the loop counter
3303 loop stepDAC ; and loop until done.
3304
3305 newDAC:
3306 cmp dotmode,19 ; roll-your-own video?
3307 jne spin_notyourown ; nope
3308 call far ptr writevideopalette
3309 cmp ax,-1 ; negative result?
3310 je go_spindoit ; yup. handle it locally.
3311 jmp spindacreturn ; else we done.
3312 go_spindoit:
3313 jmp spindoit
3314
3315 spin_notyourown:
3316 cmp dotmode, 29
3317 je TPlusOrXGAspindac
3318 cmp xga_isinmode,0 ; XGA extended graphics?
3319 je notxga
3320
3321 TPlusOrXGAspindac:
3322 mov si,offset dacbox
3323 push si
3324 mov bx,0
3325 xgalp1: mov al,[si+bx] ; adjust VGA -> XGA
3326 shl al,1
3327 shl al,1
3328 mov [si+bx],al
3329 inc bx
3330 cmp bx,768
3331 jne xgalp1
3332
3333 cmp dotmode, 29 ; Are we a TARGA+?
3334 jne XGAPaletteCall ; nope - XGA
3335 mov ax,4403h
3336 push ax
3337 mov ax,256 * 3
3338 push ax
3339 xor ax,ax
3340 push ax
3341 push ds
3342 mov ax,OFFSET dacbox
3343 push ax
3344 call far ptr TPlusLUT
3345 add sp, 10
3346 jmp TPlusOrXGASet
3347
3348 XGAPaletteCall:
3349 call far ptr xga_setpalette
3350
3351 TPlusOrXGASet:
3352 pop si
3353 mov bx,0
3354 xgalp2: mov al,[si+bx] ; adjust XGA -> VGA
3355 shr al,1
3356 shr al,1
3357 mov [si+bx],al
3358 inc bx
3359 cmp bx,768
3360 jne xgalp2
3361 jmp spindacreturn
3362 notxga:
3363
3364 cmp bios_palette,0 ; BIOS palette updates forced?
3365 je not_bios_palette ; nope
3366 mov ax,1012h ; use a BIOS update
3367 mov bx,0
3368 mov cx,256
3369 push ds
3370 pop es
3371 mov dx,offset dacbox
3372 int 10h
3373 jmp spindacreturn
3374 not_bios_palette:
3375
3376 cmp f85flag, 0 ; if 8514a then update pallette
3377 je spindoit
3378 jmp spin8514
3379
3380 spindoit:
3381 cmp colors,16 ; 16 color vga?
3382 jne spindoit2 ; nope
3383 cmp reallyega,1 ; is this really an EGA?
3384 je spindoit2 ; yup
3385 cld ; vga 16 color, straighten out dacbox,
3386 push ds ; 16 color vga uses indirection thru
3387 pop es ; palette select
3388 mov si,offset dacbox+18 ; dac[20] is used for color 6 so
3389 mov di,offset dacbox+60 ; copy dacbox[6] to dacbox[20]
3390 mov cx,3 ; ...
3391 rep movsb ; ...
3392 mov si,offset dacbox+24 ; dac[56-63] are used for colors 8-15 so
3393 mov di,offset dacbox+168 ; copy dacbox[8-15] to dacbox[56-63]
3394 mov cx,24 ; ...
3395 rep movsb ; ...
3396 spindoit2:
3397 mov bx,0 ; set up to update the DAC
3398 mov dacnorm,0 ; indicate no overflow
3399 dacupdate:
3400 cmp direction,0 ; just replace it?
3401 je fastupdate ; yup.
3402 mov cx,daccount ; ...
3403 jmp short overfast
3404 fastupdate:
3405 mov cx,256
3406 overfast:
3407 mov ax,256 ; calculate 256 - BX
3408 sub ax,bx ; ...
3409 cmp ax,cx ; is that less than the update count?
3410 jge retrace1 ; nope. no adjustment
3411 mov cx,ax ; else adjust
3412 mov dacnorm,1 ; and indicate overflow
3413 retrace1:
3414 mov dx,03dah ; wait for no retrace
3415 in al,dx ; ...
3416 and al,8 ; this bit is high during a retrace
3417 jnz retrace1 ; so loop until it goes low
3418 retrace2:
3419 in al,dx ; wait for no retrace
3420 and al,8 ; this bit is high during a retrace
3421 jz retrace2 ; so loop until it goes high
3422 cmp reallyega,1 ; is this really an EGA?
3423 je spinega ; yup. spin it that way.
3424 cmp cpu,88 ; are we on a (yuck, ugh) 8088/8086?
3425 jle spinbios ; yup. go through the BIOS
3426 .186
3427 mov dx,03c8h ; set up for a blitz-write
3428 mov ax,bx ; from this register
3429 cli ; critical section: no ints
3430 out dx,al ; starting register
3431 inc dx ; set up to update colors
3432 mov si, offset dacbox ; get starting addr in SI
3433 add si,bx ; ...
3434 add si,bx ; ...
3435 add si,bx ; ...
3436 mov ax,cx ; triple the value in CX
3437 add cx,ax ; ...
3438 add cx,ax ; ...
3439 rep outsb ; whap! Zango! They're updated!
sti ; end of critical section
mov cx,ax ; restore CX for code below
jmp spindone ; skip over the BIOS version.
.8086
spinbios:
mov dx,offset dacbox ; set up the DAC box offset
add dx,bx ; ...
add dx,bx ; ...
add dx,bx ; ...
push bp ; save some registers
push cx ; (AMSTRAD might need this)
push dx ; ...
push bx ; ...
mov ax,1012h ; update the DAC
int 10h ; do it.
pop bx ; restore the registers
pop dx ; ...
pop cx ; ...
pop bp ; ...
jmp spindone ; jump to common code
spinega:
cmp bx,0 ; skip this if not the first time thru
jne spindone ; ...
push bx ; save some registers
push cx ; aroud the call
call far ptr dactopal ; convert the VGA DAC to an EGA palette
pop cx ; restore the registers
pop bx ; from prior to the call
mov ax,1002h ; update the EGA palette
mov dx,offset palettega ; ...
int 10h ; do it.
spindone:
cmp daclearn,0 ; are we still in learn mode?
jne nolearn ; nope.
mov dx,03dah ; check for the retrace
in al,dx ; ...
and al,1 ; this bit is high if display disabled
jz donelearn ; oops. retrace finished first.
cmp dacnorm,0 ; was this a "short" update?
jne short nolearn ; then don't increment it
3440 inc daccount ; increment the daccount value
3441 inc daccount ; increment the daccount value
3442 inc daccount ; increment the daccount value
3443 mov ax,cyclelimit ; collect the cycle-limit value
3444 cmp daccount,ax ; sanity check: don't update too far
jle short nolearn ; proceed if reasonable.
donelearn:
sub daccount,6 ; done learning: reduce the daccount
mov daclearn,1 ; set flag: no more learning
cmp daccount,4 ; there's a limit to how slow we go
3445 jge nolearn ; ...
3446 mov daccount,4 ; ...
3447 nolearn:
3448 add bx,cx ; set up for the next batch
3449 cmp bx,256 ; more to go?
3450 jge spindacreturn ; nope. we done.
3451 jmp dacupdate ; yup. do it.
3452
3453 spin8514:
3454 cmp ai_8514, 0 ;check afi flag JCO 4/11/92
3455 jne spin85afi
3456 call far ptr w8514hwpal ; AW
3457 jmp spindacreturn
3458 spin85afi:
3459 call far ptr w8514pal ;use afi
3460
3461 spindacreturn:
3462 ret
3463 spindac endp
3464
3465 ; *************** Function find_special_colors ********************
3466
3467 ; Find the darkest and brightest colors in palette, and a medium
3468 ; color which is reasonably bright and reasonably grey.
3469
3470 find_special_colors proc uses si
3471 mov color_dark,0 ; for default cases
3472 mov color_medium,7 ; ...
3473 mov color_bright,15 ; ...
3474 cmp colors,2 ; 2 color mode?
3475 jg fscnot2
3476 mov color_medium,1 ; yup, set assumed values and return
3477 mov color_bright,1
3478 ret
3479 fscnot2:
3480 cmp colors,16 ; < 16 color mode? (ie probably 4)
3481 jge fscnot4
3482 mov color_medium,2 ; yup, set assumed values and return
3483 mov color_bright,3
3484 ret
3485 fscnot4:
3486 cmp gotrealdac,0 ; dac valid?
3487 je fscret ; nope, return with defaults set earlier
3488 mov bh,255 ; bh is lowest brightness found yet
3489 sub bl,bl ; bl is highest found yet
3490 sub ah,ah ; ah is best found for medium choice yet
3491 mov si,offset dacbox ; use si as pointer to dac
3492 sub cx,cx ; use cx for color number
3493 fscloop:
3494 mov al,byte ptr 0[si] ; add red,green,blue (assumed all <= 63)
3495 add al,byte ptr 1[si] ; ...
3496 add al,byte ptr 2[si] ; ...
3497 cmp al,bh ; less than lowest found so far?
3498 jae fscchkbright
3499 mov color_dark,cx ; yup, note new darkest
3500 mov bh,al ; ...
3501 fscchkbright:
3502 cmp al,bl ; > highest found so far?
3503 jbe fscchkmedium
3504 mov color_bright,cx ; yup, note new brightest
3505 mov bl,al ; ...
3506 fscchkmedium:
3507 cmp al,150 ; too bright?
3508 jae fscnextcolor ; yup, don't check for medium
add al,80 ; so the subtract below will be safe
cmp al,ah ; already less than best found?
jbe fscnextcolor
mov dh,byte ptr 0[si] ; penalize by (maxgun-mingun)/2
mov dl,byte ptr 1[si]
cmp dh,dl ; set dh to max gun
jae fscmed1
xchg dh,dl ; now dh=max(0,1), dl=min(0,1)
fscmed1:
cmp dh,byte ptr 2[si] ; 2 > dh?
jae fscmed2
mov dh,byte ptr 2[si]
fscmed2:
cmp dl,byte ptr 2[si] ; 2 < dl?
jbe fscmed3
mov dl,byte ptr 2[si]
fscmed3:
sub dh,dl ; now subtract the penalty
shr dh,1
sub al,dh
cmp al,ah ; a new best?
jbe fscnextcolor
mov color_medium,cx ; yup, note new medium
mov ah,al ; ...
fscnextcolor:
add si,3 ; point to next dac entry
inc cx ; next color number
cmp cx,colors ; scanned them all?
jl fscloop ; nope, go around again
cmp ah,0 ; find any medium color?
jne fscret ; yup, all done
mov ax,color_bright ; must be a pretty bright image,
mov color_medium,ax ; use the brightest for medium
fscret:
ret
find_special_colors endp
; *************** Functions get_a_char, put_a_char ********************
; Get and put character and attribute at cursor
; Hi nybble=character, low nybble attribute. Text mode only
get_a_char proc
mov ah,8
xor bh,bh
int 10h
ret
get_a_char endp
put_a_char proc character:word
mov ax,character
mov bl,ah
mov ah,9
xor bh,bh
mov cx,1
int 10h
ret
put_a_char endp
end