📄 vgabios.c
字号:
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); } } } } else { // FIXME gfx mode not complete cheight=vga_modes[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); } } } 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); } } } 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;/*printf("sstart=%x\n", vga_modes[line].sstart);printf("address=%x\n", address);printf("dummy=%x\n", dummy);printf("count=%x\n", count);*/ memsetw(vga_modes[line].sstart,address,dummy,count); } else { // FIXME gfx mode not complete cheight=vga_modes[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=vga_modes[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, #0x10set_intensity_loop: mov dx, # VGAREG_ACTL_ADDRESS mov al, cl out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx and al, #0xef or al, bl mov dx, # VGAREG_ACTL_ADDRESS out dx, al inc cl cmp cl, #0x04 jne set_intensity_loop mov al, #0x20 out dx, al pop dx pop cx pop bx pop ax retbiosfn_set_palette: push ax push bx push cx push dx mov dx, # VGAREG_ACTL_RESET in al, dx mov cl, #0x01 and bl, #0x01set_cga_palette_loop: mov dx, # VGAREG_ACTL_ADDRESS mov al, cl out dx, al mov dx, # VGAREG_ACTL_READ_DATA in al, dx and al, #0xfe or al, bl mov dx, # VGAREG_ACTL_ADDRESS out dx, al inc cl cmp cl, #0x04 jne set_cga_palette_loop mov al, #0x20 out dx, al pop dx pop cx pop bx pop ax retASM_END// --------------------------------------------------------------------------------------------static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;{ Bit8u mode,line,mask,attr,data; Bit16u addr; // Get the mode mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); line=find_vga_entry(mode); if(line==0xFF)return; if(vga_modes[line].class==TEXT)return; switch(vga_modes[line].memmodel) { case PLANAR4: case PLANAR1: addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); mask = 0x80 >> (CX & 0x07);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -