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 // ============================================================================================
60 static Bit8u
read_byte();
61 static Bit16u
read_word();
62 static void write_byte();
63 static void write_word();
69 static Bit16u
get_SS();
73 static void unimplemented();
74 static void unknown();
76 static Bit8u
find_vga_entry();
78 static void memsetb();
79 static void memsetw();
80 static void memcpyb();
81 static void memcpyw();
83 static void biosfn_set_video_mode();
84 static void biosfn_set_cursor_shape();
85 static void biosfn_set_cursor_pos();
86 static void biosfn_get_cursor_pos();
87 static void biosfn_set_active_page();
88 static void biosfn_scroll();
89 static void biosfn_read_char_attr();
90 static void biosfn_write_char_attr();
91 static void biosfn_write_char_only();
92 static void biosfn_write_pixel();
93 static void biosfn_read_pixel();
94 static void biosfn_write_teletype();
95 static void biosfn_perform_gray_scale_summing();
96 static void biosfn_load_text_user_pat();
97 static void biosfn_load_text_8_14_pat();
98 static void biosfn_load_text_8_8_pat();
99 static void biosfn_load_text_8_16_pat();
100 static void biosfn_load_gfx_8_8_chars();
101 static void biosfn_load_gfx_user_chars();
102 static void biosfn_load_gfx_8_14_chars();
103 static void biosfn_load_gfx_8_8_dd_chars();
104 static void biosfn_load_gfx_8_16_chars();
105 static void biosfn_get_font_info();
106 static void biosfn_alternate_prtsc();
107 static void biosfn_switch_video_interface();
108 static void biosfn_enable_video_refresh_control();
109 static void biosfn_write_string();
110 static void biosfn_read_state_info();
111 static void biosfn_read_video_state_size();
112 static void biosfn_save_video_state();
113 static void biosfn_restore_video_state();
115 // This is for compiling with gcc2 and gcc3
116 #define ASM_START #asm
117 #define ASM_END #endasm
142 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
144 .byte
0x40 /* BIOS extension length in units of 512 bytes */
149 jmp vgabios_init_func
152 .ascii
"Plex86/Bochs VGABios"
156 // Info from Bart Oldeman
175 .ascii
"(C) 2003 the LGPL VGABios developers Team"
180 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
186 .ascii
"Please visit :"
188 ;;.ascii
" . http://www.plex86.org"
190 .ascii
" . http://bochs.sourceforge.net"
192 .ascii
" . http://www.nongnu.org/vgabios"
198 ;; ============================================================================================
202 ;; ============================================================================================
208 ;; init basic bios vars
212 ;; init vbe functions
217 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
223 ;; display splash screen
224 call _display_splash_screen
226 ;; init video mode
and clear the screen
235 call vbe_display_info
240 call cirrus_display_info
250 vgabios_int10_handler
:
265 call biosfn_get_video_mode
280 call biosfn_set_text_block_specifier
287 call biosfn_get_ega_info
292 call biosfn_select_vert_res
297 call biosfn_enable_default_palette_loading
302 call biosfn_enable_video_addressing
307 call biosfn_enable_grayscale_summing
312 call biosfn_enable_cursor_emulation
330 jne int10_test_vbe_05
331 call vbe_biosfn_return_current_mode
335 jne int10_test_vbe_06
336 call vbe_biosfn_display_window_control
340 jne int10_test_vbe_07
341 call vbe_biosfn_set_get_logical_scan_line_length
345 jne int10_test_vbe_08
346 call vbe_biosfn_set_get_display_start
350 jne int10_test_vbe_0A
351 call vbe_biosfn_set_get_dac_palette_format
356 call vbe_biosfn_return_protected_mode_interface
365 ;; We have to set ds to access the right data segment
378 #include "vgatables.h"
379 #include "vgafonts.h"
382 * Boot time harware inits
386 ;; switch to color mode
and enable CPU access
480 lines
391 ;; more than
64k
3C4
/04
399 #if defined(USE_BX_INFO) || defined(DEBUG)
400 mov bx
, #msg_vga_init
408 #if defined(USE_BX_INFO) || defined(DEBUG)
410 .ascii
"VGABios $Id$"
415 // --------------------------------------------------------------------------------------------
417 * Boot time bios area inits
422 mov ax
, # BIOSMEM_SEG
425 ;; init detected hardware BIOS Area
426 mov bx
, # BIOSMEM_INITIAL_MODE
429 ;; set
80x25
color (not clear from RBIL but usual
)
433 ;; Just
for the first int10 find its children
435 ;; the
default char height
436 mov bx
, # BIOSMEM_CHAR_HEIGHT
441 mov bx
, # BIOSMEM_VIDEO_CTL
445 ;; Set the basic screen we have
446 mov bx
, # BIOSMEM_SWITCHES
450 ;; Set the basic modeset options
451 mov bx
, # BIOSMEM_MODESET_CTL
455 ;; Set the
default MSR
456 mov bx
, # BIOSMEM_CURRENT_MSR
464 // --------------------------------------------------------------------------------------------
466 * Boot time Splash screen
468 static void display_splash_screen()
472 // --------------------------------------------------------------------------------------------
477 static void display_info()
484 mov si
,#vgabios_version
487 ;;mov si
,#vgabios_copyright
488 ;;call _display_string
490 ;;call _display_string
492 mov si
,#vgabios_license
494 mov si
,#vgabios_website
499 static void display_string()
501 // Get length of string
528 // --------------------------------------------------------------------------------------------
530 static void int10_debugmsg(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
531 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
533 // 0E is write char...
535 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
539 // --------------------------------------------------------------------------------------------
541 * int10 main dispatcher
543 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
544 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
551 biosfn_set_video_mode(GET_AL());
552 switch(GET_AL()&0x7F)
570 biosfn_set_cursor_shape(GET_CH(),GET_CL());
573 biosfn_set_cursor_pos(GET_BH(),DX
);
576 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
579 // Read light pen pos (unimplemented)
589 biosfn_set_active_page(GET_AL());
592 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
595 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
598 biosfn_read_char_attr(GET_BH(),&AX
);
601 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
604 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
607 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
610 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
613 // Ralf Brown Interrupt list is WRONG on bh(page)
614 // We do output only on the current page !
615 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
618 // All other functions of group AH=0x10 rewritten in assembler
619 biosfn_perform_gray_scale_summing(BX
,CX
);
626 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
630 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
634 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
638 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
641 biosfn_load_gfx_8_8_chars(ES
,BP
);
644 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
647 biosfn_load_gfx_8_14_chars(GET_BL());
650 biosfn_load_gfx_8_8_dd_chars(GET_BL());
653 biosfn_load_gfx_8_16_chars(GET_BL());
656 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
669 biosfn_alternate_prtsc();
672 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
676 biosfn_enable_video_refresh_control(GET_AL());
686 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
689 biosfn_read_state_info(BX
,ES
,DI
);
696 biosfn_read_video_state_size(CX
,&BX
);
699 biosfn_save_video_state(CX
,ES
,BX
);
702 biosfn_restore_video_state(CX
,ES
,BX
);
714 if (vbe_has_vbe_display()) {
718 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
721 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
724 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
772 // ============================================================================================
776 // ============================================================================================
778 static void biosfn_set_video_mode(mode
) Bit8u mode
;
779 {// mode: Bit 7 is 1 if no clear screen
781 // Should we clear the screen ?
782 Bit8u noclearmem
=mode
&0x80;
783 Bit8u line
,mmask
,*palette
;
784 Bit16u i
,twidth
,theight
,cheight
;
785 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
789 if (vbe_has_vbe_display()) {
790 dispi_set_enable(VBE_DISPI_DISABLED
);
797 // find the entry in the video modes
798 line
=find_vga_entry(mode
);
801 printf("mode search %02x found line %02x\n",mode
,line
);
807 twidth
=vga_modes
[line
].twidth
;
808 theight
=vga_modes
[line
].theight
;
809 cheight
=vga_modes
[line
].cheight
;
811 // Read the bios vga control
812 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
814 // Read the bios vga switches
815 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
817 // Read the bios mode set control
818 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
820 // Then we know the number of lines
823 // if palette loading (bit 3 of modeset ctl = 0)
824 if((modeset_ctl
&0x08)==0)
826 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
828 // Set the whole dac always, from 0
829 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
831 // From which palette
832 switch(vga_modes
[line
].dacmodel
)
846 // Always 256*3 values
847 for(i
=0;i
<0x0100;i
++)
848 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
849 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
850 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
851 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
854 {outb(VGAREG_DAC_DATA
,0);
855 outb(VGAREG_DAC_DATA
,0);
856 outb(VGAREG_DAC_DATA
,0);
859 if((modeset_ctl
&0x02)==0x02)
861 biosfn_perform_gray_scale_summing(0x00, 0x100);
865 // Reset Attribute Ctl flip-flop
866 inb(VGAREG_ACTL_RESET
);
869 for(i
=0;i
<=ACTL_MAX_REG
;i
++)
870 {outb(VGAREG_ACTL_ADDRESS
,i
);
871 outb(VGAREG_ACTL_WRITE_DATA
,actl_regs
[vga_modes
[line
].actlmodel
][i
]);
875 for(i
=0;i
<=SEQU_MAX_REG
;i
++)
876 {outb(VGAREG_SEQU_ADDRESS
,i
);
877 outb(VGAREG_SEQU_DATA
,sequ_regs
[vga_modes
[line
].sequmodel
][i
]);
881 for(i
=0;i
<=GRDC_MAX_REG
;i
++)
882 {outb(VGAREG_GRDC_ADDRESS
,i
);
883 outb(VGAREG_GRDC_DATA
,grdc_regs
[vga_modes
[line
].grdcmodel
][i
]);
886 // Set CRTC address VGA or MDA
887 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
889 // Disable CRTC write protection
890 outw(crtc_addr
,0x0011);
892 for(i
=0;i
<=CRTC_MAX_REG
;i
++)
894 outb(crtc_addr
+1,crtc_regs
[vga_modes
[line
].crtcmodel
][i
]);
897 // Set the misc register
898 outb(VGAREG_WRITE_MISC_OUTPUT
,vga_modes
[line
].miscreg
);
901 outb(VGAREG_ACTL_ADDRESS
,0x20);
902 inb(VGAREG_ACTL_RESET
);
906 if(vga_modes
[line
].class==TEXT
)
908 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
914 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
918 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
919 mmask
= inb( VGAREG_SEQU_DATA
);
920 outb( VGAREG_SEQU_DATA
, 0x0f ); // all planes
921 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x8000); // 64k
922 outb( VGAREG_SEQU_DATA
, mmask
);
928 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
,mode
);
929 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
,twidth
);
930 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
,vga_modes
[line
].slength
);
931 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
932 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theight
-1);
933 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,cheight
);
934 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,(0x60|noclearmem
));
935 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
936 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)&0x7f);
938 // FIXME We nearly have the good tables. to be reworked
939 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,0x08); // 8 is VGA should be ok for now
940 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
,0x00);
941 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2,0x00);
944 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x00); // Unavailable on vanilla vga, but...
945 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAL
,0x00); // Unavailable on vanilla vga, but...
948 if(vga_modes
[line
].class==TEXT
)
950 biosfn_set_cursor_shape(0x06,0x07);
953 // Set cursor pos for page 0..7
955 biosfn_set_cursor_pos(i
,0x0000);
958 biosfn_set_active_page(0x00);
960 // Write the fonts in memory
961 if(vga_modes
[line
].class==TEXT
)
964 ;; copy
and activate
8x16 font
974 // Set the ints 0x1F and 0x43
976 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
982 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
987 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
992 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
998 // --------------------------------------------------------------------------------------------
999 static void biosfn_set_cursor_shape (CH
,CL
)
1001 {Bit16u cheight
,curs
,crtc_addr
;
1008 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
1010 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
1011 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
1012 if((modeset_ctl
&0x01) && (cheight
>8) && (CL
<8) && (CH
<0x20))
1016 CH
= ((CH
+1) * cheight
/ 8) -1;
1020 CH
= ((CL
+1) * cheight
/ 8) - 2;
1022 CL
= ((CL
+1) * cheight
/ 8) - 1;
1025 // CTRC regs 0x0a and 0x0b
1026 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1027 outb(crtc_addr
,0x0a);
1028 outb(crtc_addr
+1,CH
);
1029 outb(crtc_addr
,0x0b);
1030 outb(crtc_addr
+1,CL
);
1033 // --------------------------------------------------------------------------------------------
1034 static void biosfn_set_cursor_pos (page
, cursor
)
1035 Bit8u page
;Bit16u cursor
;
1037 Bit8u xcurs
,ycurs
,current
;
1038 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1040 // Should not happen...
1044 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1046 // Set the hardware cursor
1047 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1050 // Get the dimensions
1051 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1052 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1054 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1056 // Calculate the address knowing nbcols nbrows and page num
1057 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1059 // CRTC regs 0x0e and 0x0f
1060 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1061 outb(crtc_addr
,0x0e);
1062 outb(crtc_addr
+1,(address
&0xff00)>>8);
1063 outb(crtc_addr
,0x0f);
1064 outb(crtc_addr
+1,address
&0x00ff);
1068 // --------------------------------------------------------------------------------------------
1069 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1070 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1075 write_word(ss
, shape
, 0);
1076 write_word(ss
, pos
, 0);
1079 // FIXME should handle VGA 14/16 lines
1080 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1081 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1084 // --------------------------------------------------------------------------------------------
1085 static void biosfn_set_active_page (page
)
1088 Bit16u cursor
,dummy
,crtc_addr
;
1089 Bit16u nbcols
,nbrows
,address
;
1095 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1096 line
=find_vga_entry(mode
);
1097 if(line
==0xFF)return;
1099 // Get pos curs pos for the right page
1100 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1102 if(vga_modes
[line
].class==TEXT
)
1104 // Get the dimensions
1105 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1106 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1108 // Calculate the address knowing nbcols nbrows and page num
1109 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1110 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1113 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1117 address
= page
*vga_modes
[line
].slength
;
1120 // CRTC regs 0x0c and 0x0d
1121 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1122 outb(crtc_addr
,0x0c);
1123 outb(crtc_addr
+1,(address
&0xff00)>>8);
1124 outb(crtc_addr
,0x0d);
1125 outb(crtc_addr
+1,address
&0x00ff);
1127 // And change the BIOS page
1128 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1131 printf("Set active page %02x address %04x\n",page
,address
);
1134 // Display the cursor, now the page is active
1135 biosfn_set_cursor_pos(page
,cursor
);
1138 // --------------------------------------------------------------------------------------------
1139 static void vgamem_copy_pl4(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1140 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1145 src
=ysrc
*cheight
*nbcols
+xstart
;
1146 dest
=ydest
*cheight
*nbcols
+xstart
;
1147 outw(VGAREG_GRDC_ADDRESS
, 0x0105);
1148 for(i
=0;i
<cheight
;i
++)
1150 memcpyb(0xa000,dest
+i
*nbcols
,0xa000,src
+i
*nbcols
,cols
);
1152 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1155 // --------------------------------------------------------------------------------------------
1156 static void vgamem_fill_pl4(xstart
,ystart
,cols
,nbcols
,cheight
,attr
)
1157 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;Bit8u attr
;
1162 dest
=ystart
*cheight
*nbcols
+xstart
;
1163 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1164 for(i
=0;i
<cheight
;i
++)
1166 memsetb(0xa000,dest
+i
*nbcols
,attr
,cols
);
1168 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1171 // --------------------------------------------------------------------------------------------
1172 static void vgamem_copy_cga(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1173 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1178 src
=((ysrc
*cheight
*nbcols
)>>1)+xstart
;
1179 dest
=((ydest
*cheight
*nbcols
)>>1)+xstart
;
1180 for(i
=0;i
<cheight
;i
++)
1183 memcpyb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,0xb800,0x2000+src
+(i
>>1)*nbcols
,cols
);
1185 memcpyb(0xb800,dest
+(i
>>1)*nbcols
,0xb800,src
+(i
>>1)*nbcols
,cols
);
1189 // --------------------------------------------------------------------------------------------
1190 static void vgamem_fill_cga(xstart
,ystart
,cols
,nbcols
,cheight
,attr
)
1191 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;Bit8u attr
;
1196 dest
=((ystart
*cheight
*nbcols
)>>1)+xstart
;
1197 for(i
=0;i
<cheight
;i
++)
1200 memsetb(0xb800,0x2000+dest
+(i
>>1)*nbcols
,attr
,cols
);
1202 memsetb(0xb800,dest
+(i
>>1)*nbcols
,attr
,cols
);
1206 // --------------------------------------------------------------------------------------------
1207 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1208 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1210 // page == 0xFF if current
1212 Bit8u mode
,line
,cheight
,bpp
,cols
;
1213 Bit16u nbcols
,nbrows
,i
;
1220 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1221 line
=find_vga_entry(mode
);
1222 if(line
==0xFF)return;
1224 // Get the dimensions
1225 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1226 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1228 // Get the current page
1230 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1232 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1233 if(clr
>=nbcols
)clr
=nbcols
-1;
1234 if(nblines
>nbrows
)nblines
=0;
1237 if(vga_modes
[line
].class==TEXT
)
1239 // Compute the address
1240 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1242 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1245 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1247 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1252 {for(i
=rul
;i
<=rlr
;i
++)
1254 if((i
+nblines
>rlr
)||(nblines
==0))
1255 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1257 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,cols
);
1261 {for(i
=rlr
;i
>=rul
;i
--)
1263 if((i
<rul
+nblines
)||(nblines
==0))
1264 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',cols
);
1266 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,cols
);
1273 // FIXME gfx mode not complete
1274 cheight
=vga_modes
[line
].cheight
;
1275 switch(vga_modes
[line
].memmodel
)
1279 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1281 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1282 memsetb(vga_modes
[line
].sstart
,0,attr
,nbrows
*nbcols
*cheight
);
1283 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1288 {for(i
=rul
;i
<=rlr
;i
++)
1290 if((i
+nblines
>rlr
)||(nblines
==0))
1291 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
,attr
);
1293 vgamem_copy_pl4(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1297 {for(i
=rlr
;i
>=rul
;i
--)
1299 if((i
<rul
+nblines
)||(nblines
==0))
1300 vgamem_fill_pl4(cul
,i
,cols
,nbcols
,cheight
,attr
);
1302 vgamem_copy_pl4(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1308 bpp
=vga_modes
[line
].pixbits
;
1309 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1311 memsetb(vga_modes
[line
].sstart
,0,attr
,nbrows
*nbcols
*cheight
*bpp
);
1323 {for(i
=rul
;i
<=rlr
;i
++)
1325 if((i
+nblines
>rlr
)||(nblines
==0))
1326 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1328 vgamem_copy_cga(cul
,i
+nblines
,i
,cols
,nbcols
,cheight
);
1332 {for(i
=rlr
;i
>=rul
;i
--)
1334 if((i
<rul
+nblines
)||(nblines
==0))
1335 vgamem_fill_cga(cul
,i
,cols
,nbcols
,cheight
,attr
);
1337 vgamem_copy_cga(cul
,i
,i
-nblines
,cols
,nbcols
,cheight
);
1344 printf("Scroll in graphics mode ");
1351 // --------------------------------------------------------------------------------------------
1352 static void biosfn_read_char_attr (page
,car
)
1353 Bit8u page
;Bit16u
*car
;
1354 {Bit16u ss
=get_SS();
1355 Bit8u xcurs
,ycurs
,mode
,line
;
1356 Bit16u nbcols
,nbrows
,address
;
1357 Bit16u cursor
,dummy
;
1360 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1361 line
=find_vga_entry(mode
);
1362 if(line
==0xFF)return;
1364 // Get the cursor pos for the page
1365 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1366 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1368 // Get the dimensions
1369 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1370 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1372 if(vga_modes
[line
].class==TEXT
)
1374 // Compute the address
1375 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1377 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1388 // --------------------------------------------------------------------------------------------
1389 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1390 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1394 Bit16u addr
,dest
,src
;
1406 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1407 src
= car
* cheight
;
1408 outw(VGAREG_SEQU_ADDRESS
, 0x0f02);
1409 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1412 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1416 outw(VGAREG_GRDC_ADDRESS
, 0x0003);
1418 for(i
=0;i
<cheight
;i
++)
1424 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1425 read_byte(0xa000,dest
);
1426 if(fdata
[src
+i
]&mask
)
1428 write_byte(0xa000,dest
,attr
&0x0f);
1432 write_byte(0xa000,dest
,0x00);
1437 mov dx
, # VGAREG_GRDC_ADDRESS
1447 // --------------------------------------------------------------------------------------------
1448 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1449 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1451 Bit8u i
,j
,mask
,data
;
1453 Bit16u addr
,dest
,src
;
1456 addr
=(xcurs
*bpp
)+ycurs
*320;
1460 dest
=addr
+(i
>>1)*80;
1461 if (i
& 1) dest
+= 0x2000;
1467 data
= read_byte(0xb800,dest
);
1475 if (fdata
[src
+i
] & mask
)
1479 data
^= (attr
& 0x01) << (7-j
);
1483 data
|= (attr
& 0x01) << (7-j
);
1488 write_byte(0xb800,dest
,data
);
1496 data
= read_byte(0xb800,dest
);
1504 if (fdata
[src
+i
] & mask
)
1508 data
^= (attr
& 0x03) << ((3-j
)*2);
1512 data
|= (attr
& 0x03) << ((3-j
)*2);
1517 write_byte(0xb800,dest
,data
);
1524 // --------------------------------------------------------------------------------------------
1525 static void write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
)
1526 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;
1528 Bit8u i
,j
,mask
,data
;
1530 Bit16u addr
,dest
,src
;
1533 addr
=xcurs
*8+ycurs
*nbcols
*64;
1537 dest
=addr
+i
*nbcols
*8;
1542 if (fdata
[src
+i
] & mask
)
1546 write_byte(0xa000,dest
+j
,data
);
1552 // --------------------------------------------------------------------------------------------
1553 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1554 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1556 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1557 Bit16u nbcols
,nbrows
,address
;
1558 Bit16u cursor
,dummy
;
1561 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1562 line
=find_vga_entry(mode
);
1563 if(line
==0xFF)return;
1565 // Get the cursor pos for the page
1566 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1567 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1569 // Get the dimensions
1570 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1571 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1573 if(vga_modes
[line
].class==TEXT
)
1575 // Compute the address
1576 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1578 dummy
=((Bit16u
)attr
<<8)+car
;
1579 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1583 // FIXME gfx mode not complete
1584 cheight
=vga_modes
[line
].cheight
;
1585 bpp
=vga_modes
[line
].pixbits
;
1586 while((count
-->0) && (xcurs
<nbcols
))
1588 switch(vga_modes
[line
].memmodel
)
1592 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1595 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1598 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1610 // --------------------------------------------------------------------------------------------
1611 static void biosfn_write_char_only (car
,page
,attr
,count
)
1612 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1614 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1615 Bit16u nbcols
,nbrows
,address
;
1616 Bit16u cursor
,dummy
;
1619 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1620 line
=find_vga_entry(mode
);
1621 if(line
==0xFF)return;
1623 // Get the cursor pos for the page
1624 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1625 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1627 // Get the dimensions
1628 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1629 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1631 if(vga_modes
[line
].class==TEXT
)
1633 // Compute the address
1634 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1637 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1643 // FIXME gfx mode not complete
1644 cheight
=vga_modes
[line
].cheight
;
1645 bpp
=vga_modes
[line
].pixbits
;
1646 while((count
-->0) && (xcurs
<nbcols
))
1648 switch(vga_modes
[line
].memmodel
)
1652 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1655 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1658 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1670 // --------------------------------------------------------------------------------------------
1674 je biosfn_set_border_color
1676 je biosfn_set_palette
1681 biosfn_set_border_color
:
1686 mov dx
, # VGAREG_ACTL_RESET
1688 mov dx
, # VGAREG_ACTL_ADDRESS
1701 mov dx
, # VGAREG_ACTL_ADDRESS
1704 mov dx
, # VGAREG_ACTL_READ_DATA
1708 mov dx
, # VGAREG_ACTL_ADDRESS
1712 jne set_intensity_loop
1725 mov dx
, # VGAREG_ACTL_RESET
1729 set_cga_palette_loop
:
1730 mov dx
, # VGAREG_ACTL_ADDRESS
1733 mov dx
, # VGAREG_ACTL_READ_DATA
1737 mov dx
, # VGAREG_ACTL_ADDRESS
1741 jne set_cga_palette_loop
1751 // --------------------------------------------------------------------------------------------
1752 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1754 Bit8u mode
,line
,mask
,attr
,data
;
1758 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1759 line
=find_vga_entry(mode
);
1760 if(line
==0xFF)return;
1761 if(vga_modes
[line
].class==TEXT
)return;
1763 switch(vga_modes
[line
].memmodel
)
1767 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1768 mask
= 0x80 >> (CX
& 0x07);
1769 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1770 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1771 data
= read_byte(0xa000,addr
);
1774 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1776 write_byte(0xa000,addr
,AL
);
1778 mov dx
, # VGAREG_GRDC_ADDRESS
1788 if(vga_modes
[line
].pixbits
==2)
1790 addr
=(CX
>>2)+(DX
>>1)*80;
1794 addr
=(CX
>>3)+(DX
>>1)*80;
1796 if (DX
& 1) addr
+= 0x2000;
1797 data
= read_byte(0xb800,addr
);
1798 if(vga_modes
[line
].pixbits
==2)
1800 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1801 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1805 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1806 mask
= 0x01 << (7 - (CX
& 0x07));
1817 write_byte(0xb800,addr
,data
);
1820 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1821 write_byte(0xa000,addr
,AL
);
1830 // --------------------------------------------------------------------------------------------
1831 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1833 Bit8u mode
,line
,mask
,attr
,data
,i
;
1838 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1839 line
=find_vga_entry(mode
);
1840 if(line
==0xFF)return;
1841 if(vga_modes
[line
].class==TEXT
)return;
1843 switch(vga_modes
[line
].memmodel
)
1847 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1848 mask
= 0x80 >> (CX
& 0x07);
1852 outw(VGAREG_GRDC_ADDRESS
, (i
<< 8) | 0x04);
1853 data
= read_byte(0xa000,addr
) & mask
;
1854 if (data
> 0) attr
|= (0x01 << i
);
1858 addr
=(CX
>>2)+(DX
>>1)*80;
1859 if (DX
& 1) addr
+= 0x2000;
1860 data
= read_byte(0xb800,addr
);
1861 if(vga_modes
[line
].pixbits
==2)
1863 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1867 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1871 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1872 attr
=read_byte(0xa000,addr
);
1880 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1883 // --------------------------------------------------------------------------------------------
1884 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1885 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1886 {// flag = WITH_ATTR / NO_ATTR
1888 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1889 Bit16u nbcols
,nbrows
,address
;
1890 Bit16u cursor
,dummy
;
1892 // special case if page is 0xff, use current page
1894 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1897 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1898 line
=find_vga_entry(mode
);
1899 if(line
==0xFF)return;
1901 // Get the cursor pos for the page
1902 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1903 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1905 // Get the dimensions
1906 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1907 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1930 biosfn_write_teletype(' ',page
,attr
,flag
);
1931 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1932 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1938 if(vga_modes
[line
].class==TEXT
)
1940 // Compute the address
1941 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1944 write_byte(vga_modes
[line
].sstart
,address
,car
);
1947 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1951 // FIXME gfx mode not complete
1952 cheight
=vga_modes
[line
].cheight
;
1953 bpp
=vga_modes
[line
].pixbits
;
1954 switch(vga_modes
[line
].memmodel
)
1958 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1961 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1964 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1975 // Do we need to wrap ?
1981 // Do we need to scroll ?
1984 if(vga_modes
[line
].class==TEXT
)
1986 biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1990 biosfn_scroll(0x01,0x00,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1995 // Set the cursor for the page
1996 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1997 biosfn_set_cursor_pos(page
,cursor
);
2000 // --------------------------------------------------------------------------------------------
2002 biosfn_get_video_mode
:
2004 mov ax
, # BIOSMEM_SEG
2007 mov bx
, # BIOSMEM_CURRENT_PAGE
2012 mov bx
, # BIOSMEM_VIDEO_CTL
2015 mov bx
, # BIOSMEM_CURRENT_MODE
2018 mov bx
, # BIOSMEM_NB_COLS
2025 // --------------------------------------------------------------------------------------------
2030 jmp biosfn_set_single_palette_reg
2034 jmp biosfn_set_overscan_border_color
2038 jmp biosfn_set_all_palette_reg
2042 jmp biosfn_toggle_intensity
2046 jmp biosfn_get_single_palette_reg
2050 jmp biosfn_read_overscan_border_color
2054 jmp biosfn_get_all_palette_reg
2058 jmp biosfn_set_single_dac_reg
2062 jmp biosfn_set_all_dac_reg
2066 jmp biosfn_select_video_dac_color_page
2070 jmp biosfn_read_single_dac_reg
2074 jmp biosfn_read_all_dac_reg
2078 jmp biosfn_set_pel_mask
2082 jmp biosfn_read_pel_mask
2085 jne int10_group_10_unknown
2086 jmp biosfn_read_video_dac_state
2087 int10_group_10_unknown
:
2093 biosfn_set_single_palette_reg
:
2098 mov dx
, # VGAREG_ACTL_RESET
2100 mov dx
, # VGAREG_ACTL_ADDRESS
2113 // --------------------------------------------------------------------------------------------
2115 biosfn_set_overscan_border_color
:
2118 call biosfn_set_single_palette_reg
2123 // --------------------------------------------------------------------------------------------
2125 biosfn_set_all_palette_reg
:
2131 mov dx
, # VGAREG_ACTL_RESET
2134 mov dx
, # VGAREG_ACTL_ADDRESS
2144 jne set_palette_loop
2159 // --------------------------------------------------------------------------------------------
2161 biosfn_toggle_intensity
:
2165 mov dx
, # VGAREG_ACTL_RESET
2167 mov dx
, # VGAREG_ACTL_ADDRESS
2170 mov dx
, # VGAREG_ACTL_READ_DATA
2176 mov dx
, # VGAREG_ACTL_ADDRESS
2186 // --------------------------------------------------------------------------------------------
2188 biosfn_get_single_palette_reg
:
2193 mov dx
, # VGAREG_ACTL_RESET
2195 mov dx
, # VGAREG_ACTL_ADDRESS
2198 mov dx
, # VGAREG_ACTL_READ_DATA
2201 mov dx
, # VGAREG_ACTL_RESET
2203 mov dx
, # VGAREG_ACTL_ADDRESS
2212 // --------------------------------------------------------------------------------------------
2214 biosfn_read_overscan_border_color
:
2218 call biosfn_get_single_palette_reg
2226 // --------------------------------------------------------------------------------------------
2228 biosfn_get_all_palette_reg
:
2236 mov dx
, # VGAREG_ACTL_RESET
2238 mov dx
, # VGAREG_ACTL_ADDRESS
2241 mov dx
, # VGAREG_ACTL_READ_DATA
2248 jne get_palette_loop
2249 mov dx
, # VGAREG_ACTL_RESET
2251 mov dx
, # VGAREG_ACTL_ADDRESS
2254 mov dx
, # VGAREG_ACTL_READ_DATA
2258 mov dx
, # VGAREG_ACTL_RESET
2260 mov dx
, # VGAREG_ACTL_ADDRESS
2270 // --------------------------------------------------------------------------------------------
2272 biosfn_set_single_dac_reg
:
2275 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2278 mov dx
, # VGAREG_DAC_DATA
2292 // --------------------------------------------------------------------------------------------
2294 biosfn_set_all_dac_reg
:
2299 mov dx
, # VGAREG_DAC_WRITE_ADDRESS
2305 mov dx
, # VGAREG_DAC_DATA
2328 // --------------------------------------------------------------------------------------------
2330 biosfn_select_video_dac_color_page
:
2334 mov dx
, # VGAREG_ACTL_RESET
2336 mov dx
, # VGAREG_ACTL_ADDRESS
2339 mov dx
, # VGAREG_ACTL_READ_DATA
2346 mov dx
, # VGAREG_ACTL_ADDRESS
2351 mov dx
, # VGAREG_ACTL_RESET
2353 mov dx
, # VGAREG_ACTL_ADDRESS
2373 // --------------------------------------------------------------------------------------------
2375 biosfn_read_single_dac_reg
:
2378 mov dx
, # VGAREG_DAC_READ_ADDRESS
2383 mov dx
, # VGAREG_DAC_DATA
2396 // --------------------------------------------------------------------------------------------
2398 biosfn_read_all_dac_reg
:
2403 mov dx
, # VGAREG_DAC_READ_ADDRESS
2409 mov dx
, # VGAREG_DAC_DATA
2432 // --------------------------------------------------------------------------------------------
2434 biosfn_set_pel_mask
:
2437 mov dx
, # VGAREG_PEL_MASK
2445 // --------------------------------------------------------------------------------------------
2447 biosfn_read_pel_mask
:
2450 mov dx
, # VGAREG_PEL_MASK
2458 // --------------------------------------------------------------------------------------------
2460 biosfn_read_video_dac_state
:
2463 mov dx
, # VGAREG_ACTL_RESET
2465 mov dx
, # VGAREG_ACTL_ADDRESS
2468 mov dx
, # VGAREG_ACTL_READ_DATA
2472 mov dx
, # VGAREG_ACTL_RESET
2474 mov dx
, # VGAREG_ACTL_ADDRESS
2477 mov dx
, # VGAREG_ACTL_READ_DATA
2485 mov dx
, # VGAREG_ACTL_RESET
2487 mov dx
, # VGAREG_ACTL_ADDRESS
2495 // --------------------------------------------------------------------------------------------
2496 static void biosfn_perform_gray_scale_summing (start
,count
)
2497 Bit16u start
;Bit16u count
;
2502 inb(VGAREG_ACTL_RESET
);
2503 outb(VGAREG_ACTL_ADDRESS
,0x00);
2505 for( index
= 0; index
< count
; index
++ )
2507 // set read address and switch to read mode
2508 outb(VGAREG_DAC_READ_ADDRESS
,start
);
2509 // get 6-bit wide RGB data values
2510 r
=inb( VGAREG_DAC_DATA
);
2511 g
=inb( VGAREG_DAC_DATA
);
2512 b
=inb( VGAREG_DAC_DATA
);
2514 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2515 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
2519 // set write address and switch to write mode
2520 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
2521 // write new intensity value
2522 outb( VGAREG_DAC_DATA
, i
&0xff );
2523 outb( VGAREG_DAC_DATA
, i
&0xff );
2524 outb( VGAREG_DAC_DATA
, i
&0xff );
2527 inb(VGAREG_ACTL_RESET
);
2528 outb(VGAREG_ACTL_ADDRESS
,0x20);
2531 // --------------------------------------------------------------------------------------------
2532 static void get_font_access()
2535 mov dx
, # VGAREG_SEQU_ADDRESS
2544 mov dx
, # VGAREG_GRDC_ADDRESS
2554 static void release_font_access()
2557 mov dx
, # VGAREG_SEQU_ADDRESS
2566 mov dx
, # VGAREG_READ_MISC_OUTPUT
2573 mov dx
, # VGAREG_GRDC_ADDRESS
2589 static void set_scan_lines(lines
) Bit8u lines
;
2591 Bit16u crtc_addr
,cols
,page
,vde
;
2592 Bit8u crtc_r9
,ovl
,rows
;
2594 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2595 outb(crtc_addr
, 0x09);
2596 crtc_r9
= inb(crtc_addr
+1);
2597 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2598 outb(crtc_addr
+1, crtc_r9
);
2601 biosfn_set_cursor_shape(0x06,0x07);
2605 biosfn_set_cursor_shape(lines
-4,lines
-3);
2607 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2608 outb(crtc_addr
, 0x12);
2609 vde
= inb(crtc_addr
+1);
2610 outb(crtc_addr
, 0x07);
2611 ovl
= inb(crtc_addr
+1);
2612 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2614 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2615 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2616 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2619 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
;
2621 Bit16u blockaddr
,dest
,i
,src
;
2624 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2628 dest
= blockaddr
+ (DX
+ i
) * 32;
2629 memcpyb(0xA000, dest
, ES
, src
, BH
);
2631 release_font_access();
2638 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2640 Bit16u blockaddr
,dest
,i
,src
;
2643 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2644 for(i
=0;i
<0x100;i
++)
2647 dest
= blockaddr
+ i
* 32;
2648 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2650 release_font_access();
2657 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2659 Bit16u blockaddr
,dest
,i
,src
;
2662 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2663 for(i
=0;i
<0x100;i
++)
2666 dest
= blockaddr
+ i
* 32;
2667 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2669 release_font_access();
2676 // --------------------------------------------------------------------------------------------
2678 biosfn_set_text_block_specifier
:
2681 mov dx
, # VGAREG_SEQU_ADDRESS
2690 // --------------------------------------------------------------------------------------------
2691 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2693 Bit16u blockaddr
,dest
,i
,src
;
2696 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2697 for(i
=0;i
<0x100;i
++)
2700 dest
= blockaddr
+ i
* 32;
2701 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2703 release_font_access();
2710 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2716 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2722 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2728 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2734 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2740 // --------------------------------------------------------------------------------------------
2741 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2742 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2743 {Bit16u ss
=get_SS();
2747 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2748 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2751 write_word(ss
,ES
,read_word(0x00,0x43*4));
2752 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2755 write_word(ss
,ES
,0xC000);
2756 write_word(ss
,BP
,vgafont14
);
2759 write_word(ss
,ES
,0xC000);
2760 write_word(ss
,BP
,vgafont8
);
2763 write_word(ss
,ES
,0xC000);
2764 write_word(ss
,BP
,vgafont8
+128*8);
2767 write_word(ss
,ES
,0xC000);
2768 write_word(ss
,BP
,vgafont14alt
);
2771 write_word(ss
,ES
,0xC000);
2772 write_word(ss
,BP
,vgafont16
);
2775 write_word(ss
,ES
,0xC000);
2776 write_word(ss
,BP
,vgafont16alt
);
2780 printf("Get font info BH(%02x) was discarded\n",BH
);
2784 // Set byte/char of on screen font
2785 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2787 // Set Highest char row
2788 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2791 // --------------------------------------------------------------------------------------------
2793 biosfn_get_ega_info
:
2796 mov ax
, # BIOSMEM_SEG
2799 mov bx
, # BIOSMEM_SWITCHES
2802 mov bx
, # BIOSMEM_CRTC_ADDRESS
2805 cmp ax
, # VGAREG_MDA_CRTC_ADDRESS
2814 // --------------------------------------------------------------------------------------------
2815 static void biosfn_alternate_prtsc()
2822 // --------------------------------------------------------------------------------------------
2824 biosfn_select_vert_res
:
2826 ; res
: 00 200 lines
, 01 350 lines
, 02 400 lines
2832 mov ax
, # BIOSMEM_SEG
2834 mov bx
, # BIOSMEM_MODESET_CTL
2836 mov bx
, # BIOSMEM_SWITCHES
2847 mov bx
, #msg_vert_res
2855 ; reset modeset ctl bit
7 and set bit
4
2856 ; set switches bit
3-0 to
0x09
2865 ; reset modeset ctl bit
7 and bit
4
2866 ; set switches bit
3-0 to
0x09
2874 ; set modeset ctl bit
7 and reset bit
4
2875 ; set switches bit
3-0 to
0x08
2882 mov bx
, # BIOSMEM_MODESET_CTL
2884 mov bx
, # BIOSMEM_SWITCHES
2895 .ascii
"Select vert res (%02x) was discarded"
2896 .byte
0x0d,0x0a,0x00
2900 biosfn_enable_default_palette_loading
:
2907 mov ax
, # BIOSMEM_SEG
2909 mov bx
, # BIOSMEM_MODESET_CTL
2921 biosfn_enable_video_addressing
:
2928 mov dx
, # VGAREG_READ_MISC_OUTPUT
2932 mov dx
, # VGAREG_WRITE_MISC_OUTPUT
2940 biosfn_enable_grayscale_summing
:
2948 mov ax
, # BIOSMEM_SEG
2950 mov bx
, # BIOSMEM_MODESET_CTL
2962 biosfn_enable_cursor_emulation
:
2969 mov ax
, # BIOSMEM_SEG
2971 mov bx
, # BIOSMEM_MODESET_CTL
2983 // --------------------------------------------------------------------------------------------
2984 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2990 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2997 // --------------------------------------------------------------------------------------------
2998 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2999 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
3001 Bit16u newcurs
,oldcurs
,dummy
;
3004 // Read curs info for the page
3005 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
3007 // if row=0xff special case : use current cursor position
3009 {col
=oldcurs
&0x00ff;
3010 row
=(oldcurs
&0xff00)>>8;
3013 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
3014 biosfn_set_cursor_pos(page
,newcurs
);
3018 car
=read_byte(seg
,offset
++);
3020 attr
=read_byte(seg
,offset
++);
3022 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
3025 // Set back curs pos
3027 biosfn_set_cursor_pos(page
,oldcurs
);
3030 // --------------------------------------------------------------------------------------------
3034 je biosfn_read_display_code
3036 je biosfn_set_display_code
3041 biosfn_read_display_code
:
3044 mov ax
, # BIOSMEM_SEG
3046 mov bx
, # BIOSMEM_DCC_INDEX
3054 biosfn_set_display_code
:
3058 mov ax
, # BIOSMEM_SEG
3061 mov bx
, # BIOSMEM_DCC_INDEX
3067 mov bx
, #msg_alt_dcc
3080 .ascii
"Alternate Display code (%02x) was discarded"
3081 .byte
0x0d,0x0a,0x00
3085 // --------------------------------------------------------------------------------------------
3086 static void biosfn_read_state_info (BX
,ES
,DI
)
3087 Bit16u BX
;Bit16u ES
;Bit16u DI
;
3089 // Address of static functionality table
3090 write_word(ES
,DI
+0x00,&static_functionality
);
3091 write_word(ES
,DI
+0x02,0xC000);
3093 // Hard coded copy from BIOS area. Should it be cleaner ?
3094 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
3095 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
3097 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
3098 write_byte(ES
,DI
+0x26,0);
3099 write_byte(ES
,DI
+0x27,16);
3100 write_byte(ES
,DI
+0x28,0);
3101 write_byte(ES
,DI
+0x29,8);
3102 write_byte(ES
,DI
+0x2a,2);
3103 write_byte(ES
,DI
+0x2b,0);
3104 write_byte(ES
,DI
+0x2c,0);
3105 write_byte(ES
,DI
+0x31,3);
3106 write_byte(ES
,DI
+0x32,0);
3108 memsetb(ES
,DI
+0x33,0,13);
3111 // --------------------------------------------------------------------------------------------
3112 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3118 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3124 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
3131 // ============================================================================================
3135 // ============================================================================================
3137 // --------------------------------------------------------------------------------------------
3138 static Bit8u
find_vga_entry(mode
)
3142 for(i
=0;i
<=MODE_MAX
;i
++)
3143 if(vga_modes
[i
].svgamode
==mode
)
3150 /* =========================================================== */
3154 /* =========================================================== */
3156 // --------------------------------------------------------------------------------------------
3157 static void memsetb(seg
,offset
,value
,count
)
3172 mov cx
, 10[bp
] ; count
3175 mov ax
, 4[bp
] ; segment
3177 mov ax
, 6[bp
] ; offset
3179 mov al
, 8[bp
] ; value
3194 // --------------------------------------------------------------------------------------------
3195 static void memsetw(seg
,offset
,value
,count
)
3210 mov cx
, 10[bp
] ; count
3213 mov ax
, 4[bp
] ; segment
3215 mov ax
, 6[bp
] ; offset
3217 mov ax
, 8[bp
] ; value
3232 // --------------------------------------------------------------------------------------------
3233 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
3251 mov cx
, 12[bp
] ; count
3254 mov ax
, 4[bp
] ; dsegment
3256 mov ax
, 6[bp
] ; doffset
3258 mov ax
, 8[bp
] ; ssegment
3260 mov ax
, 10[bp
] ; soffset
3278 // --------------------------------------------------------------------------------------------
3279 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
3297 mov cx
, 12[bp
] ; count
3300 mov ax
, 4[bp
] ; dsegment
3302 mov ax
, 6[bp
] ; doffset
3304 mov ax
, 8[bp
] ; ssegment
3306 mov ax
, 10[bp
] ; soffset
3324 /* =========================================================== */
3326 * These functions where ripped from Kevin's rombios.c
3328 /* =========================================================== */
3330 // --------------------------------------------------------------------------------------------
3332 read_byte(seg
, offset
)
3342 mov ax
, 4[bp
] ; segment
3344 mov bx
, 6[bp
] ; offset
3346 ;; al
= return value (byte
)
3354 // --------------------------------------------------------------------------------------------
3356 read_word(seg
, offset
)
3366 mov ax
, 4[bp
] ; segment
3368 mov bx
, 6[bp
] ; offset
3370 ;; ax
= return value (word
)
3378 // --------------------------------------------------------------------------------------------
3380 write_byte(seg
, offset
, data
)
3392 mov ax
, 4[bp
] ; segment
3394 mov bx
, 6[bp
] ; offset
3395 mov al
, 8[bp
] ; data byte
3396 mov
[bx
], al
; write data byte
3405 // --------------------------------------------------------------------------------------------
3407 write_word(seg
, offset
, data
)
3419 mov ax
, 4[bp
] ; segment
3421 mov bx
, 6[bp
] ; offset
3422 mov ax
, 8[bp
] ; data word
3423 mov
[bx
], ax
; write data word
3432 // --------------------------------------------------------------------------------------------
3467 // --------------------------------------------------------------------------------------------
3489 // --------------------------------------------------------------------------------------------
3519 void unimplemented()
3521 printf("--> Unimplemented\n");
3526 printf("--> Unknown int10\n");
3530 // --------------------------------------------------------------------------------------------
3531 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3535 Bit8u c
, format_char
;
3537 unsigned format_width
, i
;
3539 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
3547 while (c
= read_byte(0xc000, s
)) {
3552 else if (in_format
) {
3553 if ( (c
>='0') && (c
<='9') ) {
3554 format_width
= (format_width
* 10) + (c
- '0');
3556 else if (c
== 'x') {
3557 arg_ptr
++; // increment to next arg
3558 arg
= read_word(arg_seg
, arg_ptr
);
3559 if (format_width
== 0)
3562 digit
= format_width
- 1;
3563 for (i
=0; i
<format_width
; i
++) {
3564 nibble
= (arg
>> (4 * digit
)) & 0x000f;
3566 outb(0x0500, nibble
+ '0');
3568 outb(0x0500, (nibble
- 10) + 'A');
3573 //else if (c == 'd') {
3593 // --------------------------------------------------------------------------------------------
3596 ;; DATA_SEG_DEFS_HERE
3600 .ascii
"vgabios ends here"
3604 ;; BLOCK_STRINGS_BEGIN