2010-08-09 13:28:56 +00:00
|
|
|
#ifdef PPU_CPP
|
|
|
|
|
|
|
|
void PPU::Screen::scanline() {
|
|
|
|
output = self.output + self.vcounter() * 1024;
|
|
|
|
if(self.display.interlace && self.field()) output += 512;
|
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
//the first hires pixel of each scanline is transparent
|
|
|
|
//note: exact value initializations are not confirmed on hardware
|
|
|
|
math.main.color = get_color(0);
|
|
|
|
math.sub.color = math.main.color;
|
2011-04-27 08:57:31 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
math.main.color_enable = !(self.window.regs.col_main_mask & 1);
|
|
|
|
math.sub.color_enable = !(self.window.regs.col_sub_mask & 1) && regs.back_color_enable;
|
|
|
|
|
|
|
|
math.transparent = true;
|
|
|
|
math.addsub_mode = false;
|
|
|
|
math.color_halve = regs.color_halve && !regs.addsub_mode && math.main.color_enable;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
void PPU::Screen::run() {
|
|
|
|
if(ppu.vcounter() == 0) return;
|
2011-04-30 13:12:15 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
bool hires = self.regs.pseudo_hires || self.regs.bgmode == 5 || self.regs.bgmode == 6;
|
|
|
|
auto sscolor = get_pixel_sub(hires);
|
|
|
|
auto mscolor = get_pixel_main();
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-12-20 11:40:39 +00:00
|
|
|
*output++ = (self.regs.display_brightness << 15) | (hires ? sscolor : mscolor);
|
|
|
|
*output++ = (self.regs.display_brightness << 15) | (mscolor);
|
2013-01-23 08:28:35 +00:00
|
|
|
}
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
uint16 PPU::Screen::get_pixel_sub(bool hires) {
|
|
|
|
if(self.regs.display_disable || (!self.regs.overscan && self.vcounter() >= 225)) return 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
unsigned priority = 0;
|
|
|
|
if(self.bg1.output.sub.priority) {
|
|
|
|
priority = self.bg1.output.sub.priority;
|
2010-08-09 13:28:56 +00:00
|
|
|
if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {
|
2013-01-23 08:28:35 +00:00
|
|
|
math.sub.color = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.tile);
|
2010-08-09 13:28:56 +00:00
|
|
|
} else {
|
2013-01-23 08:28:35 +00:00
|
|
|
math.sub.color = get_color(self.bg1.output.sub.palette);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.bg2.output.sub.priority > priority) {
|
|
|
|
priority = self.bg2.output.sub.priority;
|
|
|
|
math.sub.color = get_color(self.bg2.output.sub.palette);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.bg3.output.sub.priority > priority) {
|
|
|
|
priority = self.bg3.output.sub.priority;
|
|
|
|
math.sub.color = get_color(self.bg3.output.sub.palette);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.bg4.output.sub.priority > priority) {
|
|
|
|
priority = self.bg4.output.sub.priority;
|
|
|
|
math.sub.color = get_color(self.bg4.output.sub.palette);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.sprite.output.sub.priority > priority) {
|
|
|
|
priority = self.sprite.output.sub.priority;
|
|
|
|
math.sub.color = get_color(self.sprite.output.sub.palette);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(math.transparent = (priority == 0)) math.sub.color = get_color(0);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
if(!hires) return 0;
|
|
|
|
if(!math.sub.color_enable) return math.main.color_enable ? math.sub.color : 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
return addsub(
|
|
|
|
math.main.color_enable ? math.sub.color : 0,
|
|
|
|
math.addsub_mode ? math.main.color : fixed_color()
|
|
|
|
);
|
|
|
|
}
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
uint16 PPU::Screen::get_pixel_main() {
|
|
|
|
if(self.regs.display_disable || (!self.regs.overscan && self.vcounter() >= 225)) return 0;
|
|
|
|
|
|
|
|
unsigned priority = 0;
|
|
|
|
if(self.bg1.output.main.priority) {
|
|
|
|
priority = self.bg1.output.main.priority;
|
2010-08-09 13:28:56 +00:00
|
|
|
if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {
|
2013-01-23 08:28:35 +00:00
|
|
|
math.main.color = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.tile);
|
2010-08-09 13:28:56 +00:00
|
|
|
} else {
|
2013-01-23 08:28:35 +00:00
|
|
|
math.main.color = get_color(self.bg1.output.main.palette);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
math.sub.color_enable = regs.bg1_color_enable;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.bg2.output.main.priority > priority) {
|
|
|
|
priority = self.bg2.output.main.priority;
|
|
|
|
math.main.color = get_color(self.bg2.output.main.palette);
|
|
|
|
math.sub.color_enable = regs.bg2_color_enable;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.bg3.output.main.priority > priority) {
|
|
|
|
priority = self.bg3.output.main.priority;
|
|
|
|
math.main.color = get_color(self.bg3.output.main.palette);
|
|
|
|
math.sub.color_enable = regs.bg3_color_enable;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.bg4.output.main.priority > priority) {
|
|
|
|
priority = self.bg4.output.main.priority;
|
|
|
|
math.main.color = get_color(self.bg4.output.main.palette);
|
|
|
|
math.sub.color_enable = regs.bg4_color_enable;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(self.sprite.output.main.priority > priority) {
|
|
|
|
priority = self.sprite.output.main.priority;
|
|
|
|
math.main.color = get_color(self.sprite.output.main.palette);
|
|
|
|
math.sub.color_enable = regs.oam_color_enable && self.sprite.output.main.palette >= 192;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
2013-01-23 08:28:35 +00:00
|
|
|
if(priority == 0) {
|
|
|
|
math.main.color = get_color(0);
|
|
|
|
math.sub.color_enable = regs.back_color_enable;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
if(!self.window.output.sub.color_enable) math.sub.color_enable = false;
|
|
|
|
math.main.color_enable = self.window.output.main.color_enable;
|
|
|
|
if(!math.sub.color_enable) return math.main.color_enable ? math.main.color : 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
if(regs.addsub_mode && math.transparent) {
|
|
|
|
math.addsub_mode = false;
|
|
|
|
math.color_halve = false;
|
2010-08-09 13:28:56 +00:00
|
|
|
} else {
|
2013-01-23 08:28:35 +00:00
|
|
|
math.addsub_mode = regs.addsub_mode;
|
|
|
|
math.color_halve = regs.color_halve && math.main.color_enable;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
return addsub(
|
|
|
|
math.main.color_enable ? math.main.color : 0,
|
|
|
|
math.addsub_mode ? math.sub.color : fixed_color()
|
|
|
|
);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
uint16 PPU::Screen::addsub(unsigned x, unsigned y) {
|
2010-08-09 13:28:56 +00:00
|
|
|
if(!regs.color_mode) {
|
2013-01-23 08:28:35 +00:00
|
|
|
if(!math.color_halve) {
|
2010-08-09 13:28:56 +00:00
|
|
|
unsigned sum = x + y;
|
|
|
|
unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420;
|
|
|
|
return (sum - carry) | (carry - (carry >> 5));
|
|
|
|
} else {
|
|
|
|
return (x + y - ((x ^ y) & 0x0421)) >> 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsigned diff = x - y + 0x8420;
|
|
|
|
unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420;
|
2013-01-23 08:28:35 +00:00
|
|
|
if(!math.color_halve) {
|
2010-08-09 13:28:56 +00:00
|
|
|
return (diff - borrow) & (borrow - (borrow >> 5));
|
|
|
|
} else {
|
|
|
|
return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 PPU::Screen::get_color(unsigned palette) {
|
|
|
|
palette <<= 1;
|
2010-09-24 13:15:21 +00:00
|
|
|
self.regs.cgram_iaddr = palette;
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
return ppu.cgram[palette + 0] + (ppu.cgram[palette + 1] << 8);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint16 PPU::Screen::get_direct_color(unsigned palette, unsigned tile) {
|
|
|
|
//palette = -------- BBGGGRRR
|
|
|
|
//tile = ---bgr-- --------
|
|
|
|
//output = 0BBb00GG Gg0RRRr0
|
|
|
|
return ((palette << 7) & 0x6000) + ((tile >> 0) & 0x1000)
|
|
|
|
+ ((palette << 4) & 0x0380) + ((tile >> 5) & 0x0040)
|
|
|
|
+ ((palette << 2) & 0x001c) + ((tile >> 9) & 0x0002);
|
|
|
|
}
|
|
|
|
|
2013-01-23 08:28:35 +00:00
|
|
|
uint16 PPU::Screen::fixed_color() const {
|
|
|
|
return (regs.color_b << 10) | (regs.color_g << 5) | (regs.color_r << 0);
|
|
|
|
}
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
void PPU::Screen::reset() {
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.addsub_mode = random(false);
|
|
|
|
regs.direct_color = random(false);
|
|
|
|
regs.color_mode = random(false);
|
|
|
|
regs.color_halve = random(false);
|
|
|
|
regs.bg1_color_enable = random(false);
|
|
|
|
regs.bg2_color_enable = random(false);
|
|
|
|
regs.bg3_color_enable = random(false);
|
|
|
|
regs.bg4_color_enable = random(false);
|
|
|
|
regs.oam_color_enable = random(false);
|
|
|
|
regs.back_color_enable = random(false);
|
|
|
|
regs.color_r = random(0);
|
|
|
|
regs.color_g = random(0);
|
|
|
|
regs.color_b = random(0);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
PPU::Screen::Screen(PPU& self) : self(self) {
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|