1 // ============================================================================================
5 // ============================================================================================
7 // Copyright (C) 2001,2002 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 // ============================================================================================
58 static Bit8u
read_byte();
59 static Bit16u
read_word();
60 static void write_byte();
61 static void write_word();
67 static Bit16u
get_SS();
71 static void unimplemented();
72 static void unknown();
74 static Bit8u
find_vga_entry();
76 static void memsetb();
77 static void memsetw();
78 static void memcpyb();
79 static void memcpyw();
81 static void biosfn_set_video_mode();
82 static void biosfn_set_cursor_shape();
83 static void biosfn_set_cursor_pos();
84 static void biosfn_get_cursor_pos();
85 static void biosfn_set_active_page();
86 static void biosfn_scroll();
87 static void biosfn_read_char_attr();
88 static void biosfn_write_char_attr();
89 static void biosfn_write_char_only();
90 static void biosfn_set_border_color();
91 static void biosfn_set_palette();
92 static void biosfn_write_pixel();
93 static void biosfn_read_pixel();
94 static void biosfn_write_teletype();
95 static void biosfn_set_single_palette_reg();
96 static void biosfn_set_overscan_border_color();
97 static void biosfn_set_all_palette_reg();
98 static void biosfn_toggle_intensity();
99 static void biosfn_get_single_palette_reg();
100 static void biosfn_read_overscan_border_color();
101 static void biosfn_get_all_palette_reg();
102 static void biosfn_set_single_dac_reg();
103 static void biosfn_set_all_dac_reg();
104 static void biosfn_select_video_dac_color_page();
105 static void biosfn_read_single_dac_reg();
106 static void biosfn_read_all_dac_reg();
107 static void biosfn_set_pel_mask();
108 static void biosfn_read_pel_mask();
109 static void biosfn_read_video_dac_state();
110 static void biosfn_perform_gray_scale_summing();
111 static void biosfn_load_text_user_pat();
112 static void biosfn_load_text_8_14_pat();
113 static void biosfn_load_text_8_8_pat();
114 static void biosfn_set_text_block_specifier();
115 static void biosfn_load_text_8_16_pat();
116 static void biosfn_load_gfx_8_8_chars();
117 static void biosfn_load_gfx_user_chars();
118 static void biosfn_load_gfx_8_14_chars();
119 static void biosfn_load_gfx_8_8_dd_chars();
120 static void biosfn_load_gfx_8_16_chars();
121 static void biosfn_get_font_info();
122 static void biosfn_get_ega_info();
123 static void biosfn_alternate_prtsc();
124 static void biosfn_select_vert_res();
125 static void biosfn_enable_default_palette_loading();
126 static void biosfn_enable_video_addressing();
127 static void biosfn_enable_grayscale_summing();
128 static void biosfn_enable_cursor_emulation();
129 static void biosfn_switch_video_interface();
130 static void biosfn_enable_video_refresh_control();
131 static void biosfn_write_string();
132 static void biosfn_read_state_info();
133 static void biosfn_read_video_state_size();
134 static void biosfn_save_video_state();
135 static void biosfn_restore_video_state();
137 // This is for compiling with gcc2 and gcc3
138 #define ASM_START #asm
139 #define ASM_END #endasm
144 biosmem_initial_mode
= 0x10
145 biosmem_current_mode
= 0x49
146 biosmem_nb_cols
= 0x4a
147 biosmem_current_page
= 0x62
148 biosmem_current_msr
= 0x65
149 biosmem_char_height
= 0x85
150 biosmem_video_ctl
= 0x87
151 biosmem_switches
= 0x88
152 biosmem_modeset_ctl
= 0x89
153 biosmem_dcc_index
= 0x8a
155 vgareg_sequ_address
= 0x03c4
156 vgareg_grdc_address
= 0x03ce
179 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
181 .byte
0x40 /* BIOS extension length in units of 512 bytes */
186 jmp vgabios_init_func
189 .ascii
"Plex86/Bochs VGABios"
193 // Info from Bart Oldeman
212 .ascii
"(C) 2003 the LGPL VGABios developers Team"
217 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
223 .ascii
"Please visit :"
225 ;;.ascii
" . http://www.plex86.org"
227 .ascii
" . http://bochs.sourceforge.net"
229 .ascii
" . http://www.nongnu.org/vgabios"
235 ;; ============================================================================================
239 ;; ============================================================================================
245 ;; init basic bios vars
249 ;; init vbe functions
254 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
256 ;; display splash screen
257 call _display_splash_screen
259 ;; init video mode
and clear the screen
268 call _vbe_display_info
279 vgabios_int10_handler
:
283 call biosfn_get_video_mode
296 ;; We have to set ds to access the right data segment
309 #include "vgatables.h"
310 #include "vgafonts.h"
313 * Boot time harware inits
317 ;; switch to color mode
and enable CPU access
480 lines
322 ;; more than
64k
3C4
/04
330 mov bx
, #msg_vga_init
338 .ascii
"VGABios $Id$"
342 // --------------------------------------------------------------------------------------------
344 * Boot time bios area inits
352 ;; init detected hardware BIOS Area
353 mov bx
, #biosmem_initial_mode
358 ;; Just
for the first int10 find its children
360 ;; the
default char height
361 mov bx
, #biosmem_char_height
366 mov bx
, #biosmem_video_ctl
370 ;; Set the basic screen we have
371 mov bx
, #biosmem_switches
375 ;; Set the basic modeset options
376 mov bx
, #biosmem_modeset_ctl
380 ;; Set the
default MSR
381 mov bx
, #biosmem_current_msr
389 // --------------------------------------------------------------------------------------------
391 * Boot time Splash screen
393 static void display_splash_screen()
397 // --------------------------------------------------------------------------------------------
402 static void display_info()
409 mov si
,#vgabios_version
412 ;;mov si
,#vgabios_copyright
413 ;;call _display_string
415 ;;call _display_string
417 mov si
,#vgabios_license
419 mov si
,#vgabios_website
424 static void display_string()
426 // Get length of string
453 // --------------------------------------------------------------------------------------------
455 // --------------------------------------------------------------------------------------------
457 * int10 main dispatcher
459 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
460 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
463 // 0E is write char...
465 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
472 biosfn_set_video_mode(GET_AL());
473 switch(GET_AL()&0x7F)
491 biosfn_set_cursor_shape(GET_CH(),GET_CL());
494 biosfn_set_cursor_pos(GET_BH(),DX
);
497 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
500 // Read light pen pos (unimplemented)
510 biosfn_set_active_page(GET_AL());
513 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
516 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
519 biosfn_read_char_attr(GET_BH(),&AX
);
522 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
525 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
529 biosfn_set_border_color(GET_BL());
531 biosfn_set_palette(GET_BL());
534 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
537 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
540 // Ralf Brown Interrupt list is WRONG on bh(page)
541 // We do output only on the current page !
542 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
548 biosfn_set_single_palette_reg(GET_BL(),GET_BH());
551 biosfn_set_overscan_border_color(GET_BH());
554 biosfn_set_all_palette_reg(ES
,DX
);
557 biosfn_toggle_intensity(GET_BL());
560 biosfn_get_single_palette_reg(GET_BL(),&BX
);
563 biosfn_read_overscan_border_color(&BX
);
566 biosfn_get_all_palette_reg(ES
,DX
);
569 biosfn_set_single_dac_reg(BX
,GET_CH(),GET_CL(),GET_DH());
572 biosfn_set_all_dac_reg(BX
,CX
,ES
,DX
);
575 biosfn_select_video_dac_color_page(GET_BL(),GET_BH());
578 biosfn_read_single_dac_reg(GET_BL(),&DX
,&CX
);
581 biosfn_read_all_dac_reg(BX
,CX
,ES
,DX
);
584 biosfn_set_pel_mask(GET_BL());
587 biosfn_read_pel_mask(&BX
);
590 biosfn_read_video_dac_state(&BX
);
593 biosfn_perform_gray_scale_summing(BX
,CX
);
606 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
610 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
614 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
617 biosfn_set_text_block_specifier(GET_BL());
621 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
624 biosfn_load_gfx_8_8_chars(ES
,BP
);
627 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
630 biosfn_load_gfx_8_14_chars(GET_BL());
633 biosfn_load_gfx_8_8_dd_chars(GET_BL());
636 biosfn_load_gfx_8_16_chars(GET_BL());
639 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
652 biosfn_get_ega_info(&BX
,&CX
);
655 biosfn_alternate_prtsc();
658 biosfn_select_vert_res(GET_AL());
662 biosfn_enable_default_palette_loading(GET_AL());
666 biosfn_enable_video_addressing(GET_AL());
670 biosfn_enable_grayscale_summing(GET_AL());
674 biosfn_enable_cursor_emulation(GET_AL());
678 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
682 biosfn_enable_video_refresh_control(GET_AL());
692 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
695 biosfn_read_state_info(BX
,ES
,DI
);
702 biosfn_read_video_state_size(CX
,&BX
);
705 biosfn_save_video_state(CX
,ES
,BX
);
708 biosfn_restore_video_state(CX
,ES
,BX
);
720 if (vbe_has_vbe_display()) {
724 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
727 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
730 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
733 vbe_biosfn_return_current_mode(&AX
,&BX
);
744 vbe_biosfn_display_window_control(&AX
,BX
,&DX
);
747 vbe_biosfn_set_get_logical_scan_line_length(&AX
,&BX
,&CX
,&DX
);
750 vbe_biosfn_set_get_display_start(&AX
,BX
,CX
,DX
);
798 // ============================================================================================
802 // ============================================================================================
804 static void biosfn_set_video_mode(mode
) Bit8u mode
;
805 {// mode: Bit 7 is 1 if no clear screen
807 // Should we clear the screen ?
808 Bit8u noclearmem
=mode
&0x80;
809 Bit8u line
,mmask
,*palette
;
810 Bit16u i
,twidth
,theight
,cheight
;
811 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
815 if (vbe_has_vbe_display()) {
816 dispi_set_enable(VBE_DISPI_DISABLED
);
823 // find the entry in the video modes
824 line
=find_vga_entry(mode
);
827 printf("mode search %02x found line %02x\n",mode
,line
);
833 twidth
=vga_modes
[line
].twidth
;
834 theight
=vga_modes
[line
].theight
;
835 cheight
=vga_modes
[line
].cheight
;
837 // Read the bios vga control
838 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
840 // Read the bios vga switches
841 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
843 // Read the bios mode set control
844 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
846 // Then we know the number of lines
849 // if palette loading (bit 3 of modeset ctl = 0)
850 if((modeset_ctl
&0x08)==0)
852 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
854 // Set the whole dac always, from 0
855 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
857 // From which palette
858 switch(vga_modes
[line
].dacmodel
)
872 // Always 256*3 values
873 for(i
=0;i
<0x0100;i
++)
874 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
875 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
876 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
877 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
880 {outb(VGAREG_DAC_DATA
,0);
881 outb(VGAREG_DAC_DATA
,0);
882 outb(VGAREG_DAC_DATA
,0);
885 if((modeset_ctl
&0x02)==0x02)
887 biosfn_perform_gray_scale_summing(0x00, 0x100);
891 // Reset Attribute Ctl flip-flop
892 inb(VGAREG_ACTL_RESET
);
895 for(i
=0;i
<=ACTL_MAX_REG
;i
++)
896 {outb(VGAREG_ACTL_ADDRESS
,i
);
897 outb(VGAREG_ACTL_WRITE_DATA
,actl_regs
[vga_modes
[line
].actlmodel
][i
]);
901 for(i
=0;i
<=SEQU_MAX_REG
;i
++)
902 {outb(VGAREG_SEQU_ADDRESS
,i
);
903 outb(VGAREG_SEQU_DATA
,sequ_regs
[vga_modes
[line
].sequmodel
][i
]);
907 for(i
=0;i
<=GRDC_MAX_REG
;i
++)
908 {outb(VGAREG_GRDC_ADDRESS
,i
);
909 outb(VGAREG_GRDC_DATA
,grdc_regs
[vga_modes
[line
].grdcmodel
][i
]);
912 // Set CRTC address VGA or MDA
913 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
916 for(i
=0;i
<=CRTC_MAX_REG
;i
++)
918 outb(crtc_addr
+1,crtc_regs
[vga_modes
[line
].crtcmodel
][i
]);
921 // Set the misc register
922 outb(VGAREG_WRITE_MISC_OUTPUT
,vga_modes
[line
].miscreg
);
925 outb(VGAREG_ACTL_ADDRESS
,0x20);
926 inb(VGAREG_ACTL_RESET
);
930 if(vga_modes
[line
].class==TEXT
)
932 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
938 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
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
);
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
,vga_modes
[line
].slength
);
955 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
956 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theight
-1);
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
,0x00);
965 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2,0x00);
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...
972 if(vga_modes
[line
].class==TEXT
)
974 biosfn_set_cursor_shape(0x06,0x07);
977 // Set cursor pos for page 0..7
979 biosfn_set_cursor_pos(i
,0x0000);
982 biosfn_set_active_page(0x00);
984 // Write the fonts in memory
985 if(vga_modes
[line
].class==TEXT
)
988 ;; copy
and activate
8x16 font
998 // Set the ints 0x1F and 0x43
1000 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1006 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1011 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1016 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1022 // --------------------------------------------------------------------------------------------
1023 static void biosfn_set_cursor_shape (CH
,CL
)
1025 {Bit16u cheight
,curs
,crtc_addr
;
1031 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
1033 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
1034 if((cheight
>8) && (CL
<8) && (CH
<0x20))
1038 CH
= ((CH
+1) * cheight
/ 8) -1;
1042 CH
= ((CL
+1) * cheight
/ 8) - 2;
1044 CL
= ((CL
+1) * cheight
/ 8) - 1;
1047 // CTRC regs 0x0a and 0x0b
1048 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1049 outb(crtc_addr
,0x0a);
1050 outb(crtc_addr
+1,CH
);
1051 outb(crtc_addr
,0x0b);
1052 outb(crtc_addr
+1,CL
);
1055 // --------------------------------------------------------------------------------------------
1056 static void biosfn_set_cursor_pos (page
, cursor
)
1057 Bit8u page
;Bit16u cursor
;
1059 Bit8u xcurs
,ycurs
,current
;
1060 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1062 // Should not happen...
1066 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1068 // Set the hardware cursor
1069 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1072 // Get the dimensions
1073 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1074 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1076 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1078 // Calculate the address knowing nbcols nbrows and page num
1079 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1081 // CRTC regs 0x0e and 0x0f
1082 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1083 outb(crtc_addr
,0x0e);
1084 outb(crtc_addr
+1,(address
&0xff00)>>8);
1085 outb(crtc_addr
,0x0f);
1086 outb(crtc_addr
+1,address
&0x00ff);
1090 // --------------------------------------------------------------------------------------------
1091 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1092 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1097 write_word(ss
, shape
, 0);
1098 write_word(ss
, pos
, 0);
1101 // FIXME should handle VGA 14/16 lines
1102 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1103 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1106 // --------------------------------------------------------------------------------------------
1107 static void biosfn_set_active_page (page
)
1110 Bit16u cursor
,dummy
,crtc_addr
;
1111 Bit16u nbcols
,nbrows
,address
;
1117 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1118 line
=find_vga_entry(mode
);
1119 if(line
==0xFF)return;
1121 // Get pos curs pos for the right page
1122 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1124 if(vga_modes
[line
].class==TEXT
)
1126 // Get the dimensions
1127 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1128 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1130 // Calculate the address knowing nbcols nbrows and page num
1131 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1132 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1135 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1139 address
= page
*vga_modes
[line
].slength
;
1142 // CRTC regs 0x0c and 0x0d
1143 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1144 outb(crtc_addr
,0x0c);
1145 outb(crtc_addr
+1,(address
&0xff00)>>8);
1146 outb(crtc_addr
,0x0d);
1147 outb(crtc_addr
+1,address
&0x00ff);
1149 // And change the BIOS page
1150 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1153 printf("Set active page %02x address %04x\n",page
,address
);
1156 // Display the cursor, now the page is active
1157 biosfn_set_cursor_pos(page
,cursor
);
1160 // --------------------------------------------------------------------------------------------
1161 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1162 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1164 // page == 0xFF if current
1167 Bit16u nbcols
,nbrows
,i
;
1174 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1175 line
=find_vga_entry(mode
);
1176 if(line
==0xFF)return;
1178 // Get the dimensions
1179 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1180 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1182 // Get the current page
1184 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1186 if(vga_modes
[line
].class==TEXT
)
1188 // Compute the address
1189 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1191 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1194 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1195 if(clr
>=nbcols
)clr
=nbcols
-1;
1196 if(nblines
>nbrows
)nblines
=0;
1198 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1200 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1205 {for(i
=rul
;i
<=rlr
;i
++)
1207 if((i
+nblines
>rlr
)||(nblines
==0))
1208 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1210 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1214 {for(i
=rlr
;i
>=rul
;i
--)
1216 if((i
<rul
+nblines
)||(nblines
==0))
1217 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1219 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1228 printf("Scroll in graphics mode ");
1234 // --------------------------------------------------------------------------------------------
1235 static void biosfn_read_char_attr (page
,car
)
1236 Bit8u page
;Bit16u
*car
;
1237 {Bit16u ss
=get_SS();
1238 Bit8u xcurs
,ycurs
,mode
,line
;
1239 Bit16u nbcols
,nbrows
,address
;
1240 Bit16u cursor
,dummy
;
1243 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1244 line
=find_vga_entry(mode
);
1245 if(line
==0xFF)return;
1247 // Get the cursor pos for the page
1248 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1249 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1251 // Get the dimensions
1252 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1253 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1255 if(vga_modes
[line
].class==TEXT
)
1257 // Compute the address
1258 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1260 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1271 // --------------------------------------------------------------------------------------------
1272 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1273 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1277 Bit16u addr
,dest
,src
;
1289 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1290 src
= car
* cheight
;
1291 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
1292 mmask
= inb( VGAREG_SEQU_DATA
);
1293 for(i
=0;i
<cheight
;i
++)
1296 outb( VGAREG_SEQU_DATA
, 0x0f );
1297 write_byte(0xa000,dest
,0x00);
1298 outb( VGAREG_SEQU_DATA
, attr
& 0x0f );
1299 write_byte(0xa000,dest
,fdata
[src
+i
]);
1301 outb( VGAREG_SEQU_DATA
, mmask
);
1304 // --------------------------------------------------------------------------------------------
1305 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1306 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1308 Bit8u i
,j
,mask
,data
;
1310 Bit16u addr
,dest
,src
;
1313 addr
=(xcurs
*bpp
)+ycurs
*320;
1317 dest
=addr
+(i
>>1)*80;
1318 if (i
& 1) dest
+= 0x2000;
1324 data
= read_byte(0xb800,dest
);
1332 if (fdata
[src
+i
] & mask
)
1336 data
^= (attr
& 0x01) << (7-j
);
1340 data
|= (attr
& 0x01) << (7-j
);
1345 write_byte(0xb800,dest
,data
);
1353 data
= read_byte(0xb800,dest
);
1361 if (fdata
[src
+i
] & mask
)
1365 data
^= (attr
& 0x03) << ((3-j
)*2);
1369 data
|= (attr
& 0x03) << ((3-j
)*2);
1374 write_byte(0xb800,dest
,data
);
1381 // --------------------------------------------------------------------------------------------
1382 static void write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
)
1383 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;
1385 Bit8u i
,j
,mask
,data
;
1387 Bit16u addr
,dest
,src
;
1390 addr
=xcurs
*8+ycurs
*nbcols
*64;
1394 dest
=addr
+i
*nbcols
*8;
1399 if (fdata
[src
+i
] & mask
)
1403 write_byte(0xa000,dest
+j
,data
);
1409 // --------------------------------------------------------------------------------------------
1410 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1411 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1413 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1414 Bit16u nbcols
,nbrows
,address
;
1415 Bit16u cursor
,dummy
;
1418 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1419 line
=find_vga_entry(mode
);
1420 if(line
==0xFF)return;
1422 // Get the cursor pos for the page
1423 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1424 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1426 // Get the dimensions
1427 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1428 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1430 if(vga_modes
[line
].class==TEXT
)
1432 // Compute the address
1433 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1435 dummy
=((Bit16u
)attr
<<8)+car
;
1436 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1440 // FIXME gfx mode not complete
1441 cheight
=vga_modes
[line
].cheight
;
1442 bpp
=vga_modes
[line
].pixbits
;
1443 while((count
-->0) && (xcurs
<nbcols
))
1445 if(vga_modes
[line
].memmodel
==PLANAR4
)
1447 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1449 else if(vga_modes
[line
].memmodel
==CGA
)
1451 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1453 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1455 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1468 // --------------------------------------------------------------------------------------------
1469 static void biosfn_write_char_only (car
,page
,attr
,count
)
1470 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1472 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1473 Bit16u nbcols
,nbrows
,address
;
1474 Bit16u cursor
,dummy
;
1477 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1478 line
=find_vga_entry(mode
);
1479 if(line
==0xFF)return;
1481 // Get the cursor pos for the page
1482 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1483 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1485 // Get the dimensions
1486 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1487 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1489 if(vga_modes
[line
].class==TEXT
)
1491 // Compute the address
1492 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1495 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1501 // FIXME gfx mode not complete
1502 cheight
=vga_modes
[line
].cheight
;
1503 bpp
=vga_modes
[line
].pixbits
;
1504 while((count
-->0) && (xcurs
<nbcols
))
1506 if(vga_modes
[line
].memmodel
==PLANAR4
)
1508 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1510 else if(vga_modes
[line
].memmodel
==CGA
)
1512 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1514 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1516 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1529 // --------------------------------------------------------------------------------------------
1530 static void biosfn_set_border_color (BL
) Bit8u BL
;
1531 // FIXME anybody using this function ?
1538 // --------------------------------------------------------------------------------------------
1539 static void biosfn_set_palette (BL
) Bit8u BL
;
1540 // FIXME anybody using this function ?
1547 // --------------------------------------------------------------------------------------------
1548 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1550 Bit8u mode
,line
,mask
,attr
;
1554 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1555 line
=find_vga_entry(mode
);
1556 if(line
==0xFF)return;
1557 if(vga_modes
[line
].class==TEXT
)return;
1559 if(vga_modes
[line
].memmodel
==CGA
)
1561 if(vga_modes
[line
].pixbits
==2)
1563 addr
=(CX
>>2)+(DX
>>1)*80;
1567 addr
=(CX
>>3)+(DX
>>1)*80;
1569 if (DX
& 1) addr
+= 0x2000;
1570 data
= read_byte(0xb800,addr
);
1571 if(vga_modes
[line
].pixbits
==2)
1573 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1574 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1578 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1579 mask
= 0x01 << (7 - (CX
& 0x07));
1590 write_byte(0xb800,addr
,data
);
1592 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1594 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1595 write_byte(0xa000,addr
,AL
);
1605 // --------------------------------------------------------------------------------------------
1606 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1608 Bit8u mode
,line
,attr
;
1613 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1614 line
=find_vga_entry(mode
);
1615 if(line
==0xFF)return;
1616 if(vga_modes
[line
].class==TEXT
)return;
1618 if(vga_modes
[line
].memmodel
==CGA
)
1620 addr
=(CX
>>2)+(DX
>>1)*80;
1621 if (DX
& 1) addr
+= 0x2000;
1622 data
= read_byte(0xb800,addr
);
1623 if(vga_modes
[line
].pixbits
==2)
1625 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1629 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1632 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1634 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1635 attr
=read_byte(0xa000,addr
);
1644 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1647 // --------------------------------------------------------------------------------------------
1648 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1649 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1650 {// flag = WITH_ATTR / NO_ATTR
1652 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1653 Bit16u nbcols
,nbrows
,address
;
1654 Bit16u cursor
,dummy
;
1656 // special case if page is 0xff, use current page
1658 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1663 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1664 line
=find_vga_entry(mode
);
1665 if(line
==0xFF)return;
1667 // Get the cursor pos for the page
1668 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1669 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1671 // Get the dimensions
1672 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1673 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1697 biosfn_write_teletype(' ',page
,attr
,flag
);
1698 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1699 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1705 if(vga_modes
[line
].class==TEXT
)
1707 // Compute the address
1708 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1711 write_byte(vga_modes
[line
].sstart
,address
,car
);
1714 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1718 // FIXME gfx mode not complete
1719 cheight
=vga_modes
[line
].cheight
;
1720 bpp
=vga_modes
[line
].pixbits
;
1721 if(vga_modes
[line
].memmodel
==PLANAR4
)
1723 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1725 else if(vga_modes
[line
].memmodel
==CGA
)
1727 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1729 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1731 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1744 // Do we need to wrap ?
1750 // Do we need to scroll ?
1752 {biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1756 // Set the cursor for the page
1757 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1758 biosfn_set_cursor_pos(page
,cursor
);
1761 // --------------------------------------------------------------------------------------------
1763 biosfn_get_video_mode
:
1765 mov ax
, #biosmem_seg
1768 mov bx
, #biosmem_current_page
1773 mov bx
, #biosmem_video_ctl
1776 mov bx
, #biosmem_current_mode
1779 mov bx
, #biosmem_nb_cols
1786 // --------------------------------------------------------------------------------------------
1787 static void biosfn_set_single_palette_reg (reg
,value
)
1788 Bit8u reg
;Bit8u value
;
1790 if(reg
<=ACTL_MAX_REG
)
1792 inb(VGAREG_ACTL_RESET
);
1793 outb(VGAREG_ACTL_ADDRESS
,reg
);
1794 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1795 outb(VGAREG_ACTL_ADDRESS
,0x20);
1799 // --------------------------------------------------------------------------------------------
1800 static void biosfn_set_overscan_border_color (value
)
1803 inb(VGAREG_ACTL_RESET
);
1804 outb(VGAREG_ACTL_ADDRESS
,0x11);
1805 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1806 outb(VGAREG_ACTL_ADDRESS
,0x20);
1809 // --------------------------------------------------------------------------------------------
1810 static void biosfn_set_all_palette_reg (seg
,offset
)
1811 Bit16u seg
;Bit16u offset
;
1815 inb(VGAREG_ACTL_RESET
);
1819 outb(VGAREG_ACTL_ADDRESS
,i
);
1820 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1825 outb(VGAREG_ACTL_ADDRESS
,0x11);
1826 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1827 outb(VGAREG_ACTL_ADDRESS
,0x20);
1830 // --------------------------------------------------------------------------------------------
1831 static void biosfn_toggle_intensity (state
)
1835 inb(VGAREG_ACTL_RESET
);
1837 outb(VGAREG_ACTL_ADDRESS
,0x10);
1838 value
=inb(VGAREG_ACTL_READ_DATA
);
1841 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1842 outb(VGAREG_ACTL_ADDRESS
,0x20);
1845 // --------------------------------------------------------------------------------------------
1846 static void biosfn_get_single_palette_reg (reg
,value
)
1847 Bit8u reg
;Bit16u
*value
;
1848 {Bit16u ss
=get_SS();
1850 if(reg
<=ACTL_MAX_REG
)
1852 inb(VGAREG_ACTL_RESET
);
1853 outb(VGAREG_ACTL_ADDRESS
,reg
);
1854 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1855 inb(VGAREG_ACTL_RESET
);
1856 outb(VGAREG_ACTL_ADDRESS
,0x20);
1860 // --------------------------------------------------------------------------------------------
1861 static void biosfn_read_overscan_border_color (value
)
1863 {Bit16u ss
=get_SS();
1865 inb(VGAREG_ACTL_RESET
);
1866 outb(VGAREG_ACTL_ADDRESS
,0x11);
1867 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1868 outb(VGAREG_ACTL_ADDRESS
,0x20);
1871 // --------------------------------------------------------------------------------------------
1872 static void biosfn_get_all_palette_reg (seg
,offset
) Bit16u seg
;Bit16u offset
;
1879 inb(VGAREG_ACTL_RESET
);
1880 outb(VGAREG_ACTL_ADDRESS
,i
);
1881 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1886 outb(VGAREG_ACTL_ADDRESS
,0x11);
1887 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1888 outb(VGAREG_ACTL_ADDRESS
,0x20);
1891 // --------------------------------------------------------------------------------------------
1892 static void biosfn_set_single_dac_reg (reg
,g
,b
,r
)
1893 Bit16u reg
;Bit8u g
;Bit8u b
;Bit8u r
;
1895 outb(VGAREG_DAC_WRITE_ADDRESS
,reg
);
1896 outb(VGAREG_DAC_DATA
,r
);
1897 outb(VGAREG_DAC_DATA
,g
);
1898 outb(VGAREG_DAC_DATA
,b
);
1901 // --------------------------------------------------------------------------------------------
1902 static void biosfn_set_all_dac_reg (start
,count
,seg
,offset
)
1903 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1905 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
1906 for(i
=0;i
<count
;i
++)
1907 {outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1908 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1909 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1913 // --------------------------------------------------------------------------------------------
1914 static void biosfn_select_video_dac_color_page (function
,page
)
1918 inb(VGAREG_ACTL_RESET
);
1919 outb(VGAREG_ACTL_ADDRESS
,0x10);
1921 value
=inb(VGAREG_ACTL_READ_DATA
);
1927 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1931 inb(VGAREG_ACTL_RESET
);
1932 outb(VGAREG_ACTL_ADDRESS
,0x14);
1934 outb(VGAREG_ACTL_WRITE_DATA
,page
&0x0f);
1936 outb(VGAREG_ACTL_WRITE_DATA
,(page
&0x03)<<2);
1938 outb(VGAREG_ACTL_ADDRESS
,0x20);
1941 // --------------------------------------------------------------------------------------------
1942 static void biosfn_read_single_dac_reg (reg
,tor
,togb
)
1943 Bit8u reg
;Bit16u
*tor
;Bit16u
*togb
;
1944 {Bit16u ss
=get_SS();
1947 outb(VGAREG_DAC_READ_ADDRESS
,reg
);
1948 r
=inb(VGAREG_DAC_DATA
);
1949 g
=inb(VGAREG_DAC_DATA
);
1950 b
=inb(VGAREG_DAC_DATA
);
1951 write_word(ss
,tor
,((Bit16u
)r
)<<8);
1952 write_word(ss
,togb
,(((Bit16u
)g
)<<8)+b
);
1955 // --------------------------------------------------------------------------------------------
1956 static void biosfn_read_all_dac_reg (start
,count
,seg
,offset
)
1957 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1959 outb(VGAREG_DAC_READ_ADDRESS
,start
);
1960 for(i
=0;i
<count
;i
++)
1961 {write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1962 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1963 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1967 // --------------------------------------------------------------------------------------------
1968 static void biosfn_set_pel_mask (mask
)
1971 outb(VGAREG_PEL_MASK
,mask
);
1974 // --------------------------------------------------------------------------------------------
1975 static void biosfn_read_pel_mask (mask
)
1977 {Bit16u ss
=get_SS();
1979 write_word(ss
,mask
,inb(VGAREG_PEL_MASK
));
1982 // --------------------------------------------------------------------------------------------
1983 static void biosfn_read_video_dac_state (state
) Bit16u
*state
;
1984 {Bit16u ss
=get_SS();
1987 inb(VGAREG_ACTL_RESET
);
1988 outb(VGAREG_ACTL_ADDRESS
,0x10);
1989 mcr
=(inb(VGAREG_ACTL_READ_DATA
)>>7)&0x01;
1990 inb(VGAREG_ACTL_RESET
);
1991 outb(VGAREG_ACTL_ADDRESS
,0x14);
1992 csr
=inb(VGAREG_ACTL_READ_DATA
)&0x0f;
1993 if(mcr
==0)(csr
>>2)&0x03;
1995 write_word(ss
,state
,(mcr
<<8)+csr
);
1996 outb(VGAREG_ACTL_ADDRESS
,0x20);
1999 // --------------------------------------------------------------------------------------------
2000 static void biosfn_perform_gray_scale_summing (start
,count
)
2001 Bit16u start
;Bit16u count
;
2006 inb(VGAREG_ACTL_RESET
);
2007 outb(VGAREG_ACTL_ADDRESS
,0x00);
2009 for( index
= 0; index
< count
; index
++ )
2011 // set read address and switch to read mode
2012 outb(VGAREG_DAC_READ_ADDRESS
,start
);
2013 // get 6-bit wide RGB data values
2014 r
=inb( VGAREG_DAC_DATA
);
2015 g
=inb( VGAREG_DAC_DATA
);
2016 b
=inb( VGAREG_DAC_DATA
);
2018 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2019 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
2023 // set write address and switch to write mode
2024 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
2025 // write new intensity value
2026 outb( VGAREG_DAC_DATA
, i
&0xff );
2027 outb( VGAREG_DAC_DATA
, i
&0xff );
2028 outb( VGAREG_DAC_DATA
, i
&0xff );
2031 inb(VGAREG_ACTL_RESET
);
2032 outb(VGAREG_ACTL_ADDRESS
,0x20);
2035 // --------------------------------------------------------------------------------------------
2036 static void get_font_access()
2039 mov dx
, #vgareg_sequ_address
2048 mov dx
, #vgareg_grdc_address
2058 static void release_font_access()
2061 mov dx
, #vgareg_sequ_address
2070 mov dx
, #vgareg_grdc_address
2087 static void set_scan_lines(lines
) Bit8u lines
;
2089 Bit16u crtc_addr
,cols
,page
,vde
;
2090 Bit8u crtc_r9
,ovl
,rows
;
2092 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2093 outb(crtc_addr
, 0x09);
2094 crtc_r9
= inb(crtc_addr
+1);
2095 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2096 outb(crtc_addr
+1, crtc_r9
);
2099 biosfn_set_cursor_shape(0x06,0x07);
2103 biosfn_set_cursor_shape(lines
-4,lines
-3);
2105 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2106 outb(crtc_addr
, 0x12);
2107 vde
= inb(crtc_addr
+1);
2108 outb(crtc_addr
, 0x07);
2109 ovl
= inb(crtc_addr
+1);
2110 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2112 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2113 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2114 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2117 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
;
2119 Bit16u blockaddr
,dest
,i
,src
;
2122 blockaddr
= BL
<< 13;
2126 dest
= blockaddr
+ (DX
+ i
) * 32;
2127 memcpyb(0xA000, dest
, ES
, src
, BH
);
2129 release_font_access();
2136 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2138 Bit16u blockaddr
,dest
,i
,src
;
2141 blockaddr
= BL
<< 13;
2142 for(i
=0;i
<0x100;i
++)
2145 dest
= blockaddr
+ i
* 32;
2146 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2148 release_font_access();
2155 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2157 Bit16u blockaddr
,dest
,i
,src
;
2160 blockaddr
= BL
<< 13;
2161 for(i
=0;i
<0x100;i
++)
2164 dest
= blockaddr
+ i
* 32;
2165 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2167 release_font_access();
2174 static void biosfn_set_text_block_specifier (BL
) Bit8u BL
;
2176 outb( VGAREG_SEQU_ADDRESS
, 0x03 );
2177 outb( VGAREG_SEQU_DATA
, BL
);
2180 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2182 Bit16u blockaddr
,dest
,i
,src
;
2185 blockaddr
= BL
<< 13;
2186 for(i
=0;i
<0x100;i
++)
2189 dest
= blockaddr
+ i
* 32;
2190 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2192 release_font_access();
2199 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2205 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2211 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2217 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2223 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2229 // --------------------------------------------------------------------------------------------
2230 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2231 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2232 {Bit16u ss
=get_SS();
2236 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2237 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2240 write_word(ss
,ES
,read_word(0x00,0x43*4));
2241 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2244 write_word(ss
,ES
,0xC000);
2245 write_word(ss
,BP
,vgafont14
);
2248 write_word(ss
,ES
,0xC000);
2249 write_word(ss
,BP
,vgafont8
);
2252 write_word(ss
,ES
,0xC000);
2253 write_word(ss
,BP
,vgafont8
+128*8);
2256 write_word(ss
,ES
,0xC000);
2257 write_word(ss
,BP
,vgafont14alt
);
2260 write_word(ss
,ES
,0xC000);
2261 write_word(ss
,BP
,vgafont16
);
2264 write_word(ss
,ES
,0xC000);
2265 write_word(ss
,BP
,vgafont16alt
);
2269 printf("Get font info BH(%02x) was discarded\n",BH
);
2273 // Set byte/char of on screen font
2274 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2276 // Set Highest char row
2277 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2280 // --------------------------------------------------------------------------------------------
2281 static void biosfn_get_ega_info (BX
,CX
)
2282 Bit16u
*BX
;Bit16u
*CX
;
2283 {Bit16u ss
=get_SS();
2287 crtc
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2288 if(crtc
==VGAREG_MDA_CRTC_ADDRESS
)
2289 write_word(ss
,BX
,(1<<8)+0x0003);
2291 write_word(ss
,BX
,0x0003);
2293 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2294 write_word(ss
,CX
,(switches
&0x0f));
2297 // --------------------------------------------------------------------------------------------
2298 static void biosfn_alternate_prtsc()
2305 // --------------------------------------------------------------------------------------------
2306 static void biosfn_select_vert_res (res
)
2308 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2309 Bit8u modeset
,switches
;
2311 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2312 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2315 // set modeset ctl bit 7 and reset bit 4
2316 // set switches bit 3-0 to 0x08
2317 modeset
|=0x80;modeset
&=0xef;
2318 switches
&=0xf0;switches
|=0x08;
2321 // reset modeset ctl bit 7 and bit 4
2322 // set switches bit 3-0 to 0x09
2324 switches
&=0xf0;switches
|=0x09;
2327 // reset modeset ctl bit 7 and set bit 4
2328 // set switches bit 3-0 to 0x09
2329 modeset
|=0x10;modeset
&=0x7f;
2330 switches
&=0xf0;switches
|=0x09;
2334 printf("Select vert res (%02x) was discarded\n",res
);
2338 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2339 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,switches
);
2342 // --------------------------------------------------------------------------------------------
2343 static void biosfn_enable_default_palette_loading (disable
)
2348 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2351 if(disable
!=0x00)modeset
|=0x08;
2354 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2357 // --------------------------------------------------------------------------------------------
2358 static void biosfn_enable_video_addressing (disable
)
2363 misc
=inb(VGAREG_READ_MISC_OUTPUT
);
2365 if(disable
!=0x00) misc
&=0xfd;
2367 outb(VGAREG_WRITE_MISC_OUTPUT
,misc
);
2370 // --------------------------------------------------------------------------------------------
2371 static void biosfn_enable_grayscale_summing (disable
)
2376 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2378 // Bit 1 set if disable=0
2379 if(disable
==0x00)modeset
|=0x02;
2382 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2385 // --------------------------------------------------------------------------------------------
2386 static void biosfn_enable_cursor_emulation (disable
)
2391 videoctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
2393 // Bit 0 set if disable!=0
2394 if(disable
!=0x00)videoctl
|=0x01;
2395 else videoctl
&=0xfe;
2397 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,videoctl
);
2400 // --------------------------------------------------------------------------------------------
2401 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2407 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2414 // --------------------------------------------------------------------------------------------
2415 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2416 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2418 Bit16u newcurs
,oldcurs
,dummy
;
2421 // Read curs info for the page
2422 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2424 // if row=0xff special case : use current cursor position
2426 {col
=oldcurs
&0x00ff;
2427 row
=(oldcurs
&0xff00)>>8;
2430 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
2431 biosfn_set_cursor_pos(page
,newcurs
);
2435 car
=read_byte(seg
,offset
++);
2437 attr
=read_byte(seg
,offset
++);
2439 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
2442 // Set back curs pos
2444 biosfn_set_cursor_pos(page
,oldcurs
);
2447 // --------------------------------------------------------------------------------------------
2451 je biosfn_read_display_code
2453 je biosfn_set_display_code
2458 biosfn_read_display_code
:
2461 mov ax
, #biosmem_seg
2463 mov bx
, #biosmem_dcc_index
2471 biosfn_set_display_code
:
2475 mov ax
, #biosmem_seg
2478 mov bx
, #biosmem_dcc_index
2484 mov bx
, #msg_alt_dcc
2497 .ascii
"Alternate Display code (%02x) was discarded"
2498 .byte
0x0d,0x0a,0x00
2502 // --------------------------------------------------------------------------------------------
2503 static void biosfn_read_state_info (BX
,ES
,DI
)
2504 Bit16u BX
;Bit16u ES
;Bit16u DI
;
2506 // Address of static functionality table
2507 write_word(ES
,DI
+0x00,&static_functionality
);
2508 write_word(ES
,DI
+0x02,0xC000);
2510 // Hard coded copy from BIOS area. Should it be cleaner ?
2511 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
2512 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
2514 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2515 write_byte(ES
,DI
+0x26,0);
2516 write_byte(ES
,DI
+0x27,16);
2517 write_byte(ES
,DI
+0x28,0);
2518 write_byte(ES
,DI
+0x29,8);
2519 write_byte(ES
,DI
+0x2a,2);
2520 write_byte(ES
,DI
+0x2b,0);
2521 write_byte(ES
,DI
+0x2c,0);
2522 write_byte(ES
,DI
+0x31,3);
2523 write_byte(ES
,DI
+0x32,0);
2525 memsetb(ES
,DI
+0x33,0,13);
2528 // --------------------------------------------------------------------------------------------
2529 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2535 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2541 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2548 // ============================================================================================
2552 // ============================================================================================
2554 // --------------------------------------------------------------------------------------------
2555 static Bit8u
find_vga_entry(mode
)
2559 for(i
=0;i
<=MODE_MAX
;i
++)
2560 if(vga_modes
[i
].svgamode
==mode
)
2567 /* =========================================================== */
2571 /* =========================================================== */
2573 // --------------------------------------------------------------------------------------------
2574 static void memsetb(seg
,offset
,value
,count
)
2589 mov cx
, 10[bp
] ; count
2592 mov ax
, 4[bp
] ; segment
2594 mov ax
, 6[bp
] ; offset
2596 mov al
, 8[bp
] ; value
2611 // --------------------------------------------------------------------------------------------
2612 static void memsetw(seg
,offset
,value
,count
)
2627 mov cx
, 10[bp
] ; count
2630 mov ax
, 4[bp
] ; segment
2632 mov ax
, 6[bp
] ; offset
2634 mov ax
, 8[bp
] ; value
2649 // --------------------------------------------------------------------------------------------
2650 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
2668 mov cx
, 12[bp
] ; count
2671 mov ax
, 4[bp
] ; dsegment
2673 mov ax
, 6[bp
] ; doffset
2675 mov ax
, 8[bp
] ; ssegment
2677 mov ax
, 10[bp
] ; soffset
2695 // --------------------------------------------------------------------------------------------
2696 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
2714 mov cx
, 12[bp
] ; count
2717 mov ax
, 4[bp
] ; dsegment
2719 mov ax
, 6[bp
] ; doffset
2721 mov ax
, 8[bp
] ; ssegment
2723 mov ax
, 10[bp
] ; soffset
2741 /* =========================================================== */
2743 * These functions where ripped from Kevin's rombios.c
2745 /* =========================================================== */
2747 // --------------------------------------------------------------------------------------------
2749 read_byte(seg
, offset
)
2759 mov ax
, 4[bp
] ; segment
2761 mov bx
, 6[bp
] ; offset
2763 ;; al
= return value (byte
)
2771 // --------------------------------------------------------------------------------------------
2773 read_word(seg
, offset
)
2783 mov ax
, 4[bp
] ; segment
2785 mov bx
, 6[bp
] ; offset
2787 ;; ax
= return value (word
)
2795 // --------------------------------------------------------------------------------------------
2797 write_byte(seg
, offset
, data
)
2809 mov ax
, 4[bp
] ; segment
2811 mov bx
, 6[bp
] ; offset
2812 mov al
, 8[bp
] ; data byte
2813 mov
[bx
], al
; write data byte
2822 // --------------------------------------------------------------------------------------------
2824 write_word(seg
, offset
, data
)
2836 mov ax
, 4[bp
] ; segment
2838 mov bx
, 6[bp
] ; offset
2839 mov ax
, 8[bp
] ; data word
2840 mov
[bx
], ax
; write data word
2849 // --------------------------------------------------------------------------------------------
2884 // --------------------------------------------------------------------------------------------
2906 // --------------------------------------------------------------------------------------------
2936 void unimplemented()
2938 printf("--> Unimplemented\n");
2943 printf("--> Unknown int10\n");
2947 // --------------------------------------------------------------------------------------------
2951 Bit8u c
, format_char
;
2953 unsigned format_width
, i
;
2955 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
2963 while (c
= read_byte(0xc000, s
)) {
2968 else if (in_format
) {
2969 if ( (c
>='0') && (c
<='9') ) {
2970 format_width
= (format_width
* 10) + (c
- '0');
2972 else if (c
== 'x') {
2973 arg_ptr
++; // increment to next arg
2974 arg
= read_word(arg_seg
, arg_ptr
);
2975 if (format_width
== 0)
2978 digit
= format_width
- 1;
2979 for (i
=0; i
<format_width
; i
++) {
2980 nibble
= (arg
>> (4 * digit
)) & 0x000f;
2982 outb(0x0500, nibble
+ '0');
2984 outb(0x0500, (nibble
- 10) + 'A');
2989 //else if (c == 'd') {
3004 // --------------------------------------------------------------------------------------------
3007 ;; DATA_SEG_DEFS_HERE
3011 .ascii
"vgabios ends here"
3015 ;; BLOCK_STRINGS_BEGIN