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 void init_vga_card();
75 static void init_bios_area();
77 static Bit8u
find_vga_entry();
79 static void memsetb();
80 static void memsetw();
81 static void memcpyb();
82 static void memcpyw();
84 static void biosfn_set_video_mode();
85 static void biosfn_set_cursor_shape();
86 static void biosfn_set_cursor_pos();
87 static void biosfn_get_cursor_pos();
88 static void biosfn_set_active_page();
89 static void biosfn_scroll();
90 static void biosfn_read_char_attr();
91 static void biosfn_write_char_attr();
92 static void biosfn_write_char_only();
93 static void biosfn_set_border_color();
94 static void biosfn_set_palette();
95 static void biosfn_write_pixel();
96 static void biosfn_read_pixel();
97 static void biosfn_write_teletype();
98 static void biosfn_set_single_palette_reg();
99 static void biosfn_set_overscan_border_color();
100 static void biosfn_set_all_palette_reg();
101 static void biosfn_toggle_intensity();
102 static void biosfn_get_single_palette_reg();
103 static void biosfn_read_overscan_border_color();
104 static void biosfn_get_all_palette_reg();
105 static void biosfn_set_single_dac_reg();
106 static void biosfn_set_all_dac_reg();
107 static void biosfn_select_video_dac_color_page();
108 static void biosfn_read_single_dac_reg();
109 static void biosfn_read_all_dac_reg();
110 static void biosfn_set_pel_mask();
111 static void biosfn_read_pel_mask();
112 static void biosfn_read_video_dac_state();
113 static void biosfn_perform_gray_scale_summing();
114 static void biosfn_load_text_user_pat();
115 static void biosfn_load_text_8_14_pat();
116 static void biosfn_load_text_8_8_pat();
117 static void biosfn_set_text_block_specifier();
118 static void biosfn_load_text_8_16_pat();
119 static void biosfn_load_gfx_8_8_chars();
120 static void biosfn_load_gfx_user_chars();
121 static void biosfn_load_gfx_8_14_chars();
122 static void biosfn_load_gfx_8_8_dd_chars();
123 static void biosfn_load_gfx_8_16_chars();
124 static void biosfn_get_font_info();
125 static void biosfn_get_ega_info();
126 static void biosfn_alternate_prtsc();
127 static void biosfn_select_vert_res();
128 static void biosfn_enable_default_palette_loading();
129 static void biosfn_enable_video_addressing();
130 static void biosfn_enable_grayscale_summing();
131 static void biosfn_enable_cursor_emulation();
132 static void biosfn_switch_video_interface();
133 static void biosfn_enable_video_refresh_control();
134 static void biosfn_write_string();
135 static void biosfn_set_display_code();
136 static void biosfn_read_state_info();
137 static void biosfn_read_video_state_size();
138 static void biosfn_save_video_state();
139 static void biosfn_restore_video_state();
141 // This is for compiling with gcc2 and gcc3
142 #define ASM_START #asm
143 #define ASM_END #endasm
148 biosmem_current_mode
= 0x49
149 biosmem_nb_cols
= 0x4a
150 biosmem_current_page
= 0x62
151 biosmem_video_ctl
= 0x87
152 biosmem_dcc_index
= 0x8a
175 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
177 .byte
0x40 /* BIOS extension length in units of 512 bytes */
182 jmp vgabios_init_func
185 .ascii
"Plex86/Bochs VGABios"
189 // Info from Bart Oldeman
208 .ascii
"(C) 2003 the LGPL VGABios developers Team"
213 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
219 .ascii
"Please visit :"
221 ;;.ascii
" . http://www.plex86.org"
223 .ascii
" . http://bochs.sourceforge.net"
225 .ascii
" . http://www.nongnu.org/vgabios"
231 ;; ============================================================================================
235 ;; ============================================================================================
241 ;; init basic bios vars
245 ;; init vbe functions
250 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
252 ;; display splash screen
253 call _display_splash_screen
255 ;; init video mode
and clear the screen
264 call _vbe_display_info
275 vgabios_int10_handler
:
279 call biosfn_get_video_mode
284 call biosfn_read_display_code
292 ;; We have to set ds to access the right data segment
305 #include "vgatables.h"
306 #include "vgafonts.h"
309 * Boot time harware inits
311 static void init_vga_card()
314 ;; switch to color mode
and enable CPU access
480 lines
319 ;; more than
64k
3C4
/04
331 printf("VGABios $Id$\n");
334 // --------------------------------------------------------------------------------------------
336 * Boot time bios area inits
338 static void init_bios_area()
340 // init detected hardware BIOS Area
341 write_word(BIOSMEM_SEG
,BIOSMEM_INITIAL_MODE
,read_word(BIOSMEM_SEG
,BIOSMEM_INITIAL_MODE
)&0xFFCF);
343 // Just for the first int10 find its children
345 // the default chat height
346 write_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,16);
349 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,0x60);
351 // Set the basic screen we have
352 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
354 // Set the basic modeset options
355 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,0x51);
357 // Set the default MSR
358 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x09);
361 // --------------------------------------------------------------------------------------------
363 * Boot time Splash screen
365 static void display_splash_screen()
369 // --------------------------------------------------------------------------------------------
374 static void display_info()
381 mov si
,#vgabios_version
384 ;;mov si
,#vgabios_copyright
385 ;;call _display_string
387 ;;call _display_string
389 mov si
,#vgabios_license
391 mov si
,#vgabios_website
396 static void display_string()
398 // Get length of string
425 // --------------------------------------------------------------------------------------------
427 // --------------------------------------------------------------------------------------------
429 * int10 main dispatcher
431 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
432 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
435 // 0E is write char...
437 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
444 biosfn_set_video_mode(GET_AL());
445 switch(GET_AL()&0x7F)
463 biosfn_set_cursor_shape(GET_CH(),GET_CL());
466 biosfn_set_cursor_pos(GET_BH(),DX
);
469 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
472 // Read light pen pos (unimplemented)
482 biosfn_set_active_page(GET_AL());
485 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
488 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
491 biosfn_read_char_attr(GET_BH(),&AX
);
494 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
497 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
501 biosfn_set_border_color(GET_BL());
503 biosfn_set_palette(GET_BL());
506 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
509 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
512 // Ralf Brown Interrupt list is WRONG on bh(page)
513 // We do output only on the current page !
514 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
520 biosfn_set_single_palette_reg(GET_BL(),GET_BH());
523 biosfn_set_overscan_border_color(GET_BH());
526 biosfn_set_all_palette_reg(ES
,DX
);
529 biosfn_toggle_intensity(GET_BL());
532 biosfn_get_single_palette_reg(GET_BL(),&BX
);
535 biosfn_read_overscan_border_color(&BX
);
538 biosfn_get_all_palette_reg(ES
,DX
);
541 biosfn_set_single_dac_reg(BX
,GET_CH(),GET_CL(),GET_DH());
544 biosfn_set_all_dac_reg(BX
,CX
,ES
,DX
);
547 biosfn_select_video_dac_color_page(GET_BL(),GET_BH());
550 biosfn_read_single_dac_reg(GET_BL(),&DX
,&CX
);
553 biosfn_read_all_dac_reg(BX
,CX
,ES
,DX
);
556 biosfn_set_pel_mask(GET_BL());
559 biosfn_read_pel_mask(&BX
);
562 biosfn_read_video_dac_state(&BX
);
565 biosfn_perform_gray_scale_summing(BX
,CX
);
578 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
582 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
586 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
589 biosfn_set_text_block_specifier(GET_BL());
593 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
596 biosfn_load_gfx_8_8_chars(ES
,BP
);
599 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
602 biosfn_load_gfx_8_14_chars(GET_BL());
605 biosfn_load_gfx_8_8_dd_chars(GET_BL());
608 biosfn_load_gfx_8_16_chars(GET_BL());
611 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
624 biosfn_get_ega_info(&BX
,&CX
);
627 biosfn_alternate_prtsc();
630 biosfn_select_vert_res(GET_AL());
634 biosfn_enable_default_palette_loading(GET_AL());
638 biosfn_enable_video_addressing(GET_AL());
642 biosfn_enable_grayscale_summing(GET_AL());
646 biosfn_enable_cursor_emulation(GET_AL());
650 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
654 biosfn_enable_video_refresh_control(GET_AL());
664 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
670 biosfn_set_display_code(GET_BL(),GET_BH());
680 biosfn_read_state_info(BX
,ES
,DI
);
687 biosfn_read_video_state_size(CX
,&BX
);
690 biosfn_save_video_state(CX
,ES
,BX
);
693 biosfn_restore_video_state(CX
,ES
,BX
);
705 if (vbe_has_vbe_display()) {
709 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
712 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
715 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
718 vbe_biosfn_return_current_mode(&AX
,&BX
);
729 vbe_biosfn_display_window_control(&AX
,BX
,&DX
);
732 vbe_biosfn_set_get_logical_scan_line_length(&AX
,&BX
,&CX
,&DX
);
735 vbe_biosfn_set_get_display_start(&AX
,BX
,CX
,DX
);
783 // ============================================================================================
787 // ============================================================================================
789 static void biosfn_set_video_mode(mode
) Bit8u mode
;
790 {// mode: Bit 7 is 1 if no clear screen
792 // Should we clear the screen ?
793 Bit8u noclearmem
=mode
&0x80;
794 Bit8u line
,mmask
,*palette
;
795 Bit16u i
,twidth
,theight
,cheight
;
796 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
800 if (vbe_has_vbe_display()) {
801 dispi_set_enable(VBE_DISPI_DISABLED
);
808 // find the entry in the video modes
809 line
=find_vga_entry(mode
);
812 printf("mode search %02x found line %02x\n",mode
,line
);
818 twidth
=vga_modes
[line
].twidth
;
819 theight
=vga_modes
[line
].theight
;
820 cheight
=vga_modes
[line
].cheight
;
822 // Read the bios vga control
823 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
825 // Read the bios vga switches
826 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
828 // Read the bios mode set control
829 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
831 // Then we know the number of lines
834 // if palette loading (bit 3 of modeset ctl = 0)
835 if((modeset_ctl
&0x08)==0)
837 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
839 // Set the whole dac always, from 0
840 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
842 // From which palette
843 switch(vga_modes
[line
].dacmodel
)
859 // Always 256*3 values
860 for(i
=0;i
<0x0100;i
++)
861 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
862 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
863 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
864 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
867 {outb(VGAREG_DAC_DATA
,0);
868 outb(VGAREG_DAC_DATA
,0);
869 outb(VGAREG_DAC_DATA
,0);
873 // Reset Attribute Ctl flip-flop
874 inb(VGAREG_ACTL_RESET
);
877 for(i
=0;i
<=ACTL_MAX_REG
;i
++)
878 {outb(VGAREG_ACTL_ADDRESS
,i
);
879 outb(VGAREG_ACTL_WRITE_DATA
,actl_regs
[vga_modes
[line
].actlmodel
][i
]);
883 for(i
=0;i
<=SEQU_MAX_REG
;i
++)
884 {outb(VGAREG_SEQU_ADDRESS
,i
);
885 outb(VGAREG_SEQU_DATA
,sequ_regs
[vga_modes
[line
].sequmodel
][i
]);
889 for(i
=0;i
<=GRDC_MAX_REG
;i
++)
890 {outb(VGAREG_GRDC_ADDRESS
,i
);
891 outb(VGAREG_GRDC_DATA
,grdc_regs
[vga_modes
[line
].grdcmodel
][i
]);
894 // Set CRTC address VGA or MDA
895 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
898 for(i
=0;i
<=CRTC_MAX_REG
;i
++)
900 outb(crtc_addr
+1,crtc_regs
[vga_modes
[line
].crtcmodel
][i
]);
903 // Set the misc register
904 outb(VGAREG_WRITE_MISC_OUTPUT
,vga_modes
[line
].miscreg
);
907 outb(VGAREG_ACTL_ADDRESS
,0x20);
908 inb(VGAREG_ACTL_RESET
);
912 if(vga_modes
[line
].class==TEXT
)
914 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
920 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
924 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
925 mmask
= inb( VGAREG_SEQU_DATA
);
926 outb( VGAREG_SEQU_DATA
, 0x0f ); // all planes
927 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x8000); // 64k
928 outb( VGAREG_SEQU_DATA
, mmask
);
934 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
,mode
);
935 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
,twidth
);
936 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
,vga_modes
[line
].slength
);
937 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
938 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theight
-1);
939 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,cheight
);
940 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,(0x60|noclearmem
));
941 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
942 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)&0x7f);
944 // FIXME We nearly have the good tables. to be reworked
945 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,0x08); // 8 is VGA should be ok for now
946 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
,0x00);
947 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2,0x00);
950 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x00); // Unavailable on vanilla vga, but...
951 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAL
,0x00); // Unavailable on vanilla vga, but...
954 if(vga_modes
[line
].class==TEXT
)
956 biosfn_set_cursor_shape(0x06,0x07);
959 // Set cursor pos for page 0..7
961 biosfn_set_cursor_pos(i
,0x0000);
964 biosfn_set_active_page(0x00);
966 // Write the fonts in memory
967 if(vga_modes
[line
].class==TEXT
)
970 ;; copy
and activate
8x16 font
980 // Set the ints 0x1F and 0x43
982 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
988 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
993 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
998 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1004 // --------------------------------------------------------------------------------------------
1005 static void biosfn_set_cursor_shape (CH
,CL
)
1007 {Bit16u cheight
,curs
,crtc_addr
;
1013 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
1015 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
1016 if((cheight
>8) && (CL
<8) && (CH
<0x20))
1020 CH
= ((CH
+1) * cheight
/ 8) -1;
1024 CH
= ((CL
+1) * cheight
/ 8) - 2;
1026 CL
= ((CL
+1) * cheight
/ 8) - 1;
1029 // CTRC regs 0x0a and 0x0b
1030 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1031 outb(crtc_addr
,0x0a);
1032 outb(crtc_addr
+1,CH
);
1033 outb(crtc_addr
,0x0b);
1034 outb(crtc_addr
+1,CL
);
1037 // --------------------------------------------------------------------------------------------
1038 static void biosfn_set_cursor_pos (page
, cursor
)
1039 Bit8u page
;Bit16u cursor
;
1041 Bit8u xcurs
,ycurs
,current
;
1042 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1044 // Should not happen...
1048 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1050 // Set the hardware cursor
1051 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1054 // Get the dimensions
1055 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1056 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1058 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1060 // Calculate the address knowing nbcols nbrows and page num
1061 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1063 // CRTC regs 0x0e and 0x0f
1064 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1065 outb(crtc_addr
,0x0e);
1066 outb(crtc_addr
+1,(address
&0xff00)>>8);
1067 outb(crtc_addr
,0x0f);
1068 outb(crtc_addr
+1,address
&0x00ff);
1072 // --------------------------------------------------------------------------------------------
1073 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1074 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1079 write_word(ss
, shape
, 0);
1080 write_word(ss
, pos
, 0);
1083 // FIXME should handle VGA 14/16 lines
1084 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1085 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1088 // --------------------------------------------------------------------------------------------
1089 static void biosfn_set_active_page (page
)
1092 Bit16u cursor
,dummy
,crtc_addr
;
1093 Bit16u nbcols
,nbrows
,address
;
1099 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1100 line
=find_vga_entry(mode
);
1101 if(line
==0xFF)return;
1103 // Get pos curs pos for the right page
1104 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1106 if(vga_modes
[line
].class==TEXT
)
1108 // Get the dimensions
1109 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1110 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1112 // Calculate the address knowing nbcols nbrows and page num
1113 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1114 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1117 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1121 address
= page
*vga_modes
[line
].slength
;
1124 // CRTC regs 0x0c and 0x0d
1125 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1126 outb(crtc_addr
,0x0c);
1127 outb(crtc_addr
+1,(address
&0xff00)>>8);
1128 outb(crtc_addr
,0x0d);
1129 outb(crtc_addr
+1,address
&0x00ff);
1131 // And change the BIOS page
1132 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1135 printf("Set active page %02x address %04x\n",page
,address
);
1138 // Display the cursor, now the page is active
1139 biosfn_set_cursor_pos(page
,cursor
);
1142 // --------------------------------------------------------------------------------------------
1143 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1144 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1146 // page == 0xFF if current
1149 Bit16u nbcols
,nbrows
,i
;
1156 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1157 line
=find_vga_entry(mode
);
1158 if(line
==0xFF)return;
1160 // Get the dimensions
1161 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1162 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1164 // Get the current page
1166 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1168 if(vga_modes
[line
].class==TEXT
)
1170 // Compute the address
1171 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1173 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1176 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1177 if(clr
>=nbcols
)clr
=nbcols
-1;
1178 if(nblines
>nbrows
)nblines
=0;
1180 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1182 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1187 {for(i
=rul
;i
<=rlr
;i
++)
1189 if((i
+nblines
>rlr
)||(nblines
==0))
1190 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1192 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1196 {for(i
=rlr
;i
>=rul
;i
--)
1198 if((i
<rul
+nblines
)||(nblines
==0))
1199 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1201 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1210 printf("Scroll in graphics mode ");
1216 // --------------------------------------------------------------------------------------------
1217 static void biosfn_read_char_attr (page
,car
)
1218 Bit8u page
;Bit16u
*car
;
1219 {Bit16u ss
=get_SS();
1220 Bit8u xcurs
,ycurs
,mode
,line
;
1221 Bit16u nbcols
,nbrows
,address
;
1222 Bit16u cursor
,dummy
;
1225 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1226 line
=find_vga_entry(mode
);
1227 if(line
==0xFF)return;
1229 // Get the cursor pos for the page
1230 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1231 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1233 // Get the dimensions
1234 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1235 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1237 if(vga_modes
[line
].class==TEXT
)
1239 // Compute the address
1240 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1242 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1253 // --------------------------------------------------------------------------------------------
1254 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1255 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1259 Bit16u addr
,dest
,src
;
1271 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1272 src
= car
* cheight
;
1273 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
1274 mmask
= inb( VGAREG_SEQU_DATA
);
1275 for(i
=0;i
<cheight
;i
++)
1278 outb( VGAREG_SEQU_DATA
, 0x0f );
1279 write_byte(0xa000,dest
,0x00);
1280 outb( VGAREG_SEQU_DATA
, attr
& 0x0f );
1281 write_byte(0xa000,dest
,fdata
[src
+i
]);
1283 outb( VGAREG_SEQU_DATA
, mmask
);
1286 // --------------------------------------------------------------------------------------------
1287 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1288 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1290 Bit8u i
,j
,mask
,data
;
1292 Bit16u addr
,dest
,src
;
1295 addr
=(xcurs
*bpp
)+ycurs
*320;
1299 dest
=addr
+(i
>>1)*80;
1300 if (i
& 1) dest
+= 0x2000;
1306 data
= read_byte(0xb800,dest
);
1314 if (fdata
[src
+i
] & mask
)
1318 data
^= (attr
& 0x01) << (7-j
);
1322 data
|= (attr
& 0x01) << (7-j
);
1327 write_byte(0xb800,dest
,data
);
1335 data
= read_byte(0xb800,dest
);
1343 if (fdata
[src
+i
] & mask
)
1347 data
^= (attr
& 0x03) << ((3-j
)*2);
1351 data
|= (attr
& 0x03) << ((3-j
)*2);
1356 write_byte(0xb800,dest
,data
);
1363 // --------------------------------------------------------------------------------------------
1364 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1365 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1367 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1368 Bit16u nbcols
,nbrows
,address
;
1369 Bit16u cursor
,dummy
;
1372 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1373 line
=find_vga_entry(mode
);
1374 if(line
==0xFF)return;
1376 // Get the cursor pos for the page
1377 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1378 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1380 // Get the dimensions
1381 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1382 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1384 if(vga_modes
[line
].class==TEXT
)
1386 // Compute the address
1387 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1389 dummy
=((Bit16u
)attr
<<8)+car
;
1390 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1394 // FIXME gfx mode not complete
1395 cheight
=vga_modes
[line
].cheight
;
1396 bpp
=vga_modes
[line
].pixbits
;
1397 while((count
-->0) && (xcurs
<nbcols
))
1399 if(vga_modes
[line
].memmodel
==PLANAR4
)
1401 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1403 else if(vga_modes
[line
].memmodel
==CGA
)
1405 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1418 // --------------------------------------------------------------------------------------------
1419 static void biosfn_write_char_only (car
,page
,attr
,count
)
1420 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1422 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1423 Bit16u nbcols
,nbrows
,address
;
1424 Bit16u cursor
,dummy
;
1427 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1428 line
=find_vga_entry(mode
);
1429 if(line
==0xFF)return;
1431 // Get the cursor pos for the page
1432 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1433 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1435 // Get the dimensions
1436 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1437 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1439 if(vga_modes
[line
].class==TEXT
)
1441 // Compute the address
1442 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1445 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1451 // FIXME gfx mode not complete
1452 cheight
=vga_modes
[line
].cheight
;
1453 bpp
=vga_modes
[line
].pixbits
;
1454 while((count
-->0) && (xcurs
<nbcols
))
1456 if(vga_modes
[line
].memmodel
==PLANAR4
)
1458 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1460 else if(vga_modes
[line
].memmodel
==CGA
)
1462 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1475 // --------------------------------------------------------------------------------------------
1476 static void biosfn_set_border_color (BL
) Bit8u BL
;
1477 // FIXME anybody using this function ?
1484 // --------------------------------------------------------------------------------------------
1485 static void biosfn_set_palette (BL
) Bit8u BL
;
1486 // FIXME anybody using this function ?
1493 // --------------------------------------------------------------------------------------------
1494 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1496 Bit8u mode
,line
,mask
,attr
;
1500 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1501 line
=find_vga_entry(mode
);
1502 if(line
==0xFF)return;
1503 if(vga_modes
[line
].class==TEXT
)return;
1505 if(vga_modes
[line
].memmodel
==CGA
)
1507 if(vga_modes
[line
].pixbits
==2)
1509 addr
=(CX
>>2)+(DX
>>1)*80;
1513 addr
=(CX
>>3)+(DX
>>1)*80;
1515 if (DX
& 1) addr
+= 0x2000;
1516 data
= read_byte(0xb800,addr
);
1517 if(vga_modes
[line
].pixbits
==2)
1519 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1520 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1524 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1525 mask
= 0x01 << (7 - (CX
& 0x07));
1536 write_byte(0xb800,addr
,data
);
1538 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1540 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1541 write_byte(0xa000,addr
,AL
);
1551 // --------------------------------------------------------------------------------------------
1552 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1554 Bit8u mode
,line
,attr
;
1559 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1560 line
=find_vga_entry(mode
);
1561 if(line
==0xFF)return;
1562 if(vga_modes
[line
].class==TEXT
)return;
1564 if(vga_modes
[line
].memmodel
==CGA
)
1566 addr
=(CX
>>2)+(DX
>>1)*80;
1567 if (DX
& 1) addr
+= 0x2000;
1568 data
= read_byte(0xb800,addr
);
1569 if(vga_modes
[line
].pixbits
==2)
1571 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1575 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1578 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1580 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1581 attr
=read_byte(0xa000,addr
);
1590 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1593 // --------------------------------------------------------------------------------------------
1594 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1595 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1596 {// flag = WITH_ATTR / NO_ATTR
1598 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1599 Bit16u nbcols
,nbrows
,address
;
1600 Bit16u cursor
,dummy
;
1602 // special case if page is 0xff, use current page
1604 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1609 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1610 line
=find_vga_entry(mode
);
1611 if(line
==0xFF)return;
1613 // Get the cursor pos for the page
1614 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1615 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1617 // Get the dimensions
1618 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1619 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1643 biosfn_write_teletype(' ',page
,attr
,flag
);
1644 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1645 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1651 if(vga_modes
[line
].class==TEXT
)
1653 // Compute the address
1654 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1657 write_byte(vga_modes
[line
].sstart
,address
,car
);
1660 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1664 // FIXME gfx mode not complete
1665 cheight
=vga_modes
[line
].cheight
;
1666 bpp
=vga_modes
[line
].pixbits
;
1667 if(vga_modes
[line
].memmodel
==PLANAR4
)
1669 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1671 else if(vga_modes
[line
].memmodel
==CGA
)
1673 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1686 // Do we need to wrap ?
1692 // Do we need to scroll ?
1694 {biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1698 // Set the cursor for the page
1699 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1700 biosfn_set_cursor_pos(page
,cursor
);
1703 // --------------------------------------------------------------------------------------------
1705 biosfn_get_video_mode
:
1707 mov ax
, #biosmem_seg
1710 mov bx
, #biosmem_current_page
1715 mov bx
, #biosmem_video_ctl
1718 mov bx
, #biosmem_current_mode
1721 mov bx
, #biosmem_nb_cols
1728 // --------------------------------------------------------------------------------------------
1729 static void biosfn_set_single_palette_reg (reg
,value
)
1730 Bit8u reg
;Bit8u value
;
1732 if(reg
<=ACTL_MAX_REG
)
1734 inb(VGAREG_ACTL_RESET
);
1735 outb(VGAREG_ACTL_ADDRESS
,reg
);
1736 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1737 outb(VGAREG_ACTL_ADDRESS
,0x20);
1741 // --------------------------------------------------------------------------------------------
1742 static void biosfn_set_overscan_border_color (value
)
1745 inb(VGAREG_ACTL_RESET
);
1746 outb(VGAREG_ACTL_ADDRESS
,0x11);
1747 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1748 outb(VGAREG_ACTL_ADDRESS
,0x20);
1751 // --------------------------------------------------------------------------------------------
1752 static void biosfn_set_all_palette_reg (seg
,offset
)
1753 Bit16u seg
;Bit16u offset
;
1757 inb(VGAREG_ACTL_RESET
);
1761 outb(VGAREG_ACTL_ADDRESS
,i
);
1762 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1767 outb(VGAREG_ACTL_ADDRESS
,0x11);
1768 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1769 outb(VGAREG_ACTL_ADDRESS
,0x20);
1772 // --------------------------------------------------------------------------------------------
1773 static void biosfn_toggle_intensity (state
)
1777 inb(VGAREG_ACTL_RESET
);
1779 outb(VGAREG_ACTL_ADDRESS
,0x10);
1780 value
=inb(VGAREG_ACTL_READ_DATA
);
1783 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1784 outb(VGAREG_ACTL_ADDRESS
,0x20);
1787 // --------------------------------------------------------------------------------------------
1788 static void biosfn_get_single_palette_reg (reg
,value
)
1789 Bit8u reg
;Bit16u
*value
;
1790 {Bit16u ss
=get_SS();
1792 if(reg
<=ACTL_MAX_REG
)
1794 inb(VGAREG_ACTL_RESET
);
1795 outb(VGAREG_ACTL_ADDRESS
,reg
);
1796 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1797 inb(VGAREG_ACTL_RESET
);
1798 outb(VGAREG_ACTL_ADDRESS
,0x20);
1802 // --------------------------------------------------------------------------------------------
1803 static void biosfn_read_overscan_border_color (value
)
1805 {Bit16u ss
=get_SS();
1807 inb(VGAREG_ACTL_RESET
);
1808 outb(VGAREG_ACTL_ADDRESS
,0x11);
1809 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1810 outb(VGAREG_ACTL_ADDRESS
,0x20);
1813 // --------------------------------------------------------------------------------------------
1814 static void biosfn_get_all_palette_reg (seg
,offset
) Bit16u seg
;Bit16u offset
;
1821 inb(VGAREG_ACTL_RESET
);
1822 outb(VGAREG_ACTL_ADDRESS
,i
);
1823 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1828 outb(VGAREG_ACTL_ADDRESS
,0x11);
1829 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1830 outb(VGAREG_ACTL_ADDRESS
,0x20);
1833 // --------------------------------------------------------------------------------------------
1834 static void biosfn_set_single_dac_reg (reg
,g
,b
,r
)
1835 Bit16u reg
;Bit8u g
;Bit8u b
;Bit8u r
;
1837 outb(VGAREG_DAC_WRITE_ADDRESS
,reg
);
1838 outb(VGAREG_DAC_DATA
,r
);
1839 outb(VGAREG_DAC_DATA
,g
);
1840 outb(VGAREG_DAC_DATA
,b
);
1843 // --------------------------------------------------------------------------------------------
1844 static void biosfn_set_all_dac_reg (start
,count
,seg
,offset
)
1845 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1847 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
1848 for(i
=0;i
<count
;i
++)
1849 {outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1850 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1851 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1855 // --------------------------------------------------------------------------------------------
1856 static void biosfn_select_video_dac_color_page (function
,page
)
1860 inb(VGAREG_ACTL_RESET
);
1861 outb(VGAREG_ACTL_ADDRESS
,0x10);
1863 value
=inb(VGAREG_ACTL_READ_DATA
);
1869 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1873 inb(VGAREG_ACTL_RESET
);
1874 outb(VGAREG_ACTL_ADDRESS
,0x14);
1876 outb(VGAREG_ACTL_WRITE_DATA
,page
&0x0f);
1878 outb(VGAREG_ACTL_WRITE_DATA
,(page
&0x03)<<2);
1880 outb(VGAREG_ACTL_ADDRESS
,0x20);
1883 // --------------------------------------------------------------------------------------------
1884 static void biosfn_read_single_dac_reg (reg
,tor
,togb
)
1885 Bit8u reg
;Bit16u
*tor
;Bit16u
*togb
;
1886 {Bit16u ss
=get_SS();
1889 outb(VGAREG_DAC_READ_ADDRESS
,reg
);
1890 r
=inb(VGAREG_DAC_DATA
);
1891 g
=inb(VGAREG_DAC_DATA
);
1892 b
=inb(VGAREG_DAC_DATA
);
1893 write_word(ss
,tor
,((Bit16u
)r
)<<8);
1894 write_word(ss
,togb
,(((Bit16u
)g
)<<8)+b
);
1897 // --------------------------------------------------------------------------------------------
1898 static void biosfn_read_all_dac_reg (start
,count
,seg
,offset
)
1899 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1901 outb(VGAREG_DAC_READ_ADDRESS
,start
);
1902 for(i
=0;i
<count
;i
++)
1903 {write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1904 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1905 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1909 // --------------------------------------------------------------------------------------------
1910 static void biosfn_set_pel_mask (mask
)
1913 outb(VGAREG_PEL_MASK
,mask
);
1916 // --------------------------------------------------------------------------------------------
1917 static void biosfn_read_pel_mask (mask
)
1919 {Bit16u ss
=get_SS();
1921 write_word(ss
,mask
,inb(VGAREG_PEL_MASK
));
1924 // --------------------------------------------------------------------------------------------
1925 static void biosfn_read_video_dac_state (state
) Bit16u
*state
;
1926 {Bit16u ss
=get_SS();
1929 inb(VGAREG_ACTL_RESET
);
1930 outb(VGAREG_ACTL_ADDRESS
,0x10);
1931 mcr
=(inb(VGAREG_ACTL_READ_DATA
)>>7)&0x01;
1932 inb(VGAREG_ACTL_RESET
);
1933 outb(VGAREG_ACTL_ADDRESS
,0x14);
1934 csr
=inb(VGAREG_ACTL_READ_DATA
)&0x0f;
1935 if(mcr
==0)(csr
>>2)&0x03;
1937 write_word(ss
,state
,(mcr
<<8)+csr
);
1938 outb(VGAREG_ACTL_ADDRESS
,0x20);
1941 // --------------------------------------------------------------------------------------------
1942 static void biosfn_perform_gray_scale_summing (start
,count
)
1943 Bit16u start
;Bit16u count
;
1948 inb(VGAREG_ACTL_RESET
);
1949 outb(VGAREG_ACTL_ADDRESS
,0x10);
1950 d
=(inb(VGAREG_ACTL_READ_DATA
)>>6)&0x01;
1952 // depth is 8 or 6 bits
1957 // We start overwriting at
1958 outb(VGAREG_DAC_READ_ADDRESS
,start
);
1959 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
1961 for( index
= 0; index
< count
; index
++ )
1963 // get 6-bit wide RGB data values
1964 r
=inb( VGAREG_DAC_DATA
);
1965 g
=inb( VGAREG_DAC_DATA
);
1966 b
=inb( VGAREG_DAC_DATA
);
1968 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
1969 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
1973 // write new intensity value
1974 outb( VGAREG_DAC_DATA
, i
&0xff );
1975 outb( VGAREG_DAC_DATA
, i
&0xff );
1976 outb( VGAREG_DAC_DATA
, i
&0xff );
1978 outb(VGAREG_ACTL_ADDRESS
,0x20);
1981 // --------------------------------------------------------------------------------------------
1982 static void get_font_access()
1984 outw( VGAREG_SEQU_ADDRESS
, 0x0100 );
1985 outw( VGAREG_SEQU_ADDRESS
, 0x0402 );
1986 outw( VGAREG_SEQU_ADDRESS
, 0x0704 );
1987 outw( VGAREG_SEQU_ADDRESS
, 0x0300 );
1988 outw( VGAREG_GRDC_ADDRESS
, 0x0204 );
1989 outw( VGAREG_GRDC_ADDRESS
, 0x0005 );
1990 outw( VGAREG_GRDC_ADDRESS
, 0x0406 );
1993 static void release_font_access()
1995 outw( VGAREG_SEQU_ADDRESS
, 0x0100 );
1996 outw( VGAREG_SEQU_ADDRESS
, 0x0302 );
1997 outw( VGAREG_SEQU_ADDRESS
, 0x0304 );
1998 outw( VGAREG_SEQU_ADDRESS
, 0x0300 );
1999 outw( VGAREG_GRDC_ADDRESS
, 0x0004 );
2000 outw( VGAREG_GRDC_ADDRESS
, 0x1005 );
2001 outw( VGAREG_GRDC_ADDRESS
, 0x0e06 );
2011 static void set_scan_lines(lines
) Bit8u lines
;
2013 Bit16u crtc_addr
,cols
,page
,vde
;
2014 Bit8u crtc_r9
,ovl
,rows
;
2016 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2017 outb(crtc_addr
, 0x09);
2018 crtc_r9
= inb(crtc_addr
+1);
2019 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2020 outb(crtc_addr
+1, crtc_r9
);
2023 biosfn_set_cursor_shape(0x06,0x07);
2027 biosfn_set_cursor_shape(lines
-4,lines
-3);
2029 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2030 outb(crtc_addr
, 0x12);
2031 vde
= inb(crtc_addr
+1);
2032 outb(crtc_addr
, 0x07);
2033 ovl
= inb(crtc_addr
+1);
2034 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2036 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2037 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2038 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2041 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
;
2043 Bit16u blockaddr
,dest
,i
,src
;
2046 blockaddr
= BL
<< 13;
2050 dest
= blockaddr
+ (DX
+ i
) * 32;
2051 memcpyb(0xA000, dest
, ES
, src
, BH
);
2053 release_font_access();
2060 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2062 Bit16u blockaddr
,dest
,i
,src
;
2065 blockaddr
= BL
<< 13;
2066 for(i
=0;i
<0x100;i
++)
2069 dest
= blockaddr
+ i
* 32;
2070 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2072 release_font_access();
2079 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2081 Bit16u blockaddr
,dest
,i
,src
;
2084 blockaddr
= BL
<< 13;
2085 for(i
=0;i
<0x100;i
++)
2088 dest
= blockaddr
+ i
* 32;
2089 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2091 release_font_access();
2098 static void biosfn_set_text_block_specifier (BL
) Bit8u BL
;
2100 outb( VGAREG_SEQU_ADDRESS
, 0x03 );
2101 outb( VGAREG_SEQU_DATA
, BL
);
2104 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2106 Bit16u blockaddr
,dest
,i
,src
;
2109 blockaddr
= BL
<< 13;
2110 for(i
=0;i
<0x100;i
++)
2113 dest
= blockaddr
+ i
* 32;
2114 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2116 release_font_access();
2123 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2129 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2135 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2141 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2147 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2153 // --------------------------------------------------------------------------------------------
2154 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2155 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2156 {Bit16u ss
=get_SS();
2160 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2161 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2164 write_word(ss
,ES
,read_word(0x00,0x43*4));
2165 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2168 write_word(ss
,ES
,0xC000);
2169 write_word(ss
,BP
,vgafont14
);
2172 write_word(ss
,ES
,0xC000);
2173 write_word(ss
,BP
,vgafont8
);
2176 write_word(ss
,ES
,0xC000);
2177 write_word(ss
,BP
,vgafont8
+128*8);
2180 write_word(ss
,ES
,0xC000);
2181 write_word(ss
,BP
,vgafont14alt
);
2184 write_word(ss
,ES
,0xC000);
2185 write_word(ss
,BP
,vgafont16
);
2188 write_word(ss
,ES
,0xC000);
2189 write_word(ss
,BP
,vgafont16alt
);
2193 printf("Get font info BH(%02x) was discarded\n",BH
);
2197 // Set byte/char of on screen font
2198 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2200 // Set Highest char row
2201 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2204 // --------------------------------------------------------------------------------------------
2205 static void biosfn_get_ega_info (BX
,CX
)
2206 Bit16u
*BX
;Bit16u
*CX
;
2207 {Bit16u ss
=get_SS();
2211 crtc
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2212 if(crtc
==VGAREG_MDA_CRTC_ADDRESS
)
2213 write_word(ss
,BX
,(1<<8)+0x0003);
2215 write_word(ss
,BX
,0x0003);
2217 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2218 write_word(ss
,CX
,(switches
&0x0f));
2221 // --------------------------------------------------------------------------------------------
2222 static void biosfn_alternate_prtsc()
2229 // --------------------------------------------------------------------------------------------
2230 static void biosfn_select_vert_res (res
)
2232 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2233 Bit8u modeset
,switches
;
2235 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2236 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2239 // set modeset ctl bit 7 and reset bit 4
2240 // set switches bit 3-0 to 0x08
2241 modeset
|=0x80;modeset
&=0xef;
2242 switches
&=0xf0;switches
|=0x08;
2245 // reset modeset ctl bit 7 and bit 4
2246 // set switches bit 3-0 to 0x09
2248 switches
&=0xf0;switches
|=0x09;
2251 // reset modeset ctl bit 7 and set bit 4
2252 // set switches bit 3-0 to 0x09
2253 modeset
|=0x10;modeset
&=0x7f;
2254 switches
&=0xf0;switches
|=0x09;
2258 printf("Select vert res (%02x) was discarded\n",res
);
2262 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2263 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,switches
);
2266 // --------------------------------------------------------------------------------------------
2267 static void biosfn_enable_default_palette_loading (disable
)
2272 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2275 if(disable
!=0x00)modeset
|=0x08;
2278 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2281 // --------------------------------------------------------------------------------------------
2282 static void biosfn_enable_video_addressing (disable
)
2287 misc
=inb(VGAREG_READ_MISC_OUTPUT
);
2289 if(disable
!=0x00) misc
&=0xfd;
2291 outb(VGAREG_WRITE_MISC_OUTPUT
,misc
);
2294 // --------------------------------------------------------------------------------------------
2295 static void biosfn_enable_grayscale_summing (disable
)
2300 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2302 // Bit 1 set if disable=0
2303 if(disable
==0x00)modeset
|=0x02;
2306 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2309 // --------------------------------------------------------------------------------------------
2310 static void biosfn_enable_cursor_emulation (disable
)
2315 videoctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
2317 // Bit 0 set if disable!=0
2318 if(disable
!=0x00)videoctl
|=0x01;
2319 else videoctl
&=0xfe;
2321 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,videoctl
);
2324 // --------------------------------------------------------------------------------------------
2325 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2331 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2338 // --------------------------------------------------------------------------------------------
2339 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2340 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2342 Bit16u newcurs
,oldcurs
,dummy
;
2345 // Read curs info for the page
2346 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2348 // if row=0xff special case : use current cursor position
2350 {col
=oldcurs
&0x00ff;
2351 row
=(oldcurs
&0xff00)>>8;
2354 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
2355 biosfn_set_cursor_pos(page
,newcurs
);
2359 car
=read_byte(seg
,offset
++);
2361 attr
=read_byte(seg
,offset
++);
2363 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
2366 // Set back curs pos
2368 biosfn_set_cursor_pos(page
,oldcurs
);
2371 // --------------------------------------------------------------------------------------------
2373 biosfn_read_display_code
:
2376 mov ax
, #biosmem_seg
2378 mov bx
, #biosmem_dcc_index
2387 // --------------------------------------------------------------------------------------------
2388 static void biosfn_set_display_code (BL
,BH
)
2391 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,BL
);
2394 printf("Alternate Display code (%02x) was discarded\n",BH
);
2398 // --------------------------------------------------------------------------------------------
2399 static void biosfn_read_state_info (BX
,ES
,DI
)
2400 Bit16u BX
;Bit16u ES
;Bit16u DI
;
2402 // Address of static functionality table
2403 write_word(ES
,DI
+0x00,&static_functionality
);
2404 write_word(ES
,DI
+0x02,0xC000);
2406 // Hard coded copy from BIOS area. Should it be cleaner ?
2407 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
2408 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
2410 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2411 write_byte(ES
,DI
+0x26,0);
2412 write_byte(ES
,DI
+0x27,16);
2413 write_byte(ES
,DI
+0x28,0);
2414 write_byte(ES
,DI
+0x29,8);
2415 write_byte(ES
,DI
+0x2a,2);
2416 write_byte(ES
,DI
+0x2b,0);
2417 write_byte(ES
,DI
+0x2c,0);
2418 write_byte(ES
,DI
+0x31,3);
2419 write_byte(ES
,DI
+0x32,0);
2421 memsetb(ES
,DI
+0x33,0,13);
2424 // --------------------------------------------------------------------------------------------
2425 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2431 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2437 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2444 // ============================================================================================
2448 // ============================================================================================
2450 // --------------------------------------------------------------------------------------------
2451 static Bit8u
find_vga_entry(mode
)
2455 for(i
=0;i
<=MODE_MAX
;i
++)
2456 if(vga_modes
[i
].svgamode
==mode
)
2463 /* =========================================================== */
2467 /* =========================================================== */
2469 // --------------------------------------------------------------------------------------------
2470 static void memsetb(seg
,offset
,value
,count
)
2485 mov cx
, 10[bp
] ; count
2488 mov ax
, 4[bp
] ; segment
2490 mov ax
, 6[bp
] ; offset
2492 mov al
, 8[bp
] ; value
2507 // --------------------------------------------------------------------------------------------
2508 static void memsetw(seg
,offset
,value
,count
)
2523 mov cx
, 10[bp
] ; count
2526 mov ax
, 4[bp
] ; segment
2528 mov ax
, 6[bp
] ; offset
2530 mov ax
, 8[bp
] ; value
2545 // --------------------------------------------------------------------------------------------
2546 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
2564 mov cx
, 12[bp
] ; count
2567 mov ax
, 4[bp
] ; dsegment
2569 mov ax
, 6[bp
] ; doffset
2571 mov ax
, 8[bp
] ; ssegment
2573 mov ax
, 10[bp
] ; soffset
2591 // --------------------------------------------------------------------------------------------
2592 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
2610 mov cx
, 12[bp
] ; count
2613 mov ax
, 4[bp
] ; dsegment
2615 mov ax
, 6[bp
] ; doffset
2617 mov ax
, 8[bp
] ; ssegment
2619 mov ax
, 10[bp
] ; soffset
2637 /* =========================================================== */
2639 * These functions where ripped from Kevin's rombios.c
2641 /* =========================================================== */
2643 // --------------------------------------------------------------------------------------------
2645 read_byte(seg
, offset
)
2655 mov ax
, 4[bp
] ; segment
2657 mov bx
, 6[bp
] ; offset
2659 ;; al
= return value (byte
)
2667 // --------------------------------------------------------------------------------------------
2669 read_word(seg
, offset
)
2679 mov ax
, 4[bp
] ; segment
2681 mov bx
, 6[bp
] ; offset
2683 ;; ax
= return value (word
)
2691 // --------------------------------------------------------------------------------------------
2693 write_byte(seg
, offset
, data
)
2705 mov ax
, 4[bp
] ; segment
2707 mov bx
, 6[bp
] ; offset
2708 mov al
, 8[bp
] ; data byte
2709 mov
[bx
], al
; write data byte
2718 // --------------------------------------------------------------------------------------------
2720 write_word(seg
, offset
, data
)
2732 mov ax
, 4[bp
] ; segment
2734 mov bx
, 6[bp
] ; offset
2735 mov ax
, 8[bp
] ; data word
2736 mov
[bx
], ax
; write data word
2745 // --------------------------------------------------------------------------------------------
2780 // --------------------------------------------------------------------------------------------
2802 // --------------------------------------------------------------------------------------------
2832 void unimplemented()
2834 printf("--> Unimplemented\n");
2839 printf("--> Unknown int10\n");
2843 // --------------------------------------------------------------------------------------------
2847 Bit8u c
, format_char
;
2849 unsigned format_width
, i
;
2851 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
2859 while (c
= read_byte(0xc000, s
)) {
2864 else if (in_format
) {
2865 if ( (c
>='0') && (c
<='9') ) {
2866 format_width
= (format_width
* 10) + (c
- '0');
2868 else if (c
== 'x') {
2869 arg_ptr
++; // increment to next arg
2870 arg
= read_word(arg_seg
, arg_ptr
);
2871 if (format_width
== 0)
2874 digit
= format_width
- 1;
2875 for (i
=0; i
<format_width
; i
++) {
2876 nibble
= (arg
>> (4 * digit
)) & 0x000f;
2878 outb(0x0500, nibble
+ '0');
2880 outb(0x0500, (nibble
- 10) + 'A');
2885 //else if (c == 'd') {
2900 // --------------------------------------------------------------------------------------------
2903 ;; DATA_SEG_DEFS_HERE
2907 .ascii
"vgabios ends here"
2911 ;; BLOCK_STRINGS_BEGIN