📄 vgabios.c
字号:
} // 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 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols); }}// --------------------------------------------------------------------------------------------static void vgamem_fill_cga(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)>>1)+xstart; for(i=0;i<cheight;i++) { if (i & 1) memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols); else memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols); }}// --------------------------------------------------------------------------------------------static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;{ // page == 0xFF if current Bit8u mode,line,cheight,bpp,cols; Bit16u nbcols,nbrows,i; Bit16u address; if(rul>rlr)return; if(cul>clr)return; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); // Get the current page if(page==0xFF) page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); if(rlr>=nbrows)rlr=nbrows-1; if(clr>=nbcols)clr=nbcols-1; if(nblines>nbrows)nblines=0; cols=clr-cul+1; if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page);#ifdef DEBUG printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);#endif if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) { memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols); } else {// if Scroll up if(dir==SCROLL_UP) {for(i=rul;i<=rlr;i++) { if((i+nblines>rlr)||(nblines==0)) memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols); else memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols); } } else {for(i=rlr;i>=rul;i--) { if((i<rul+nblines)||(nblines==0)) memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols); else memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols); if (i>rlr) break; } } } } else { // FIXME gfx mode not complete cheight=video_param_table[line_to_vpti[line]].cheight; switch(vga_modes[line].memmodel) { case PLANAR4: case PLANAR1: if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) { outw(VGAREG_GRDC_ADDRESS, 0x0205); memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight); outw(VGAREG_GRDC_ADDRESS, 0x0005); } else {// if Scroll up if(dir==SCROLL_UP) {for(i=rul;i<=rlr;i++) { if((i+nblines>rlr)||(nblines==0)) vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr); else vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight); } } else {for(i=rlr;i>=rul;i--) { if((i<rul+nblines)||(nblines==0)) vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr); else vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight); if (i>rlr) break; } } } break; case CGA: bpp=vga_modes[line].pixbits; if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) { memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp); } else { if(bpp==2) { cul<<=1; cols<<=1; nbcols<<=1; } // if Scroll up if(dir==SCROLL_UP) {for(i=rul;i<=rlr;i++) { if((i+nblines>rlr)||(nblines==0)) vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr); else vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight); } } else {for(i=rlr;i>=rul;i--) { if((i<rul+nblines)||(nblines==0)) vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr); else vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight); if (i>rlr) break; } } } break;#ifdef DEBUG default: printf("Scroll in graphics mode "); unimplemented();#endif } }}// --------------------------------------------------------------------------------------------static void biosfn_read_char_attr (page,car) Bit8u page;Bit16u *car;{Bit16u ss=get_SS(); Bit8u xcurs,ycurs,mode,line; Bit16u nbcols,nbrows,address; Bit16u cursor,dummy; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get the cursor pos for the page biosfn_get_cursor_pos(page,&dummy,&cursor); xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; write_word(ss,car,read_word(vga_modes[line].sstart,address)); } else { // FIXME gfx mode#ifdef DEBUG unimplemented();#endif }}// --------------------------------------------------------------------------------------------static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;{ Bit8u i,j,mask; Bit8u *fdata; Bit16u addr,dest,src; switch(cheight) {case 14: fdata = &vgafont14; break; case 16: fdata = &vgafont16; break; default: fdata = &vgafont8; } addr=xcurs+ycurs*cheight*nbcols; src = car * cheight; outw(VGAREG_SEQU_ADDRESS, 0x0f02); outw(VGAREG_GRDC_ADDRESS, 0x0205); if(attr&0x80) { outw(VGAREG_GRDC_ADDRESS, 0x1803); } else { outw(VGAREG_GRDC_ADDRESS, 0x0003); } for(i=0;i<cheight;i++) { dest=addr+i*nbcols; for(j=0;j<8;j++) { mask=0x80>>j; outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); read_byte(0xa000,dest); if(fdata[src+i]&mask) { write_byte(0xa000,dest,attr&0x0f); } else { write_byte(0xa000,dest,0x00); } } }ASM_START mov dx, # VGAREG_GRDC_ADDRESS mov ax, #0xff08 out dx, ax mov ax, #0x0005 out dx, ax mov ax, #0x0003 out dx, axASM_END}// --------------------------------------------------------------------------------------------static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;{ Bit8u i,j,mask,data; Bit8u *fdata; Bit16u addr,dest,src; fdata = &vgafont8; addr=(xcurs*bpp)+ycurs*320; src = car * 8; for(i=0;i<8;i++) { dest=addr+(i>>1)*80; if (i & 1) dest += 0x2000; mask = 0x80; if (bpp == 1) { if (attr & 0x80) { data = read_byte(0xb800,dest); } else { data = 0x00; } for(j=0;j<8;j++) { if (fdata[src+i] & mask) { if (attr & 0x80) { data ^= (attr & 0x01) << (7-j); } else { data |= (attr & 0x01) << (7-j); } } mask >>= 1; } write_byte(0xb800,dest,data); } else { while (mask > 0) { if (attr & 0x80) { data = read_byte(0xb800,dest); } else { data = 0x00; } for(j=0;j<4;j++) { if (fdata[src+i] & mask) { if (attr & 0x80) { data ^= (attr & 0x03) << ((3-j)*2); } else { data |= (attr & 0x03) << ((3-j)*2); } } mask >>= 1; } write_byte(0xb800,dest,data); dest += 1; } } }}// --------------------------------------------------------------------------------------------static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;{ Bit8u i,j,mask,data; Bit8u *fdata; Bit16u addr,dest,src; fdata = &vgafont8; addr=xcurs*8+ycurs*nbcols*64; src = car * 8; for(i=0;i<8;i++) { dest=addr+i*nbcols*8; mask = 0x80; for(j=0;j<8;j++) { data = 0x00; if (fdata[src+i] & mask) { data = attr; } write_byte(0xa000,dest+j,data); mask >>= 1; } }}// --------------------------------------------------------------------------------------------static void biosfn_write_char_attr (car,page,attr,count) Bit8u car;Bit8u page;Bit8u attr;Bit16u count;{ Bit8u cheight,xcurs,ycurs,mode,line,bpp; Bit16u nbcols,nbrows,address; Bit16u cursor,dummy; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get the cursor pos for the page biosfn_get_cursor_pos(page,&dummy,&cursor); xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; dummy=((Bit16u)attr<<8)+car; memsetw(vga_modes[line].sstart,address,dummy,count); } else { // FIXME gfx mode not complete cheight=video_param_table[line_to_vpti[line]].cheight; bpp=vga_modes[line].pixbits; while((count-->0) && (xcurs<nbcols)) { switch(vga_modes[line].memmodel) { case PLANAR4: case PLANAR1: write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight); break; case CGA: write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); break; case LINEAR8: write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); break;#ifdef DEBUG default: unimplemented();#endif } xcurs++; } }}// --------------------------------------------------------------------------------------------static void biosfn_write_char_only (car,page,attr,count)Bit8u car;Bit8u page;Bit8u attr;Bit16u count;{ Bit8u cheight,xcurs,ycurs,mode,line,bpp; Bit16u nbcols,nbrows,address; Bit16u cursor,dummy; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; // Get the cursor pos for the page biosfn_get_cursor_pos(page,&dummy,&cursor); xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; // Get the dimensions nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); if(vga_modes[line].class==TEXT) { // Compute the address address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; while(count-->0) {write_byte(vga_modes[line].sstart,address,car); address+=2; } } else { // FIXME gfx mode not complete cheight=video_param_table[line_to_vpti[line]].cheight; bpp=vga_modes[line].pixbits; while((count-->0) && (xcurs<nbcols)) { switch(vga_modes[line].memmodel) { case PLANAR4: case PLANAR1: write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight); break; case CGA: write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); break; case LINEAR8: write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); break;#ifdef DEBUG default: unimplemented();#endif } xcurs++; } }}// --------------------------------------------------------------------------------------------ASM_STARTbiosfn_group_0B: cmp bh, #0x00 je biosfn_set_border_color cmp bh, #0x01 je biosfn_set_palette#ifdef DEBUG call _unknown#endif retbiosfn_set_border_color: push ax push bx push cx push dx mov dx, # VGAREG_ACTL_RESET in al, dx mov dx, # VGAREG_ACTL_ADDRESS mov al, #0x00 out dx, al mov al, bl and al, #0x0f test al, #0x08 jz set_low_border add al, #0x08set_low_border: out dx, al mov cl, #0x01 and bl, #0x10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -