- improved VGA compatible setup for VBE modes (disable CGA and Hercules
[vgabios.git] / vgabios.c
bloba1fb756c658a244007ab23f9fcccc8f11b71f6ba
1 // ============================================================================================
2 /*
3 * vgabios.c
4 */
5 // ============================================================================================
6 //
7 // Copyright (C) 2001,2002 the LGPL VGABios developers Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // ============================================================================================
24 //
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
27 //
28 // ============================================================================================
29 //
30 // This file contains code ripped from :
31 // - rombios.c of plex86
33 // This VGA Bios contains fonts from :
34 // - fntcol16.zip (c) by Joseph Gil avalable at :
35 // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36 // These fonts are public domain
38 // This VGA Bios is based on information taken from :
39 // - Kevin Lawton's vga card emulation for bochs/plex86
40 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41 // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42 // - Michael Abrash's Graphics Programming Black Book
43 // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44 // - DOSEMU 1.0.1 source code for several tables values and formulas
46 // Thanks for patches, comments and ideas to :
47 // - techt@pikeonline.net
49 // ============================================================================================
51 #include "vgabios.h"
53 #ifdef VBE
54 #include "vbe.h"
55 #endif
57 #define USE_BX_INFO
59 /* Declares */
60 static Bit8u read_byte();
61 static Bit16u read_word();
62 static void write_byte();
63 static void write_word();
64 static Bit8u inb();
65 static Bit16u inw();
66 static void outb();
67 static void outw();
69 static Bit16u get_SS();
71 // Output
72 static void printf();
73 static void unimplemented();
74 static void unknown();
76 static Bit8u find_vga_entry();
78 static void memsetb();
79 static void memsetw();
80 static void memcpyb();
81 static void memcpyw();
83 static void biosfn_set_video_mode();
84 static void biosfn_set_cursor_shape();
85 static void biosfn_set_cursor_pos();
86 static void biosfn_get_cursor_pos();
87 static void biosfn_set_active_page();
88 static void biosfn_scroll();
89 static void biosfn_read_char_attr();
90 static void biosfn_write_char_attr();
91 static void biosfn_write_char_only();
92 static void biosfn_write_pixel();
93 static void biosfn_read_pixel();
94 static void biosfn_write_teletype();
95 static void biosfn_perform_gray_scale_summing();
96 static void biosfn_load_text_user_pat();
97 static void biosfn_load_text_8_14_pat();
98 static void biosfn_load_text_8_8_pat();
99 static void biosfn_load_text_8_16_pat();
100 static void biosfn_load_gfx_8_8_chars();
101 static void biosfn_load_gfx_user_chars();
102 static void biosfn_load_gfx_8_14_chars();
103 static void biosfn_load_gfx_8_8_dd_chars();
104 static void biosfn_load_gfx_8_16_chars();
105 static void biosfn_get_font_info();
106 static void biosfn_alternate_prtsc();
107 static void biosfn_switch_video_interface();
108 static void biosfn_enable_video_refresh_control();
109 static void biosfn_write_string();
110 static void biosfn_read_state_info();
111 static void biosfn_read_video_state_size();
112 static Bit16u biosfn_save_video_state();
113 static Bit16u biosfn_restore_video_state();
114 extern Bit8u video_save_pointer_table[];
116 // This is for compiling with gcc2 and gcc3
117 #define ASM_START #asm
118 #define ASM_END #endasm
120 ASM_START
122 MACRO SET_INT_VECTOR
123 push ds
124 xor ax, ax
125 mov ds, ax
126 mov ax, ?3
127 mov ?1*4, ax
128 mov ax, ?2
129 mov ?1*4+2, ax
130 pop ds
131 MEND
133 ASM_END
135 ASM_START
136 .text
137 .rom
138 .org 0
140 use16 386
142 vgabios_start:
143 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
145 .byte 0x40 /* BIOS extension length in units of 512 bytes */
148 vgabios_entry_point:
150 jmp vgabios_init_func
152 vgabios_name:
153 .ascii "Plex86/Bochs VGABios"
154 .ascii " "
155 .byte 0x00
157 // Info from Bart Oldeman
158 .org 0x1e
159 .ascii "IBM"
160 .byte 0x00
162 vgabios_version:
163 #ifndef VGABIOS_VERS
164 .ascii "current-cvs"
165 #else
166 .ascii VGABIOS_VERS
167 #endif
168 .ascii " "
170 vgabios_date:
171 .ascii VGABIOS_DATE
172 .byte 0x0a,0x0d
173 .byte 0x00
175 vgabios_copyright:
176 .ascii "(C) 2003 the LGPL VGABios developers Team"
177 .byte 0x0a,0x0d
178 .byte 0x00
180 vgabios_license:
181 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
182 .byte 0x0a,0x0d
183 .byte 0x0a,0x0d
184 .byte 0x00
186 vgabios_website:
187 .ascii "Please visit :"
188 .byte 0x0a,0x0d
189 ;;.ascii " . http://www.plex86.org"
190 ;;.byte 0x0a,0x0d
191 .ascii " . http://bochs.sourceforge.net"
192 .byte 0x0a,0x0d
193 .ascii " . http://www.nongnu.org/vgabios"
194 .byte 0x0a,0x0d
195 .byte 0x0a,0x0d
196 .byte 0x00
199 ;; ============================================================================================
201 ;; Init Entry point
203 ;; ============================================================================================
204 vgabios_init_func:
206 ;; init vga card
207 call init_vga_card
209 ;; init basic bios vars
210 call init_bios_area
212 #ifdef VBE
213 ;; init vbe functions
214 call vbe_init
215 #endif
217 ;; set int10 vect
218 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
220 #ifdef CIRRUS
221 call cirrus_init
222 #endif
224 ;; display splash screen
225 call _display_splash_screen
227 ;; init video mode and clear the screen
228 mov ax,#0x0003
229 int #0x10
231 ;; show info
232 call _display_info
234 #ifdef VBE
235 ;; show vbe info
236 call vbe_display_info
237 #endif
239 #ifdef CIRRUS
240 ;; show cirrus info
241 call cirrus_display_info
242 #endif
244 retf
245 ASM_END
248 * int10 handled here
250 ASM_START
251 vgabios_int10_handler:
252 pushf
253 #ifdef DEBUG
254 push es
255 push ds
256 pusha
257 mov bx, #0xc000
258 mov ds, bx
259 call _int10_debugmsg
260 popa
261 pop ds
262 pop es
263 #endif
264 cmp ah, #0x0f
265 jne int10_test_1A
266 call biosfn_get_video_mode
267 jmp int10_end
268 int10_test_1A:
269 cmp ah, #0x1a
270 jne int10_test_0B
271 call biosfn_group_1A
272 jmp int10_end
273 int10_test_0B:
274 cmp ah, #0x0b
275 jne int10_test_1103
276 call biosfn_group_0B
277 jmp int10_end
278 int10_test_1103:
279 cmp ax, #0x1103
280 jne int10_test_12
281 call biosfn_set_text_block_specifier
282 jmp int10_end
283 int10_test_12:
284 cmp ah, #0x12
285 jne int10_test_101B
286 cmp bl, #0x10
287 jne int10_test_BL30
288 call biosfn_get_ega_info
289 jmp int10_end
290 int10_test_BL30:
291 cmp bl, #0x30
292 jne int10_test_BL31
293 call biosfn_select_vert_res
294 jmp int10_end
295 int10_test_BL31:
296 cmp bl, #0x31
297 jne int10_test_BL32
298 call biosfn_enable_default_palette_loading
299 jmp int10_end
300 int10_test_BL32:
301 cmp bl, #0x32
302 jne int10_test_BL33
303 call biosfn_enable_video_addressing
304 jmp int10_end
305 int10_test_BL33:
306 cmp bl, #0x33
307 jne int10_test_BL34
308 call biosfn_enable_grayscale_summing
309 jmp int10_end
310 int10_test_BL34:
311 cmp bl, #0x34
312 jne int10_normal
313 call biosfn_enable_cursor_emulation
314 jmp int10_end
315 int10_test_101B:
316 cmp ax, #0x101b
317 je int10_normal
318 cmp ah, #0x10
319 #ifndef VBE
320 jne int10_normal
321 #else
322 jne int10_test_4F
323 #endif
324 call biosfn_group_10
325 jmp int10_end
326 #ifdef VBE
327 int10_test_4F:
328 cmp ah, #0x4f
329 jne int10_normal
330 cmp al, #0x03
331 jne int10_test_vbe_05
332 call vbe_biosfn_return_current_mode
333 jmp int10_end
334 int10_test_vbe_05:
335 cmp al, #0x05
336 jne int10_test_vbe_06
337 call vbe_biosfn_display_window_control
338 jmp int10_end
339 int10_test_vbe_06:
340 cmp al, #0x06
341 jne int10_test_vbe_07
342 call vbe_biosfn_set_get_logical_scan_line_length
343 jmp int10_end
344 int10_test_vbe_07:
345 cmp al, #0x07
346 jne int10_test_vbe_08
347 call vbe_biosfn_set_get_display_start
348 jmp int10_end
349 int10_test_vbe_08:
350 cmp al, #0x08
351 jne int10_test_vbe_0A
352 call vbe_biosfn_set_get_dac_palette_format
353 jmp int10_end
354 int10_test_vbe_0A:
355 cmp al, #0x0A
356 jne int10_normal
357 call vbe_biosfn_return_protected_mode_interface
358 jmp int10_end
359 #endif
361 int10_normal:
362 push es
363 push ds
364 pusha
366 ;; We have to set ds to access the right data segment
367 mov bx, #0xc000
368 mov ds, bx
369 call _int10_func
371 popa
372 pop ds
373 pop es
374 int10_end:
375 popf
376 iret
377 ASM_END
379 #include "vgatables.h"
380 #include "vgafonts.h"
383 * Boot time harware inits
385 ASM_START
386 init_vga_card:
387 ;; switch to color mode and enable CPU access 480 lines
388 mov dx, #0x3C2
389 mov al, #0xC3
390 outb dx,al
392 ;; more than 64k 3C4/04
393 mov dx, #0x3C4
394 mov al, #0x04
395 outb dx,al
396 mov dx, #0x3C5
397 mov al, #0x02
398 outb dx,al
400 #if defined(USE_BX_INFO) || defined(DEBUG)
401 mov bx, #msg_vga_init
402 push bx
403 call _printf
404 #endif
405 inc sp
406 inc sp
409 #if defined(USE_BX_INFO) || defined(DEBUG)
410 msg_vga_init:
411 .ascii "VGABios $Id$"
412 .byte 0x0d,0x0a,0x00
413 #endif
414 ASM_END
416 // --------------------------------------------------------------------------------------------
418 * Boot time bios area inits
420 ASM_START
421 init_bios_area:
422 push ds
423 mov ax, # BIOSMEM_SEG
424 mov ds, ax
426 ;; init detected hardware BIOS Area
427 mov bx, # BIOSMEM_INITIAL_MODE
428 mov ax, [bx]
429 and ax, #0xffcf
430 ;; set 80x25 color (not clear from RBIL but usual)
431 or ax, #0x0020
432 mov [bx], ax
434 ;; Just for the first int10 find its children
436 ;; the default char height
437 mov bx, # BIOSMEM_CHAR_HEIGHT
438 mov al, #0x10
439 mov [bx], al
441 ;; Clear the screen
442 mov bx, # BIOSMEM_VIDEO_CTL
443 mov al, #0x60
444 mov [bx], al
446 ;; Set the basic screen we have
447 mov bx, # BIOSMEM_SWITCHES
448 mov al, #0xf9
449 mov [bx], al
451 ;; Set the basic modeset options
452 mov bx, # BIOSMEM_MODESET_CTL
453 mov al, #0x51
454 mov [bx], al
456 ;; Set the default MSR
457 mov bx, # BIOSMEM_CURRENT_MSR
458 mov al, #0x09
459 mov [bx], al
461 pop ds
464 _video_save_pointer_table:
465 .word _video_param_table
466 .word 0xc000
468 .word 0 /* XXX: fill it */
469 .word 0
471 .word 0 /* XXX: fill it */
472 .word 0
474 .word 0 /* XXX: fill it */
475 .word 0
477 .word 0 /* XXX: fill it */
478 .word 0
480 .word 0 /* XXX: fill it */
481 .word 0
483 .word 0 /* XXX: fill it */
484 .word 0
486 ASM_END
488 // --------------------------------------------------------------------------------------------
490 * Boot time Splash screen
492 static void display_splash_screen()
496 // --------------------------------------------------------------------------------------------
498 * Tell who we are
501 static void display_info()
503 ASM_START
504 mov ax,#0xc000
505 mov ds,ax
506 mov si,#vgabios_name
507 call _display_string
508 mov si,#vgabios_version
509 call _display_string
511 ;;mov si,#vgabios_copyright
512 ;;call _display_string
513 ;;mov si,#crlf
514 ;;call _display_string
516 mov si,#vgabios_license
517 call _display_string
518 mov si,#vgabios_website
519 call _display_string
520 ASM_END
523 static void display_string()
525 // Get length of string
526 ASM_START
527 mov ax,ds
528 mov es,ax
529 mov di,si
530 xor cx,cx
531 not cx
532 xor al,al
534 repne
535 scasb
536 not cx
537 dec cx
538 push cx
540 mov ax,#0x0300
541 mov bx,#0x0000
542 int #0x10
544 pop cx
545 mov ax,#0x1301
546 mov bx,#0x000b
547 mov bp,si
548 int #0x10
549 ASM_END
552 // --------------------------------------------------------------------------------------------
553 #ifdef DEBUG
554 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
555 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
557 // 0E is write char...
558 if(GET_AH()!=0x0E)
559 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
561 #endif
563 // --------------------------------------------------------------------------------------------
565 * int10 main dispatcher
567 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
568 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
571 // BIOS functions
572 switch(GET_AH())
574 case 0x00:
575 biosfn_set_video_mode(GET_AL());
576 switch(GET_AL()&0x7F)
577 {case 6:
578 SET_AL(0x3F);
579 break;
580 case 0:
581 case 1:
582 case 2:
583 case 3:
584 case 4:
585 case 5:
586 case 7:
587 SET_AL(0x30);
588 break;
589 default:
590 SET_AL(0x20);
592 break;
593 case 0x01:
594 biosfn_set_cursor_shape(GET_CH(),GET_CL());
595 break;
596 case 0x02:
597 biosfn_set_cursor_pos(GET_BH(),DX);
598 break;
599 case 0x03:
600 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
601 break;
602 case 0x04:
603 // Read light pen pos (unimplemented)
604 #ifdef DEBUG
605 unimplemented();
606 #endif
607 AX=0x00;
608 BX=0x00;
609 CX=0x00;
610 DX=0x00;
611 break;
612 case 0x05:
613 biosfn_set_active_page(GET_AL());
614 break;
615 case 0x06:
616 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
617 break;
618 case 0x07:
619 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
620 break;
621 case 0x08:
622 biosfn_read_char_attr(GET_BH(),&AX);
623 break;
624 case 0x09:
625 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
626 break;
627 case 0x0A:
628 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
629 break;
630 case 0x0C:
631 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
632 break;
633 case 0x0D:
634 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
635 break;
636 case 0x0E:
637 // Ralf Brown Interrupt list is WRONG on bh(page)
638 // We do output only on the current page !
639 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
640 break;
641 case 0x10:
642 // All other functions of group AH=0x10 rewritten in assembler
643 biosfn_perform_gray_scale_summing(BX,CX);
644 break;
645 case 0x11:
646 switch(GET_AL())
648 case 0x00:
649 case 0x10:
650 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
651 break;
652 case 0x01:
653 case 0x11:
654 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
655 break;
656 case 0x02:
657 case 0x12:
658 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
659 break;
660 case 0x04:
661 case 0x14:
662 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
663 break;
664 case 0x20:
665 biosfn_load_gfx_8_8_chars(ES,BP);
666 break;
667 case 0x21:
668 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
669 break;
670 case 0x22:
671 biosfn_load_gfx_8_14_chars(GET_BL());
672 break;
673 case 0x23:
674 biosfn_load_gfx_8_8_dd_chars(GET_BL());
675 break;
676 case 0x24:
677 biosfn_load_gfx_8_16_chars(GET_BL());
678 break;
679 case 0x30:
680 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
681 break;
682 #ifdef DEBUG
683 default:
684 unknown();
685 #endif
688 break;
689 case 0x12:
690 switch(GET_BL())
692 case 0x20:
693 biosfn_alternate_prtsc();
694 break;
695 case 0x35:
696 biosfn_switch_video_interface(GET_AL(),ES,DX);
697 SET_AL(0x12);
698 break;
699 case 0x36:
700 biosfn_enable_video_refresh_control(GET_AL());
701 SET_AL(0x12);
702 break;
703 #ifdef DEBUG
704 default:
705 unknown();
706 #endif
708 break;
709 case 0x13:
710 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
711 break;
712 case 0x1B:
713 biosfn_read_state_info(BX,ES,DI);
714 SET_AL(0x1B);
715 break;
716 case 0x1C:
717 switch(GET_AL())
719 case 0x00:
720 biosfn_read_video_state_size(CX,&BX);
721 break;
722 case 0x01:
723 biosfn_save_video_state(CX,ES,BX);
724 break;
725 case 0x02:
726 biosfn_restore_video_state(CX,ES,BX);
727 break;
728 #ifdef DEBUG
729 default:
730 unknown();
731 #endif
733 SET_AL(0x1C);
734 break;
736 #ifdef VBE
737 case 0x4f:
738 if (vbe_has_vbe_display()) {
739 switch(GET_AL())
741 case 0x00:
742 vbe_biosfn_return_controller_information(&AX,ES,DI);
743 break;
744 case 0x01:
745 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
746 break;
747 case 0x02:
748 vbe_biosfn_set_mode(&AX,BX,ES,DI);
749 break;
750 case 0x04:
751 vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
752 break;
753 case 0x09:
754 //FIXME
755 #ifdef DEBUG
756 unimplemented();
757 #endif
758 // function failed
759 AX=0x100;
760 break;
761 case 0x0A:
762 //FIXME
763 #ifdef DEBUG
764 unimplemented();
765 #endif
766 // function failed
767 AX=0x100;
768 break;
769 default:
770 #ifdef DEBUG
771 unknown();
772 #endif
773 // function failed
774 AX=0x100;
777 else {
778 // No VBE display
779 AX=0x0100;
781 break;
782 #endif
784 #ifdef DEBUG
785 default:
786 unknown();
787 #endif
791 // ============================================================================================
793 // BIOS functions
795 // ============================================================================================
797 static void biosfn_set_video_mode(mode) Bit8u mode;
798 {// mode: Bit 7 is 1 if no clear screen
800 // Should we clear the screen ?
801 Bit8u noclearmem=mode&0x80;
802 Bit8u line,mmask,*palette,vpti;
803 Bit16u i,twidth,theightm1,cheight;
804 Bit8u modeset_ctl,video_ctl,vga_switches;
805 Bit16u crtc_addr;
807 #ifdef VBE
808 if (vbe_has_vbe_display()) {
809 dispi_set_enable(VBE_DISPI_DISABLED);
811 #endif // def VBE
813 // The real mode
814 mode=mode&0x7f;
816 // find the entry in the video modes
817 line=find_vga_entry(mode);
819 #ifdef DEBUG
820 printf("mode search %02x found line %02x\n",mode,line);
821 #endif
823 if(line==0xFF)
824 return;
826 vpti=line_to_vpti[line];
827 twidth=video_param_table[vpti].twidth;
828 theightm1=video_param_table[vpti].theightm1;
829 cheight=video_param_table[vpti].cheight;
831 // Read the bios vga control
832 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
834 // Read the bios vga switches
835 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
837 // Read the bios mode set control
838 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
840 // Then we know the number of lines
841 // FIXME
843 // if palette loading (bit 3 of modeset ctl = 0)
844 if((modeset_ctl&0x08)==0)
845 {// Set the PEL mask
846 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
848 // Set the whole dac always, from 0
849 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
851 // From which palette
852 switch(vga_modes[line].dacmodel)
853 {case 0:
854 palette=&palette0;
855 break;
856 case 1:
857 palette=&palette1;
858 break;
859 case 2:
860 palette=&palette2;
861 break;
862 case 3:
863 palette=&palette3;
864 break;
866 // Always 256*3 values
867 for(i=0;i<0x0100;i++)
868 {if(i<=dac_regs[vga_modes[line].dacmodel])
869 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
870 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
871 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
873 else
874 {outb(VGAREG_DAC_DATA,0);
875 outb(VGAREG_DAC_DATA,0);
876 outb(VGAREG_DAC_DATA,0);
879 if((modeset_ctl&0x02)==0x02)
881 biosfn_perform_gray_scale_summing(0x00, 0x100);
885 // Reset Attribute Ctl flip-flop
886 inb(VGAREG_ACTL_RESET);
888 // Set Attribute Ctl
889 for(i=0;i<=0x13;i++)
890 {outb(VGAREG_ACTL_ADDRESS,i);
891 outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
893 outb(VGAREG_ACTL_ADDRESS,0x14);
894 outb(VGAREG_ACTL_WRITE_DATA,0x00);
896 // Set Sequencer Ctl
897 outb(VGAREG_SEQU_ADDRESS,0);
898 outb(VGAREG_SEQU_DATA,0x03);
899 for(i=1;i<=4;i++)
900 {outb(VGAREG_SEQU_ADDRESS,i);
901 outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
904 // Set Grafx Ctl
905 for(i=0;i<=8;i++)
906 {outb(VGAREG_GRDC_ADDRESS,i);
907 outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
910 // Set CRTC address VGA or MDA
911 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
913 // Disable CRTC write protection
914 outw(crtc_addr,0x0011);
915 // Set CRTC regs
916 for(i=0;i<=0x18;i++)
917 {outb(crtc_addr,i);
918 outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
921 // Set the misc register
922 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
924 // Enable video
925 outb(VGAREG_ACTL_ADDRESS,0x20);
926 inb(VGAREG_ACTL_RESET);
928 if(noclearmem==0x00)
930 if(vga_modes[line].class==TEXT)
932 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
934 else
936 if(mode<0x0d)
938 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
940 else
942 outb( VGAREG_SEQU_ADDRESS, 0x02 );
943 mmask = inb( VGAREG_SEQU_DATA );
944 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
945 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
946 outb( VGAREG_SEQU_DATA, mmask );
951 // Set the BIOS mem
952 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
953 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
954 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
955 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
956 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
957 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
958 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
959 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
960 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
962 // FIXME We nearly have the good tables. to be reworked
963 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
964 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
965 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
967 // FIXME
968 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
969 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
971 // Set cursor shape
972 if(vga_modes[line].class==TEXT)
974 biosfn_set_cursor_shape(0x06,0x07);
977 // Set cursor pos for page 0..7
978 for(i=0;i<8;i++)
979 biosfn_set_cursor_pos(i,0x0000);
981 // Set active page 0
982 biosfn_set_active_page(0x00);
984 // Write the fonts in memory
985 if(vga_modes[line].class==TEXT)
987 ASM_START
988 ;; copy and activate 8x16 font
989 mov ax, #0x1104
990 mov bl, #0x00
991 int #0x10
992 mov ax, #0x1103
993 mov bl, #0x00
994 int #0x10
995 ASM_END
998 // Set the ints 0x1F and 0x43
999 ASM_START
1000 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1001 ASM_END
1003 switch(cheight)
1004 {case 8:
1005 ASM_START
1006 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1007 ASM_END
1008 break;
1009 case 14:
1010 ASM_START
1011 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1012 ASM_END
1013 break;
1014 case 16:
1015 ASM_START
1016 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1017 ASM_END
1018 break;
1022 // --------------------------------------------------------------------------------------------
1023 static void biosfn_set_cursor_shape (CH,CL)
1024 Bit8u CH;Bit8u CL;
1025 {Bit16u cheight,curs,crtc_addr;
1026 Bit8u modeset_ctl;
1028 CH&=0x3f;
1029 CL&=0x1f;
1031 curs=(CH<<8)+CL;
1032 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1034 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1035 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1036 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1038 if(CL!=(CH+1))
1040 CH = ((CH+1) * cheight / 8) -1;
1042 else
1044 CH = ((CL+1) * cheight / 8) - 2;
1046 CL = ((CL+1) * cheight / 8) - 1;
1049 // CTRC regs 0x0a and 0x0b
1050 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1051 outb(crtc_addr,0x0a);
1052 outb(crtc_addr+1,CH);
1053 outb(crtc_addr,0x0b);
1054 outb(crtc_addr+1,CL);
1057 // --------------------------------------------------------------------------------------------
1058 static void biosfn_set_cursor_pos (page, cursor)
1059 Bit8u page;Bit16u cursor;
1061 Bit8u xcurs,ycurs,current;
1062 Bit16u nbcols,nbrows,address,crtc_addr;
1064 // Should not happen...
1065 if(page>7)return;
1067 // Bios cursor pos
1068 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1070 // Set the hardware cursor
1071 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1072 if(page==current)
1074 // Get the dimensions
1075 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1076 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1078 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1080 // Calculate the address knowing nbcols nbrows and page num
1081 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1083 // CRTC regs 0x0e and 0x0f
1084 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1085 outb(crtc_addr,0x0e);
1086 outb(crtc_addr+1,(address&0xff00)>>8);
1087 outb(crtc_addr,0x0f);
1088 outb(crtc_addr+1,address&0x00ff);
1092 // --------------------------------------------------------------------------------------------
1093 static void biosfn_get_cursor_pos (page,shape, pos)
1094 Bit8u page;Bit16u *shape;Bit16u *pos;
1096 Bit16u ss=get_SS();
1098 // Default
1099 write_word(ss, shape, 0);
1100 write_word(ss, pos, 0);
1102 if(page>7)return;
1103 // FIXME should handle VGA 14/16 lines
1104 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1105 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1108 // --------------------------------------------------------------------------------------------
1109 static void biosfn_set_active_page (page)
1110 Bit8u page;
1112 Bit16u cursor,dummy,crtc_addr;
1113 Bit16u nbcols,nbrows,address;
1114 Bit8u mode,line;
1116 if(page>7)return;
1118 // Get the mode
1119 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1120 line=find_vga_entry(mode);
1121 if(line==0xFF)return;
1123 // Get pos curs pos for the right page
1124 biosfn_get_cursor_pos(page,&dummy,&cursor);
1126 if(vga_modes[line].class==TEXT)
1128 // Get the dimensions
1129 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1130 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1132 // Calculate the address knowing nbcols nbrows and page num
1133 address=SCREEN_MEM_START(nbcols,nbrows,page);
1134 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1136 // Start address
1137 address=SCREEN_IO_START(nbcols,nbrows,page);
1139 else
1141 address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
1144 // CRTC regs 0x0c and 0x0d
1145 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1146 outb(crtc_addr,0x0c);
1147 outb(crtc_addr+1,(address&0xff00)>>8);
1148 outb(crtc_addr,0x0d);
1149 outb(crtc_addr+1,address&0x00ff);
1151 // And change the BIOS page
1152 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1154 #ifdef DEBUG
1155 printf("Set active page %02x address %04x\n",page,address);
1156 #endif
1158 // Display the cursor, now the page is active
1159 biosfn_set_cursor_pos(page,cursor);
1162 // --------------------------------------------------------------------------------------------
1163 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1164 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1166 Bit16u src,dest;
1167 Bit8u i;
1169 src=ysrc*cheight*nbcols+xstart;
1170 dest=ydest*cheight*nbcols+xstart;
1171 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1172 for(i=0;i<cheight;i++)
1174 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1176 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1179 // --------------------------------------------------------------------------------------------
1180 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1181 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1183 Bit16u dest;
1184 Bit8u i;
1186 dest=ystart*cheight*nbcols+xstart;
1187 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1188 for(i=0;i<cheight;i++)
1190 memsetb(0xa000,dest+i*nbcols,attr,cols);
1192 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1195 // --------------------------------------------------------------------------------------------
1196 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1197 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1199 Bit16u src,dest;
1200 Bit8u i;
1202 src=((ysrc*cheight*nbcols)>>1)+xstart;
1203 dest=((ydest*cheight*nbcols)>>1)+xstart;
1204 for(i=0;i<cheight;i++)
1206 if (i & 1)
1207 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1208 else
1209 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1213 // --------------------------------------------------------------------------------------------
1214 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1215 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1217 Bit16u dest;
1218 Bit8u i;
1220 dest=((ystart*cheight*nbcols)>>1)+xstart;
1221 for(i=0;i<cheight;i++)
1223 if (i & 1)
1224 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1225 else
1226 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1230 // --------------------------------------------------------------------------------------------
1231 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1232 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1234 // page == 0xFF if current
1236 Bit8u mode,line,cheight,bpp,cols;
1237 Bit16u nbcols,nbrows,i;
1238 Bit16u address;
1240 if(rul>rlr)return;
1241 if(cul>clr)return;
1243 // Get the mode
1244 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1245 line=find_vga_entry(mode);
1246 if(line==0xFF)return;
1248 // Get the dimensions
1249 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1250 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1252 // Get the current page
1253 if(page==0xFF)
1254 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1256 if(rlr>=nbrows)rlr=nbrows-1;
1257 if(clr>=nbcols)clr=nbcols-1;
1258 if(nblines>nbrows)nblines=0;
1259 cols=clr-cul+1;
1261 if(vga_modes[line].class==TEXT)
1263 // Compute the address
1264 address=SCREEN_MEM_START(nbcols,nbrows,page);
1265 #ifdef DEBUG
1266 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1267 #endif
1269 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1271 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1273 else
1274 {// if Scroll up
1275 if(dir==SCROLL_UP)
1276 {for(i=rul;i<=rlr;i++)
1278 if((i+nblines>rlr)||(nblines==0))
1279 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1280 else
1281 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1284 else
1285 {for(i=rlr;i>=rul;i--)
1287 if((i<rul+nblines)||(nblines==0))
1288 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1289 else
1290 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1291 if (i>rlr) break;
1296 else
1298 // FIXME gfx mode not complete
1299 cheight=video_param_table[line_to_vpti[line]].cheight;
1300 switch(vga_modes[line].memmodel)
1302 case PLANAR4:
1303 case PLANAR1:
1304 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1306 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1307 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1308 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1310 else
1311 {// if Scroll up
1312 if(dir==SCROLL_UP)
1313 {for(i=rul;i<=rlr;i++)
1315 if((i+nblines>rlr)||(nblines==0))
1316 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1317 else
1318 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1321 else
1322 {for(i=rlr;i>=rul;i--)
1324 if((i<rul+nblines)||(nblines==0))
1325 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1326 else
1327 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1328 if (i>rlr) break;
1332 break;
1333 case CGA:
1334 bpp=vga_modes[line].pixbits;
1335 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1337 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1339 else
1341 if(bpp==2)
1343 cul<<=1;
1344 cols<<=1;
1345 nbcols<<=1;
1347 // if Scroll up
1348 if(dir==SCROLL_UP)
1349 {for(i=rul;i<=rlr;i++)
1351 if((i+nblines>rlr)||(nblines==0))
1352 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1353 else
1354 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1357 else
1358 {for(i=rlr;i>=rul;i--)
1360 if((i<rul+nblines)||(nblines==0))
1361 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1362 else
1363 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1364 if (i>rlr) break;
1368 break;
1369 #ifdef DEBUG
1370 default:
1371 printf("Scroll in graphics mode ");
1372 unimplemented();
1373 #endif
1378 // --------------------------------------------------------------------------------------------
1379 static void biosfn_read_char_attr (page,car)
1380 Bit8u page;Bit16u *car;
1381 {Bit16u ss=get_SS();
1382 Bit8u xcurs,ycurs,mode,line;
1383 Bit16u nbcols,nbrows,address;
1384 Bit16u cursor,dummy;
1386 // Get the mode
1387 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1388 line=find_vga_entry(mode);
1389 if(line==0xFF)return;
1391 // Get the cursor pos for the page
1392 biosfn_get_cursor_pos(page,&dummy,&cursor);
1393 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1395 // Get the dimensions
1396 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1397 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1399 if(vga_modes[line].class==TEXT)
1401 // Compute the address
1402 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1404 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1406 else
1408 // FIXME gfx mode
1409 #ifdef DEBUG
1410 unimplemented();
1411 #endif
1415 // --------------------------------------------------------------------------------------------
1416 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1417 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1419 Bit8u i,j,mask;
1420 Bit8u *fdata;
1421 Bit16u addr,dest,src;
1423 switch(cheight)
1424 {case 14:
1425 fdata = &vgafont14;
1426 break;
1427 case 16:
1428 fdata = &vgafont16;
1429 break;
1430 default:
1431 fdata = &vgafont8;
1433 addr=xcurs+ycurs*cheight*nbcols;
1434 src = car * cheight;
1435 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1436 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1437 if(attr&0x80)
1439 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1441 else
1443 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1445 for(i=0;i<cheight;i++)
1447 dest=addr+i*nbcols;
1448 for(j=0;j<8;j++)
1450 mask=0x80>>j;
1451 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1452 read_byte(0xa000,dest);
1453 if(fdata[src+i]&mask)
1455 write_byte(0xa000,dest,attr&0x0f);
1457 else
1459 write_byte(0xa000,dest,0x00);
1463 ASM_START
1464 mov dx, # VGAREG_GRDC_ADDRESS
1465 mov ax, #0xff08
1466 out dx, ax
1467 mov ax, #0x0005
1468 out dx, ax
1469 mov ax, #0x0003
1470 out dx, ax
1471 ASM_END
1474 // --------------------------------------------------------------------------------------------
1475 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1476 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1478 Bit8u i,j,mask,data;
1479 Bit8u *fdata;
1480 Bit16u addr,dest,src;
1482 fdata = &vgafont8;
1483 addr=(xcurs*bpp)+ycurs*320;
1484 src = car * 8;
1485 for(i=0;i<8;i++)
1487 dest=addr+(i>>1)*80;
1488 if (i & 1) dest += 0x2000;
1489 mask = 0x80;
1490 if (bpp == 1)
1492 if (attr & 0x80)
1494 data = read_byte(0xb800,dest);
1496 else
1498 data = 0x00;
1500 for(j=0;j<8;j++)
1502 if (fdata[src+i] & mask)
1504 if (attr & 0x80)
1506 data ^= (attr & 0x01) << (7-j);
1508 else
1510 data |= (attr & 0x01) << (7-j);
1513 mask >>= 1;
1515 write_byte(0xb800,dest,data);
1517 else
1519 while (mask > 0)
1521 if (attr & 0x80)
1523 data = read_byte(0xb800,dest);
1525 else
1527 data = 0x00;
1529 for(j=0;j<4;j++)
1531 if (fdata[src+i] & mask)
1533 if (attr & 0x80)
1535 data ^= (attr & 0x03) << ((3-j)*2);
1537 else
1539 data |= (attr & 0x03) << ((3-j)*2);
1542 mask >>= 1;
1544 write_byte(0xb800,dest,data);
1545 dest += 1;
1551 // --------------------------------------------------------------------------------------------
1552 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1553 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1555 Bit8u i,j,mask,data;
1556 Bit8u *fdata;
1557 Bit16u addr,dest,src;
1559 fdata = &vgafont8;
1560 addr=xcurs*8+ycurs*nbcols*64;
1561 src = car * 8;
1562 for(i=0;i<8;i++)
1564 dest=addr+i*nbcols*8;
1565 mask = 0x80;
1566 for(j=0;j<8;j++)
1568 data = 0x00;
1569 if (fdata[src+i] & mask)
1571 data = attr;
1573 write_byte(0xa000,dest+j,data);
1574 mask >>= 1;
1579 // --------------------------------------------------------------------------------------------
1580 static void biosfn_write_char_attr (car,page,attr,count)
1581 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1583 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1584 Bit16u nbcols,nbrows,address;
1585 Bit16u cursor,dummy;
1587 // Get the mode
1588 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1589 line=find_vga_entry(mode);
1590 if(line==0xFF)return;
1592 // Get the cursor pos for the page
1593 biosfn_get_cursor_pos(page,&dummy,&cursor);
1594 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1596 // Get the dimensions
1597 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1598 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1600 if(vga_modes[line].class==TEXT)
1602 // Compute the address
1603 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1605 dummy=((Bit16u)attr<<8)+car;
1606 memsetw(vga_modes[line].sstart,address,dummy,count);
1608 else
1610 // FIXME gfx mode not complete
1611 cheight=video_param_table[line_to_vpti[line]].cheight;
1612 bpp=vga_modes[line].pixbits;
1613 while((count-->0) && (xcurs<nbcols))
1615 switch(vga_modes[line].memmodel)
1617 case PLANAR4:
1618 case PLANAR1:
1619 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1620 break;
1621 case CGA:
1622 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1623 break;
1624 case LINEAR8:
1625 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1626 break;
1627 #ifdef DEBUG
1628 default:
1629 unimplemented();
1630 #endif
1632 xcurs++;
1637 // --------------------------------------------------------------------------------------------
1638 static void biosfn_write_char_only (car,page,attr,count)
1639 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1641 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1642 Bit16u nbcols,nbrows,address;
1643 Bit16u cursor,dummy;
1645 // Get the mode
1646 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1647 line=find_vga_entry(mode);
1648 if(line==0xFF)return;
1650 // Get the cursor pos for the page
1651 biosfn_get_cursor_pos(page,&dummy,&cursor);
1652 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1654 // Get the dimensions
1655 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1656 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1658 if(vga_modes[line].class==TEXT)
1660 // Compute the address
1661 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1663 while(count-->0)
1664 {write_byte(vga_modes[line].sstart,address,car);
1665 address+=2;
1668 else
1670 // FIXME gfx mode not complete
1671 cheight=video_param_table[line_to_vpti[line]].cheight;
1672 bpp=vga_modes[line].pixbits;
1673 while((count-->0) && (xcurs<nbcols))
1675 switch(vga_modes[line].memmodel)
1677 case PLANAR4:
1678 case PLANAR1:
1679 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1680 break;
1681 case CGA:
1682 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1683 break;
1684 case LINEAR8:
1685 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1686 break;
1687 #ifdef DEBUG
1688 default:
1689 unimplemented();
1690 #endif
1692 xcurs++;
1697 // --------------------------------------------------------------------------------------------
1698 ASM_START
1699 biosfn_group_0B:
1700 cmp bh, #0x00
1701 je biosfn_set_border_color
1702 cmp bh, #0x01
1703 je biosfn_set_palette
1704 #ifdef DEBUG
1705 call _unknown
1706 #endif
1708 biosfn_set_border_color:
1709 push ax
1710 push bx
1711 push cx
1712 push dx
1713 mov dx, # VGAREG_ACTL_RESET
1714 in al, dx
1715 mov dx, # VGAREG_ACTL_ADDRESS
1716 mov al, #0x00
1717 out dx, al
1718 mov al, bl
1719 and al, #0x0f
1720 test al, #0x08
1721 jz set_low_border
1722 add al, #0x08
1723 set_low_border:
1724 out dx, al
1725 mov cl, #0x01
1726 and bl, #0x10
1727 set_intensity_loop:
1728 mov dx, # VGAREG_ACTL_ADDRESS
1729 mov al, cl
1730 out dx, al
1731 mov dx, # VGAREG_ACTL_READ_DATA
1732 in al, dx
1733 and al, #0xef
1734 or al, bl
1735 mov dx, # VGAREG_ACTL_ADDRESS
1736 out dx, al
1737 inc cl
1738 cmp cl, #0x04
1739 jne set_intensity_loop
1740 mov al, #0x20
1741 out dx, al
1742 pop dx
1743 pop cx
1744 pop bx
1745 pop ax
1747 biosfn_set_palette:
1748 push ax
1749 push bx
1750 push cx
1751 push dx
1752 mov dx, # VGAREG_ACTL_RESET
1753 in al, dx
1754 mov cl, #0x01
1755 and bl, #0x01
1756 set_cga_palette_loop:
1757 mov dx, # VGAREG_ACTL_ADDRESS
1758 mov al, cl
1759 out dx, al
1760 mov dx, # VGAREG_ACTL_READ_DATA
1761 in al, dx
1762 and al, #0xfe
1763 or al, bl
1764 mov dx, # VGAREG_ACTL_ADDRESS
1765 out dx, al
1766 inc cl
1767 cmp cl, #0x04
1768 jne set_cga_palette_loop
1769 mov al, #0x20
1770 out dx, al
1771 pop dx
1772 pop cx
1773 pop bx
1774 pop ax
1776 ASM_END
1778 // --------------------------------------------------------------------------------------------
1779 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1781 Bit8u mode,line,mask,attr,data;
1782 Bit16u addr;
1784 // Get the mode
1785 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1786 line=find_vga_entry(mode);
1787 if(line==0xFF)return;
1788 if(vga_modes[line].class==TEXT)return;
1790 switch(vga_modes[line].memmodel)
1792 case PLANAR4:
1793 case PLANAR1:
1794 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1795 mask = 0x80 >> (CX & 0x07);
1796 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1797 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1798 data = read_byte(0xa000,addr);
1799 if (AL & 0x80)
1801 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1803 write_byte(0xa000,addr,AL);
1804 ASM_START
1805 mov dx, # VGAREG_GRDC_ADDRESS
1806 mov ax, #0xff08
1807 out dx, ax
1808 mov ax, #0x0005
1809 out dx, ax
1810 mov ax, #0x0003
1811 out dx, ax
1812 ASM_END
1813 break;
1814 case CGA:
1815 if(vga_modes[line].pixbits==2)
1817 addr=(CX>>2)+(DX>>1)*80;
1819 else
1821 addr=(CX>>3)+(DX>>1)*80;
1823 if (DX & 1) addr += 0x2000;
1824 data = read_byte(0xb800,addr);
1825 if(vga_modes[line].pixbits==2)
1827 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1828 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1830 else
1832 attr = (AL & 0x01) << (7 - (CX & 0x07));
1833 mask = 0x01 << (7 - (CX & 0x07));
1835 if (AL & 0x80)
1837 data ^= attr;
1839 else
1841 data &= ~mask;
1842 data |= attr;
1844 write_byte(0xb800,addr,data);
1845 break;
1846 case LINEAR8:
1847 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1848 write_byte(0xa000,addr,AL);
1849 break;
1850 #ifdef DEBUG
1851 default:
1852 unimplemented();
1853 #endif
1857 // --------------------------------------------------------------------------------------------
1858 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1860 Bit8u mode,line,mask,attr,data,i;
1861 Bit16u addr;
1862 Bit16u ss=get_SS();
1864 // Get the mode
1865 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1866 line=find_vga_entry(mode);
1867 if(line==0xFF)return;
1868 if(vga_modes[line].class==TEXT)return;
1870 switch(vga_modes[line].memmodel)
1872 case PLANAR4:
1873 case PLANAR1:
1874 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1875 mask = 0x80 >> (CX & 0x07);
1876 attr = 0x00;
1877 for(i=0;i<4;i++)
1879 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1880 data = read_byte(0xa000,addr) & mask;
1881 if (data > 0) attr |= (0x01 << i);
1883 break;
1884 case CGA:
1885 addr=(CX>>2)+(DX>>1)*80;
1886 if (DX & 1) addr += 0x2000;
1887 data = read_byte(0xb800,addr);
1888 if(vga_modes[line].pixbits==2)
1890 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1892 else
1894 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1896 break;
1897 case LINEAR8:
1898 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1899 attr=read_byte(0xa000,addr);
1900 break;
1901 default:
1902 #ifdef DEBUG
1903 unimplemented();
1904 #endif
1905 attr = 0;
1907 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1910 // --------------------------------------------------------------------------------------------
1911 static void biosfn_write_teletype (car, page, attr, flag)
1912 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1913 {// flag = WITH_ATTR / NO_ATTR
1915 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1916 Bit16u nbcols,nbrows,address;
1917 Bit16u cursor,dummy;
1919 // special case if page is 0xff, use current page
1920 if(page==0xff)
1921 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1923 // Get the mode
1924 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1925 line=find_vga_entry(mode);
1926 if(line==0xFF)return;
1928 // Get the cursor pos for the page
1929 biosfn_get_cursor_pos(page,&dummy,&cursor);
1930 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1932 // Get the dimensions
1933 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1934 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1936 switch(car)
1938 case 7:
1939 //FIXME should beep
1940 break;
1942 case 8:
1943 if(xcurs>0)xcurs--;
1944 break;
1946 case '\r':
1947 xcurs=0;
1948 break;
1950 case '\n':
1951 ycurs++;
1952 break;
1954 case '\t':
1957 biosfn_write_teletype(' ',page,attr,flag);
1958 biosfn_get_cursor_pos(page,&dummy,&cursor);
1959 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1960 }while(xcurs%8==0);
1961 break;
1963 default:
1965 if(vga_modes[line].class==TEXT)
1967 // Compute the address
1968 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1970 // Write the char
1971 write_byte(vga_modes[line].sstart,address,car);
1973 if(flag==WITH_ATTR)
1974 write_byte(vga_modes[line].sstart,address+1,attr);
1976 else
1978 // FIXME gfx mode not complete
1979 cheight=video_param_table[line_to_vpti[line]].cheight;
1980 bpp=vga_modes[line].pixbits;
1981 switch(vga_modes[line].memmodel)
1983 case PLANAR4:
1984 case PLANAR1:
1985 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1986 break;
1987 case CGA:
1988 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1989 break;
1990 case LINEAR8:
1991 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1992 break;
1993 #ifdef DEBUG
1994 default:
1995 unimplemented();
1996 #endif
1999 xcurs++;
2002 // Do we need to wrap ?
2003 if(xcurs==nbcols)
2004 {xcurs=0;
2005 ycurs++;
2008 // Do we need to scroll ?
2009 if(ycurs==nbrows)
2011 if(vga_modes[line].class==TEXT)
2013 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2015 else
2017 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2019 ycurs-=1;
2022 // Set the cursor for the page
2023 cursor=ycurs; cursor<<=8; cursor+=xcurs;
2024 biosfn_set_cursor_pos(page,cursor);
2027 // --------------------------------------------------------------------------------------------
2028 ASM_START
2029 biosfn_get_video_mode:
2030 push ds
2031 mov ax, # BIOSMEM_SEG
2032 mov ds, ax
2033 push bx
2034 mov bx, # BIOSMEM_CURRENT_PAGE
2035 mov al, [bx]
2036 pop bx
2037 mov bh, al
2038 push bx
2039 mov bx, # BIOSMEM_VIDEO_CTL
2040 mov ah, [bx]
2041 and ah, #0x80
2042 mov bx, # BIOSMEM_CURRENT_MODE
2043 mov al, [bx]
2044 or al, ah
2045 mov bx, # BIOSMEM_NB_COLS
2046 mov ah, [bx]
2047 pop bx
2048 pop ds
2050 ASM_END
2052 // --------------------------------------------------------------------------------------------
2053 ASM_START
2054 biosfn_group_10:
2055 cmp al, #0x00
2056 jne int10_test_1001
2057 jmp biosfn_set_single_palette_reg
2058 int10_test_1001:
2059 cmp al, #0x01
2060 jne int10_test_1002
2061 jmp biosfn_set_overscan_border_color
2062 int10_test_1002:
2063 cmp al, #0x02
2064 jne int10_test_1003
2065 jmp biosfn_set_all_palette_reg
2066 int10_test_1003:
2067 cmp al, #0x03
2068 jne int10_test_1007
2069 jmp biosfn_toggle_intensity
2070 int10_test_1007:
2071 cmp al, #0x07
2072 jne int10_test_1008
2073 jmp biosfn_get_single_palette_reg
2074 int10_test_1008:
2075 cmp al, #0x08
2076 jne int10_test_1009
2077 jmp biosfn_read_overscan_border_color
2078 int10_test_1009:
2079 cmp al, #0x09
2080 jne int10_test_1010
2081 jmp biosfn_get_all_palette_reg
2082 int10_test_1010:
2083 cmp al, #0x10
2084 jne int10_test_1012
2085 jmp biosfn_set_single_dac_reg
2086 int10_test_1012:
2087 cmp al, #0x12
2088 jne int10_test_1013
2089 jmp biosfn_set_all_dac_reg
2090 int10_test_1013:
2091 cmp al, #0x13
2092 jne int10_test_1015
2093 jmp biosfn_select_video_dac_color_page
2094 int10_test_1015:
2095 cmp al, #0x15
2096 jne int10_test_1017
2097 jmp biosfn_read_single_dac_reg
2098 int10_test_1017:
2099 cmp al, #0x17
2100 jne int10_test_1018
2101 jmp biosfn_read_all_dac_reg
2102 int10_test_1018:
2103 cmp al, #0x18
2104 jne int10_test_1019
2105 jmp biosfn_set_pel_mask
2106 int10_test_1019:
2107 cmp al, #0x19
2108 jne int10_test_101A
2109 jmp biosfn_read_pel_mask
2110 int10_test_101A:
2111 cmp al, #0x1a
2112 jne int10_group_10_unknown
2113 jmp biosfn_read_video_dac_state
2114 int10_group_10_unknown:
2115 #ifdef DEBUG
2116 call _unknown
2117 #endif
2120 biosfn_set_single_palette_reg:
2121 cmp bl, #0x14
2122 ja no_actl_reg1
2123 push ax
2124 push dx
2125 mov dx, # VGAREG_ACTL_RESET
2126 in al, dx
2127 mov dx, # VGAREG_ACTL_ADDRESS
2128 mov al, bl
2129 out dx, al
2130 mov al, bh
2131 out dx, al
2132 mov al, #0x20
2133 out dx, al
2134 pop dx
2135 pop ax
2136 no_actl_reg1:
2138 ASM_END
2140 // --------------------------------------------------------------------------------------------
2141 ASM_START
2142 biosfn_set_overscan_border_color:
2143 push bx
2144 mov bl, #0x11
2145 call biosfn_set_single_palette_reg
2146 pop bx
2148 ASM_END
2150 // --------------------------------------------------------------------------------------------
2151 ASM_START
2152 biosfn_set_all_palette_reg:
2153 push ax
2154 push bx
2155 push cx
2156 push dx
2157 mov bx, dx
2158 mov dx, # VGAREG_ACTL_RESET
2159 in al, dx
2160 mov cl, #0x00
2161 mov dx, # VGAREG_ACTL_ADDRESS
2162 set_palette_loop:
2163 mov al, cl
2164 out dx, al
2165 seg es
2166 mov al, [bx]
2167 out dx, al
2168 inc bx
2169 inc cl
2170 cmp cl, #0x10
2171 jne set_palette_loop
2172 mov al, #0x11
2173 out dx, al
2174 seg es
2175 mov al, [bx]
2176 out dx, al
2177 mov al, #0x20
2178 out dx, al
2179 pop dx
2180 pop cx
2181 pop bx
2182 pop ax
2184 ASM_END
2186 // --------------------------------------------------------------------------------------------
2187 ASM_START
2188 biosfn_toggle_intensity:
2189 push ax
2190 push bx
2191 push dx
2192 mov dx, # VGAREG_ACTL_RESET
2193 in al, dx
2194 mov dx, # VGAREG_ACTL_ADDRESS
2195 mov al, #0x10
2196 out dx, al
2197 mov dx, # VGAREG_ACTL_READ_DATA
2198 in al, dx
2199 and al, #0xf7
2200 and bl, #0x01
2201 shl bl, 3
2202 or al, bl
2203 mov dx, # VGAREG_ACTL_ADDRESS
2204 out dx, al
2205 mov al, #0x20
2206 out dx, al
2207 pop dx
2208 pop bx
2209 pop ax
2211 ASM_END
2213 // --------------------------------------------------------------------------------------------
2214 ASM_START
2215 biosfn_get_single_palette_reg:
2216 cmp bl, #0x14
2217 ja no_actl_reg2
2218 push ax
2219 push dx
2220 mov dx, # VGAREG_ACTL_RESET
2221 in al, dx
2222 mov dx, # VGAREG_ACTL_ADDRESS
2223 mov al, bl
2224 out dx, al
2225 mov dx, # VGAREG_ACTL_READ_DATA
2226 in al, dx
2227 mov bh, al
2228 mov dx, # VGAREG_ACTL_RESET
2229 in al, dx
2230 mov dx, # VGAREG_ACTL_ADDRESS
2231 mov al, #0x20
2232 out dx, al
2233 pop dx
2234 pop ax
2235 no_actl_reg2:
2237 ASM_END
2239 // --------------------------------------------------------------------------------------------
2240 ASM_START
2241 biosfn_read_overscan_border_color:
2242 push ax
2243 push bx
2244 mov bl, #0x11
2245 call biosfn_get_single_palette_reg
2246 mov al, bh
2247 pop bx
2248 mov bh, al
2249 pop ax
2251 ASM_END
2253 // --------------------------------------------------------------------------------------------
2254 ASM_START
2255 biosfn_get_all_palette_reg:
2256 push ax
2257 push bx
2258 push cx
2259 push dx
2260 mov bx, dx
2261 mov cl, #0x00
2262 get_palette_loop:
2263 mov dx, # VGAREG_ACTL_RESET
2264 in al, dx
2265 mov dx, # VGAREG_ACTL_ADDRESS
2266 mov al, cl
2267 out dx, al
2268 mov dx, # VGAREG_ACTL_READ_DATA
2269 in al, dx
2270 seg es
2271 mov [bx], al
2272 inc bx
2273 inc cl
2274 cmp cl, #0x10
2275 jne get_palette_loop
2276 mov dx, # VGAREG_ACTL_RESET
2277 in al, dx
2278 mov dx, # VGAREG_ACTL_ADDRESS
2279 mov al, #0x11
2280 out dx, al
2281 mov dx, # VGAREG_ACTL_READ_DATA
2282 in al, dx
2283 seg es
2284 mov [bx], al
2285 mov dx, # VGAREG_ACTL_RESET
2286 in al, dx
2287 mov dx, # VGAREG_ACTL_ADDRESS
2288 mov al, #0x20
2289 out dx, al
2290 pop dx
2291 pop cx
2292 pop bx
2293 pop ax
2295 ASM_END
2297 // --------------------------------------------------------------------------------------------
2298 ASM_START
2299 biosfn_set_single_dac_reg:
2300 push ax
2301 push dx
2302 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2303 mov al, bl
2304 out dx, al
2305 mov dx, # VGAREG_DAC_DATA
2306 pop ax
2307 push ax
2308 mov al, ah
2309 out dx, al
2310 mov al, ch
2311 out dx, al
2312 mov al, cl
2313 out dx, al
2314 pop dx
2315 pop ax
2317 ASM_END
2319 // --------------------------------------------------------------------------------------------
2320 ASM_START
2321 biosfn_set_all_dac_reg:
2322 push ax
2323 push bx
2324 push cx
2325 push dx
2326 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2327 mov al, bl
2328 out dx, al
2329 pop dx
2330 push dx
2331 mov bx, dx
2332 mov dx, # VGAREG_DAC_DATA
2333 set_dac_loop:
2334 seg es
2335 mov al, [bx]
2336 out dx, al
2337 inc bx
2338 seg es
2339 mov al, [bx]
2340 out dx, al
2341 inc bx
2342 seg es
2343 mov al, [bx]
2344 out dx, al
2345 inc bx
2346 dec cx
2347 jnz set_dac_loop
2348 pop dx
2349 pop cx
2350 pop bx
2351 pop ax
2353 ASM_END
2355 // --------------------------------------------------------------------------------------------
2356 ASM_START
2357 biosfn_select_video_dac_color_page:
2358 push ax
2359 push bx
2360 push dx
2361 mov dx, # VGAREG_ACTL_RESET
2362 in al, dx
2363 mov dx, # VGAREG_ACTL_ADDRESS
2364 mov al, #0x10
2365 out dx, al
2366 mov dx, # VGAREG_ACTL_READ_DATA
2367 in al, dx
2368 and bl, #0x01
2369 jnz set_dac_page
2370 and al, #0x7f
2371 shl bh, 7
2372 or al, bh
2373 mov dx, # VGAREG_ACTL_ADDRESS
2374 out dx, al
2375 jmp set_actl_normal
2376 set_dac_page:
2377 push ax
2378 mov dx, # VGAREG_ACTL_RESET
2379 in al, dx
2380 mov dx, # VGAREG_ACTL_ADDRESS
2381 mov al, #0x14
2382 out dx, al
2383 pop ax
2384 and al, #0x80
2385 jnz set_dac_16_page
2386 shl bh, 2
2387 set_dac_16_page:
2388 and bh, #0x0f
2389 mov al, bh
2390 out dx, al
2391 set_actl_normal:
2392 mov al, #0x20
2393 out dx, al
2394 pop dx
2395 pop bx
2396 pop ax
2398 ASM_END
2400 // --------------------------------------------------------------------------------------------
2401 ASM_START
2402 biosfn_read_single_dac_reg:
2403 push ax
2404 push dx
2405 mov dx, # VGAREG_DAC_READ_ADDRESS
2406 mov al, bl
2407 out dx, al
2408 pop ax
2409 mov ah, al
2410 mov dx, # VGAREG_DAC_DATA
2411 in al, dx
2412 xchg al, ah
2413 push ax
2414 in al, dx
2415 mov ch, al
2416 in al, dx
2417 mov cl, al
2418 pop dx
2419 pop ax
2421 ASM_END
2423 // --------------------------------------------------------------------------------------------
2424 ASM_START
2425 biosfn_read_all_dac_reg:
2426 push ax
2427 push bx
2428 push cx
2429 push dx
2430 mov dx, # VGAREG_DAC_READ_ADDRESS
2431 mov al, bl
2432 out dx, al
2433 pop dx
2434 push dx
2435 mov bx, dx
2436 mov dx, # VGAREG_DAC_DATA
2437 read_dac_loop:
2438 in al, dx
2439 seg es
2440 mov [bx], al
2441 inc bx
2442 in al, dx
2443 seg es
2444 mov [bx], al
2445 inc bx
2446 in al, dx
2447 seg es
2448 mov [bx], al
2449 inc bx
2450 dec cx
2451 jnz read_dac_loop
2452 pop dx
2453 pop cx
2454 pop bx
2455 pop ax
2457 ASM_END
2459 // --------------------------------------------------------------------------------------------
2460 ASM_START
2461 biosfn_set_pel_mask:
2462 push ax
2463 push dx
2464 mov dx, # VGAREG_PEL_MASK
2465 mov al, bl
2466 out dx, al
2467 pop dx
2468 pop ax
2470 ASM_END
2472 // --------------------------------------------------------------------------------------------
2473 ASM_START
2474 biosfn_read_pel_mask:
2475 push ax
2476 push dx
2477 mov dx, # VGAREG_PEL_MASK
2478 in al, dx
2479 mov bl, al
2480 pop dx
2481 pop ax
2483 ASM_END
2485 // --------------------------------------------------------------------------------------------
2486 ASM_START
2487 biosfn_read_video_dac_state:
2488 push ax
2489 push dx
2490 mov dx, # VGAREG_ACTL_RESET
2491 in al, dx
2492 mov dx, # VGAREG_ACTL_ADDRESS
2493 mov al, #0x10
2494 out dx, al
2495 mov dx, # VGAREG_ACTL_READ_DATA
2496 in al, dx
2497 mov bl, al
2498 shr bl, 7
2499 mov dx, # VGAREG_ACTL_RESET
2500 in al, dx
2501 mov dx, # VGAREG_ACTL_ADDRESS
2502 mov al, #0x14
2503 out dx, al
2504 mov dx, # VGAREG_ACTL_READ_DATA
2505 in al, dx
2506 mov bh, al
2507 and bh, #0x0f
2508 test bl, #0x01
2509 jnz get_dac_16_page
2510 shr bh, 2
2511 get_dac_16_page:
2512 mov dx, # VGAREG_ACTL_RESET
2513 in al, dx
2514 mov dx, # VGAREG_ACTL_ADDRESS
2515 mov al, #0x20
2516 out dx, al
2517 pop dx
2518 pop ax
2520 ASM_END
2522 // --------------------------------------------------------------------------------------------
2523 static void biosfn_perform_gray_scale_summing (start,count)
2524 Bit16u start;Bit16u count;
2525 {Bit8u r,g,b;
2526 Bit16u i;
2527 Bit16u index;
2529 inb(VGAREG_ACTL_RESET);
2530 outb(VGAREG_ACTL_ADDRESS,0x00);
2532 for( index = 0; index < count; index++ )
2534 // set read address and switch to read mode
2535 outb(VGAREG_DAC_READ_ADDRESS,start);
2536 // get 6-bit wide RGB data values
2537 r=inb( VGAREG_DAC_DATA );
2538 g=inb( VGAREG_DAC_DATA );
2539 b=inb( VGAREG_DAC_DATA );
2541 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2542 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2544 if(i>0x3f)i=0x3f;
2546 // set write address and switch to write mode
2547 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2548 // write new intensity value
2549 outb( VGAREG_DAC_DATA, i&0xff );
2550 outb( VGAREG_DAC_DATA, i&0xff );
2551 outb( VGAREG_DAC_DATA, i&0xff );
2552 start++;
2554 inb(VGAREG_ACTL_RESET);
2555 outb(VGAREG_ACTL_ADDRESS,0x20);
2558 // --------------------------------------------------------------------------------------------
2559 static void get_font_access()
2561 ASM_START
2562 mov dx, # VGAREG_SEQU_ADDRESS
2563 mov ax, #0x0100
2564 out dx, ax
2565 mov ax, #0x0402
2566 out dx, ax
2567 mov ax, #0x0704
2568 out dx, ax
2569 mov ax, #0x0300
2570 out dx, ax
2571 mov dx, # VGAREG_GRDC_ADDRESS
2572 mov ax, #0x0204
2573 out dx, ax
2574 mov ax, #0x0005
2575 out dx, ax
2576 mov ax, #0x0406
2577 out dx, ax
2578 ASM_END
2581 static void release_font_access()
2583 ASM_START
2584 mov dx, # VGAREG_SEQU_ADDRESS
2585 mov ax, #0x0100
2586 out dx, ax
2587 mov ax, #0x0302
2588 out dx, ax
2589 mov ax, #0x0304
2590 out dx, ax
2591 mov ax, #0x0300
2592 out dx, ax
2593 mov dx, # VGAREG_READ_MISC_OUTPUT
2594 in al, dx
2595 and al, #0x01
2596 shl al, 2
2597 or al, #0x0a
2598 mov ah, al
2599 mov al, #0x06
2600 mov dx, # VGAREG_GRDC_ADDRESS
2601 out dx, ax
2602 mov ax, #0x0004
2603 out dx, ax
2604 mov ax, #0x1005
2605 out dx, ax
2606 ASM_END
2609 ASM_START
2610 idiv_u:
2611 xor dx,dx
2612 div bx
2614 ASM_END
2616 static void set_scan_lines(lines) Bit8u lines;
2618 Bit16u crtc_addr,cols,page,vde;
2619 Bit8u crtc_r9,ovl,rows;
2621 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2622 outb(crtc_addr, 0x09);
2623 crtc_r9 = inb(crtc_addr+1);
2624 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2625 outb(crtc_addr+1, crtc_r9);
2626 if(lines==8)
2628 biosfn_set_cursor_shape(0x06,0x07);
2630 else
2632 biosfn_set_cursor_shape(lines-4,lines-3);
2634 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2635 outb(crtc_addr, 0x12);
2636 vde = inb(crtc_addr+1);
2637 outb(crtc_addr, 0x07);
2638 ovl = inb(crtc_addr+1);
2639 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2640 rows = vde / lines;
2641 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2642 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2643 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2646 static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH;
2648 Bit16u blockaddr,dest,i,src;
2650 get_font_access();
2651 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2652 for(i=0;i<CX;i++)
2654 src = BP + i * BH;
2655 dest = blockaddr + (DX + i) * 32;
2656 memcpyb(0xA000, dest, ES, src, BH);
2658 release_font_access();
2659 if(AL>=0x10)
2661 set_scan_lines(BH);
2665 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2667 Bit16u blockaddr,dest,i,src;
2669 get_font_access();
2670 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2671 for(i=0;i<0x100;i++)
2673 src = i * 14;
2674 dest = blockaddr + i * 32;
2675 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2677 release_font_access();
2678 if(AL>=0x10)
2680 set_scan_lines(14);
2684 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2686 Bit16u blockaddr,dest,i,src;
2688 get_font_access();
2689 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2690 for(i=0;i<0x100;i++)
2692 src = i * 8;
2693 dest = blockaddr + i * 32;
2694 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2696 release_font_access();
2697 if(AL>=0x10)
2699 set_scan_lines(8);
2703 // --------------------------------------------------------------------------------------------
2704 ASM_START
2705 biosfn_set_text_block_specifier:
2706 push ax
2707 push dx
2708 mov dx, # VGAREG_SEQU_ADDRESS
2709 mov ah, bl
2710 mov al, #0x03
2711 out dx, ax
2712 pop dx
2713 pop ax
2715 ASM_END
2717 // --------------------------------------------------------------------------------------------
2718 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2720 Bit16u blockaddr,dest,i,src;
2722 get_font_access();
2723 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2724 for(i=0;i<0x100;i++)
2726 src = i * 16;
2727 dest = blockaddr + i * 32;
2728 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2730 release_font_access();
2731 if(AL>=0x10)
2733 set_scan_lines(16);
2737 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2739 #ifdef DEBUG
2740 unimplemented();
2741 #endif
2743 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2745 #ifdef DEBUG
2746 unimplemented();
2747 #endif
2749 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2751 #ifdef DEBUG
2752 unimplemented();
2753 #endif
2755 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2757 #ifdef DEBUG
2758 unimplemented();
2759 #endif
2761 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2763 #ifdef DEBUG
2764 unimplemented();
2765 #endif
2767 // --------------------------------------------------------------------------------------------
2768 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2769 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2770 {Bit16u ss=get_SS();
2772 switch(BH)
2773 {case 0x00:
2774 write_word(ss,ES,read_word(0x00,0x1f*4));
2775 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2776 break;
2777 case 0x01:
2778 write_word(ss,ES,read_word(0x00,0x43*4));
2779 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2780 break;
2781 case 0x02:
2782 write_word(ss,ES,0xC000);
2783 write_word(ss,BP,vgafont14);
2784 break;
2785 case 0x03:
2786 write_word(ss,ES,0xC000);
2787 write_word(ss,BP,vgafont8);
2788 break;
2789 case 0x04:
2790 write_word(ss,ES,0xC000);
2791 write_word(ss,BP,vgafont8+128*8);
2792 break;
2793 case 0x05:
2794 write_word(ss,ES,0xC000);
2795 write_word(ss,BP,vgafont14alt);
2796 break;
2797 case 0x06:
2798 write_word(ss,ES,0xC000);
2799 write_word(ss,BP,vgafont16);
2800 break;
2801 case 0x07:
2802 write_word(ss,ES,0xC000);
2803 write_word(ss,BP,vgafont16alt);
2804 break;
2805 default:
2806 #ifdef DEBUG
2807 printf("Get font info BH(%02x) was discarded\n",BH);
2808 #endif
2809 return;
2811 // Set byte/char of on screen font
2812 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2814 // Set Highest char row
2815 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2818 // --------------------------------------------------------------------------------------------
2819 ASM_START
2820 biosfn_get_ega_info:
2821 push ds
2822 push ax
2823 mov ax, # BIOSMEM_SEG
2824 mov ds, ax
2825 xor ch, ch
2826 mov bx, # BIOSMEM_SWITCHES
2827 mov cl, [bx]
2828 and cl, #0x0f
2829 mov bx, # BIOSMEM_CRTC_ADDRESS
2830 mov ax, [bx]
2831 mov bx, #0x0003
2832 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2833 jne mode_ega_color
2834 mov bh, #0x01
2835 mode_ega_color:
2836 pop ax
2837 pop ds
2839 ASM_END
2841 // --------------------------------------------------------------------------------------------
2842 static void biosfn_alternate_prtsc()
2844 #ifdef DEBUG
2845 unimplemented();
2846 #endif
2849 // --------------------------------------------------------------------------------------------
2850 ASM_START
2851 biosfn_select_vert_res:
2853 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2855 push ds
2856 push bx
2857 push dx
2858 mov dl, al
2859 mov ax, # BIOSMEM_SEG
2860 mov ds, ax
2861 mov bx, # BIOSMEM_MODESET_CTL
2862 mov al, [bx]
2863 mov bx, # BIOSMEM_SWITCHES
2864 mov ah, [bx]
2865 cmp dl, #0x01
2866 je vert_res_350
2867 jb vert_res_200
2868 cmp dl, #0x02
2869 je vert_res_400
2870 #ifdef DEBUG
2871 mov al, dl
2872 xor ah, ah
2873 push ax
2874 mov bx, #msg_vert_res
2875 push bx
2876 call _printf
2877 add sp, #4
2878 #endif
2879 jmp set_retcode
2880 vert_res_400:
2882 ; reset modeset ctl bit 7 and set bit 4
2883 ; set switches bit 3-0 to 0x09
2885 and al, #0x7f
2886 or al, #0x10
2887 and ah, #0xf0
2888 or ah, #0x09
2889 jnz set_vert_res
2890 vert_res_350:
2892 ; reset modeset ctl bit 7 and bit 4
2893 ; set switches bit 3-0 to 0x09
2895 and al, #0x6f
2896 and ah, #0xf0
2897 or ah, #0x09
2898 jnz set_vert_res
2899 vert_res_200:
2901 ; set modeset ctl bit 7 and reset bit 4
2902 ; set switches bit 3-0 to 0x08
2904 and al, #0xef
2905 or al, #0x80
2906 and ah, #0xf0
2907 or ah, #0x08
2908 set_vert_res:
2909 mov bx, # BIOSMEM_MODESET_CTL
2910 mov [bx], al
2911 mov bx, # BIOSMEM_SWITCHES
2912 mov [bx], ah
2913 set_retcode:
2914 mov ax, #0x1212
2915 pop dx
2916 pop bx
2917 pop ds
2920 #ifdef DEBUG
2921 msg_vert_res:
2922 .ascii "Select vert res (%02x) was discarded"
2923 .byte 0x0d,0x0a,0x00
2924 #endif
2927 biosfn_enable_default_palette_loading:
2928 push ds
2929 push bx
2930 push dx
2931 mov dl, al
2932 and dl, #0x01
2933 shl dl, 3
2934 mov ax, # BIOSMEM_SEG
2935 mov ds, ax
2936 mov bx, # BIOSMEM_MODESET_CTL
2937 mov al, [bx]
2938 and al, #0xf7
2939 or al, dl
2940 mov [bx], al
2941 mov ax, #0x1212
2942 pop dx
2943 pop bx
2944 pop ds
2948 biosfn_enable_video_addressing:
2949 push bx
2950 push dx
2951 mov bl, al
2952 and bl, #0x01
2953 xor bl, #0x01
2954 shl bl, 1
2955 mov dx, # VGAREG_READ_MISC_OUTPUT
2956 in al, dx
2957 and al, #0xfd
2958 or al, bl
2959 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2960 out dx, al
2961 mov ax, #0x1212
2962 pop dx
2963 pop bx
2967 biosfn_enable_grayscale_summing:
2968 push ds
2969 push bx
2970 push dx
2971 mov dl, al
2972 and dl, #0x01
2973 xor dl, #0x01
2974 shl dl, 1
2975 mov ax, # BIOSMEM_SEG
2976 mov ds, ax
2977 mov bx, # BIOSMEM_MODESET_CTL
2978 mov al, [bx]
2979 and al, #0xfd
2980 or al, dl
2981 mov [bx], al
2982 mov ax, #0x1212
2983 pop dx
2984 pop bx
2985 pop ds
2989 biosfn_enable_cursor_emulation:
2990 push ds
2991 push bx
2992 push dx
2993 mov dl, al
2994 and dl, #0x01
2995 xor dl, #0x01
2996 mov ax, # BIOSMEM_SEG
2997 mov ds, ax
2998 mov bx, # BIOSMEM_MODESET_CTL
2999 mov al, [bx]
3000 and al, #0xfe
3001 or al, dl
3002 mov [bx], al
3003 mov ax, #0x1212
3004 pop dx
3005 pop bx
3006 pop ds
3008 ASM_END
3010 // --------------------------------------------------------------------------------------------
3011 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3013 #ifdef DEBUG
3014 unimplemented();
3015 #endif
3017 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3019 #ifdef DEBUG
3020 unimplemented();
3021 #endif
3024 // --------------------------------------------------------------------------------------------
3025 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3026 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3028 Bit16u newcurs,oldcurs,dummy;
3029 Bit8u car,carattr;
3031 // Read curs info for the page
3032 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3034 // if row=0xff special case : use current cursor position
3035 if(row==0xff)
3036 {col=oldcurs&0x00ff;
3037 row=(oldcurs&0xff00)>>8;
3040 newcurs=row; newcurs<<=8; newcurs+=col;
3041 biosfn_set_cursor_pos(page,newcurs);
3043 while(count--!=0)
3045 car=read_byte(seg,offset++);
3046 if((flag&0x02)!=0)
3047 attr=read_byte(seg,offset++);
3049 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3052 // Set back curs pos
3053 if((flag&0x01)==0)
3054 biosfn_set_cursor_pos(page,oldcurs);
3057 // --------------------------------------------------------------------------------------------
3058 ASM_START
3059 biosfn_group_1A:
3060 cmp al, #0x00
3061 je biosfn_read_display_code
3062 cmp al, #0x01
3063 je biosfn_set_display_code
3064 #ifdef DEBUG
3065 call _unknown
3066 #endif
3068 biosfn_read_display_code:
3069 push ds
3070 push ax
3071 mov ax, # BIOSMEM_SEG
3072 mov ds, ax
3073 mov bx, # BIOSMEM_DCC_INDEX
3074 mov al, [bx]
3075 mov bl, al
3076 xor bh, bh
3077 pop ax
3078 mov al, ah
3079 pop ds
3081 biosfn_set_display_code:
3082 push ds
3083 push ax
3084 push bx
3085 mov ax, # BIOSMEM_SEG
3086 mov ds, ax
3087 mov ax, bx
3088 mov bx, # BIOSMEM_DCC_INDEX
3089 mov [bx], al
3090 #ifdef DEBUG
3091 mov al, ah
3092 xor ah, ah
3093 push ax
3094 mov bx, #msg_alt_dcc
3095 push bx
3096 call _printf
3097 add sp, #4
3098 #endif
3099 pop bx
3100 pop ax
3101 mov al, ah
3102 pop ds
3105 #ifdef DEBUG
3106 msg_alt_dcc:
3107 .ascii "Alternate Display code (%02x) was discarded"
3108 .byte 0x0d,0x0a,0x00
3109 #endif
3110 ASM_END
3112 // --------------------------------------------------------------------------------------------
3113 static void biosfn_read_state_info (BX,ES,DI)
3114 Bit16u BX;Bit16u ES;Bit16u DI;
3116 // Address of static functionality table
3117 write_word(ES,DI+0x00,&static_functionality);
3118 write_word(ES,DI+0x02,0xC000);
3120 // Hard coded copy from BIOS area. Should it be cleaner ?
3121 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3122 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3124 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3125 write_byte(ES,DI+0x26,0);
3126 write_byte(ES,DI+0x27,16);
3127 write_byte(ES,DI+0x28,0);
3128 write_byte(ES,DI+0x29,8);
3129 write_byte(ES,DI+0x2a,2);
3130 write_byte(ES,DI+0x2b,0);
3131 write_byte(ES,DI+0x2c,0);
3132 write_byte(ES,DI+0x31,3);
3133 write_byte(ES,DI+0x32,0);
3135 memsetb(ES,DI+0x33,0,13);
3138 // --------------------------------------------------------------------------------------------
3139 // --------------------------------------------------------------------------------------------
3140 static Bit16u biosfn_read_video_state_size2 (CX)
3141 Bit16u CX;
3143 Bit16u size;
3144 size = 0;
3145 if (CX & 1) {
3146 size += 0x46;
3148 if (CX & 2) {
3149 size += (5 + 8 + 5) * 2 + 6;
3151 if (CX & 4) {
3152 size += 3 + 256 * 3 + 1;
3154 return size;
3157 static void biosfn_read_video_state_size (CX, BX)
3158 Bit16u CX; Bit16u *BX;
3160 Bit16u ss=get_SS();
3161 write_word(ss, BX, biosfn_read_video_state_size2(CX));
3164 static Bit16u biosfn_save_video_state (CX,ES,BX)
3165 Bit16u CX;Bit16u ES;Bit16u BX;
3167 Bit16u i, v, crtc_addr, ar_index;
3169 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3170 if (CX & 1) {
3171 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3172 write_byte(ES, BX, inb(crtc_addr)); BX++;
3173 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3174 inb(VGAREG_ACTL_RESET);
3175 ar_index = inb(VGAREG_ACTL_ADDRESS);
3176 write_byte(ES, BX, ar_index); BX++;
3177 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3179 for(i=1;i<=4;i++){
3180 outb(VGAREG_SEQU_ADDRESS, i);
3181 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3183 outb(VGAREG_SEQU_ADDRESS, 0);
3184 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3186 for(i=0;i<=0x18;i++) {
3187 outb(crtc_addr,i);
3188 write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3191 for(i=0;i<=0x13;i++) {
3192 inb(VGAREG_ACTL_RESET);
3193 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3194 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3196 inb(VGAREG_ACTL_RESET);
3198 for(i=0;i<=8;i++) {
3199 outb(VGAREG_GRDC_ADDRESS,i);
3200 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3203 write_word(ES, BX, crtc_addr); BX+= 2;
3205 /* XXX: read plane latches */
3206 write_byte(ES, BX, 0); BX++;
3207 write_byte(ES, BX, 0); BX++;
3208 write_byte(ES, BX, 0); BX++;
3209 write_byte(ES, BX, 0); BX++;
3211 if (CX & 2) {
3212 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3213 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3214 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3215 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3216 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3217 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3218 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3219 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3220 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3221 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3222 for(i=0;i<8;i++) {
3223 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3224 BX += 2;
3226 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3227 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3228 /* current font */
3229 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3230 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3231 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3232 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3234 if (CX & 4) {
3235 /* XXX: check this */
3236 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3237 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3238 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3239 // Set the whole dac always, from 0
3240 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3241 for(i=0;i<256*3;i++) {
3242 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3244 write_byte(ES, BX, 0); BX++; /* color select register */
3246 return BX;
3249 static Bit16u biosfn_restore_video_state (CX,ES,BX)
3250 Bit16u CX;Bit16u ES;Bit16u BX;
3252 Bit16u i, crtc_addr, v, addr1, ar_index;
3254 if (CX & 1) {
3255 // Reset Attribute Ctl flip-flop
3256 inb(VGAREG_ACTL_RESET);
3258 crtc_addr = read_word(ES, BX + 0x40);
3259 addr1 = BX;
3260 BX += 5;
3262 for(i=1;i<=4;i++){
3263 outb(VGAREG_SEQU_ADDRESS, i);
3264 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3266 outb(VGAREG_SEQU_ADDRESS, 0);
3267 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3269 // Disable CRTC write protection
3270 outw(crtc_addr,0x0011);
3271 // Set CRTC regs
3272 for(i=0;i<=0x18;i++) {
3273 if (i != 0x11) {
3274 outb(crtc_addr,i);
3275 outb(crtc_addr+1, read_byte(ES, BX));
3277 BX++;
3279 // select crtc base address
3280 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3281 if (crtc_addr = 0x3d4)
3282 v |= 0x01;
3283 outb(VGAREG_WRITE_MISC_OUTPUT, v);
3285 // enable write protection if needed
3286 outb(crtc_addr, 0x11);
3287 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3289 // Set Attribute Ctl
3290 ar_index = read_byte(ES, addr1 + 0x03);
3291 inb(VGAREG_ACTL_RESET);
3292 for(i=0;i<=0x13;i++) {
3293 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3294 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3296 outb(VGAREG_ACTL_ADDRESS, ar_index);
3297 inb(VGAREG_ACTL_RESET);
3299 for(i=0;i<=8;i++) {
3300 outb(VGAREG_GRDC_ADDRESS,i);
3301 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3303 BX += 2; /* crtc_addr */
3304 BX += 4; /* plane latches */
3306 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3307 outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3308 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3309 addr1++;
3310 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3312 if (CX & 2) {
3313 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3314 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3315 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3316 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3317 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3318 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3319 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3320 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3321 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3322 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3323 for(i=0;i<8;i++) {
3324 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3325 BX += 2;
3327 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3328 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3329 /* current font */
3330 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3331 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3332 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3333 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3335 if (CX & 4) {
3336 BX++;
3337 v = read_byte(ES, BX); BX++;
3338 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3339 // Set the whole dac always, from 0
3340 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3341 for(i=0;i<256*3;i++) {
3342 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3344 BX++;
3345 outb(VGAREG_DAC_WRITE_ADDRESS, v);
3347 return BX;
3350 // ============================================================================================
3352 // Video Utils
3354 // ============================================================================================
3356 // --------------------------------------------------------------------------------------------
3357 static Bit8u find_vga_entry(mode)
3358 Bit8u mode;
3360 Bit8u i,line=0xFF;
3361 for(i=0;i<=MODE_MAX;i++)
3362 if(vga_modes[i].svgamode==mode)
3363 {line=i;
3364 break;
3366 return line;
3369 /* =========================================================== */
3371 * Misc Utils
3373 /* =========================================================== */
3375 // --------------------------------------------------------------------------------------------
3376 static void memsetb(seg,offset,value,count)
3377 Bit16u seg;
3378 Bit16u offset;
3379 Bit16u value;
3380 Bit16u count;
3382 ASM_START
3383 push bp
3384 mov bp, sp
3386 push ax
3387 push cx
3388 push es
3389 push di
3391 mov cx, 10[bp] ; count
3392 cmp cx, #0x00
3393 je memsetb_end
3394 mov ax, 4[bp] ; segment
3395 mov es, ax
3396 mov ax, 6[bp] ; offset
3397 mov di, ax
3398 mov al, 8[bp] ; value
3401 stosb
3403 memsetb_end:
3404 pop di
3405 pop es
3406 pop cx
3407 pop ax
3409 pop bp
3410 ASM_END
3413 // --------------------------------------------------------------------------------------------
3414 static void memsetw(seg,offset,value,count)
3415 Bit16u seg;
3416 Bit16u offset;
3417 Bit16u value;
3418 Bit16u count;
3420 ASM_START
3421 push bp
3422 mov bp, sp
3424 push ax
3425 push cx
3426 push es
3427 push di
3429 mov cx, 10[bp] ; count
3430 cmp cx, #0x00
3431 je memsetw_end
3432 mov ax, 4[bp] ; segment
3433 mov es, ax
3434 mov ax, 6[bp] ; offset
3435 mov di, ax
3436 mov ax, 8[bp] ; value
3439 stosw
3441 memsetw_end:
3442 pop di
3443 pop es
3444 pop cx
3445 pop ax
3447 pop bp
3448 ASM_END
3451 // --------------------------------------------------------------------------------------------
3452 static void memcpyb(dseg,doffset,sseg,soffset,count)
3453 Bit16u dseg;
3454 Bit16u doffset;
3455 Bit16u sseg;
3456 Bit16u soffset;
3457 Bit16u count;
3459 ASM_START
3460 push bp
3461 mov bp, sp
3463 push ax
3464 push cx
3465 push es
3466 push di
3467 push ds
3468 push si
3470 mov cx, 12[bp] ; count
3471 cmp cx, #0x0000
3472 je memcpyb_end
3473 mov ax, 4[bp] ; dsegment
3474 mov es, ax
3475 mov ax, 6[bp] ; doffset
3476 mov di, ax
3477 mov ax, 8[bp] ; ssegment
3478 mov ds, ax
3479 mov ax, 10[bp] ; soffset
3480 mov si, ax
3483 movsb
3485 memcpyb_end:
3486 pop si
3487 pop ds
3488 pop di
3489 pop es
3490 pop cx
3491 pop ax
3493 pop bp
3494 ASM_END
3497 // --------------------------------------------------------------------------------------------
3498 static void memcpyw(dseg,doffset,sseg,soffset,count)
3499 Bit16u dseg;
3500 Bit16u doffset;
3501 Bit16u sseg;
3502 Bit16u soffset;
3503 Bit16u count;
3505 ASM_START
3506 push bp
3507 mov bp, sp
3509 push ax
3510 push cx
3511 push es
3512 push di
3513 push ds
3514 push si
3516 mov cx, 12[bp] ; count
3517 cmp cx, #0x0000
3518 je memcpyw_end
3519 mov ax, 4[bp] ; dsegment
3520 mov es, ax
3521 mov ax, 6[bp] ; doffset
3522 mov di, ax
3523 mov ax, 8[bp] ; ssegment
3524 mov ds, ax
3525 mov ax, 10[bp] ; soffset
3526 mov si, ax
3529 movsw
3531 memcpyw_end:
3532 pop si
3533 pop ds
3534 pop di
3535 pop es
3536 pop cx
3537 pop ax
3539 pop bp
3540 ASM_END
3543 /* =========================================================== */
3545 * These functions where ripped from Kevin's rombios.c
3547 /* =========================================================== */
3549 // --------------------------------------------------------------------------------------------
3550 static Bit8u
3551 read_byte(seg, offset)
3552 Bit16u seg;
3553 Bit16u offset;
3555 ASM_START
3556 push bp
3557 mov bp, sp
3559 push bx
3560 push ds
3561 mov ax, 4[bp] ; segment
3562 mov ds, ax
3563 mov bx, 6[bp] ; offset
3564 mov al, [bx]
3565 ;; al = return value (byte)
3566 pop ds
3567 pop bx
3569 pop bp
3570 ASM_END
3573 // --------------------------------------------------------------------------------------------
3574 static Bit16u
3575 read_word(seg, offset)
3576 Bit16u seg;
3577 Bit16u offset;
3579 ASM_START
3580 push bp
3581 mov bp, sp
3583 push bx
3584 push ds
3585 mov ax, 4[bp] ; segment
3586 mov ds, ax
3587 mov bx, 6[bp] ; offset
3588 mov ax, [bx]
3589 ;; ax = return value (word)
3590 pop ds
3591 pop bx
3593 pop bp
3594 ASM_END
3597 // --------------------------------------------------------------------------------------------
3598 static void
3599 write_byte(seg, offset, data)
3600 Bit16u seg;
3601 Bit16u offset;
3602 Bit8u data;
3604 ASM_START
3605 push bp
3606 mov bp, sp
3608 push ax
3609 push bx
3610 push ds
3611 mov ax, 4[bp] ; segment
3612 mov ds, ax
3613 mov bx, 6[bp] ; offset
3614 mov al, 8[bp] ; data byte
3615 mov [bx], al ; write data byte
3616 pop ds
3617 pop bx
3618 pop ax
3620 pop bp
3621 ASM_END
3624 // --------------------------------------------------------------------------------------------
3625 static void
3626 write_word(seg, offset, data)
3627 Bit16u seg;
3628 Bit16u offset;
3629 Bit16u data;
3631 ASM_START
3632 push bp
3633 mov bp, sp
3635 push ax
3636 push bx
3637 push ds
3638 mov ax, 4[bp] ; segment
3639 mov ds, ax
3640 mov bx, 6[bp] ; offset
3641 mov ax, 8[bp] ; data word
3642 mov [bx], ax ; write data word
3643 pop ds
3644 pop bx
3645 pop ax
3647 pop bp
3648 ASM_END
3651 // --------------------------------------------------------------------------------------------
3652 Bit8u
3653 inb(port)
3654 Bit16u port;
3656 ASM_START
3657 push bp
3658 mov bp, sp
3660 push dx
3661 mov dx, 4[bp]
3662 in al, dx
3663 pop dx
3665 pop bp
3666 ASM_END
3669 Bit16u
3670 inw(port)
3671 Bit16u port;
3673 ASM_START
3674 push bp
3675 mov bp, sp
3677 push dx
3678 mov dx, 4[bp]
3679 in ax, dx
3680 pop dx
3682 pop bp
3683 ASM_END
3686 // --------------------------------------------------------------------------------------------
3687 void
3688 outb(port, val)
3689 Bit16u port;
3690 Bit8u val;
3692 ASM_START
3693 push bp
3694 mov bp, sp
3696 push ax
3697 push dx
3698 mov dx, 4[bp]
3699 mov al, 6[bp]
3700 out dx, al
3701 pop dx
3702 pop ax
3704 pop bp
3705 ASM_END
3708 // --------------------------------------------------------------------------------------------
3709 void
3710 outw(port, val)
3711 Bit16u port;
3712 Bit16u val;
3714 ASM_START
3715 push bp
3716 mov bp, sp
3718 push ax
3719 push dx
3720 mov dx, 4[bp]
3721 mov ax, 6[bp]
3722 out dx, ax
3723 pop dx
3724 pop ax
3726 pop bp
3727 ASM_END
3730 Bit16u get_SS()
3732 ASM_START
3733 mov ax, ss
3734 ASM_END
3737 #ifdef DEBUG
3738 void unimplemented()
3740 printf("--> Unimplemented\n");
3743 void unknown()
3745 printf("--> Unknown int10\n");
3747 #endif
3749 // --------------------------------------------------------------------------------------------
3750 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3751 void printf(s)
3752 Bit8u *s;
3754 Bit8u c, format_char;
3755 Boolean in_format;
3756 unsigned format_width, i;
3757 Bit16u *arg_ptr;
3758 Bit16u arg_seg, arg, digit, nibble, shift_count;
3760 arg_ptr = &s;
3761 arg_seg = get_SS();
3763 in_format = 0;
3764 format_width = 0;
3766 while (c = read_byte(0xc000, s)) {
3767 if ( c == '%' ) {
3768 in_format = 1;
3769 format_width = 0;
3771 else if (in_format) {
3772 if ( (c>='0') && (c<='9') ) {
3773 format_width = (format_width * 10) + (c - '0');
3775 else if (c == 'x') {
3776 arg_ptr++; // increment to next arg
3777 arg = read_word(arg_seg, arg_ptr);
3778 if (format_width == 0)
3779 format_width = 4;
3780 i = 0;
3781 digit = format_width - 1;
3782 for (i=0; i<format_width; i++) {
3783 nibble = (arg >> (4 * digit)) & 0x000f;
3784 if (nibble <= 9)
3785 outb(0x0500, nibble + '0');
3786 else
3787 outb(0x0500, (nibble - 10) + 'A');
3788 digit--;
3790 in_format = 0;
3792 //else if (c == 'd') {
3793 // in_format = 0;
3794 // }
3796 else {
3797 outb(0x0500, c);
3799 s ++;
3802 #endif
3804 #ifdef VBE
3805 #include "vbe.c"
3806 #endif
3808 #ifdef CIRRUS
3809 #include "clext.c"
3810 #endif
3812 // --------------------------------------------------------------------------------------------
3814 ASM_START
3815 ;; DATA_SEG_DEFS_HERE
3816 ASM_END
3818 ASM_START
3819 .ascii "vgabios ends here"
3820 .byte 0x00
3821 vgabios_end:
3822 .byte 0xCB
3823 ;; BLOCK_STRINGS_BEGIN
3824 ASM_END