1 !
2 ! Display adapter & video mode setup, version 2.6 (25-Mar-96)
3 !
4 ! Copyright (C) 1995, 1996 Martin Mares <mj@k332.feld.cvut.cz>
5 ! Based on the original setup.S code (C) Linus Torvalds
6 !
7
8 ! Enable autodetection of SVGA adapters and modes
9 #define CONFIG_VIDEO_SVGA
10
11 ! Enable autodetection of VESA modes
12 #define CONFIG_VIDEO_VESA
13
14 ! Enable compacting of mode table
15 #define CONFIG_VIDEO_COMPACT
16
17 ! Retain screen contents when switching modes
18 #define CONFIG_VIDEO_RETAIN
19
20 ! Enable local mode list
21 #undef CONFIG_VIDEO_LOCAL
22
23 ! This code uses an extended set of video mode numbers. These include:
24 ! Aliases for standard modes
25 ! NORMAL_VGA (-1)
26 ! EXTENDED_VGA (-2)
27 ! ASK_VGA (-3)
28 ! Video modes numbered by menu position -- NOT RECOMMENDED because of lack
29 ! of compatibility when extending the table. These are between 0x00 and 0xff.
30 #define VIDEO_FIRST_MENU 0x0000
31 ! Standard BIOS video modes (BIOS number + 0x0100)
32 #define VIDEO_FIRST_BIOS 0x0100
33 ! VESA BIOS video modes (VESA number + 0x0200)
34 #define VIDEO_FIRST_VESA 0x0200
35 ! Special video modes
36 #define VIDEO_FIRST_SPECIAL 0x0f00
37 #define VIDEO_80x25 0x0f00
38 #define VIDEO_8POINT 0x0f01
39 #define VIDEO_80x43 0x0f02
40 #define VIDEO_80x28 0x0f03
41 #define VIDEO_CURRENT_MODE 0x0f04
42 #define VIDEO_LAST_SPECIAL 0x0f05
43 ! Video modes given by resolution
44 #define VIDEO_FIRST_RESOLUTION 0x1000
45
46 ! The "recalculate timings" flag
47 #define VIDEO_RECALC 0x8000
48
49 ! Positions of various video parameters passed to the kernel
50 #define PARAM_CURSOR_POS 0
51 #define PARAM_VIDEO_PAGE 4
52 #define PARAM_VIDEO_MODE 6
53 #define PARAM_VIDEO_COLS 7
54 #define PARAM_VIDEO_EGA_BX 10
55 #define PARAM_VIDEO_LINES 14
56 #define PARAM_HAVE_VGA 15
57 #define PARAM_FONT_POINTS 16
58
59 ! Define DO_STORE according to CONFIG_VIDEO_RETAIN
60 #ifdef CONFIG_VIDEO_RETAIN
61 #define DO_STORE call store_screen
62 #else
63 #define DO_STORE
64 #endif
65
66 !
67 ! This is the main entry point called by setup.S
68 !
69 ! Input:
70 ! DS pointing to the bootsector
71
72 video: push ds ! We use different segments
73 push ds ! FS contains original DS
74 pop fs
75 push cs ! DS is equal to CS
76 pop ds
77 push cs ! ES is equal to CS
78 pop es
79 xor ax,ax
80 mov gs,ax ! GS is zero
81 cld
82 call basic_detect ! Basic adapter type testing (EGA/VGA/MDA/CGA)
83 seg fs ! User-selected video mode
84 mov ax,[0x01fa]
85 cmp ax,#ASK_VGA ! Bring up the menu
86 jz vid2
87 call mode_set ! Set the mode
88 jc vid1
89 lea si,badmdt ! Invalid mode ID
90 call prtstr
91 vid2: call mode_menu
92 vid1:
93 #ifdef CONFIG_VIDEO_RETAIN
94 call restore_screen ! Restore screen contents
95 #endif
96 call mode_params ! Store mode parameters
97 pop ds ! Restore original DS
98 ret
99
100 !
101 ! Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
102 !
103
104 basic_detect:
105 seg fs ! Default is no VGA
106 movb [PARAM_HAVE_VGA],#0
107
108 mov ah,#0x12 ! Check EGA/VGA
109 mov bl,#0x10
110 int 0x10
111 seg fs
112 mov [PARAM_VIDEO_EGA_BX],bx ! Used for identification of EGA in the kernel
113 cmp bl,#0x10 ! No, this is a CGA/MDA/HGA card.
114 je basret
115 incb [adapter]
116
117 mov ax,#0x1a00 ! Check for EGA/VGA discrimination
118 int 0x10
119 cmp al,#0x1a ! 1a means VGA, anything else EGA
120 jne basret
121 seg fs
122 incb [PARAM_HAVE_VGA] ! We've detected a VGA
123 incb [adapter]
124
125 basret: ret
126
127 !
128 ! Store the video mode parameters for later usage by the kernel.
129 ! This is done by asking the BIOS except for the rows/columns
130 ! parameters in the default 80x25 mode -- these are set directly,
131 ! because some very obscure BIOSes supply insane values.
132 !
133
134 mode_params:
135 mov ah,#0x03 ! Read cursor position
136 xor bh,bh
137 int 0x10
138 seg fs
139 mov [PARAM_CURSOR_POS],dx
140
141 mov ah,#0x0f ! Read page/mode/width
142 int 0x10
143 seg fs
144 mov [PARAM_VIDEO_PAGE],bx
145 seg fs
146 mov [PARAM_VIDEO_MODE],ax ! Video mode and screen width
147 cmp al,#7 ! MDA/HGA => segment differs
148 jnz mopar0
149 mov [video_segment],#0xb000
150 mopar0: seg gs ! Font size
151 mov ax,[0x485]
152 seg fs
153 mov [PARAM_FONT_POINTS],ax ! (valid only on EGA/VGA)
154
155 cmpb [def_mode],#0 ! Default mode -- force sane values
156 jz mopar1
157 seg fs
158 movb [PARAM_VIDEO_COLS],#80
159 mopar2: seg fs
160 movb [PARAM_VIDEO_LINES],#25
161 ret
162
163 mopar1: cmpb [adapter],#0 ! If we are on CGA/MDA/HGA, the screen must
164 jz mopar2 ! have 25 lines.
165 seg gs ! On EGA/VGA, use the EGA+ BIOS variable
166 mov al,[0x484] ! containing maximal line number.
167 inc al
168 seg fs
169 movb [PARAM_VIDEO_LINES],al
170 ret
171
172 !
173 ! The video mode menu
174 !
175
176 mode_menu:
177 lea si,keymsg ! "Return/Space/Timeout" message
178 call prtstr
179 call flush
180 nokey: call getkt
181 cmp al,#0x0d ! ENTER ?
182 je listm ! yes - manual mode selection
183 cmp al,#0x20 ! SPACE ?
184 je defmd1 ! no - repeat
185 call beep
186 jmp nokey
187 defmd1: ret ! No mode selected => use the 80x25 default
188
189 listm: call mode_table ! We need a mode table to be listed
190 listm0: lea si,name_bann ! Print adapter name
191 call prtstr
192 mov si,[card_name]
193 or si,si
194 jnz an2
195 mov al,[adapter]
196 lea si,old_name
197 or al,al
198 jz an1
199 lea si,ega_name
200 dec al
201 jz an1
202 lea si,vga_name
203 jmp an1
204 an2: call prtstr
205 lea si,svga_name
206 an1: call prtstr
207 lea si,listhdr ! Table header
208 call prtstr
209 mov dl,#0x30 ! DL holds mode number
210 lea si,modelist
211 lm1: cmp (si),#ASK_VGA ! End?
212 jz lm2
213 mov al,dl ! Menu selection number
214 call prtchr
215 call prtsp2
216 lodsw
217 call prthw ! Mode ID
218 call prtsp2
219 mov al,(si+1)
220 call prtdec ! Rows
221 mov al,#0x78 ! 'x'
222 call prtchr
223 lodsw
224 call prtdec ! Columns
225 mov al,#0x0d ! New line
226 call prtchr
227 mov al,#0x0a
228 call prtchr
229 inc dl ! Next character
230 cmp dl,#0x3a
231 jnz lm1
232 mov dl,#0x61
233 jmp lm1
234
235 lm2: lea si,prompt ! Mode prompt
236 call prtstr
237 lea di,edit_buf ! Editor buffer
238 lm3: call getkey
239 cmp al,#0x0d ! Enter?
240 jz lment
241 cmp al,#0x08 ! Backspace?
242 jz lmbs
243 cmp al,#0x20 ! Printable?
244 jc lm3
245 cmp di,#edit_buf+4 ! Enough space?
246 jz lm3
247 stosb
248 call prtchr
249 jmp lm3
250
251 lmbs: cmp di,#edit_buf ! Backspace
252 jz lm3
253 dec di
254 mov al,#0x08
255 call prtchr
256 call prtspc
257 mov al,#0x08
258 call prtchr
259 jmp lm3
260
261 lment: movb (di),#0
262 lea si,crlft
263 call prtstr
264 lea si,edit_buf
265 cmpb (si),#0 ! Empty string => use default mode
266 jz lmdef
267 cmpb (si+1),#0 ! One character => menu selection
268 jz mnusel
269 cmp (si),#0x6373 ! "scan" => mode scanning
270 jnz lmhx
271 cmp (si+2),#0x6e61
272 jz lmscan
273 lmhx: xor bx,bx ! Else => mode ID in hex
274 lmhex: lodsb
275 or al,al
276 jz lmuse1
277 sub al,#0x30
278 jc lmbad
279 cmp al,#10
280 jc lmhx1
281 sub al,#7
282 and al,#0xdf
283 cmp al,#10
284 jc lmbad
285 cmp al,#16
286 jnc lmbad
287 lmhx1: shl bx,#4
288 or bl,al
289 jmp lmhex
290 lmuse1: mov ax,bx
291 jmp lmuse
292
293 mnusel: lodsb ! Menu selection
294 xor ah,ah
295 sub al,#0x30
296 jc lmbad
297 cmp al,#10
298 jc lmuse
299 cmp al,#0x61-0x30
300 jc lmbad
301 sub al,#0x61-0x30-10
302 cmp al,#36
303 jnc lmbad
304 lmuse: call mode_set
305 jc lmdef
306 lmbad: lea si,unknt
307 call prtstr
308 br lm2
309
310 lmscan: cmpb [adapter],#0 ! Scanning supported only on EGA/VGA
311 jz lmbad
312 mov [mt_end],#0 ! Scanning of modes: done as new autodetection
313 movb [scanning],#1
314 call mode_table
315 br listm0
316
317 lmdef: ret
318
319 !
320 ! Aliases for backward compatibility.
321 !
322
323 setalias:
324 mov ax,#VIDEO_80x25
325 inc bx
326 jz mode_set
327 mov al,#VIDEO_8POINT-VIDEO_FIRST_SPECIAL
328 inc bx
329 jnz setbad
330
331 ! Fall-thru !
332
333 !
334 ! Setting of user mode (AX=mode ID) => CF=success
335 !
336
337 mode_set:
338 mov bx,ax
339 cmp ah,#0xff
340 jz setalias
341 test ah,#VIDEO_RECALC>>8
342 jnz setrec
343 cmp ah,#VIDEO_FIRST_RESOLUTION>>8
344 jnc setres
345 cmp ah,#VIDEO_FIRST_SPECIAL>>8
346 jz setspc
347 cmp ah,#VIDEO_FIRST_VESA>>8
348 jnc setvesa
349 or ah,ah
350 jz setmenu
351 dec ah
352 jz setbios
353 setbad: clc
354 movb [do_restore],#0 ! The screen needn't be restored
355 ret
356
357 setvesa:
358 DO_STORE
359 sub bh,#VIDEO_FIRST_VESA>>8
360 mov ax,#0x4f02 ! VESA BIOS mode set call
361 int 0x10
362 cmp ax,#0x004f ! AL=4f if implemented, AH=0 if OK
363 jnz setbad
364 stc
365 ret
366
367 setbios:
368 DO_STORE
369 int 0x10 ! Standard BIOS mode set call
370 push bx
371 mov ah,#0x0f ! Check if really set
372 int 0x10
373 pop bx
374 cmp al,bl
375 jnz setbad
376 stc
377 ret
378
379 setspc: xor bh,bh ! Set special mode
380 cmp bl,#VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL
381 jnc setbad
382 add bx,bx
383 .word 0xa7ff, spec_inits ! JMP [BX+spec_inits]
384
385 setmenu:
386 push bx ! Set mode chosen from menu
387 call mode_table ! Build the mode table
388 pop ax
389 shl ax,#2
390 add si,ax
391 cmp si,di
392 jnc setbad
393 mov ax,(si) ! Fetch mode ID
394 _m_s: jmp mode_set
395
396 setres:
397 push bx ! Set mode chosen by its resolution
398 call mode_table
399 pop bx
400 xchg bh,bl
401 setr1: lodsw
402 cmp ax,#ASK_VGA ! End of the list?
403 jz setbad
404 lodsw
405 cmp ax,bx
406 jnz setr1
407 mov ax,(si-4) ! Fetch mode ID
408 jmp _m_s
409
410 !
411 ! Recalculate vertical display end registers -- this fixes various
412 ! inconsistencies of extended modes on many adapters. Called when
413 ! the VIDEO_RECALC flag is set in the mode ID.
414 !
415
416 setrec: sub ah,#VIDEO_RECALC>>8 ! Set the base mode
417 call mode_set
418 jnc rct3
419 seg gs ! Font size in pixels
420 mov ax,[0x485]
421 seg gs ! Number of rows
422 mov bl,[0x484]
423 inc bl
424 mul bl ! Number of visible
425 dec ax ! scan lines - 1
426 mov dx,#0x3d4
427 mov bx,ax
428 mov al,#0x12 ! Lower 8 bits
429 mov ah,bl
430 out dx,ax
431 mov al,#0x07 ! Bits 8 and 9 in the overflow register
432 call inidx
433 xchg ah,al
434 and ah,#0xbd
435 shr bh,#1
436 jnc rct1
437 or ah,#0x02
438 rct1: shr bh,#1
439 jnc rct2
440 or ah,#0x40
441 rct2: mov al,#0x07
442 out dx,ax
443 stc
444 rct3: ret
445
446 !
447 ! Table of routines for setting of the special modes.
448 !
449
450 spec_inits:
451 .word set_80x25
452 .word set_8pixel
453 .word set_80x43
454 .word set_80x28
455 .word set_current
456
457 !
458 ! Set the 80x25 mode. If already set, do nothing.
459 !
460
461 set_80x25:
462 incb [def_mode] ! Signal "we use default mode"
463 use_80x25:
464 mov ah,#0x0f ! Get current mode ID
465 int 0x10
466 cmp ax,#0x5007 ! Mode 7 (80x25 mono) is the only one available
467 jz st80 ! on CGA/MDA/HGA and is also available on EGAM
468 cmp ax,#0x5003 ! Unknown mode => force 80x25 color
469 jnz force3
470 st80: cmpb [adapter],#0 ! CGA/MDA/HGA => mode 3/7 is always 80x25
471 jz set80
472 seg gs ! This is EGA+ -- beware of 80x50 etc.
473 mov al,[0x0484]
474 or al,al ! Some buggy BIOS'es set 0 rows
475 jz set80
476 cmp al,#24 ! It's hopefully correct
477 jz set80
478 force3: DO_STORE
479 mov ax,#0x0003 ! Forced set
480 int 0x10
481 set80: stc
482 ret
483
484 !
485 ! Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
486 !
487
488 set_8pixel:
489 DO_STORE
490 call use_80x25 ! The base is 80x25
491 set_8pt:
492 mov ax,#0x1112 ! Use 8x8 font
493 xor bl,bl
494 int 0x10
495 mov ax,#0x1200 ! Use alternate print screen
496 mov bl,#0x20
497 int 0x10
498 mov ax,#0x1201 ! Turn off cursor emulation
499 mov bl,#0x34
500 int 0x10
501 mov ah,#0x01 ! Define cursor (scan lines 6 to 7)
502 mov cx,#0x0607
503 int 0x10
504 set_current:
505 stc
506 ret
507
508 !
509 ! Set the 80x28 mode. This mode works on all VGA's, because it's a standard
510 ! 80x25 mode with 14-point fonts instead of 16-point.
511 !
512
513 set_80x28:
514 DO_STORE
515 call use_80x25 ! The base is 80x25
516 mov ax,#0x1111 ! Use 9x14 font
517 xor bl,bl
518 int 0x10
519 mov ah,#0x01 ! Define cursor (scan lines 11 to 12)
520 mov cx,#0x0b0c
521 int 0x10
522 stc
523 ret
524
525 !
526 ! Set the 80x43 mode. This mode is works on all VGA's.
527 ! It's a 350-scanline mode with 8-pixel font.
528 !
529
530 set_80x43:
531 DO_STORE
532 mov ax,#0x1201 ! Set 350 scans
533 mov bl,#0x30
534 int 0x10
535 mov ax,#0x0003 ! Reset video mode
536 int 0x10
537 jmp set_8pt ! Use 8-pixel font
538
539 #ifdef CONFIG_VIDEO_RETAIN
540
541 !
542 ! Store screen contents to temporary buffer.
543 !
544
545 store_screen:
546 cmpb [do_restore],#0 ! Already stored?
547 jnz stsr
548 testb [loadflags],#CAN_USE_HEAP ! Have we space for storing?
549 jz stsr
550 push ax
551 push bx
552 mov al,[def_mode] ! "Default mode" flag overriden
553 push ax
554 movb [def_mode],#0
555 call mode_params ! Obtain params of current mode
556 pop ax
557 mov [def_mode],al
558
559 seg fs
560 mov ah,[PARAM_VIDEO_LINES]
561 seg fs
562 mov al,[PARAM_VIDEO_COLS]
563 mov bx,ax ! BX=dimensions
564 mul ah
565 mov cx,ax ! CX=number of characters to store
566 add ax,ax ! Calculate image size
567 add ax,modelist+1024+4
568 cmp ax,[heap_end_ptr]
569 jnc sts1 ! Unfortunately, out of memory
570
571 seg fs ! Store mode params
572 mov ax,[PARAM_CURSOR_POS]
573 lea di,modelist+1024
574 stosw
575 mov ax,bx
576 stosw
577
578 push ds ! Store the screen
579 mov ds,[video_segment]
580 xor si,si
581 rep
582 movsw
583 pop ds
584 incb [do_restore] ! Screen will be restored later
585 sts1: pop bx
586 pop ax
587 stsr: ret
588
589 !
590 ! Restore screen contents from temporary buffer.
591 !
592
593 restore_screen:
594 cmpb [do_restore],#0 ! Has the screen been stored?
595 jz res1
596 call mode_params ! Get parameters of current mode
597 seg fs
598 mov cl,[PARAM_VIDEO_LINES]
599 seg fs
600 mov ch,[PARAM_VIDEO_COLS]
601 lea si,modelist+1024 ! Screen buffer
602 lodsw ! Set cursor position
603 mov dx,ax
604 cmp dh,cl
605 jc res2
606 mov dh,cl
607 dec dh
608 res2: cmp dl,ch
609 jc res3
610 mov dl,ch
611 dec dl
612 res3: mov ah,#0x02
613 mov bh,#0x00
614 int 0x10
615 lodsw ! Display size
616 mov dl,ah ! DL=number of lines
617 mov ah,#0 ! BX=physical length of orig. line
618 mov bx,ax
619 cmp dl,cl ! Too many?
620 jc res4
621 push ax
622 mov al,dl
623 sub al,cl
624 mul bl
625 add si,ax
626 add si,ax
627 pop ax
628 mov dl,cl
629 res4: cmp al,ch ! Too wide?
630 jc res5
631 mov al,ch ! AX=width of src. line
632 res5: mov cl,#0
633 xchg cl,ch
634 mov bp,cx ! BP=width of dest. line
635 push es
636 mov es,[video_segment]
637 xor di,di ! Move the data
638 add bx,bx ! Convert BX and BP to _bytes_
639 add bp,bp
640 res6: push si
641 push di
642 mov cx,ax
643 rep
644 movsw
645 pop di
646 pop si
647 add di,bp
648 add si,bx
649 dec dl
650 jnz res6
651 pop es ! Done
652 res1: ret
653
654 #endif
655
656 !
657 ! Build the table of video modes (stored after the setup.S code at the
658 ! `modelist' label. Each video mode record looks like:
659 ! .word MODE-ID (our special mode ID (see above))
660 ! .byte rows (number of rows)
661 ! .byte columns (number of columns)
662 ! Returns address of the end of the table in DI, the end is marked
663 ! with a ASK_VGA ID.
664 !
665
666 mode_table:
667 mov di,[mt_end] ! Already filled?
668 or di,di
669 jnz mtab1x
670 lea di,modelist ! Store standard modes:
671
672 mov eax,#VIDEO_80x25 + 0x50190000 ! The 80x25 mode (ALL)
673 stosd
674 mov al,[adapter] ! CGA/MDA/HGA -- no more modes
675 or al,al
676 jz mtabe
677 dec al
678 jnz mtabv
679 mov eax,#VIDEO_8POINT + 0x502b0000 ! The 80x43 EGA mode
680 stosd
681 jmp mtabe
682 mtab1x: jmp mtab1
683
684 mtabv: mov eax,#VIDEO_8POINT + 0x50320000 ! The 80x50 mode (VGA only)
685 stosd
686 mov eax,#VIDEO_80x43 + 0x502b0000 ! The 80x43 mode (VGA only)
687 stosd
688 mov eax,#VIDEO_80x28 + 0x501c0000 ! The 80x28 mode (VGA only)
689 stosd
690
691 cmpb [scanning],#0 ! Mode scan requested?
692 jz mscan1
693 call mode_scan
694 mscan1:
695
696 #ifdef CONFIG_VIDEO_LOCAL
697 call local_modes
698 #endif
699 #ifdef CONFIG_VIDEO_VESA
700 call vesa_modes ! Detect VESA VGA modes
701 #endif
702 #ifdef CONFIG_VIDEO_SVGA
703 cmpb [scanning],#0 ! Bypass when scanning
704 jnz mscan2
705 call svga_modes ! Detect SVGA cards & modes
706 mscan2:
707 #endif
708
709 mtabe:
710
711 #ifdef CONFIG_VIDEO_COMPACT
712 lea si,modelist ! Compact video mode list if requested.
713 mov dx,di
714 mov di,si
715 cmt1: cmp si,dx ! Scan all modes
716 jz cmt2
717 lea bx,modelist ! Find in previous entries
718 mov cx,(si+2)
719 cmt3: cmp si,bx
720 jz cmt4
721 cmp cx,(bx+2) ! Found => don't copy this entry
722 jz cmt5
723 add bx,#4
724 jmp cmt3
725
726 cmt4: movsd ! Copy entry
727 jmp cmt1
728
729 cmt5: add si,#4 ! Skip entry
730 jmp cmt1
731
732 cmt2:
733 #endif
734
735 mov (di),#ASK_VGA ! End marker
736 mov [mt_end],di
737 mtab1: lea si,modelist ! Returning: SI=mode list, DI=list end
738 ret0: ret
739
740 !
741 ! Detect VESA modes.
742 !
743
744 #ifdef CONFIG_VIDEO_VESA
745
746 vesa_modes:
747 cmpb [adapter],#2 ! VGA only
748 jnz ret0
749 mov bp,di ! BP=original mode table end
750 add di,#0x200 ! Buffer space
751 mov ax,#0x4f00 ! VESA Get card info call
752 int #0x10
753 mov di,bp
754 cmp ax,#0x004f ! Successful?
755 jnz ret0
756 cmp (di+0x200),#0x4556
757 jnz ret0
758 cmp (di+0x202),#0x4153
759 jnz ret0
760 mov [card_name],#vesa_name ! Set name to "VESA VGA"
761 push gs
762 lgs si,(di+0x20e) ! GS:SI=mode list
763 mov cx,#128 ! Iteration limit
764 vesa1: seg gs ! Get next mode in the list
765 lodsw
766 cmp ax,#0xffff ! End of the table?
767 jz vesar
768 cmp ax,#0x0080 ! Check validity of mode ID
769 jc vesa2
770 or ah,ah ! Valid ID's are 0x0000-0x007f
771 jz vesae ! and 0x0100-0x02ff.
772 cmp ax,#0x0300
773 jnc vesae
774 vesa2: push cx
775 mov cx,ax ! Get mode information structure
776 mov ax,#0x4f01
777 int 0x10
778 mov bx,cx ! BX=mode number
779 add bh,#VIDEO_FIRST_VESA>>8
780 pop cx
781 cmp ax,#0x004f
782 jnz vesan ! Don't report errors (buggy BIOSES :-[ )
783 mov al,(di) ! Check capabilities. We require
784 and al,#0x19 ! a color text mode.
785 cmp al,#0x09
786 jnz vesan
787 cmp (di+8),#0xb800 ! Standard video memory address required
788 jnz vesan
789 testb (di),#2 ! Mode characteristics supplied?
790 mov (di),bx ! Store mode number
791 jz vesa3
792 xor dx,dx
793 mov bx,(di+0x12) ! Width
794 or bh,bh
795 jnz vesan
796 mov (di+3),bl
797 mov ax,(di+0x14) ! Height
798 or ah,ah
799 jnz vesan
800 mov (di+2),al
801 mul bl
802 cmp ax,#8193 ! Small enough for Linux console driver?
803 jnc vesan
804 jmp vesaok
805
806 vesa3: sub bx,#0x8108 ! This mode has no detailed info specified,
807 jc vesan ! so it must be a standard VESA mode.
808 cmp bx,#5
809 jnc vesan
810 mov ax,(bx+vesa_text_mode_table)
811 mov (di+2),ax
812 vesaok: add di,#4 ! The mode is valid. Store it.
813 vesan: loop vesa1 ! Next mode. Limit exceeded => error
814 vesae: lea si,vesaer
815 call prtstr
816 mov di,bp ! Discard already found modes.
817 vesar: pop gs
818 ret
819
820 !
821 ! Dimensions of standard VESA text modes
822 !
823
824 vesa_text_mode_table:
825 db 60, 80 ! 0108
826 db 25, 132 ! 0109
827 db 43, 132 ! 010A
828 db 50, 132 ! 010B
829 db 60, 132 ! 010C
830
831 #endif
832
833 !
834 ! Scan for video modes. A bit dirty, but should work.
835 !
836
837 mode_scan:
838 mov cx,#0x0100 ! Start with mode 0
839 scm1: mov ah,#0 ! Test the mode
840 mov al,cl
841 int 0x10
842 mov ah,#0x0f
843 int 0x10
844 cmp al,cl
845 jnz scm2 ! Mode not set
846 mov dx,#0x3c0 ! Test if it's a text mode
847 mov al,#0x10 ! Mode bits
848 call inidx
849 and al,#0x03
850 jnz scm2
851 mov dx,#0x3d4 ! Cursor location
852 mov al,#0x0f
853 call inidx
854 or al,al
855 jnz scm2
856 mov ax,cx ! OK, store the mode
857 stosw
858 seg gs ! Number of rows
859 mov al,[0x484]
860 inc al
861 stosb
862 seg gs ! Number of columns
863 mov ax,[0x44a]
864 stosb
865 scm2: inc cl
866 jns scm1
867 mov ax,#0x0003 ! Return back to mode 3
868 int 0x10
869 ret
870
871 tstidx: out dx,ax ! OUT DX,AX and inidx
872 inidx: out dx,al ! Read from indexed VGA register
873 inc dx ! AL=index, DX=index reg port -> AL=data
874 in al,dx
875 dec dx
876 ret
877
878 !
879 ! Try to detect type of SVGA card and supply (usually approximate) video
880 ! mode table for it.
881 !
882
883 #ifdef CONFIG_VIDEO_SVGA
884
885 svga_modes:
886 lea si,svga_table ! Test all known SVGA adapters
887 dosvga: lodsw
888 mov bp,ax ! Default mode table
889 or ax,ax
890 jz didsv1
891 lodsw ! Pointer to test routine
892 push si
893 push di
894 push es
895 mov bx,#0xc000
896 mov es,bx
897 call ax ! Call test routine
898 pop es
899 pop di
900 pop si
901 or bp,bp
902 jz dosvga
903 mov si,bp ! Found, copy the modes
904 mov ah,#0x01
905 cpsvga: lodsb
906 or al,al
907 jz didsv
908 stosw
909 movsw
910 jmp cpsvga
911
912 didsv: mov [card_name],si ! Store pointer to card name
913 didsv1: ret
914
915 !
916 ! Table of all known SVGA cards. For each card, we store a pointer to
917 ! a table of video modes supported by the card and a pointer to a routine
918 ! used for testing of presence of the card. The video mode table is always
919 ! followed by the name of the card or the chipset.
920 !
921
922 svga_table:
923 .word s3_md, s3_test
924 .word ati_md, ati_test
925 .word chips_md, chips_test
926 .word cirrus5_md, cirrus5_test
927 .word cirrus6_md, cirrus6_test
928 .word cirrus1_md, cirrus1_test
929 .word ahead_md, ahead_test
930 .word everex_md, everex_test
931 .word genoa_md, genoa_test
932 .word oak_md, oak_test
933 .word paradise_md, paradise_test
934 .word trident_md, trident_test
935 .word tseng_md, tseng_test
936 .word video7_md, video7_test
937 .word 0
938
939 !
940 ! Test routines and mode tables:
941 !
942
943 ! S3 - The test algorithm was taken from the SuperProbe package
944 ! for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
945
946 s3_test:
947 mov cx,#0x0f35 ! we store some constants in cl/ch
948 mov dx,#0x03d4
949 movb al,#0x38
950 call inidx
951 mov bh,al ! store current value of CRT-register 0x38
952 mov ax,#0x0038
953 call outidx ! disable writing to special regs
954 movb al,cl ! check whether we can write special reg 0x35
955 call inidx
956 movb bl,al ! save the current value of CRT reg 0x35
957 andb al,#0xf0 ! clear bits 0-3
958 movb ah,al
959 movb al,cl ! and write it to CRT reg 0x35
960 call outidx
961 call inidx ! now read it back
962 andb al,ch ! clear the upper 4 bits
963 jz s3_2 ! the first test failed. But we have a
964 movb ah,bl ! second chance
965 mov al,cl
966 call outidx
967 jmp s3_1 ! do the other tests
968 s3_2: mov ax,cx ! load ah with 0xf and al with 0x35
969 orb ah,bl ! set the upper 4 bits of ah with the orig value
970 call outidx ! write ...
971 call inidx ! ... and reread
972 andb al,cl ! turn off the upper 4 bits
973 push ax
974 movb ah,bl ! restore old value in register 0x35
975 movb al,cl
976 call outidx
977 pop ax
978 cmp al,ch ! setting lower 4 bits was successful => bad
979 je no_s3 ! writing is allowed => this is not an S3
980 s3_1: mov ax,#0x4838 ! allow writing to special regs by putting
981 call outidx ! magic number into CRT-register 0x38
982 movb al,cl ! check whether we can write special reg 0x35
983 call inidx
984 movb bl,al
985 andb al,#0xf0
986 movb ah,al
987 movb al,cl
988 call outidx
989 call inidx
990 andb al,ch
991 jnz no_s3 ! no, we can't write => no S3
992 mov ax,cx
993 orb ah,bl
994 call outidx
995 call inidx
996 andb al,ch
997 push ax
998 movb ah,bl ! restore old value in register 0x35
999 movb al,cl
1000 call outidx
1001 pop ax
1002 cmp al,ch
1003 jne no_s31 ! writing not possible => no S3
1004 movb al,#0x30
1005 call inidx ! now get the S3 id ...
1006 lea di,idS3
1007 mov cx,#0x10
1008 repne
1009 scasb
1010 je no_s31
1011 movb ah,bh
1012 movb al,#0x38
1013 jmp s3rest
1014 no_s3: movb al,#0x35 ! restore CRT register 0x35
1015 movb ah,bl
1016 call outidx
1017 no_s31: xor bp,bp ! Detection failed
1018 s3rest: movb ah,bh
1019 movb al,#0x38 ! restore old value of CRT register 0x38
1020 outidx: out dx,al ! Write to indexed VGA register
1021 push ax ! AL=index, AH=data, DX=index reg port
1022 mov al,ah
1023 inc dx
1024 out dx,al
1025 dec dx
1026 pop ax
1027 ret
1028
1029 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1030 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1031
1032 s3_md: .byte 0x54, 0x2b, 0x84
1033 .byte 0x55, 0x19, 0x84
1034 .byte 0
1035 .ascii "S3"
1036 .byte 0
1037
1038 ! ATI cards.
1039
1040 ati_test:
1041 lea si,idati
1042 mov di,#0x31
1043 mov cx,#0x09
1044 repe
1045 cmpsb
1046 je atiok
1047 xor bp,bp
1048 atiok: ret
1049
1050 idati: .ascii "761295520"
1051
1052 ati_md: .byte 0x23, 0x19, 0x84
1053 .byte 0x33, 0x2c, 0x84
1054 .byte 0x22, 0x1e, 0x64
1055 .byte 0x21, 0x19, 0x64
1056 .byte 0x58, 0x21, 0x50
1057 .byte 0x5b, 0x1e, 0x50
1058 .byte 0
1059 .ascii "ATI"
1060 .byte 0
1061
1062 ! AHEAD
1063
1064 ahead_test:
1065 mov ax,#0x200f
1066 mov dx,#0x3ce
1067 out dx,ax
1068 inc dx
1069 in al,dx
1070 cmp al,#0x20
1071 je isahed
1072 cmp al,#0x21
1073 je isahed
1074 xor bp,bp
1075 isahed: ret
1076
1077 ahead_md:
1078 .byte 0x22, 0x2c, 0x84
1079 .byte 0x23, 0x19, 0x84
1080 .byte 0x24, 0x1c, 0x84
1081 .byte 0x2f, 0x32, 0xa0
1082 .byte 0x32, 0x22, 0x50
1083 .byte 0x34, 0x42, 0x50
1084 .byte 0
1085 .ascii "Ahead"
1086 .byte 0
1087
1088 ! Chips & Tech.
1089
1090 chips_test:
1091 mov dx,#0x3c3
1092 in al,dx
1093 or al,#0x10
1094 out dx,al
1095 mov dx,#0x104
1096 in al,dx
1097 mov bl,al
1098 mov dx,#0x3c3
1099 in al,dx
1100 and al,#0xef
1101 out dx,al
1102 cmp bl,#0xa5
1103 je cantok
1104 xor bp,bp
1105 cantok: ret
1106
1107 chips_md:
1108 .byte 0x60, 0x19, 0x84
1109 .byte 0x61, 0x32, 0x84
1110 .byte 0
1111 .ascii "Chips & Technologies"
1112 .byte 0
1113
1114 ! Cirrus Logic 5X0
1115
1116 cirrus1_test:
1117 mov dx,#0x3d4
1118 mov al,#0x0c
1119 out dx,al
1120 inc dx
1121 in al,dx
1122 mov bl,al
1123 xor al,al
1124 out dx,al
1125 dec dx
1126 mov al,#0x1f
1127 out dx,al
1128 inc dx
1129 in al,dx
1130 mov bh,al
1131 xor ah,ah
1132 shl al,#4
1133 mov cx,ax
1134 mov al,bh
1135 shr al,#4
1136 add cx,ax
1137 shl cx,#8
1138 add cx,#6
1139 mov ax,cx
1140 mov dx,#0x3c4
1141 out dx,ax
1142 inc dx
1143 in al,dx
1144 and al,al
1145 jnz nocirr
1146 mov al,bh
1147 out dx,al
1148 in al,dx
1149 cmp al,#0x01
1150 je iscirr
1151 nocirr: xor bp,bp
1152 iscirr: mov dx,#0x3d4
1153 mov al,bl
1154 xor ah,ah
1155 shl ax,#8
1156 add ax,#0x0c
1157 out dx,ax
1158 ret
1159
1160 cirrus1_md:
1161 .byte 0x1f, 0x19, 0x84
1162 .byte 0x20, 0x2c, 0x84
1163 .byte 0x22, 0x1e, 0x84
1164 .byte 0x31, 0x25, 0x64
1165 .byte 0
1166 .ascii "Cirrus Logic 5X0"
1167 .byte 0
1168
1169 ! Cirrus Logic 54XX
1170
1171 cirrus5_test:
1172 mov dx,#0x3c4
1173 mov al,#6
1174 call inidx
1175 mov bl,al ! BL=backup
1176 mov ax,#6
1177 call tstidx
1178 cmp al,#0x0f
1179 jne c5fail
1180 mov ax,#0x1206
1181 call tstidx
1182 cmp al,#0x12
1183 jne c5fail
1184 mov al,#0x1e
1185 call inidx
1186 mov bh,al
1187 mov ah,bh
1188 and ah,#0xc0
1189 mov al,#0x1e
1190 call tstidx
1191 and al,#0x3f
1192 jne c5xx
1193 mov al,#0x1e
1194 mov ah,bh
1195 or ah,#0x3f
1196 call tstidx
1197 xor al,#0x3f
1198 and al,#0x3f
1199 c5xx: pushf
1200 mov al,#0x1e
1201 mov ah,bh
1202 out dx,ax
1203 popf
1204 je c5done
1205 c5fail: xor bp,bp
1206 c5done: mov al,#6
1207 mov ah,bl
1208 out dx,ax
1209 ret
1210
1211 cirrus5_md:
1212 .byte 0x14, 0x19, 0x84
1213 .byte 0x54, 0x2b, 0x84
1214 .byte 0
1215 .ascii "Cirrus Logic 54XX"
1216 .byte 0
1217
1218 ! Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1219 ! it's misidentified by the Ahead test.
1220
1221 cirrus6_test:
1222 mov dx,#0x3ce
1223 mov al,#0x0a
1224 call inidx
1225 mov bl,al ! BL=backup
1226 mov ax,#0xce0a
1227 call tstidx
1228 or al,al
1229 jne c2fail
1230 mov ax,#0xec0a
1231 call tstidx
1232 cmp al,#0x01
1233 jne c2fail
1234 mov al,#0xaa
1235 call inidx ! 4X, 5X, 7X and 8X are valid 64XX chip ID's
1236 shr al,#4
1237 sub al,#4
1238 jz c6done
1239 dec al
1240 jz c6done
1241 sub al,#2
1242 jz c6done
1243 dec al
1244 jz c6done
1245 c2fail: xor bp,bp
1246 c6done: mov al,#0x0a
1247 mov ah,bl
1248 out dx,ax
1249 ret
1250
1251 cirrus6_md:
1252 .byte 0
1253 .ascii "Cirrus Logic 64XX"
1254 .byte 0
1255
1256 ! Everex / Trident
1257
1258 everex_test:
1259 mov ax,#0x7000
1260 xor bx,bx
1261 int 0x10
1262 cmp al,#0x70
1263 jne noevrx
1264 shr dx,#4
1265 cmp dx,#0x678
1266 je evtrid
1267 cmp dx,#0x236
1268 jne evrxok
1269 evtrid: lea bp,trident_md
1270 evrxok: ret
1271
1272 noevrx: xor bp,bp
1273 ret
1274
1275 everex_md:
1276 .byte 0x03, 0x22, 0x50
1277 .byte 0x04, 0x3c, 0x50
1278 .byte 0x07, 0x2b, 0x64
1279 .byte 0x08, 0x4b, 0x64
1280 .byte 0x0a, 0x19, 0x84
1281 .byte 0x0b, 0x2c, 0x84
1282 .byte 0x16, 0x1e, 0x50
1283 .byte 0x18, 0x1b, 0x64
1284 .byte 0x21, 0x40, 0xa0
1285 .byte 0x40, 0x1e, 0x84
1286 .byte 0
1287 .ascii "Everex/Trident"
1288 .byte 0
1289
1290 ! Genoa.
1291
1292 genoa_test:
1293 lea si,idgenoa ! Check Genoa 'clues'
1294 xor ax,ax
1295 seg es
1296 mov al,[0x37]
1297 mov di,ax
1298 mov cx,#0x04
1299 dec si
1300 dec di
1301 l1: inc si
1302 inc di
1303 mov al,(si)
1304 test al,al
1305 jz l2
1306 seg es
1307 cmp al,(di)
1308 l2: loope l1
1309 or cx,cx
1310 je isgen
1311 xor bp,bp
1312 isgen: ret
1313
1314 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1315
1316 genoa_md:
1317 .byte 0x58, 0x20, 0x50
1318 .byte 0x5a, 0x2a, 0x64
1319 .byte 0x60, 0x19, 0x84
1320 .byte 0x61, 0x1d, 0x84
1321 .byte 0x62, 0x20, 0x84
1322 .byte 0x63, 0x2c, 0x84
1323 .byte 0x64, 0x3c, 0x84
1324 .byte 0x6b, 0x4f, 0x64
1325 .byte 0x72, 0x3c, 0x50
1326 .byte 0x74, 0x42, 0x50
1327 .byte 0x78, 0x4b, 0x64
1328 .byte 0
1329 .ascii "Genoa"
1330 .byte 0
1331
1332 ! OAK
1333
1334 oak_test:
1335 lea si,idoakvga
1336 mov di,#0x08
1337 mov cx,#0x08
1338 repe
1339 cmpsb
1340 je isoak
1341 xor bp,bp
1342 isoak: ret
1343
1344 idoakvga: .ascii "OAK VGA "
1345
1346 oak_md: .byte 0x4e, 0x3c, 0x50
1347 .byte 0x4f, 0x3c, 0x84
1348 .byte 0x50, 0x19, 0x84
1349 .byte 0x51, 0x2b, 0x84
1350 .byte 0
1351 .ascii "OAK"
1352 .byte 0
1353
1354 ! WD Paradise.
1355
1356 paradise_test:
1357 lea si,idparadise
1358 mov di,#0x7d
1359 mov cx,#0x04
1360 repe
1361 cmpsb
1362 je ispara
1363 xor bp,bp
1364 ispara: ret
1365
1366 idparadise: .ascii "VGA="
1367
1368 paradise_md:
1369 .byte 0x41, 0x22, 0x50
1370 .byte 0x47, 0x1c, 0x84
1371 .byte 0x55, 0x19, 0x84
1372 .byte 0x54, 0x2c, 0x84
1373 .byte 0
1374 .ascii "Paradise"
1375 .byte 0
1376
1377 ! Trident.
1378
1379 trident_test:
1380 mov dx,#0x3c4
1381 mov al,#0x0e
1382 out dx,al
1383 inc dx
1384 in al,dx
1385 xchg ah,al
1386 xor al,al
1387 out dx,al
1388 in al,dx
1389 xchg al,ah
1390 mov bl,al ! Strange thing ... in the book this wasn't
1391 and bl,#0x02 ! necessary but it worked on my card which
1392 jz setb2 ! is a trident. Without it the screen goes
1393 and al,#0xfd ! blurred ...
1394 jmp clrb2 !
1395 setb2: or al,#0x02 !
1396 clrb2: out dx,al
1397 and ah,#0x0f
1398 cmp ah,#0x02
1399 je istrid
1400 xor bp,bp
1401 istrid: ret
1402
1403 trident_md:
1404 .byte 0x50, 0x1e, 0x50
1405 .byte 0x51, 0x2b, 0x50
1406 .byte 0x52, 0x3c, 0x50
1407 .byte 0x57, 0x19, 0x84
1408 .byte 0x58, 0x1e, 0x84
1409 .byte 0x59, 0x2b, 0x84
1410 .byte 0x5a, 0x3c, 0x84
1411 .byte 0
1412 .ascii "Trident"
1413 .byte 0
1414
1415 ! Tseng.
1416
1417 tseng_test:
1418 mov dx,#0x3cd
1419 in al,dx ! Could things be this simple ! :-)
1420 mov bl,al
1421 mov al,#0x55
1422 out dx,al
1423 in al,dx
1424 mov ah,al
1425 mov al,bl
1426 out dx,al
1427 cmp ah,#0x55
1428 je istsen
1429 xor bp,bp
1430 istsen: ret
1431
1432 tseng_md:
1433 .byte 0x26, 0x3c, 0x50
1434 .byte 0x2a, 0x28, 0x64
1435 .byte 0x23, 0x19, 0x84
1436 .byte 0x24, 0x1c, 0x84
1437 .byte 0x22, 0x2c, 0x84
1438 .byte 0x21, 0x3c, 0x84
1439 .byte 0
1440 .ascii "Tseng"
1441 .byte 0
1442
1443 ! Video7.
1444
1445 video7_test:
1446 mov dx,#0x3cc
1447 in al,dx
1448 mov dx,#0x3b4
1449 and al,#0x01
1450 jz even7
1451 mov dx,#0x3d4
1452 even7: mov al,#0x0c
1453 out dx,al
1454 inc dx
1455 in al,dx
1456 mov bl,al
1457 mov al,#0x55
1458 out dx,al
1459 in al,dx
1460 dec dx
1461 mov al,#0x1f
1462 out dx,al
1463 inc dx
1464 in al,dx
1465 mov bh,al
1466 dec dx
1467 mov al,#0x0c
1468 out dx,al
1469 inc dx
1470 mov al,bl
1471 out dx,al
1472 mov al,#0x55
1473 xor al,#0xea
1474 cmp al,bh
1475 je isvid7
1476 xor bp,bp
1477 isvid7: ret
1478
1479 video7_md:
1480 .byte 0x40, 0x2b, 0x50
1481 .byte 0x43, 0x3c, 0x50
1482 .byte 0x44, 0x3c, 0x64
1483 .byte 0x41, 0x19, 0x84
1484 .byte 0x42, 0x2c, 0x84
1485 .byte 0x45, 0x1c, 0x84
1486 .byte 0
1487 .ascii "Video 7"
1488 .byte 0
1489
1490 #endif
1491
1492 !
1493 ! User-defined local mode table (VGA only)
1494 !
1495
1496 #ifdef CONFIG_VIDEO_LOCAL
1497
1498 local_modes:
1499 lea si,local_mode_table
1500 locm1: lodsw
1501 or ax,ax
1502 jz locm2
1503 stosw
1504 movsw
1505 jmp locm1
1506 locm2: ret
1507
1508 ! This is the table of local video modes which can be supplied manually
1509 ! by the user. Each entry consists of mode ID (word) and dimensions
1510 ! (byte for column count and another byte for row count). These modes
1511 ! are placed before all SVGA and VESA modes and override them if table
1512 ! compacting is enabled. The table must end with a zero word followed
1513 ! by NUL-terminated video adapter name.
1514
1515 local_mode_table:
1516 .word 0x0100 ! Example: 40x25
1517 .byte 25,40
1518 .word 0
1519 .ascii "Local"
1520 .byte 0
1521
1522 #endif
1523
1524 !
1525 ! Read a key and return the ASCII code in al, scan code in ah
1526 !
1527
1528 getkey: xor ah,ah
1529 int 0x16
1530 ret
1531
1532 !
1533 ! Read a key with a timeout of 30 seconds. The hardware clock is used to get
1534 ! the time.
1535 !
1536
1537 getkt: call gettime
1538 add al,#30 ! Wait 30 seconds
1539 cmp al,#60
1540 jl lminute
1541 sub al,#60
1542 lminute:
1543 mov cl,al
1544 again: mov ah,#0x01
1545 int 0x16
1546 jnz getkey ! key pressed, so get it
1547 call gettime
1548 cmp al,cl
1549 jne again
1550 mov al,#0x20 ! timeout, return default char `space'
1551 ret
1552
1553 !
1554 ! Flush the keyboard buffer
1555 !
1556
1557 flush: mov ah,#0x01
1558 int 0x16
1559 jz empty
1560 xor ah,ah
1561 int 0x16
1562 jmp flush
1563 empty: ret
1564
1565 !
1566 ! Print hexadecimal number.
1567 !
1568
1569 prthw: push ax
1570 mov al,ah
1571 call prthb
1572 pop ax
1573 prthb: push ax
1574 shr al,#4
1575 call prthn
1576 pop ax
1577 and al,#0x0f
1578 prthn: cmp al,#0x0a
1579 jc prth1
1580 add al,#0x07
1581 prth1: add al,#0x30
1582 br prtchr
1583
1584 !
1585 ! Print decimal number (AL).
1586 !
1587
1588 prtdec: push ax
1589 push cx
1590 xor ah,ah ! Clear ah
1591 mov cl,#0x0a
1592 idiv cl
1593 cmp al,#0x09
1594 jbe lt100
1595 call prtdec
1596 jmp skip10
1597 lt100: add al,#0x30
1598 call prtchr
1599 skip10: mov al,ah
1600 add al,#0x30
1601 call prtchr
1602 pop cx
1603 pop ax
1604 ret
1605
1606 ! Variables:
1607
1608 adapter: .byte 0 ! Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
1609 def_mode: .byte 0 ! "Default mode selected" flag
1610 mt_end: .word 0 ! End of video mode table if built
1611 edit_buf: .space 6 ! Line editor buffer
1612 card_name: .word 0 ! Pointer to adapter name
1613 scanning: .byte 0 ! Performing mode scan
1614 do_restore: .byte 0 ! Screen contents altered during mode change
1615 video_segment: .word 0xb800 ! Video memory segment
1616
1617 ! Messages:
1618
1619 keymsg: .ascii "Press <RETURN> to see video modes available, "
1620 .ascii "<SPACE> to continue or wait 30 secs"
1621 db 0x0d, 0x0a, 0
1622 listhdr: db 0x0d, 0x0a
1623 .ascii "Mode: COLSxROWS:"
1624 crlft: db 0x0d, 0x0a, 0
1625 prompt: db 0x0d, 0x0a
1626 .ascii "Enter mode number: "
1627 db 0
1628 unknt: .ascii "Unknown mode ID. Try again."
1629 db 0
1630 badmdt: .ascii "You passed an undefined mode number to setup."
1631 db 0x0d, 0x0a, 0
1632 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
1633 .ascii "report to <mj@k332.feld.cvut.cz>."
1634 db 0x0d, 0x0a, 0
1635 old_name: .ascii "CGA/MDA/HGA"
1636 db 0
1637 ega_name: .ascii "EGA"
1638 db 0
1639 svga_name: .ascii " "
1640 vga_name: .ascii "VGA"
1641 db 0
1642 vesa_name: .ascii "VESA"
1643 db 0
1644 name_bann: .ascii "Video adapter: "
1645 db 0