Update to bsnes v063r12 release.

Well I really don't want to think about a caching system right now, so
I skipped that.

- added sPPU::Background::get_tile(), which computes its own copies of
mask_xy, screen_xy, tile_size, etc; allows BG3 offset-per-tile to
compute tile correctly
- fixed two V=(start of Vblank) checks that lacked overscan tests
- removed fade stuff from video output, going to rely exclusively on
filters for that stuff now
- modified state. to t. for brevity
- cached regs.overscan for overscan() function
- PPUDebugger uses interlace_enable() and overscan_enable() to avoid
conflicts with the base classes; forgot to move PPUcounter to
PPUCounter
- added controller selection capability to libsnes; still needs cheat
code and save state support

Should fix that Adventure Island thing, confirmation would be
appreciated.

I tried some quick hacks and was able to get mode7 caching (NHL '94)
and OAM caching (Winter Gold) working without breaking anything, but
it's too scanline-PPU for my tastes. There's really no reason to half-
ass this just to get games playable, so I'll wait and do it the right
way later on.

Only worked on this for about an hour today ... I must be burned out.
Think I'll try messing around with Python or something, since Ruby is
a dead-end for using libsnes.
This commit is contained in:
byuu 2010-04-11 13:00:48 +00:00
parent 35fdb71f3d
commit 717aa69d42
21 changed files with 169 additions and 182 deletions

BIN
bsnes.exe

Binary file not shown.

View File

@ -54,6 +54,10 @@ void snes_run() {
SNES::system.run();
}
void snes_set_controller_port_device(bool port, unsigned device) {
SNES::input.port_set_device(port, (SNES::Input::Device)device);
}
void snes_set_video_refresh(snes_video_refresh_t video_refresh) {
interface.pvideo_refresh = video_refresh;
}

View File

@ -9,6 +9,7 @@ void snes_init();
void snes_term();
void snes_unload();
void snes_run();
void snes_set_controller_port_device(bool port, unsigned device);
typedef void (*snes_video_refresh_t)(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height);
typedef void (*snes_audio_sample_t)(uint16_t left, uint16_t right);

View File

@ -267,9 +267,9 @@ unsigned bPPUDebugger::color_constant_red() { return regs.color_r; }
//$2133
bool bPPUDebugger::mode7_extbg() { return regs.mode7_extbg; }
bool bPPUDebugger::pseudo_hires() { return regs.pseudo_hires; }
bool bPPUDebugger::overscan() { return regs.overscan; }
bool bPPUDebugger::overscan_enable() { return regs.overscan; }
bool bPPUDebugger::oam_interlace() { return regs.oam_interlace; }
bool bPPUDebugger::interlace() { return regs.interlace; }
bool bPPUDebugger::interlace_enable() { return regs.interlace; }
//$213c
unsigned bPPUDebugger::hcounter() { return bPPU::hcounter(); }

View File

@ -250,9 +250,9 @@ public:
//$2133
bool mode7_extbg();
bool pseudo_hires();
bool overscan();
bool overscan_enable();
bool oam_interlace();
bool interlace();
bool interlace_enable();
//$213c
unsigned hcounter();

View File

@ -275,9 +275,9 @@ bool PPUDebugger::property(unsigned id, string &name, string &value) {
if(id == n++) { name = "$2133"; value = ""; return true; }
if(id == n++) { name = "Mode 7 EXTBG"; value = mode7_extbg(); return true; }
if(id == n++) { name = "Pseudo Hires"; value = pseudo_hires(); return true; }
if(id == n++) { name = "Overscan"; value = overscan(); return true; }
if(id == n++) { name = "Overscan"; value = overscan_enable(); return true; }
if(id == n++) { name = "OAM Interlace"; value = oam_interlace(); return true; }
if(id == n++) { name = "Interlace"; value = interlace(); return true; }
if(id == n++) { name = "Interlace"; value = interlace_enable(); return true; }
//$213c
if(id == n++) { name = "$213c"; value = ""; return true; }

View File

@ -221,9 +221,9 @@ struct PPUDebugger : ChipDebugger {
//$2133
virtual bool mode7_extbg() { return 0; }
virtual bool pseudo_hires() { return 0; }
virtual bool overscan() { return 0; }
virtual bool overscan_enable() { return 0; }
virtual bool oam_interlace() { return 0; }
virtual bool interlace() { return 0; }
virtual bool interlace_enable() { return 0; }
//$213c
virtual unsigned hcounter() { return 0; }

View File

@ -4,15 +4,15 @@
void sPPU::Background::scanline() {
if(self.vcounter() == 1) {
state.mosaic_y = 1;
state.mosaic_countdown = 0;
t.mosaic_y = 1;
t.mosaic_countdown = 0;
} else {
if(!regs.mosaic || !state.mosaic_countdown) state.mosaic_y = self.vcounter();
if(!state.mosaic_countdown) state.mosaic_countdown = regs.mosaic + 1;
state.mosaic_countdown--;
if(!regs.mosaic || !t.mosaic_countdown) t.mosaic_y = self.vcounter();
if(!t.mosaic_countdown) t.mosaic_countdown = regs.mosaic + 1;
t.mosaic_countdown--;
}
state.x = 0;
t.x = 0;
}
void sPPU::Background::run() {
@ -28,8 +28,8 @@ void sPPU::Background::run() {
if(regs.mode == Mode::Inactive) return;
if(regs.main_enabled == false && regs.sub_enabled == false) return;
unsigned x = state.x++;
unsigned y = state.mosaic_y;
unsigned x = t.x++;
unsigned y = t.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);
@ -49,10 +49,6 @@ void sPPU::Background::run() {
mask_x--;
mask_y--;
unsigned screen_y = (regs.screen_size & 2 ? (32 << 5) : 0);
unsigned screen_x = (regs.screen_size & 1 ? (32 << 5) : 0);
if(regs.screen_size == 3) screen_y <<= 1;
unsigned hscroll = regs.hoffset;
unsigned vscroll = regs.voffset;
if(hires) {
@ -63,34 +59,12 @@ void sPPU::Background::run() {
unsigned hoffset = hscroll + mosaic_table[regs.mosaic][x];
unsigned voffset = vscroll + y;
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) {
if(self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6) {
uint16 opt_x = (x + (hscroll & 7));
//tile 0 is unaffected by offset-per-tile mode
if(opt_x >= 8) {
uint16 hval; {
unsigned px = (opt_x - 8) + (self.bg3.regs.hoffset & ~7);
unsigned py = self.bg3.regs.voffset;
unsigned tx = (px & (width - 1)) >> tile_width;
unsigned ty = (py & (width - 1)) >> tile_height;
uint16 pos = ((ty & 0x1f) << 5) + (tx & 0x1f);
uint16 addr = self.bg3.regs.screen_addr + (pos << 1);
hval = memory::vram[addr + 0] + (memory::vram[addr + 1] << 8);
}
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 & (width - 1)) >> tile_width;
unsigned ty = (py & (width - 1)) >> tile_height;
uint16 pos = ((ty & 0x1f) << 5) + (tx & 0x1f);
uint16 addr = self.bg3.regs.screen_addr + (pos << 1);
vval = memory::vram[addr + 0] + (memory::vram[addr + 1] << 8);
}
unsigned hval = self.bg3.get_tile((opt_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 0);
unsigned vval = self.bg3.get_tile((opt_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 8);
unsigned opt_valid_bit = (id == ID::BG1 ? 0x2000 : 0x4000);
if(self.regs.bgmode == 4) {
@ -102,12 +76,8 @@ void sPPU::Background::run() {
}
}
} else {
if(hval & opt_valid_bit) {
hoffset = opt_x + (hval & ~7);
}
if(vval & opt_valid_bit) {
voffset = y + vval;
}
if(hval & opt_valid_bit) hoffset = opt_x + (hval & ~7);
if(vval & opt_valid_bit) voffset = y + vval;
}
}
}
@ -115,16 +85,7 @@ void sPPU::Background::run() {
hoffset &= mask_x;
voffset &= mask_y;
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);
}
unsigned tile_number = get_tile(hoffset, voffset);
bool mirror_y = tile_number & 0x8000;
bool mirror_x = tile_number & 0x4000;
unsigned priority = (tile_number & 0x2000 ? regs.priority1 : regs.priority0);
@ -137,8 +98,8 @@ void sPPU::Background::run() {
tile_number += tiledata_index;
tile_number &= tile_mask;
if(mirror_y) voffset ^= 7;
if(mirror_x) hoffset ^= 7;
if(mirror_y) voffset ^= 7;
uint8 color = get_color(hoffset, voffset, tile_number);
if(color == 0) return;
@ -147,29 +108,60 @@ void sPPU::Background::run() {
if(hires == false) {
if(regs.main_enabled) {
output.main.palette = color | (palette_number << 8);
output.main.priority = priority;
output.main.palette = color;
output.main.tile = tile_number;
}
if(regs.sub_enabled) {
output.sub.palette = color | (palette_number << 8);
output.sub.priority = priority;
output.sub.palette = color;
output.sub.tile = tile_number;
}
} else {
if(x & 1) {
if(regs.main_enabled) {
output.main.palette = color | (palette_number << 8);
output.main.priority = priority;
output.main.palette = color;
output.main.tile = tile_number;
}
} else {
if(regs.sub_enabled) {
output.sub.palette = color | (palette_number << 8);
output.sub.priority = priority;
output.sub.palette = color;
output.sub.tile = tile_number;
}
}
}
}
unsigned sPPU::Background::get_tile(unsigned x, unsigned y) {
bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6);
unsigned tile_height = (regs.tile_size == TileSize::Size8x8 ? 3 : 4);
unsigned tile_width = (!hires ? tile_height : 4);
unsigned width = (!hires ? 256 : 512);
unsigned mask_x = (tile_height == 3 ? width : (width << 1));
unsigned mask_y = mask_x;
if(regs.screen_size & 1) mask_x <<= 1;
if(regs.screen_size & 2) mask_y <<= 1;
mask_x--;
mask_y--;
unsigned screen_x = (regs.screen_size & 1 ? (32 << 5) : 0);
unsigned screen_y = (regs.screen_size & 2 ? (32 << 5) : 0);
if(regs.screen_size == 3) screen_y <<= 1;
x = (x & mask_x) >> tile_width;
y = (y & mask_y) >> tile_height;
uint16 pos = ((y & 0x1f) << 5) + (x & 0x1f);
if(x & 0x20) pos += screen_x;
if(y & 0x20) pos += screen_y;
uint16 addr = regs.screen_addr + (pos << 1);
return memory::vram[addr + 0] + (memory::vram[addr + 1] << 8);
}
unsigned sPPU::Background::get_color(unsigned x, unsigned y, uint16 offset) {
unsigned mask = 0x80 >> (x & 7);
@ -223,9 +215,9 @@ 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;
t.x = 0;
t.mosaic_y = 0;
t.mosaic_countdown = 0;
regs.tiledata_addr = 0;
regs.screen_addr = 0;
regs.screen_size = 0;
@ -245,7 +237,6 @@ void sPPU::Background::reset() {
}
sPPU::Background::Background(sPPU &self, unsigned id) : self(self), id(id) {
//generate mosaic table
for(unsigned m = 0; m < 16; m++) {
for(unsigned x = 0; x < 4096; x++) {
mosaic_table[m][x] = (x / (m + 1)) * (m + 1);

View File

@ -12,7 +12,7 @@ public:
unsigned x;
unsigned mosaic_y;
unsigned mosaic_countdown;
} state;
} t;
struct {
unsigned tiledata_addr;
@ -36,11 +36,13 @@ public:
struct {
unsigned priority; //0 = none (transparent)
unsigned palette; //(direct_color_bits << 8) + index
unsigned tile;
} main, sub;
} output;
void scanline();
void run();
unsigned get_tile(unsigned x, unsigned y);
unsigned get_color(unsigned x, unsigned y, uint16 offset);
void reset();
Background(sPPU &self, unsigned id);

View File

@ -1,6 +1,3 @@
#ifdef SPPU_CPP
bool sPPUDebugger::interlace() { return false; }
bool sPPUDebugger::overscan() { return false; }
#endif

View File

@ -5,7 +5,4 @@ public:
bool bg3_enabled[2];
bool bg4_enabled[2];
bool oam_enabled[4];
bool interlace();
bool overscan();
};

View File

@ -52,12 +52,11 @@ void sPPU::cgram_write(unsigned addr, uint8 data) {
}
bool sPPU::interlace() const {
//return true;
return display.interlace;
}
bool sPPU::overscan() const {
return regs.overscan;
return display.overscan;
}
bool sPPU::hires() const {
@ -164,7 +163,7 @@ void sPPU::mmio_update_video_mode() {
//INIDISP
void sPPU::mmio_w2100(uint8 data) {
if(regs.display_disabled && vcounter() == 225) oam.address_reset();
if(regs.display_disabled && vcounter() == (!regs.overscan ? 225 : 240)) oam.address_reset();
regs.display_disabled = data & 0x80;
regs.display_brightness = data & 0x0f;
}

View File

@ -1,13 +1,8 @@
#ifdef SPPU_CPP
void sPPU::Screen::scanline() {
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;
}
output = self.output + self.vcounter() * 1024;
if(self.display.interlace && self.field()) output += 512;
}
void sPPU::Screen::run() {
@ -22,9 +17,6 @@ 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) {
@ -42,7 +34,7 @@ uint16 sPPU::Screen::get_pixel(bool swap) {
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);
color_main = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.tile);
} else {
color_main = get_color(self.bg1.output.main.palette);
}
@ -84,7 +76,7 @@ uint16 sPPU::Screen::get_pixel(bool swap) {
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);
color_sub = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.tile);
} else {
color_sub = get_color(self.bg1.output.sub.palette);
}
@ -178,16 +170,18 @@ uint16 sPPU::Screen::addsub(unsigned x, unsigned y, bool halve) {
}
}
uint16 sPPU::Screen::get_color(uint8 n) {
return memory::cgram[(n << 1) + 0] + (memory::cgram[(n << 1) + 1] << 8);
uint16 sPPU::Screen::get_color(unsigned palette) {
palette <<= 1;
return memory::cgram[palette + 0] + (memory::cgram[palette + 1] << 8);
}
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);
uint16 sPPU::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);
}
void sPPU::Screen::reset() {
@ -207,7 +201,6 @@ void sPPU::Screen::reset() {
}
sPPU::Screen::Screen(sPPU &self) : self(self) {
//generate light table
for(unsigned l = 0; l < 16; l++) {
for(unsigned r = 0; r < 32; r++) {
for(unsigned g = 0; g < 32; g++) {

View File

@ -2,7 +2,6 @@ class Screen {
public:
sPPU &self;
uint16 *output;
uint16 *fade;
struct {
bool addsub_mode;
@ -32,6 +31,6 @@ private:
uint16 light_table[16][32768];
uint16 get_pixel(bool swap);
uint16 addsub(unsigned x, unsigned y, bool halve);
uint16 get_color(uint8 n);
uint16 get_direct_color(unsigned n);
uint16 get_color(unsigned palette);
uint16 get_direct_color(unsigned palette, unsigned tile);
};

View File

@ -97,6 +97,7 @@ void sPPU::frame() {
oam.frame();
display.interlace = regs.interlace;
display.overscan = regs.overscan;
}
sPPU::sPPU() :

View File

@ -16,6 +16,7 @@ public:
struct {
bool interlace;
bool overscan;
} display;
void enter();

View File

@ -11,11 +11,11 @@ void sPPU::Sprite::frame() {
}
void sPPU::Sprite::scanline() {
state.x = 0;
state.y = self.vcounter();
t.x = 0;
t.y = self.vcounter();
if(state.y == 225 && self.regs.display_disabled == false) address_reset();
if(state.y < 1 || state.y > (!self.regs.overscan ? 224 : 239)) return;
if(t.y == (!self.regs.overscan ? 225 : 240) && self.regs.display_disabled == false) address_reset();
if(t.y < 1 || t.y > (!self.regs.overscan ? 224 : 239)) return;
const uint8 *tableA = memory::oam.data();
const uint8 *tableB = memory::oam.data() + 512;
@ -66,30 +66,30 @@ void sPPU::Sprite::scanline() {
if((i & 3) == 3) tableB++;
}
state.item_count = 0;
state.tile_count = 0;
memset(state.output_priority, 0xff, 256);
memset(state.item_list, 0xff, 32);
for(unsigned i = 0; i < 34; i++) state.tile_list[i].tile = 0xffff;
t.item_count = 0;
t.tile_count = 0;
memset(t.output_priority, 0xff, 256);
memset(t.item_list, 0xff, 32);
for(unsigned i = 0; i < 34; i++) t.tile_list[i].tile = 0xffff;
for(unsigned i = 0; i < 128; i++) {
state.active_sprite = (i + regs.first_sprite) & 127;
t.active_sprite = (i + regs.first_sprite) & 127;
if(on_scanline() == false) continue;
if(state.item_count++ >= 32) break;
state.item_list[state.item_count - 1] = (i + regs.first_sprite) & 127;
if(t.item_count++ >= 32) break;
t.item_list[t.item_count - 1] = (i + regs.first_sprite) & 127;
}
for(signed i = 31; i >= 0; i--) {
if(state.item_list[i] == 0xff) continue;
state.active_sprite = state.item_list[i];
if(t.item_list[i] == 0xff) continue;
t.active_sprite = t.item_list[i];
load_tiles();
}
regs.time_over |= (state.tile_count > 34);
regs.range_over |= (state.item_count > 32);
regs.time_over |= (t.tile_count > 34);
regs.range_over |= (t.item_count > 32);
for(unsigned i = 0; i < 34; i++) {
if(state.tile_list[i].tile == 0xffff) continue;
if(t.tile_list[i].tile == 0xffff) continue;
render_tile(i);
}
}
@ -98,38 +98,37 @@ void sPPU::Sprite::run() {
output.main.priority = 0;
output.sub.priority = 0;
unsigned x = state.x++;
if(state.output_priority[x] != 0xff) {
unsigned x = t.x++;
if(t.output_priority[x] != 0xff) {
unsigned priority_table[] = { regs.priority0, regs.priority1, regs.priority2, regs.priority3 };
if(regs.main_enabled) {
output.main.palette = state.output_palette[x];
output.main.priority = priority_table[state.output_priority[x]];
output.main.palette = t.output_palette[x];
output.main.priority = priority_table[t.output_priority[x]];
}
if(regs.sub_enabled) {
output.sub.palette = state.output_palette[x];
output.sub.priority = priority_table[state.output_priority[x]];
output.sub.palette = t.output_palette[x];
output.sub.priority = priority_table[t.output_priority[x]];
}
}
}
bool sPPU::Sprite::on_scanline() {
SpriteItem &sprite = list[state.active_sprite];
SpriteItem &sprite = list[t.active_sprite];
if(sprite.x > 256 && (sprite.x + sprite.width - 1) < 512) return false;
signed height = (regs.interlace == false ? sprite.height : (sprite.height >> 1));
if(state.y >= sprite.y && state.y < (sprite.y + height)) return true;
if((sprite.y + height) >= 256 && state.y < ((sprite.y + height) & 255)) return true;
if(t.y >= sprite.y && t.y < (sprite.y + height)) return true;
if((sprite.y + height) >= 256 && t.y < ((sprite.y + height) & 255)) return true;
return false;
}
void sPPU::Sprite::load_tiles() {
SpriteItem &sprite = list[state.active_sprite];
SpriteItem &sprite = list[t.active_sprite];
unsigned tile_width = sprite.width >> 3;
signed x = sprite.x;
signed y = (state.y - sprite.y) & 0xff;
signed y = (t.y - sprite.y) & 0xff;
if(regs.interlace) y <<= 1;
if(sprite.vflip) {
@ -161,22 +160,22 @@ void sPPU::Sprite::load_tiles() {
unsigned sx = (x + (tx << 3)) & 511;
if(x != 256 && sx >= 256 && (sx + 7) < 512) continue;
if(state.tile_count++ >= 34) break;
unsigned n = state.tile_count - 1;
state.tile_list[n].x = sx;
state.tile_list[n].y = y;
state.tile_list[n].priority = sprite.priority;
state.tile_list[n].palette = 128 + (sprite.palette << 4);
state.tile_list[n].hflip = sprite.hflip;
if(t.tile_count++ >= 34) break;
unsigned n = t.tile_count - 1;
t.tile_list[n].x = sx;
t.tile_list[n].y = y;
t.tile_list[n].priority = sprite.priority;
t.tile_list[n].palette = 128 + (sprite.palette << 4);
t.tile_list[n].hflip = sprite.hflip;
unsigned mx = (sprite.hflip == false) ? tx : ((tile_width - 1) - tx);
unsigned pos = tiledata_addr + ((chry + ((chrx + mx) & 15)) << 5);
state.tile_list[n].tile = (pos >> 5) & 0x07ff;
t.tile_list[n].tile = (pos >> 5) & 0x07ff;
}
}
void sPPU::Sprite::render_tile(unsigned tile) {
TileItem &item = state.tile_list[tile];
TileItem &item = t.tile_list[tile];
unsigned sx = item.x;
uint16 addr = (item.tile << 5) + ((item.y & 7) * 2);
@ -199,8 +198,8 @@ void sPPU::Sprite::render_tile(unsigned tile) {
if(color) {
color += item.palette;
state.output_palette[sx] = color;
state.output_priority[sx] = item.priority;
t.output_palette[sx] = color;
t.output_priority[sx] = item.priority;
}
}
sx++;
@ -208,6 +207,36 @@ void sPPU::Sprite::render_tile(unsigned tile) {
}
void sPPU::Sprite::reset() {
t.x = 0;
t.y = 0;
t.item_count = 0;
t.tile_count = 0;
memset(t.output_palette, 0, 256);
memset(t.output_priority, 0, 256);
memset(t.item_list, 0, 32);
for(unsigned i = 0; i < 34; i++) {
t.tile_list[i].x = 0;
t.tile_list[i].y = 0;
t.tile_list[i].priority = 0;
t.tile_list[i].palette = 0;
t.tile_list[i].tile = 0;
t.tile_list[i].hflip = 0;
}
t.active_sprite = 0;
for(unsigned i = 0; i < 128; i++) {
list[i].width = 0;
list[i].height = 0;
list[i].x = 0;
list[i].y = 0;
list[i].character = 0;
list[i].nameselect = 0;
list[i].vflip = 0;
list[i].hflip = 0;
list[i].palette = 0;
list[i].priority = 0;
}
regs.main_enabled = 0;
regs.sub_enabled = 0;
regs.interlace = 0;
@ -221,34 +250,7 @@ void sPPU::Sprite::reset() {
regs.priority3 = 0;
regs.time_over = 0;
regs.range_over = 0;
for(unsigned i = 0; i < 128; i++) {
list[i].width = 0;
list[i].height = 0;
list[i].x = 0;
list[i].y = 0;
list[i].character = 0;
list[i].nameselect = 0;
list[i].vflip = 0;
list[i].hflip = 0;
list[i].palette = 0;
list[i].priority = 0;
}
state.x = 0;
state.y = 0;
state.item_count = 0;
state.tile_count = 0;
memset(state.output_palette, 0, 256);
memset(state.output_priority, 0, 256);
memset(state.item_list, 0, 32);
for(unsigned i = 0; i < 34; i++) {
state.tile_list[i].x = 0;
state.tile_list[i].y = 0;
state.tile_list[i].priority = 0;
state.tile_list[i].palette = 0;
state.tile_list[i].tile = 0;
state.tile_list[i].hflip = 0;
}
state.active_sprite = 0;
output.main.palette = 0;
output.main.priority = 0;
output.sub.palette = 0;

View File

@ -35,7 +35,7 @@ public:
uint8 item_list[32];
TileItem tile_list[34];
unsigned active_sprite;
} state;
} t;
struct {
bool main_enabled;

View File

@ -1,7 +1,7 @@
#ifdef SPPU_CPP
void sPPU::Window::scanline() {
state.x = 0;
t.x = 0;
}
void sPPU::Window::run() {
@ -76,7 +76,7 @@ void sPPU::Window::run() {
output.main.color_enable = main;
output.sub.color_enable = sub;
state.x++;
t.x++;
}
void sPPU::Window::test(
@ -85,7 +85,7 @@ void sPPU::Window::test(
bool two_enable, bool two_invert,
uint8 mask, bool main_enable, bool sub_enable
) {
unsigned x = state.x;
unsigned x = t.x;
bool output;
if(one_enable == false && two_enable == false) {
@ -110,6 +110,7 @@ void sPPU::Window::test(
}
void sPPU::Window::reset() {
t.x = 0;
regs.bg1_one_enable = false;
regs.bg1_one_invert = false;
regs.bg1_two_enable = false;
@ -156,7 +157,6 @@ void sPPU::Window::reset() {
regs.oam_sub_enable = 0;
regs.col_main_mask = 0;
regs.col_sub_mask = 0;
state.x = 0;
output.main.color_enable = 0;
output.sub.color_enable = 0;
}

View File

@ -2,6 +2,10 @@ class Window {
public:
sPPU &self;
struct {
unsigned x;
} t;
struct {
bool bg1_one_enable;
bool bg1_one_invert;
@ -60,10 +64,6 @@ public:
uint8 col_sub_mask;
} regs;
struct {
unsigned x;
} state;
struct {
struct {
bool color_enable;

View File

@ -1,4 +1,4 @@
static const char bsnesVersion[] = "063.11";
static const char bsnesVersion[] = "063.12";
static const char bsnesTitle[] = "bsnes";
static const unsigned bsnesSerializerVersion = 9;