public unsafe void Begin() { if (_CanRender) { _IsRendering = true; lastLineState = RenderLineState.RenderClipping; if (highResSnap) { log = new StreamWriter(snapfile + "log.txt"); takingSnap = true; } } }
public void BlankPixel(int X, int Y) { if (_CanRender & _IsRendering) { //Check if we should cut this line if (Y >= _FirstLinesTCut & Y < (_ScanLines + _FirstLinesTCut)) { if (lastLineState != oppu.rstate) { lastLineState = oppu.rstate; lastTileNo = -1; } if (hasHiResPack) { RenderTile(X, Y); } } } }
public void DrawPixel(int X, int Y, int Color) { if (_CanRender & _IsRendering) { //Check if we should cut this line if (Y >= _FirstLinesTCut & Y < (_ScanLines + _FirstLinesTCut)) { if (lastLineState != oppu.rstate) { lastLineState = oppu.rstate; lastTileNo = -1; } if (oppu.rstate == RenderLineState.ClearScanline || oppu.rstate == RenderLineState.RenderClipping || !hasHiResPack) { DrawBasicPixel(X, Y, Color); } else { RenderTile(X, Y); } } } }
public void RunPPU() { ScanCycle++; TileCycle++; if (ScanCycle == 341) { ScanCycle = 0; TileCycle = 8; SpritesRendered = false; ScanLine++; //Render the actual data to be displayed on the screen if (ScanLine >= ScanlineOfEndOfVblank & ScanLine <= 239 + ScanlineOfEndOfVblank) { rstate = RenderLineState.ClearScanline; //Clean up the line from before /*fixed (byte* pSrc = piorityBuff) * { * byte* ps = pSrc; * for (int i = 0; i < 256; i += 8) * { *((UInt64*)(ps + i)) = 0; * } * }*/ //Draw background color byte B = MEM_PPU[0x3F00]; if (B >= 63) { B = 63; } for (int i = 0; i < 256; i++) { VIDEO.DrawPixel(i, ScanLine - ScanlineOfEndOfVblank, PALETTE[B]); piorityBuff[i] = 0; } //Tick mapper timer (scanline timer) if (BackgroundVisibility | SpriteVisibility) { MEM_CPU.MAPPER.TickScanlineTimer(); } } //do nothing for 1 scanline if (ScanLine == ScanlinesPerFrame) { //Handle the speed if (!NoLimiter) { double currentTime = Timer.GetCurrentTime(); _currentFrameTime = currentTime - _lastFrameTime; if ((_currentFrameTime < FramePeriod)) { while (true) { if ((Timer.GetCurrentTime() - _lastFrameTime) >= FramePeriod) { break; } } } } _lastFrameTime = Timer.GetCurrentTime(); ScanLine = -1; FPS++; //Odd frame ? only in ntsc if (TV == TVFORMAT.NTSC) { OddFrame = !OddFrame; if (!OddFrame & BackgroundVisibility) { if (BBackgroundVisibility) { ScanCycle += 1; } } BBackgroundVisibility = BackgroundVisibility; } //render into screen VIDEO.RenderFrame(); } } else if (ScanLine >= ScanlineOfEndOfVblank & ScanLine <= 239 + ScanlineOfEndOfVblank) { if (ScanCycle < 256) //Render on the screen { if (TileCycle >= 8) //Render BG tile each 8 cycles { if (BackgroundVisibility) { if (rstate != RenderLineState.RenderBackground) { rstate = RenderLineState.RenderBackground; hflip = true; vflip = false; } RenderNextBackgroundTile(); } TileCycle -= 8; } } else if (!SpritesRendered) { if (SpriteVisibility) { rstate = RenderLineState.RenderSprite; RenderSprites(); } if (BackgroundClipping) { for (int i = 0; i < 8; i++) { VIDEO.DrawPixel(i, ScanLine - ScanlineOfEndOfVblank, 0); } } //Update Hscroll if (SpriteVisibility | BackgroundVisibility) { VRAM_ADDRESS = (ushort)((VRAM_ADDRESS & 0x7BE0) | (VRAM_TEMP & 0x041F)); nameTableAddress = (VRAM_ADDRESS & 0x0800) + (VRAM_TEMP & 0x0400) + 0x2000; HScroll = (((VRAM_TEMP & 0x001F) << 3) | TileX); } SpritesRendered = true; } } //Start of vblank if (ScanLine == 0 & ScanCycle == 339) { if (ExecuteNMIOnVBlank) { CPU.NMIRequest = true; } VBlank = true; } //End of vblank else if (ScanLine == ScanlineOfEndOfVblank) { if (ScanCycle == 305) { //Update Vscroll if (SpriteVisibility | BackgroundVisibility) { VRAM_ADDRESS = VRAM_TEMP; VScroll = (((VRAM_TEMP & 0x03E0) >> 2) | ((VRAM_TEMP & 0x7000) >> 12)); if (VScroll >= 240) { VScroll -= 256; } } } if (ScanCycle == 339) { VIDEO.Begin(); //Clear flags Sprite0Hit = false; VBlank = false; SpriteCrossed = 0; } } }