📄 vgabios.c
字号:
// 0E is write char... if(GET_AH()!=0x0E) printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);}#endif// --------------------------------------------------------------------------------------------/* * int10 main dispatcher */static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS) Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;{ // BIOS functions switch(GET_AH()) { case 0x00: biosfn_set_video_mode(GET_AL()); switch(GET_AL()&0x7F) {case 6: SET_AL(0x3F); break; case 0: case 1: case 2: case 3: case 4: case 5: case 7: SET_AL(0x30); break; default: SET_AL(0x20); } break; case 0x01: biosfn_set_cursor_shape(GET_CH(),GET_CL()); break; case 0x02: biosfn_set_cursor_pos(GET_BH(),DX); break; case 0x03: biosfn_get_cursor_pos(GET_BH(),&CX,&DX); break; case 0x04: // Read light pen pos (unimplemented)#ifdef DEBUG unimplemented();#endif AX=0x00; BX=0x00; CX=0x00; DX=0x00; break; case 0x05: biosfn_set_active_page(GET_AL()); break; case 0x06: biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP); break; case 0x07: biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN); break; case 0x08: biosfn_read_char_attr(GET_BH(),&AX); break; case 0x09: biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX); break; case 0x0A: biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX); break; case 0x0C: biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX); break; case 0x0D: biosfn_read_pixel(GET_BH(),CX,DX,&AX); break; case 0x0E: // Ralf Brown Interrupt list is WRONG on bh(page) // We do output only on the current page ! biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR); break; case 0x10: // All other functions of group AH=0x10 rewritten in assembler biosfn_perform_gray_scale_summing(BX,CX); break; case 0x11: switch(GET_AL()) { case 0x00: case 0x10: biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH()); break; case 0x01: case 0x11: biosfn_load_text_8_14_pat(GET_AL(),GET_BL()); break; case 0x02: case 0x12: biosfn_load_text_8_8_pat(GET_AL(),GET_BL()); break; case 0x04: case 0x14: biosfn_load_text_8_16_pat(GET_AL(),GET_BL()); break; case 0x20: biosfn_load_gfx_8_8_chars(ES,BP); break; case 0x21: biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL()); break; case 0x22: biosfn_load_gfx_8_14_chars(GET_BL()); break; case 0x23: biosfn_load_gfx_8_8_dd_chars(GET_BL()); break; case 0x24: biosfn_load_gfx_8_16_chars(GET_BL()); break; case 0x30: biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX); break;#ifdef DEBUG default: unknown();#endif } break; case 0x12: switch(GET_BL()) { case 0x20: biosfn_alternate_prtsc(); break; case 0x35: biosfn_switch_video_interface(GET_AL(),ES,DX); SET_AL(0x12); break; case 0x36: biosfn_enable_video_refresh_control(GET_AL()); SET_AL(0x12); break;#ifdef DEBUG default: unknown();#endif } break; case 0x13: biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP); break; case 0x1B: biosfn_read_state_info(BX,ES,DI); SET_AL(0x1B); break; case 0x1C: switch(GET_AL()) { case 0x00: biosfn_read_video_state_size(CX,&BX); break; case 0x01: biosfn_save_video_state(CX,ES,BX); break; case 0x02: biosfn_restore_video_state(CX,ES,BX); break;#ifdef DEBUG default: unknown();#endif } SET_AL(0x1C); break;#ifdef VBE case 0x4f: if (vbe_has_vbe_display()) { switch(GET_AL()) { case 0x00: vbe_biosfn_return_controller_information(&AX,ES,DI); break; case 0x01: vbe_biosfn_return_mode_information(&AX,CX,ES,DI); break; case 0x02: vbe_biosfn_set_mode(&AX,BX,ES,DI); break; case 0x04: vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX); break; case 0x09: //FIXME#ifdef DEBUG unimplemented();#endif // function failed AX=0x100; break; case 0x0A: //FIXME#ifdef DEBUG unimplemented();#endif // function failed AX=0x100; break; default:#ifdef DEBUG unknown();#endif // function failed AX=0x100; } } else { // No VBE display AX=0x0100; } break;#endif#ifdef DEBUG default: unknown();#endif }}// ============================================================================================// // BIOS functions// // ============================================================================================static void biosfn_set_video_mode(mode) Bit8u mode; {// mode: Bit 7 is 1 if no clear screen // Should we clear the screen ? Bit8u noclearmem=mode&0x80; Bit8u line,mmask,*palette,vpti; Bit16u i,twidth,theightm1,cheight; Bit8u modeset_ctl,video_ctl,vga_switches; Bit16u crtc_addr; #ifdef VBE if (vbe_has_vbe_display()) { dispi_set_enable(VBE_DISPI_DISABLED); }#endif // def VBE // The real mode mode=mode&0x7f; // find the entry in the video modes line=find_vga_entry(mode);#ifdef DEBUG printf("mode search %02x found line %02x\n",mode,line);#endif if(line==0xFF) return; vpti=line_to_vpti[line]; twidth=video_param_table[vpti].twidth; theightm1=video_param_table[vpti].theightm1; cheight=video_param_table[vpti].cheight; // Read the bios vga control video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL); // Read the bios vga switches vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES); // Read the bios mode set control modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); // Then we know the number of lines// FIXME // if palette loading (bit 3 of modeset ctl = 0) if((modeset_ctl&0x08)==0) {// Set the PEL mask outb(VGAREG_PEL_MASK,vga_modes[line].pelmask); // Set the whole dac always, from 0 outb(VGAREG_DAC_WRITE_ADDRESS,0x00); // From which palette switch(vga_modes[line].dacmodel) {case 0: palette=&palette0; break; case 1: palette=&palette1; break; case 2: palette=&palette2; break; case 3: palette=&palette3; break; } // Always 256*3 values for(i=0;i<0x0100;i++) {if(i<=dac_regs[vga_modes[line].dacmodel]) {outb(VGAREG_DAC_DATA,palette[(i*3)+0]); outb(VGAREG_DAC_DATA,palette[(i*3)+1]); outb(VGAREG_DAC_DATA,palette[(i*3)+2]); } else {outb(VGAREG_DAC_DATA,0); outb(VGAREG_DAC_DATA,0); outb(VGAREG_DAC_DATA,0); } } if((modeset_ctl&0x02)==0x02) { biosfn_perform_gray_scale_summing(0x00, 0x100); } } // Reset Attribute Ctl flip-flop inb(VGAREG_ACTL_RESET); // Set Attribute Ctl for(i=0;i<=0x13;i++) {outb(VGAREG_ACTL_ADDRESS,i); outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]); } outb(VGAREG_ACTL_ADDRESS,0x14); outb(VGAREG_ACTL_WRITE_DATA,0x00); // Set Sequencer Ctl outb(VGAREG_SEQU_ADDRESS,0); outb(VGAREG_SEQU_DATA,0x03); for(i=1;i<=4;i++) {outb(VGAREG_SEQU_ADDRESS,i); outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]); } // Set Grafx Ctl for(i=0;i<=8;i++) {outb(VGAREG_GRDC_ADDRESS,i); outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]); } // Set CRTC address VGA or MDA crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS; // Disable CRTC write protection outw(crtc_addr,0x0011); // Set CRTC regs for(i=0;i<=0x18;i++) {outb(crtc_addr,i); outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]); } // Set the misc register outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg); // Enable video outb(VGAREG_ACTL_ADDRESS,0x20); inb(VGAREG_ACTL_RESET); if(noclearmem==0x00) { if(vga_modes[line].class==TEXT) { memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k } else { if(mode<0x0d) { memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k } else { outb( VGAREG_SEQU_ADDRESS, 0x02 ); mmask = inb( VGAREG_SEQU_DATA ); outb( VGAREG_SEQU_DATA, 0x0f ); // all planes memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k outb( VGAREG_SEQU_DATA, mmask ); } } } // Set the BIOS mem write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode); write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth); write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l); write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr); write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1); write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight); write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem)); write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9); write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f); // FIXME We nearly have the good tables. to be reworked write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table); write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000); // FIXME write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but... write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but... // Set cursor shape if(vga_modes[line].class==TEXT) { biosfn_set_cursor_shape(0x06,0x07); } // Set cursor pos for page 0..7 for(i=0;i<8;i++) biosfn_set_cursor_pos(i,0x0000); // Set active page 0 biosfn_set_active_page(0x00); // Write the fonts in memory if(vga_modes[line].class==TEXT) { ASM_START ;; copy and activate 8x16 font mov ax, #0x1104 mov bl, #0x00 int #0x10 mov ax, #0x1103 mov bl, #0x00 int #0x10ASM_END } // Set the ints 0x1F and 0x43ASM_START SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)ASM_END switch(cheight) {case 8:ASM_START SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)ASM_END break; case 14:ASM_START SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)ASM_END break; case 16:ASM_START SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)ASM_END break; }}// --------------------------------------------------------------------------------------------static void biosfn_set_cursor_shape (CH,CL) Bit8u CH;Bit8u CL; {Bit16u cheight,curs,crtc_addr; Bit8u modeset_ctl; CH&=0x3f; CL&=0x1f; curs=(CH<<8)+CL; write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs); modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20)) { if(CL!=(CH+1)) { CH = ((CH+1) * cheight / 8) -1; } else { CH = ((CL+1) * cheight / 8) - 2; } CL = ((CL+1) * cheight / 8) - 1; } // CTRC regs 0x0a and 0x0b crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); outb(crtc_addr,0x0a); outb(crtc_addr+1,CH); outb(crtc_addr,0x0b); outb(crtc_addr+1,CL);}// --------------------------------------------------------------------------------------------static void biosfn_set_cursor_pos (page, cursor) Bit8u page;Bit16u cursor;{ Bit8u xcurs,ycurs,current; Bit16u nbcols,nbrows,address,crtc_addr; // Should not happen... if(page>7)return; // Bios cursor pos write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor); // Set the hardware cursor current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); if(page==current) { // Get the dimensions nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; // Calculate the address knowing nbcols nbrows and page num address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols; // CRTC regs 0x0e and 0x0f crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); outb(crtc_addr,0x0e); outb(crtc_addr+1,(address&0xff00)>>8); outb(crtc_addr,0x0f); outb(crtc_addr+1,address&0x00ff); }}// --------------------------------------------------------------------------------------------static void biosfn_get_cursor_pos (page,shape, pos) Bit8u page;Bit16u *shape;Bit16u *pos;{ Bit16u ss=get_SS(); // Default write_word(ss, shape, 0); write_word(ss, pos, 0); if(page>7)return; // FIXME should handle VGA 14/16 lines write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));}// --------------------------------------------------------------------------------------------static void biosfn_set_active_page (page) Bit8u page;{ Bit16u cursor,dummy,crtc_addr; Bit16u nbcols,nbrows,address; Bit8u mode,line; if(page>7)return; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get pos curs pos for the right page biosfn_get_cursor_pos(page,&dummy,&cursor); if(vga_modes[line].class==TEXT) { // Get the dimensions nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; // Calculate the address knowing nbcols nbrows and page num address=SCREEN_MEM_START(nbcols,nbrows,page); write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address); // Start address address=SCREEN_IO_START(nbcols,nbrows,page); } else { address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -