diff --git a/bsnes.exe b/bsnes.exe index 71cdf87e..b7297ff0 100644 Binary files a/bsnes.exe and b/bsnes.exe differ diff --git a/src/snes/libsnes/libsnes.cpp b/src/snes/libsnes/libsnes.cpp index efd117a3..554648c9 100644 --- a/src/snes/libsnes/libsnes.cpp +++ b/src/snes/libsnes/libsnes.cpp @@ -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; } diff --git a/src/snes/libsnes/libsnes.hpp b/src/snes/libsnes/libsnes.hpp index df73e7ad..903f5db2 100644 --- a/src/snes/libsnes/libsnes.hpp +++ b/src/snes/libsnes/libsnes.hpp @@ -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); diff --git a/src/snes/ppu/bppu/debugger/debugger.cpp b/src/snes/ppu/bppu/debugger/debugger.cpp index c4272914..bcb2ce96 100644 --- a/src/snes/ppu/bppu/debugger/debugger.cpp +++ b/src/snes/ppu/bppu/debugger/debugger.cpp @@ -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(); } diff --git a/src/snes/ppu/bppu/debugger/debugger.hpp b/src/snes/ppu/bppu/debugger/debugger.hpp index 8d254c5c..b0138a05 100644 --- a/src/snes/ppu/bppu/debugger/debugger.hpp +++ b/src/snes/ppu/bppu/debugger/debugger.hpp @@ -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(); diff --git a/src/snes/ppu/ppu-debugger.cpp b/src/snes/ppu/ppu-debugger.cpp index 2236996f..5c71ca7e 100644 --- a/src/snes/ppu/ppu-debugger.cpp +++ b/src/snes/ppu/ppu-debugger.cpp @@ -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; } diff --git a/src/snes/ppu/ppu-debugger.hpp b/src/snes/ppu/ppu-debugger.hpp index 800bedd1..a45bed7c 100644 --- a/src/snes/ppu/ppu-debugger.hpp +++ b/src/snes/ppu/ppu-debugger.hpp @@ -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; } diff --git a/src/snes/ppu/sppu/background/background.cpp b/src/snes/ppu/sppu/background/background.cpp index 546e4632..0bede2ae 100644 --- a/src/snes/ppu/sppu/background/background.cpp +++ b/src/snes/ppu/sppu/background/background.cpp @@ -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); diff --git a/src/snes/ppu/sppu/background/background.hpp b/src/snes/ppu/sppu/background/background.hpp index a79f637d..25249857 100644 --- a/src/snes/ppu/sppu/background/background.hpp +++ b/src/snes/ppu/sppu/background/background.hpp @@ -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); diff --git a/src/snes/ppu/sppu/debugger/debugger.cpp b/src/snes/ppu/sppu/debugger/debugger.cpp index c31bc18e..6c181688 100644 --- a/src/snes/ppu/sppu/debugger/debugger.cpp +++ b/src/snes/ppu/sppu/debugger/debugger.cpp @@ -1,6 +1,3 @@ #ifdef SPPU_CPP -bool sPPUDebugger::interlace() { return false; } -bool sPPUDebugger::overscan() { return false; } - #endif diff --git a/src/snes/ppu/sppu/debugger/debugger.hpp b/src/snes/ppu/sppu/debugger/debugger.hpp index a0df354e..56d9fd59 100644 --- a/src/snes/ppu/sppu/debugger/debugger.hpp +++ b/src/snes/ppu/sppu/debugger/debugger.hpp @@ -5,7 +5,4 @@ public: bool bg3_enabled[2]; bool bg4_enabled[2]; bool oam_enabled[4]; - - bool interlace(); - bool overscan(); }; diff --git a/src/snes/ppu/sppu/mmio/mmio.cpp b/src/snes/ppu/sppu/mmio/mmio.cpp index 38ecb6ca..0591f707 100644 --- a/src/snes/ppu/sppu/mmio/mmio.cpp +++ b/src/snes/ppu/sppu/mmio/mmio.cpp @@ -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; } diff --git a/src/snes/ppu/sppu/screen/screen.cpp b/src/snes/ppu/sppu/screen/screen.cpp index 2c9e2cbb..ee7034f8 100644 --- a/src/snes/ppu/sppu/screen/screen.cpp +++ b/src/snes/ppu/sppu/screen/screen.cpp @@ -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++) { diff --git a/src/snes/ppu/sppu/screen/screen.hpp b/src/snes/ppu/sppu/screen/screen.hpp index df32fd29..98f92240 100644 --- a/src/snes/ppu/sppu/screen/screen.hpp +++ b/src/snes/ppu/sppu/screen/screen.hpp @@ -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); }; diff --git a/src/snes/ppu/sppu/sppu.cpp b/src/snes/ppu/sppu/sppu.cpp index a4cf2f97..6085bad9 100644 --- a/src/snes/ppu/sppu/sppu.cpp +++ b/src/snes/ppu/sppu/sppu.cpp @@ -97,6 +97,7 @@ void sPPU::frame() { oam.frame(); display.interlace = regs.interlace; + display.overscan = regs.overscan; } sPPU::sPPU() : diff --git a/src/snes/ppu/sppu/sppu.hpp b/src/snes/ppu/sppu/sppu.hpp index f1dc2284..6d740c12 100644 --- a/src/snes/ppu/sppu/sppu.hpp +++ b/src/snes/ppu/sppu/sppu.hpp @@ -16,6 +16,7 @@ public: struct { bool interlace; + bool overscan; } display; void enter(); diff --git a/src/snes/ppu/sppu/sprite/sprite.cpp b/src/snes/ppu/sppu/sprite/sprite.cpp index 40ad6568..95105593 100644 --- a/src/snes/ppu/sppu/sprite/sprite.cpp +++ b/src/snes/ppu/sppu/sprite/sprite.cpp @@ -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; diff --git a/src/snes/ppu/sppu/sprite/sprite.hpp b/src/snes/ppu/sppu/sprite/sprite.hpp index 89f9de4a..a0a95c15 100644 --- a/src/snes/ppu/sppu/sprite/sprite.hpp +++ b/src/snes/ppu/sppu/sprite/sprite.hpp @@ -35,7 +35,7 @@ public: uint8 item_list[32]; TileItem tile_list[34]; unsigned active_sprite; - } state; + } t; struct { bool main_enabled; diff --git a/src/snes/ppu/sppu/window/window.cpp b/src/snes/ppu/sppu/window/window.cpp index 3cd570e3..0013aa4d 100644 --- a/src/snes/ppu/sppu/window/window.cpp +++ b/src/snes/ppu/sppu/window/window.cpp @@ -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; } diff --git a/src/snes/ppu/sppu/window/window.hpp b/src/snes/ppu/sppu/window/window.hpp index ae62f94d..828f3f26 100644 --- a/src/snes/ppu/sppu/window/window.hpp +++ b/src/snes/ppu/sppu/window/window.hpp @@ -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; diff --git a/src/snes/snes.hpp b/src/snes/snes.hpp index 25d349a5..126c668a 100644 --- a/src/snes/snes.hpp +++ b/src/snes/snes.hpp @@ -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;