📄 gfx.cpp
字号:
b2 &= ~0x10; GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); } } } } else { GFX.X2 = NULL; GFX.ZERO_OR_X2 = NULL; GFX.ZERO = NULL; } return (TRUE);}void S9xGraphicsDeinit (void){ // Free any memory allocated in S9xGraphicsInit if (GFX.X2) { free ((char *) GFX.X2); GFX.X2 = NULL; } if (GFX.ZERO_OR_X2) { free ((char *) GFX.ZERO_OR_X2); GFX.ZERO_OR_X2 = NULL; } if (GFX.ZERO) { free ((char *) GFX.ZERO); GFX.ZERO = NULL; }}void S9xBuildDirectColourMaps (){ for (uint32 p = 0; p < 8; p++) { for (uint32 c = 0; c < 256; c++) {// XXX: Brightness DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1), ((c & 0x38) >> 1) | (p & 2), ((c & 0xc0) >> 3) | (p & 4)); } } IPPU.DirectColourMapsNeedRebuild = FALSE;}void S9xStartScreenRefresh (){ if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0) GFX.InfoString = NULL; if (IPPU.RenderThisFrame) { if (!S9xInitUpdate ()) { IPPU.RenderThisFrame = FALSE; return; } IPPU.RenderedFramesCount++; IPPU.PreviousLine = IPPU.CurrentLine = 0; IPPU.MaxBrightness = PPU.Brightness; IPPU.LatchedBlanking = PPU.ForcedBlanking; if(PPU.BGMode == 5 || PPU.BGMode == 6) IPPU.Interlace = (Memory.FillRAM[0x2133] & 1); if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace)) { if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.Interlace) { IPPU.RenderedScreenWidth = 512; IPPU.DoubleWidthPixels = TRUE; } else { IPPU.RenderedScreenWidth = 256; IPPU.DoubleWidthPixels = FALSE; } if (IPPU.Interlace) { IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; IPPU.DoubleHeightPixels = TRUE; GFX.Pitch2 = GFX.RealPitch; GFX.Pitch = GFX.RealPitch * 2; if (Settings.SixteenBit) GFX.PPL = GFX.PPLx2 = GFX.RealPitch; else GFX.PPL = GFX.PPLx2 = GFX.RealPitch << 1; } else { IPPU.RenderedScreenHeight = PPU.ScreenHeight; GFX.Pitch2 = GFX.Pitch = GFX.RealPitch; IPPU.DoubleHeightPixels = FALSE; if (Settings.SixteenBit) GFX.PPL = GFX.Pitch >> 1; else GFX.PPL = GFX.Pitch; GFX.PPLx2 = GFX.PPL << 1; }#if defined(USE_GLIDE) || defined(USE_OPENGL) GFX.ZPitch = GFX.RealPitch; if (Settings.SixteenBit) GFX.ZPitch >>= 1;#endif } else { IPPU.RenderedScreenWidth = 256; IPPU.RenderedScreenHeight = PPU.ScreenHeight; IPPU.DoubleWidthPixels = FALSE; IPPU.DoubleHeightPixels = FALSE;#ifdef USE_GLIDE if (Settings.GlideEnable) { // Speed up hack for Glide: render low res. SNES images // into a handy 256x256 sized buffer that can be uploaded into // texture memory with one Glide call without having to copy it // into a second, suitably sized buffer first. GFX.Pitch2 = GFX.Pitch = 256 * sizeof (uint16); GFX.PPL = 256; GFX.PPLx2 = GFX.Pitch; GFX.ZPitch = 256; } else#endif#ifdef USE_OPENGL if (Settings.OpenGLEnable) { GFX.Pitch2 = GFX.Pitch = 256 * sizeof (uint16); GFX.PPL = 256; GFX.PPLx2 = GFX.Pitch; GFX.ZPitch = 256; } else#endif { GFX.Pitch2 = GFX.Pitch = GFX.RealPitch; GFX.PPL = GFX.PPLx2 >> 1; GFX.ZPitch = GFX.RealPitch; if (Settings.SixteenBit) GFX.ZPitch >>= 1; } } PPU.RecomputeClipWindows = TRUE; GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; } if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) { IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; IPPU.RenderedFramesCount = 0; IPPU.FrameCount = 0; }}void RenderLine (uint8 C){ if (IPPU.RenderThisFrame) { LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; if (PPU.BGMode == 7) { struct SLineMatrixData *p = &LineMatrixData [C]; p->MatrixA = PPU.MatrixA; p->MatrixB = PPU.MatrixB; p->MatrixC = PPU.MatrixC; p->MatrixD = PPU.MatrixD; p->CentreX = PPU.CentreX; p->CentreY = PPU.CentreY; } else { if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && PPU.BG[2].HOffset == 0xe000) { LineData[C].BG[2].VOffset = 0xe1; LineData[C].BG[2].HOffset = 0; } else { LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1; LineData[C].BG[2].HOffset = PPU.BG[2].HOffset; LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1; LineData[C].BG[3].HOffset = PPU.BG[3].HOffset; } } IPPU.CurrentLine = C + 1; } else { /* if we're not rendering this frame, we still need to update this */ // XXX: Check ForceBlank? Or anything else? if(IPPU.OBJChanged) S9xSetupOBJ(); PPU.RangeTimeOver |= GFX.OBJLines[C].RTOFlags; }}void S9xEndScreenRefresh (){ IPPU.HDMAStarted = FALSE; if (IPPU.RenderThisFrame) { FLUSH_REDRAW (); if (IPPU.ColorsChanged) { uint32 saved = PPU.CGDATA[0]; if (!Settings.SixteenBit) { // Hack for Super Mario World - to get its sky blue // (It uses Fixed colour addition on the backdrop colour) if (!(Memory.FillRAM [0x2131] & 0x80) && (Memory.FillRAM[0x2131] & 0x20) && (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue)) { PPU.CGDATA[0] = PPU.FixedColourRed | (PPU.FixedColourGreen << 5) | (PPU.FixedColourBlue << 10); } } IPPU.ColorsChanged = FALSE; S9xSetPalette (); PPU.CGDATA[0] = saved; } if (#ifdef USE_GLIDE !Settings.GlideEnable &&#endif#ifdef USE_OPENGL !Settings.OpenGLEnable &&#endif TRUE) { GFX.Pitch = GFX.Pitch2 = GFX.RealPitch; GFX.PPL = GFX.PPLx2 >> 1; }//take screenshot here. if(Settings.TakeScreenshot) S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); if (Settings.DisplayFrameRate) S9xDisplayFrameRate (); if (GFX.InfoString) S9xDisplayString (GFX.InfoString); S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, Settings.SixteenBit); } S9xApplyCheats ();#ifdef DEBUGGER if (CPU.Flags & FRAME_ADVANCE_FLAG) { if (ICPU.FrameAdvanceCount) { ICPU.FrameAdvanceCount--; IPPU.RenderThisFrame = TRUE; IPPU.FrameSkip = 0; } else { CPU.Flags &= ~FRAME_ADVANCE_FLAG; CPU.Flags |= DEBUG_MODE_FLAG; } }#endif if (CPU.SRAMModified) { if (!CPU.AutoSaveTimer) { if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) CPU.SRAMModified = FALSE; } else { if (!--CPU.AutoSaveTimer) { S9xAutoSaveSRAM (); CPU.SRAMModified = FALSE; } } }}void S9xSetInfoString (const char *string){ GFX.InfoString = string; GFX.InfoStringTimeout = 120;}inline void SelectTileRenderer (bool8 normal){ if (normal) { DrawTilePtr = DrawTile16; DrawClippedTilePtr = DrawClippedTile16; DrawLargePixelPtr = DrawLargePixel16; } else { if (GFX.r2131 & 0x80) { if (GFX.r2131 & 0x40) { if (GFX.r2130 & 2) { DrawTilePtr = DrawTile16Sub1_2; DrawClippedTilePtr = DrawClippedTile16Sub1_2; } else { // Fixed colour substraction DrawTilePtr = DrawTile16FixedSub1_2; DrawClippedTilePtr = DrawClippedTile16FixedSub1_2; } DrawLargePixelPtr = DrawLargePixel16Sub1_2; } else { DrawTilePtr = DrawTile16Sub; DrawClippedTilePtr = DrawClippedTile16Sub; DrawLargePixelPtr = DrawLargePixel16Sub; } } else { if (GFX.r2131 & 0x40) { if (GFX.r2130 & 2) { DrawTilePtr = DrawTile16Add1_2; DrawClippedTilePtr = DrawClippedTile16Add1_2; } else { // Fixed colour addition DrawTilePtr = DrawTile16FixedAdd1_2; DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2; } DrawLargePixelPtr = DrawLargePixel16Add1_2; } else { DrawTilePtr = DrawTile16Add; DrawClippedTilePtr = DrawClippedTile16Add; DrawLargePixelPtr = DrawLargePixel16Add; } } }}void S9xSetupOBJ (){#ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "Entering SetupOBJS()\n");#endif int SmallWidth, SmallHeight; int LargeWidth, LargeHeight; switch (PPU.OBJSizeSelect) { case 0: SmallWidth = SmallHeight = 8; LargeWidth = LargeHeight = 16; break; case 1: SmallWidth = SmallHeight = 8; LargeWidth = LargeHeight = 32; break; case 2: SmallWidth = SmallHeight = 8; LargeWidth = LargeHeight = 64; break; case 3: SmallWidth = SmallHeight = 16; LargeWidth = LargeHeight = 32; break; case 4: SmallWidth = SmallHeight = 16; LargeWidth = LargeHeight = 64; break; default: case 5: SmallWidth = SmallHeight = 32; LargeWidth = LargeHeight = 64; break; case 6: SmallWidth = 16; SmallHeight = 32; LargeWidth = 32; LargeHeight = 64; break; case 7: SmallWidth = 16; SmallHeight = 32; LargeWidth = LargeHeight = 32; break; } if(IPPU.InterlaceSprites) { SmallHeight>>=1; LargeHeight>>=1; }#ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "Sizes are %dx%d and %dx%d\n", SmallWidth, SmallHeight, LargeWidth, LargeHeight);#endif /* OK, we have three cases here. Either there's no priority, priority is * normal FirstSprite, or priority is FirstSprite+Y. The first two are * easy, the last is somewhat more ... interesting. So we split them up. */ int Height; uint8 S;#ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "Priority rotation=%d, OAMAddr=%d -> ", PPU.OAMPriorityRotation, PPU.OAMAddr*2 | (PPU.OAMFlip&1));#endif if(!PPU.OAMPriorityRotation || !(PPU.OAMFlip&PPU.OAMAddr&1)){#ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "normal FirstSprite = %02x\n", PPU.FirstSprite);#endif /* normal case */ uint8 LineOBJ[SNES_HEIGHT_EXTENDED]; memset(LineOBJ, 0, sizeof(LineOBJ)); for(int i=0; i<SNES_HEIGHT_EXTENDED; i++){ GFX.OBJLines[i].RTOFlags=0; GFX.OBJLines[i].Tiles=34; for(int j=0; j<32; j++){ GFX.OBJLines[i].OBJ[j].Sprite=-1; } } uint8 FirstSprite=PPU.FirstSprite; S=FirstSprite; do { if(PPU.OBJ[S].Size){ GFX.OBJWidths[S]=LargeWidth; Height=LargeHeight; } else { GFX.OBJWidths[S]=SmallWidth; Height=SmallHeight; } int HPos=PPU.OBJ[S].HPos; if(HPos==-256) HPos=256; if(HPos>-GFX.OBJWidths[S] && HPos<=256) { if(HPos<0){ GFX.OBJVisibleTiles[S]=(GFX.OBJWidths[S]+HPos+7)>>3; } else if(HPos+GFX.OBJWidths[S]>=257){ GFX.OBJVisibleTiles[S]=(257-HPos+7)>>3; } else { GFX.OBJVisibleTiles[S]=GFX.OBJWidths[S]>>3; } for(uint8 line=0, Y=(uint8)(PPU.OBJ[S].VPos&0xff); line<Height; Y++, line++){ if(Y>=SNES_HEIGHT_EXTENDED) continue; if(LineOBJ[Y]>=32){ GFX.OBJLines[Y].RTOFlags|=0x40;#ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S);#endif continue; } GFX.OBJLines[Y].Tiles-=GFX.OBJVisibleTiles[S]; if(GFX.OBJLines[Y].Tiles<0) GFX.OBJLines[Y].RTOFlags|=0x80; GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite=S; if(PPU.OBJ[S].VFlip){ // Yes, Width not Height. It so happens that the // sprites with H=2*W flip as two WxW sprites. GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line=line^(GFX.OBJWidths[S]-1); } else { GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line=line; } LineOBJ[Y]++; } } S=(S+1)&0x7F; } while(S!=FirstSprite); for(int Y=1; Y<SNES_HEIGHT_EXTENDED; Y++){ GFX.OBJLines[Y].RTOFlags |= GFX.OBJLines[Y-1].RTOFlags; } } else { /* evil FirstSprite+Y case */#ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "FirstSprite+Y\n");#endif /* First, find out which sprites are on which lines */ uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128]; memset(OBJOnLine, 0, sizeof(OBJOnLine)); for(S=0; S<128; S++){ if(PPU.OBJ[S].Size){ GFX.OBJWidths[S]=LargeWidth; Height=LargeHeight; } else { GFX.OBJWidths[S]=SmallWidth; Height=SmallHeight; } int HPos=PPU.OBJ[S].HPos; if(HPos==-256) HPos=256; if(HPos>-GFX.OBJWidths[S] && HPos<=256) { if(HPos<0){ GFX.OBJVisibleTiles[S]=(GFX.OBJWidths[S]+HPos+7)>>3; } else if(HPos+GFX.OBJWidths[S]>=257){ GFX.OBJVisibleTiles[S]=(257-HPos+7)>>3; } else { GFX.OBJVisibleTiles[S]=GFX.OBJWidths[S]>>3; } for(uint8 line=0, Y=(uint8)(PPU.OBJ[S].VPos&0xff); line<Height; Y++, line++){ if(Y>=SNES_HEIGHT_EXTENDED) continue; if(PPU.OBJ[S].VFlip){ // Yes, Width not Height. It so happens that the // sprites with H=2*W flip as two WxW sprites. OBJOnLine[Y][S]=(line^(GFX.OBJWidths[S]-1)) | 0x80; } else { OBJOnLine[Y][S]=line | 0x80; } } } } /* Now go through and pull out those OBJ that are actually visible. */ int j; for(int Y=0; Y<SNES_HEIGHT_EXTENDED; Y++){ GFX.OBJLines[Y].RTOFlags=Y?0:GFX.OBJLines[Y-1].RTOFlags; GFX.OBJLines[Y].Tiles=34; uint8 FirstSprite=(PPU.FirstSprite+Y)&0x7F; S=FirstSprite; j=0; do { if(OBJOnLine[Y][S]){ if(j>=32){ GFX.OBJLines[Y].RTOFlags|=0x40;#ifdef MK_DEBUG_RTO if(Settings.BGLayering) fprintf(stderr, "%d: OBJ %02x ranged over\n", Y, S);#endif break; } GFX.OBJLines[Y].Tiles-=GFX.OBJVisibleTiles[S]; if(GFX.OBJLines[Y].Tiles<0) GFX.OBJLines[Y].RTOFlags|=0x80; GFX.OBJLines[Y].OBJ[j].Sprite=S; GFX.OBJLines[Y].OBJ[j++].Line=OBJOnLine[Y][S]&~0x80; } S=(S+1)&0x7F; } while(S!=FirstSprite);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -