Path: blob/master/libsnes/bsnes/snes/ppu/screen/screen.cpp
2 views
#ifdef PPU_CPP12void PPU::Screen::scanline() {3output = self.output + self.vcounter() * 1024;4if(self.display.interlace && self.field()) output += 512;5}67void PPU::Screen::run() {8if(ppu.vcounter() == 0) return;910uint32 color;11if(self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) {12color = get_pixel(0);13*output++ = color;14*output++ = color;15} else {16color = get_pixel(1);17*output++ = color;18color = get_pixel(0);19*output++ = color;20}21}2223uint32 PPU::Screen::get_pixel(bool swap) {24if(ppu.regs.overscan == false && ppu.vcounter() >= 225) return 0x0000;2526enum source_t { BG1, BG2, BG3, BG4, OAM, BACK };27bool color_enable[] = { regs.bg1_color_enable, regs.bg2_color_enable, regs.bg3_color_enable, regs.bg4_color_enable, regs.oam_color_enable, regs.back_color_enable };2829//===========30//main screen31//===========3233unsigned priority_main = 0;34unsigned color_main;35unsigned source_main;3637if(self.bg1.output.main.priority) {38priority_main = self.bg1.output.main.priority;39if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {40color_main = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.tile);41} else {42color_main = get_color(self.bg1.output.main.palette);43}44source_main = BG1;45}46if(self.bg2.output.main.priority > priority_main) {47priority_main = self.bg2.output.main.priority;48color_main = get_color(self.bg2.output.main.palette);49source_main = BG2;50}51if(self.bg3.output.main.priority > priority_main) {52priority_main = self.bg3.output.main.priority;53color_main = get_color(self.bg3.output.main.palette);54source_main = BG3;55}56if(self.bg4.output.main.priority > priority_main) {57priority_main = self.bg4.output.main.priority;58color_main = get_color(self.bg4.output.main.palette);59source_main = BG4;60}61if(self.sprite.output.main.priority > priority_main) {62priority_main = self.sprite.output.main.priority;63color_main = get_color(self.sprite.output.main.palette);64source_main = OAM;65}66if(priority_main == 0) {67color_main = get_color(0);68source_main = BACK;69}7071//==========72//sub screen73//==========7475unsigned priority_sub = 0;76unsigned color_sub;77unsigned source_sub;7879if(self.bg1.output.sub.priority) {80priority_sub = self.bg1.output.sub.priority;81if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {82color_sub = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.tile);83} else {84color_sub = get_color(self.bg1.output.sub.palette);85}86source_sub = BG1;87}88if(self.bg2.output.sub.priority > priority_sub) {89priority_sub = self.bg2.output.sub.priority;90color_sub = get_color(self.bg2.output.sub.palette);91source_sub = BG2;92}93if(self.bg3.output.sub.priority > priority_sub) {94priority_sub = self.bg3.output.sub.priority;95color_sub = get_color(self.bg3.output.sub.palette);96source_sub = BG3;97}98if(self.bg4.output.sub.priority > priority_sub) {99priority_sub = self.bg4.output.sub.priority;100color_sub = get_color(self.bg4.output.sub.palette);101source_sub = BG4;102}103if(self.sprite.output.sub.priority > priority_sub) {104priority_sub = self.sprite.output.sub.priority;105color_sub = get_color(self.sprite.output.sub.palette);106source_sub = OAM;107}108if(priority_sub == 0) {109if(self.regs.pseudo_hires == true || self.regs.bgmode == 5 || self.regs.bgmode == 6) {110color_sub = get_color(0);111} else {112color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0);113}114source_sub = BACK;115}116117if(swap == true) {118std::swap(priority_main, priority_sub);119std::swap(color_main, color_sub);120std::swap(source_main, source_sub);121}122123uint16 output;124if(!regs.addsub_mode) {125source_sub = BACK;126color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0);127}128129if(self.window.output.main.color_enable == false) {130if(self.window.output.sub.color_enable == false) {131return 0x0000;132}133color_main = 0x0000;134}135136bool color_exempt = (source_main == OAM && self.sprite.output.main.palette < 192);137if(!color_exempt && color_enable[source_main] && self.window.output.sub.color_enable) {138bool halve = false;139if(regs.color_halve && self.window.output.main.color_enable) {140if(!regs.addsub_mode || source_sub != BACK) halve = true;141}142output = addsub(color_main, color_sub, halve);143} else {144output = color_main;145}146147//========148//lighting149//========150151if(self.regs.display_disable) return 0;152return (self.regs.display_brightness << 15) | output;153}154155uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) {156if(!regs.color_mode) {157if(!halve) {158unsigned sum = x + y;159unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420;160return (sum - carry) | (carry - (carry >> 5));161} else {162return (x + y - ((x ^ y) & 0x0421)) >> 1;163}164} else {165unsigned diff = x - y + 0x8420;166unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420;167if(!halve) {168return (diff - borrow) & (borrow - (borrow >> 5));169} else {170return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1;171}172}173}174175uint16 PPU::Screen::get_color(unsigned palette) {176palette <<= 1;177self.regs.cgram_iaddr = palette;178return ppu.cgram[palette + 0] + (ppu.cgram[palette + 1] << 8);179}180181uint16 PPU::Screen::get_direct_color(unsigned palette, unsigned tile) {182//palette = -------- BBGGGRRR183//tile = ---bgr-- --------184//output = 0BBb00GG Gg0RRRr0185return ((palette << 7) & 0x6000) + ((tile >> 0) & 0x1000)186+ ((palette << 4) & 0x0380) + ((tile >> 5) & 0x0040)187+ ((palette << 2) & 0x001c) + ((tile >> 9) & 0x0002);188}189190void PPU::Screen::reset() {191regs.addsub_mode = random(false);192regs.direct_color = random(false);193regs.color_mode = random(false);194regs.color_halve = random(false);195regs.bg1_color_enable = random(false);196regs.bg2_color_enable = random(false);197regs.bg3_color_enable = random(false);198regs.bg4_color_enable = random(false);199regs.oam_color_enable = random(false);200regs.back_color_enable = random(false);201regs.color_r = random(0);202regs.color_g = random(0);203regs.color_b = random(0);204}205206PPU::Screen::Screen(PPU &self) : self(self) {207}208209#endif210211212