1 // ============================================================================================
5 // ============================================================================================
7 // Copyright (C) 2001-2008 the LGPL VGABios developers Team
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
23 // ============================================================================================
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
28 // ============================================================================================
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 // ============================================================================================
60 static Bit8u
read_byte();
61 static Bit16u
read_word();
62 static void write_byte();
63 static void write_word();
69 static Bit16u
get_SS();
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
143 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
145 .byte
0x40 /* BIOS extension length in units of 512 bytes */
150 jmp vgabios_init_func
154 .word vgabios_pci_data
157 // Info from Bart Oldeman
163 .ascii
"Plex86/Bochs VGABios"
184 .ascii
"(C) 2008 the LGPL VGABios developers Team"
189 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
195 .ascii
"Please visit :"
197 ;;.ascii
" . http://www.plex86.org"
199 .ascii
" . http://bochs.sourceforge.net"
201 .ascii
" . http://www.nongnu.org/vgabios"
211 .word
0x00b8 // CLGD5446
213 #error "Unknown PCI vendor and device id"
218 .byte
0x0 // class,hi: vga display
219 .word
0x300 // class,lo: vga display
220 .word
0x40 // bios size
222 .byte
0 // intel x86 data
223 .byte
0x80 // last image
228 ;; ============================================================================================
232 ;; ============================================================================================
238 ;; init basic bios vars
242 ;; init vbe functions
247 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
253 ;; display splash screen
254 call _display_splash_screen
256 ;; init video mode
and clear the screen
265 call vbe_display_info
270 call cirrus_display_info
280 vgabios_int10_handler
:
295 call biosfn_get_video_mode
310 call biosfn_set_text_block_specifier
317 call biosfn_get_ega_info
322 call biosfn_select_vert_res
327 call biosfn_enable_default_palette_loading
332 call biosfn_enable_video_addressing
337 call biosfn_enable_grayscale_summing
342 call biosfn_enable_cursor_emulation
360 jne int10_test_vbe_05
361 call vbe_biosfn_return_current_mode
365 jne int10_test_vbe_06
366 call vbe_biosfn_display_window_control
370 jne int10_test_vbe_07
371 call vbe_biosfn_set_get_logical_scan_line_length
375 jne int10_test_vbe_08
376 call vbe_biosfn_set_get_display_start
380 jne int10_test_vbe_0A
381 call vbe_biosfn_set_get_dac_palette_format
386 call vbe_biosfn_return_protected_mode_interface
395 ;; We have to set ds to access the right data segment
408 #include "vgatables.h"
409 #include "vgafonts.h"
412 * Boot time harware inits
416 ;; switch to color mode
and enable CPU access
480 lines
421 ;; more than
64k
3C4
/04
429 #if defined(USE_BX_INFO) || defined(DEBUG)
430 mov bx
, #msg_vga_init
438 #if defined(USE_BX_INFO) || defined(DEBUG)
440 .ascii
"VGABios $Id$"
445 // --------------------------------------------------------------------------------------------
447 * Boot time bios area inits
452 mov ax
, # BIOSMEM_SEG
455 ;; init detected hardware BIOS Area
456 mov bx
, # BIOSMEM_INITIAL_MODE
459 ;; set
80x25
color (not clear from RBIL but usual
)
463 ;; Just
for the first int10 find its children
465 ;; the
default char height
466 mov bx
, # BIOSMEM_CHAR_HEIGHT
471 mov bx
, # BIOSMEM_VIDEO_CTL
475 ;; Set the basic screen we have
476 mov bx
, # BIOSMEM_SWITCHES
480 ;; Set the basic modeset options
481 mov bx
, # BIOSMEM_MODESET_CTL
485 ;; Set the
default MSR
486 mov bx
, # BIOSMEM_CURRENT_MSR
493 _video_save_pointer_table
:
494 .word _video_param_table
497 .word
0 /* XXX: fill it */
500 .word
0 /* XXX: fill it */
503 .word
0 /* XXX: fill it */
506 .word
0 /* XXX: fill it */
509 .word
0 /* XXX: fill it */
512 .word
0 /* XXX: fill it */
517 // --------------------------------------------------------------------------------------------
519 * Boot time Splash screen
521 static void display_splash_screen()
525 // --------------------------------------------------------------------------------------------
530 static void display_info()
537 mov si
,#vgabios_version
540 ;;mov si
,#vgabios_copyright
541 ;;call _display_string
543 ;;call _display_string
545 mov si
,#vgabios_license
547 mov si
,#vgabios_website
552 static void display_string()
554 // Get length of string
581 // --------------------------------------------------------------------------------------------
583 static void int10_debugmsg(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
584 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
586 // 0E is write char...
588 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
592 // --------------------------------------------------------------------------------------------
594 * int10 main dispatcher
596 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
597 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
604 biosfn_set_video_mode(GET_AL());
605 switch(GET_AL()&0x7F)
623 biosfn_set_cursor_shape(GET_CH(),GET_CL());
626 biosfn_set_cursor_pos(GET_BH(),DX
);
629 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
632 // Read light pen pos (unimplemented)
642 biosfn_set_active_page(GET_AL());
645 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
648 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
651 biosfn_read_char_attr(GET_BH(),&AX
);
654 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
657 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
660 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
663 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
666 // Ralf Brown Interrupt list is WRONG on bh(page)
667 // We do output only on the current page !
668 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
671 // All other functions of group AH=0x10 rewritten in assembler
672 biosfn_perform_gray_scale_summing(BX
,CX
);
679 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
683 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
687 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
691 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
694 biosfn_load_gfx_8_8_chars(ES
,BP
);
697 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
700 biosfn_load_gfx_8_14_chars(GET_BL());
703 biosfn_load_gfx_8_8_dd_chars(GET_BL());
706 biosfn_load_gfx_8_16_chars(GET_BL());
709 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
722 biosfn_alternate_prtsc();
725 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
729 biosfn_enable_video_refresh_control(GET_AL());
739 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
742 biosfn_read_state_info(BX
,ES
,DI
);
749 biosfn_read_video_state_size(CX
,&BX
);
752 biosfn_save_video_state(CX
,ES
,BX
);
755 biosfn_restore_video_state(CX
,ES
,BX
);
767 if (vbe_has_vbe_display()) {
771 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
774 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
777 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
780 vbe_biosfn_save_restore_state(&AX
, CX
, DX
, ES
, &BX
);
820 // ============================================================================================
824 // ============================================================================================
826 static void biosfn_set_video_mode(mode
) Bit8u mode
;
827 {// mode: Bit 7 is 1 if no clear screen
829 // Should we clear the screen ?
830 Bit8u noclearmem
=mode
&0x80;
831 Bit8u line
,mmask
,*palette
,vpti
;
832 Bit16u i
,twidth
,theightm1
,cheight
;
833 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
837 if (vbe_has_vbe_display()) {
838 dispi_set_enable(VBE_DISPI_DISABLED
);
845 // find the entry in the video modes
846 line
=find_vga_entry(mode
);
849 printf("mode search %02x found line %02x\n",mode
,line
);
855 vpti
=line_to_vpti
[line
];
856 twidth
=video_param_table
[vpti
].twidth
;
857 theightm1
=video_param_table
[vpti
].theightm1
;
858 cheight
=video_param_table
[vpti
].cheight
;
860 // Read the bios vga control
861 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
863 // Read the bios vga switches
864 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
866 // Read the bios mode set control
867 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
869 // Then we know the number of lines
872 // if palette loading (bit 3 of modeset ctl = 0)
873 if((modeset_ctl
&0x08)==0)
875 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
877 // Set the whole dac always, from 0
878 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
880 // From which palette
881 switch(vga_modes
[line
].dacmodel
)
895 // Always 256*3 values
896 for(i
=0;i
<0x0100;i
++)
897 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
898 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
899 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
900 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
903 {outb(VGAREG_DAC_DATA
,0);
904 outb(VGAREG_DAC_DATA
,0);
905 outb(VGAREG_DAC_DATA
,0);
908 if((modeset_ctl
&0x02)==0x02)
910 biosfn_perform_gray_scale_summing(0x00, 0x100);
914 // Reset Attribute Ctl flip-flop
915 inb(VGAREG_ACTL_RESET
);
919 {outb(VGAREG_ACTL_ADDRESS
,i
);
920 outb(VGAREG_ACTL_WRITE_DATA
,video_param_table
[vpti
].actl_regs
[i
]);
922 outb(VGAREG_ACTL_ADDRESS
,0x14);
923 outb(VGAREG_ACTL_WRITE_DATA
,0x00);
926 outb(VGAREG_SEQU_ADDRESS
,0);
927 outb(VGAREG_SEQU_DATA
,0x03);
929 {outb(VGAREG_SEQU_ADDRESS
,i
);
930 outb(VGAREG_SEQU_DATA
,video_param_table
[vpti
].sequ_regs
[i
- 1]);
935 {outb(VGAREG_GRDC_ADDRESS
,i
);
936 outb(VGAREG_GRDC_DATA
,video_param_table
[vpti
].grdc_regs
[i
]);
939 // Set CRTC address VGA or MDA
940 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
942 // Disable CRTC write protection
943 outw(crtc_addr
,0x0011);
947 outb(crtc_addr
+1,video_param_table
[vpti
].crtc_regs
[i
]);
950 // Set the misc register
951 outb(VGAREG_WRITE_MISC_OUTPUT
,video_param_table
[vpti
].miscreg
);
954 outb(VGAREG_ACTL_ADDRESS
,0x20);
955 inb(VGAREG_ACTL_RESET
);
959 if(vga_modes
[line
].class==TEXT
)
961 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
967 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
971 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
972 mmask
= inb( VGAREG_SEQU_DATA
);
973 outb( VGAREG_SEQU_DATA
, 0x0f ); // all planes
974 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x8000); // 64k
975 outb( VGAREG_SEQU_DATA
, mmask
);
981 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
,mode
);
982 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
,twidth
);
983 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
,*(Bit16u
*)&video_param_table
[vpti
].slength_l
);
984 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
985 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theightm1
);
986 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,cheight
);
987 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,(0x60|noclearmem
));
988 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
989 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)&0x7f);
991 // FIXME We nearly have the good tables. to be reworked
992 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,0x08); // 8 is VGA should be ok for now
993 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
, video_save_pointer_table
);
994 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2, 0xc000);
997 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x00); // Unavailable on vanilla vga, but...
998 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAL
,0x00); // Unavailable on vanilla vga, but...
1001 if(vga_modes
[line
].class==TEXT
)
1003 biosfn_set_cursor_shape(0x06,0x07);
1006 // Set cursor pos for page 0..7
1008 biosfn_set_cursor_pos(i
,0x0000);
1010 // Set active page 0
1011 biosfn_set_active_page(0x00);
1013 // Write the fonts in memory
1014 if(vga_modes
[line
].class==TEXT
)
1017 ;; copy
and activate
8x16 font
1027 // Set the ints 0x1F and 0x43
1029 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1035 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1040 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1045 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1051 // --------------------------------------------------------------------------------------------
1052 static void biosfn_set_cursor_shape (CH
,CL
)
1054 {Bit16u cheight
,curs
,crtc_addr
;
1061 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
1063 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
1064 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
1065 if((modeset_ctl
&0x01) && (cheight
>8) && (CL
<8) && (CH
<0x20))
1069 CH
= ((CH
+1) * cheight
/ 8) -1;
1073 CH
= ((CL
+1) * cheight
/ 8) - 2;
1075 CL
= ((CL
+1) * cheight
/ 8) - 1;
1078 // CTRC regs 0x0a and 0x0b
1079 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1080 outb(crtc_addr
,0x0a);
1081 outb(crtc_addr
+1,CH
);
1082 outb(crtc_addr
,0x0b);
1083 outb(crtc_addr
+1,CL
);
1086 // --------------------------------------------------------------------------------------------
1087 static void biosfn_set_cursor_pos (page
, cursor
)
1088 Bit8u page
;Bit16u cursor
;
1090 Bit8u xcurs
,ycurs
,current
;
1091 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1093 // Should not happen...
1097 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1099 // Set the hardware cursor
1100 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1103 // Get the dimensions
1104 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1105 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1107 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1109 // Calculate the address knowing nbcols nbrows and page num
1110 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1112 // CRTC regs 0x0e and 0x0f
1113 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1114 outb(crtc_addr
,0x0e);
1115 outb(crtc_addr
+1,(address
&0xff00)>>8);
1116 outb(crtc_addr
,0x0f);
1117 outb(crtc_addr
+1,address
&0x00ff);
1121 // --------------------------------------------------------------------------------------------
1122 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1123 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1128 write_word(ss
, shape
, 0);
1129 write_word(ss
, pos
, 0);
1132 // FIXME should handle VGA 14/16 lines
1133 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1134 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1137 // --------------------------------------------------------------------------------------------
1138 static void biosfn_set_active_page (page
)
1141 Bit16u cursor
,dummy
,crtc_addr
;
1142 Bit16u nbcols
,nbrows
,address
;
1148 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1149 line
=find_vga_entry(mode
);
1150 if(line
==0xFF)return;
1152 // Get pos curs pos for the right page
1153 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1155 if(vga_modes
[line
].class==TEXT
)
1157 // Get the dimensions
1158 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1159 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1161 // Calculate the address knowing nbcols nbrows and page num
1162 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1163 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1166 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1170 address
= page
* (*(Bit16u
*)&video_param_table
[line_to_vpti
[line
]].slength_l
);
1173 // CRTC regs 0x0c and 0x0d
1174 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1175 outb(crtc_addr
,0x0c);
1176 outb(crtc_addr
+1,(address
&0xff00)>>8);
1177 outb(crtc_addr
,0x0d);
1178 outb(crtc_addr
+1,address
&0x00ff);
1180 // And change the BIOS page
1181 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1184 printf("Set active page %02x address %04x\n",page
,address
);
1187 // Display the cursor, now the page is active
1188 biosfn_set_cursor_pos(page
,cursor
);
1191 // --------------------------------------------------------------------------------------------
1192 static void vgamem_copy_pl4(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1193 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1198 src
=ysrc
*cheight
*nbcols
+xstart
;
1199 dest
=ydest
*cheight
*nbcols
+xstart
;
1200 outw(VGAREG_GRDC_ADDRESS
, 0x0105);
1201 for(i
=0;i
<cheight
;i
++)
1203 memcpyb(0xa000,dest
+i
*nbcols
,0xa000,src
+i
*nbcols
,cols
);
1205 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1208 // --------------------------------------------------------------------------------------------
1209 static void vgamem_fill_pl4(xstart
,ystart
,cols
,nbcols
,cheight
,attr
)
1210 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;Bit8u attr
;
1215 dest
=ystart
*cheight
*nbcols
+xstart
;
1216 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1217 for(i
=0;i
<cheight
;i
++)
1219 memsetb(0xa000,dest
+i
*nbcols
,attr
,cols
);
1221 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1224 // --------------------------------------------------------------------------------------------
1225 static void vgamem_copy_cga(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1226 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1231 src
=((ysrc
*cheight
*nbcols
)>>1)+xstart
;
1232 dest
=((ydest
*cheight
*nbcols
)>>1)+xstart
;
1233 for(i
=0;i
<cheight
;i
++)
1236 memcpyb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,0xb800,0x2000+src
+(i
>>1)*nbcols
,cols
);
1238 memcpyb(0xb800,dest
+(i
>>1)*nbcols
,0xb800,src
+(i
>>1)*nbcols
,cols
);
1242 // --------------------------------------------------------------------------------------------
1243 static void vgamem_fill_cga(xstart
,ystart
,cols
,nbcols
,cheight
,attr
)
1244 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;Bit8u attr
;
1249 dest
=((ystart
*cheight
*nbcols
)>>1)+xstart
;
1250 for(i
=0;i
<cheight
;i
++)
1253 memsetb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,attr
,cols
);
1255 memsetb(0xb800,dest
+(i
>>1)*nbcols
,attr
,cols
);
1259 // --------------------------------------------------------------------------------------------
1260 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1261 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1263 // page == 0xFF if current
1265 Bit8u mode
,line
,cheight
,bpp
,cols
;
1266 Bit16u nbcols
,nbrows
,i
;
1273 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1274 line
=find_vga_entry(mode
);
1275 if(line
==0xFF)return;
1277 // Get the dimensions
1278 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1279 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1281 // Get the current page
1283 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1285 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1286 if(clr
>=nbcols
)clr
=nbcols
-1;
1287 if(nblines
>nbrows
)nblines
=0;
1290 if(vga_modes
[line
].class==TEXT
)
1292 // Compute the address
1293 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1295 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1298 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1300 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1305 {for(i
=rul
;i
<=rlr
;i
++)
1307 if((i
+nblines
>rlr
)||(nblines
==0))
1308 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1310 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,cols
);
1314 {for(i
=rlr
;i
>=rul
;i
--)
1316 if((i
<rul
+nblines
)||(nblines
==0))
1317 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1319 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,cols
);
1327 // FIXME gfx mode not complete
1328 cheight
=video_param_table
[line_to_vpti
[line
]].cheight
;
1329 switch(vga_modes
[line
].memmodel
)
1333 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1335 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1336 memsetb(vga_modes
[line
].sstart
,0,attr
,nbrows
*nbcols
*cheight
);
1337 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1342 {for(i
=rul
;i
<=rlr
;i
++)
1344 if((i
+nblines
>rlr
)||(nblines
==0))
1345 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
,attr
);
1347 vgamem_copy_pl4(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1351 {for(i
=rlr
;i
>=rul
;i
--)
1353 if((i
<rul
+nblines
)||(nblines
==0))
1354 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
,attr
);
1356 vgamem_copy_pl4(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1363 bpp
=vga_modes
[line
].pixbits
;
1364 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1366 memsetb(vga_modes
[line
].sstart
,0,attr
,nbrows
*nbcols
*cheight
*bpp
);
1378 {for(i
=rul
;i
<=rlr
;i
++)
1380 if((i
+nblines
>rlr
)||(nblines
==0))
1381 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1383 vgamem_copy_cga(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1387 {for(i
=rlr
;i
>=rul
;i
--)
1389 if((i
<rul
+nblines
)||(nblines
==0))
1390 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1392 vgamem_copy_cga(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1400 printf("Scroll in graphics mode ");
1407 // --------------------------------------------------------------------------------------------
1408 static void biosfn_read_char_attr (page
,car
)
1409 Bit8u page
;Bit16u
*car
;
1410 {Bit16u ss
=get_SS();
1411 Bit8u xcurs
,ycurs
,mode
,line
;
1412 Bit16u nbcols
,nbrows
,address
;
1413 Bit16u cursor
,dummy
;
1416 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1417 line
=find_vga_entry(mode
);
1418 if(line
==0xFF)return;
1420 // Get the cursor pos for the page
1421 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1422 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1424 // Get the dimensions
1425 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1426 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1428 if(vga_modes
[line
].class==TEXT
)
1430 // Compute the address
1431 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1433 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1444 // --------------------------------------------------------------------------------------------
1445 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1446 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1450 Bit16u addr
,dest
,src
;
1462 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1463 src
= car
* cheight
;
1464 outw(VGAREG_SEQU_ADDRESS
, 0x0f02);
1465 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1468 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1472 outw(VGAREG_GRDC_ADDRESS
, 0x0003);
1474 for(i
=0;i
<cheight
;i
++)
1480 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1481 read_byte(0xa000,dest
);
1482 if(fdata
[src
+i
]&mask
)
1484 write_byte(0xa000,dest
,attr
&0x0f);
1488 write_byte(0xa000,dest
,0x00);
1493 mov dx
, # VGAREG_GRDC_ADDRESS
1503 // --------------------------------------------------------------------------------------------
1504 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1505 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1507 Bit8u i
,j
,mask
,data
;
1509 Bit16u addr
,dest
,src
;
1512 addr
=(xcurs
*bpp
)+ycurs
*320;
1516 dest
=addr
+(i
>>1)*80;
1517 if (i
& 1) dest
+= 0x2000;
1523 data
= read_byte(0xb800,dest
);
1531 if (fdata
[src
+i
] & mask
)
1535 data
^= (attr
& 0x01) << (7-j
);
1539 data
|= (attr
& 0x01) << (7-j
);
1544 write_byte(0xb800,dest
,data
);
1552 data
= read_byte(0xb800,dest
);
1560 if (fdata
[src
+i
] & mask
)
1564 data
^= (attr
& 0x03) << ((3-j
)*2);
1568 data
|= (attr
& 0x03) << ((3-j
)*2);
1573 write_byte(0xb800,dest
,data
);
1580 // --------------------------------------------------------------------------------------------
1581 static void write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
)
1582 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;
1584 Bit8u i
,j
,mask
,data
;
1586 Bit16u addr
,dest
,src
;
1589 addr
=xcurs
*8+ycurs
*nbcols
*64;
1593 dest
=addr
+i
*nbcols
*8;
1598 if (fdata
[src
+i
] & mask
)
1602 write_byte(0xa000,dest
+j
,data
);
1608 // --------------------------------------------------------------------------------------------
1609 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1610 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1612 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1613 Bit16u nbcols
,nbrows
,address
;
1614 Bit16u cursor
,dummy
;
1617 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1618 line
=find_vga_entry(mode
);
1619 if(line
==0xFF)return;
1621 // Get the cursor pos for the page
1622 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1623 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1625 // Get the dimensions
1626 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1627 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1629 if(vga_modes
[line
].class==TEXT
)
1631 // Compute the address
1632 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1634 dummy
=((Bit16u
)attr
<<8)+car
;
1635 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1639 // FIXME gfx mode not complete
1640 cheight
=video_param_table
[line_to_vpti
[line
]].cheight
;
1641 bpp
=vga_modes
[line
].pixbits
;
1642 while((count
-->0) && (xcurs
<nbcols
))
1644 switch(vga_modes
[line
].memmodel
)
1648 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1651 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1654 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1666 // --------------------------------------------------------------------------------------------
1667 static void biosfn_write_char_only (car
,page
,attr
,count
)
1668 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1670 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1671 Bit16u nbcols
,nbrows
,address
;
1672 Bit16u cursor
,dummy
;
1675 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1676 line
=find_vga_entry(mode
);
1677 if(line
==0xFF)return;
1679 // Get the cursor pos for the page
1680 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1681 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1683 // Get the dimensions
1684 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1685 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1687 if(vga_modes
[line
].class==TEXT
)
1689 // Compute the address
1690 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1693 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1699 // FIXME gfx mode not complete
1700 cheight
=video_param_table
[line_to_vpti
[line
]].cheight
;
1701 bpp
=vga_modes
[line
].pixbits
;
1702 while((count
-->0) && (xcurs
<nbcols
))
1704 switch(vga_modes
[line
].memmodel
)
1708 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1711 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1714 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1726 // --------------------------------------------------------------------------------------------
1730 je biosfn_set_border_color
1732 je biosfn_set_palette
1737 biosfn_set_border_color
:
1742 mov dx
, # VGAREG_ACTL_RESET
1744 mov dx
, # VGAREG_ACTL_ADDRESS
1757 mov dx
, # VGAREG_ACTL_ADDRESS
1760 mov dx
, # VGAREG_ACTL_READ_DATA
1764 mov dx
, # VGAREG_ACTL_ADDRESS
1768 jne set_intensity_loop
1781 mov dx
, # VGAREG_ACTL_RESET
1785 set_cga_palette_loop
:
1786 mov dx
, # VGAREG_ACTL_ADDRESS
1789 mov dx
, # VGAREG_ACTL_READ_DATA
1793 mov dx
, # VGAREG_ACTL_ADDRESS
1797 jne set_cga_palette_loop
1807 // --------------------------------------------------------------------------------------------
1808 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1810 Bit8u mode
,line
,mask
,attr
,data
;
1814 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1815 line
=find_vga_entry(mode
);
1816 if(line
==0xFF)return;
1817 if(vga_modes
[line
].class==TEXT
)return;
1819 switch(vga_modes
[line
].memmodel
)
1823 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1824 mask
= 0x80 >> (CX
& 0x07);
1825 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1826 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1827 data
= read_byte(0xa000,addr
);
1830 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1832 write_byte(0xa000,addr
,AL
);
1834 mov dx
, # VGAREG_GRDC_ADDRESS
1844 if(vga_modes
[line
].pixbits
==2)
1846 addr
=(CX
>>2)+(DX
>>1)*80;
1850 addr
=(CX
>>3)+(DX
>>1)*80;
1852 if (DX
& 1) addr
+= 0x2000;
1853 data
= read_byte(0xb800,addr
);
1854 if(vga_modes
[line
].pixbits
==2)
1856 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1857 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1861 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1862 mask
= 0x01 << (7 - (CX
& 0x07));
1873 write_byte(0xb800,addr
,data
);
1876 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1877 write_byte(0xa000,addr
,AL
);
1886 // --------------------------------------------------------------------------------------------
1887 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1889 Bit8u mode
,line
,mask
,attr
,data
,i
;
1894 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1895 line
=find_vga_entry(mode
);
1896 if(line
==0xFF)return;
1897 if(vga_modes
[line
].class==TEXT
)return;
1899 switch(vga_modes
[line
].memmodel
)
1903 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1904 mask
= 0x80 >> (CX
& 0x07);
1908 outw(VGAREG_GRDC_ADDRESS
, (i
<< 8) | 0x04);
1909 data
= read_byte(0xa000,addr
) & mask
;
1910 if (data
> 0) attr
|= (0x01 << i
);
1914 addr
=(CX
>>2)+(DX
>>1)*80;
1915 if (DX
& 1) addr
+= 0x2000;
1916 data
= read_byte(0xb800,addr
);
1917 if(vga_modes
[line
].pixbits
==2)
1919 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1923 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1927 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1928 attr
=read_byte(0xa000,addr
);
1936 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1939 // --------------------------------------------------------------------------------------------
1940 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1941 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1942 {// flag = WITH_ATTR / NO_ATTR
1944 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1945 Bit16u nbcols
,nbrows
,address
;
1946 Bit16u cursor
,dummy
;
1948 // special case if page is 0xff, use current page
1950 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1953 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1954 line
=find_vga_entry(mode
);
1955 if(line
==0xFF)return;
1957 // Get the cursor pos for the page
1958 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1959 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1961 // Get the dimensions
1962 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1963 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1986 biosfn_write_teletype(' ',page
,attr
,flag
);
1987 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1988 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1994 if(vga_modes
[line
].class==TEXT
)
1996 // Compute the address
1997 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
2000 write_byte(vga_modes
[line
].sstart
,address
,car
);
2003 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
2007 // FIXME gfx mode not complete
2008 cheight
=video_param_table
[line_to_vpti
[line
]].cheight
;
2009 bpp
=vga_modes
[line
].pixbits
;
2010 switch(vga_modes
[line
].memmodel
)
2014 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
2017 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
2020 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
2031 // Do we need to wrap ?
2037 // Do we need to scroll ?
2040 if(vga_modes
[line
].class==TEXT
)
2042 biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
2046 biosfn_scroll(0x01,0x00,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
2051 // Set the cursor for the page
2052 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
2053 biosfn_set_cursor_pos(page
,cursor
);
2056 // --------------------------------------------------------------------------------------------
2058 biosfn_get_video_mode
:
2060 mov ax
, # BIOSMEM_SEG
2063 mov bx
, # BIOSMEM_CURRENT_PAGE
2068 mov bx
, # BIOSMEM_VIDEO_CTL
2071 mov bx
, # BIOSMEM_CURRENT_MODE
2074 mov bx
, # BIOSMEM_NB_COLS
2081 // --------------------------------------------------------------------------------------------
2086 jmp biosfn_set_single_palette_reg
2090 jmp biosfn_set_overscan_border_color
2094 jmp biosfn_set_all_palette_reg
2098 jmp biosfn_toggle_intensity
2102 jmp biosfn_get_single_palette_reg
2106 jmp biosfn_read_overscan_border_color
2110 jmp biosfn_get_all_palette_reg
2114 jmp biosfn_set_single_dac_reg
2118 jmp biosfn_set_all_dac_reg
2122 jmp biosfn_select_video_dac_color_page
2126 jmp biosfn_read_single_dac_reg
2130 jmp biosfn_read_all_dac_reg
2134 jmp biosfn_set_pel_mask
2138 jmp biosfn_read_pel_mask
2141 jne int10_group_10_unknown
2142 jmp biosfn_read_video_dac_state
2143 int10_group_10_unknown
:
2149 biosfn_set_single_palette_reg
:
2154 mov dx
, # VGAREG_ACTL_RESET
2156 mov dx
, # VGAREG_ACTL_ADDRESS
2169 // --------------------------------------------------------------------------------------------
2171 biosfn_set_overscan_border_color
:
2174 call biosfn_set_single_palette_reg
2179 // --------------------------------------------------------------------------------------------
2181 biosfn_set_all_palette_reg
:
2187 mov dx
, # VGAREG_ACTL_RESET
2190 mov dx
, # VGAREG_ACTL_ADDRESS
2200 jne set_palette_loop
2215 // --------------------------------------------------------------------------------------------
2217 biosfn_toggle_intensity
:
2221 mov dx
, # VGAREG_ACTL_RESET
2223 mov dx
, # VGAREG_ACTL_ADDRESS
2226 mov dx
, # VGAREG_ACTL_READ_DATA
2232 mov dx
, # VGAREG_ACTL_ADDRESS
2242 // --------------------------------------------------------------------------------------------
2244 biosfn_get_single_palette_reg
:
2249 mov dx
, # VGAREG_ACTL_RESET
2251 mov dx
, # VGAREG_ACTL_ADDRESS
2254 mov dx
, # VGAREG_ACTL_READ_DATA
2257 mov dx
, # VGAREG_ACTL_RESET
2259 mov dx
, # VGAREG_ACTL_ADDRESS
2268 // --------------------------------------------------------------------------------------------
2270 biosfn_read_overscan_border_color
:
2274 call biosfn_get_single_palette_reg
2282 // --------------------------------------------------------------------------------------------
2284 biosfn_get_all_palette_reg
:
2292 mov dx
, # VGAREG_ACTL_RESET
2294 mov dx
, # VGAREG_ACTL_ADDRESS
2297 mov dx
, # VGAREG_ACTL_READ_DATA
2304 jne get_palette_loop
2305 mov dx
, # VGAREG_ACTL_RESET
2307 mov dx
, # VGAREG_ACTL_ADDRESS
2310 mov dx
, # VGAREG_ACTL_READ_DATA
2314 mov dx
, # VGAREG_ACTL_RESET
2316 mov dx
, # VGAREG_ACTL_ADDRESS
2326 // --------------------------------------------------------------------------------------------
2328 biosfn_set_single_dac_reg
:
2331 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2334 mov dx
, # VGAREG_DAC_DATA
2348 // --------------------------------------------------------------------------------------------
2350 biosfn_set_all_dac_reg
:
2355 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2361 mov dx
, # VGAREG_DAC_DATA
2384 // --------------------------------------------------------------------------------------------
2386 biosfn_select_video_dac_color_page
:
2390 mov dx
, # VGAREG_ACTL_RESET
2392 mov dx
, # VGAREG_ACTL_ADDRESS
2395 mov dx
, # VGAREG_ACTL_READ_DATA
2402 mov dx
, # VGAREG_ACTL_ADDRESS
2407 mov dx
, # VGAREG_ACTL_RESET
2409 mov dx
, # VGAREG_ACTL_ADDRESS
2429 // --------------------------------------------------------------------------------------------
2431 biosfn_read_single_dac_reg
:
2434 mov dx
, # VGAREG_DAC_READ_ADDRESS
2439 mov dx
, # VGAREG_DAC_DATA
2452 // --------------------------------------------------------------------------------------------
2454 biosfn_read_all_dac_reg
:
2459 mov dx
, # VGAREG_DAC_READ_ADDRESS
2465 mov dx
, # VGAREG_DAC_DATA
2488 // --------------------------------------------------------------------------------------------
2490 biosfn_set_pel_mask
:
2493 mov dx
, # VGAREG_PEL_MASK
2501 // --------------------------------------------------------------------------------------------
2503 biosfn_read_pel_mask
:
2506 mov dx
, # VGAREG_PEL_MASK
2514 // --------------------------------------------------------------------------------------------
2516 biosfn_read_video_dac_state
:
2519 mov dx
, # VGAREG_ACTL_RESET
2521 mov dx
, # VGAREG_ACTL_ADDRESS
2524 mov dx
, # VGAREG_ACTL_READ_DATA
2528 mov dx
, # VGAREG_ACTL_RESET
2530 mov dx
, # VGAREG_ACTL_ADDRESS
2533 mov dx
, # VGAREG_ACTL_READ_DATA
2541 mov dx
, # VGAREG_ACTL_RESET
2543 mov dx
, # VGAREG_ACTL_ADDRESS
2551 // --------------------------------------------------------------------------------------------
2552 static void biosfn_perform_gray_scale_summing (start
,count
)
2553 Bit16u start
;Bit16u count
;
2558 inb(VGAREG_ACTL_RESET
);
2559 outb(VGAREG_ACTL_ADDRESS
,0x00);
2561 for( index
= 0; index
< count
; index
++ )
2563 // set read address and switch to read mode
2564 outb(VGAREG_DAC_READ_ADDRESS
,start
);
2565 // get 6-bit wide RGB data values
2566 r
=inb( VGAREG_DAC_DATA
);
2567 g
=inb( VGAREG_DAC_DATA
);
2568 b
=inb( VGAREG_DAC_DATA
);
2570 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2571 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
2575 // set write address and switch to write mode
2576 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
2577 // write new intensity value
2578 outb( VGAREG_DAC_DATA
, i
&0xff );
2579 outb( VGAREG_DAC_DATA
, i
&0xff );
2580 outb( VGAREG_DAC_DATA
, i
&0xff );
2583 inb(VGAREG_ACTL_RESET
);
2584 outb(VGAREG_ACTL_ADDRESS
,0x20);
2587 // --------------------------------------------------------------------------------------------
2588 static void get_font_access()
2591 mov dx
, # VGAREG_SEQU_ADDRESS
2600 mov dx
, # VGAREG_GRDC_ADDRESS
2610 static void release_font_access()
2613 mov dx
, # VGAREG_SEQU_ADDRESS
2622 mov dx
, # VGAREG_READ_MISC_OUTPUT
2629 mov dx
, # VGAREG_GRDC_ADDRESS
2645 static void set_scan_lines(lines
) Bit8u lines
;
2647 Bit16u crtc_addr
,cols
,page
,vde
;
2648 Bit8u crtc_r9
,ovl
,rows
;
2650 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2651 outb(crtc_addr
, 0x09);
2652 crtc_r9
= inb(crtc_addr
+1);
2653 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2654 outb(crtc_addr
+1, crtc_r9
);
2657 biosfn_set_cursor_shape(0x06,0x07);
2661 biosfn_set_cursor_shape(lines
-4,lines
-3);
2663 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2664 outb(crtc_addr
, 0x12);
2665 vde
= inb(crtc_addr
+1);
2666 outb(crtc_addr
, 0x07);
2667 ovl
= inb(crtc_addr
+1);
2668 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2670 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2671 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2672 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2675 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
;
2677 Bit16u blockaddr
,dest
,i
,src
;
2680 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2684 dest
= blockaddr
+ (DX
+ i
) * 32;
2685 memcpyb(0xA000, dest
, ES
, src
, BH
);
2687 release_font_access();
2694 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2696 Bit16u blockaddr
,dest
,i
,src
;
2699 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2700 for(i
=0;i
<0x100;i
++)
2703 dest
= blockaddr
+ i
* 32;
2704 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2706 release_font_access();
2713 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2715 Bit16u blockaddr
,dest
,i
,src
;
2718 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2719 for(i
=0;i
<0x100;i
++)
2722 dest
= blockaddr
+ i
* 32;
2723 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2725 release_font_access();
2732 // --------------------------------------------------------------------------------------------
2734 biosfn_set_text_block_specifier
:
2737 mov dx
, # VGAREG_SEQU_ADDRESS
2746 // --------------------------------------------------------------------------------------------
2747 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2749 Bit16u blockaddr
,dest
,i
,src
;
2752 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2753 for(i
=0;i
<0x100;i
++)
2756 dest
= blockaddr
+ i
* 32;
2757 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2759 release_font_access();
2766 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2772 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2778 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2784 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2790 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2796 // --------------------------------------------------------------------------------------------
2797 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2798 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2799 {Bit16u ss
=get_SS();
2803 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2804 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2807 write_word(ss
,ES
,read_word(0x00,0x43*4));
2808 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2811 write_word(ss
,ES
,0xC000);
2812 write_word(ss
,BP
,vgafont14
);
2815 write_word(ss
,ES
,0xC000);
2816 write_word(ss
,BP
,vgafont8
);
2819 write_word(ss
,ES
,0xC000);
2820 write_word(ss
,BP
,vgafont8
+128*8);
2823 write_word(ss
,ES
,0xC000);
2824 write_word(ss
,BP
,vgafont14alt
);
2827 write_word(ss
,ES
,0xC000);
2828 write_word(ss
,BP
,vgafont16
);
2831 write_word(ss
,ES
,0xC000);
2832 write_word(ss
,BP
,vgafont16alt
);
2836 printf("Get font info BH(%02x) was discarded\n",BH
);
2840 // Set byte/char of on screen font
2841 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2843 // Set Highest char row
2844 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2847 // --------------------------------------------------------------------------------------------
2849 biosfn_get_ega_info
:
2852 mov ax
, # BIOSMEM_SEG
2855 mov bx
, # BIOSMEM_SWITCHES
2858 mov bx
, # BIOSMEM_CRTC_ADDRESS
2861 cmp ax
, # VGAREG_MDA_CRTC_ADDRESS
2870 // --------------------------------------------------------------------------------------------
2871 static void biosfn_alternate_prtsc()
2878 // --------------------------------------------------------------------------------------------
2880 biosfn_select_vert_res
:
2882 ; res
: 00 200 lines
, 01 350 lines
, 02 400 lines
2888 mov ax
, # BIOSMEM_SEG
2890 mov bx
, # BIOSMEM_MODESET_CTL
2892 mov bx
, # BIOSMEM_SWITCHES
2903 mov bx
, #msg_vert_res
2911 ; reset modeset ctl bit
7 and set bit
4
2912 ; set switches bit
3-0 to
0x09
2921 ; reset modeset ctl bit
7 and bit
4
2922 ; set switches bit
3-0 to
0x09
2930 ; set modeset ctl bit
7 and reset bit
4
2931 ; set switches bit
3-0 to
0x08
2938 mov bx
, # BIOSMEM_MODESET_CTL
2940 mov bx
, # BIOSMEM_SWITCHES
2951 .ascii
"Select vert res (%02x) was discarded"
2952 .byte
0x0d,0x0a,0x00
2956 biosfn_enable_default_palette_loading
:
2963 mov ax
, # BIOSMEM_SEG
2965 mov bx
, # BIOSMEM_MODESET_CTL
2977 biosfn_enable_video_addressing
:
2984 mov dx
, # VGAREG_READ_MISC_OUTPUT
2988 mov dx
, # VGAREG_WRITE_MISC_OUTPUT
2996 biosfn_enable_grayscale_summing
:
3004 mov ax
, # BIOSMEM_SEG
3006 mov bx
, # BIOSMEM_MODESET_CTL
3018 biosfn_enable_cursor_emulation
:
3025 mov ax
, # BIOSMEM_SEG
3027 mov bx
, # BIOSMEM_MODESET_CTL
3039 // --------------------------------------------------------------------------------------------
3040 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
3046 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
3053 // --------------------------------------------------------------------------------------------
3054 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
3055 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
3057 Bit16u newcurs
,oldcurs
,dummy
;
3060 // Read curs info for the page
3061 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
3063 // if row=0xff special case : use current cursor position
3065 {col
=oldcurs
&0x00ff;
3066 row
=(oldcurs
&0xff00)>>8;
3069 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
3070 biosfn_set_cursor_pos(page
,newcurs
);
3074 car
=read_byte(seg
,offset
++);
3076 attr
=read_byte(seg
,offset
++);
3078 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
3081 // Set back curs pos
3083 biosfn_set_cursor_pos(page
,oldcurs
);
3086 // --------------------------------------------------------------------------------------------
3090 je biosfn_read_display_code
3092 je biosfn_set_display_code
3097 biosfn_read_display_code
:
3100 mov ax
, # BIOSMEM_SEG
3102 mov bx
, # BIOSMEM_DCC_INDEX
3110 biosfn_set_display_code
:
3114 mov ax
, # BIOSMEM_SEG
3117 mov bx
, # BIOSMEM_DCC_INDEX
3123 mov bx
, #msg_alt_dcc
3136 .ascii
"Alternate Display code (%02x) was discarded"
3137 .byte
0x0d,0x0a,0x00
3141 // --------------------------------------------------------------------------------------------
3142 static void biosfn_read_state_info (BX
,ES
,DI
)
3143 Bit16u BX
;Bit16u ES
;Bit16u DI
;
3145 // Address of static functionality table
3146 write_word(ES
,DI
+0x00,&static_functionality
);
3147 write_word(ES
,DI
+0x02,0xC000);
3149 // Hard coded copy from BIOS area. Should it be cleaner ?
3150 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
3151 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
3153 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
3154 write_byte(ES
,DI
+0x26,0);
3155 write_byte(ES
,DI
+0x27,16);
3156 write_byte(ES
,DI
+0x28,0);
3157 write_byte(ES
,DI
+0x29,8);
3158 write_byte(ES
,DI
+0x2a,2);
3159 write_byte(ES
,DI
+0x2b,0);
3160 write_byte(ES
,DI
+0x2c,0);
3161 write_byte(ES
,DI
+0x31,3);
3162 write_byte(ES
,DI
+0x32,0);
3164 memsetb(ES
,DI
+0x33,0,13);
3167 // --------------------------------------------------------------------------------------------
3168 // --------------------------------------------------------------------------------------------
3169 static Bit16u
biosfn_read_video_state_size2 (CX
)
3178 size
+= (5 + 8 + 5) * 2 + 6;
3181 size
+= 3 + 256 * 3 + 1;
3186 static void biosfn_read_video_state_size (CX
, BX
)
3187 Bit16u CX
; Bit16u
*BX
;
3190 write_word(ss
, BX
, biosfn_read_video_state_size2(CX
));
3193 static Bit16u
biosfn_save_video_state (CX
,ES
,BX
)
3194 Bit16u CX
;Bit16u ES
;Bit16u BX
;
3196 Bit16u i
, v
, crtc_addr
, ar_index
;
3198 crtc_addr
= read_word(BIOSMEM_SEG
, BIOSMEM_CRTC_ADDRESS
);
3200 write_byte(ES
, BX
, inb(VGAREG_SEQU_ADDRESS
)); BX
++;
3201 write_byte(ES
, BX
, inb(crtc_addr
)); BX
++;
3202 write_byte(ES
, BX
, inb(VGAREG_GRDC_ADDRESS
)); BX
++;
3203 inb(VGAREG_ACTL_RESET
);
3204 ar_index
= inb(VGAREG_ACTL_ADDRESS
);
3205 write_byte(ES
, BX
, ar_index
); BX
++;
3206 write_byte(ES
, BX
, inb(VGAREG_READ_FEATURE_CTL
)); BX
++;
3209 outb(VGAREG_SEQU_ADDRESS
, i
);
3210 write_byte(ES
, BX
, inb(VGAREG_SEQU_DATA
)); BX
++;
3212 outb(VGAREG_SEQU_ADDRESS
, 0);
3213 write_byte(ES
, BX
, inb(VGAREG_SEQU_DATA
)); BX
++;
3215 for(i
=0;i
<=0x18;i
++) {
3217 write_byte(ES
, BX
, inb(crtc_addr
+1)); BX
++;
3220 for(i
=0;i
<=0x13;i
++) {
3221 inb(VGAREG_ACTL_RESET
);
3222 outb(VGAREG_ACTL_ADDRESS
, i
| (ar_index
& 0x20));
3223 write_byte(ES
, BX
, inb(VGAREG_ACTL_READ_DATA
)); BX
++;
3225 inb(VGAREG_ACTL_RESET
);
3228 outb(VGAREG_GRDC_ADDRESS
,i
);
3229 write_byte(ES
, BX
, inb(VGAREG_GRDC_DATA
)); BX
++;
3232 write_word(ES
, BX
, crtc_addr
); BX
+= 2;
3234 /* XXX: read plane latches */
3235 write_byte(ES
, BX
, 0); BX
++;
3236 write_byte(ES
, BX
, 0); BX
++;
3237 write_byte(ES
, BX
, 0); BX
++;
3238 write_byte(ES
, BX
, 0); BX
++;
3241 write_byte(ES
, BX
, read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
)); BX
++;
3242 write_word(ES
, BX
, read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)); BX
+= 2;
3243 write_word(ES
, BX
, read_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
)); BX
+= 2;
3244 write_word(ES
, BX
, read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)); BX
+= 2;
3245 write_byte(ES
, BX
, read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)); BX
++;
3246 write_word(ES
, BX
, read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
)); BX
+= 2;
3247 write_byte(ES
, BX
, read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
)); BX
++;
3248 write_byte(ES
, BX
, read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
)); BX
++;
3249 write_byte(ES
, BX
, read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)); BX
++;
3250 write_word(ES
, BX
, read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
)); BX
+= 2;
3252 write_word(ES
, BX
, read_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*i
));
3255 write_word(ES
, BX
, read_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
)); BX
+= 2;
3256 write_byte(ES
, BX
, read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
)); BX
++;
3258 write_word(ES
, BX
, read_word(0, 0x1f * 4)); BX
+= 2;
3259 write_word(ES
, BX
, read_word(0, 0x1f * 4 + 2)); BX
+= 2;
3260 write_word(ES
, BX
, read_word(0, 0x43 * 4)); BX
+= 2;
3261 write_word(ES
, BX
, read_word(0, 0x43 * 4 + 2)); BX
+= 2;
3264 /* XXX: check this */
3265 write_byte(ES
, BX
, inb(VGAREG_DAC_STATE
)); BX
++; /* read/write mode dac */
3266 write_byte(ES
, BX
, inb(VGAREG_DAC_WRITE_ADDRESS
)); BX
++; /* pix address */
3267 write_byte(ES
, BX
, inb(VGAREG_PEL_MASK
)); BX
++;
3268 // Set the whole dac always, from 0
3269 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
3270 for(i
=0;i
<256*3;i
++) {
3271 write_byte(ES
, BX
, inb(VGAREG_DAC_DATA
)); BX
++;
3273 write_byte(ES
, BX
, 0); BX
++; /* color select register */
3278 static Bit16u
biosfn_restore_video_state (CX
,ES
,BX
)
3279 Bit16u CX
;Bit16u ES
;Bit16u BX
;
3281 Bit16u i
, crtc_addr
, v
, addr1
, ar_index
;
3284 // Reset Attribute Ctl flip-flop
3285 inb(VGAREG_ACTL_RESET
);
3287 crtc_addr
= read_word(ES
, BX
+ 0x40);
3292 outb(VGAREG_SEQU_ADDRESS
, i
);
3293 outb(VGAREG_SEQU_DATA
, read_byte(ES
, BX
)); BX
++;
3295 outb(VGAREG_SEQU_ADDRESS
, 0);
3296 outb(VGAREG_SEQU_DATA
, read_byte(ES
, BX
)); BX
++;
3298 // Disable CRTC write protection
3299 outw(crtc_addr
,0x0011);
3301 for(i
=0;i
<=0x18;i
++) {
3304 outb(crtc_addr
+1, read_byte(ES
, BX
));
3308 // select crtc base address
3309 v
= inb(VGAREG_READ_MISC_OUTPUT
) & ~0x01;
3310 if (crtc_addr
= 0x3d4)
3312 outb(VGAREG_WRITE_MISC_OUTPUT
, v
);
3314 // enable write protection if needed
3315 outb(crtc_addr
, 0x11);
3316 outb(crtc_addr
+1, read_byte(ES
, BX
- 0x18 + 0x11));
3318 // Set Attribute Ctl
3319 ar_index
= read_byte(ES
, addr1
+ 0x03);
3320 inb(VGAREG_ACTL_RESET
);
3321 for(i
=0;i
<=0x13;i
++) {
3322 outb(VGAREG_ACTL_ADDRESS
, i
| (ar_index
& 0x20));
3323 outb(VGAREG_ACTL_WRITE_DATA
, read_byte(ES
, BX
)); BX
++;
3325 outb(VGAREG_ACTL_ADDRESS
, ar_index
);
3326 inb(VGAREG_ACTL_RESET
);
3329 outb(VGAREG_GRDC_ADDRESS
,i
);
3330 outb(VGAREG_GRDC_DATA
, read_byte(ES
, BX
)); BX
++;
3332 BX
+= 2; /* crtc_addr */
3333 BX
+= 4; /* plane latches */
3335 outb(VGAREG_SEQU_ADDRESS
, read_byte(ES
, addr1
)); addr1
++;
3336 outb(crtc_addr
, read_byte(ES
, addr1
)); addr1
++;
3337 outb(VGAREG_GRDC_ADDRESS
, read_byte(ES
, addr1
)); addr1
++;
3339 outb(crtc_addr
- 0x4 + 0xa, read_byte(ES
, addr1
)); addr1
++;
3342 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
, read_byte(ES
, BX
)); BX
++;
3343 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
, read_word(ES
, BX
)); BX
+= 2;
3344 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, read_word(ES
, BX
)); BX
+= 2;
3345 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
, read_word(ES
, BX
)); BX
+= 2;
3346 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, read_byte(ES
, BX
)); BX
++;
3347 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, read_word(ES
, BX
)); BX
+= 2;
3348 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
, read_byte(ES
, BX
)); BX
++;
3349 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
, read_byte(ES
, BX
)); BX
++;
3350 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
, read_byte(ES
, BX
)); BX
++;
3351 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
, read_word(ES
, BX
)); BX
+= 2;
3353 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*i
, read_word(ES
, BX
));
3356 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
, read_word(ES
, BX
)); BX
+= 2;
3357 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
, read_byte(ES
, BX
)); BX
++;
3359 write_word(0, 0x1f * 4, read_word(ES
, BX
)); BX
+= 2;
3360 write_word(0, 0x1f * 4 + 2, read_word(ES
, BX
)); BX
+= 2;
3361 write_word(0, 0x43 * 4, read_word(ES
, BX
)); BX
+= 2;
3362 write_word(0, 0x43 * 4 + 2, read_word(ES
, BX
)); BX
+= 2;
3366 v
= read_byte(ES
, BX
); BX
++;
3367 outb(VGAREG_PEL_MASK
, read_byte(ES
, BX
)); BX
++;
3368 // Set the whole dac always, from 0
3369 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
3370 for(i
=0;i
<256*3;i
++) {
3371 outb(VGAREG_DAC_DATA
, read_byte(ES
, BX
)); BX
++;
3374 outb(VGAREG_DAC_WRITE_ADDRESS
, v
);
3379 // ============================================================================================
3383 // ============================================================================================
3385 // --------------------------------------------------------------------------------------------
3386 static Bit8u
find_vga_entry(mode
)
3390 for(i
=0;i
<=MODE_MAX
;i
++)
3391 if(vga_modes
[i
].svgamode
==mode
)
3398 /* =========================================================== */
3402 /* =========================================================== */
3404 // --------------------------------------------------------------------------------------------
3405 static void memsetb(seg
,offset
,value
,count
)
3420 mov cx
, 10[bp
] ; count
3423 mov ax
, 4[bp
] ; segment
3425 mov ax
, 6[bp
] ; offset
3427 mov al
, 8[bp
] ; value
3442 // --------------------------------------------------------------------------------------------
3443 static void memsetw(seg
,offset
,value
,count
)
3458 mov cx
, 10[bp
] ; count
3461 mov ax
, 4[bp
] ; segment
3463 mov ax
, 6[bp
] ; offset
3465 mov ax
, 8[bp
] ; value
3480 // --------------------------------------------------------------------------------------------
3481 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
3499 mov cx
, 12[bp
] ; count
3502 mov ax
, 4[bp
] ; dsegment
3504 mov ax
, 6[bp
] ; doffset
3506 mov ax
, 8[bp
] ; ssegment
3508 mov ax
, 10[bp
] ; soffset
3526 // --------------------------------------------------------------------------------------------
3527 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
3545 mov cx
, 12[bp
] ; count
3548 mov ax
, 4[bp
] ; dsegment
3550 mov ax
, 6[bp
] ; doffset
3552 mov ax
, 8[bp
] ; ssegment
3554 mov ax
, 10[bp
] ; soffset
3572 /* =========================================================== */
3574 * These functions where ripped from Kevin's rombios.c
3576 /* =========================================================== */
3578 // --------------------------------------------------------------------------------------------
3580 read_byte(seg
, offset
)
3590 mov ax
, 4[bp
] ; segment
3592 mov bx
, 6[bp
] ; offset
3594 ;; al
= return value (byte
)
3602 // --------------------------------------------------------------------------------------------
3604 read_word(seg
, offset
)
3614 mov ax
, 4[bp
] ; segment
3616 mov bx
, 6[bp
] ; offset
3618 ;; ax
= return value (word
)
3626 // --------------------------------------------------------------------------------------------
3628 write_byte(seg
, offset
, data
)
3640 mov ax
, 4[bp
] ; segment
3642 mov bx
, 6[bp
] ; offset
3643 mov al
, 8[bp
] ; data byte
3644 mov
[bx
], al
; write data byte
3653 // --------------------------------------------------------------------------------------------
3655 write_word(seg
, offset
, data
)
3667 mov ax
, 4[bp
] ; segment
3669 mov bx
, 6[bp
] ; offset
3670 mov ax
, 8[bp
] ; data word
3671 mov
[bx
], ax
; write data word
3680 // --------------------------------------------------------------------------------------------
3715 // --------------------------------------------------------------------------------------------
3737 // --------------------------------------------------------------------------------------------
3767 void unimplemented()
3769 printf("--> Unimplemented\n");
3774 printf("--> Unknown int10\n");
3778 // --------------------------------------------------------------------------------------------
3779 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3783 Bit8u c
, format_char
;
3785 unsigned format_width
, i
;
3787 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
3795 while (c
= read_byte(0xc000, s
)) {
3800 else if (in_format
) {
3801 if ( (c
>='0') && (c
<='9') ) {
3802 format_width
= (format_width
* 10) + (c
- '0');
3804 else if (c
== 'x') {
3805 arg_ptr
++; // increment to next arg
3806 arg
= read_word(arg_seg
, arg_ptr
);
3807 if (format_width
== 0)
3810 digit
= format_width
- 1;
3811 for (i
=0; i
<format_width
; i
++) {
3812 nibble
= (arg
>> (4 * digit
)) & 0x000f;
3814 outb(0x0500, nibble
+ '0');
3816 outb(0x0500, (nibble
- 10) + 'A');
3821 //else if (c == 'd') {
3841 // --------------------------------------------------------------------------------------------
3844 ;; DATA_SEG_DEFS_HERE
3848 .ascii
"vgabios ends here"
3852 ;; BLOCK_STRINGS_BEGIN