private void RunVBlank() { if (lcdClock >= 144) { lcdClock -= 144; LY++; // Move to next line // If LY == LYC, set the flag and raise interrupt if it's enabled matchFlag = LY == LYC; if (matchFlag && (enabledInterrupts & GPUInterrupts.OnMatch) != 0) { LCDCInterrupt?.Invoke(); } if (LY == 154) { renderTask.Wait(); // Wait for the frame to finish rendering // Start rendering the next frame LY = 0; if (LY == LYC && (enabledInterrupts & GPUInterrupts.OnMatch) != 0) { LCDCInterrupt?.Invoke(); } lcdMode = GPUMode.OAMRead; if ((enabledInterrupts & GPUInterrupts.OnOAMRead) != 0) { LCDCInterrupt?.Invoke(); } renderTask = Task.Run(() => LoadSpriteData()); } } }
private void RunVRAMRead() { if (lcdClock >= 43) { renderTask.Wait(); // Wait for pre-rendering to finish lcdClock -= 43; // Switch to HBlank mode lcdMode = GPUMode.HBlank; if ((enabledInterrupts & GPUInterrupts.OnHBlank) != 0) { LCDCInterrupt?.Invoke(); } // No task is run during HBlank } }
private void RunHBlank() { if (lcdClock >= 51) // Horizontal Blank lasts for ~51 m-clock ticks { lcdClock -= 51; LY++; // Move to next line // If LY == LYC, set the flag and raise interrupt if it's enabled matchFlag = LY == LYC; if (matchFlag && (enabledInterrupts & GPUInterrupts.OnMatch) != 0) { LCDCInterrupt?.Invoke(); } if (LY == 144) // Switch to vertical blank mode { // Begin rendering the frame renderTask = Task.Run(() => RenderFrame()); lcdMode = GPUMode.VBlank; // signal vertical blank interrupt and LCD interrupt (if enabled) VBlankInterrupt?.Invoke(); if ((enabledInterrupts & GPUInterrupts.OnVBlank) != 0) { LCDCInterrupt?.Invoke(); } } else // Start rendering the next line { lcdMode = GPUMode.OAMRead; if ((enabledInterrupts & GPUInterrupts.OnOAMRead) != 0) { LCDCInterrupt?.Invoke(); } renderTask = Task.Run(() => LoadSpriteData()); } } }