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_perform_gray_scale_summing();
96 static void biosfn_load_text_user_pat();
97 static void biosfn_load_text_8_14_pat();
98 static void biosfn_load_text_8_8_pat();
99 static void biosfn_set_text_block_specifier();
100 static void biosfn_load_text_8_16_pat();
101 static void biosfn_load_gfx_8_8_chars();
102 static void biosfn_load_gfx_user_chars();
103 static void biosfn_load_gfx_8_14_chars();
104 static void biosfn_load_gfx_8_8_dd_chars();
105 static void biosfn_load_gfx_8_16_chars();
106 static void biosfn_get_font_info();
107 static void biosfn_get_ega_info();
108 static void biosfn_alternate_prtsc();
109 static void biosfn_select_vert_res();
110 static void biosfn_enable_default_palette_loading();
111 static void biosfn_enable_video_addressing();
112 static void biosfn_enable_grayscale_summing();
113 static void biosfn_enable_cursor_emulation();
114 static void biosfn_switch_video_interface();
115 static void biosfn_enable_video_refresh_control();
116 static void biosfn_write_string();
117 static void biosfn_read_state_info();
118 static void biosfn_read_video_state_size();
119 static void biosfn_save_video_state();
120 static void biosfn_restore_video_state();
122 // This is for compiling with gcc2 and gcc3
123 #define ASM_START #asm
124 #define ASM_END #endasm
129 biosmem_initial_mode
= 0x10
130 biosmem_current_mode
= 0x49
131 biosmem_nb_cols
= 0x4a
132 biosmem_current_page
= 0x62
133 biosmem_current_msr
= 0x65
134 biosmem_char_height
= 0x85
135 biosmem_video_ctl
= 0x87
136 biosmem_switches
= 0x88
137 biosmem_modeset_ctl
= 0x89
138 biosmem_dcc_index
= 0x8a
140 vgareg_actl_address
= 0x03c0
141 vgareg_actl_read_data
= 0x03c1
142 vgareg_sequ_address
= 0x03c4
143 vgareg_pel_mask
= 0x03c6
144 vgareg_dac_read_address
= 0x03c7
145 vgareg_dac_write_address
= 0x03c8
146 vgareg_dac_data
= 0x03c9
147 vgareg_grdc_address
= 0x03ce
148 vgareg_actl_reset
= 0x03da
171 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
173 .byte
0x40 /* BIOS extension length in units of 512 bytes */
178 jmp vgabios_init_func
181 .ascii
"Plex86/Bochs VGABios"
185 // Info from Bart Oldeman
204 .ascii
"(C) 2003 the LGPL VGABios developers Team"
209 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
215 .ascii
"Please visit :"
217 ;;.ascii
" . http://www.plex86.org"
219 .ascii
" . http://bochs.sourceforge.net"
221 .ascii
" . http://www.nongnu.org/vgabios"
227 ;; ============================================================================================
231 ;; ============================================================================================
237 ;; init basic bios vars
241 ;; init vbe functions
246 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
248 ;; display splash screen
249 call _display_splash_screen
251 ;; init video mode
and clear the screen
260 call _vbe_display_info
271 vgabios_int10_handler
:
286 call biosfn_get_video_mode
306 ;; We have to set ds to access the right data segment
319 #include "vgatables.h"
320 #include "vgafonts.h"
323 * Boot time harware inits
327 ;; switch to color mode
and enable CPU access
480 lines
332 ;; more than
64k
3C4
/04
340 mov bx
, #msg_vga_init
348 .ascii
"VGABios $Id$"
352 // --------------------------------------------------------------------------------------------
354 * Boot time bios area inits
362 ;; init detected hardware BIOS Area
363 mov bx
, #biosmem_initial_mode
368 ;; Just
for the first int10 find its children
370 ;; the
default char height
371 mov bx
, #biosmem_char_height
376 mov bx
, #biosmem_video_ctl
380 ;; Set the basic screen we have
381 mov bx
, #biosmem_switches
385 ;; Set the basic modeset options
386 mov bx
, #biosmem_modeset_ctl
390 ;; Set the
default MSR
391 mov bx
, #biosmem_current_msr
399 // --------------------------------------------------------------------------------------------
401 * Boot time Splash screen
403 static void display_splash_screen()
407 // --------------------------------------------------------------------------------------------
412 static void display_info()
419 mov si
,#vgabios_version
422 ;;mov si
,#vgabios_copyright
423 ;;call _display_string
425 ;;call _display_string
427 mov si
,#vgabios_license
429 mov si
,#vgabios_website
434 static void display_string()
436 // Get length of string
463 // --------------------------------------------------------------------------------------------
465 static void int10_debugmsg(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
466 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
468 // 0E is write char...
470 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
474 // --------------------------------------------------------------------------------------------
476 * int10 main dispatcher
478 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
479 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
486 biosfn_set_video_mode(GET_AL());
487 switch(GET_AL()&0x7F)
505 biosfn_set_cursor_shape(GET_CH(),GET_CL());
508 biosfn_set_cursor_pos(GET_BH(),DX
);
511 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
514 // Read light pen pos (unimplemented)
524 biosfn_set_active_page(GET_AL());
527 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
530 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
533 biosfn_read_char_attr(GET_BH(),&AX
);
536 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
539 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
543 biosfn_set_border_color(GET_BL());
545 biosfn_set_palette(GET_BL());
548 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
551 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
554 // Ralf Brown Interrupt list is WRONG on bh(page)
555 // We do output only on the current page !
556 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
559 // All other functions of group AH=0x10 rewritten in assembler
560 biosfn_perform_gray_scale_summing(BX
,CX
);
567 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
571 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
575 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
578 biosfn_set_text_block_specifier(GET_BL());
582 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
585 biosfn_load_gfx_8_8_chars(ES
,BP
);
588 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
591 biosfn_load_gfx_8_14_chars(GET_BL());
594 biosfn_load_gfx_8_8_dd_chars(GET_BL());
597 biosfn_load_gfx_8_16_chars(GET_BL());
600 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
613 biosfn_get_ega_info(&BX
,&CX
);
616 biosfn_alternate_prtsc();
619 biosfn_select_vert_res(GET_AL());
623 biosfn_enable_default_palette_loading(GET_AL());
627 biosfn_enable_video_addressing(GET_AL());
631 biosfn_enable_grayscale_summing(GET_AL());
635 biosfn_enable_cursor_emulation(GET_AL());
639 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
643 biosfn_enable_video_refresh_control(GET_AL());
653 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
656 biosfn_read_state_info(BX
,ES
,DI
);
663 biosfn_read_video_state_size(CX
,&BX
);
666 biosfn_save_video_state(CX
,ES
,BX
);
669 biosfn_restore_video_state(CX
,ES
,BX
);
681 if (vbe_has_vbe_display()) {
685 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
688 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
691 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
694 vbe_biosfn_return_current_mode(&AX
,&BX
);
705 vbe_biosfn_display_window_control(&AX
,BX
,&DX
);
708 vbe_biosfn_set_get_logical_scan_line_length(&AX
,&BX
,&CX
,&DX
);
711 vbe_biosfn_set_get_display_start(&AX
,BX
,CX
,DX
);
759 // ============================================================================================
763 // ============================================================================================
765 static void biosfn_set_video_mode(mode
) Bit8u mode
;
766 {// mode: Bit 7 is 1 if no clear screen
768 // Should we clear the screen ?
769 Bit8u noclearmem
=mode
&0x80;
770 Bit8u line
,mmask
,*palette
;
771 Bit16u i
,twidth
,theight
,cheight
;
772 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
776 if (vbe_has_vbe_display()) {
777 dispi_set_enable(VBE_DISPI_DISABLED
);
784 // find the entry in the video modes
785 line
=find_vga_entry(mode
);
788 printf("mode search %02x found line %02x\n",mode
,line
);
794 twidth
=vga_modes
[line
].twidth
;
795 theight
=vga_modes
[line
].theight
;
796 cheight
=vga_modes
[line
].cheight
;
798 // Read the bios vga control
799 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
801 // Read the bios vga switches
802 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
804 // Read the bios mode set control
805 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
807 // Then we know the number of lines
810 // if palette loading (bit 3 of modeset ctl = 0)
811 if((modeset_ctl
&0x08)==0)
813 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
815 // Set the whole dac always, from 0
816 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
818 // From which palette
819 switch(vga_modes
[line
].dacmodel
)
833 // Always 256*3 values
834 for(i
=0;i
<0x0100;i
++)
835 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
836 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
837 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
838 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
841 {outb(VGAREG_DAC_DATA
,0);
842 outb(VGAREG_DAC_DATA
,0);
843 outb(VGAREG_DAC_DATA
,0);
846 if((modeset_ctl
&0x02)==0x02)
848 biosfn_perform_gray_scale_summing(0x00, 0x100);
852 // Reset Attribute Ctl flip-flop
853 inb(VGAREG_ACTL_RESET
);
856 for(i
=0;i
<=ACTL_MAX_REG
;i
++)
857 {outb(VGAREG_ACTL_ADDRESS
,i
);
858 outb(VGAREG_ACTL_WRITE_DATA
,actl_regs
[vga_modes
[line
].actlmodel
][i
]);
862 for(i
=0;i
<=SEQU_MAX_REG
;i
++)
863 {outb(VGAREG_SEQU_ADDRESS
,i
);
864 outb(VGAREG_SEQU_DATA
,sequ_regs
[vga_modes
[line
].sequmodel
][i
]);
868 for(i
=0;i
<=GRDC_MAX_REG
;i
++)
869 {outb(VGAREG_GRDC_ADDRESS
,i
);
870 outb(VGAREG_GRDC_DATA
,grdc_regs
[vga_modes
[line
].grdcmodel
][i
]);
873 // Set CRTC address VGA or MDA
874 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
877 for(i
=0;i
<=CRTC_MAX_REG
;i
++)
879 outb(crtc_addr
+1,crtc_regs
[vga_modes
[line
].crtcmodel
][i
]);
882 // Set the misc register
883 outb(VGAREG_WRITE_MISC_OUTPUT
,vga_modes
[line
].miscreg
);
886 outb(VGAREG_ACTL_ADDRESS
,0x20);
887 inb(VGAREG_ACTL_RESET
);
891 if(vga_modes
[line
].class==TEXT
)
893 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
899 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
903 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
904 mmask
= inb( VGAREG_SEQU_DATA
);
905 outb( VGAREG_SEQU_DATA
, 0x0f ); // all planes
906 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x8000); // 64k
907 outb( VGAREG_SEQU_DATA
, mmask
);
913 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
,mode
);
914 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
,twidth
);
915 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
,vga_modes
[line
].slength
);
916 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
917 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theight
-1);
918 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,cheight
);
919 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,(0x60|noclearmem
));
920 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
921 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)&0x7f);
923 // FIXME We nearly have the good tables. to be reworked
924 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,0x08); // 8 is VGA should be ok for now
925 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
,0x00);
926 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2,0x00);
929 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x00); // Unavailable on vanilla vga, but...
930 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAL
,0x00); // Unavailable on vanilla vga, but...
933 if(vga_modes
[line
].class==TEXT
)
935 biosfn_set_cursor_shape(0x06,0x07);
938 // Set cursor pos for page 0..7
940 biosfn_set_cursor_pos(i
,0x0000);
943 biosfn_set_active_page(0x00);
945 // Write the fonts in memory
946 if(vga_modes
[line
].class==TEXT
)
949 ;; copy
and activate
8x16 font
959 // Set the ints 0x1F and 0x43
961 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
967 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
972 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
977 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
983 // --------------------------------------------------------------------------------------------
984 static void biosfn_set_cursor_shape (CH
,CL
)
986 {Bit16u cheight
,curs
,crtc_addr
;
992 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
994 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
995 if((cheight
>8) && (CL
<8) && (CH
<0x20))
999 CH
= ((CH
+1) * cheight
/ 8) -1;
1003 CH
= ((CL
+1) * cheight
/ 8) - 2;
1005 CL
= ((CL
+1) * cheight
/ 8) - 1;
1008 // CTRC regs 0x0a and 0x0b
1009 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1010 outb(crtc_addr
,0x0a);
1011 outb(crtc_addr
+1,CH
);
1012 outb(crtc_addr
,0x0b);
1013 outb(crtc_addr
+1,CL
);
1016 // --------------------------------------------------------------------------------------------
1017 static void biosfn_set_cursor_pos (page
, cursor
)
1018 Bit8u page
;Bit16u cursor
;
1020 Bit8u xcurs
,ycurs
,current
;
1021 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1023 // Should not happen...
1027 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1029 // Set the hardware cursor
1030 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1033 // Get the dimensions
1034 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1035 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1037 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1039 // Calculate the address knowing nbcols nbrows and page num
1040 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1042 // CRTC regs 0x0e and 0x0f
1043 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1044 outb(crtc_addr
,0x0e);
1045 outb(crtc_addr
+1,(address
&0xff00)>>8);
1046 outb(crtc_addr
,0x0f);
1047 outb(crtc_addr
+1,address
&0x00ff);
1051 // --------------------------------------------------------------------------------------------
1052 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1053 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1058 write_word(ss
, shape
, 0);
1059 write_word(ss
, pos
, 0);
1062 // FIXME should handle VGA 14/16 lines
1063 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1064 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1067 // --------------------------------------------------------------------------------------------
1068 static void biosfn_set_active_page (page
)
1071 Bit16u cursor
,dummy
,crtc_addr
;
1072 Bit16u nbcols
,nbrows
,address
;
1078 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1079 line
=find_vga_entry(mode
);
1080 if(line
==0xFF)return;
1082 // Get pos curs pos for the right page
1083 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1085 if(vga_modes
[line
].class==TEXT
)
1087 // Get the dimensions
1088 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1089 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1091 // Calculate the address knowing nbcols nbrows and page num
1092 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1093 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1096 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1100 address
= page
*vga_modes
[line
].slength
;
1103 // CRTC regs 0x0c and 0x0d
1104 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1105 outb(crtc_addr
,0x0c);
1106 outb(crtc_addr
+1,(address
&0xff00)>>8);
1107 outb(crtc_addr
,0x0d);
1108 outb(crtc_addr
+1,address
&0x00ff);
1110 // And change the BIOS page
1111 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1114 printf("Set active page %02x address %04x\n",page
,address
);
1117 // Display the cursor, now the page is active
1118 biosfn_set_cursor_pos(page
,cursor
);
1121 // --------------------------------------------------------------------------------------------
1122 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1123 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1125 // page == 0xFF if current
1128 Bit16u nbcols
,nbrows
,i
;
1135 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1136 line
=find_vga_entry(mode
);
1137 if(line
==0xFF)return;
1139 // Get the dimensions
1140 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1141 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1143 // Get the current page
1145 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1147 if(vga_modes
[line
].class==TEXT
)
1149 // Compute the address
1150 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1152 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1155 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1156 if(clr
>=nbcols
)clr
=nbcols
-1;
1157 if(nblines
>nbrows
)nblines
=0;
1159 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1161 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1166 {for(i
=rul
;i
<=rlr
;i
++)
1168 if((i
+nblines
>rlr
)||(nblines
==0))
1169 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1171 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1175 {for(i
=rlr
;i
>=rul
;i
--)
1177 if((i
<rul
+nblines
)||(nblines
==0))
1178 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1180 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1189 printf("Scroll in graphics mode ");
1195 // --------------------------------------------------------------------------------------------
1196 static void biosfn_read_char_attr (page
,car
)
1197 Bit8u page
;Bit16u
*car
;
1198 {Bit16u ss
=get_SS();
1199 Bit8u xcurs
,ycurs
,mode
,line
;
1200 Bit16u nbcols
,nbrows
,address
;
1201 Bit16u cursor
,dummy
;
1204 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1205 line
=find_vga_entry(mode
);
1206 if(line
==0xFF)return;
1208 // Get the cursor pos for the page
1209 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1210 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1212 // Get the dimensions
1213 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1214 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1216 if(vga_modes
[line
].class==TEXT
)
1218 // Compute the address
1219 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1221 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1232 // --------------------------------------------------------------------------------------------
1233 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1234 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1238 Bit16u addr
,dest
,src
;
1250 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1251 src
= car
* cheight
;
1252 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
1253 mmask
= inb( VGAREG_SEQU_DATA
);
1254 for(i
=0;i
<cheight
;i
++)
1257 outb( VGAREG_SEQU_DATA
, 0x0f );
1258 write_byte(0xa000,dest
,0x00);
1259 outb( VGAREG_SEQU_DATA
, attr
& 0x0f );
1260 write_byte(0xa000,dest
,fdata
[src
+i
]);
1262 outb( VGAREG_SEQU_DATA
, mmask
);
1265 // --------------------------------------------------------------------------------------------
1266 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1267 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1269 Bit8u i
,j
,mask
,data
;
1271 Bit16u addr
,dest
,src
;
1274 addr
=(xcurs
*bpp
)+ycurs
*320;
1278 dest
=addr
+(i
>>1)*80;
1279 if (i
& 1) dest
+= 0x2000;
1285 data
= read_byte(0xb800,dest
);
1293 if (fdata
[src
+i
] & mask
)
1297 data
^= (attr
& 0x01) << (7-j
);
1301 data
|= (attr
& 0x01) << (7-j
);
1306 write_byte(0xb800,dest
,data
);
1314 data
= read_byte(0xb800,dest
);
1322 if (fdata
[src
+i
] & mask
)
1326 data
^= (attr
& 0x03) << ((3-j
)*2);
1330 data
|= (attr
& 0x03) << ((3-j
)*2);
1335 write_byte(0xb800,dest
,data
);
1342 // --------------------------------------------------------------------------------------------
1343 static void write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
)
1344 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;
1346 Bit8u i
,j
,mask
,data
;
1348 Bit16u addr
,dest
,src
;
1351 addr
=xcurs
*8+ycurs
*nbcols
*64;
1355 dest
=addr
+i
*nbcols
*8;
1360 if (fdata
[src
+i
] & mask
)
1364 write_byte(0xa000,dest
+j
,data
);
1370 // --------------------------------------------------------------------------------------------
1371 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1372 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1374 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1375 Bit16u nbcols
,nbrows
,address
;
1376 Bit16u cursor
,dummy
;
1379 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1380 line
=find_vga_entry(mode
);
1381 if(line
==0xFF)return;
1383 // Get the cursor pos for the page
1384 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1385 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1387 // Get the dimensions
1388 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1389 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1391 if(vga_modes
[line
].class==TEXT
)
1393 // Compute the address
1394 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1396 dummy
=((Bit16u
)attr
<<8)+car
;
1397 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1401 // FIXME gfx mode not complete
1402 cheight
=vga_modes
[line
].cheight
;
1403 bpp
=vga_modes
[line
].pixbits
;
1404 while((count
-->0) && (xcurs
<nbcols
))
1406 if(vga_modes
[line
].memmodel
==PLANAR4
)
1408 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1410 else if(vga_modes
[line
].memmodel
==CGA
)
1412 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1414 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1416 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1429 // --------------------------------------------------------------------------------------------
1430 static void biosfn_write_char_only (car
,page
,attr
,count
)
1431 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1433 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1434 Bit16u nbcols
,nbrows
,address
;
1435 Bit16u cursor
,dummy
;
1438 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1439 line
=find_vga_entry(mode
);
1440 if(line
==0xFF)return;
1442 // Get the cursor pos for the page
1443 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1444 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1446 // Get the dimensions
1447 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1448 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1450 if(vga_modes
[line
].class==TEXT
)
1452 // Compute the address
1453 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1456 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1462 // FIXME gfx mode not complete
1463 cheight
=vga_modes
[line
].cheight
;
1464 bpp
=vga_modes
[line
].pixbits
;
1465 while((count
-->0) && (xcurs
<nbcols
))
1467 if(vga_modes
[line
].memmodel
==PLANAR4
)
1469 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1471 else if(vga_modes
[line
].memmodel
==CGA
)
1473 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1475 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1477 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1490 // --------------------------------------------------------------------------------------------
1491 static void biosfn_set_border_color (BL
) Bit8u BL
;
1492 // FIXME anybody using this function ?
1499 // --------------------------------------------------------------------------------------------
1500 static void biosfn_set_palette (BL
) Bit8u BL
;
1501 // FIXME anybody using this function ?
1508 // --------------------------------------------------------------------------------------------
1509 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1511 Bit8u mode
,line
,mask
,attr
;
1515 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1516 line
=find_vga_entry(mode
);
1517 if(line
==0xFF)return;
1518 if(vga_modes
[line
].class==TEXT
)return;
1520 if(vga_modes
[line
].memmodel
==CGA
)
1522 if(vga_modes
[line
].pixbits
==2)
1524 addr
=(CX
>>2)+(DX
>>1)*80;
1528 addr
=(CX
>>3)+(DX
>>1)*80;
1530 if (DX
& 1) addr
+= 0x2000;
1531 data
= read_byte(0xb800,addr
);
1532 if(vga_modes
[line
].pixbits
==2)
1534 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1535 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1539 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1540 mask
= 0x01 << (7 - (CX
& 0x07));
1551 write_byte(0xb800,addr
,data
);
1553 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1555 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1556 write_byte(0xa000,addr
,AL
);
1566 // --------------------------------------------------------------------------------------------
1567 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1569 Bit8u mode
,line
,attr
;
1574 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1575 line
=find_vga_entry(mode
);
1576 if(line
==0xFF)return;
1577 if(vga_modes
[line
].class==TEXT
)return;
1579 if(vga_modes
[line
].memmodel
==CGA
)
1581 addr
=(CX
>>2)+(DX
>>1)*80;
1582 if (DX
& 1) addr
+= 0x2000;
1583 data
= read_byte(0xb800,addr
);
1584 if(vga_modes
[line
].pixbits
==2)
1586 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1590 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1593 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1595 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1596 attr
=read_byte(0xa000,addr
);
1605 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1608 // --------------------------------------------------------------------------------------------
1609 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1610 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1611 {// flag = WITH_ATTR / NO_ATTR
1613 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1614 Bit16u nbcols
,nbrows
,address
;
1615 Bit16u cursor
,dummy
;
1617 // special case if page is 0xff, use current page
1619 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1624 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1625 line
=find_vga_entry(mode
);
1626 if(line
==0xFF)return;
1628 // Get the cursor pos for the page
1629 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1630 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1632 // Get the dimensions
1633 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1634 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1658 biosfn_write_teletype(' ',page
,attr
,flag
);
1659 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1660 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1666 if(vga_modes
[line
].class==TEXT
)
1668 // Compute the address
1669 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1672 write_byte(vga_modes
[line
].sstart
,address
,car
);
1675 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1679 // FIXME gfx mode not complete
1680 cheight
=vga_modes
[line
].cheight
;
1681 bpp
=vga_modes
[line
].pixbits
;
1682 if(vga_modes
[line
].memmodel
==PLANAR4
)
1684 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1686 else if(vga_modes
[line
].memmodel
==CGA
)
1688 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1690 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1692 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1705 // Do we need to wrap ?
1711 // Do we need to scroll ?
1713 {biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1717 // Set the cursor for the page
1718 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1719 biosfn_set_cursor_pos(page
,cursor
);
1722 // --------------------------------------------------------------------------------------------
1724 biosfn_get_video_mode
:
1726 mov ax
, #biosmem_seg
1729 mov bx
, #biosmem_current_page
1734 mov bx
, #biosmem_video_ctl
1737 mov bx
, #biosmem_current_mode
1740 mov bx
, #biosmem_nb_cols
1747 // --------------------------------------------------------------------------------------------
1752 jmp biosfn_set_single_palette_reg
1756 jmp biosfn_set_overscan_border_color
1760 jmp biosfn_set_all_palette_reg
1764 jmp biosfn_toggle_intensity
1768 jmp biosfn_get_single_palette_reg
1772 jmp biosfn_read_overscan_border_color
1776 jmp biosfn_get_all_palette_reg
1780 jmp biosfn_set_single_dac_reg
1784 jmp biosfn_set_all_dac_reg
1788 jmp biosfn_select_video_dac_color_page
1792 jmp biosfn_read_single_dac_reg
1796 jmp biosfn_read_all_dac_reg
1800 jmp biosfn_set_pel_mask
1804 jmp biosfn_read_pel_mask
1807 jne int10_group_10_unknown
1808 jmp biosfn_read_video_dac_state
1809 int10_group_10_unknown
:
1815 biosfn_set_single_palette_reg
:
1820 mov dx
, #vgareg_actl_reset
1822 mov dx
, #vgareg_actl_address
1835 // --------------------------------------------------------------------------------------------
1837 biosfn_set_overscan_border_color
:
1840 call biosfn_set_single_palette_reg
1845 // --------------------------------------------------------------------------------------------
1847 biosfn_set_all_palette_reg
:
1853 mov dx
, #vgareg_actl_reset
1856 mov dx
, #vgareg_actl_address
1866 jne set_palette_loop
1881 // --------------------------------------------------------------------------------------------
1883 biosfn_toggle_intensity
:
1887 mov dx
, #vgareg_actl_reset
1889 mov dx
, #vgareg_actl_address
1892 mov dx
, #vgareg_actl_read_data
1898 mov dx
, #vgareg_actl_address
1908 // --------------------------------------------------------------------------------------------
1910 biosfn_get_single_palette_reg
:
1915 mov dx
, #vgareg_actl_reset
1917 mov dx
, #vgareg_actl_address
1920 mov dx
, #vgareg_actl_read_data
1923 mov dx
, #vgareg_actl_reset
1925 mov dx
, #vgareg_actl_address
1934 // --------------------------------------------------------------------------------------------
1936 biosfn_read_overscan_border_color
:
1940 call biosfn_get_single_palette_reg
1948 // --------------------------------------------------------------------------------------------
1950 biosfn_get_all_palette_reg
:
1958 mov dx
, #vgareg_actl_reset
1960 mov dx
, #vgareg_actl_address
1963 mov dx
, #vgareg_actl_read_data
1970 jne get_palette_loop
1971 mov dx
, #vgareg_actl_reset
1973 mov dx
, #vgareg_actl_address
1976 mov dx
, #vgareg_actl_read_data
1980 mov dx
, #vgareg_actl_reset
1982 mov dx
, #vgareg_actl_address
1992 // --------------------------------------------------------------------------------------------
1994 biosfn_set_single_dac_reg
:
1997 mov dx
, #vgareg_dac_write_address
2000 mov dx
, #vgareg_dac_data
2014 // --------------------------------------------------------------------------------------------
2016 biosfn_set_all_dac_reg
:
2021 mov dx
, #vgareg_dac_write_address
2027 mov dx
, #vgareg_dac_data
2050 // --------------------------------------------------------------------------------------------
2052 biosfn_select_video_dac_color_page
:
2056 mov dx
, #vgareg_actl_reset
2058 mov dx
, #vgareg_actl_address
2061 mov dx
, #vgareg_actl_read_data
2068 mov dx
, #vgareg_actl_address
2073 mov dx
, #vgareg_actl_reset
2075 mov dx
, #vgareg_actl_address
2095 // --------------------------------------------------------------------------------------------
2097 biosfn_read_single_dac_reg
:
2100 mov dx
, #vgareg_dac_read_address
2105 mov dx
, #vgareg_dac_data
2118 // --------------------------------------------------------------------------------------------
2120 biosfn_read_all_dac_reg
:
2125 mov dx
, #vgareg_dac_read_address
2131 mov dx
, #vgareg_dac_data
2154 // --------------------------------------------------------------------------------------------
2156 biosfn_set_pel_mask
:
2159 mov dx
, #vgareg_pel_mask
2167 // --------------------------------------------------------------------------------------------
2169 biosfn_read_pel_mask
:
2172 mov dx
, #vgareg_pel_mask
2180 // --------------------------------------------------------------------------------------------
2182 biosfn_read_video_dac_state
:
2185 mov dx
, #vgareg_actl_reset
2187 mov dx
, #vgareg_actl_address
2190 mov dx
, #vgareg_actl_read_data
2194 mov dx
, #vgareg_actl_reset
2196 mov dx
, #vgareg_actl_address
2199 mov dx
, #vgareg_actl_read_data
2207 mov dx
, #vgareg_actl_reset
2209 mov dx
, #vgareg_actl_address
2217 // --------------------------------------------------------------------------------------------
2218 static void biosfn_perform_gray_scale_summing (start
,count
)
2219 Bit16u start
;Bit16u count
;
2224 inb(VGAREG_ACTL_RESET
);
2225 outb(VGAREG_ACTL_ADDRESS
,0x00);
2227 for( index
= 0; index
< count
; index
++ )
2229 // set read address and switch to read mode
2230 outb(VGAREG_DAC_READ_ADDRESS
,start
);
2231 // get 6-bit wide RGB data values
2232 r
=inb( VGAREG_DAC_DATA
);
2233 g
=inb( VGAREG_DAC_DATA
);
2234 b
=inb( VGAREG_DAC_DATA
);
2236 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2237 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
2241 // set write address and switch to write mode
2242 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
2243 // write new intensity value
2244 outb( VGAREG_DAC_DATA
, i
&0xff );
2245 outb( VGAREG_DAC_DATA
, i
&0xff );
2246 outb( VGAREG_DAC_DATA
, i
&0xff );
2249 inb(VGAREG_ACTL_RESET
);
2250 outb(VGAREG_ACTL_ADDRESS
,0x20);
2253 // --------------------------------------------------------------------------------------------
2254 static void get_font_access()
2257 mov dx
, #vgareg_sequ_address
2266 mov dx
, #vgareg_grdc_address
2276 static void release_font_access()
2279 mov dx
, #vgareg_sequ_address
2288 mov dx
, #vgareg_grdc_address
2305 static void set_scan_lines(lines
) Bit8u lines
;
2307 Bit16u crtc_addr
,cols
,page
,vde
;
2308 Bit8u crtc_r9
,ovl
,rows
;
2310 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2311 outb(crtc_addr
, 0x09);
2312 crtc_r9
= inb(crtc_addr
+1);
2313 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2314 outb(crtc_addr
+1, crtc_r9
);
2317 biosfn_set_cursor_shape(0x06,0x07);
2321 biosfn_set_cursor_shape(lines
-4,lines
-3);
2323 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2324 outb(crtc_addr
, 0x12);
2325 vde
= inb(crtc_addr
+1);
2326 outb(crtc_addr
, 0x07);
2327 ovl
= inb(crtc_addr
+1);
2328 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2330 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2331 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2332 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2335 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
;
2337 Bit16u blockaddr
,dest
,i
,src
;
2340 blockaddr
= BL
<< 13;
2344 dest
= blockaddr
+ (DX
+ i
) * 32;
2345 memcpyb(0xA000, dest
, ES
, src
, BH
);
2347 release_font_access();
2354 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2356 Bit16u blockaddr
,dest
,i
,src
;
2359 blockaddr
= BL
<< 13;
2360 for(i
=0;i
<0x100;i
++)
2363 dest
= blockaddr
+ i
* 32;
2364 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2366 release_font_access();
2373 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2375 Bit16u blockaddr
,dest
,i
,src
;
2378 blockaddr
= BL
<< 13;
2379 for(i
=0;i
<0x100;i
++)
2382 dest
= blockaddr
+ i
* 32;
2383 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2385 release_font_access();
2392 static void biosfn_set_text_block_specifier (BL
) Bit8u BL
;
2394 outb( VGAREG_SEQU_ADDRESS
, 0x03 );
2395 outb( VGAREG_SEQU_DATA
, BL
);
2398 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2400 Bit16u blockaddr
,dest
,i
,src
;
2403 blockaddr
= BL
<< 13;
2404 for(i
=0;i
<0x100;i
++)
2407 dest
= blockaddr
+ i
* 32;
2408 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2410 release_font_access();
2417 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2423 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2429 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2435 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2441 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2447 // --------------------------------------------------------------------------------------------
2448 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2449 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2450 {Bit16u ss
=get_SS();
2454 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2455 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2458 write_word(ss
,ES
,read_word(0x00,0x43*4));
2459 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2462 write_word(ss
,ES
,0xC000);
2463 write_word(ss
,BP
,vgafont14
);
2466 write_word(ss
,ES
,0xC000);
2467 write_word(ss
,BP
,vgafont8
);
2470 write_word(ss
,ES
,0xC000);
2471 write_word(ss
,BP
,vgafont8
+128*8);
2474 write_word(ss
,ES
,0xC000);
2475 write_word(ss
,BP
,vgafont14alt
);
2478 write_word(ss
,ES
,0xC000);
2479 write_word(ss
,BP
,vgafont16
);
2482 write_word(ss
,ES
,0xC000);
2483 write_word(ss
,BP
,vgafont16alt
);
2487 printf("Get font info BH(%02x) was discarded\n",BH
);
2491 // Set byte/char of on screen font
2492 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2494 // Set Highest char row
2495 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2498 // --------------------------------------------------------------------------------------------
2499 static void biosfn_get_ega_info (BX
,CX
)
2500 Bit16u
*BX
;Bit16u
*CX
;
2501 {Bit16u ss
=get_SS();
2505 crtc
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2506 if(crtc
==VGAREG_MDA_CRTC_ADDRESS
)
2507 write_word(ss
,BX
,(1<<8)+0x0003);
2509 write_word(ss
,BX
,0x0003);
2511 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2512 write_word(ss
,CX
,(switches
&0x0f));
2515 // --------------------------------------------------------------------------------------------
2516 static void biosfn_alternate_prtsc()
2523 // --------------------------------------------------------------------------------------------
2524 static void biosfn_select_vert_res (res
)
2526 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2527 Bit8u modeset
,switches
;
2529 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2530 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2533 // set modeset ctl bit 7 and reset bit 4
2534 // set switches bit 3-0 to 0x08
2535 modeset
|=0x80;modeset
&=0xef;
2536 switches
&=0xf0;switches
|=0x08;
2539 // reset modeset ctl bit 7 and bit 4
2540 // set switches bit 3-0 to 0x09
2542 switches
&=0xf0;switches
|=0x09;
2545 // reset modeset ctl bit 7 and set bit 4
2546 // set switches bit 3-0 to 0x09
2547 modeset
|=0x10;modeset
&=0x7f;
2548 switches
&=0xf0;switches
|=0x09;
2552 printf("Select vert res (%02x) was discarded\n",res
);
2556 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2557 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,switches
);
2560 // --------------------------------------------------------------------------------------------
2561 static void biosfn_enable_default_palette_loading (disable
)
2566 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2569 if(disable
!=0x00)modeset
|=0x08;
2572 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2575 // --------------------------------------------------------------------------------------------
2576 static void biosfn_enable_video_addressing (disable
)
2581 misc
=inb(VGAREG_READ_MISC_OUTPUT
);
2583 if(disable
!=0x00) misc
&=0xfd;
2585 outb(VGAREG_WRITE_MISC_OUTPUT
,misc
);
2588 // --------------------------------------------------------------------------------------------
2589 static void biosfn_enable_grayscale_summing (disable
)
2594 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2596 // Bit 1 set if disable=0
2597 if(disable
==0x00)modeset
|=0x02;
2600 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2603 // --------------------------------------------------------------------------------------------
2604 static void biosfn_enable_cursor_emulation (disable
)
2609 videoctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
2611 // Bit 0 set if disable!=0
2612 if(disable
!=0x00)videoctl
|=0x01;
2613 else videoctl
&=0xfe;
2615 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,videoctl
);
2618 // --------------------------------------------------------------------------------------------
2619 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2625 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2632 // --------------------------------------------------------------------------------------------
2633 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2634 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2636 Bit16u newcurs
,oldcurs
,dummy
;
2639 // Read curs info for the page
2640 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2642 // if row=0xff special case : use current cursor position
2644 {col
=oldcurs
&0x00ff;
2645 row
=(oldcurs
&0xff00)>>8;
2648 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
2649 biosfn_set_cursor_pos(page
,newcurs
);
2653 car
=read_byte(seg
,offset
++);
2655 attr
=read_byte(seg
,offset
++);
2657 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
2660 // Set back curs pos
2662 biosfn_set_cursor_pos(page
,oldcurs
);
2665 // --------------------------------------------------------------------------------------------
2669 je biosfn_read_display_code
2671 je biosfn_set_display_code
2676 biosfn_read_display_code
:
2679 mov ax
, #biosmem_seg
2681 mov bx
, #biosmem_dcc_index
2689 biosfn_set_display_code
:
2693 mov ax
, #biosmem_seg
2696 mov bx
, #biosmem_dcc_index
2702 mov bx
, #msg_alt_dcc
2715 .ascii
"Alternate Display code (%02x) was discarded"
2716 .byte
0x0d,0x0a,0x00
2720 // --------------------------------------------------------------------------------------------
2721 static void biosfn_read_state_info (BX
,ES
,DI
)
2722 Bit16u BX
;Bit16u ES
;Bit16u DI
;
2724 // Address of static functionality table
2725 write_word(ES
,DI
+0x00,&static_functionality
);
2726 write_word(ES
,DI
+0x02,0xC000);
2728 // Hard coded copy from BIOS area. Should it be cleaner ?
2729 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
2730 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
2732 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2733 write_byte(ES
,DI
+0x26,0);
2734 write_byte(ES
,DI
+0x27,16);
2735 write_byte(ES
,DI
+0x28,0);
2736 write_byte(ES
,DI
+0x29,8);
2737 write_byte(ES
,DI
+0x2a,2);
2738 write_byte(ES
,DI
+0x2b,0);
2739 write_byte(ES
,DI
+0x2c,0);
2740 write_byte(ES
,DI
+0x31,3);
2741 write_byte(ES
,DI
+0x32,0);
2743 memsetb(ES
,DI
+0x33,0,13);
2746 // --------------------------------------------------------------------------------------------
2747 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2753 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2759 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2766 // ============================================================================================
2770 // ============================================================================================
2772 // --------------------------------------------------------------------------------------------
2773 static Bit8u
find_vga_entry(mode
)
2777 for(i
=0;i
<=MODE_MAX
;i
++)
2778 if(vga_modes
[i
].svgamode
==mode
)
2785 /* =========================================================== */
2789 /* =========================================================== */
2791 // --------------------------------------------------------------------------------------------
2792 static void memsetb(seg
,offset
,value
,count
)
2807 mov cx
, 10[bp
] ; count
2810 mov ax
, 4[bp
] ; segment
2812 mov ax
, 6[bp
] ; offset
2814 mov al
, 8[bp
] ; value
2829 // --------------------------------------------------------------------------------------------
2830 static void memsetw(seg
,offset
,value
,count
)
2845 mov cx
, 10[bp
] ; count
2848 mov ax
, 4[bp
] ; segment
2850 mov ax
, 6[bp
] ; offset
2852 mov ax
, 8[bp
] ; value
2867 // --------------------------------------------------------------------------------------------
2868 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
2886 mov cx
, 12[bp
] ; count
2889 mov ax
, 4[bp
] ; dsegment
2891 mov ax
, 6[bp
] ; doffset
2893 mov ax
, 8[bp
] ; ssegment
2895 mov ax
, 10[bp
] ; soffset
2913 // --------------------------------------------------------------------------------------------
2914 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
2932 mov cx
, 12[bp
] ; count
2935 mov ax
, 4[bp
] ; dsegment
2937 mov ax
, 6[bp
] ; doffset
2939 mov ax
, 8[bp
] ; ssegment
2941 mov ax
, 10[bp
] ; soffset
2959 /* =========================================================== */
2961 * These functions where ripped from Kevin's rombios.c
2963 /* =========================================================== */
2965 // --------------------------------------------------------------------------------------------
2967 read_byte(seg
, offset
)
2977 mov ax
, 4[bp
] ; segment
2979 mov bx
, 6[bp
] ; offset
2981 ;; al
= return value (byte
)
2989 // --------------------------------------------------------------------------------------------
2991 read_word(seg
, offset
)
3001 mov ax
, 4[bp
] ; segment
3003 mov bx
, 6[bp
] ; offset
3005 ;; ax
= return value (word
)
3013 // --------------------------------------------------------------------------------------------
3015 write_byte(seg
, offset
, data
)
3027 mov ax
, 4[bp
] ; segment
3029 mov bx
, 6[bp
] ; offset
3030 mov al
, 8[bp
] ; data byte
3031 mov
[bx
], al
; write data byte
3040 // --------------------------------------------------------------------------------------------
3042 write_word(seg
, offset
, data
)
3054 mov ax
, 4[bp
] ; segment
3056 mov bx
, 6[bp
] ; offset
3057 mov ax
, 8[bp
] ; data word
3058 mov
[bx
], ax
; write data word
3067 // --------------------------------------------------------------------------------------------
3102 // --------------------------------------------------------------------------------------------
3124 // --------------------------------------------------------------------------------------------
3154 void unimplemented()
3156 printf("--> Unimplemented\n");
3161 printf("--> Unknown int10\n");
3165 // --------------------------------------------------------------------------------------------
3169 Bit8u c
, format_char
;
3171 unsigned format_width
, i
;
3173 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
3181 while (c
= read_byte(0xc000, s
)) {
3186 else if (in_format
) {
3187 if ( (c
>='0') && (c
<='9') ) {
3188 format_width
= (format_width
* 10) + (c
- '0');
3190 else if (c
== 'x') {
3191 arg_ptr
++; // increment to next arg
3192 arg
= read_word(arg_seg
, arg_ptr
);
3193 if (format_width
== 0)
3196 digit
= format_width
- 1;
3197 for (i
=0; i
<format_width
; i
++) {
3198 nibble
= (arg
>> (4 * digit
)) & 0x000f;
3200 outb(0x0500, nibble
+ '0');
3202 outb(0x0500, (nibble
- 10) + 'A');
3207 //else if (c == 'd') {
3222 // --------------------------------------------------------------------------------------------
3225 ;; DATA_SEG_DEFS_HERE
3229 .ascii
"vgabios ends here"
3233 ;; BLOCK_STRINGS_BEGIN