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_write_pixel();
91 static void biosfn_read_pixel();
92 static void biosfn_write_teletype();
93 static void biosfn_perform_gray_scale_summing();
94 static void biosfn_load_text_user_pat();
95 static void biosfn_load_text_8_14_pat();
96 static void biosfn_load_text_8_8_pat();
97 static void biosfn_load_text_8_16_pat();
98 static void biosfn_load_gfx_8_8_chars();
99 static void biosfn_load_gfx_user_chars();
100 static void biosfn_load_gfx_8_14_chars();
101 static void biosfn_load_gfx_8_8_dd_chars();
102 static void biosfn_load_gfx_8_16_chars();
103 static void biosfn_get_font_info();
104 static void biosfn_alternate_prtsc();
105 static void biosfn_switch_video_interface();
106 static void biosfn_enable_video_refresh_control();
107 static void biosfn_write_string();
108 static void biosfn_read_state_info();
109 static void biosfn_read_video_state_size();
110 static void biosfn_save_video_state();
111 static void biosfn_restore_video_state();
113 // This is for compiling with gcc2 and gcc3
114 #define ASM_START #asm
115 #define ASM_END #endasm
140 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
142 .byte
0x40 /* BIOS extension length in units of 512 bytes */
147 jmp vgabios_init_func
150 .ascii
"Plex86/Bochs VGABios"
154 // Info from Bart Oldeman
173 .ascii
"(C) 2003 the LGPL VGABios developers Team"
178 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
184 .ascii
"Please visit :"
186 ;;.ascii
" . http://www.plex86.org"
188 .ascii
" . http://bochs.sourceforge.net"
190 .ascii
" . http://www.nongnu.org/vgabios"
196 ;; ============================================================================================
200 ;; ============================================================================================
206 ;; init basic bios vars
210 ;; init vbe functions
215 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
221 ;; display splash screen
222 call _display_splash_screen
224 ;; init video mode
and clear the screen
233 call vbe_display_info
238 call cirrus_display_info
248 vgabios_int10_handler
:
263 call biosfn_get_video_mode
278 call biosfn_set_text_block_specifier
285 call biosfn_get_ega_info
290 call biosfn_select_vert_res
295 call biosfn_enable_default_palette_loading
300 call biosfn_enable_video_addressing
305 call biosfn_enable_grayscale_summing
310 call biosfn_enable_cursor_emulation
328 jne int10_test_vbe_05
329 call vbe_biosfn_return_current_mode
333 jne int10_test_vbe_06
334 call vbe_biosfn_display_window_control
338 jne int10_test_vbe_07
339 call vbe_biosfn_set_get_logical_scan_line_length
343 jne int10_test_vbe_08
344 call vbe_biosfn_set_get_display_start
349 call vbe_biosfn_set_get_dac_palette_format
358 ;; We have to set ds to access the right data segment
371 #include "vgatables.h"
372 #include "vgafonts.h"
375 * Boot time harware inits
379 ;; switch to color mode
and enable CPU access
480 lines
384 ;; more than
64k
3C4
/04
392 mov bx
, #msg_vga_init
400 .ascii
"VGABios $Id$"
404 // --------------------------------------------------------------------------------------------
406 * Boot time bios area inits
411 mov ax
, # BIOSMEM_SEG
414 ;; init detected hardware BIOS Area
415 mov bx
, # BIOSMEM_INITIAL_MODE
420 ;; Just
for the first int10 find its children
422 ;; the
default char height
423 mov bx
, # BIOSMEM_CHAR_HEIGHT
428 mov bx
, # BIOSMEM_VIDEO_CTL
432 ;; Set the basic screen we have
433 mov bx
, # BIOSMEM_SWITCHES
437 ;; Set the basic modeset options
438 mov bx
, # BIOSMEM_MODESET_CTL
442 ;; Set the
default MSR
443 mov bx
, # BIOSMEM_CURRENT_MSR
451 // --------------------------------------------------------------------------------------------
453 * Boot time Splash screen
455 static void display_splash_screen()
459 // --------------------------------------------------------------------------------------------
464 static void display_info()
471 mov si
,#vgabios_version
474 ;;mov si
,#vgabios_copyright
475 ;;call _display_string
477 ;;call _display_string
479 mov si
,#vgabios_license
481 mov si
,#vgabios_website
486 static void display_string()
488 // Get length of string
515 // --------------------------------------------------------------------------------------------
517 static void int10_debugmsg(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
518 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
520 // 0E is write char...
522 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
526 // --------------------------------------------------------------------------------------------
528 * int10 main dispatcher
530 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
531 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
538 biosfn_set_video_mode(GET_AL());
539 switch(GET_AL()&0x7F)
557 biosfn_set_cursor_shape(GET_CH(),GET_CL());
560 biosfn_set_cursor_pos(GET_BH(),DX
);
563 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
566 // Read light pen pos (unimplemented)
576 biosfn_set_active_page(GET_AL());
579 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
582 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
585 biosfn_read_char_attr(GET_BH(),&AX
);
588 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
591 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
594 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
597 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
600 // Ralf Brown Interrupt list is WRONG on bh(page)
601 // We do output only on the current page !
602 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
605 // All other functions of group AH=0x10 rewritten in assembler
606 biosfn_perform_gray_scale_summing(BX
,CX
);
613 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
617 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
621 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
625 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
628 biosfn_load_gfx_8_8_chars(ES
,BP
);
631 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
634 biosfn_load_gfx_8_14_chars(GET_BL());
637 biosfn_load_gfx_8_8_dd_chars(GET_BL());
640 biosfn_load_gfx_8_16_chars(GET_BL());
643 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
656 biosfn_alternate_prtsc();
659 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
663 biosfn_enable_video_refresh_control(GET_AL());
673 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
676 biosfn_read_state_info(BX
,ES
,DI
);
683 biosfn_read_video_state_size(CX
,&BX
);
686 biosfn_save_video_state(CX
,ES
,BX
);
689 biosfn_restore_video_state(CX
,ES
,BX
);
701 if (vbe_has_vbe_display()) {
705 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
708 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
711 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
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
;
993 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
995 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
996 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
997 if((modeset_ctl
&0x01) && (cheight
>8) && (CL
<8) && (CH
<0x20))
1001 CH
= ((CH
+1) * cheight
/ 8) -1;
1005 CH
= ((CL
+1) * cheight
/ 8) - 2;
1007 CL
= ((CL
+1) * cheight
/ 8) - 1;
1010 // CTRC regs 0x0a and 0x0b
1011 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1012 outb(crtc_addr
,0x0a);
1013 outb(crtc_addr
+1,CH
);
1014 outb(crtc_addr
,0x0b);
1015 outb(crtc_addr
+1,CL
);
1018 // --------------------------------------------------------------------------------------------
1019 static void biosfn_set_cursor_pos (page
, cursor
)
1020 Bit8u page
;Bit16u cursor
;
1022 Bit8u xcurs
,ycurs
,current
;
1023 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1025 // Should not happen...
1029 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1031 // Set the hardware cursor
1032 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1035 // Get the dimensions
1036 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1037 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1039 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1041 // Calculate the address knowing nbcols nbrows and page num
1042 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1044 // CRTC regs 0x0e and 0x0f
1045 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1046 outb(crtc_addr
,0x0e);
1047 outb(crtc_addr
+1,(address
&0xff00)>>8);
1048 outb(crtc_addr
,0x0f);
1049 outb(crtc_addr
+1,address
&0x00ff);
1053 // --------------------------------------------------------------------------------------------
1054 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1055 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1060 write_word(ss
, shape
, 0);
1061 write_word(ss
, pos
, 0);
1064 // FIXME should handle VGA 14/16 lines
1065 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1066 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1069 // --------------------------------------------------------------------------------------------
1070 static void biosfn_set_active_page (page
)
1073 Bit16u cursor
,dummy
,crtc_addr
;
1074 Bit16u nbcols
,nbrows
,address
;
1080 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1081 line
=find_vga_entry(mode
);
1082 if(line
==0xFF)return;
1084 // Get pos curs pos for the right page
1085 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1087 if(vga_modes
[line
].class==TEXT
)
1089 // Get the dimensions
1090 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1091 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1093 // Calculate the address knowing nbcols nbrows and page num
1094 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1095 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1098 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1102 address
= page
*vga_modes
[line
].slength
;
1105 // CRTC regs 0x0c and 0x0d
1106 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1107 outb(crtc_addr
,0x0c);
1108 outb(crtc_addr
+1,(address
&0xff00)>>8);
1109 outb(crtc_addr
,0x0d);
1110 outb(crtc_addr
+1,address
&0x00ff);
1112 // And change the BIOS page
1113 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1116 printf("Set active page %02x address %04x\n",page
,address
);
1119 // Display the cursor, now the page is active
1120 biosfn_set_cursor_pos(page
,cursor
);
1123 // --------------------------------------------------------------------------------------------
1124 static void vgamem_copy_pl4(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1125 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1130 src
=ysrc
*cheight
*nbcols
+xstart
;
1131 dest
=ydest
*cheight
*nbcols
+xstart
;
1132 outw(VGAREG_GRDC_ADDRESS
, 0x0105);
1133 for(i
=0;i
<cheight
;i
++)
1135 memcpyb(0xa000,dest
+i
*nbcols
,0xa000,src
+i
*nbcols
,cols
);
1137 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1140 // --------------------------------------------------------------------------------------------
1141 static void vgamem_fill_pl4(xstart
,ystart
,cols
,nbcols
,cheight
,attr
)
1142 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;Bit8u attr
;
1147 dest
=ystart
*cheight
*nbcols
+xstart
;
1148 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1149 for(i
=0;i
<cheight
;i
++)
1151 memsetb(0xa000,dest
+i
*nbcols
,attr
,cols
);
1153 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1156 // --------------------------------------------------------------------------------------------
1157 static void vgamem_copy_cga(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1158 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1163 src
=((ysrc
*cheight
*nbcols
)>>1)+xstart
;
1164 dest
=((ydest
*cheight
*nbcols
)>>1)+xstart
;
1165 for(i
=0;i
<cheight
;i
++)
1168 memcpyb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,0xb800,0x2000+src
+(i
>>1)*nbcols
,cols
);
1170 memcpyb(0xb800,dest
+(i
>>1)*nbcols
,0xb800,src
+(i
>>1)*nbcols
,cols
);
1174 // --------------------------------------------------------------------------------------------
1175 static void vgamem_fill_cga(xstart
,ystart
,cols
,nbcols
,cheight
,attr
)
1176 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;Bit8u attr
;
1181 dest
=((ystart
*cheight
*nbcols
)>>1)+xstart
;
1182 for(i
=0;i
<cheight
;i
++)
1185 memsetb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,attr
,cols
);
1187 memsetb(0xb800,dest
+(i
>>1)*nbcols
,attr
,cols
);
1191 // --------------------------------------------------------------------------------------------
1192 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1193 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1195 // page == 0xFF if current
1197 Bit8u mode
,line
,cheight
,bpp
,cols
;
1198 Bit16u nbcols
,nbrows
,i
;
1205 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1206 line
=find_vga_entry(mode
);
1207 if(line
==0xFF)return;
1209 // Get the dimensions
1210 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1211 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1213 // Get the current page
1215 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1217 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1218 if(clr
>=nbcols
)clr
=nbcols
-1;
1219 if(nblines
>nbrows
)nblines
=0;
1222 if(vga_modes
[line
].class==TEXT
)
1224 // Compute the address
1225 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1227 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1230 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1232 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1237 {for(i
=rul
;i
<=rlr
;i
++)
1239 if((i
+nblines
>rlr
)||(nblines
==0))
1240 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1242 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,cols
);
1246 {for(i
=rlr
;i
>=rul
;i
--)
1248 if((i
<rul
+nblines
)||(nblines
==0))
1249 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1251 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,cols
);
1258 // FIXME gfx mode not complete
1259 cheight
=vga_modes
[line
].cheight
;
1260 switch(vga_modes
[line
].memmodel
)
1264 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1266 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1267 memsetb(vga_modes
[line
].sstart
,0,attr
,nbrows
*nbcols
*cheight
);
1268 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1273 {for(i
=rul
;i
<=rlr
;i
++)
1275 if((i
+nblines
>rlr
)||(nblines
==0))
1276 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
,attr
);
1278 vgamem_copy_pl4(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1282 {for(i
=rlr
;i
>=rul
;i
--)
1284 if((i
<rul
+nblines
)||(nblines
==0))
1285 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
,attr
);
1287 vgamem_copy_pl4(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1293 bpp
=vga_modes
[line
].pixbits
;
1294 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1296 memsetb(vga_modes
[line
].sstart
,0,attr
,nbrows
*nbcols
*cheight
*bpp
);
1308 {for(i
=rul
;i
<=rlr
;i
++)
1310 if((i
+nblines
>rlr
)||(nblines
==0))
1311 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1313 vgamem_copy_cga(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1317 {for(i
=rlr
;i
>=rul
;i
--)
1319 if((i
<rul
+nblines
)||(nblines
==0))
1320 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1322 vgamem_copy_cga(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1329 printf("Scroll in graphics mode ");
1336 // --------------------------------------------------------------------------------------------
1337 static void biosfn_read_char_attr (page
,car
)
1338 Bit8u page
;Bit16u
*car
;
1339 {Bit16u ss
=get_SS();
1340 Bit8u xcurs
,ycurs
,mode
,line
;
1341 Bit16u nbcols
,nbrows
,address
;
1342 Bit16u cursor
,dummy
;
1345 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1346 line
=find_vga_entry(mode
);
1347 if(line
==0xFF)return;
1349 // Get the cursor pos for the page
1350 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1351 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1353 // Get the dimensions
1354 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1355 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1357 if(vga_modes
[line
].class==TEXT
)
1359 // Compute the address
1360 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1362 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1373 // --------------------------------------------------------------------------------------------
1374 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1375 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1379 Bit16u addr
,dest
,src
;
1391 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1392 src
= car
* cheight
;
1393 outw(VGAREG_SEQU_ADDRESS
, 0x0f02);
1394 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1397 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1401 outw(VGAREG_GRDC_ADDRESS
, 0x0003);
1403 for(i
=0;i
<cheight
;i
++)
1409 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1410 read_byte(0xa000,dest
);
1411 if(fdata
[src
+i
]&mask
)
1413 write_byte(0xa000,dest
,attr
&0x0f);
1417 write_byte(0xa000,dest
,0x00);
1422 mov dx
, # VGAREG_GRDC_ADDRESS
1432 // --------------------------------------------------------------------------------------------
1433 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1434 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1436 Bit8u i
,j
,mask
,data
;
1438 Bit16u addr
,dest
,src
;
1441 addr
=(xcurs
*bpp
)+ycurs
*320;
1445 dest
=addr
+(i
>>1)*80;
1446 if (i
& 1) dest
+= 0x2000;
1452 data
= read_byte(0xb800,dest
);
1460 if (fdata
[src
+i
] & mask
)
1464 data
^= (attr
& 0x01) << (7-j
);
1468 data
|= (attr
& 0x01) << (7-j
);
1473 write_byte(0xb800,dest
,data
);
1481 data
= read_byte(0xb800,dest
);
1489 if (fdata
[src
+i
] & mask
)
1493 data
^= (attr
& 0x03) << ((3-j
)*2);
1497 data
|= (attr
& 0x03) << ((3-j
)*2);
1502 write_byte(0xb800,dest
,data
);
1509 // --------------------------------------------------------------------------------------------
1510 static void write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
)
1511 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;
1513 Bit8u i
,j
,mask
,data
;
1515 Bit16u addr
,dest
,src
;
1518 addr
=xcurs
*8+ycurs
*nbcols
*64;
1522 dest
=addr
+i
*nbcols
*8;
1527 if (fdata
[src
+i
] & mask
)
1531 write_byte(0xa000,dest
+j
,data
);
1537 // --------------------------------------------------------------------------------------------
1538 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1539 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1541 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1542 Bit16u nbcols
,nbrows
,address
;
1543 Bit16u cursor
,dummy
;
1546 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1547 line
=find_vga_entry(mode
);
1548 if(line
==0xFF)return;
1550 // Get the cursor pos for the page
1551 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1552 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1554 // Get the dimensions
1555 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1556 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1558 if(vga_modes
[line
].class==TEXT
)
1560 // Compute the address
1561 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1563 dummy
=((Bit16u
)attr
<<8)+car
;
1564 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1568 // FIXME gfx mode not complete
1569 cheight
=vga_modes
[line
].cheight
;
1570 bpp
=vga_modes
[line
].pixbits
;
1571 while((count
-->0) && (xcurs
<nbcols
))
1573 switch(vga_modes
[line
].memmodel
)
1577 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1580 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1583 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1595 // --------------------------------------------------------------------------------------------
1596 static void biosfn_write_char_only (car
,page
,attr
,count
)
1597 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1599 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1600 Bit16u nbcols
,nbrows
,address
;
1601 Bit16u cursor
,dummy
;
1604 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1605 line
=find_vga_entry(mode
);
1606 if(line
==0xFF)return;
1608 // Get the cursor pos for the page
1609 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1610 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1612 // Get the dimensions
1613 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1614 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1616 if(vga_modes
[line
].class==TEXT
)
1618 // Compute the address
1619 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1622 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1628 // FIXME gfx mode not complete
1629 cheight
=vga_modes
[line
].cheight
;
1630 bpp
=vga_modes
[line
].pixbits
;
1631 while((count
-->0) && (xcurs
<nbcols
))
1633 switch(vga_modes
[line
].memmodel
)
1637 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1640 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1643 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1655 // --------------------------------------------------------------------------------------------
1659 je biosfn_set_border_color
1661 je biosfn_set_palette
1666 biosfn_set_border_color
:
1671 mov dx
, # VGAREG_ACTL_RESET
1673 mov dx
, # VGAREG_ACTL_ADDRESS
1686 mov dx
, # VGAREG_ACTL_ADDRESS
1689 mov dx
, # VGAREG_ACTL_READ_DATA
1693 mov dx
, # VGAREG_ACTL_ADDRESS
1697 jne set_intensity_loop
1710 mov dx
, # VGAREG_ACTL_RESET
1714 set_cga_palette_loop
:
1715 mov dx
, # VGAREG_ACTL_ADDRESS
1718 mov dx
, # VGAREG_ACTL_READ_DATA
1722 mov dx
, # VGAREG_ACTL_ADDRESS
1726 jne set_cga_palette_loop
1736 // --------------------------------------------------------------------------------------------
1737 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1739 Bit8u mode
,line
,mask
,attr
,data
;
1743 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1744 line
=find_vga_entry(mode
);
1745 if(line
==0xFF)return;
1746 if(vga_modes
[line
].class==TEXT
)return;
1748 switch(vga_modes
[line
].memmodel
)
1752 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1753 mask
= 0x80 >> (CX
& 0x07);
1754 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1755 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1756 data
= read_byte(0xa000,addr
);
1759 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1761 write_byte(0xa000,addr
,AL
);
1763 mov dx
, # VGAREG_GRDC_ADDRESS
1773 if(vga_modes
[line
].pixbits
==2)
1775 addr
=(CX
>>2)+(DX
>>1)*80;
1779 addr
=(CX
>>3)+(DX
>>1)*80;
1781 if (DX
& 1) addr
+= 0x2000;
1782 data
= read_byte(0xb800,addr
);
1783 if(vga_modes
[line
].pixbits
==2)
1785 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1786 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1790 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1791 mask
= 0x01 << (7 - (CX
& 0x07));
1802 write_byte(0xb800,addr
,data
);
1805 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1806 write_byte(0xa000,addr
,AL
);
1815 // --------------------------------------------------------------------------------------------
1816 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1818 Bit8u mode
,line
,mask
,attr
,data
,i
;
1823 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1824 line
=find_vga_entry(mode
);
1825 if(line
==0xFF)return;
1826 if(vga_modes
[line
].class==TEXT
)return;
1828 switch(vga_modes
[line
].memmodel
)
1832 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1833 mask
= 0x80 >> (CX
& 0x07);
1837 outw(VGAREG_GRDC_ADDRESS
, (i
<< 8) | 0x04);
1838 data
= read_byte(0xa000,addr
) & mask
;
1839 if (data
> 0) attr
|= (0x01 << i
);
1843 addr
=(CX
>>2)+(DX
>>1)*80;
1844 if (DX
& 1) addr
+= 0x2000;
1845 data
= read_byte(0xb800,addr
);
1846 if(vga_modes
[line
].pixbits
==2)
1848 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1852 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1856 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1857 attr
=read_byte(0xa000,addr
);
1865 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1868 // --------------------------------------------------------------------------------------------
1869 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1870 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1871 {// flag = WITH_ATTR / NO_ATTR
1873 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1874 Bit16u nbcols
,nbrows
,address
;
1875 Bit16u cursor
,dummy
;
1877 // special case if page is 0xff, use current page
1879 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1882 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1883 line
=find_vga_entry(mode
);
1884 if(line
==0xFF)return;
1886 // Get the cursor pos for the page
1887 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1888 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1890 // Get the dimensions
1891 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1892 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1916 biosfn_write_teletype(' ',page
,attr
,flag
);
1917 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1918 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1924 if(vga_modes
[line
].class==TEXT
)
1926 // Compute the address
1927 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1930 write_byte(vga_modes
[line
].sstart
,address
,car
);
1933 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1937 // FIXME gfx mode not complete
1938 cheight
=vga_modes
[line
].cheight
;
1939 bpp
=vga_modes
[line
].pixbits
;
1940 switch(vga_modes
[line
].memmodel
)
1944 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1947 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1950 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1961 // Do we need to wrap ?
1967 // Do we need to scroll ?
1970 if(vga_modes
[line
].class==TEXT
)
1972 biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1976 biosfn_scroll(0x01,0x00,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1981 // Set the cursor for the page
1982 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1983 biosfn_set_cursor_pos(page
,cursor
);
1986 // --------------------------------------------------------------------------------------------
1988 biosfn_get_video_mode
:
1990 mov ax
, # BIOSMEM_SEG
1993 mov bx
, # BIOSMEM_CURRENT_PAGE
1998 mov bx
, # BIOSMEM_VIDEO_CTL
2001 mov bx
, # BIOSMEM_CURRENT_MODE
2004 mov bx
, # BIOSMEM_NB_COLS
2011 // --------------------------------------------------------------------------------------------
2016 jmp biosfn_set_single_palette_reg
2020 jmp biosfn_set_overscan_border_color
2024 jmp biosfn_set_all_palette_reg
2028 jmp biosfn_toggle_intensity
2032 jmp biosfn_get_single_palette_reg
2036 jmp biosfn_read_overscan_border_color
2040 jmp biosfn_get_all_palette_reg
2044 jmp biosfn_set_single_dac_reg
2048 jmp biosfn_set_all_dac_reg
2052 jmp biosfn_select_video_dac_color_page
2056 jmp biosfn_read_single_dac_reg
2060 jmp biosfn_read_all_dac_reg
2064 jmp biosfn_set_pel_mask
2068 jmp biosfn_read_pel_mask
2071 jne int10_group_10_unknown
2072 jmp biosfn_read_video_dac_state
2073 int10_group_10_unknown
:
2079 biosfn_set_single_palette_reg
:
2084 mov dx
, # VGAREG_ACTL_RESET
2086 mov dx
, # VGAREG_ACTL_ADDRESS
2099 // --------------------------------------------------------------------------------------------
2101 biosfn_set_overscan_border_color
:
2104 call biosfn_set_single_palette_reg
2109 // --------------------------------------------------------------------------------------------
2111 biosfn_set_all_palette_reg
:
2117 mov dx
, # VGAREG_ACTL_RESET
2120 mov dx
, # VGAREG_ACTL_ADDRESS
2130 jne set_palette_loop
2145 // --------------------------------------------------------------------------------------------
2147 biosfn_toggle_intensity
:
2151 mov dx
, # VGAREG_ACTL_RESET
2153 mov dx
, # VGAREG_ACTL_ADDRESS
2156 mov dx
, # VGAREG_ACTL_READ_DATA
2162 mov dx
, # VGAREG_ACTL_ADDRESS
2172 // --------------------------------------------------------------------------------------------
2174 biosfn_get_single_palette_reg
:
2179 mov dx
, # VGAREG_ACTL_RESET
2181 mov dx
, # VGAREG_ACTL_ADDRESS
2184 mov dx
, # VGAREG_ACTL_READ_DATA
2187 mov dx
, # VGAREG_ACTL_RESET
2189 mov dx
, # VGAREG_ACTL_ADDRESS
2198 // --------------------------------------------------------------------------------------------
2200 biosfn_read_overscan_border_color
:
2204 call biosfn_get_single_palette_reg
2212 // --------------------------------------------------------------------------------------------
2214 biosfn_get_all_palette_reg
:
2222 mov dx
, # VGAREG_ACTL_RESET
2224 mov dx
, # VGAREG_ACTL_ADDRESS
2227 mov dx
, # VGAREG_ACTL_READ_DATA
2234 jne get_palette_loop
2235 mov dx
, # VGAREG_ACTL_RESET
2237 mov dx
, # VGAREG_ACTL_ADDRESS
2240 mov dx
, # VGAREG_ACTL_READ_DATA
2244 mov dx
, # VGAREG_ACTL_RESET
2246 mov dx
, # VGAREG_ACTL_ADDRESS
2256 // --------------------------------------------------------------------------------------------
2258 biosfn_set_single_dac_reg
:
2261 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2264 mov dx
, # VGAREG_DAC_DATA
2278 // --------------------------------------------------------------------------------------------
2280 biosfn_set_all_dac_reg
:
2285 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2291 mov dx
, # VGAREG_DAC_DATA
2314 // --------------------------------------------------------------------------------------------
2316 biosfn_select_video_dac_color_page
:
2320 mov dx
, # VGAREG_ACTL_RESET
2322 mov dx
, # VGAREG_ACTL_ADDRESS
2325 mov dx
, # VGAREG_ACTL_READ_DATA
2332 mov dx
, # VGAREG_ACTL_ADDRESS
2337 mov dx
, # VGAREG_ACTL_RESET
2339 mov dx
, # VGAREG_ACTL_ADDRESS
2359 // --------------------------------------------------------------------------------------------
2361 biosfn_read_single_dac_reg
:
2364 mov dx
, # VGAREG_DAC_READ_ADDRESS
2369 mov dx
, # VGAREG_DAC_DATA
2382 // --------------------------------------------------------------------------------------------
2384 biosfn_read_all_dac_reg
:
2389 mov dx
, # VGAREG_DAC_READ_ADDRESS
2395 mov dx
, # VGAREG_DAC_DATA
2418 // --------------------------------------------------------------------------------------------
2420 biosfn_set_pel_mask
:
2423 mov dx
, # VGAREG_PEL_MASK
2431 // --------------------------------------------------------------------------------------------
2433 biosfn_read_pel_mask
:
2436 mov dx
, # VGAREG_PEL_MASK
2444 // --------------------------------------------------------------------------------------------
2446 biosfn_read_video_dac_state
:
2449 mov dx
, # VGAREG_ACTL_RESET
2451 mov dx
, # VGAREG_ACTL_ADDRESS
2454 mov dx
, # VGAREG_ACTL_READ_DATA
2458 mov dx
, # VGAREG_ACTL_RESET
2460 mov dx
, # VGAREG_ACTL_ADDRESS
2463 mov dx
, # VGAREG_ACTL_READ_DATA
2471 mov dx
, # VGAREG_ACTL_RESET
2473 mov dx
, # VGAREG_ACTL_ADDRESS
2481 // --------------------------------------------------------------------------------------------
2482 static void biosfn_perform_gray_scale_summing (start
,count
)
2483 Bit16u start
;Bit16u count
;
2488 inb(VGAREG_ACTL_RESET
);
2489 outb(VGAREG_ACTL_ADDRESS
,0x00);
2491 for( index
= 0; index
< count
; index
++ )
2493 // set read address and switch to read mode
2494 outb(VGAREG_DAC_READ_ADDRESS
,start
);
2495 // get 6-bit wide RGB data values
2496 r
=inb( VGAREG_DAC_DATA
);
2497 g
=inb( VGAREG_DAC_DATA
);
2498 b
=inb( VGAREG_DAC_DATA
);
2500 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2501 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
2505 // set write address and switch to write mode
2506 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
2507 // write new intensity value
2508 outb( VGAREG_DAC_DATA
, i
&0xff );
2509 outb( VGAREG_DAC_DATA
, i
&0xff );
2510 outb( VGAREG_DAC_DATA
, i
&0xff );
2513 inb(VGAREG_ACTL_RESET
);
2514 outb(VGAREG_ACTL_ADDRESS
,0x20);
2517 // --------------------------------------------------------------------------------------------
2518 static void get_font_access()
2521 mov dx
, # VGAREG_SEQU_ADDRESS
2530 mov dx
, # VGAREG_GRDC_ADDRESS
2540 static void release_font_access()
2543 mov dx
, # VGAREG_SEQU_ADDRESS
2552 mov dx
, # VGAREG_READ_MISC_OUTPUT
2559 mov dx
, # VGAREG_GRDC_ADDRESS
2575 static void set_scan_lines(lines
) Bit8u lines
;
2577 Bit16u crtc_addr
,cols
,page
,vde
;
2578 Bit8u crtc_r9
,ovl
,rows
;
2580 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2581 outb(crtc_addr
, 0x09);
2582 crtc_r9
= inb(crtc_addr
+1);
2583 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2584 outb(crtc_addr
+1, crtc_r9
);
2587 biosfn_set_cursor_shape(0x06,0x07);
2591 biosfn_set_cursor_shape(lines
-4,lines
-3);
2593 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2594 outb(crtc_addr
, 0x12);
2595 vde
= inb(crtc_addr
+1);
2596 outb(crtc_addr
, 0x07);
2597 ovl
= inb(crtc_addr
+1);
2598 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2600 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2601 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2602 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2605 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
;
2607 Bit16u blockaddr
,dest
,i
,src
;
2610 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2614 dest
= blockaddr
+ (DX
+ i
) * 32;
2615 memcpyb(0xA000, dest
, ES
, src
, BH
);
2617 release_font_access();
2624 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2626 Bit16u blockaddr
,dest
,i
,src
;
2629 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2630 for(i
=0;i
<0x100;i
++)
2633 dest
= blockaddr
+ i
* 32;
2634 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2636 release_font_access();
2643 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2645 Bit16u blockaddr
,dest
,i
,src
;
2648 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2649 for(i
=0;i
<0x100;i
++)
2652 dest
= blockaddr
+ i
* 32;
2653 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2655 release_font_access();
2662 // --------------------------------------------------------------------------------------------
2664 biosfn_set_text_block_specifier
:
2667 mov dx
, # VGAREG_SEQU_ADDRESS
2676 // --------------------------------------------------------------------------------------------
2677 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2679 Bit16u blockaddr
,dest
,i
,src
;
2682 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2683 for(i
=0;i
<0x100;i
++)
2686 dest
= blockaddr
+ i
* 32;
2687 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2689 release_font_access();
2696 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2702 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2708 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2714 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2720 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2726 // --------------------------------------------------------------------------------------------
2727 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2728 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2729 {Bit16u ss
=get_SS();
2733 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2734 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2737 write_word(ss
,ES
,read_word(0x00,0x43*4));
2738 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2741 write_word(ss
,ES
,0xC000);
2742 write_word(ss
,BP
,vgafont14
);
2745 write_word(ss
,ES
,0xC000);
2746 write_word(ss
,BP
,vgafont8
);
2749 write_word(ss
,ES
,0xC000);
2750 write_word(ss
,BP
,vgafont8
+128*8);
2753 write_word(ss
,ES
,0xC000);
2754 write_word(ss
,BP
,vgafont14alt
);
2757 write_word(ss
,ES
,0xC000);
2758 write_word(ss
,BP
,vgafont16
);
2761 write_word(ss
,ES
,0xC000);
2762 write_word(ss
,BP
,vgafont16alt
);
2766 printf("Get font info BH(%02x) was discarded\n",BH
);
2770 // Set byte/char of on screen font
2771 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2773 // Set Highest char row
2774 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2777 // --------------------------------------------------------------------------------------------
2779 biosfn_get_ega_info
:
2782 mov ax
, # BIOSMEM_SEG
2785 mov bx
, # BIOSMEM_SWITCHES
2788 mov bx
, # BIOSMEM_CRTC_ADDRESS
2791 cmp ax
, # VGAREG_MDA_CRTC_ADDRESS
2800 // --------------------------------------------------------------------------------------------
2801 static void biosfn_alternate_prtsc()
2808 // --------------------------------------------------------------------------------------------
2810 biosfn_select_vert_res
:
2812 ; res
: 00 200 lines
, 01 350 lines
, 02 400 lines
2818 mov ax
, # BIOSMEM_SEG
2820 mov bx
, # BIOSMEM_MODESET_CTL
2822 mov bx
, # BIOSMEM_SWITCHES
2833 mov bx
, #msg_vert_res
2841 ; reset modeset ctl bit
7 and set bit
4
2842 ; set switches bit
3-0 to
0x09
2851 ; reset modeset ctl bit
7 and bit
4
2852 ; set switches bit
3-0 to
0x09
2860 ; set modeset ctl bit
7 and reset bit
4
2861 ; set switches bit
3-0 to
0x08
2868 mov bx
, # BIOSMEM_MODESET_CTL
2870 mov bx
, # BIOSMEM_SWITCHES
2881 .ascii
"Select vert res (%02x) was discarded"
2882 .byte
0x0d,0x0a,0x00
2886 biosfn_enable_default_palette_loading
:
2893 mov ax
, # BIOSMEM_SEG
2895 mov bx
, # BIOSMEM_MODESET_CTL
2907 biosfn_enable_video_addressing
:
2914 mov dx
, # VGAREG_READ_MISC_OUTPUT
2918 mov dx
, # VGAREG_WRITE_MISC_OUTPUT
2926 biosfn_enable_grayscale_summing
:
2934 mov ax
, # BIOSMEM_SEG
2936 mov bx
, # BIOSMEM_MODESET_CTL
2948 biosfn_enable_cursor_emulation
:
2955 mov ax
, # BIOSMEM_SEG
2957 mov bx
, # BIOSMEM_MODESET_CTL
2969 // --------------------------------------------------------------------------------------------
2970 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2976 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2983 // --------------------------------------------------------------------------------------------
2984 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2985 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2987 Bit16u newcurs
,oldcurs
,dummy
;
2990 // Read curs info for the page
2991 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2993 // if row=0xff special case : use current cursor position
2995 {col
=oldcurs
&0x00ff;
2996 row
=(oldcurs
&0xff00)>>8;
2999 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
3000 biosfn_set_cursor_pos(page
,newcurs
);
3004 car
=read_byte(seg
,offset
++);
3006 attr
=read_byte(seg
,offset
++);
3008 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
3011 // Set back curs pos
3013 biosfn_set_cursor_pos(page
,oldcurs
);
3016 // --------------------------------------------------------------------------------------------
3020 je biosfn_read_display_code
3022 je biosfn_set_display_code
3027 biosfn_read_display_code
:
3030 mov ax
, # BIOSMEM_SEG
3032 mov bx
, # BIOSMEM_DCC_INDEX
3040 biosfn_set_display_code
:
3044 mov ax
, # BIOSMEM_SEG
3047 mov bx
, # BIOSMEM_DCC_INDEX
3053 mov bx
, #msg_alt_dcc
3066 .ascii
"Alternate Display code (%02x) was discarded"
3067 .byte
0x0d,0x0a,0x00
3071 // --------------------------------------------------------------------------------------------
3072 static void biosfn_read_state_info (BX
,ES
,DI
)
3073 Bit16u BX
;Bit16u ES
;Bit16u DI
;
3075 // Address of static functionality table
3076 write_word(ES
,DI
+0x00,&static_functionality
);
3077 write_word(ES
,DI
+0x02,0xC000);
3079 // Hard coded copy from BIOS area. Should it be cleaner ?
3080 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
3081 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
3083 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
3084 write_byte(ES
,DI
+0x26,0);
3085 write_byte(ES
,DI
+0x27,16);
3086 write_byte(ES
,DI
+0x28,0);
3087 write_byte(ES
,DI
+0x29,8);
3088 write_byte(ES
,DI
+0x2a,2);
3089 write_byte(ES
,DI
+0x2b,0);
3090 write_byte(ES
,DI
+0x2c,0);
3091 write_byte(ES
,DI
+0x31,3);
3092 write_byte(ES
,DI
+0x32,0);
3094 memsetb(ES
,DI
+0x33,0,13);
3097 // --------------------------------------------------------------------------------------------
3098 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3104 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3110 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3117 // ============================================================================================
3121 // ============================================================================================
3123 // --------------------------------------------------------------------------------------------
3124 static Bit8u
find_vga_entry(mode
)
3128 for(i
=0;i
<=MODE_MAX
;i
++)
3129 if(vga_modes
[i
].svgamode
==mode
)
3136 /* =========================================================== */
3140 /* =========================================================== */
3142 // --------------------------------------------------------------------------------------------
3143 static void memsetb(seg
,offset
,value
,count
)
3158 mov cx
, 10[bp
] ; count
3161 mov ax
, 4[bp
] ; segment
3163 mov ax
, 6[bp
] ; offset
3165 mov al
, 8[bp
] ; value
3180 // --------------------------------------------------------------------------------------------
3181 static void memsetw(seg
,offset
,value
,count
)
3196 mov cx
, 10[bp
] ; count
3199 mov ax
, 4[bp
] ; segment
3201 mov ax
, 6[bp
] ; offset
3203 mov ax
, 8[bp
] ; value
3218 // --------------------------------------------------------------------------------------------
3219 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
3237 mov cx
, 12[bp
] ; count
3240 mov ax
, 4[bp
] ; dsegment
3242 mov ax
, 6[bp
] ; doffset
3244 mov ax
, 8[bp
] ; ssegment
3246 mov ax
, 10[bp
] ; soffset
3264 // --------------------------------------------------------------------------------------------
3265 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
3283 mov cx
, 12[bp
] ; count
3286 mov ax
, 4[bp
] ; dsegment
3288 mov ax
, 6[bp
] ; doffset
3290 mov ax
, 8[bp
] ; ssegment
3292 mov ax
, 10[bp
] ; soffset
3310 /* =========================================================== */
3312 * These functions where ripped from Kevin's rombios.c
3314 /* =========================================================== */
3316 // --------------------------------------------------------------------------------------------
3318 read_byte(seg
, offset
)
3328 mov ax
, 4[bp
] ; segment
3330 mov bx
, 6[bp
] ; offset
3332 ;; al
= return value (byte
)
3340 // --------------------------------------------------------------------------------------------
3342 read_word(seg
, offset
)
3352 mov ax
, 4[bp
] ; segment
3354 mov bx
, 6[bp
] ; offset
3356 ;; ax
= return value (word
)
3364 // --------------------------------------------------------------------------------------------
3366 write_byte(seg
, offset
, data
)
3378 mov ax
, 4[bp
] ; segment
3380 mov bx
, 6[bp
] ; offset
3381 mov al
, 8[bp
] ; data byte
3382 mov
[bx
], al
; write data byte
3391 // --------------------------------------------------------------------------------------------
3393 write_word(seg
, offset
, data
)
3405 mov ax
, 4[bp
] ; segment
3407 mov bx
, 6[bp
] ; offset
3408 mov ax
, 8[bp
] ; data word
3409 mov
[bx
], ax
; write data word
3418 // --------------------------------------------------------------------------------------------
3453 // --------------------------------------------------------------------------------------------
3475 // --------------------------------------------------------------------------------------------
3505 void unimplemented()
3507 printf("--> Unimplemented\n");
3512 printf("--> Unknown int10\n");
3516 // --------------------------------------------------------------------------------------------
3520 Bit8u c
, format_char
;
3522 unsigned format_width
, i
;
3524 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
3532 while (c
= read_byte(0xc000, s
)) {
3537 else if (in_format
) {
3538 if ( (c
>='0') && (c
<='9') ) {
3539 format_width
= (format_width
* 10) + (c
- '0');
3541 else if (c
== 'x') {
3542 arg_ptr
++; // increment to next arg
3543 arg
= read_word(arg_seg
, arg_ptr
);
3544 if (format_width
== 0)
3547 digit
= format_width
- 1;
3548 for (i
=0; i
<format_width
; i
++) {
3549 nibble
= (arg
>> (4 * digit
)) & 0x000f;
3551 outb(0x0500, nibble
+ '0');
3553 outb(0x0500, (nibble
- 10) + 'A');
3558 //else if (c == 'd') {
3577 // --------------------------------------------------------------------------------------------
3580 ;; DATA_SEG_DEFS_HERE
3584 .ascii
"vgabios ends here"
3588 ;; BLOCK_STRINGS_BEGIN