📄 vgamach64xx.c
字号:
d = ((p.y+dy-1)&~(dy-1)) - physr->max.y; physr->min.y += d; physr->max.y += d; } if(p.x < physr->min.x){ d = physr->min.x - (p.x&~(dx-1)); physr->min.x -= d; physr->max.x -= d; } if(p.x > physr->max.x){ d = ((p.x+dx-1)&~(dx-1)) - physr->max.x; physr->min.x += d; physr->max.x += d; } return 1;}static intmach64xxcurmove(VGAscr* scr, Point p){ int x, xo, y, yo; int dx; ulong off, pitch; /* * If the point we want to display is outside the current * screen rectangle, pan the screen to display it. * * We have to move in 64-bit chunks. */ if(scr->gscreen->depth == 24) dx = (64*3)/24; else dx = 64 / scr->gscreen->depth; if(screenpan(p, &physgscreenr, dx, 1)){ off = (physgscreenr.min.y*Dx(scr->gscreen->r)+physgscreenr.min.x)/dx; pitch = Dx(scr->gscreen->r)/8; iow32(scr, CrtcOffPitch, (pitch<<22)|off); } p.x -= physgscreenr.min.x; p.y -= physgscreenr.min.y; /* * Mustn't position the cursor offscreen even partially, * or it disappears. Therefore, if x or y is -ve, adjust the * cursor presets instead. If y is negative also have to * adjust the starting offset. */ if((x = p.x+scr->offset.x) < 0){ xo = x; x = 0; } else xo = 0; if((y = p.y+scr->offset.y) < 0){ yo = y; y = 0; } else yo = 0; iow32(scr, CurHVoff, ((64-16-yo)<<16)|(64-16-xo)); iow32(scr, CurOffset, scr->storage/8 + (-yo*2)); iow32(scr, CurHVposn, (y<<16)|x); return 0;}static voidmach64xxcurenable(VGAscr* scr){ ulong r, storage; mach64xxenable(scr); if(scr->io == 0) return; r = ior32(scr, GenTestCntl); iow32(scr, GenTestCntl, r & ~0x80); iow32(scr, CurClr0, (Pwhite<<24)|(Pwhite<<16)|(Pwhite<<8)|Pwhite); iow32(scr, CurClr1, (Pblack<<24)|(Pblack<<16)|(Pblack<<8)|Pblack); /* * Find a place for the cursor data in display memory. * Must be 64-bit aligned. */ storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+7)/8; iow32(scr, CurOffset, storage); scr->storage = storage*8; /* * Cursor goes in the top right corner of the 64x64 array * so the horizontal and vertical presets are 64-16. */ iow32(scr, CurHVposn, (0<<16)|0); iow32(scr, CurHVoff, ((64-16)<<16)|(64-16)); /* * Load, locate and enable the 64x64 cursor. */ mach64xxcurload(scr, &arrow); mach64xxcurmove(scr, ZP); iow32(scr, GenTestCntl, 0x80|r);}static voidwaitforfifo(VGAscr *scr, int entries){ int x; x = 0; while((ior32(scr, FifoStat)&0xFF) > (0x8000>>entries) && x++ < 1000000) ; if(x >= 1000000) iprint("fifo %d stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", entries, ior32(scr, FifoStat), scr->mmio[mmoffset[FifoStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));}static voidwaitforidle(VGAscr *scr){ int x; waitforfifo(scr, 16); x = 0; while((ior32(scr, GuiStat)&1) && x++ < 1000000) ; if(x >= 1000000) iprint("idle stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", ior32(scr, GuiStat), scr->mmio[mmoffset[GuiStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));}static voidresetengine(VGAscr *scr){ ulong x; x = ior32(scr, GenTestCntl); iow32(scr, GenTestCntl, x&~0x100); iow32(scr, GenTestCntl, x|0x100); iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000);}static voidinitengine(VGAscr *scr){ ulong pitch; pitch = Dx(scr->gscreen->r)/8; if(scr->gscreen->depth == 24) pitch *= 3; resetengine(scr); waitforfifo(scr, 14); iow32(scr, ContextMask, ~0); iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstYX, 0); iow32(scr, DstHeight, 0); iow32(scr, DstBresErr, 0); iow32(scr, DstBresInc, 0); iow32(scr, DstBresDec, 0); iow32(scr, DstCntl, 0x23); iow32(scr, SrcOffPitch, pitch<<22); iow32(scr, SrcYX, 0); iow32(scr, SrcHeight1Width1, 1); iow32(scr, SrcYXstart, 0); iow32(scr, SrcHeight2Width2, 1); iow32(scr, SrcCntl, 0x01); waitforfifo(scr, 13); iow32(scr, HostCntl, 0); iow32(scr, PatReg0, 0); iow32(scr, PatReg1, 0); iow32(scr, PatCntl, 0); iow32(scr, ScLeft, 0); iow32(scr, ScTop, 0); iow32(scr, ScBottom, 0xFFFF); iow32(scr, ScRight, 0xFFFF); iow32(scr, DpBkgdClr, 0); iow32(scr, DpFrgdClr, ~0); iow32(scr, DpWriteMask, ~0); iow32(scr, DpMix, 0x70003); iow32(scr, DpSrc, 0x00010100); waitforfifo(scr, 3); iow32(scr, ClrCmpClr, 0); iow32(scr, ClrCmpMask, ~0); iow32(scr, ClrCmpCntl, 0); waitforfifo(scr, 2); switch(scr->gscreen->depth){ case 8: case 24: /* [sic] */ iow32(scr, DpPixWidth, 0x00020202); iow32(scr, DpChainMask, 0x8080); break; case 16: iow32(scr, DpPixWidth, 0x00040404); iow32(scr, DpChainMask, 0x8410); break; case 32: iow32(scr, DpPixWidth, 0x00060606); iow32(scr, DpChainMask, 0x8080); break; } waitforidle(scr);}static intmach64hwfill(VGAscr *scr, Rectangle r, ulong sval){ ulong pitch; ulong ctl;if(drawdebug) iprint("hwfill %R val %lux...\n", r, sval); /* shouldn't happen */ if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0) return 0; pitch = Dx(scr->gscreen->r)/8; ctl = 1|2; /* left-to-right, top-to-bottom */ if(scr->gscreen->depth == 24){ r.min.x *= 3; r.max.x *= 3; pitch *= 3; ctl |= (1<<7)|(((r.min.x/4)%6)<<8); } waitforfifo(scr, 11); iow32(scr, DpFrgdClr, sval); iow32(scr, DpWriteMask, 0xFFFFFFFF); iow32(scr, DpMix, 0x00070003); iow32(scr, DpSrc, 0x00000111); iow32(scr, ClrCmpCntl, 0x00000000); iow32(scr, ScLeftRight, 0x1FFF0000); iow32(scr, ScTopBottom, 0x1FFF0000); iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstCntl, ctl); iow32(scr, DstYX, (r.min.x<<16)|r.min.y); iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r)); waitforidle(scr); return 1;}static intmach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr){ ulong pitch; Point dp, sp; ulong ctl; int dx, dy; dx = Dx(r); dy = Dy(r); pitch = Dx(scr->gscreen->r)/8; if(scr->gscreen->depth == 24){ dx *= 3; pitch *= 3; r.min.x *= 3; sr.min.x *= 3; } ctl = 0; if(r.min.x <= sr.min.x){ ctl |= 1; dp.x = r.min.x; sp.x = sr.min.x; }else{ dp.x = r.min.x+dx-1; sp.x = sr.min.x+dx-1; } if(r.min.y <= sr.min.y){ ctl |= 2; dp.y = r.min.y; sp.y = sr.min.y; }else{ dp.y = r.min.y+dy-1; sp.y = sr.min.y+dy-1; } if(scr->gscreen->depth == 24) ctl |= (1<<7)|(((dp.x/4)%6)<<8); waitforfifo(scr, 6); iow32(scr, ScLeftRight, 0x1FFF0000); iow32(scr, ScTopBottom, 0x1FFF0000); iow32(scr, DpWriteMask, 0xFFFFFFFF); iow32(scr, DpMix, 0x00070003); iow32(scr, DpSrc, 0x00000300); iow32(scr, ClrCmpCntl, 0x00000000); waitforfifo(scr, 8); iow32(scr, SrcOffPitch, pitch<<22); iow32(scr, SrcCntl, 0x00000000); iow32(scr, SrcYX, (sp.x<<16)|sp.y); iow32(scr, SrcWidth1, dx); iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstCntl, ctl); iow32(scr, DstYX, (dp.x<<16)|dp.y); iow32(scr, DstHeightWidth, (dx<<16)|dy); waitforidle(scr); return 1;}/* * This should work, but doesn't. * It messes up the screen timings for some reason. */static voidmach64blank(VGAscr *scr, int blank){ ulong ctl; ctl = ior32(scr, CrtcGenCtl) & ~(CrtcHsyncDis|CrtcVsyncDis); if(blank) ctl |= CrtcHsyncDis|CrtcVsyncDis; iow32(scr, CrtcGenCtl, ctl);}/* * We squirrel away whether the LCD and/or CRT were * on when we were called to blank the screen, and * restore the old state. If we are called to blank the * screen when it is already blank, we don't update the state. * Such a call sequence should not happen, though. * * We could try forcing the chip into power management * mode instead, but I'm not sure how that would interact * with screen updates going on while the screen is blanked. */static voidmach64lcdblank(VGAscr *scr, int blank){ static int crtlcd; ulong x; if(blank) { x = lcdr32(scr, LCD_GenCtrl); if(x & 3) { crtlcd = x & 3; lcdw32(scr, LCD_GenCtrl, x&~3); } } else { if(crtlcd == 0) crtlcd = 2; /* lcd only */ x = lcdr32(scr, LCD_GenCtrl); lcdw32(scr, LCD_GenCtrl, x | crtlcd); }}static voidmach64xxdrawinit(VGAscr *scr){ if(scr->io > 0x2FF){ initengine(scr); scr->fill = mach64hwfill; scr->scroll = mach64hwscroll; }/* scr->blank = mach64blank; */ if(scr->id == ('L'<<8)|'P') /* Rage LT PRO */ scr->blank = mach64lcdblank;}VGAdev vgamach64xxdev = { "mach64xx", mach64xxenable, /* enable */ 0, /* disable */ 0, /* page */ mach64xxlinear, /* linear */ mach64xxdrawinit, /* drawinit */};VGAcur vgamach64xxcur = { "mach64xxhwgc", mach64xxcurenable, /* enable */ mach64xxcurdisable, /* disable */ mach64xxcurload, /* load */ mach64xxcurmove, /* move */ 1 /* doespanning */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -