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
121 biosmem_initial_mode
= 0x10
122 biosmem_current_mode
= 0x49
123 biosmem_nb_cols
= 0x4a
124 biosmem_current_page
= 0x62
125 biosmem_crtc_address
= 0x63
126 biosmem_current_msr
= 0x65
127 biosmem_char_height
= 0x85
128 biosmem_video_ctl
= 0x87
129 biosmem_switches
= 0x88
130 biosmem_modeset_ctl
= 0x89
131 biosmem_dcc_index
= 0x8a
133 vgareg_mda_crtc_address
= 0x03b4
134 vgareg_actl_address
= 0x03c0
135 vgareg_actl_read_data
= 0x03c1
136 vgareg_write_misc_output
= 0x03c2
137 vgareg_sequ_address
= 0x03c4
138 vgareg_pel_mask
= 0x03c6
139 vgareg_dac_read_address
= 0x03c7
140 vgareg_dac_write_address
= 0x03c8
141 vgareg_dac_data
= 0x03c9
142 vgareg_read_misc_output
= 0x03cc
143 vgareg_grdc_address
= 0x03ce
144 vgareg_actl_reset
= 0x03da
167 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
169 .byte
0x40 /* BIOS extension length in units of 512 bytes */
174 jmp vgabios_init_func
177 .ascii
"Plex86/Bochs VGABios"
181 // Info from Bart Oldeman
200 .ascii
"(C) 2003 the LGPL VGABios developers Team"
205 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
211 .ascii
"Please visit :"
213 ;;.ascii
" . http://www.plex86.org"
215 .ascii
" . http://bochs.sourceforge.net"
217 .ascii
" . http://www.nongnu.org/vgabios"
223 ;; ============================================================================================
227 ;; ============================================================================================
233 ;; init basic bios vars
237 ;; init vbe functions
242 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
244 ;; display splash screen
245 call _display_splash_screen
247 ;; init video mode
and clear the screen
256 call _vbe_display_info
267 vgabios_int10_handler
:
282 call biosfn_get_video_mode
297 call biosfn_set_text_block_specifier
304 call biosfn_get_ega_info
309 call biosfn_enable_default_palette_loading
314 call biosfn_enable_video_addressing
319 call biosfn_enable_grayscale_summing
324 call biosfn_enable_cursor_emulation
339 ;; We have to set ds to access the right data segment
352 #include "vgatables.h"
353 #include "vgafonts.h"
356 * Boot time harware inits
360 ;; switch to color mode
and enable CPU access
480 lines
365 ;; more than
64k
3C4
/04
373 mov bx
, #msg_vga_init
381 .ascii
"VGABios $Id$"
385 // --------------------------------------------------------------------------------------------
387 * Boot time bios area inits
395 ;; init detected hardware BIOS Area
396 mov bx
, #biosmem_initial_mode
401 ;; Just
for the first int10 find its children
403 ;; the
default char height
404 mov bx
, #biosmem_char_height
409 mov bx
, #biosmem_video_ctl
413 ;; Set the basic screen we have
414 mov bx
, #biosmem_switches
418 ;; Set the basic modeset options
419 mov bx
, #biosmem_modeset_ctl
423 ;; Set the
default MSR
424 mov bx
, #biosmem_current_msr
432 // --------------------------------------------------------------------------------------------
434 * Boot time Splash screen
436 static void display_splash_screen()
440 // --------------------------------------------------------------------------------------------
445 static void display_info()
452 mov si
,#vgabios_version
455 ;;mov si
,#vgabios_copyright
456 ;;call _display_string
458 ;;call _display_string
460 mov si
,#vgabios_license
462 mov si
,#vgabios_website
467 static void display_string()
469 // Get length of string
496 // --------------------------------------------------------------------------------------------
498 static void int10_debugmsg(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
499 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
501 // 0E is write char...
503 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
507 // --------------------------------------------------------------------------------------------
509 * int10 main dispatcher
511 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
512 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
519 biosfn_set_video_mode(GET_AL());
520 switch(GET_AL()&0x7F)
538 biosfn_set_cursor_shape(GET_CH(),GET_CL());
541 biosfn_set_cursor_pos(GET_BH(),DX
);
544 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
547 // Read light pen pos (unimplemented)
557 biosfn_set_active_page(GET_AL());
560 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
563 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
566 biosfn_read_char_attr(GET_BH(),&AX
);
569 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
572 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
575 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
578 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
581 // Ralf Brown Interrupt list is WRONG on bh(page)
582 // We do output only on the current page !
583 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
586 // All other functions of group AH=0x10 rewritten in assembler
587 biosfn_perform_gray_scale_summing(BX
,CX
);
594 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
598 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
602 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
606 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
609 biosfn_load_gfx_8_8_chars(ES
,BP
);
612 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
615 biosfn_load_gfx_8_14_chars(GET_BL());
618 biosfn_load_gfx_8_8_dd_chars(GET_BL());
621 biosfn_load_gfx_8_16_chars(GET_BL());
624 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
637 biosfn_alternate_prtsc();
640 biosfn_select_vert_res(GET_AL());
644 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
648 biosfn_enable_video_refresh_control(GET_AL());
658 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
661 biosfn_read_state_info(BX
,ES
,DI
);
668 biosfn_read_video_state_size(CX
,&BX
);
671 biosfn_save_video_state(CX
,ES
,BX
);
674 biosfn_restore_video_state(CX
,ES
,BX
);
686 if (vbe_has_vbe_display()) {
690 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
693 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
696 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
699 vbe_biosfn_return_current_mode(&AX
,&BX
);
710 vbe_biosfn_display_window_control(&AX
,BX
,&DX
);
713 vbe_biosfn_set_get_logical_scan_line_length(&AX
,&BX
,&CX
,&DX
);
716 vbe_biosfn_set_get_display_start(&AX
,BX
,CX
,DX
);
764 // ============================================================================================
768 // ============================================================================================
770 static void biosfn_set_video_mode(mode
) Bit8u mode
;
771 {// mode: Bit 7 is 1 if no clear screen
773 // Should we clear the screen ?
774 Bit8u noclearmem
=mode
&0x80;
775 Bit8u line
,mmask
,*palette
;
776 Bit16u i
,twidth
,theight
,cheight
;
777 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
781 if (vbe_has_vbe_display()) {
782 dispi_set_enable(VBE_DISPI_DISABLED
);
789 // find the entry in the video modes
790 line
=find_vga_entry(mode
);
793 printf("mode search %02x found line %02x\n",mode
,line
);
799 twidth
=vga_modes
[line
].twidth
;
800 theight
=vga_modes
[line
].theight
;
801 cheight
=vga_modes
[line
].cheight
;
803 // Read the bios vga control
804 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
806 // Read the bios vga switches
807 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
809 // Read the bios mode set control
810 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
812 // Then we know the number of lines
815 // if palette loading (bit 3 of modeset ctl = 0)
816 if((modeset_ctl
&0x08)==0)
818 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
820 // Set the whole dac always, from 0
821 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
823 // From which palette
824 switch(vga_modes
[line
].dacmodel
)
838 // Always 256*3 values
839 for(i
=0;i
<0x0100;i
++)
840 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
841 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
842 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
843 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
846 {outb(VGAREG_DAC_DATA
,0);
847 outb(VGAREG_DAC_DATA
,0);
848 outb(VGAREG_DAC_DATA
,0);
851 if((modeset_ctl
&0x02)==0x02)
853 biosfn_perform_gray_scale_summing(0x00, 0x100);
857 // Reset Attribute Ctl flip-flop
858 inb(VGAREG_ACTL_RESET
);
861 for(i
=0;i
<=ACTL_MAX_REG
;i
++)
862 {outb(VGAREG_ACTL_ADDRESS
,i
);
863 outb(VGAREG_ACTL_WRITE_DATA
,actl_regs
[vga_modes
[line
].actlmodel
][i
]);
867 for(i
=0;i
<=SEQU_MAX_REG
;i
++)
868 {outb(VGAREG_SEQU_ADDRESS
,i
);
869 outb(VGAREG_SEQU_DATA
,sequ_regs
[vga_modes
[line
].sequmodel
][i
]);
873 for(i
=0;i
<=GRDC_MAX_REG
;i
++)
874 {outb(VGAREG_GRDC_ADDRESS
,i
);
875 outb(VGAREG_GRDC_DATA
,grdc_regs
[vga_modes
[line
].grdcmodel
][i
]);
878 // Set CRTC address VGA or MDA
879 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
882 for(i
=0;i
<=CRTC_MAX_REG
;i
++)
884 outb(crtc_addr
+1,crtc_regs
[vga_modes
[line
].crtcmodel
][i
]);
887 // Set the misc register
888 outb(VGAREG_WRITE_MISC_OUTPUT
,vga_modes
[line
].miscreg
);
891 outb(VGAREG_ACTL_ADDRESS
,0x20);
892 inb(VGAREG_ACTL_RESET
);
896 if(vga_modes
[line
].class==TEXT
)
898 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
904 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
908 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
909 mmask
= inb( VGAREG_SEQU_DATA
);
910 outb( VGAREG_SEQU_DATA
, 0x0f ); // all planes
911 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x8000); // 64k
912 outb( VGAREG_SEQU_DATA
, mmask
);
918 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
,mode
);
919 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
,twidth
);
920 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
,vga_modes
[line
].slength
);
921 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
922 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theight
-1);
923 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,cheight
);
924 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,(0x60|noclearmem
));
925 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
926 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)&0x7f);
928 // FIXME We nearly have the good tables. to be reworked
929 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,0x08); // 8 is VGA should be ok for now
930 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
,0x00);
931 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2,0x00);
934 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x00); // Unavailable on vanilla vga, but...
935 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAL
,0x00); // Unavailable on vanilla vga, but...
938 if(vga_modes
[line
].class==TEXT
)
940 biosfn_set_cursor_shape(0x06,0x07);
943 // Set cursor pos for page 0..7
945 biosfn_set_cursor_pos(i
,0x0000);
948 biosfn_set_active_page(0x00);
950 // Write the fonts in memory
951 if(vga_modes
[line
].class==TEXT
)
954 ;; copy
and activate
8x16 font
964 // Set the ints 0x1F and 0x43
966 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
972 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
977 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
982 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
988 // --------------------------------------------------------------------------------------------
989 static void biosfn_set_cursor_shape (CH
,CL
)
991 {Bit16u cheight
,curs
,crtc_addr
;
998 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
1000 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
1001 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
1002 if((modeset_ctl
&0x01) && (cheight
>8) && (CL
<8) && (CH
<0x20))
1006 CH
= ((CH
+1) * cheight
/ 8) -1;
1010 CH
= ((CL
+1) * cheight
/ 8) - 2;
1012 CL
= ((CL
+1) * cheight
/ 8) - 1;
1015 // CTRC regs 0x0a and 0x0b
1016 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1017 outb(crtc_addr
,0x0a);
1018 outb(crtc_addr
+1,CH
);
1019 outb(crtc_addr
,0x0b);
1020 outb(crtc_addr
+1,CL
);
1023 // --------------------------------------------------------------------------------------------
1024 static void biosfn_set_cursor_pos (page
, cursor
)
1025 Bit8u page
;Bit16u cursor
;
1027 Bit8u xcurs
,ycurs
,current
;
1028 Bit16u nbcols
,nbrows
,address
,crtc_addr
;
1030 // Should not happen...
1034 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1036 // Set the hardware cursor
1037 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1040 // Get the dimensions
1041 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1042 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1044 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1046 // Calculate the address knowing nbcols nbrows and page num
1047 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1049 // CRTC regs 0x0e and 0x0f
1050 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1051 outb(crtc_addr
,0x0e);
1052 outb(crtc_addr
+1,(address
&0xff00)>>8);
1053 outb(crtc_addr
,0x0f);
1054 outb(crtc_addr
+1,address
&0x00ff);
1058 // --------------------------------------------------------------------------------------------
1059 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1060 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1065 write_word(ss
, shape
, 0);
1066 write_word(ss
, pos
, 0);
1069 // FIXME should handle VGA 14/16 lines
1070 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1071 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1074 // --------------------------------------------------------------------------------------------
1075 static void biosfn_set_active_page (page
)
1078 Bit16u cursor
,dummy
,crtc_addr
;
1079 Bit16u nbcols
,nbrows
,address
;
1085 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1086 line
=find_vga_entry(mode
);
1087 if(line
==0xFF)return;
1089 // Get pos curs pos for the right page
1090 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1092 if(vga_modes
[line
].class==TEXT
)
1094 // Get the dimensions
1095 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1096 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1098 // Calculate the address knowing nbcols nbrows and page num
1099 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1100 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1103 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1107 address
= page
*vga_modes
[line
].slength
;
1110 // CRTC regs 0x0c and 0x0d
1111 crtc_addr
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
1112 outb(crtc_addr
,0x0c);
1113 outb(crtc_addr
+1,(address
&0xff00)>>8);
1114 outb(crtc_addr
,0x0d);
1115 outb(crtc_addr
+1,address
&0x00ff);
1117 // And change the BIOS page
1118 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1121 printf("Set active page %02x address %04x\n",page
,address
);
1124 // Display the cursor, now the page is active
1125 biosfn_set_cursor_pos(page
,cursor
);
1128 // --------------------------------------------------------------------------------------------
1129 static void vgamem_copy_pl4(xstart
,ysrc
,ydest
,cols
,nbcols
,cheight
)
1130 Bit8u xstart
;Bit8u ysrc
;Bit8u ydest
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1135 src
=ysrc
*cheight
*nbcols
+xstart
;
1136 dest
=ydest
*cheight
*nbcols
+xstart
;
1137 outw(VGAREG_GRDC_ADDRESS
, 0x0105);
1138 for(i
=0;i
<cheight
;i
++)
1140 memcpyb(0xa000,dest
+i
*nbcols
,0xa000,src
+i
*nbcols
,cols
);
1142 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1145 // --------------------------------------------------------------------------------------------
1146 static void vgamem_fill_pl4(xstart
,ystart
,cols
,nbcols
,cheight
)
1147 Bit8u xstart
;Bit8u ystart
;Bit8u cols
;Bit8u nbcols
;Bit8u cheight
;
1152 dest
=ystart
*cheight
*nbcols
+xstart
;
1153 for(i
=0;i
<cheight
;i
++)
1155 memsetb(0xa000,dest
+i
*nbcols
,0x00,cols
);
1159 // --------------------------------------------------------------------------------------------
1160 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1161 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1163 // page == 0xFF if current
1165 Bit8u mode
,line
,cheight
;
1166 Bit16u nbcols
,nbrows
,i
;
1173 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1174 line
=find_vga_entry(mode
);
1175 if(line
==0xFF)return;
1177 // Get the dimensions
1178 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1179 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1181 // Get the current page
1183 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1185 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1186 if(clr
>=nbcols
)clr
=nbcols
-1;
1187 if(nblines
>nbrows
)nblines
=0;
1189 if(vga_modes
[line
].class==TEXT
)
1191 // Compute the address
1192 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1194 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1197 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1199 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1204 {for(i
=rul
;i
<=rlr
;i
++)
1206 if((i
+nblines
>rlr
)||(nblines
==0))
1207 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1209 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1213 {for(i
=rlr
;i
>=rul
;i
--)
1215 if((i
<rul
+nblines
)||(nblines
==0))
1216 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1218 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1225 // FIXME gfx mode not complete
1226 cheight
=vga_modes
[line
].cheight
;
1227 if((vga_modes
[line
].memmodel
==PLANAR4
)||(vga_modes
[line
].memmodel
==PLANAR1
))
1229 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1231 memsetb(vga_modes
[line
].sstart
,0,0x00,nbrows
*nbcols
*cheight
);
1236 {for(i
=rul
;i
<=rlr
;i
++)
1238 if((i
+nblines
>rlr
)||(nblines
==0))
1239 vgamem_fill_pl4(cul
,i
,clr
-cul
+1,nbcols
,cheight
);
1241 vgamem_copy_pl4(cul
,i
+nblines
,i
,clr
-cul
+1,nbcols
,cheight
);
1245 {for(i
=rlr
;i
>=rul
;i
--)
1247 if((i
<rul
+nblines
)||(nblines
==0))
1248 vgamem_fill_pl4(cul
,i
,clr
-cul
+1,nbcols
,cheight
);
1250 vgamem_copy_pl4(cul
,i
,i
-nblines
,clr
-cul
+1,nbcols
,cheight
);
1258 printf("Scroll in graphics mode ");
1265 // --------------------------------------------------------------------------------------------
1266 static void biosfn_read_char_attr (page
,car
)
1267 Bit8u page
;Bit16u
*car
;
1268 {Bit16u ss
=get_SS();
1269 Bit8u xcurs
,ycurs
,mode
,line
;
1270 Bit16u nbcols
,nbrows
,address
;
1271 Bit16u cursor
,dummy
;
1274 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1275 line
=find_vga_entry(mode
);
1276 if(line
==0xFF)return;
1278 // Get the cursor pos for the page
1279 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1280 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1282 // Get the dimensions
1283 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1284 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1286 if(vga_modes
[line
].class==TEXT
)
1288 // Compute the address
1289 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1291 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1302 // --------------------------------------------------------------------------------------------
1303 static void write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1304 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1308 Bit16u addr
,dest
,src
;
1320 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1321 src
= car
* cheight
;
1322 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1325 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1327 for(i
=0;i
<cheight
;i
++)
1333 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1334 read_byte(0xa000,dest
);
1335 if(fdata
[src
+i
]&mask
)
1337 write_byte(0xa000,dest
,attr
&0x0f);
1341 write_byte(0xa000,dest
,0x00);
1346 mov dx
, #vgareg_grdc_address
1356 // --------------------------------------------------------------------------------------------
1357 static void write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
)
1358 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u bpp
;
1360 Bit8u i
,j
,mask
,data
;
1362 Bit16u addr
,dest
,src
;
1365 addr
=(xcurs
*bpp
)+ycurs
*320;
1369 dest
=addr
+(i
>>1)*80;
1370 if (i
& 1) dest
+= 0x2000;
1376 data
= read_byte(0xb800,dest
);
1384 if (fdata
[src
+i
] & mask
)
1388 data
^= (attr
& 0x01) << (7-j
);
1392 data
|= (attr
& 0x01) << (7-j
);
1397 write_byte(0xb800,dest
,data
);
1405 data
= read_byte(0xb800,dest
);
1413 if (fdata
[src
+i
] & mask
)
1417 data
^= (attr
& 0x03) << ((3-j
)*2);
1421 data
|= (attr
& 0x03) << ((3-j
)*2);
1426 write_byte(0xb800,dest
,data
);
1433 // --------------------------------------------------------------------------------------------
1434 static void write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
)
1435 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;
1437 Bit8u i
,j
,mask
,data
;
1439 Bit16u addr
,dest
,src
;
1442 addr
=xcurs
*8+ycurs
*nbcols
*64;
1446 dest
=addr
+i
*nbcols
*8;
1451 if (fdata
[src
+i
] & mask
)
1455 write_byte(0xa000,dest
+j
,data
);
1461 // --------------------------------------------------------------------------------------------
1462 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1463 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1465 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1466 Bit16u nbcols
,nbrows
,address
;
1467 Bit16u cursor
,dummy
;
1470 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1471 line
=find_vga_entry(mode
);
1472 if(line
==0xFF)return;
1474 // Get the cursor pos for the page
1475 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1476 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1478 // Get the dimensions
1479 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1480 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1482 if(vga_modes
[line
].class==TEXT
)
1484 // Compute the address
1485 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1487 dummy
=((Bit16u
)attr
<<8)+car
;
1488 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1492 // FIXME gfx mode not complete
1493 cheight
=vga_modes
[line
].cheight
;
1494 bpp
=vga_modes
[line
].pixbits
;
1495 while((count
-->0) && (xcurs
<nbcols
))
1497 if((vga_modes
[line
].memmodel
==PLANAR4
)||(vga_modes
[line
].memmodel
==PLANAR1
))
1499 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1501 else if(vga_modes
[line
].memmodel
==CGA
)
1503 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1505 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1507 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1520 // --------------------------------------------------------------------------------------------
1521 static void biosfn_write_char_only (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;
1547 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1553 // FIXME gfx mode not complete
1554 cheight
=vga_modes
[line
].cheight
;
1555 bpp
=vga_modes
[line
].pixbits
;
1556 while((count
-->0) && (xcurs
<nbcols
))
1558 if((vga_modes
[line
].memmodel
==PLANAR4
)||(vga_modes
[line
].memmodel
==PLANAR1
))
1560 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1562 else if(vga_modes
[line
].memmodel
==CGA
)
1564 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1566 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1568 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1581 // --------------------------------------------------------------------------------------------
1585 je biosfn_set_border_color
1587 je biosfn_set_palette
1592 biosfn_set_border_color
:
1597 mov dx
, #vgareg_actl_reset
1599 mov dx
, #vgareg_actl_address
1612 mov dx
, #vgareg_actl_address
1615 mov dx
, #vgareg_actl_read_data
1619 mov dx
, #vgareg_actl_address
1623 jne set_intensity_loop
1636 mov dx
, #vgareg_actl_reset
1640 set_cga_palette_loop
:
1641 mov dx
, #vgareg_actl_address
1644 mov dx
, #vgareg_actl_read_data
1648 mov dx
, #vgareg_actl_address
1652 jne set_cga_palette_loop
1662 // --------------------------------------------------------------------------------------------
1663 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1665 Bit8u mode
,line
,mask
,attr
,data
;
1669 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1670 line
=find_vga_entry(mode
);
1671 if(line
==0xFF)return;
1672 if(vga_modes
[line
].class==TEXT
)return;
1674 switch(vga_modes
[line
].memmodel
)
1678 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1679 mask
= 0x01 << (7 - (CX
& 0x07));
1680 outw(VGAREG_GRDC_ADDRESS
, (mask
<< 8) | 0x08);
1681 outw(VGAREG_GRDC_ADDRESS
, 0x0205);
1682 data
= read_byte(0xa000,addr
);
1685 outw(VGAREG_GRDC_ADDRESS
, 0x1803);
1687 write_byte(0xa000,addr
,AL
);
1688 outw(VGAREG_GRDC_ADDRESS
, 0xff08);
1689 outw(VGAREG_GRDC_ADDRESS
, 0x0005);
1690 outw(VGAREG_GRDC_ADDRESS
, 0x0003);
1693 if(vga_modes
[line
].pixbits
==2)
1695 addr
=(CX
>>2)+(DX
>>1)*80;
1699 addr
=(CX
>>3)+(DX
>>1)*80;
1701 if (DX
& 1) addr
+= 0x2000;
1702 data
= read_byte(0xb800,addr
);
1703 if(vga_modes
[line
].pixbits
==2)
1705 attr
= (AL
& 0x03) << ((3 - (CX
& 0x03)) * 2);
1706 mask
= 0x03 << ((3 - (CX
& 0x03)) * 2);
1710 attr
= (AL
& 0x01) << (7 - (CX
& 0x07));
1711 mask
= 0x01 << (7 - (CX
& 0x07));
1722 write_byte(0xb800,addr
,data
);
1725 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1726 write_byte(0xa000,addr
,AL
);
1735 // --------------------------------------------------------------------------------------------
1736 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1738 Bit8u mode
,line
,mask
,attr
,data
,i
;
1743 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1744 line
=find_vga_entry(mode
);
1745 if(line
==0xFF)return;
1746 if(vga_modes
[line
].class==TEXT
)return;
1748 switch(vga_modes
[line
].memmodel
)
1752 addr
= CX
/8+DX
*read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1753 mask
= 0x01 << (7 - (CX
& 0x07));
1757 outw(VGAREG_GRDC_ADDRESS
, (i
<< 8) | 0x04);
1758 data
= read_byte(0xa000,addr
) & mask
;
1759 if (data
> 0) attr
|= (0x01 << i
);
1763 addr
=(CX
>>2)+(DX
>>1)*80;
1764 if (DX
& 1) addr
+= 0x2000;
1765 data
= read_byte(0xb800,addr
);
1766 if(vga_modes
[line
].pixbits
==2)
1768 attr
= (data
>> ((3 - (CX
& 0x03)) * 2)) & 0x03;
1772 attr
= (data
>> (7 - (CX
& 0x07))) & 0x01;
1776 addr
=CX
+DX
*(read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
)*8);
1777 attr
=read_byte(0xa000,addr
);
1785 write_word(ss
,AX
,(read_word(ss
,AX
) & 0xff00) | attr
);
1788 // --------------------------------------------------------------------------------------------
1789 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1790 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1791 {// flag = WITH_ATTR / NO_ATTR
1793 Bit8u cheight
,xcurs
,ycurs
,mode
,line
,bpp
;
1794 Bit16u nbcols
,nbrows
,address
;
1795 Bit16u cursor
,dummy
;
1797 // special case if page is 0xff, use current page
1799 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1802 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1803 line
=find_vga_entry(mode
);
1804 if(line
==0xFF)return;
1806 // Get the cursor pos for the page
1807 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1808 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1810 // Get the dimensions
1811 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1812 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1836 biosfn_write_teletype(' ',page
,attr
,flag
);
1837 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1838 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1844 if(vga_modes
[line
].class==TEXT
)
1846 // Compute the address
1847 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1850 write_byte(vga_modes
[line
].sstart
,address
,car
);
1853 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1857 // FIXME gfx mode not complete
1858 cheight
=vga_modes
[line
].cheight
;
1859 bpp
=vga_modes
[line
].pixbits
;
1860 if((vga_modes
[line
].memmodel
==PLANAR4
)||(vga_modes
[line
].memmodel
==PLANAR1
))
1862 write_gfx_char_pl4(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1864 else if(vga_modes
[line
].memmodel
==CGA
)
1866 write_gfx_char_cga(car
,attr
,xcurs
,ycurs
,nbcols
,bpp
);
1868 else if(vga_modes
[line
].memmodel
==LINEAR8
)
1870 write_gfx_char_lin(car
,attr
,xcurs
,ycurs
,nbcols
);
1883 // Do we need to wrap ?
1889 // Do we need to scroll ?
1891 {biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1895 // Set the cursor for the page
1896 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1897 biosfn_set_cursor_pos(page
,cursor
);
1900 // --------------------------------------------------------------------------------------------
1902 biosfn_get_video_mode
:
1904 mov ax
, #biosmem_seg
1907 mov bx
, #biosmem_current_page
1912 mov bx
, #biosmem_video_ctl
1915 mov bx
, #biosmem_current_mode
1918 mov bx
, #biosmem_nb_cols
1925 // --------------------------------------------------------------------------------------------
1930 jmp biosfn_set_single_palette_reg
1934 jmp biosfn_set_overscan_border_color
1938 jmp biosfn_set_all_palette_reg
1942 jmp biosfn_toggle_intensity
1946 jmp biosfn_get_single_palette_reg
1950 jmp biosfn_read_overscan_border_color
1954 jmp biosfn_get_all_palette_reg
1958 jmp biosfn_set_single_dac_reg
1962 jmp biosfn_set_all_dac_reg
1966 jmp biosfn_select_video_dac_color_page
1970 jmp biosfn_read_single_dac_reg
1974 jmp biosfn_read_all_dac_reg
1978 jmp biosfn_set_pel_mask
1982 jmp biosfn_read_pel_mask
1985 jne int10_group_10_unknown
1986 jmp biosfn_read_video_dac_state
1987 int10_group_10_unknown
:
1993 biosfn_set_single_palette_reg
:
1998 mov dx
, #vgareg_actl_reset
2000 mov dx
, #vgareg_actl_address
2013 // --------------------------------------------------------------------------------------------
2015 biosfn_set_overscan_border_color
:
2018 call biosfn_set_single_palette_reg
2023 // --------------------------------------------------------------------------------------------
2025 biosfn_set_all_palette_reg
:
2031 mov dx
, #vgareg_actl_reset
2034 mov dx
, #vgareg_actl_address
2044 jne set_palette_loop
2059 // --------------------------------------------------------------------------------------------
2061 biosfn_toggle_intensity
:
2065 mov dx
, #vgareg_actl_reset
2067 mov dx
, #vgareg_actl_address
2070 mov dx
, #vgareg_actl_read_data
2076 mov dx
, #vgareg_actl_address
2086 // --------------------------------------------------------------------------------------------
2088 biosfn_get_single_palette_reg
:
2093 mov dx
, #vgareg_actl_reset
2095 mov dx
, #vgareg_actl_address
2098 mov dx
, #vgareg_actl_read_data
2101 mov dx
, #vgareg_actl_reset
2103 mov dx
, #vgareg_actl_address
2112 // --------------------------------------------------------------------------------------------
2114 biosfn_read_overscan_border_color
:
2118 call biosfn_get_single_palette_reg
2126 // --------------------------------------------------------------------------------------------
2128 biosfn_get_all_palette_reg
:
2136 mov dx
, #vgareg_actl_reset
2138 mov dx
, #vgareg_actl_address
2141 mov dx
, #vgareg_actl_read_data
2148 jne get_palette_loop
2149 mov dx
, #vgareg_actl_reset
2151 mov dx
, #vgareg_actl_address
2154 mov dx
, #vgareg_actl_read_data
2158 mov dx
, #vgareg_actl_reset
2160 mov dx
, #vgareg_actl_address
2170 // --------------------------------------------------------------------------------------------
2172 biosfn_set_single_dac_reg
:
2175 mov dx
, #vgareg_dac_write_address
2178 mov dx
, #vgareg_dac_data
2192 // --------------------------------------------------------------------------------------------
2194 biosfn_set_all_dac_reg
:
2199 mov dx
, #vgareg_dac_write_address
2205 mov dx
, #vgareg_dac_data
2228 // --------------------------------------------------------------------------------------------
2230 biosfn_select_video_dac_color_page
:
2234 mov dx
, #vgareg_actl_reset
2236 mov dx
, #vgareg_actl_address
2239 mov dx
, #vgareg_actl_read_data
2246 mov dx
, #vgareg_actl_address
2251 mov dx
, #vgareg_actl_reset
2253 mov dx
, #vgareg_actl_address
2273 // --------------------------------------------------------------------------------------------
2275 biosfn_read_single_dac_reg
:
2278 mov dx
, #vgareg_dac_read_address
2283 mov dx
, #vgareg_dac_data
2296 // --------------------------------------------------------------------------------------------
2298 biosfn_read_all_dac_reg
:
2303 mov dx
, #vgareg_dac_read_address
2309 mov dx
, #vgareg_dac_data
2332 // --------------------------------------------------------------------------------------------
2334 biosfn_set_pel_mask
:
2337 mov dx
, #vgareg_pel_mask
2345 // --------------------------------------------------------------------------------------------
2347 biosfn_read_pel_mask
:
2350 mov dx
, #vgareg_pel_mask
2358 // --------------------------------------------------------------------------------------------
2360 biosfn_read_video_dac_state
:
2363 mov dx
, #vgareg_actl_reset
2365 mov dx
, #vgareg_actl_address
2368 mov dx
, #vgareg_actl_read_data
2372 mov dx
, #vgareg_actl_reset
2374 mov dx
, #vgareg_actl_address
2377 mov dx
, #vgareg_actl_read_data
2385 mov dx
, #vgareg_actl_reset
2387 mov dx
, #vgareg_actl_address
2395 // --------------------------------------------------------------------------------------------
2396 static void biosfn_perform_gray_scale_summing (start
,count
)
2397 Bit16u start
;Bit16u count
;
2402 inb(VGAREG_ACTL_RESET
);
2403 outb(VGAREG_ACTL_ADDRESS
,0x00);
2405 for( index
= 0; index
< count
; index
++ )
2407 // set read address and switch to read mode
2408 outb(VGAREG_DAC_READ_ADDRESS
,start
);
2409 // get 6-bit wide RGB data values
2410 r
=inb( VGAREG_DAC_DATA
);
2411 g
=inb( VGAREG_DAC_DATA
);
2412 b
=inb( VGAREG_DAC_DATA
);
2414 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2415 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
2419 // set write address and switch to write mode
2420 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
2421 // write new intensity value
2422 outb( VGAREG_DAC_DATA
, i
&0xff );
2423 outb( VGAREG_DAC_DATA
, i
&0xff );
2424 outb( VGAREG_DAC_DATA
, i
&0xff );
2427 inb(VGAREG_ACTL_RESET
);
2428 outb(VGAREG_ACTL_ADDRESS
,0x20);
2431 // --------------------------------------------------------------------------------------------
2432 static void get_font_access()
2435 mov dx
, #vgareg_sequ_address
2444 mov dx
, #vgareg_grdc_address
2454 static void release_font_access()
2457 mov dx
, #vgareg_sequ_address
2466 mov dx
, #vgareg_read_misc_output
2473 mov dx
, #vgareg_grdc_address
2489 static void set_scan_lines(lines
) Bit8u lines
;
2491 Bit16u crtc_addr
,cols
,page
,vde
;
2492 Bit8u crtc_r9
,ovl
,rows
;
2494 crtc_addr
= read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2495 outb(crtc_addr
, 0x09);
2496 crtc_r9
= inb(crtc_addr
+1);
2497 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
2498 outb(crtc_addr
+1, crtc_r9
);
2501 biosfn_set_cursor_shape(0x06,0x07);
2505 biosfn_set_cursor_shape(lines
-4,lines
-3);
2507 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
2508 outb(crtc_addr
, 0x12);
2509 vde
= inb(crtc_addr
+1);
2510 outb(crtc_addr
, 0x07);
2511 ovl
= inb(crtc_addr
+1);
2512 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
2514 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
2515 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
2516 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
2519 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
;
2521 Bit16u blockaddr
,dest
,i
,src
;
2524 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2528 dest
= blockaddr
+ (DX
+ i
) * 32;
2529 memcpyb(0xA000, dest
, ES
, src
, BH
);
2531 release_font_access();
2538 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2540 Bit16u blockaddr
,dest
,i
,src
;
2543 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2544 for(i
=0;i
<0x100;i
++)
2547 dest
= blockaddr
+ i
* 32;
2548 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
2550 release_font_access();
2557 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2559 Bit16u blockaddr
,dest
,i
,src
;
2562 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2563 for(i
=0;i
<0x100;i
++)
2566 dest
= blockaddr
+ i
* 32;
2567 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
2569 release_font_access();
2576 // --------------------------------------------------------------------------------------------
2578 biosfn_set_text_block_specifier
:
2581 mov dx
, #vgareg_sequ_address
2590 // --------------------------------------------------------------------------------------------
2591 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
2593 Bit16u blockaddr
,dest
,i
,src
;
2596 blockaddr
= ((BL
& 0x03) << 14) + ((BL
& 0x04) << 11);
2597 for(i
=0;i
<0x100;i
++)
2600 dest
= blockaddr
+ i
* 32;
2601 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
2603 release_font_access();
2610 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
2616 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
2622 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
2628 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
2634 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
2640 // --------------------------------------------------------------------------------------------
2641 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
2642 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
2643 {Bit16u ss
=get_SS();
2647 write_word(ss
,ES
,read_word(0x00,0x1f*4));
2648 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
2651 write_word(ss
,ES
,read_word(0x00,0x43*4));
2652 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
2655 write_word(ss
,ES
,0xC000);
2656 write_word(ss
,BP
,vgafont14
);
2659 write_word(ss
,ES
,0xC000);
2660 write_word(ss
,BP
,vgafont8
);
2663 write_word(ss
,ES
,0xC000);
2664 write_word(ss
,BP
,vgafont8
+128*8);
2667 write_word(ss
,ES
,0xC000);
2668 write_word(ss
,BP
,vgafont14alt
);
2671 write_word(ss
,ES
,0xC000);
2672 write_word(ss
,BP
,vgafont16
);
2675 write_word(ss
,ES
,0xC000);
2676 write_word(ss
,BP
,vgafont16alt
);
2680 printf("Get font info BH(%02x) was discarded\n",BH
);
2684 // Set byte/char of on screen font
2685 write_word(ss
,CX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2687 // Set Highest char row
2688 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2691 // --------------------------------------------------------------------------------------------
2693 biosfn_get_ega_info
:
2696 mov ax
, #biosmem_seg
2699 mov bx
, #biosmem_switches
2702 mov bx
, #biosmem_crtc_address
2705 cmp ax
, #vgareg_mda_crtc_address
2714 // --------------------------------------------------------------------------------------------
2715 static void biosfn_alternate_prtsc()
2722 // --------------------------------------------------------------------------------------------
2723 static void biosfn_select_vert_res (res
)
2725 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2726 Bit8u modeset
,switches
;
2728 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2729 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2732 // set modeset ctl bit 7 and reset bit 4
2733 // set switches bit 3-0 to 0x08
2734 modeset
|=0x80;modeset
&=0xef;
2735 switches
&=0xf0;switches
|=0x08;
2738 // reset modeset ctl bit 7 and bit 4
2739 // set switches bit 3-0 to 0x09
2741 switches
&=0xf0;switches
|=0x09;
2744 // reset modeset ctl bit 7 and set bit 4
2745 // set switches bit 3-0 to 0x09
2746 modeset
|=0x10;modeset
&=0x7f;
2747 switches
&=0xf0;switches
|=0x09;
2751 printf("Select vert res (%02x) was discarded\n",res
);
2755 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2756 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,switches
);
2759 // --------------------------------------------------------------------------------------------
2761 biosfn_enable_default_palette_loading
:
2768 mov ax
, #biosmem_seg
2770 mov bx
, #biosmem_modeset_ctl
2782 // --------------------------------------------------------------------------------------------
2784 biosfn_enable_video_addressing
:
2791 mov dx
, #vgareg_read_misc_output
2795 mov dx
, #vgareg_write_misc_output
2803 // --------------------------------------------------------------------------------------------
2805 biosfn_enable_grayscale_summing
:
2813 mov ax
, #biosmem_seg
2815 mov bx
, #biosmem_modeset_ctl
2827 // --------------------------------------------------------------------------------------------
2829 biosfn_enable_cursor_emulation
:
2836 mov ax
, #biosmem_seg
2838 mov bx
, #biosmem_modeset_ctl
2850 // --------------------------------------------------------------------------------------------
2851 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2857 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2864 // --------------------------------------------------------------------------------------------
2865 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2866 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2868 Bit16u newcurs
,oldcurs
,dummy
;
2871 // Read curs info for the page
2872 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2874 // if row=0xff special case : use current cursor position
2876 {col
=oldcurs
&0x00ff;
2877 row
=(oldcurs
&0xff00)>>8;
2880 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
2881 biosfn_set_cursor_pos(page
,newcurs
);
2885 car
=read_byte(seg
,offset
++);
2887 attr
=read_byte(seg
,offset
++);
2889 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
2892 // Set back curs pos
2894 biosfn_set_cursor_pos(page
,oldcurs
);
2897 // --------------------------------------------------------------------------------------------
2901 je biosfn_read_display_code
2903 je biosfn_set_display_code
2908 biosfn_read_display_code
:
2911 mov ax
, #biosmem_seg
2913 mov bx
, #biosmem_dcc_index
2921 biosfn_set_display_code
:
2925 mov ax
, #biosmem_seg
2928 mov bx
, #biosmem_dcc_index
2934 mov bx
, #msg_alt_dcc
2947 .ascii
"Alternate Display code (%02x) was discarded"
2948 .byte
0x0d,0x0a,0x00
2952 // --------------------------------------------------------------------------------------------
2953 static void biosfn_read_state_info (BX
,ES
,DI
)
2954 Bit16u BX
;Bit16u ES
;Bit16u DI
;
2956 // Address of static functionality table
2957 write_word(ES
,DI
+0x00,&static_functionality
);
2958 write_word(ES
,DI
+0x02,0xC000);
2960 // Hard coded copy from BIOS area. Should it be cleaner ?
2961 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
2962 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
2964 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2965 write_byte(ES
,DI
+0x26,0);
2966 write_byte(ES
,DI
+0x27,16);
2967 write_byte(ES
,DI
+0x28,0);
2968 write_byte(ES
,DI
+0x29,8);
2969 write_byte(ES
,DI
+0x2a,2);
2970 write_byte(ES
,DI
+0x2b,0);
2971 write_byte(ES
,DI
+0x2c,0);
2972 write_byte(ES
,DI
+0x31,3);
2973 write_byte(ES
,DI
+0x32,0);
2975 memsetb(ES
,DI
+0x33,0,13);
2978 // --------------------------------------------------------------------------------------------
2979 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2985 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2991 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2998 // ============================================================================================
3002 // ============================================================================================
3004 // --------------------------------------------------------------------------------------------
3005 static Bit8u
find_vga_entry(mode
)
3009 for(i
=0;i
<=MODE_MAX
;i
++)
3010 if(vga_modes
[i
].svgamode
==mode
)
3017 /* =========================================================== */
3021 /* =========================================================== */
3023 // --------------------------------------------------------------------------------------------
3024 static void memsetb(seg
,offset
,value
,count
)
3039 mov cx
, 10[bp
] ; count
3042 mov ax
, 4[bp
] ; segment
3044 mov ax
, 6[bp
] ; offset
3046 mov al
, 8[bp
] ; value
3061 // --------------------------------------------------------------------------------------------
3062 static void memsetw(seg
,offset
,value
,count
)
3077 mov cx
, 10[bp
] ; count
3080 mov ax
, 4[bp
] ; segment
3082 mov ax
, 6[bp
] ; offset
3084 mov ax
, 8[bp
] ; value
3099 // --------------------------------------------------------------------------------------------
3100 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
3118 mov cx
, 12[bp
] ; count
3121 mov ax
, 4[bp
] ; dsegment
3123 mov ax
, 6[bp
] ; doffset
3125 mov ax
, 8[bp
] ; ssegment
3127 mov ax
, 10[bp
] ; soffset
3145 // --------------------------------------------------------------------------------------------
3146 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
3164 mov cx
, 12[bp
] ; count
3167 mov ax
, 4[bp
] ; dsegment
3169 mov ax
, 6[bp
] ; doffset
3171 mov ax
, 8[bp
] ; ssegment
3173 mov ax
, 10[bp
] ; soffset
3191 /* =========================================================== */
3193 * These functions where ripped from Kevin's rombios.c
3195 /* =========================================================== */
3197 // --------------------------------------------------------------------------------------------
3199 read_byte(seg
, offset
)
3209 mov ax
, 4[bp
] ; segment
3211 mov bx
, 6[bp
] ; offset
3213 ;; al
= return value (byte
)
3221 // --------------------------------------------------------------------------------------------
3223 read_word(seg
, offset
)
3233 mov ax
, 4[bp
] ; segment
3235 mov bx
, 6[bp
] ; offset
3237 ;; ax
= return value (word
)
3245 // --------------------------------------------------------------------------------------------
3247 write_byte(seg
, offset
, data
)
3259 mov ax
, 4[bp
] ; segment
3261 mov bx
, 6[bp
] ; offset
3262 mov al
, 8[bp
] ; data byte
3263 mov
[bx
], al
; write data byte
3272 // --------------------------------------------------------------------------------------------
3274 write_word(seg
, offset
, data
)
3286 mov ax
, 4[bp
] ; segment
3288 mov bx
, 6[bp
] ; offset
3289 mov ax
, 8[bp
] ; data word
3290 mov
[bx
], ax
; write data word
3299 // --------------------------------------------------------------------------------------------
3334 // --------------------------------------------------------------------------------------------
3356 // --------------------------------------------------------------------------------------------
3386 void unimplemented()
3388 printf("--> Unimplemented\n");
3393 printf("--> Unknown int10\n");
3397 // --------------------------------------------------------------------------------------------
3401 Bit8u c
, format_char
;
3403 unsigned format_width
, i
;
3405 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
3413 while (c
= read_byte(0xc000, s
)) {
3418 else if (in_format
) {
3419 if ( (c
>='0') && (c
<='9') ) {
3420 format_width
= (format_width
* 10) + (c
- '0');
3422 else if (c
== 'x') {
3423 arg_ptr
++; // increment to next arg
3424 arg
= read_word(arg_seg
, arg_ptr
);
3425 if (format_width
== 0)
3428 digit
= format_width
- 1;
3429 for (i
=0; i
<format_width
; i
++) {
3430 nibble
= (arg
>> (4 * digit
)) & 0x000f;
3432 outb(0x0500, nibble
+ '0');
3434 outb(0x0500, (nibble
- 10) + 'A');
3439 //else if (c == 'd') {
3454 // --------------------------------------------------------------------------------------------
3457 ;; DATA_SEG_DEFS_HERE
3461 .ascii
"vgabios ends here"
3465 ;; BLOCK_STRINGS_BEGIN