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 // ============================================================================================
61 static Bit8u read_byte();
62 static Bit16u read_word();
63 static void write_byte();
64 static void write_word();
70 static Bit16u get_SS();
74 static void unimplemented();
75 static void unknown();
77 static Bit8u find_vga_entry();
79 static void memsetb();
80 static void memsetw();
81 static void memcpyb();
82 static void memcpyw();
84 static void biosfn_set_video_mode();
85 static void biosfn_set_cursor_shape();
86 static void biosfn_set_cursor_pos();
87 static void biosfn_get_cursor_pos();
88 static void biosfn_set_active_page();
89 static void biosfn_scroll();
90 static void biosfn_read_char_attr();
91 static void biosfn_write_char_attr();
92 static void biosfn_write_char_only();
93 static void biosfn_write_pixel();
94 static void biosfn_read_pixel();
95 static void biosfn_write_teletype();
96 static void biosfn_perform_gray_scale_summing();
97 static void biosfn_load_text_user_pat();
98 static void biosfn_load_text_8_14_pat();
99 static void biosfn_load_text_8_8_pat();
100 static void biosfn_load_text_8_16_pat();
101 static void biosfn_load_gfx_8_8_chars();
102 static void biosfn_load_gfx_user_chars();
103 static void biosfn_load_gfx_8_14_chars();
104 static void biosfn_load_gfx_8_8_dd_chars();
105 static void biosfn_load_gfx_8_16_chars();
106 static void biosfn_get_font_info();
107 static void biosfn_alternate_prtsc();
108 static void biosfn_switch_video_interface();
109 static void biosfn_enable_video_refresh_control();
110 static void biosfn_write_string();
111 static void biosfn_read_state_info();
112 static void biosfn_read_video_state_size();
113 static void biosfn_save_video_state();
114 static void biosfn_restore_video_state();
116 // This is for compiling with gcc2 and gcc3
117 #define ASM_START #asm
118 #define ASM_END #endasm
143 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
145 .byte 0x40 /* BIOS extension length in units of 512 bytes */
150 jmp vgabios_init_func
153 .ascii "Plex86/Bochs VGABios"
157 // Info from Bart Oldeman
176 .ascii "(C) 2003 the LGPL VGABios developers Team"
181 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
187 .ascii "Please visit :"
189 ;;.ascii " . http://www.plex86.org"
191 .ascii " . http://bochs.sourceforge.net"
193 .ascii " . http://www.nongnu.org/vgabios"
199 ;; ============================================================================================
203 ;; ============================================================================================
209 ;; init basic bios vars
213 ;; init vbe functions
218 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
224 ;; display splash screen
225 call _display_splash_screen
227 ;; init video mode and clear the screen
236 call vbe_display_info
241 call cirrus_display_info
251 vgabios_int10_handler:
266 call biosfn_get_video_mode
281 call biosfn_set_text_block_specifier
288 call biosfn_get_ega_info
293 call biosfn_select_vert_res
298 call biosfn_enable_default_palette_loading
303 call biosfn_enable_video_addressing
308 call biosfn_enable_grayscale_summing
313 call biosfn_enable_cursor_emulation
331 jne int10_test_vbe_05
332 call vbe_biosfn_return_current_mode
336 jne int10_test_vbe_06
337 call vbe_biosfn_display_window_control
341 jne int10_test_vbe_07
342 call vbe_biosfn_set_get_logical_scan_line_length
346 jne int10_test_vbe_08
347 call vbe_biosfn_set_get_display_start
352 call vbe_biosfn_set_get_dac_palette_format
361 ;; We have to set ds to access the right data segment
374 #include "vgatables.h"
375 #include "vgafonts.h"
378 * Boot time harware inits
382 ;; switch to color mode and enable CPU access 480 lines
387 ;; more than 64k 3C4/04
395 #if defined(USE_BX_INFO) || defined(DEBUG)
396 mov bx, #msg_vga_init
404 #if defined(USE_BX_INFO) || defined(DEBUG)
406 .ascii "VGABios $Id: vgabios.c,v 1.1 2007/11/29 20:26:38 pdinda Exp $"
411 // --------------------------------------------------------------------------------------------
413 * Boot time bios area inits
418 mov ax, # BIOSMEM_SEG
421 ;; init detected hardware BIOS Area
422 mov bx, # BIOSMEM_INITIAL_MODE
427 ;; Just for the first int10 find its children
429 ;; the default char height
430 mov bx, # BIOSMEM_CHAR_HEIGHT
435 mov bx, # BIOSMEM_VIDEO_CTL
439 ;; Set the basic screen we have
440 mov bx, # BIOSMEM_SWITCHES
444 ;; Set the basic modeset options
445 mov bx, # BIOSMEM_MODESET_CTL
449 ;; Set the default MSR
450 mov bx, # BIOSMEM_CURRENT_MSR
458 // --------------------------------------------------------------------------------------------
460 * Boot time Splash screen
462 static void display_splash_screen()
466 // --------------------------------------------------------------------------------------------
471 static void display_info()
478 mov si,#vgabios_version
481 ;;mov si,#vgabios_copyright
482 ;;call _display_string
484 ;;call _display_string
486 mov si,#vgabios_license
488 mov si,#vgabios_website
493 static void display_string()
495 // Get length of string
522 // --------------------------------------------------------------------------------------------
524 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
525 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
527 // 0E is write char...
529 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
533 // --------------------------------------------------------------------------------------------
535 * int10 main dispatcher
537 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
538 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
545 biosfn_set_video_mode(GET_AL());
546 switch(GET_AL()&0x7F)
564 biosfn_set_cursor_shape(GET_CH(),GET_CL());
567 biosfn_set_cursor_pos(GET_BH(),DX);
570 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
573 // Read light pen pos (unimplemented)
583 biosfn_set_active_page(GET_AL());
586 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
589 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
592 biosfn_read_char_attr(GET_BH(),&AX);
595 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
598 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
601 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
604 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
607 // Ralf Brown Interrupt list is WRONG on bh(page)
608 // We do output only on the current page !
609 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
612 // All other functions of group AH=0x10 rewritten in assembler
613 biosfn_perform_gray_scale_summing(BX,CX);
620 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
624 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
628 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
632 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
635 biosfn_load_gfx_8_8_chars(ES,BP);
638 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
641 biosfn_load_gfx_8_14_chars(GET_BL());
644 biosfn_load_gfx_8_8_dd_chars(GET_BL());
647 biosfn_load_gfx_8_16_chars(GET_BL());
650 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
663 biosfn_alternate_prtsc();
666 biosfn_switch_video_interface(GET_AL(),ES,DX);
670 biosfn_enable_video_refresh_control(GET_AL());
680 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
683 biosfn_read_state_info(BX,ES,DI);
690 biosfn_read_video_state_size(CX,&BX);
693 biosfn_save_video_state(CX,ES,BX);
696 biosfn_restore_video_state(CX,ES,BX);
708 if (vbe_has_vbe_display()) {
712 vbe_biosfn_return_controller_information(&AX,ES,DI);
715 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
718 vbe_biosfn_set_mode(&AX,BX,ES,DI);
766 // ============================================================================================
770 // ============================================================================================
772 static void biosfn_set_video_mode(mode) Bit8u mode;
773 {// mode: Bit 7 is 1 if no clear screen
775 // Should we clear the screen ?
776 Bit8u noclearmem=mode&0x80;
777 Bit8u line,mmask,*palette;
778 Bit16u i,twidth,theight,cheight;
779 Bit8u modeset_ctl,video_ctl,vga_switches;
783 if (vbe_has_vbe_display()) {
784 dispi_set_enable(VBE_DISPI_DISABLED);
791 // find the entry in the video modes
792 line=find_vga_entry(mode);
795 printf("mode search %02x found line %02x\n",mode,line);
801 twidth=vga_modes[line].twidth;
802 theight=vga_modes[line].theight;
803 cheight=vga_modes[line].cheight;
805 // Read the bios vga control
806 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
808 // Read the bios vga switches
809 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
811 // Read the bios mode set control
812 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
814 // Then we know the number of lines
817 // if palette loading (bit 3 of modeset ctl = 0)
818 if((modeset_ctl&0x08)==0)
820 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
822 // Set the whole dac always, from 0
823 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
825 // From which palette
826 switch(vga_modes[line].dacmodel)
841 // Always 256*3 values
842 for(i=0;i<0x0100;i++)
844 if(i<=dac_regs[vga_modes[line].dacmodel])
845 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
846 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
847 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
850 {outb(VGAREG_DAC_DATA,0);
851 outb(VGAREG_DAC_DATA,0);
852 outb(VGAREG_DAC_DATA,0);
855 if((modeset_ctl&0x02)==0x02)
857 biosfn_perform_gray_scale_summing(0x00, 0x100);
861 // Reset Attribute Ctl flip-flop
862 inb(VGAREG_ACTL_RESET);
865 for(i=0;i<=ACTL_MAX_REG;i++)
866 {outb(VGAREG_ACTL_ADDRESS,i);
867 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
871 for(i=0;i<=SEQU_MAX_REG;i++)
872 {outb(VGAREG_SEQU_ADDRESS,i);
873 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
877 for(i=0;i<=GRDC_MAX_REG;i++)
878 {outb(VGAREG_GRDC_ADDRESS,i);
879 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
882 // Set CRTC address VGA or MDA
883 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
885 // Disable CRTC write protection
886 outw(crtc_addr,0x0011);
888 for(i=0;i<=CRTC_MAX_REG;i++)
890 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
893 // Set the misc register
894 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
897 outb(VGAREG_ACTL_ADDRESS,0x20);
898 inb(VGAREG_ACTL_RESET);
902 if(vga_modes[line].class==TEXT)
904 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
910 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
914 outb( VGAREG_SEQU_ADDRESS, 0x02 );
915 mmask = inb( VGAREG_SEQU_DATA );
916 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
917 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
918 outb( VGAREG_SEQU_DATA, mmask );
924 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
925 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
926 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
927 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
928 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
929 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
930 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
931 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
932 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
934 // FIXME We nearly have the good tables. to be reworked
935 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
936 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
937 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
940 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
941 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
944 if(vga_modes[line].class==TEXT)
946 biosfn_set_cursor_shape(0x06,0x07);
949 // Set cursor pos for page 0..7
951 biosfn_set_cursor_pos(i,0x0000);
954 biosfn_set_active_page(0x00);
956 // Write the fonts in memory
957 if(vga_modes[line].class==TEXT)
960 ;; copy and activate 8x16 font
970 // Set the ints 0x1F and 0x43
972 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
978 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
983 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
988 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
994 // --------------------------------------------------------------------------------------------
995 static void biosfn_set_cursor_shape (CH,CL)
997 {Bit16u cheight,curs,crtc_addr;
1004 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1006 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1007 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1008 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1012 CH = ((CH+1) * cheight / 8) -1;
1016 CH = ((CL+1) * cheight / 8) - 2;
1018 CL = ((CL+1) * cheight / 8) - 1;
1021 // CTRC regs 0x0a and 0x0b
1022 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1023 outb(crtc_addr,0x0a);
1024 outb(crtc_addr+1,CH);
1025 outb(crtc_addr,0x0b);
1026 outb(crtc_addr+1,CL);
1029 // --------------------------------------------------------------------------------------------
1030 static void biosfn_set_cursor_pos (page, cursor)
1031 Bit8u page;Bit16u cursor;
1033 Bit8u xcurs,ycurs,current;
1034 Bit16u nbcols,nbrows,address,crtc_addr;
1036 // Should not happen...
1040 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1042 // Set the hardware cursor
1043 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1046 // Get the dimensions
1047 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1048 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1050 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1052 // Calculate the address knowing nbcols nbrows and page num
1053 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1055 // CRTC regs 0x0e and 0x0f
1056 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1057 outb(crtc_addr,0x0e);
1058 outb(crtc_addr+1,(address&0xff00)>>8);
1059 outb(crtc_addr,0x0f);
1060 outb(crtc_addr+1,address&0x00ff);
1064 // --------------------------------------------------------------------------------------------
1065 static void biosfn_get_cursor_pos (page,shape, pos)
1066 Bit8u page;Bit16u *shape;Bit16u *pos;
1071 write_word(ss, shape, 0);
1072 write_word(ss, pos, 0);
1075 // FIXME should handle VGA 14/16 lines
1076 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1077 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1080 // --------------------------------------------------------------------------------------------
1081 static void biosfn_set_active_page (page)
1084 Bit16u cursor,dummy,crtc_addr;
1085 Bit16u nbcols,nbrows,address;
1091 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1092 line=find_vga_entry(mode);
1093 if(line==0xFF)return;
1095 // Get pos curs pos for the right page
1096 biosfn_get_cursor_pos(page,&dummy,&cursor);
1098 if(vga_modes[line].class==TEXT)
1100 // Get the dimensions
1101 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1102 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1104 // Calculate the address knowing nbcols nbrows and page num
1105 address=SCREEN_MEM_START(nbcols,nbrows,page);
1106 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1109 address=SCREEN_IO_START(nbcols,nbrows,page);
1113 address = page*vga_modes[line].slength;
1116 // CRTC regs 0x0c and 0x0d
1117 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1118 outb(crtc_addr,0x0c);
1119 outb(crtc_addr+1,(address&0xff00)>>8);
1120 outb(crtc_addr,0x0d);
1121 outb(crtc_addr+1,address&0x00ff);
1123 // And change the BIOS page
1124 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1127 printf("Set active page %02x address %04x\n",page,address);
1130 // Display the cursor, now the page is active
1131 biosfn_set_cursor_pos(page,cursor);
1134 // --------------------------------------------------------------------------------------------
1135 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1136 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1141 src=ysrc*cheight*nbcols+xstart;
1142 dest=ydest*cheight*nbcols+xstart;
1143 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1144 for(i=0;i<cheight;i++)
1146 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1148 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1151 // --------------------------------------------------------------------------------------------
1152 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1153 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1158 dest=ystart*cheight*nbcols+xstart;
1159 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1160 for(i=0;i<cheight;i++)
1162 memsetb(0xa000,dest+i*nbcols,attr,cols);
1164 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1167 // --------------------------------------------------------------------------------------------
1168 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1169 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1174 src=((ysrc*cheight*nbcols)>>1)+xstart;
1175 dest=((ydest*cheight*nbcols)>>1)+xstart;
1176 for(i=0;i<cheight;i++)
1179 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1181 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1185 // --------------------------------------------------------------------------------------------
1186 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1187 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1192 dest=((ystart*cheight*nbcols)>>1)+xstart;
1193 for(i=0;i<cheight;i++)
1196 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1198 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1202 // --------------------------------------------------------------------------------------------
1203 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1204 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1206 // page == 0xFF if current
1208 Bit8u mode,line,cheight,bpp,cols;
1209 Bit16u nbcols,nbrows,i;
1216 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1217 line=find_vga_entry(mode);
1218 if(line==0xFF)return;
1220 // Get the dimensions
1221 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1222 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1224 // Get the current page
1226 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1228 if(rlr>=nbrows)rlr=nbrows-1;
1229 if(clr>=nbcols)clr=nbcols-1;
1230 if(nblines>nbrows)nblines=0;
1233 if(vga_modes[line].class==TEXT)
1235 // Compute the address
1236 address=SCREEN_MEM_START(nbcols,nbrows,page);
1238 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1241 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1243 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1248 {for(i=rul;i<=rlr;i++)
1250 if((i+nblines>rlr)||(nblines==0))
1251 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1253 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1257 {for(i=rlr;i>=rul;i--)
1259 if((i<rul+nblines)||(nblines==0))
1260 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1262 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1269 // FIXME gfx mode not complete
1270 cheight=vga_modes[line].cheight;
1271 switch(vga_modes[line].memmodel)
1275 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1277 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1278 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1279 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1284 {for(i=rul;i<=rlr;i++)
1286 if((i+nblines>rlr)||(nblines==0))
1287 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1289 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1293 {for(i=rlr;i>=rul;i--)
1295 if((i<rul+nblines)||(nblines==0))
1296 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1298 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1304 bpp=vga_modes[line].pixbits;
1305 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1307 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1319 {for(i=rul;i<=rlr;i++)
1321 if((i+nblines>rlr)||(nblines==0))
1322 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1324 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1328 {for(i=rlr;i>=rul;i--)
1330 if((i<rul+nblines)||(nblines==0))
1331 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1333 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1340 printf("Scroll in graphics mode ");
1347 // --------------------------------------------------------------------------------------------
1348 static void biosfn_read_char_attr (page,car)
1349 Bit8u page;Bit16u *car;
1350 {Bit16u ss=get_SS();
1351 Bit8u xcurs,ycurs,mode,line;
1352 Bit16u nbcols,nbrows,address;
1353 Bit16u cursor,dummy;
1356 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1357 line=find_vga_entry(mode);
1358 if(line==0xFF)return;
1360 // Get the cursor pos for the page
1361 biosfn_get_cursor_pos(page,&dummy,&cursor);
1362 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1364 // Get the dimensions
1365 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1366 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1368 if(vga_modes[line].class==TEXT)
1370 // Compute the address
1371 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1373 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1384 // --------------------------------------------------------------------------------------------
1385 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1386 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1390 Bit16u addr,dest,src;
1402 addr=xcurs+ycurs*cheight*nbcols;
1403 src = car * cheight;
1404 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1405 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1408 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1412 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1414 for(i=0;i<cheight;i++)
1420 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1421 read_byte(0xa000,dest);
1422 if(fdata[src+i]&mask)
1424 write_byte(0xa000,dest,attr&0x0f);
1428 write_byte(0xa000,dest,0x00);
1433 mov dx, # VGAREG_GRDC_ADDRESS
1443 // --------------------------------------------------------------------------------------------
1444 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1445 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1447 Bit8u i,j,mask,data;
1449 Bit16u addr,dest,src;
1452 addr=(xcurs*bpp)+ycurs*320;
1456 dest=addr+(i>>1)*80;
1457 if (i & 1) dest += 0x2000;
1463 data = read_byte(0xb800,dest);
1471 if (fdata[src+i] & mask)
1475 data ^= (attr & 0x01) << (7-j);
1479 data |= (attr & 0x01) << (7-j);
1484 write_byte(0xb800,dest,data);
1492 data = read_byte(0xb800,dest);
1500 if (fdata[src+i] & mask)
1504 data ^= (attr & 0x03) << ((3-j)*2);
1508 data |= (attr & 0x03) << ((3-j)*2);
1513 write_byte(0xb800,dest,data);
1520 // --------------------------------------------------------------------------------------------
1521 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1522 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1524 Bit8u i,j,mask,data;
1526 Bit16u addr,dest,src;
1529 addr=xcurs*8+ycurs*nbcols*64;
1533 dest=addr+i*nbcols*8;
1538 if (fdata[src+i] & mask)
1542 write_byte(0xa000,dest+j,data);
1548 // --------------------------------------------------------------------------------------------
1549 static void biosfn_write_char_attr (car,page,attr,count)
1550 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1552 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1553 Bit16u nbcols,nbrows,address;
1554 Bit16u cursor,dummy;
1557 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1558 line=find_vga_entry(mode);
1559 if(line==0xFF)return;
1561 // Get the cursor pos for the page
1562 biosfn_get_cursor_pos(page,&dummy,&cursor);
1563 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1565 // Get the dimensions
1566 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1567 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1569 if(vga_modes[line].class==TEXT)
1571 // Compute the address
1572 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1574 dummy=((Bit16u)attr<<8)+car;
1576 printf("sstart=%x\n", vga_modes[line].sstart);
1577 printf("address=%x\n", address);
1578 printf("dummy=%x\n", dummy);
1579 printf("count=%x\n", count);
1581 memsetw(vga_modes[line].sstart,address,dummy,count);
1585 // FIXME gfx mode not complete
1586 cheight=vga_modes[line].cheight;
1587 bpp=vga_modes[line].pixbits;
1588 while((count-->0) && (xcurs<nbcols))
1590 switch(vga_modes[line].memmodel)
1594 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1597 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1600 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1612 // --------------------------------------------------------------------------------------------
1613 static void biosfn_write_char_only (car,page,attr,count)
1614 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1616 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1617 Bit16u nbcols,nbrows,address;
1618 Bit16u cursor,dummy;
1621 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1622 line=find_vga_entry(mode);
1623 if(line==0xFF)return;
1625 // Get the cursor pos for the page
1626 biosfn_get_cursor_pos(page,&dummy,&cursor);
1627 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1629 // Get the dimensions
1630 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1631 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1633 if(vga_modes[line].class==TEXT)
1635 // Compute the address
1636 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1639 {write_byte(vga_modes[line].sstart,address,car);
1645 // FIXME gfx mode not complete
1646 cheight=vga_modes[line].cheight;
1647 bpp=vga_modes[line].pixbits;
1648 while((count-->0) && (xcurs<nbcols))
1650 switch(vga_modes[line].memmodel)
1654 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1657 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1660 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1672 // --------------------------------------------------------------------------------------------
1676 je biosfn_set_border_color
1678 je biosfn_set_palette
1683 biosfn_set_border_color:
1688 mov dx, # VGAREG_ACTL_RESET
1690 mov dx, # VGAREG_ACTL_ADDRESS
1703 mov dx, # VGAREG_ACTL_ADDRESS
1706 mov dx, # VGAREG_ACTL_READ_DATA
1710 mov dx, # VGAREG_ACTL_ADDRESS
1714 jne set_intensity_loop
1727 mov dx, # VGAREG_ACTL_RESET
1731 set_cga_palette_loop:
1732 mov dx, # VGAREG_ACTL_ADDRESS
1735 mov dx, # VGAREG_ACTL_READ_DATA
1739 mov dx, # VGAREG_ACTL_ADDRESS
1743 jne set_cga_palette_loop
1753 // --------------------------------------------------------------------------------------------
1754 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1756 Bit8u mode,line,mask,attr,data;
1760 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1761 line=find_vga_entry(mode);
1762 if(line==0xFF)return;
1763 if(vga_modes[line].class==TEXT)return;
1765 switch(vga_modes[line].memmodel)
1769 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1770 mask = 0x80 >> (CX & 0x07);
1771 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1772 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1773 data = read_byte(0xa000,addr);
1776 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1778 write_byte(0xa000,addr,AL);
1780 mov dx, # VGAREG_GRDC_ADDRESS
1790 if(vga_modes[line].pixbits==2)
1792 addr=(CX>>2)+(DX>>1)*80;
1796 addr=(CX>>3)+(DX>>1)*80;
1798 if (DX & 1) addr += 0x2000;
1799 data = read_byte(0xb800,addr);
1800 if(vga_modes[line].pixbits==2)
1802 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1803 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1807 attr = (AL & 0x01) << (7 - (CX & 0x07));
1808 mask = 0x01 << (7 - (CX & 0x07));
1819 write_byte(0xb800,addr,data);
1822 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1823 write_byte(0xa000,addr,AL);
1832 // --------------------------------------------------------------------------------------------
1833 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1835 Bit8u mode,line,mask,attr,data,i;
1840 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1841 line=find_vga_entry(mode);
1842 if(line==0xFF)return;
1843 if(vga_modes[line].class==TEXT)return;
1845 switch(vga_modes[line].memmodel)
1849 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1850 mask = 0x80 >> (CX & 0x07);
1854 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1855 data = read_byte(0xa000,addr) & mask;
1856 if (data > 0) attr |= (0x01 << i);
1860 addr=(CX>>2)+(DX>>1)*80;
1861 if (DX & 1) addr += 0x2000;
1862 data = read_byte(0xb800,addr);
1863 if(vga_modes[line].pixbits==2)
1865 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1869 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1873 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1874 attr=read_byte(0xa000,addr);
1882 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1885 // --------------------------------------------------------------------------------------------
1886 static void biosfn_write_teletype (car, page, attr, flag)
1887 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1888 {// flag = WITH_ATTR / NO_ATTR
1890 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1891 Bit16u nbcols,nbrows,address;
1892 Bit16u cursor,dummy;
1894 // special case if page is 0xff, use current page
1896 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1899 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1900 line=find_vga_entry(mode);
1901 if(line==0xFF)return;
1903 // Get the cursor pos for the page
1904 biosfn_get_cursor_pos(page,&dummy,&cursor);
1905 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1907 // Get the dimensions
1908 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1909 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1933 biosfn_write_teletype(' ',page,attr,flag);
1934 biosfn_get_cursor_pos(page,&dummy,&cursor);
1935 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1941 if(vga_modes[line].class==TEXT)
1943 // Compute the address
1944 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1947 write_byte(vga_modes[line].sstart,address,car);
1950 write_byte(vga_modes[line].sstart,address+1,attr);
1954 // FIXME gfx mode not complete
1955 cheight=vga_modes[line].cheight;
1956 bpp=vga_modes[line].pixbits;
1957 switch(vga_modes[line].memmodel)
1961 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1964 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1967 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1978 // Do we need to wrap ?
1984 // Do we need to scroll ?
1987 if(vga_modes[line].class==TEXT)
1989 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1993 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1998 // Set the cursor for the page
1999 cursor=ycurs; cursor<<=8; cursor+=xcurs;
2000 biosfn_set_cursor_pos(page,cursor);
2003 // --------------------------------------------------------------------------------------------
2005 biosfn_get_video_mode:
2007 mov ax, # BIOSMEM_SEG
2010 mov bx, # BIOSMEM_CURRENT_PAGE
2015 mov bx, # BIOSMEM_VIDEO_CTL
2018 mov bx, # BIOSMEM_CURRENT_MODE
2021 mov bx, # BIOSMEM_NB_COLS
2028 // --------------------------------------------------------------------------------------------
2033 jmp biosfn_set_single_palette_reg
2037 jmp biosfn_set_overscan_border_color
2041 jmp biosfn_set_all_palette_reg
2045 jmp biosfn_toggle_intensity
2049 jmp biosfn_get_single_palette_reg
2053 jmp biosfn_read_overscan_border_color
2057 jmp biosfn_get_all_palette_reg
2061 jmp biosfn_set_single_dac_reg
2065 jmp biosfn_set_all_dac_reg
2069 jmp biosfn_select_video_dac_color_page
2073 jmp biosfn_read_single_dac_reg
2077 jmp biosfn_read_all_dac_reg
2081 jmp biosfn_set_pel_mask
2085 jmp biosfn_read_pel_mask
2088 jne int10_group_10_unknown
2089 jmp biosfn_read_video_dac_state
2090 int10_group_10_unknown:
2096 biosfn_set_single_palette_reg:
2101 mov dx, # VGAREG_ACTL_RESET
2103 mov dx, # VGAREG_ACTL_ADDRESS
2116 // --------------------------------------------------------------------------------------------
2118 biosfn_set_overscan_border_color:
2121 call biosfn_set_single_palette_reg
2126 // --------------------------------------------------------------------------------------------
2128 biosfn_set_all_palette_reg:
2134 mov dx, # VGAREG_ACTL_RESET
2137 mov dx, # VGAREG_ACTL_ADDRESS
2147 jne set_palette_loop
2162 // --------------------------------------------------------------------------------------------
2164 biosfn_toggle_intensity:
2168 mov dx, # VGAREG_ACTL_RESET
2170 mov dx, # VGAREG_ACTL_ADDRESS
2173 mov dx, # VGAREG_ACTL_READ_DATA
2179 mov dx, # VGAREG_ACTL_ADDRESS
2189 // --------------------------------------------------------------------------------------------
2191 biosfn_get_single_palette_reg:
2196 mov dx, # VGAREG_ACTL_RESET
2198 mov dx, # VGAREG_ACTL_ADDRESS
2201 mov dx, # VGAREG_ACTL_READ_DATA
2204 mov dx, # VGAREG_ACTL_RESET
2206 mov dx, # VGAREG_ACTL_ADDRESS
2215 // --------------------------------------------------------------------------------------------
2217 biosfn_read_overscan_border_color:
2221 call biosfn_get_single_palette_reg
2229 // --------------------------------------------------------------------------------------------
2231 biosfn_get_all_palette_reg:
2239 mov dx, # VGAREG_ACTL_RESET
2241 mov dx, # VGAREG_ACTL_ADDRESS
2244 mov dx, # VGAREG_ACTL_READ_DATA
2251 jne get_palette_loop
2252 mov dx, # VGAREG_ACTL_RESET
2254 mov dx, # VGAREG_ACTL_ADDRESS
2257 mov dx, # VGAREG_ACTL_READ_DATA
2261 mov dx, # VGAREG_ACTL_RESET
2263 mov dx, # VGAREG_ACTL_ADDRESS
2273 // --------------------------------------------------------------------------------------------
2275 biosfn_set_single_dac_reg:
2278 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2281 mov dx, # VGAREG_DAC_DATA
2295 // --------------------------------------------------------------------------------------------
2297 biosfn_set_all_dac_reg:
2302 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2308 mov dx, # VGAREG_DAC_DATA
2331 // --------------------------------------------------------------------------------------------
2333 biosfn_select_video_dac_color_page:
2337 mov dx, # VGAREG_ACTL_RESET
2339 mov dx, # VGAREG_ACTL_ADDRESS
2342 mov dx, # VGAREG_ACTL_READ_DATA
2349 mov dx, # VGAREG_ACTL_ADDRESS
2354 mov dx, # VGAREG_ACTL_RESET
2356 mov dx, # VGAREG_ACTL_ADDRESS
2376 // --------------------------------------------------------------------------------------------
2378 biosfn_read_single_dac_reg:
2381 mov dx, # VGAREG_DAC_READ_ADDRESS
2386 mov dx, # VGAREG_DAC_DATA
2399 // --------------------------------------------------------------------------------------------
2401 biosfn_read_all_dac_reg:
2406 mov dx, # VGAREG_DAC_READ_ADDRESS
2412 mov dx, # VGAREG_DAC_DATA
2435 // --------------------------------------------------------------------------------------------
2437 biosfn_set_pel_mask:
2440 mov dx, # VGAREG_PEL_MASK
2448 // --------------------------------------------------------------------------------------------
2450 biosfn_read_pel_mask:
2453 mov dx, # VGAREG_PEL_MASK
2461 // --------------------------------------------------------------------------------------------
2463 biosfn_read_video_dac_state:
2466 mov dx, # VGAREG_ACTL_RESET
2468 mov dx, # VGAREG_ACTL_ADDRESS
2471 mov dx, # VGAREG_ACTL_READ_DATA
2475 mov dx, # VGAREG_ACTL_RESET
2477 mov dx, # VGAREG_ACTL_ADDRESS
2480 mov dx, # VGAREG_ACTL_READ_DATA
2488 mov dx, # VGAREG_ACTL_RESET
2490 mov dx, # VGAREG_ACTL_ADDRESS
2498 // --------------------------------------------------------------------------------------------
2499 static void biosfn_perform_gray_scale_summing (start,count)
2500 Bit16u start;Bit16u count;
2505 inb(VGAREG_ACTL_RESET);
2506 outb(VGAREG_ACTL_ADDRESS,0x00);
2508 for( index = 0; index < count; index++ )
2510 // set read address and switch to read mode
2511 outb(VGAREG_DAC_READ_ADDRESS,start);
2512 // get 6-bit wide RGB data values
2513 r=inb( VGAREG_DAC_DATA );
2514 g=inb( VGAREG_DAC_DATA );
2515 b=inb( VGAREG_DAC_DATA );
2517 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2518 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2522 // set write address and switch to write mode
2523 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2524 // write new intensity value
2525 outb( VGAREG_DAC_DATA, i&0xff );
2526 outb( VGAREG_DAC_DATA, i&0xff );
2527 outb( VGAREG_DAC_DATA, i&0xff );
2530 inb(VGAREG_ACTL_RESET);
2531 outb(VGAREG_ACTL_ADDRESS,0x20);
2534 // --------------------------------------------------------------------------------------------
2535 static void get_font_access()
2538 mov dx, # VGAREG_SEQU_ADDRESS
2547 mov dx, # VGAREG_GRDC_ADDRESS
2557 static void release_font_access()
2560 mov dx, # VGAREG_SEQU_ADDRESS
2569 mov dx, # VGAREG_READ_MISC_OUTPUT
2576 mov dx, # VGAREG_GRDC_ADDRESS
2592 static void set_scan_lines(lines) Bit8u lines;
2594 Bit16u crtc_addr,cols,page,vde;
2595 Bit8u crtc_r9,ovl,rows;
2597 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2598 outb(crtc_addr, 0x09);
2599 crtc_r9 = inb(crtc_addr+1);
2600 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2601 outb(crtc_addr+1, crtc_r9);
2604 biosfn_set_cursor_shape(0x06,0x07);
2608 biosfn_set_cursor_shape(lines-4,lines-3);
2610 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2611 outb(crtc_addr, 0x12);
2612 vde = inb(crtc_addr+1);
2613 outb(crtc_addr, 0x07);
2614 ovl = inb(crtc_addr+1);
2615 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2617 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2618 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2619 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2622 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;
2624 Bit16u blockaddr,dest,i,src;
2627 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2631 dest = blockaddr + (DX + i) * 32;
2632 memcpyb(0xA000, dest, ES, src, BH);
2634 release_font_access();
2641 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2643 Bit16u blockaddr,dest,i,src;
2646 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2647 for(i=0;i<0x100;i++)
2650 dest = blockaddr + i * 32;
2651 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2653 release_font_access();
2660 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2662 Bit16u blockaddr,dest,i,src;
2665 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2666 for(i=0;i<0x100;i++)
2669 dest = blockaddr + i * 32;
2670 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2672 release_font_access();
2679 // --------------------------------------------------------------------------------------------
2681 biosfn_set_text_block_specifier:
2684 mov dx, # VGAREG_SEQU_ADDRESS
2693 // --------------------------------------------------------------------------------------------
2694 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2696 Bit16u blockaddr,dest,i,src;
2699 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2700 for(i=0;i<0x100;i++)
2703 dest = blockaddr + i * 32;
2704 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2706 release_font_access();
2713 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2719 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2725 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2731 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2737 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2743 // --------------------------------------------------------------------------------------------
2744 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2745 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2746 {Bit16u ss=get_SS();
2750 write_word(ss,ES,read_word(0x00,0x1f*4));
2751 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2754 write_word(ss,ES,read_word(0x00,0x43*4));
2755 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2758 write_word(ss,ES,0xC000);
2759 write_word(ss,BP,vgafont14);
2762 write_word(ss,ES,0xC000);
2763 write_word(ss,BP,vgafont8);
2766 write_word(ss,ES,0xC000);
2767 write_word(ss,BP,vgafont8+128*8);
2770 write_word(ss,ES,0xC000);
2771 write_word(ss,BP,vgafont14alt);
2774 write_word(ss,ES,0xC000);
2775 write_word(ss,BP,vgafont16);
2778 write_word(ss,ES,0xC000);
2779 write_word(ss,BP,vgafont16alt);
2783 printf("Get font info BH(%02x) was discarded\n",BH);
2787 // Set byte/char of on screen font
2788 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2790 // Set Highest char row
2791 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2794 // --------------------------------------------------------------------------------------------
2796 biosfn_get_ega_info:
2799 mov ax, # BIOSMEM_SEG
2802 mov bx, # BIOSMEM_SWITCHES
2805 mov bx, # BIOSMEM_CRTC_ADDRESS
2808 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2817 // --------------------------------------------------------------------------------------------
2818 static void biosfn_alternate_prtsc()
2825 // --------------------------------------------------------------------------------------------
2827 biosfn_select_vert_res:
2829 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2835 mov ax, # BIOSMEM_SEG
2837 mov bx, # BIOSMEM_MODESET_CTL
2839 mov bx, # BIOSMEM_SWITCHES
2850 mov bx, #msg_vert_res
2858 ; reset modeset ctl bit 7 and set bit 4
2859 ; set switches bit 3-0 to 0x09
2868 ; reset modeset ctl bit 7 and bit 4
2869 ; set switches bit 3-0 to 0x09
2877 ; set modeset ctl bit 7 and reset bit 4
2878 ; set switches bit 3-0 to 0x08
2885 mov bx, # BIOSMEM_MODESET_CTL
2887 mov bx, # BIOSMEM_SWITCHES
2898 .ascii "Select vert res (%02x) was discarded"
2899 .byte 0x0d,0x0a,0x00
2903 biosfn_enable_default_palette_loading:
2910 mov ax, # BIOSMEM_SEG
2912 mov bx, # BIOSMEM_MODESET_CTL
2924 biosfn_enable_video_addressing:
2931 mov dx, # VGAREG_READ_MISC_OUTPUT
2935 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2943 biosfn_enable_grayscale_summing:
2951 mov ax, # BIOSMEM_SEG
2953 mov bx, # BIOSMEM_MODESET_CTL
2965 biosfn_enable_cursor_emulation:
2972 mov ax, # BIOSMEM_SEG
2974 mov bx, # BIOSMEM_MODESET_CTL
2986 // --------------------------------------------------------------------------------------------
2987 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2993 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3000 // --------------------------------------------------------------------------------------------
3001 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3002 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3004 Bit16u newcurs,oldcurs,dummy;
3007 // Read curs info for the page
3008 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3010 // if row=0xff special case : use current cursor position
3012 {col=oldcurs&0x00ff;
3013 row=(oldcurs&0xff00)>>8;
3016 newcurs=row; newcurs<<=8; newcurs+=col;
3017 biosfn_set_cursor_pos(page,newcurs);
3021 car=read_byte(seg,offset++);
3023 attr=read_byte(seg,offset++);
3025 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3028 // Set back curs pos
3030 biosfn_set_cursor_pos(page,oldcurs);
3033 // --------------------------------------------------------------------------------------------
3037 je biosfn_read_display_code
3039 je biosfn_set_display_code
3044 biosfn_read_display_code:
3047 mov ax, # BIOSMEM_SEG
3049 mov bx, # BIOSMEM_DCC_INDEX
3057 biosfn_set_display_code:
3061 mov ax, # BIOSMEM_SEG
3064 mov bx, # BIOSMEM_DCC_INDEX
3070 mov bx, #msg_alt_dcc
3083 .ascii "Alternate Display code (%02x) was discarded"
3084 .byte 0x0d,0x0a,0x00
3088 // --------------------------------------------------------------------------------------------
3089 static void biosfn_read_state_info (BX,ES,DI)
3090 Bit16u BX;Bit16u ES;Bit16u DI;
3092 // Address of static functionality table
3093 write_word(ES,DI+0x00,&static_functionality);
3094 write_word(ES,DI+0x02,0xC000);
3096 // Hard coded copy from BIOS area. Should it be cleaner ?
3097 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3098 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3100 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3101 write_byte(ES,DI+0x26,0);
3102 write_byte(ES,DI+0x27,16);
3103 write_byte(ES,DI+0x28,0);
3104 write_byte(ES,DI+0x29,8);
3105 write_byte(ES,DI+0x2a,2);
3106 write_byte(ES,DI+0x2b,0);
3107 write_byte(ES,DI+0x2c,0);
3108 write_byte(ES,DI+0x31,3);
3109 write_byte(ES,DI+0x32,0);
3111 memsetb(ES,DI+0x33,0,13);
3114 // --------------------------------------------------------------------------------------------
3115 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3121 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3127 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3134 // ============================================================================================
3138 // ============================================================================================
3140 // --------------------------------------------------------------------------------------------
3141 static Bit8u find_vga_entry(mode)
3145 for(i=0;i<=MODE_MAX;i++)
3146 if(vga_modes[i].svgamode==mode)
3153 /* =========================================================== */
3157 /* =========================================================== */
3159 // --------------------------------------------------------------------------------------------
3160 static void memsetb(seg,offset,value,count)
3175 mov cx, 10[bp] ; count
3178 mov ax, 4[bp] ; segment
3180 mov ax, 6[bp] ; offset
3182 mov al, 8[bp] ; value
3197 // --------------------------------------------------------------------------------------------
3198 static void memsetw(seg,offset,value,count)
3213 mov cx, 10[bp] ; count
3216 mov ax, 4[bp] ; segment
3218 mov ax, 6[bp] ; offset
3220 mov ax, 8[bp] ; value
3235 // --------------------------------------------------------------------------------------------
3236 static void memcpyb(dseg,doffset,sseg,soffset,count)
3254 mov cx, 12[bp] ; count
3257 mov ax, 4[bp] ; dsegment
3259 mov ax, 6[bp] ; doffset
3261 mov ax, 8[bp] ; ssegment
3263 mov ax, 10[bp] ; soffset
3281 // --------------------------------------------------------------------------------------------
3282 static void memcpyw(dseg,doffset,sseg,soffset,count)
3300 mov cx, 12[bp] ; count
3303 mov ax, 4[bp] ; dsegment
3305 mov ax, 6[bp] ; doffset
3307 mov ax, 8[bp] ; ssegment
3309 mov ax, 10[bp] ; soffset
3327 /* =========================================================== */
3329 * These functions where ripped from Kevin's rombios.c
3331 /* =========================================================== */
3333 // --------------------------------------------------------------------------------------------
3335 read_byte(seg, offset)
3345 mov ax, 4[bp] ; segment
3347 mov bx, 6[bp] ; offset
3349 ;; al = return value (byte)
3357 // --------------------------------------------------------------------------------------------
3359 read_word(seg, offset)
3369 mov ax, 4[bp] ; segment
3371 mov bx, 6[bp] ; offset
3373 ;; ax = return value (word)
3381 // --------------------------------------------------------------------------------------------
3383 write_byte(seg, offset, data)
3395 mov ax, 4[bp] ; segment
3397 mov bx, 6[bp] ; offset
3398 mov al, 8[bp] ; data byte
3399 mov [bx], al ; write data byte
3408 // --------------------------------------------------------------------------------------------
3410 write_word(seg, offset, data)
3422 mov ax, 4[bp] ; segment
3424 mov bx, 6[bp] ; offset
3425 mov ax, 8[bp] ; data word
3426 mov [bx], ax ; write data word
3435 // --------------------------------------------------------------------------------------------
3470 // --------------------------------------------------------------------------------------------
3492 // --------------------------------------------------------------------------------------------
3522 void unimplemented()
3524 printf("--> Unimplemented\n");
3529 printf("--> Unknown int10\n");
3533 // --------------------------------------------------------------------------------------------
3534 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3538 Bit8u c, format_char;
3540 unsigned format_width, i;
3542 Bit16u arg_seg, arg, digit, nibble, shift_count;
3550 while (c = read_byte(0xc000, s)) {
3555 else if (in_format) {
3556 if ( (c>='0') && (c<='9') ) {
3557 format_width = (format_width * 10) + (c - '0');
3559 else if (c == 'x') {
3560 arg_ptr++; // increment to next arg
3561 arg = read_word(arg_seg, arg_ptr);
3562 if (format_width == 0)
3565 digit = format_width - 1;
3566 for (i=0; i<format_width; i++) {
3567 nibble = (arg >> (4 * digit)) & 0x000f;
3569 outb(0xE9, nibble + '0');
3571 outb(0xE9, (nibble - 10) + 'A');
3576 //else if (c == 'd') {
3596 // --------------------------------------------------------------------------------------------
3599 ;; DATA_SEG_DEFS_HERE
3603 .ascii "vgabios ends here"
3607 ;; BLOCK_STRINGS_BEGIN