diff --git a/bsnes/nes/cpu/core/opcodes.cpp b/bsnes/nes/cpu/core/opcodes.cpp index f7fb5241..f6a131fc 100755 --- a/bsnes/nes/cpu/core/opcodes.cpp +++ b/bsnes/nes/cpu/core/opcodes.cpp @@ -232,9 +232,9 @@ L rd = op_readpci(); template void CPU::opi_read_indirect_zero_page_x() { zp = op_readpci(); - op_readpc(); - abs.l = op_readdp(zp++ + regs.x); - abs.h = op_readdp(zp++ + regs.x); + op_readzp(zp); + abs.l = op_readzp(zp++ + regs.x); + abs.h = op_readzp(zp++ + regs.x); L rd = op_read(abs.w); call(op); } @@ -242,8 +242,8 @@ L rd = op_read(abs.w); template void CPU::opi_read_indirect_zero_page_y() { rd = op_readpci(); - abs.l = op_read(rd++); - abs.h = op_read(rd++); + abs.l = op_readzp(rd++); + abs.h = op_readzp(rd++); op_page(abs.w, abs.w + regs.y); L rd = op_read(abs.w + regs.y); call(op); @@ -252,23 +252,23 @@ L rd = op_read(abs.w + regs.y); template void CPU::opi_read_zero_page() { zp = op_readpci(); -L rd = op_read(zp); +L rd = op_readzp(zp); call(op); } template void CPU::opi_read_zero_page_x() { zp = op_readpci(); - op_readpc(); -L rd = op_readdp(zp + regs.x); + op_readzp(zp); +L rd = op_readzp(zp + regs.x); call(op); } template void CPU::opi_read_zero_page_y() { zp = op_readpci(); - op_readpc(); -L rd = op_readdp(zp + regs.y); + op_readzp(zp); +L rd = op_readzp(zp + regs.y); call(op); } @@ -286,7 +286,7 @@ template void CPU::opi_rmw_absolute_x() { abs.l = op_readpci(); abs.h = op_readpci(); - op_readpc(); + op_page_always(abs.w, abs.w + regs.x); rd = op_read(abs.w + regs.x); op_write(abs.w + regs.x, rd); call(op); @@ -296,20 +296,20 @@ L op_write(abs.w + regs.x, rd); template void CPU::opi_rmw_zero_page() { zp = op_readpci(); - rd = op_read(zp); - op_write(zp, rd); + rd = op_readzp(zp); + op_writezp(zp, rd); call(op); -L op_write(zp, rd); +L op_writezp(zp, rd); } template void CPU::opi_rmw_zero_page_x() { zp = op_readpci(); - op_readpc(); - rd = op_readdp(zp + regs.x); - op_writedp(zp + regs.x, rd); + op_readzp(zp); + rd = op_readzp(zp + regs.x); + op_writezp(zp + regs.x, rd); call(op); -L op_writedp(zp + regs.x, rd); +L op_writezp(zp + regs.x, rd); } void CPU::opi_set_flag(bool &flag) { @@ -332,48 +332,48 @@ L op_write(abs.w, r); void CPU::opi_store_absolute_x(uint8 &r) { abs.l = op_readpci(); abs.h = op_readpci(); - op_page(abs.w, abs.w + regs.x); + op_page_always(abs.w, abs.w + regs.x); L op_write(abs.w + regs.x, r); } void CPU::opi_store_absolute_y(uint8 &r) { abs.l = op_readpci(); abs.h = op_readpci(); - op_page(abs.w, abs.w + regs.y); + op_page_always(abs.w, abs.w + regs.y); L op_write(abs.w + regs.y, r); } void CPU::opi_store_indirect_zero_page_x(uint8 &r) { zp = op_readpci(); - op_readpc(); - abs.l = op_readdp(zp++ + regs.x); - abs.h = op_readdp(zp++ + regs.x); + op_readzp(zp); + abs.l = op_readzp(zp++ + regs.x); + abs.h = op_readzp(zp++ + regs.x); L op_write(abs.w, r); } void CPU::opi_store_indirect_zero_page_y(uint8 &r) { rd = op_readpci(); - abs.l = op_read(rd++); - abs.h = op_read(rd++); - op_page(abs.w, abs.w + regs.y); + abs.l = op_readzp(rd++); + abs.h = op_readzp(rd++); + op_page_always(abs.w, abs.w + regs.y); L op_write(abs.w + regs.y, r); } void CPU::opi_store_zero_page(uint8 &r) { - rd = op_readpci(); -L op_write(rd, r); + zp = op_readpci(); +L op_writezp(zp, r); } void CPU::opi_store_zero_page_x(uint8 &r) { zp = op_readpci(); - op_readpc(); -L op_writedp(zp + regs.x, r); + op_readzp(zp); +L op_writezp(zp + regs.x, r); } void CPU::opi_store_zero_page_y(uint8 &r) { zp = op_readpci(); - op_readpc(); -L op_writedp(zp + regs.y, r); + op_readzp(zp); +L op_writezp(zp + regs.y, r); } void CPU::opi_transfer(uint8 &s, uint8 &d, bool flag) { @@ -492,11 +492,11 @@ L op_readpc(); void CPU::opill_nop_zero_page() { zp = op_readpci(); -L op_readpc(); +L op_readzp(zp); } void CPU::opill_nop_zero_page_x() { zp = op_readpci(); - op_readpc(); -L op_readpc(); + op_readzp(zp); +L op_readzp(zp + regs.x); } diff --git a/bsnes/nes/cpu/memory/memory.cpp b/bsnes/nes/cpu/memory/memory.cpp index 3bb994e2..38c26c51 100755 --- a/bsnes/nes/cpu/memory/memory.cpp +++ b/bsnes/nes/cpu/memory/memory.cpp @@ -23,7 +23,7 @@ uint8 CPU::op_readsp() { return op_read(0x0100 | ++regs.s); } -uint8 CPU::op_readdp(uint8 addr) { +uint8 CPU::op_readzp(uint8 addr) { return op_read(addr); } @@ -33,12 +33,16 @@ void CPU::op_writesp(uint8 data) { op_write(0x0100 | regs.s--, data); } -void CPU::op_writedp(uint8 addr, uint8 data) { +void CPU::op_writezp(uint8 addr, uint8 data) { op_write(addr, data); } // void CPU::op_page(uint16 x, uint16 y) { - if((x & 0xff00) != (y & 0xff00)) op_readpc(); + if((x & 0xff00) != (y & 0xff00)) op_read((x & 0xff00) | (y & 0x00ff)); +} + +void CPU::op_page_always(uint16 x, uint16 y) { + op_read((x & 0xff00) | (y & 0x00ff)); } diff --git a/bsnes/nes/cpu/memory/memory.hpp b/bsnes/nes/cpu/memory/memory.hpp index 16c4c40c..5edcfe42 100755 --- a/bsnes/nes/cpu/memory/memory.hpp +++ b/bsnes/nes/cpu/memory/memory.hpp @@ -4,9 +4,10 @@ void op_write(uint16 addr, uint8 data); uint8 op_readpc(); uint8 op_readpci(); uint8 op_readsp(); -uint8 op_readdp(uint8 addr); +uint8 op_readzp(uint8 addr); void op_writesp(uint8 data); -void op_writedp(uint8 addr, uint8 data); +void op_writezp(uint8 addr, uint8 data); void op_page(uint16 x, uint16 y); +void op_page_always(uint16 x, uint16 y); diff --git a/bsnes/nes/nes.hpp b/bsnes/nes/nes.hpp index e46e705c..ed9c9c7c 100755 --- a/bsnes/nes/nes.hpp +++ b/bsnes/nes/nes.hpp @@ -4,7 +4,7 @@ namespace NES { namespace Info { static const char Name[] = "bnes"; - static const char Version[] = "000.04"; + static const char Version[] = "000.05"; } } diff --git a/bsnes/nes/ppu/ppu.cpp b/bsnes/nes/ppu/ppu.cpp index fb34d299..6dfc2da4 100755 --- a/bsnes/nes/ppu/ppu.cpp +++ b/bsnes/nes/ppu/ppu.cpp @@ -278,6 +278,48 @@ void PPU::scrolly_increment() { // +void PPU::raster_pixel(unsigned x) { + uint32 *output = buffer + status.ly * 256; + + unsigned mask = 0x8000 >> (status.xaddr + x); + unsigned palette = 0; + palette |= (raster.tiledatalo & mask) ? 1 : 0; + palette |= (raster.tiledatahi & mask) ? 2 : 0; + if(palette) { + unsigned attr = raster.attribute; + if(mask >= 256) attr >>= 2; + palette |= (attr & 3) << 2; + } + + if(status.bg_edge_enable == false && status.lx < 8) palette = 0; + + for(unsigned sprite = 0; sprite < 8; sprite++) { + if(status.sprite_edge_enable == false && status.lx < 8) continue; + if(raster.oam[sprite].id == 64) continue; + + unsigned spritex = status.lx - raster.oam[sprite].x; + if(spritex >= 8) continue; + + if(raster.oam[sprite].attr & 0x40) spritex ^= 7; + unsigned mask = 0x80 >> spritex; + unsigned sprite_palette = 0; + sprite_palette |= (raster.oam[sprite].tiledatalo & mask) ? 1 : 0; + sprite_palette |= (raster.oam[sprite].tiledatahi & mask) ? 2 : 0; + if(sprite_palette == 0) continue; + + if(raster.oam[sprite].id == 0 && palette) status.sprite_zero_hit = 1; + sprite_palette |= (raster.oam[sprite].attr & 3) << 2; + + if((raster.oam[sprite].attr & 0x20) == 0 || palette == 0) { + palette = 16 + sprite_palette; + break; + } + } + + if(raster_enable() == false) palette = 0; + output[status.lx++] = paletteRGB[cgram[palette]]; +} + void PPU::raster_scanline() { if((status.ly >= 240 && status.ly <= 260)) { for(unsigned x = 0; x < 340; x++) tick(); @@ -287,71 +329,42 @@ void PPU::raster_scanline() { uint32 *output = buffer + status.ly * 256; signed lx = 0, ly = (status.ly == 261 ? -1 : status.ly); + status.lx = 0; for(unsigned tile = 0; tile < 32; tile++) { // 0-255 - unsigned mask = 0x8000 >> status.xaddr; - for(unsigned n = 0; n < 8; n++) { - uint8 palette = 0; - palette |= (raster.tiledatalo & mask) ? 1 : 0; - palette |= (raster.tiledatahi & mask) ? 2 : 0; - if(palette) { - unsigned attr = raster.attribute; - if(mask >= 256) attr >>= 2; - palette |= (attr & 3) << 2; - } - mask >>= 1; - - if(status.bg_edge_enable == false && lx < 8) palette = 0; - - for(unsigned sprite = 0; sprite < 8; sprite++) { - if(status.sprite_edge_enable == false && lx < 8) continue; - if(raster.oam[sprite].id == 64) continue; - - unsigned spritex = lx - raster.oam[sprite].x; - if(spritex >= 8) continue; - - if(raster.oam[sprite].attr & 0x40) spritex ^= 7; - unsigned mask = 0x80 >> spritex; - unsigned sprite_palette = 0; - sprite_palette |= (raster.oam[sprite].tiledatalo & mask) ? 1 : 0; - sprite_palette |= (raster.oam[sprite].tiledatahi & mask) ? 2 : 0; - if(sprite_palette == 0) continue; - - if(raster.oam[sprite].id == 0) status.sprite_zero_hit = 1; - sprite_palette |= (raster.oam[sprite].attr & 3) << 2; - - if((raster.oam[sprite].attr & 0x20) == 0 || palette == 0) { - palette = 16 + sprite_palette; - break; - } - } - - if(raster_enable() == false) palette = 0; - output[lx++] = paletteRGB[cgram[palette]]; - } - unsigned nametable = cartridge.ciram_read((uint13)status.vaddr); unsigned tileaddr = status.bg_addr + (nametable << 4) + (scrolly() & 7); + raster_pixel(0); tick(); + + raster_pixel(1); tick(); unsigned attribute = cartridge.ciram_read(0x03c0 | (status.vaddr & 0x0fc0) | ((scrolly() >> 5) << 3) | (scrollx() >> 5)); if(scrolly() & 16) attribute >>= 4; if(scrollx() & 16) attribute >>= 2; + raster_pixel(2); tick(); if(raster_enable()) { scrollx_increment(); if(tile == 31) scrolly_increment(); } + raster_pixel(3); tick(); unsigned tiledatalo = cartridge.chr_read(tileaddr + 0); + raster_pixel(4); tick(); + + raster_pixel(5); tick(); unsigned tiledatahi = cartridge.chr_read(tileaddr + 8); + raster_pixel(6); tick(); + + raster_pixel(7); tick(); raster.nametable = (raster.nametable << 8) | nametable; diff --git a/bsnes/nes/ppu/ppu.hpp b/bsnes/nes/ppu/ppu.hpp index f38769bc..55f12433 100755 --- a/bsnes/nes/ppu/ppu.hpp +++ b/bsnes/nes/ppu/ppu.hpp @@ -27,12 +27,14 @@ struct PPU : Processor { void scrollx_increment(); void scrolly_increment(); + void raster_pixel(unsigned x); void raster_scanline(); struct Status { uint8 mdr; bool field; + unsigned lx; unsigned ly; uint8 bus_data; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 7b34f1b2..417bd1c3 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -4,7 +4,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "082.08"; + static const char Version[] = "082.09"; static const unsigned SerializerVersion = 21; } }