mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v063r11 release.
Writing to SETINI will update video mode priorities for EXTBG mode. Merged pixel output { main, sub { valid, priority } } into just priority. A priority of zero is considered invalid now. Merged pixel output { main, sub { palette_index, palette_number } } into just palette with the tiledata bits for direct color mode at d8-d10. This cuts a lot of copying and extra comparisons out of the final screen rendering pass, though it doesn't really help speed. Output is always 512x448 now. Having trouble deciding on how to do video for that, but I'll post more on that later. Really need to figure out how offset-per-tile fetches in regards to lores v hires and SC size, tile size and wrapping. For now, I simplified it to constants; whereas the scanline-renderer uses the BG3 settings. I also made it not perform OPT lookup on BG3 and BG4 anymore. Skips a pointless trickery of setting the OPT valid bit to zero for BG3,BG4 and is faster. Forgot an overscan check in sprite drawing, should draw sprites properly to V=225-239 now. Made the mode7 variable names more consistent.
This commit is contained in:
parent
c33f70a8c6
commit
35fdb71f3d
BIN
bsnes-sppu.exe
BIN
bsnes-sppu.exe
Binary file not shown.
|
@ -13,7 +13,7 @@ objects :=
|
|||
# link += -lgcov
|
||||
|
||||
# profile-guided optimization
|
||||
flags += -fprofile-use
|
||||
# flags += -fprofile-use
|
||||
|
||||
# platform
|
||||
ifeq ($(platform),x)
|
||||
|
|
|
@ -75,7 +75,6 @@ void sCPU::mmio_w4200(uint8 data) {
|
|||
|
||||
//WRIO
|
||||
void sCPU::mmio_w4201(uint8 data) {
|
||||
scheduler.sync_cpuppu();
|
||||
if((status.pio & 0x80) && !(data & 0x80)) {
|
||||
ppu.latch_counters();
|
||||
}
|
||||
|
|
|
@ -66,14 +66,7 @@ public:
|
|||
unsigned frames_executed;
|
||||
} status;
|
||||
|
||||
//PPU1 version number
|
||||
//* 1 is known
|
||||
//* reported by $213e
|
||||
uint8 ppu1_version;
|
||||
|
||||
//PPU2 version number
|
||||
//* 1 and 3 are known
|
||||
//* reported by $213f
|
||||
uint8 ppu2_version;
|
||||
|
||||
virtual bool interlace() const = 0;
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
void sPPU::Background::scanline() {
|
||||
if(self.vcounter() == 1) {
|
||||
regs.mosaic_y = 1;
|
||||
regs.mosaic_countdown = 0;
|
||||
state.mosaic_y = 1;
|
||||
state.mosaic_countdown = 0;
|
||||
} else {
|
||||
if(!regs.mosaic || !regs.mosaic_countdown) regs.mosaic_y = self.vcounter();
|
||||
if(!regs.mosaic_countdown) regs.mosaic_countdown = regs.mosaic + 1;
|
||||
regs.mosaic_countdown--;
|
||||
if(!regs.mosaic || !state.mosaic_countdown) state.mosaic_y = self.vcounter();
|
||||
if(!state.mosaic_countdown) state.mosaic_countdown = regs.mosaic + 1;
|
||||
state.mosaic_countdown--;
|
||||
}
|
||||
|
||||
state.x = 0;
|
||||
|
@ -19,8 +19,8 @@ void sPPU::Background::run() {
|
|||
bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6);
|
||||
|
||||
if((self.hcounter() & 2) == 0) {
|
||||
output.main.valid = false;
|
||||
output.sub.valid = false;
|
||||
output.main.priority = 0;
|
||||
output.sub.priority = 0;
|
||||
} else if(hires == false) {
|
||||
return;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ void sPPU::Background::run() {
|
|||
if(regs.main_enabled == false && regs.sub_enabled == false) return;
|
||||
|
||||
unsigned x = state.x++;
|
||||
unsigned y = regs.mosaic_y;
|
||||
unsigned y = state.mosaic_y;
|
||||
if(regs.mode == Mode::Mode7) return run_mode7(x, y);
|
||||
|
||||
unsigned color_depth = (regs.mode == Mode::BPP2 ? 0 : regs.mode == Mode::BPP4 ? 1 : 2);
|
||||
|
@ -63,7 +63,10 @@ void sPPU::Background::run() {
|
|||
unsigned hoffset = hscroll + mosaic_table[regs.mosaic][x];
|
||||
unsigned voffset = vscroll + y;
|
||||
|
||||
if(self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6) {
|
||||
bool offset_per_tile = (self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6);
|
||||
if(id != ID::BG1 && id != ID::BG2) offset_per_tile = false;
|
||||
|
||||
if(offset_per_tile) {
|
||||
uint16 opt_x = (x + (hscroll & 7));
|
||||
|
||||
//tile 0 is unaffected by offset-per-tile mode
|
||||
|
@ -71,14 +74,9 @@ void sPPU::Background::run() {
|
|||
uint16 hval; {
|
||||
unsigned px = (opt_x - 8) + (self.bg3.regs.hoffset & ~7);
|
||||
unsigned py = self.bg3.regs.voffset;
|
||||
|
||||
unsigned tx = (px & mask_x) >> tile_width;
|
||||
unsigned ty = (py & mask_y) >> tile_height;
|
||||
|
||||
unsigned tx = (px & (width - 1)) >> tile_width;
|
||||
unsigned ty = (py & (width - 1)) >> tile_height;
|
||||
uint16 pos = ((ty & 0x1f) << 5) + (tx & 0x1f);
|
||||
if(ty & 0x20) pos += screen_y;
|
||||
if(tx & 0x20) pos += screen_x;
|
||||
|
||||
uint16 addr = self.bg3.regs.screen_addr + (pos << 1);
|
||||
hval = memory::vram[addr + 0] + (memory::vram[addr + 1] << 8);
|
||||
}
|
||||
|
@ -86,19 +84,14 @@ void sPPU::Background::run() {
|
|||
uint16 vval; if(self.regs.bgmode != 4) {
|
||||
unsigned px = (opt_x - 8) + (self.bg3.regs.hoffset & ~7);
|
||||
unsigned py = self.bg3.regs.voffset + 8;
|
||||
|
||||
unsigned tx = (px & mask_x) >> tile_width;
|
||||
unsigned ty = (py & mask_y) >> tile_height;
|
||||
|
||||
unsigned tx = (px & (width - 1)) >> tile_width;
|
||||
unsigned ty = (py & (width - 1)) >> tile_height;
|
||||
uint16 pos = ((ty & 0x1f) << 5) + (tx & 0x1f);
|
||||
if(ty & 0x20) pos += screen_y;
|
||||
if(tx & 0x20) pos += screen_x;
|
||||
|
||||
uint16 addr = self.bg3.regs.screen_addr + (pos << 1);
|
||||
vval = memory::vram[addr + 0] + (memory::vram[addr + 1] << 8);
|
||||
}
|
||||
|
||||
unsigned opt_valid_bit = (id == ID::BG1 ? 0x2000 : id == ID::BG2 ? 0x4000 : 0x0000);
|
||||
unsigned opt_valid_bit = (id == ID::BG1 ? 0x2000 : 0x4000);
|
||||
|
||||
if(self.regs.bgmode == 4) {
|
||||
if(hval & opt_valid_bit) {
|
||||
|
@ -125,11 +118,9 @@ void sPPU::Background::run() {
|
|||
unsigned tile_number; {
|
||||
unsigned tx = hoffset >> tile_width;
|
||||
unsigned ty = voffset >> tile_height;
|
||||
|
||||
uint16 pos = ((ty & 0x1f) << 5) + (tx & 0x1f);
|
||||
if(ty & 0x20) pos += screen_y;
|
||||
if(tx & 0x20) pos += screen_x;
|
||||
|
||||
uint16 addr = regs.screen_addr + (pos << 1);
|
||||
tile_number = memory::vram[addr + 0] + (memory::vram[addr + 1] << 8);
|
||||
}
|
||||
|
@ -149,38 +140,30 @@ void sPPU::Background::run() {
|
|||
if(mirror_y) voffset ^= 7;
|
||||
if(mirror_x) hoffset ^= 7;
|
||||
|
||||
unsigned color = get_color(hoffset, voffset, tile_number);
|
||||
uint8 color = get_color(hoffset, voffset, tile_number);
|
||||
if(color == 0) return;
|
||||
|
||||
color += palette_index;
|
||||
|
||||
if(hires == false) {
|
||||
if(regs.main_enabled) {
|
||||
output.main.valid = true;
|
||||
output.main.palette = color;
|
||||
output.main.palette_number = palette_number;
|
||||
output.main.palette = color | (palette_number << 8);
|
||||
output.main.priority = priority;
|
||||
}
|
||||
|
||||
if(regs.sub_enabled) {
|
||||
output.sub.valid = true;
|
||||
output.sub.palette = color;
|
||||
output.sub.palette_number = palette_number;
|
||||
output.sub.palette = color | (palette_number << 8);
|
||||
output.sub.priority = priority;
|
||||
}
|
||||
} else {
|
||||
if(x & 1) {
|
||||
if(regs.main_enabled) {
|
||||
output.main.valid = true;
|
||||
output.main.palette = color;
|
||||
output.main.palette_number = palette_number;
|
||||
output.main.palette = color | (palette_number << 8);
|
||||
output.main.priority = priority;
|
||||
}
|
||||
} else {
|
||||
if(regs.sub_enabled) {
|
||||
output.sub.valid = true;
|
||||
output.sub.palette = color;
|
||||
output.sub.palette_number = palette_number;
|
||||
output.sub.palette = color | (palette_number << 8);
|
||||
output.sub.priority = priority;
|
||||
}
|
||||
}
|
||||
|
@ -241,12 +224,12 @@ unsigned sPPU::Background::get_color(unsigned x, unsigned y, uint16 offset) {
|
|||
|
||||
void sPPU::Background::reset() {
|
||||
state.x = 0;
|
||||
state.mosaic_y = 0;
|
||||
state.mosaic_countdown = 0;
|
||||
regs.tiledata_addr = 0;
|
||||
regs.screen_addr = 0;
|
||||
regs.screen_size = 0;
|
||||
regs.mosaic = 0;
|
||||
regs.mosaic_y = 0;
|
||||
regs.mosaic_countdown = 0;
|
||||
regs.tile_size = 0;
|
||||
regs.mode = 0;
|
||||
regs.priority0 = 0;
|
||||
|
@ -255,13 +238,9 @@ void sPPU::Background::reset() {
|
|||
regs.sub_enabled = 0;
|
||||
regs.hoffset = 0;
|
||||
regs.voffset = 0;
|
||||
output.main.valid = 0;
|
||||
output.main.palette = 0;
|
||||
output.main.palette_number = 0;
|
||||
output.main.priority = 0;
|
||||
output.sub.valid = 0;
|
||||
output.sub.palette = 0;
|
||||
output.sub.palette_number = 0;
|
||||
output.sub.priority = 0;
|
||||
}
|
||||
|
||||
|
@ -272,20 +251,6 @@ sPPU::Background::Background(sPPU &self, unsigned id) : self(self), id(id) {
|
|||
mosaic_table[m][x] = (x / (m + 1)) * (m + 1);
|
||||
}
|
||||
}
|
||||
|
||||
regs.tiledata_addr = 0x0000;
|
||||
regs.screen_addr = 0x0000;
|
||||
regs.screen_size = ScreenSize::Size32x32;
|
||||
regs.mosaic = 0;
|
||||
regs.mosaic_y = 0;
|
||||
regs.tile_size = TileSize::Size8x8;
|
||||
|
||||
regs.mode = Mode::BPP2;
|
||||
regs.priority0 = 0;
|
||||
regs.priority1 = 0;
|
||||
|
||||
regs.main_enabled = false;
|
||||
regs.sub_enabled = false;
|
||||
}
|
||||
|
||||
uint16 sPPU::Background::mosaic_table[16][4096];
|
||||
|
|
|
@ -10,6 +10,8 @@ public:
|
|||
|
||||
struct {
|
||||
unsigned x;
|
||||
unsigned mosaic_y;
|
||||
unsigned mosaic_countdown;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
|
@ -17,8 +19,6 @@ public:
|
|||
unsigned screen_addr;
|
||||
unsigned screen_size;
|
||||
unsigned mosaic;
|
||||
unsigned mosaic_y;
|
||||
unsigned mosaic_countdown;
|
||||
bool tile_size;
|
||||
|
||||
unsigned mode;
|
||||
|
@ -34,10 +34,8 @@ public:
|
|||
|
||||
struct {
|
||||
struct {
|
||||
bool valid;
|
||||
uint8 palette;
|
||||
uint8 palette_number;
|
||||
uint8 priority;
|
||||
unsigned priority; //0 = none (transparent)
|
||||
unsigned palette; //(direct_color_bits << 8) + index
|
||||
} main, sub;
|
||||
} output;
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ void sPPU::Background::run_mode7(unsigned x, unsigned y) {
|
|||
|
||||
signed cx = sclip<13>(self.regs.m7x);
|
||||
signed cy = sclip<13>(self.regs.m7y);
|
||||
signed hofs = sclip<13>(self.regs.m7hofs);
|
||||
signed vofs = sclip<13>(self.regs.m7vofs);
|
||||
signed hoffset = sclip<13>(self.regs.mode7_hoffset);
|
||||
signed voffset = sclip<13>(self.regs.mode7_voffset);
|
||||
|
||||
if(self.regs.mode7_hflip) x = 255 - x;
|
||||
if(self.regs.mode7_vflip) y = 255 - y;
|
||||
|
@ -29,8 +29,8 @@ void sPPU::Background::run_mode7(unsigned x, unsigned y) {
|
|||
mosaic_y = mosaic_table[self.bg1.regs.mosaic][y]; //BG2 vertical mosaic uses BG1 mosaic size
|
||||
}
|
||||
|
||||
signed psx = ((a * clip(hofs - cx)) & ~63) + ((b * clip(vofs - cy)) & ~63) + ((b * mosaic_y) & ~63) + (cx << 8);
|
||||
signed psy = ((c * clip(hofs - cx)) & ~63) + ((d * clip(vofs - cy)) & ~63) + ((d * mosaic_y) & ~63) + (cy << 8);
|
||||
signed psx = ((a * clip(hoffset - cx)) & ~63) + ((b * clip(voffset - cy)) & ~63) + ((b * mosaic_y) & ~63) + (cx << 8);
|
||||
signed psy = ((c * clip(hoffset - cx)) & ~63) + ((d * clip(voffset - cy)) & ~63) + ((d * mosaic_y) & ~63) + (cy << 8);
|
||||
|
||||
signed px = psx + (a * mosaic_x);
|
||||
signed py = psy + (c * mosaic_x);
|
||||
|
@ -87,16 +87,12 @@ void sPPU::Background::run_mode7(unsigned x, unsigned y) {
|
|||
if(palette == 0) return;
|
||||
|
||||
if(regs.main_enabled) {
|
||||
output.main.valid = true;
|
||||
output.main.palette = palette;
|
||||
output.main.palette_number = 0;
|
||||
output.main.priority = priority;
|
||||
}
|
||||
|
||||
if(regs.sub_enabled) {
|
||||
output.sub.valid = true;
|
||||
output.sub.palette = palette;
|
||||
output.sub.palette_number = 0;
|
||||
output.sub.priority = priority;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifdef SPPU_CPP
|
||||
|
||||
void sPPU::latch_counters() {
|
||||
scheduler.sync_cpuppu();
|
||||
regs.hcounter = hdot();
|
||||
regs.vcounter = vcounter();
|
||||
regs.counters_latched = true;
|
||||
|
@ -51,6 +52,7 @@ void sPPU::cgram_write(unsigned addr, uint8 data) {
|
|||
}
|
||||
|
||||
bool sPPU::interlace() const {
|
||||
//return true;
|
||||
return display.interlace;
|
||||
}
|
||||
|
||||
|
@ -62,59 +64,7 @@ bool sPPU::hires() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
//INIDISP
|
||||
void sPPU::mmio_w2100(uint8 data) {
|
||||
if(regs.display_disabled && vcounter() == 225) oam.address_reset();
|
||||
regs.display_disabled = data & 0x80;
|
||||
regs.display_brightness = data & 0x0f;
|
||||
}
|
||||
|
||||
//OBSEL
|
||||
void sPPU::mmio_w2101(uint8 data) {
|
||||
oam.regs.base_size = (data >> 5) & 7;
|
||||
oam.regs.nameselect = (data >> 3) & 3;
|
||||
oam.regs.tiledata_addr = (data & 3) << 14;
|
||||
}
|
||||
|
||||
//OAMADDL
|
||||
void sPPU::mmio_w2102(uint8 data) {
|
||||
regs.oam_baseaddr &= 0x0100;
|
||||
regs.oam_baseaddr |= (data << 0);
|
||||
oam.address_reset();
|
||||
}
|
||||
|
||||
//OAMADDH
|
||||
void sPPU::mmio_w2103(uint8 data) {
|
||||
regs.oam_priority = data & 0x80;
|
||||
regs.oam_baseaddr &= 0x00ff;
|
||||
regs.oam_baseaddr |= (data & 1) << 8;
|
||||
oam.address_reset();
|
||||
}
|
||||
|
||||
//OAMDATA
|
||||
void sPPU::mmio_w2104(uint8 data) {
|
||||
if(regs.oam_addr & 0x0200) {
|
||||
oam_write(regs.oam_addr, data);
|
||||
} else if((regs.oam_addr & 1) == 0) {
|
||||
regs.oam_latchdata = data;
|
||||
} else {
|
||||
oam_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam_write((regs.oam_addr & ~1) + 1, data);
|
||||
}
|
||||
|
||||
regs.oam_addr = (regs.oam_addr + 1) & 0x03ff;
|
||||
oam.regs.first_sprite = (regs.oam_priority == false ? 0 : (regs.oam_addr >> 2) & 127);
|
||||
}
|
||||
|
||||
//BGMODE
|
||||
void sPPU::mmio_w2105(uint8 data) {
|
||||
bg4.regs.tile_size = (data & 0x80);
|
||||
bg3.regs.tile_size = (data & 0x40);
|
||||
bg2.regs.tile_size = (data & 0x20);
|
||||
bg1.regs.tile_size = (data & 0x10);
|
||||
regs.bg3_priority = (data & 0x08);
|
||||
regs.bgmode = (data & 0x07);
|
||||
|
||||
void sPPU::mmio_update_video_mode() {
|
||||
switch(regs.bgmode) {
|
||||
case 0: {
|
||||
bg1.regs.mode = Background::Mode::BPP2; bg1.regs.priority0 = 8; bg1.regs.priority1 = 11;
|
||||
|
@ -212,6 +162,61 @@ void sPPU::mmio_w2105(uint8 data) {
|
|||
}
|
||||
}
|
||||
|
||||
//INIDISP
|
||||
void sPPU::mmio_w2100(uint8 data) {
|
||||
if(regs.display_disabled && vcounter() == 225) oam.address_reset();
|
||||
regs.display_disabled = data & 0x80;
|
||||
regs.display_brightness = data & 0x0f;
|
||||
}
|
||||
|
||||
//OBSEL
|
||||
void sPPU::mmio_w2101(uint8 data) {
|
||||
oam.regs.base_size = (data >> 5) & 7;
|
||||
oam.regs.nameselect = (data >> 3) & 3;
|
||||
oam.regs.tiledata_addr = (data & 3) << 14;
|
||||
}
|
||||
|
||||
//OAMADDL
|
||||
void sPPU::mmio_w2102(uint8 data) {
|
||||
regs.oam_baseaddr &= 0x0100;
|
||||
regs.oam_baseaddr |= (data << 0);
|
||||
oam.address_reset();
|
||||
}
|
||||
|
||||
//OAMADDH
|
||||
void sPPU::mmio_w2103(uint8 data) {
|
||||
regs.oam_priority = data & 0x80;
|
||||
regs.oam_baseaddr &= 0x00ff;
|
||||
regs.oam_baseaddr |= (data & 1) << 8;
|
||||
oam.address_reset();
|
||||
}
|
||||
|
||||
//OAMDATA
|
||||
void sPPU::mmio_w2104(uint8 data) {
|
||||
if(regs.oam_addr & 0x0200) {
|
||||
oam_write(regs.oam_addr, data);
|
||||
} else if((regs.oam_addr & 1) == 0) {
|
||||
regs.oam_latchdata = data;
|
||||
} else {
|
||||
oam_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam_write((regs.oam_addr & ~1) + 1, data);
|
||||
}
|
||||
|
||||
regs.oam_addr = (regs.oam_addr + 1) & 0x03ff;
|
||||
oam.regs.first_sprite = (regs.oam_priority == false ? 0 : (regs.oam_addr >> 2) & 127);
|
||||
}
|
||||
|
||||
//BGMODE
|
||||
void sPPU::mmio_w2105(uint8 data) {
|
||||
bg4.regs.tile_size = (data & 0x80);
|
||||
bg3.regs.tile_size = (data & 0x40);
|
||||
bg2.regs.tile_size = (data & 0x20);
|
||||
bg1.regs.tile_size = (data & 0x10);
|
||||
regs.bg3_priority = (data & 0x08);
|
||||
regs.bgmode = (data & 0x07);
|
||||
mmio_update_video_mode();
|
||||
}
|
||||
|
||||
//MOSAIC
|
||||
void sPPU::mmio_w2106(uint8 data) {
|
||||
unsigned mosaic_size = (data >> 4) & 15;
|
||||
|
@ -259,8 +264,8 @@ void sPPU::mmio_w210c(uint8 data) {
|
|||
|
||||
//BG1HOFS
|
||||
void sPPU::mmio_w210d(uint8 data) {
|
||||
regs.m7hofs = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.mode7_hoffset = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
|
||||
bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7);
|
||||
regs.bgofs_latchdata = data;
|
||||
|
@ -268,8 +273,8 @@ void sPPU::mmio_w210d(uint8 data) {
|
|||
|
||||
//BG1VOFS
|
||||
void sPPU::mmio_w210e(uint8 data) {
|
||||
regs.m7vofs = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.mode7_voffset = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
|
||||
bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata;
|
||||
regs.bgofs_latchdata = data;
|
||||
|
@ -364,38 +369,38 @@ void sPPU::mmio_w211a(uint8 data) {
|
|||
|
||||
//M7A
|
||||
void sPPU::mmio_w211b(uint8 data) {
|
||||
regs.m7a = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.m7a = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
}
|
||||
|
||||
//M7B
|
||||
void sPPU::mmio_w211c(uint8 data) {
|
||||
regs.m7b = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.m7b = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
}
|
||||
|
||||
//M7C
|
||||
void sPPU::mmio_w211d(uint8 data) {
|
||||
regs.m7c = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.m7c = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
}
|
||||
|
||||
//M7D
|
||||
void sPPU::mmio_w211e(uint8 data) {
|
||||
regs.m7d = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.m7d = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
}
|
||||
|
||||
//M7X
|
||||
void sPPU::mmio_w211f(uint8 data) {
|
||||
regs.m7x = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.m7x = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
}
|
||||
|
||||
//M7Y
|
||||
void sPPU::mmio_w2120(uint8 data) {
|
||||
regs.m7y = (data << 8) | regs.m7_latchdata;
|
||||
regs.m7_latchdata = data;
|
||||
regs.m7y = (data << 8) | regs.mode7_latchdata;
|
||||
regs.mode7_latchdata = data;
|
||||
}
|
||||
|
||||
//CGADD
|
||||
|
@ -545,7 +550,6 @@ void sPPU::mmio_w2132(uint8 data) {
|
|||
if(data & 0x80) screen.regs.color_b = data & 0x1f;
|
||||
if(data & 0x40) screen.regs.color_g = data & 0x1f;
|
||||
if(data & 0x20) screen.regs.color_r = data & 0x1f;
|
||||
screen.regs.color_rgb = (screen.regs.color_b << 10) + (screen.regs.color_g << 5) + screen.regs.color_r;
|
||||
}
|
||||
|
||||
//SETINI
|
||||
|
@ -555,6 +559,7 @@ void sPPU::mmio_w2133(uint8 data) {
|
|||
regs.overscan = data & 0x04;
|
||||
oam.regs.interlace = data & 0x02;
|
||||
regs.interlace = data & 0x01;
|
||||
mmio_update_video_mode();
|
||||
}
|
||||
|
||||
//MPYL
|
||||
|
@ -689,7 +694,7 @@ void sPPU::mmio_reset() {
|
|||
regs.oam_latchdata = 0x00;
|
||||
regs.cgram_latchdata = 0x00;
|
||||
regs.bgofs_latchdata = 0x00;
|
||||
regs.m7_latchdata = 0x00;
|
||||
regs.mode7_latchdata = 0x00;
|
||||
regs.counters_latched = false;
|
||||
regs.latch_hcounter = 0;
|
||||
regs.latch_vcounter = 0;
|
||||
|
@ -709,10 +714,10 @@ void sPPU::mmio_reset() {
|
|||
regs.bgmode = 0;
|
||||
|
||||
//$210d BG1HOFS
|
||||
regs.m7hofs = 0x0000;
|
||||
regs.mode7_hoffset = 0x0000;
|
||||
|
||||
//$210e BG1VOFS
|
||||
regs.m7vofs = 0x0000;
|
||||
regs.mode7_voffset = 0x0000;
|
||||
|
||||
//$2115 VMAIN
|
||||
regs.vram_incmode = 1;
|
||||
|
|
|
@ -6,7 +6,7 @@ struct {
|
|||
uint8 oam_latchdata;
|
||||
uint8 cgram_latchdata;
|
||||
uint8 bgofs_latchdata;
|
||||
uint8 m7_latchdata;
|
||||
uint8 mode7_latchdata;
|
||||
bool counters_latched;
|
||||
bool latch_hcounter;
|
||||
bool latch_vcounter;
|
||||
|
@ -26,10 +26,10 @@ struct {
|
|||
uint8 bgmode;
|
||||
|
||||
//$210d BG1HOFS
|
||||
uint16 m7hofs;
|
||||
uint16 mode7_hoffset;
|
||||
|
||||
//$210e BG1VOFS
|
||||
uint16 m7vofs;
|
||||
uint16 mode7_voffset;
|
||||
|
||||
//$2115 VMAIN
|
||||
bool vram_incmode;
|
||||
|
@ -95,70 +95,72 @@ bool interlace() const;
|
|||
bool overscan() const;
|
||||
bool hires() const;
|
||||
|
||||
void mmio_w2100(uint8);
|
||||
void mmio_w2101(uint8);
|
||||
void mmio_w2102(uint8);
|
||||
void mmio_w2103(uint8);
|
||||
void mmio_w2104(uint8);
|
||||
void mmio_w2105(uint8);
|
||||
void mmio_w2106(uint8);
|
||||
void mmio_w2107(uint8);
|
||||
void mmio_w2108(uint8);
|
||||
void mmio_w2109(uint8);
|
||||
void mmio_w210a(uint8);
|
||||
void mmio_w210b(uint8);
|
||||
void mmio_w210c(uint8);
|
||||
void mmio_w210d(uint8);
|
||||
void mmio_w210e(uint8);
|
||||
void mmio_w210f(uint8);
|
||||
void mmio_w2110(uint8);
|
||||
void mmio_w2111(uint8);
|
||||
void mmio_w2112(uint8);
|
||||
void mmio_w2113(uint8);
|
||||
void mmio_w2114(uint8);
|
||||
void mmio_w2115(uint8);
|
||||
void mmio_w2116(uint8);
|
||||
void mmio_w2117(uint8);
|
||||
void mmio_w2118(uint8);
|
||||
void mmio_w2119(uint8);
|
||||
void mmio_w211a(uint8);
|
||||
void mmio_w211b(uint8);
|
||||
void mmio_w211c(uint8);
|
||||
void mmio_w211d(uint8);
|
||||
void mmio_w211e(uint8);
|
||||
void mmio_w211f(uint8);
|
||||
void mmio_w2120(uint8);
|
||||
void mmio_w2121(uint8);
|
||||
void mmio_w2122(uint8);
|
||||
void mmio_w2123(uint8);
|
||||
void mmio_w2124(uint8);
|
||||
void mmio_w2125(uint8);
|
||||
void mmio_w2126(uint8);
|
||||
void mmio_w2127(uint8);
|
||||
void mmio_w2128(uint8);
|
||||
void mmio_w2129(uint8);
|
||||
void mmio_w212a(uint8);
|
||||
void mmio_w212b(uint8);
|
||||
void mmio_w212c(uint8);
|
||||
void mmio_w212d(uint8);
|
||||
void mmio_w212e(uint8);
|
||||
void mmio_w212f(uint8);
|
||||
void mmio_w2130(uint8);
|
||||
void mmio_w2131(uint8);
|
||||
void mmio_w2132(uint8);
|
||||
void mmio_w2133(uint8);
|
||||
uint8 mmio_r2134();
|
||||
uint8 mmio_r2135();
|
||||
uint8 mmio_r2136();
|
||||
uint8 mmio_r2137();
|
||||
uint8 mmio_r2138();
|
||||
uint8 mmio_r2139();
|
||||
uint8 mmio_r213a();
|
||||
uint8 mmio_r213b();
|
||||
uint8 mmio_r213c();
|
||||
uint8 mmio_r213d();
|
||||
uint8 mmio_r213e();
|
||||
uint8 mmio_r213f();
|
||||
void mmio_update_video_mode();
|
||||
|
||||
void mmio_w2100(uint8); //INIDISP
|
||||
void mmio_w2101(uint8); //OBSEL
|
||||
void mmio_w2102(uint8); //OAMADDL
|
||||
void mmio_w2103(uint8); //OAMADDH
|
||||
void mmio_w2104(uint8); //OAMDATA
|
||||
void mmio_w2105(uint8); //BGMODE
|
||||
void mmio_w2106(uint8); //MOSAIC
|
||||
void mmio_w2107(uint8); //BG1SC
|
||||
void mmio_w2108(uint8); //BG2SC
|
||||
void mmio_w2109(uint8); //BG3SC
|
||||
void mmio_w210a(uint8); //BG4SC
|
||||
void mmio_w210b(uint8); //BG12NBA
|
||||
void mmio_w210c(uint8); //BG34NBA
|
||||
void mmio_w210d(uint8); //BG1HOFS
|
||||
void mmio_w210e(uint8); //BG1VOFS
|
||||
void mmio_w210f(uint8); //BG2HOFS
|
||||
void mmio_w2110(uint8); //BG2VOFS
|
||||
void mmio_w2111(uint8); //BG3HOFS
|
||||
void mmio_w2112(uint8); //BG3VOFS
|
||||
void mmio_w2113(uint8); //BG4HOFS
|
||||
void mmio_w2114(uint8); //BG4VOFS
|
||||
void mmio_w2115(uint8); //VMAIN
|
||||
void mmio_w2116(uint8); //VMADDL
|
||||
void mmio_w2117(uint8); //VMADDH
|
||||
void mmio_w2118(uint8); //VMDATAL
|
||||
void mmio_w2119(uint8); //VMDATAH
|
||||
void mmio_w211a(uint8); //M7SEL
|
||||
void mmio_w211b(uint8); //M7A
|
||||
void mmio_w211c(uint8); //M7B
|
||||
void mmio_w211d(uint8); //M7C
|
||||
void mmio_w211e(uint8); //M7D
|
||||
void mmio_w211f(uint8); //M7X
|
||||
void mmio_w2120(uint8); //M7Y
|
||||
void mmio_w2121(uint8); //CGADD
|
||||
void mmio_w2122(uint8); //CGDATA
|
||||
void mmio_w2123(uint8); //W12SEL
|
||||
void mmio_w2124(uint8); //W34SEL
|
||||
void mmio_w2125(uint8); //WOBJSEL
|
||||
void mmio_w2126(uint8); //WH0
|
||||
void mmio_w2127(uint8); //WH1
|
||||
void mmio_w2128(uint8); //WH2
|
||||
void mmio_w2129(uint8); //WH3
|
||||
void mmio_w212a(uint8); //WBGLOG
|
||||
void mmio_w212b(uint8); //WOBJLOG
|
||||
void mmio_w212c(uint8); //TM
|
||||
void mmio_w212d(uint8); //TS
|
||||
void mmio_w212e(uint8); //TMW
|
||||
void mmio_w212f(uint8); //TSW
|
||||
void mmio_w2130(uint8); //CGWSEL
|
||||
void mmio_w2131(uint8); //CGADDSUB
|
||||
void mmio_w2132(uint8); //COLDATA
|
||||
void mmio_w2133(uint8); //SETINI
|
||||
uint8 mmio_r2134(); //MPYL
|
||||
uint8 mmio_r2135(); //MPYM
|
||||
uint8 mmio_r2136(); //MPYH
|
||||
uint8 mmio_r2137(); //SLHV
|
||||
uint8 mmio_r2138(); //OAMDATAREAD
|
||||
uint8 mmio_r2139(); //VMDATALREAD
|
||||
uint8 mmio_r213a(); //VMDATAHREAD
|
||||
uint8 mmio_r213b(); //CGDATAREAD
|
||||
uint8 mmio_r213c(); //OPHCT
|
||||
uint8 mmio_r213d(); //OPVCT
|
||||
uint8 mmio_r213e(); //STAT77
|
||||
uint8 mmio_r213f(); //STAT78
|
||||
|
||||
void mmio_reset();
|
||||
uint8 mmio_read(unsigned addr);
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#ifdef SPPU_CPP
|
||||
|
||||
void sPPU::Screen::scanline() {
|
||||
output = self.output + self.vcounter() * 1024;
|
||||
if(self.display.interlace && self.field() == 1) output += 512;
|
||||
if(self.display.interlace == false || self.field() == 0) {
|
||||
output = self.output + self.vcounter() * 1024;
|
||||
fade = output + 512;
|
||||
} else {
|
||||
output = self.output + self.vcounter() * 1024 + 512;
|
||||
fade = output - 512;
|
||||
}
|
||||
}
|
||||
|
||||
void sPPU::Screen::run() {
|
||||
|
@ -17,6 +22,9 @@ void sPPU::Screen::run() {
|
|||
color = get_pixel(false);
|
||||
*output++ = color;
|
||||
}
|
||||
|
||||
*fade++ = light_table[10][*fade];
|
||||
*fade++ = light_table[10][*fade];
|
||||
}
|
||||
|
||||
uint16 sPPU::Screen::get_pixel(bool swap) {
|
||||
|
@ -31,31 +39,31 @@ uint16 sPPU::Screen::get_pixel(bool swap) {
|
|||
unsigned color_main;
|
||||
unsigned source_main;
|
||||
|
||||
if(self.bg1.output.main.valid) {
|
||||
if(self.bg1.output.main.priority) {
|
||||
priority_main = self.bg1.output.main.priority;
|
||||
if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {
|
||||
color_main = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.palette_number);
|
||||
color_main = get_direct_color(self.bg1.output.main.palette);
|
||||
} else {
|
||||
color_main = get_color(self.bg1.output.main.palette);
|
||||
}
|
||||
source_main = BG1;
|
||||
}
|
||||
if(self.bg2.output.main.valid && self.bg2.output.main.priority > priority_main) {
|
||||
if(self.bg2.output.main.priority > priority_main) {
|
||||
priority_main = self.bg2.output.main.priority;
|
||||
color_main = get_color(self.bg2.output.main.palette);
|
||||
source_main = BG2;
|
||||
}
|
||||
if(self.bg3.output.main.valid && self.bg3.output.main.priority > priority_main) {
|
||||
if(self.bg3.output.main.priority > priority_main) {
|
||||
priority_main = self.bg3.output.main.priority;
|
||||
color_main = get_color(self.bg3.output.main.palette);
|
||||
source_main = BG3;
|
||||
}
|
||||
if(self.bg4.output.main.valid && self.bg4.output.main.priority > priority_main) {
|
||||
if(self.bg4.output.main.priority > priority_main) {
|
||||
priority_main = self.bg4.output.main.priority;
|
||||
color_main = get_color(self.bg4.output.main.palette);
|
||||
source_main = BG4;
|
||||
}
|
||||
if(self.oam.output.main.valid && self.oam.output.main.priority > priority_main) {
|
||||
if(self.oam.output.main.priority > priority_main) {
|
||||
priority_main = self.oam.output.main.priority;
|
||||
color_main = get_color(self.oam.output.main.palette);
|
||||
source_main = OAM;
|
||||
|
@ -73,31 +81,31 @@ uint16 sPPU::Screen::get_pixel(bool swap) {
|
|||
unsigned color_sub;
|
||||
unsigned source_sub;
|
||||
|
||||
if(self.bg1.output.sub.valid) {
|
||||
if(self.bg1.output.sub.priority) {
|
||||
priority_sub = self.bg1.output.sub.priority;
|
||||
if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {
|
||||
color_sub = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.palette_number);
|
||||
color_sub = get_direct_color(self.bg1.output.sub.palette);
|
||||
} else {
|
||||
color_sub = get_color(self.bg1.output.sub.palette);
|
||||
}
|
||||
source_sub = BG1;
|
||||
}
|
||||
if(self.bg2.output.sub.valid && self.bg2.output.sub.priority > priority_sub) {
|
||||
if(self.bg2.output.sub.priority > priority_sub) {
|
||||
priority_sub = self.bg2.output.sub.priority;
|
||||
color_sub = get_color(self.bg2.output.sub.palette);
|
||||
source_sub = BG2;
|
||||
}
|
||||
if(self.bg3.output.sub.valid && self.bg3.output.sub.priority > priority_sub) {
|
||||
if(self.bg3.output.sub.priority > priority_sub) {
|
||||
priority_sub = self.bg3.output.sub.priority;
|
||||
color_sub = get_color(self.bg3.output.sub.palette);
|
||||
source_sub = BG3;
|
||||
}
|
||||
if(self.bg4.output.sub.valid && self.bg4.output.sub.priority > priority_sub) {
|
||||
if(self.bg4.output.sub.priority > priority_sub) {
|
||||
priority_sub = self.bg4.output.sub.priority;
|
||||
color_sub = get_color(self.bg4.output.sub.palette);
|
||||
source_sub = BG4;
|
||||
}
|
||||
if(self.oam.output.sub.valid && self.oam.output.sub.priority > priority_sub) {
|
||||
if(self.oam.output.sub.priority > priority_sub) {
|
||||
priority_sub = self.oam.output.sub.priority;
|
||||
color_sub = get_color(self.oam.output.sub.palette);
|
||||
source_sub = OAM;
|
||||
|
@ -106,7 +114,7 @@ uint16 sPPU::Screen::get_pixel(bool swap) {
|
|||
if(self.regs.bgmode == 5 || self.regs.bgmode == 6) {
|
||||
color_sub = get_color(0);
|
||||
} else {
|
||||
color_sub = regs.color_rgb;
|
||||
color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0);
|
||||
}
|
||||
source_sub = BACK;
|
||||
}
|
||||
|
@ -120,7 +128,7 @@ uint16 sPPU::Screen::get_pixel(bool swap) {
|
|||
uint16 output;
|
||||
if(!regs.addsub_mode) {
|
||||
source_sub = BACK;
|
||||
color_sub = regs.color_rgb;
|
||||
color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0);
|
||||
}
|
||||
|
||||
if(self.window.output.main.color_enable == false) {
|
||||
|
@ -134,8 +142,7 @@ uint16 sPPU::Screen::get_pixel(bool swap) {
|
|||
if(!color_exempt && color_enable[source_main] && self.window.output.sub.color_enable) {
|
||||
bool halve = false;
|
||||
if(regs.color_halve && self.window.output.main.color_enable) {
|
||||
if(regs.addsub_mode && source_sub == BACK);
|
||||
else halve = true;
|
||||
if(!regs.addsub_mode || source_sub != BACK) halve = true;
|
||||
}
|
||||
output = addsub(color_main, color_sub, halve);
|
||||
} else {
|
||||
|
@ -175,13 +182,12 @@ uint16 sPPU::Screen::get_color(uint8 n) {
|
|||
return memory::cgram[(n << 1) + 0] + (memory::cgram[(n << 1) + 1] << 8);
|
||||
}
|
||||
|
||||
//color = BBBGGGRR (from tiledata)
|
||||
//palette = 00000bgr (from tilemap)
|
||||
//result = 0BBb00GGGg0RRRr0
|
||||
uint16 sPPU::Screen::get_direct_color(uint8 color, uint8 palette) {
|
||||
return ((color & 7) << 2) | ((palette & 1) << 1)
|
||||
| (((color >> 3) & 7) << 7) | (((palette >> 1) & 1) << 6)
|
||||
| ((color >> 6) << 13) | ((palette >> 2) << 12);
|
||||
uint16 sPPU::Screen::get_direct_color(unsigned n) {
|
||||
//input = 00000bgrBBGGGRRR (BGR = palette index [tiledata], bgr = palette number [tilemap])
|
||||
//output = 0BBb00GGGg0RRRr0
|
||||
return ((n << 7) & 0x6000) + ((n << 2) & 0x1000)
|
||||
+ ((n << 4) & 0x0380) + ((n >> 3) & 0x0040)
|
||||
+ ((n << 2) & 0x001c) + ((n >> 7) & 0x0002);
|
||||
}
|
||||
|
||||
void sPPU::Screen::reset() {
|
||||
|
@ -198,7 +204,6 @@ void sPPU::Screen::reset() {
|
|||
regs.color_r = 0;
|
||||
regs.color_g = 0;
|
||||
regs.color_b = 0;
|
||||
regs.color_rgb = 0;
|
||||
}
|
||||
|
||||
sPPU::Screen::Screen(sPPU &self) : self(self) {
|
||||
|
|
|
@ -2,6 +2,7 @@ class Screen {
|
|||
public:
|
||||
sPPU &self;
|
||||
uint16 *output;
|
||||
uint16 *fade;
|
||||
|
||||
struct {
|
||||
bool addsub_mode;
|
||||
|
@ -19,7 +20,6 @@ public:
|
|||
uint8 color_b;
|
||||
uint8 color_g;
|
||||
uint8 color_r;
|
||||
uint16 color_rgb;
|
||||
} regs;
|
||||
|
||||
void scanline();
|
||||
|
@ -33,5 +33,5 @@ private:
|
|||
uint16 get_pixel(bool swap);
|
||||
uint16 addsub(unsigned x, unsigned y, bool halve);
|
||||
uint16 get_color(uint8 n);
|
||||
uint16 get_direct_color(uint8 color, uint8 palette);
|
||||
uint16 get_direct_color(unsigned n);
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ void sPPU::Sprite::scanline() {
|
|||
state.y = self.vcounter();
|
||||
|
||||
if(state.y == 225 && self.regs.display_disabled == false) address_reset();
|
||||
if(state.y < 1 || state.y > 224) return;
|
||||
if(state.y < 1 || state.y > (!self.regs.overscan ? 224 : 239)) return;
|
||||
|
||||
const uint8 *tableA = memory::oam.data();
|
||||
const uint8 *tableB = memory::oam.data() + 512;
|
||||
|
@ -95,8 +95,8 @@ void sPPU::Sprite::scanline() {
|
|||
}
|
||||
|
||||
void sPPU::Sprite::run() {
|
||||
output.main.valid = false;
|
||||
output.sub.valid = false;
|
||||
output.main.priority = 0;
|
||||
output.sub.priority = 0;
|
||||
|
||||
unsigned x = state.x++;
|
||||
|
||||
|
@ -104,13 +104,11 @@ void sPPU::Sprite::run() {
|
|||
unsigned priority_table[] = { regs.priority0, regs.priority1, regs.priority2, regs.priority3 };
|
||||
|
||||
if(regs.main_enabled) {
|
||||
output.main.valid = true;
|
||||
output.main.palette = state.output_palette[x];
|
||||
output.main.priority = priority_table[state.output_priority[x]];
|
||||
}
|
||||
|
||||
if(regs.sub_enabled) {
|
||||
output.sub.valid = true;
|
||||
output.sub.palette = state.output_palette[x];
|
||||
output.sub.priority = priority_table[state.output_priority[x]];
|
||||
}
|
||||
|
@ -251,10 +249,8 @@ void sPPU::Sprite::reset() {
|
|||
state.tile_list[i].hflip = 0;
|
||||
}
|
||||
state.active_sprite = 0;
|
||||
output.main.valid = 0;
|
||||
output.main.palette = 0;
|
||||
output.main.priority = 0;
|
||||
output.sub.valid = 0;
|
||||
output.sub.palette = 0;
|
||||
output.sub.priority = 0;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,41 @@ class Sprite {
|
|||
public:
|
||||
sPPU &self;
|
||||
|
||||
struct TileItem {
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint16 priority;
|
||||
uint16 palette;
|
||||
uint16 tile;
|
||||
bool hflip;
|
||||
};
|
||||
|
||||
struct SpriteItem {
|
||||
uint8 width;
|
||||
uint8 height;
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint8 character;
|
||||
bool nameselect;
|
||||
bool vflip;
|
||||
bool hflip;
|
||||
uint8 palette;
|
||||
uint8 priority;
|
||||
} list[128];
|
||||
|
||||
struct State {
|
||||
unsigned x;
|
||||
unsigned y;
|
||||
|
||||
unsigned item_count;
|
||||
unsigned tile_count;
|
||||
uint8 output_palette[256];
|
||||
uint8 output_priority[256];
|
||||
uint8 item_list[32];
|
||||
TileItem tile_list[34];
|
||||
unsigned active_sprite;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
bool main_enabled;
|
||||
bool sub_enabled;
|
||||
|
@ -21,46 +56,10 @@ public:
|
|||
bool range_over;
|
||||
} regs;
|
||||
|
||||
struct SpriteItem {
|
||||
uint8 width;
|
||||
uint8 height;
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint8 character;
|
||||
bool nameselect;
|
||||
bool vflip;
|
||||
bool hflip;
|
||||
uint8 palette;
|
||||
uint8 priority;
|
||||
} list[128];
|
||||
|
||||
struct TileItem {
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
uint16 priority;
|
||||
uint16 palette;
|
||||
uint16 tile;
|
||||
bool hflip;
|
||||
};
|
||||
|
||||
struct State {
|
||||
unsigned x;
|
||||
unsigned y;
|
||||
|
||||
unsigned item_count;
|
||||
unsigned tile_count;
|
||||
uint8 output_palette[256];
|
||||
uint8 output_priority[256];
|
||||
uint8 item_list[32];
|
||||
TileItem tile_list[34];
|
||||
unsigned active_sprite;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
bool valid;
|
||||
uint8 palette;
|
||||
uint8 priority;
|
||||
unsigned priority; //0 = none (transparent)
|
||||
unsigned palette; //index
|
||||
} main, sub;
|
||||
} output;
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ void sPPU::Window::run() {
|
|||
regs.bg1_two_enable, regs.bg1_two_invert,
|
||||
regs.bg1_mask, regs.bg1_main_enable, regs.bg1_sub_enable
|
||||
);
|
||||
if(main) self.bg1.output.main.valid = false;
|
||||
if(sub) self.bg1.output.sub.valid = false;
|
||||
if(main) self.bg1.output.main.priority = 0;
|
||||
if(sub) self.bg1.output.sub.priority = 0;
|
||||
|
||||
test(
|
||||
main, sub,
|
||||
|
@ -22,8 +22,8 @@ void sPPU::Window::run() {
|
|||
regs.bg2_two_enable, regs.bg2_two_invert,
|
||||
regs.bg2_mask, regs.bg2_main_enable, regs.bg2_sub_enable
|
||||
);
|
||||
if(main) self.bg2.output.main.valid = false;
|
||||
if(sub) self.bg2.output.sub.valid = false;
|
||||
if(main) self.bg2.output.main.priority = 0;
|
||||
if(sub) self.bg2.output.sub.priority = 0;
|
||||
|
||||
test(
|
||||
main, sub,
|
||||
|
@ -31,8 +31,8 @@ void sPPU::Window::run() {
|
|||
regs.bg3_two_enable, regs.bg3_two_invert,
|
||||
regs.bg3_mask, regs.bg3_main_enable, regs.bg3_sub_enable
|
||||
);
|
||||
if(main) self.bg3.output.main.valid = false;
|
||||
if(sub) self.bg3.output.sub.valid = false;
|
||||
if(main) self.bg3.output.main.priority = 0;
|
||||
if(sub) self.bg3.output.sub.priority = 0;
|
||||
|
||||
test(
|
||||
main, sub,
|
||||
|
@ -40,8 +40,8 @@ void sPPU::Window::run() {
|
|||
regs.bg4_two_enable, regs.bg4_two_invert,
|
||||
regs.bg4_mask, regs.bg4_main_enable, regs.bg4_sub_enable
|
||||
);
|
||||
if(main) self.bg4.output.main.valid = false;
|
||||
if(sub) self.bg4.output.sub.valid = false;
|
||||
if(main) self.bg4.output.main.priority = 0;
|
||||
if(sub) self.bg4.output.sub.priority = 0;
|
||||
|
||||
test(
|
||||
main, sub,
|
||||
|
@ -49,8 +49,8 @@ void sPPU::Window::run() {
|
|||
regs.oam_two_enable, regs.oam_two_invert,
|
||||
regs.oam_mask, regs.oam_main_enable, regs.oam_sub_enable
|
||||
);
|
||||
if(main) self.oam.output.main.valid = false;
|
||||
if(sub) self.oam.output.sub.valid = false;
|
||||
if(main) self.oam.output.main.priority = 0;
|
||||
if(sub) self.oam.output.sub.priority = 0;
|
||||
|
||||
test(
|
||||
main, sub,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
static const char bsnesVersion[] = "063.10";
|
||||
static const char bsnesVersion[] = "063.11";
|
||||
static const char bsnesTitle[] = "bsnes";
|
||||
static const unsigned bsnesSerializerVersion = 9;
|
||||
|
||||
|
|
Loading…
Reference in New Issue