📄 vgabios.c
字号:
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: //FIXME#ifdef DEBUG unimplemented();#endif // function failed AX=0x100; 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; Bit16u i,twidth,theight,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; twidth=vga_modes[line].twidth; theight=vga_modes[line].theight; cheight=vga_modes[line].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<=ACTL_MAX_REG;i++) {outb(VGAREG_ACTL_ADDRESS,i); outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]); } // Set Sequencer Ctl for(i=0;i<=SEQU_MAX_REG;i++) {outb(VGAREG_SEQU_ADDRESS,i); outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]); } // Set Grafx Ctl for(i=0;i<=GRDC_MAX_REG;i++) {outb(VGAREG_GRDC_ADDRESS,i); outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][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<=CRTC_MAX_REG;i++) {outb(crtc_addr,i); outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]); } // Set the misc register outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].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,vga_modes[line].slength); write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr); write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1); 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,0x00); write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00); // 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*vga_modes[line].slength; } // CRTC regs 0x0c and 0x0d crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); outb(crtc_addr,0x0c); outb(crtc_addr+1,(address&0xff00)>>8); outb(crtc_addr,0x0d); outb(crtc_addr+1,address&0x00ff); // And change the BIOS page write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);#ifdef DEBUG printf("Set active page %02x address %04x\n",page,address);#endif // Display the cursor, now the page is active biosfn_set_cursor_pos(page,cursor);}// --------------------------------------------------------------------------------------------static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;{ Bit16u src,dest; Bit8u i; src=ysrc*cheight*nbcols+xstart; dest=ydest*cheight*nbcols+xstart; outw(VGAREG_GRDC_ADDRESS, 0x0105); for(i=0;i<cheight;i++) { memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols); } outw(VGAREG_GRDC_ADDRESS, 0x0005);}// --------------------------------------------------------------------------------------------static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;{ Bit16u dest; Bit8u i; dest=ystart*cheight*nbcols+xstart; outw(VGAREG_GRDC_ADDRESS, 0x0205); for(i=0;i<cheight;i++) { memsetb(0xa000,dest+i*nbcols,attr,cols); } outw(VGAREG_GRDC_ADDRESS, 0x0005);}// --------------------------------------------------------------------------------------------static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;{ Bit16u src,dest; Bit8u i; src=((ysrc*cheight*nbcols)>>1)+xstart; dest=((ydest*cheight*nbcols)>>1)+xstart; for(i=0;i<cheight;i++) { if (i & 1) memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -