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_select_vert_res();
106 static void biosfn_switch_video_interface();
107 static void biosfn_enable_video_refresh_control();
108 static void biosfn_write_string();
109 static void biosfn_read_state_info();
110 static void biosfn_read_video_state_size();
111 static void biosfn_save_video_state();
112 static void biosfn_restore_video_state();
114 // This is for compiling with gcc2 and gcc3
115 #define ASM_START #asm
116 #define ASM_END #endasm
141 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
143 .byte
0x40 /* BIOS extension length in units of 512 bytes */
148 jmp vgabios_init_func
151 .ascii
"Plex86/Bochs VGABios"
155 // Info from Bart Oldeman
174 .ascii
"(C) 2003 the LGPL VGABios developers Team"
179 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
185 .ascii
"Please visit :"
187 ;;.ascii
" . http://www.plex86.org"
189 .ascii
" . http://bochs.sourceforge.net"
191 .ascii
" . http://www.nongnu.org/vgabios"
197 ;; ============================================================================================
201 ;; ============================================================================================
207 ;; init basic bios vars
211 ;; init vbe functions
216 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
218 ;; display splash screen
219 call _display_splash_screen
221 ;; init video mode
and clear the screen
230 call vbe_display_info
241 vgabios_int10_handler
:
256 call biosfn_get_video_mode
271 call biosfn_set_text_block_specifier
278 call biosfn_get_ega_info
283 call biosfn_enable_default_palette_loading
288 call biosfn_enable_video_addressing
293 call biosfn_enable_grayscale_summing
298 call biosfn_enable_cursor_emulation
316 jne int10_test_vbe_05
317 call vbe_biosfn_return_current_mode
321 jne int10_test_vbe_06
322 call vbe_biosfn_display_window_control
326 jne int10_test_vbe_07
327 call vbe_biosfn_set_get_logical_scan_line_length
331 jne int10_test_vbe_08
332 call vbe_biosfn_set_get_display_start
337 call vbe_biosfn_set_get_dac_palette_format
346 ;; We have to set ds to access the right data segment
359 #include "vgatables.h"
360 #include "vgafonts.h"
363 * Boot time harware inits
367 ;; switch to color mode
and enable CPU access
480 lines
372 ;; more than
64k
3C4
/04
380 mov bx
, #msg_vga_init
388 .ascii
"VGABios $Id$"
392 // --------------------------------------------------------------------------------------------
394 * Boot time bios area inits
399 mov ax
, # BIOSMEM_SEG
402 ;; init detected hardware BIOS Area
403 mov bx
, # BIOSMEM_INITIAL_MODE
408 ;; Just
for the first int10 find its children
410 ;; the
default char height
411 mov bx
, # BIOSMEM_CHAR_HEIGHT
416 mov bx
, # BIOSMEM_VIDEO_CTL
420 ;; Set the basic screen we have
421 mov bx
, # BIOSMEM_SWITCHES
425 ;; Set the basic modeset options
426 mov bx
, # BIOSMEM_MODESET_CTL
430 ;; Set the
default MSR
431 mov bx
, # BIOSMEM_CURRENT_MSR
439 // --------------------------------------------------------------------------------------------
441 * Boot time Splash screen
443 static void display_splash_screen()
447 // --------------------------------------------------------------------------------------------
452 static void display_info()
459 mov si
,#vgabios_version
462 ;;mov si
,#vgabios_copyright
463 ;;call _display_string
465 ;;call _display_string
467 mov si
,#vgabios_license
469 mov si
,#vgabios_website
474 static void display_string()
476 // Get length of string
503 // --------------------------------------------------------------------------------------------
505 static void int10_debugmsg(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
506 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
508 // 0E is write char...
510 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
514 // --------------------------------------------------------------------------------------------
516 * int10 main dispatcher
518 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
519 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
526 biosfn_set_video_mode(GET_AL());
527 switch(GET_AL()&0x7F)
545 biosfn_set_cursor_shape(GET_CH(),GET_CL());
548 biosfn_set_cursor_pos(GET_BH(),DX
);
551 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
554 // Read light pen pos (unimplemented)
564 biosfn_set_active_page(GET_AL());
567 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
570 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
573 biosfn_read_char_attr(GET_BH(),&AX
);
576 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
579 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
582 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
585 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
588 // Ralf Brown Interrupt list is WRONG on bh(page)
589 // We do output only on the current page !
590 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
593 // All other functions of group AH=0x10 rewritten in assembler
594 biosfn_perform_gray_scale_summing(BX
,CX
);
601 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
605 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
609 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
613 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
616 biosfn_load_gfx_8_8_chars(ES
,BP
);
619 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
622 biosfn_load_gfx_8_14_chars(GET_BL());
625 biosfn_load_gfx_8_8_dd_chars(GET_BL());
628 biosfn_load_gfx_8_16_chars(GET_BL());
631 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
644 biosfn_alternate_prtsc();
647 biosfn_select_vert_res(GET_AL());
651 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
655 biosfn_enable_video_refresh_control(GET_AL());
665 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
668 biosfn_read_state_info(BX
,ES
,DI
);
675 biosfn_read_video_state_size(CX
,&BX
);
678 biosfn_save_video_state(CX
,ES
,BX
);
681 biosfn_restore_video_state(CX
,ES
,BX
);
693 if (vbe_has_vbe_display()) {
697 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
700 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
703 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
751 // ============================================================================================
755 // ============================================================================================
757 static void biosfn_set_video_mode(mode
) Bit8u mode
;
758 {// mode: Bit 7 is 1 if no clear screen
760 // Should we clear the screen ?
761 Bit8u noclearmem
=mode
&0x80;
762 Bit8u line
,mmask
,*palette
;
763 Bit16u i
,twidth
,theight
,cheight
;
764 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
768 if (vbe_has_vbe_display()) {
769 dispi_set_enable(VBE_DISPI_DISABLED
);
776 // find the entry in the video modes
777 line
=find_vga_entry(mode
);
780 printf("mode search %02x found line %02x\n",mode
,line
);
786 twidth
=vga_modes
[line
].twidth
;
787 theight
=vga_modes
[line
].theight
;
788 cheight
=vga_modes
[line
].cheight
;
790 // Read the bios vga control
791 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
793 // Read the bios vga switches
794 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
796 // Read the bios mode set control
797 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
799 // Then we know the number of lines
802 // if palette loading (bit 3 of modeset ctl = 0)
803 if((modeset_ctl
&0x08)==0)
805 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
807 // Set the whole dac always, from 0
808 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
810 // From which palette
811 switch(vga_modes
[line
].dacmodel
)
825 // Always 256*3 values
826 for(i
=0;i
<0x0100;i
++)
827 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
828 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
829 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
830 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
833 {outb(VGAREG_DAC_DATA
,0);
834 outb(VGAREG_DAC_DATA
,0);
835 outb(VGAREG_DAC_DATA
,0);
838 if((modeset_ctl
&0x02)==0x02)
840 biosfn_perform_gray_scale_summing(0x00, 0x100);
844 // Reset Attribute Ctl flip-flop
845 inb(VGAREG_ACTL_RESET
);
848 for(i
=0;i
<=ACTL_MAX_REG
;i
++)
849 {outb(VGAREG_ACTL_ADDRESS
,i
);
850 outb(VGAREG_ACTL_WRITE_DATA
,actl_regs
[vga_modes
[line
].actlmodel
][i
]);
854 for(i
=0;i
<=SEQU_MAX_REG
;i
++)
855 {outb(VGAREG_SEQU_ADDRESS
,i
);
856 outb(VGAREG_SEQU_DATA
,sequ_regs
[vga_modes
[line
].sequmodel
][i
]);
860 for(i
=0;i
<=GRDC_MAX_REG
;i
++)
861 {outb(VGAREG_GRDC_ADDRESS
,i
);
862 outb(VGAREG_GRDC_DATA
,grdc_regs
[vga_modes
[line
].grdcmodel
][i
]);
865 // Set CRTC address VGA or MDA
866 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
869 for(i
=0;i
<=CRTC_MAX_REG
;i
++)
871 outb(crtc_addr
+1,crtc_regs
[vga_modes
[line
].crtcmodel
][i
]);
874 // Set the misc register
875 outb(VGAREG_WRITE_MISC_OUTPUT
,vga_modes
[line
].miscreg
);
878 outb(VGAREG_ACTL_ADDRESS
,0x20);
879 inb(VGAREG_ACTL_RESET
);
883 if(vga_modes
[line
].class==TEXT
)
885 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
891 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
895 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
896 mmask
= inb( VGAREG_SEQU_DATA
);
897 outb( VGAREG_SEQU_DATA
, 0x0f ); // all planes
898 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x8000); // 64k
899 outb( VGAREG_SEQU_DATA
, mmask
);
905 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
,mode
);
906 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
,twidth
);
907 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
,vga_modes
[line
].slength
);
908 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
909 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theight
-1);
910 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,cheight
);
911 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,(0x60|noclearmem
));
912 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
913 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)&0x7f);
915 // FIXME We nearly have the good tables. to be reworked
916 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,0x08); // 8 is VGA should be ok for now
917 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
,0x00);
918 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2,0x00);
921 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x00); // Unavailable on vanilla vga, but...
922 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAL
,0x00); // Unavailable on vanilla vga, but...
925 if(vga_modes
[line
].class==TEXT
)
927 biosfn_set_cursor_shape(0x06,0x07);
930 // Set cursor pos for page 0..7
932 biosfn_set_cursor_pos(i
,0x0000);
935 biosfn_set_active_page(0x00);
937 // Write the fonts in memory
938 if(vga_modes
[line
].class==TEXT
)
941 ;; copy
and activate
8x16 font
951 // Set the ints 0x1F and 0x43
953 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
959 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
964 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
969 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
975 // --------------------------------------------------------------------------------------------
976 static void biosfn_set_cursor_shape (CH
,CL
)
978 {Bit16u cheight
,curs
,crtc_addr
;
985 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
987 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
988 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
989 if((modeset_ctl
&0x01) && (cheight
>8) && (CL
<8) && (CH
<0x20))
993 CH
= ((CH
+1) * cheight
/ 8) -1;
997 CH
= ((CL
+1) * cheight
/ 8) - 2;
999 CL
= ((CL
+1) * cheight
/ 8) - 1;
1002 // CTRC regs 0x0a and 0x0b
1003 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1004 outb(crtc_addr
,0x0a);
1005 outb(crtc_addr
+1,CH
);
1006 outb(crtc_addr
,0x0b);
1007 outb(crtc_addr
+1,CL
);
1010 // --------------------------------------------------------------------------------------------
1011 static void biosfn_set_cursor_pos (page
, cursor
)
1012 Bit8u page
;Bit16u cursor
;
1014 Bit8u xcurs
,ycurs
,current
;
1015 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1017 // Should not happen...
1021 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1023 // Set the hardware cursor
1024 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1027 // Get the dimensions
1028 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1029 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1031 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1033 // Calculate the address knowing nbcols nbrows and page num
1034 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1036 // CRTC regs 0x0e and 0x0f
1037 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1038 outb(crtc_addr
,0x0e);
1039 outb(crtc_addr
+1,(address
&0xff00)>>8);
1040 outb(crtc_addr
,0x0f);
1041 outb(crtc_addr
+1,address
&0x00ff);
1045 // --------------------------------------------------------------------------------------------
1046 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1047 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1052 write_word(ss
, shape
, 0);
1053 write_word(ss
, pos
, 0);
1056 // FIXME should handle VGA 14/16 lines
1057 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1058 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1061 // --------------------------------------------------------------------------------------------
1062 static void biosfn_set_active_page (page
)
1065 Bit16u cursor
,dummy
,crtc_addr
;
1066 Bit16u nbcols
,nbrows
,address
;
1072 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1073 line
=find_vga_entry(mode
);
1074 if(line
==0xFF)return;
1076 // Get pos curs pos for the right page
1077 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1079 if(vga_modes
[line
].class==TEXT
)
1081 // Get the dimensions
1082 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1083 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1085 // Calculate the address knowing nbcols nbrows and page num
1086 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1087 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1090 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1094 address
= page
*vga_modes
[line
].slength
;
1097 // CRTC regs 0x0c and 0x0d
1098 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1099 outb(crtc_addr
,0x0c);
1100 outb(crtc_addr
+1,(address
&0xff00)>>8);
1101 outb(crtc_addr
,0x0d);
1102 outb(crtc_addr
+1,address
&0x00ff);
1104 // And change the BIOS page
1105 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1108 printf("Set active page %02x address %04x\n",page
,address
);
1111 // Display the cursor, now the page is active
1112 biosfn_set_cursor_pos(page
,cursor
);
1115 // --------------------------------------------------------------------------------------------
1116 static void vgamem_copy_pl4(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1117 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1122 src
=ysrc
*cheight
*nbcols
+xstart
;
1123 dest
=ydest
*cheight
*nbcols
+xstart
;
1124 outw(VGAREG_GRDC_ADDRESS
, 0x0105);
1125 for(i
=0;i
<cheight
;i
++)
1127 memcpyb(0xa000,dest
+i
*nbcols
,0xa000,src
+i
*nbcols
,cols
);
1129 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1132 // --------------------------------------------------------------------------------------------
1133 static void vgamem_fill_pl4(xstart
,ystart
,cols
,nbcols
,cheight
)
1134 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1139 dest
=ystart
*cheight
*nbcols
+xstart
;
1140 for(i
=0;i
<cheight
;i
++)
1142 memsetb(0xa000,dest
+i
*nbcols
,0x00,cols
);
1146 // --------------------------------------------------------------------------------------------
1147 static void vgamem_copy_cga(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1148 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1153 src
=((ysrc
*cheight
*nbcols
)>>1)+xstart
;
1154 dest
=((ydest
*cheight
*nbcols
)>>1)+xstart
;
1155 for(i
=0;i
<cheight
;i
++)
1158 memcpyb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,0xb800,0x2000+src
+(i
>>1)*nbcols
,cols
);
1160 memcpyb(0xb800,dest
+(i
>>1)*nbcols
,0xb800,src
+(i
>>1)*nbcols
,cols
);
1164 // --------------------------------------------------------------------------------------------
1165 static void vgamem_fill_cga(xstart
,ystart
,cols
,nbcols
,cheight
,attr
)
1166 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;Bit8u attr
;
1171 dest
=((ystart
*cheight
*nbcols
)>>1)+xstart
;
1172 for(i
=0;i
<cheight
;i
++)
1175 memsetb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,attr
,cols
);
1177 memsetb(0xb800,dest
+(i
>>1)*nbcols
,attr
,cols
);
1181 // --------------------------------------------------------------------------------------------
1182 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1183 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1185 // page == 0xFF if current
1187 Bit8u mode
,line
,cheight
,bpp
,cols
;
1188 Bit16u nbcols
,nbrows
,i
;
1195 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1196 line
=find_vga_entry(mode
);
1197 if(line
==0xFF)return;
1199 // Get the dimensions
1200 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1201 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1203 // Get the current page
1205 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1207 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1208 if(clr
>=nbcols
)clr
=nbcols
-1;
1209 if(nblines
>nbrows
)nblines
=0;
1212 if(vga_modes
[line
].class==TEXT
)
1214 // Compute the address
1215 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1217 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1220 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1222 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1227 {for(i
=rul
;i
<=rlr
;i
++)
1229 if((i
+nblines
>rlr
)||(nblines
==0))
1230 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1232 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,cols
);
1236 {for(i
=rlr
;i
>=rul
;i
--)
1238 if((i
<rul
+nblines
)||(nblines
==0))
1239 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1241 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,cols
);
1248 // FIXME gfx mode not complete
1249 cheight
=vga_modes
[line
].cheight
;
1250 switch(vga_modes
[line
].memmodel
)
1254 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1256 memsetb(vga_modes
[line
].sstart
,0,0x00,nbrows
*nbcols
*cheight
);
1261 {for(i
=rul
;i
<=rlr
;i
++)
1263 if((i
+nblines
>rlr
)||(nblines
==0))
1264 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
);
1266 vgamem_copy_pl4(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1270 {for(i
=rlr
;i
>=rul
;i
--)
1272 if((i
<rul
+nblines
)||(nblines
==0))
1273 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
);
1275 vgamem_copy_pl4(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1281 bpp
=vga_modes
[line
].pixbits
;
1282 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1284 memsetb(vga_modes
[line
].sstart
,0,attr
,nbrows
*nbcols
*cheight
*bpp
);
1296 {for(i
=rul
;i
<=rlr
;i
++)
1298 if((i
+nblines
>rlr
)||(nblines
==0))
1299 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1301 vgamem_copy_cga(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1305 {for(i
=rlr
;i
>=rul
;i
--)
1307 if((i
<rul
+nblines
)||(nblines
==0))
1308 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1310 vgamem_copy_cga(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1317 printf("Scroll in graphics mode ");
1324 // --------------------------------------------------------------------------------------------
1325 static void biosfn_read_char_attr (page
,car
)
1326 Bit8u page
;Bit16u
*car
;
1327 {Bit16u ss
=get_SS();
1328 Bit8u xcurs
,ycurs
,mode
,line
;
1329 Bit16u nbcols
,nbrows
,address
;
1330 Bit16u cursor
,dummy
;
1333 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1334 line
=find_vga_entry(mode
);
1335 if(line
==0xFF)return;
1337 // Get the cursor pos for the page
1338 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1339 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1341 // Get the dimensions
1342 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1343 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1345 if(vga_modes
[line
].class==TEXT
)
1347 // Compute the address
1348 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1350 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1361 // --------------------------------------------------------------------------------------------
1362 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1363 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1367 Bit16u addr
,dest
,src
;
1379 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1380 src
= car
* cheight
;
1381 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1384 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1386 for(i
=0;i
<cheight
;i
++)
1392 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1393 read_byte(0xa000,dest
);
1394 if(fdata
[src
+i
]&mask
)
1396 write_byte(0xa000,dest
,attr
&0x0f);
1400 write_byte(0xa000,dest
,0x00);
1405 mov dx
, # VGAREG_GRDC_ADDRESS
1415 // --------------------------------------------------------------------------------------------
1416 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1417 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1419 Bit8u i
,j
,mask
,data
;
1421 Bit16u addr
,dest
,src
;
1424 addr
=(xcurs
*bpp
)+ycurs
*320;
1428 dest
=addr
+(i
>>1)*80;
1429 if (i
& 1) dest
+= 0x2000;
1435 data
= read_byte(0xb800,dest
);
1443 if (fdata
[src
+i
] & mask
)
1447 data
^= (attr
& 0x01) << (7-j
);
1451 data
|= (attr
& 0x01) << (7-j
);
1456 write_byte(0xb800,dest
,data
);
1464 data
= read_byte(0xb800,dest
);
1472 if (fdata
[src
+i
] & mask
)
1476 data
^= (attr
& 0x03) << ((3-j
)*2);
1480 data
|= (attr
& 0x03) << ((3-j
)*2);
1485 write_byte(0xb800,dest
,data
);
1492 // --------------------------------------------------------------------------------------------
1493 static void write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
)
1494 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;
1496 Bit8u i
,j
,mask
,data
;
1498 Bit16u addr
,dest
,src
;
1501 addr
=xcurs
*8+ycurs
*nbcols
*64;
1505 dest
=addr
+i
*nbcols
*8;
1510 if (fdata
[src
+i
] & mask
)
1514 write_byte(0xa000,dest
+j
,data
);
1520 // --------------------------------------------------------------------------------------------
1521 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1522 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1524 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1525 Bit16u nbcols
,nbrows
,address
;
1526 Bit16u cursor
,dummy
;
1529 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1530 line
=find_vga_entry(mode
);
1531 if(line
==0xFF)return;
1533 // Get the cursor pos for the page
1534 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1535 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1537 // Get the dimensions
1538 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1539 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1541 if(vga_modes
[line
].class==TEXT
)
1543 // Compute the address
1544 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1546 dummy
=((Bit16u
)attr
<<8)+car
;
1547 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1551 // FIXME gfx mode not complete
1552 cheight
=vga_modes
[line
].cheight
;
1553 bpp
=vga_modes
[line
].pixbits
;
1554 while((count
-->0) && (xcurs
<nbcols
))
1556 switch(vga_modes
[line
].memmodel
)
1560 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1563 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1566 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1578 // --------------------------------------------------------------------------------------------
1579 static void biosfn_write_char_only (car
,page
,attr
,count
)
1580 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1582 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1583 Bit16u nbcols
,nbrows
,address
;
1584 Bit16u cursor
,dummy
;
1587 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1588 line
=find_vga_entry(mode
);
1589 if(line
==0xFF)return;
1591 // Get the cursor pos for the page
1592 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1593 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1595 // Get the dimensions
1596 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1597 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1599 if(vga_modes
[line
].class==TEXT
)
1601 // Compute the address
1602 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1605 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1611 // FIXME gfx mode not complete
1612 cheight
=vga_modes
[line
].cheight
;
1613 bpp
=vga_modes
[line
].pixbits
;
1614 while((count
-->0) && (xcurs
<nbcols
))
1616 switch(vga_modes
[line
].memmodel
)
1620 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1623 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1626 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1638 // --------------------------------------------------------------------------------------------
1642 je biosfn_set_border_color
1644 je biosfn_set_palette
1649 biosfn_set_border_color
:
1654 mov dx
, # VGAREG_ACTL_RESET
1656 mov dx
, # VGAREG_ACTL_ADDRESS
1669 mov dx
, # VGAREG_ACTL_ADDRESS
1672 mov dx
, # VGAREG_ACTL_READ_DATA
1676 mov dx
, # VGAREG_ACTL_ADDRESS
1680 jne set_intensity_loop
1693 mov dx
, # VGAREG_ACTL_RESET
1697 set_cga_palette_loop
:
1698 mov dx
, # VGAREG_ACTL_ADDRESS
1701 mov dx
, # VGAREG_ACTL_READ_DATA
1705 mov dx
, # VGAREG_ACTL_ADDRESS
1709 jne set_cga_palette_loop
1719 // --------------------------------------------------------------------------------------------
1720 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1722 Bit8u mode
,line
,mask
,attr
,data
;
1726 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1727 line
=find_vga_entry(mode
);
1728 if(line
==0xFF)return;
1729 if(vga_modes
[line
].class==TEXT
)return;
1731 switch(vga_modes
[line
].memmodel
)
1735 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1736 mask
= 0x01 << (7 - (CX
& 0x07));
1737 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1738 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1739 data
= read_byte(0xa000,addr
);
1742 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1744 write_byte(0xa000,addr
,AL
);
1745 outw(VGAREG_GRDC_ADDRESS
, 0xff08);
1746 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1747 outw(VGAREG_GRDC_ADDRESS
, 0x0003);
1750 if(vga_modes
[line
].pixbits
==2)
1752 addr
=(CX
>>2)+(DX
>>1)*80;
1756 addr
=(CX
>>3)+(DX
>>1)*80;
1758 if (DX
& 1) addr
+= 0x2000;
1759 data
= read_byte(0xb800,addr
);
1760 if(vga_modes
[line
].pixbits
==2)
1762 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1763 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1767 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1768 mask
= 0x01 << (7 - (CX
& 0x07));
1779 write_byte(0xb800,addr
,data
);
1782 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1783 write_byte(0xa000,addr
,AL
);
1792 // --------------------------------------------------------------------------------------------
1793 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1795 Bit8u mode
,line
,mask
,attr
,data
,i
;
1800 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1801 line
=find_vga_entry(mode
);
1802 if(line
==0xFF)return;
1803 if(vga_modes
[line
].class==TEXT
)return;
1805 switch(vga_modes
[line
].memmodel
)
1809 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1810 mask
= 0x01 << (7 - (CX
& 0x07));
1814 outw(VGAREG_GRDC_ADDRESS
, (i
<< 8) | 0x04);
1815 data
= read_byte(0xa000,addr
) & mask
;
1816 if (data
> 0) attr
|= (0x01 << i
);
1820 addr
=(CX
>>2)+(DX
>>1)*80;
1821 if (DX
& 1) addr
+= 0x2000;
1822 data
= read_byte(0xb800,addr
);
1823 if(vga_modes
[line
].pixbits
==2)
1825 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1829 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1833 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1834 attr
=read_byte(0xa000,addr
);
1842 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1845 // --------------------------------------------------------------------------------------------
1846 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1847 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1848 {// flag = WITH_ATTR / NO_ATTR
1850 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1851 Bit16u nbcols
,nbrows
,address
;
1852 Bit16u cursor
,dummy
;
1854 // special case if page is 0xff, use current page
1856 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1859 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1860 line
=find_vga_entry(mode
);
1861 if(line
==0xFF)return;
1863 // Get the cursor pos for the page
1864 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1865 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1867 // Get the dimensions
1868 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1869 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1893 biosfn_write_teletype(' ',page
,attr
,flag
);
1894 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1895 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1901 if(vga_modes
[line
].class==TEXT
)
1903 // Compute the address
1904 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1907 write_byte(vga_modes
[line
].sstart
,address
,car
);
1910 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1914 // FIXME gfx mode not complete
1915 cheight
=vga_modes
[line
].cheight
;
1916 bpp
=vga_modes
[line
].pixbits
;
1917 switch(vga_modes
[line
].memmodel
)
1921 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1924 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1927 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1938 // Do we need to wrap ?
1944 // Do we need to scroll ?
1947 if(vga_modes
[line
].class==TEXT
)
1949 biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1953 biosfn_scroll(0x01,0x00,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1958 // Set the cursor for the page
1959 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1960 biosfn_set_cursor_pos(page
,cursor
);
1963 // --------------------------------------------------------------------------------------------
1965 biosfn_get_video_mode
:
1967 mov ax
, # BIOSMEM_SEG
1970 mov bx
, # BIOSMEM_CURRENT_PAGE
1975 mov bx
, # BIOSMEM_VIDEO_CTL
1978 mov bx
, # BIOSMEM_CURRENT_MODE
1981 mov bx
, # BIOSMEM_NB_COLS
1988 // --------------------------------------------------------------------------------------------
1993 jmp biosfn_set_single_palette_reg
1997 jmp biosfn_set_overscan_border_color
2001 jmp biosfn_set_all_palette_reg
2005 jmp biosfn_toggle_intensity
2009 jmp biosfn_get_single_palette_reg
2013 jmp biosfn_read_overscan_border_color
2017 jmp biosfn_get_all_palette_reg
2021 jmp biosfn_set_single_dac_reg
2025 jmp biosfn_set_all_dac_reg
2029 jmp biosfn_select_video_dac_color_page
2033 jmp biosfn_read_single_dac_reg
2037 jmp biosfn_read_all_dac_reg
2041 jmp biosfn_set_pel_mask
2045 jmp biosfn_read_pel_mask
2048 jne int10_group_10_unknown
2049 jmp biosfn_read_video_dac_state
2050 int10_group_10_unknown
:
2056 biosfn_set_single_palette_reg
:
2061 mov dx
, # VGAREG_ACTL_RESET
2063 mov dx
, # VGAREG_ACTL_ADDRESS
2076 // --------------------------------------------------------------------------------------------
2078 biosfn_set_overscan_border_color
:
2081 call biosfn_set_single_palette_reg
2086 // --------------------------------------------------------------------------------------------
2088 biosfn_set_all_palette_reg
:
2094 mov dx
, # VGAREG_ACTL_RESET
2097 mov dx
, # VGAREG_ACTL_ADDRESS
2107 jne set_palette_loop
2122 // --------------------------------------------------------------------------------------------
2124 biosfn_toggle_intensity
:
2128 mov dx
, # VGAREG_ACTL_RESET
2130 mov dx
, # VGAREG_ACTL_ADDRESS
2133 mov dx
, # VGAREG_ACTL_READ_DATA
2139 mov dx
, # VGAREG_ACTL_ADDRESS
2149 // --------------------------------------------------------------------------------------------
2151 biosfn_get_single_palette_reg
:
2156 mov dx
, # VGAREG_ACTL_RESET
2158 mov dx
, # VGAREG_ACTL_ADDRESS
2161 mov dx
, # VGAREG_ACTL_READ_DATA
2164 mov dx
, # VGAREG_ACTL_RESET
2166 mov dx
, # VGAREG_ACTL_ADDRESS
2175 // --------------------------------------------------------------------------------------------
2177 biosfn_read_overscan_border_color
:
2181 call biosfn_get_single_palette_reg
2189 // --------------------------------------------------------------------------------------------
2191 biosfn_get_all_palette_reg
:
2199 mov dx
, # VGAREG_ACTL_RESET
2201 mov dx
, # VGAREG_ACTL_ADDRESS
2204 mov dx
, # VGAREG_ACTL_READ_DATA
2211 jne get_palette_loop
2212 mov dx
, # VGAREG_ACTL_RESET
2214 mov dx
, # VGAREG_ACTL_ADDRESS
2217 mov dx
, # VGAREG_ACTL_READ_DATA
2221 mov dx
, # VGAREG_ACTL_RESET
2223 mov dx
, # VGAREG_ACTL_ADDRESS
2233 // --------------------------------------------------------------------------------------------
2235 biosfn_set_single_dac_reg
:
2238 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2241 mov dx
, # VGAREG_DAC_DATA
2255 // --------------------------------------------------------------------------------------------
2257 biosfn_set_all_dac_reg
:
2262 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2268 mov dx
, # VGAREG_DAC_DATA
2291 // --------------------------------------------------------------------------------------------
2293 biosfn_select_video_dac_color_page
:
2297 mov dx
, # VGAREG_ACTL_RESET
2299 mov dx
, # VGAREG_ACTL_ADDRESS
2302 mov dx
, # VGAREG_ACTL_READ_DATA
2309 mov dx
, # VGAREG_ACTL_ADDRESS
2314 mov dx
, # VGAREG_ACTL_RESET
2316 mov dx
, # VGAREG_ACTL_ADDRESS
2336 // --------------------------------------------------------------------------------------------
2338 biosfn_read_single_dac_reg
:
2341 mov dx
, # VGAREG_DAC_READ_ADDRESS
2346 mov dx
, # VGAREG_DAC_DATA
2359 // --------------------------------------------------------------------------------------------
2361 biosfn_read_all_dac_reg
:
2366 mov dx
, # VGAREG_DAC_READ_ADDRESS
2372 mov dx
, # VGAREG_DAC_DATA
2395 // --------------------------------------------------------------------------------------------
2397 biosfn_set_pel_mask
:
2400 mov dx
, # VGAREG_PEL_MASK
2408 // --------------------------------------------------------------------------------------------
2410 biosfn_read_pel_mask
:
2413 mov dx
, # VGAREG_PEL_MASK
2421 // --------------------------------------------------------------------------------------------
2423 biosfn_read_video_dac_state
:
2426 mov dx
, # VGAREG_ACTL_RESET
2428 mov dx
, # VGAREG_ACTL_ADDRESS
2431 mov dx
, # VGAREG_ACTL_READ_DATA
2435 mov dx
, # VGAREG_ACTL_RESET
2437 mov dx
, # VGAREG_ACTL_ADDRESS
2440 mov dx
, # VGAREG_ACTL_READ_DATA
2448 mov dx
, # VGAREG_ACTL_RESET
2450 mov dx
, # VGAREG_ACTL_ADDRESS
2458 // --------------------------------------------------------------------------------------------
2459 static void biosfn_perform_gray_scale_summing (start
,count
)
2460 Bit16u start
;Bit16u count
;
2465 inb(VGAREG_ACTL_RESET
);
2466 outb(VGAREG_ACTL_ADDRESS
,0x00);
2468 for( index
= 0; index
< count
; index
++ )
2470 // set read address and switch to read mode
2471 outb(VGAREG_DAC_READ_ADDRESS
,start
);
2472 // get 6-bit wide RGB data values
2473 r
=inb( VGAREG_DAC_DATA
);
2474 g
=inb( VGAREG_DAC_DATA
);
2475 b
=inb( VGAREG_DAC_DATA
);
2477 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2478 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
2482 // set write address and switch to write mode
2483 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
2484 // write new intensity value
2485 outb( VGAREG_DAC_DATA
, i
&0xff );
2486 outb( VGAREG_DAC_DATA
, i
&0xff );
2487 outb( VGAREG_DAC_DATA
, i
&0xff );
2490 inb(VGAREG_ACTL_RESET
);
2491 outb(VGAREG_ACTL_ADDRESS
,0x20);
2494 // --------------------------------------------------------------------------------------------
2495 static void get_font_access()
2498 mov dx
, # VGAREG_SEQU_ADDRESS
2507 mov dx
, # VGAREG_GRDC_ADDRESS
2517 static void release_font_access()
2520 mov dx
, # VGAREG_SEQU_ADDRESS
2529 mov dx
, # VGAREG_READ_MISC_OUTPUT
2536 mov dx
, # VGAREG_GRDC_ADDRESS
2552 static void set_scan_lines(lines
) Bit8u lines
;
2554 Bit16u crtc_addr
,cols
,page
,vde
;
2555 Bit8u crtc_r9
,ovl
,rows
;
2557 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2558 outb(crtc_addr
, 0x09);
2559 crtc_r9
= inb(crtc_addr
+1);
2560 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2561 outb(crtc_addr
+1, crtc_r9
);
2564 biosfn_set_cursor_shape(0x06,0x07);
2568 biosfn_set_cursor_shape(lines
-4,lines
-3);
2570 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2571 outb(crtc_addr
, 0x12);
2572 vde
= inb(crtc_addr
+1);
2573 outb(crtc_addr
, 0x07);
2574 ovl
= inb(crtc_addr
+1);
2575 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2577 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2578 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2579 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2582 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
;
2584 Bit16u blockaddr
,dest
,i
,src
;
2587 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2591 dest
= blockaddr
+ (DX
+ i
) * 32;
2592 memcpyb(0xA000, dest
, ES
, src
, BH
);
2594 release_font_access();
2601 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2603 Bit16u blockaddr
,dest
,i
,src
;
2606 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2607 for(i
=0;i
<0x100;i
++)
2610 dest
= blockaddr
+ i
* 32;
2611 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2613 release_font_access();
2620 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2622 Bit16u blockaddr
,dest
,i
,src
;
2625 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2626 for(i
=0;i
<0x100;i
++)
2629 dest
= blockaddr
+ i
* 32;
2630 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2632 release_font_access();
2639 // --------------------------------------------------------------------------------------------
2641 biosfn_set_text_block_specifier
:
2644 mov dx
, # VGAREG_SEQU_ADDRESS
2653 // --------------------------------------------------------------------------------------------
2654 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2656 Bit16u blockaddr
,dest
,i
,src
;
2659 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2660 for(i
=0;i
<0x100;i
++)
2663 dest
= blockaddr
+ i
* 32;
2664 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2666 release_font_access();
2673 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2679 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2685 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2691 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2697 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2703 // --------------------------------------------------------------------------------------------
2704 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2705 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2706 {Bit16u ss
=get_SS();
2710 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2711 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2714 write_word(ss
,ES
,read_word(0x00,0x43*4));
2715 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2718 write_word(ss
,ES
,0xC000);
2719 write_word(ss
,BP
,vgafont14
);
2722 write_word(ss
,ES
,0xC000);
2723 write_word(ss
,BP
,vgafont8
);
2726 write_word(ss
,ES
,0xC000);
2727 write_word(ss
,BP
,vgafont8
+128*8);
2730 write_word(ss
,ES
,0xC000);
2731 write_word(ss
,BP
,vgafont14alt
);
2734 write_word(ss
,ES
,0xC000);
2735 write_word(ss
,BP
,vgafont16
);
2738 write_word(ss
,ES
,0xC000);
2739 write_word(ss
,BP
,vgafont16alt
);
2743 printf("Get font info BH(%02x) was discarded\n",BH
);
2747 // Set byte/char of on screen font
2748 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2750 // Set Highest char row
2751 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2754 // --------------------------------------------------------------------------------------------
2756 biosfn_get_ega_info
:
2759 mov ax
, # BIOSMEM_SEG
2762 mov bx
, # BIOSMEM_SWITCHES
2765 mov bx
, # BIOSMEM_CRTC_ADDRESS
2768 cmp ax
, # VGAREG_MDA_CRTC_ADDRESS
2777 // --------------------------------------------------------------------------------------------
2778 static void biosfn_alternate_prtsc()
2785 // --------------------------------------------------------------------------------------------
2786 static void biosfn_select_vert_res (res
)
2788 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2789 Bit8u modeset
,switches
;
2791 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2792 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2795 // set modeset ctl bit 7 and reset bit 4
2796 // set switches bit 3-0 to 0x08
2797 modeset
|=0x80;modeset
&=0xef;
2798 switches
&=0xf0;switches
|=0x08;
2801 // reset modeset ctl bit 7 and bit 4
2802 // set switches bit 3-0 to 0x09
2804 switches
&=0xf0;switches
|=0x09;
2807 // reset modeset ctl bit 7 and set bit 4
2808 // set switches bit 3-0 to 0x09
2809 modeset
|=0x10;modeset
&=0x7f;
2810 switches
&=0xf0;switches
|=0x09;
2814 printf("Select vert res (%02x) was discarded\n",res
);
2818 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2819 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,switches
);
2822 // --------------------------------------------------------------------------------------------
2824 biosfn_enable_default_palette_loading
:
2831 mov ax
, # BIOSMEM_SEG
2833 mov bx
, # BIOSMEM_MODESET_CTL
2845 // --------------------------------------------------------------------------------------------
2847 biosfn_enable_video_addressing
:
2854 mov dx
, # VGAREG_READ_MISC_OUTPUT
2858 mov dx
, # VGAREG_WRITE_MISC_OUTPUT
2866 // --------------------------------------------------------------------------------------------
2868 biosfn_enable_grayscale_summing
:
2876 mov ax
, # BIOSMEM_SEG
2878 mov bx
, # BIOSMEM_MODESET_CTL
2890 // --------------------------------------------------------------------------------------------
2892 biosfn_enable_cursor_emulation
:
2899 mov ax
, # BIOSMEM_SEG
2901 mov bx
, # BIOSMEM_MODESET_CTL
2913 // --------------------------------------------------------------------------------------------
2914 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2920 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2927 // --------------------------------------------------------------------------------------------
2928 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2929 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2931 Bit16u newcurs
,oldcurs
,dummy
;
2934 // Read curs info for the page
2935 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2937 // if row=0xff special case : use current cursor position
2939 {col
=oldcurs
&0x00ff;
2940 row
=(oldcurs
&0xff00)>>8;
2943 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
2944 biosfn_set_cursor_pos(page
,newcurs
);
2948 car
=read_byte(seg
,offset
++);
2950 attr
=read_byte(seg
,offset
++);
2952 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
2955 // Set back curs pos
2957 biosfn_set_cursor_pos(page
,oldcurs
);
2960 // --------------------------------------------------------------------------------------------
2964 je biosfn_read_display_code
2966 je biosfn_set_display_code
2971 biosfn_read_display_code
:
2974 mov ax
, # BIOSMEM_SEG
2976 mov bx
, # BIOSMEM_DCC_INDEX
2984 biosfn_set_display_code
:
2988 mov ax
, # BIOSMEM_SEG
2991 mov bx
, # BIOSMEM_DCC_INDEX
2997 mov bx
, #msg_alt_dcc
3010 .ascii
"Alternate Display code (%02x) was discarded"
3011 .byte
0x0d,0x0a,0x00
3015 // --------------------------------------------------------------------------------------------
3016 static void biosfn_read_state_info (BX
,ES
,DI
)
3017 Bit16u BX
;Bit16u ES
;Bit16u DI
;
3019 // Address of static functionality table
3020 write_word(ES
,DI
+0x00,&static_functionality
);
3021 write_word(ES
,DI
+0x02,0xC000);
3023 // Hard coded copy from BIOS area. Should it be cleaner ?
3024 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
3025 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
3027 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
3028 write_byte(ES
,DI
+0x26,0);
3029 write_byte(ES
,DI
+0x27,16);
3030 write_byte(ES
,DI
+0x28,0);
3031 write_byte(ES
,DI
+0x29,8);
3032 write_byte(ES
,DI
+0x2a,2);
3033 write_byte(ES
,DI
+0x2b,0);
3034 write_byte(ES
,DI
+0x2c,0);
3035 write_byte(ES
,DI
+0x31,3);
3036 write_byte(ES
,DI
+0x32,0);
3038 memsetb(ES
,DI
+0x33,0,13);
3041 // --------------------------------------------------------------------------------------------
3042 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3048 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3054 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3061 // ============================================================================================
3065 // ============================================================================================
3067 // --------------------------------------------------------------------------------------------
3068 static Bit8u
find_vga_entry(mode
)
3072 for(i
=0;i
<=MODE_MAX
;i
++)
3073 if(vga_modes
[i
].svgamode
==mode
)
3080 /* =========================================================== */
3084 /* =========================================================== */
3086 // --------------------------------------------------------------------------------------------
3087 static void memsetb(seg
,offset
,value
,count
)
3102 mov cx
, 10[bp
] ; count
3105 mov ax
, 4[bp
] ; segment
3107 mov ax
, 6[bp
] ; offset
3109 mov al
, 8[bp
] ; value
3124 // --------------------------------------------------------------------------------------------
3125 static void memsetw(seg
,offset
,value
,count
)
3140 mov cx
, 10[bp
] ; count
3143 mov ax
, 4[bp
] ; segment
3145 mov ax
, 6[bp
] ; offset
3147 mov ax
, 8[bp
] ; value
3162 // --------------------------------------------------------------------------------------------
3163 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
3181 mov cx
, 12[bp
] ; count
3184 mov ax
, 4[bp
] ; dsegment
3186 mov ax
, 6[bp
] ; doffset
3188 mov ax
, 8[bp
] ; ssegment
3190 mov ax
, 10[bp
] ; soffset
3208 // --------------------------------------------------------------------------------------------
3209 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
3227 mov cx
, 12[bp
] ; count
3230 mov ax
, 4[bp
] ; dsegment
3232 mov ax
, 6[bp
] ; doffset
3234 mov ax
, 8[bp
] ; ssegment
3236 mov ax
, 10[bp
] ; soffset
3254 /* =========================================================== */
3256 * These functions where ripped from Kevin's rombios.c
3258 /* =========================================================== */
3260 // --------------------------------------------------------------------------------------------
3262 read_byte(seg
, offset
)
3272 mov ax
, 4[bp
] ; segment
3274 mov bx
, 6[bp
] ; offset
3276 ;; al
= return value (byte
)
3284 // --------------------------------------------------------------------------------------------
3286 read_word(seg
, offset
)
3296 mov ax
, 4[bp
] ; segment
3298 mov bx
, 6[bp
] ; offset
3300 ;; ax
= return value (word
)
3308 // --------------------------------------------------------------------------------------------
3310 write_byte(seg
, offset
, data
)
3322 mov ax
, 4[bp
] ; segment
3324 mov bx
, 6[bp
] ; offset
3325 mov al
, 8[bp
] ; data byte
3326 mov
[bx
], al
; write data byte
3335 // --------------------------------------------------------------------------------------------
3337 write_word(seg
, offset
, data
)
3349 mov ax
, 4[bp
] ; segment
3351 mov bx
, 6[bp
] ; offset
3352 mov ax
, 8[bp
] ; data word
3353 mov
[bx
], ax
; write data word
3362 // --------------------------------------------------------------------------------------------
3397 // --------------------------------------------------------------------------------------------
3419 // --------------------------------------------------------------------------------------------
3449 void unimplemented()
3451 printf("--> Unimplemented\n");
3456 printf("--> Unknown int10\n");
3460 // --------------------------------------------------------------------------------------------
3464 Bit8u c
, format_char
;
3466 unsigned format_width
, i
;
3468 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
3476 while (c
= read_byte(0xc000, s
)) {
3481 else if (in_format
) {
3482 if ( (c
>='0') && (c
<='9') ) {
3483 format_width
= (format_width
* 10) + (c
- '0');
3485 else if (c
== 'x') {
3486 arg_ptr
++; // increment to next arg
3487 arg
= read_word(arg_seg
, arg_ptr
);
3488 if (format_width
== 0)
3491 digit
= format_width
- 1;
3492 for (i
=0; i
<format_width
; i
++) {
3493 nibble
= (arg
>> (4 * digit
)) & 0x000f;
3495 outb(0x0500, nibble
+ '0');
3497 outb(0x0500, (nibble
- 10) + 'A');
3502 //else if (c == 'd') {
3517 // --------------------------------------------------------------------------------------------
3520 ;; DATA_SEG_DEFS_HERE
3524 .ascii
"vgabios ends here"
3528 ;; BLOCK_STRINGS_BEGIN