Path: blob/master/libsnes/bsnes/snes/alt/ppu-performance/ppu.cpp
2 views
#include <snes/snes.hpp>12#define PPU_CPP3namespace SNES {45PPU ppu;67#include "mmio/mmio.cpp"8#include "window/window.cpp"9#include "cache/cache.cpp"10#include "background/background.cpp"11#include "sprite/sprite.cpp"12#include "screen/screen.cpp"13#include "serialization.cpp"1415void PPU::step(unsigned clocks) {16clock += clocks;17}1819void PPU::synchronize_cpu() {20if(CPU::Threaded == true) {21if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);22} else {23while(clock >= 0) cpu.enter();24}25}2627void PPU::Enter() { ppu.enter(); }2829void PPU::enter() {30while(true) {31if(scheduler.sync == Scheduler::SynchronizeMode::All) {32scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);33}3435scanline();36if(vcounter() < display.height && vcounter()) {37add_clocks(512);38render_scanline();39add_clocks(lineclocks() - 512);40} else {41add_clocks(lineclocks());42}43}44}4546void PPU::add_clocks(unsigned clocks) {47tick(clocks);48step(clocks);49synchronize_cpu();50}5152void PPU::render_scanline() {53if(display.framecounter) return; //skip this frame?54bg1.scanline();55bg2.scanline();56bg3.scanline();57bg4.scanline();58if(regs.display_disable) return screen.render_black();59screen.scanline();60bg1.render();61bg2.render();62bg3.render();63bg4.render();64sprite.render();65screen.render();66}6768void PPU::scanline() {69display.width = !hires() ? 256 : 512;70display.height = !overscan() ? 225 : 240;71if(vcounter() == 0) frame();72if(vcounter() == display.height && regs.display_disable == false) sprite.address_reset();73}7475void PPU::frame() {76sprite.frame();77system.frame();78display.interlace = regs.interlace;79display.overscan = regs.overscan;80display.framecounter = display.frameskip == 0 ? 0 : (display.framecounter + 1) % display.frameskip;81}8283void PPU::enable() {84function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };85function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };8687bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);88bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);89}9091void PPU::power() {92for(int i=0;i<128*1024;i++) vram[i] = 0;93for(int i=0;i<544;i++) oam[i] = 0;94for(int i=0;i<512;i++) cgram[i] = 0;95reset();96}9798void PPU::reset() {99create(Enter, system.cpu_frequency());100PPUcounter::reset();101memset(surface, 0, 512 * 512 * sizeof(uint32));102mmio_reset();103display.interlace = false;104display.overscan = false;105}106107void PPU::layer_enable(unsigned layer, unsigned priority, bool enable) {108switch(layer * 4 + priority) {109case 0: bg1.priority0_enable = enable; break;110case 1: bg1.priority1_enable = enable; break;111case 4: bg2.priority0_enable = enable; break;112case 5: bg2.priority1_enable = enable; break;113case 8: bg3.priority0_enable = enable; break;114case 9: bg3.priority1_enable = enable; break;115case 12: bg4.priority0_enable = enable; break;116case 13: bg4.priority1_enable = enable; break;117case 16: sprite.priority0_enable = enable; break;118case 17: sprite.priority1_enable = enable; break;119case 18: sprite.priority2_enable = enable; break;120case 19: sprite.priority3_enable = enable; break;121}122}123124void PPU::set_frameskip(unsigned frameskip) {125display.frameskip = frameskip;126display.framecounter = 0;127}128129PPU::PPU() :130cache(*this),131bg1(*this, Background::ID::BG1),132bg2(*this, Background::ID::BG2),133bg3(*this, Background::ID::BG3),134bg4(*this, Background::ID::BG4),135sprite(*this),136screen(*this),137vram(nullptr),138oam(nullptr),139cgram(nullptr)140{141surface = new uint32[512 * 512];142output = surface + 16 * 512;143display.width = 256;144display.height = 224;145display.frameskip = 0;146display.framecounter = 0;147}148149PPU::~PPU() {150delete[] surface;151interface()->freeSharedMemory(vram);152interface()->freeSharedMemory(oam);153interface()->freeSharedMemory(cgram);154}155156void PPU::initialize()157{158vram = (uint8*)interface()->allocSharedMemory("VRAM",128 * 1024);159oam = (uint8*)interface()->allocSharedMemory("OAM",544);160cgram = (uint8*)interface()->allocSharedMemory("CGRAM",512);161}162163}164165166