mirror of https://github.com/bsnes-emu/bsnes.git
parent
55e78b03de
commit
fb463d34ef
|
@ -29,13 +29,13 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "bsnes";
|
||||
static const string Version = "114";
|
||||
static const string Version = "114.1";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "https://byuu.org";
|
||||
|
||||
//incremented only when serialization format changes
|
||||
static const string SerializerVersion = "112";
|
||||
static const string SerializerVersion = "114.1";
|
||||
|
||||
namespace Constants {
|
||||
namespace Colorburst {
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
//single-threaded
|
||||
auto PPU::Line::cacheBackground(PPU::IO::Background& bg) -> void {
|
||||
if(y == 1) {
|
||||
bg.mosaicCounter = ppu.io.mosaicSize + 1;
|
||||
bg.mosaicOffset = 1;
|
||||
} else if(--bg.mosaicCounter == 0) {
|
||||
bg.mosaicCounter = ppu.io.mosaicSize + 1;
|
||||
bg.mosaicOffset += ppu.io.mosaicSize + 1;
|
||||
}
|
||||
}
|
||||
|
||||
//parallelized
|
||||
auto PPU::Line::renderBackground(PPU::IO::Background& self, uint8 source) -> void {
|
||||
if(!self.aboveEnable && !self.belowEnable) return;
|
||||
if(self.tileMode == TileMode::Mode7) return renderMode7(self, source);
|
||||
|
@ -39,10 +27,14 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint8 source) -> voi
|
|||
uint hmask = (width << self.tileSize << !!(self.screenSize & 1)) - 1;
|
||||
uint vmask = (width << self.tileSize << !!(self.screenSize & 2)) - 1;
|
||||
|
||||
uint y = self.mosaicEnable ? self.mosaicOffset : this->y;
|
||||
uint y = this->y;
|
||||
if(self.mosaicEnable) y -= io.mosaic.size - io.mosaic.counter;
|
||||
if(hires) {
|
||||
hscroll <<= 1;
|
||||
if(io.interlace) y = y << 1 | field();
|
||||
if(io.interlace) {
|
||||
y = y << 1 | field();
|
||||
if(self.mosaicEnable) y -= io.mosaic.size - io.mosaic.counter + ppu.field();
|
||||
}
|
||||
}
|
||||
|
||||
uint mosaicCounter = 1;
|
||||
|
@ -103,7 +95,7 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint8 source) -> voi
|
|||
|
||||
for(uint tileX = 0; tileX < 8; tileX++, x++) {
|
||||
if(x & width) continue; //x < 0 || x >= width
|
||||
if(!self.mosaicEnable || --mosaicCounter == 0) {
|
||||
if(--mosaicCounter == 0) {
|
||||
uint color, shift = mirrorX ? tileX : 7 - tileX;
|
||||
/*if(self.tileMode >= TileMode::BPP2)*/ {
|
||||
color = data >> shift + 0 & 1;
|
||||
|
@ -120,7 +112,7 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint8 source) -> voi
|
|||
color += data >> shift + 49 & 128;
|
||||
}
|
||||
|
||||
mosaicCounter = 1 + io.mosaicSize;
|
||||
mosaicCounter = self.mosaicEnable ? io.mosaic.size : 1;
|
||||
mosaicPalette = color;
|
||||
mosaicPriority = tilePriority;
|
||||
if(directColorMode) {
|
||||
|
|
|
@ -248,11 +248,17 @@ auto PPU::writeIO(uint address, uint8 data) -> void {
|
|||
}
|
||||
|
||||
case 0x2106: { //MOSAIC
|
||||
bool enable = io.bg1.mosaicEnable || io.bg2.mosaicEnable || io.bg3.mosaicEnable || io.bg4.mosaicEnable;
|
||||
io.bg1.mosaicEnable = data >> 0 & 1;
|
||||
io.bg2.mosaicEnable = data >> 1 & 1;
|
||||
io.bg3.mosaicEnable = data >> 2 & 1;
|
||||
io.bg4.mosaicEnable = data >> 3 & 1;
|
||||
io.mosaicSize = data >> 4 & 15;
|
||||
io.mosaic.enable = data >> 0 & 15;
|
||||
io.mosaic.size = (data >> 4 & 15) + 1;
|
||||
if(!enable && (data >> 0 & 15)) {
|
||||
//mosaic vcounter is reloaded when mosaic becomes enabled
|
||||
io.mosaic.counter = io.mosaic.size + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,13 @@ auto PPU::Line::flush() -> void {
|
|||
}
|
||||
|
||||
auto PPU::Line::cache() -> void {
|
||||
cacheBackground(ppu.io.bg1);
|
||||
cacheBackground(ppu.io.bg2);
|
||||
cacheBackground(ppu.io.bg3);
|
||||
cacheBackground(ppu.io.bg4);
|
||||
|
||||
uint y = ppu.vcounter();
|
||||
if(y == 1) {
|
||||
ppu.io.mosaic.counter = ppu.io.mosaic.enable ? ppu.io.mosaic.size + 1 : 0;
|
||||
}
|
||||
if(ppu.io.mosaic.counter && !--ppu.io.mosaic.counter) {
|
||||
ppu.io.mosaic.counter = ppu.io.mosaic.enable ? ppu.io.mosaic.size + 0 : 0;
|
||||
}
|
||||
if(ppu.io.displayDisable || y >= ppu.vdisp()) {
|
||||
io.displayDisable = true;
|
||||
} else {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
auto PPU::Line::renderMode7(PPU::IO::Background& self, uint8 source) -> void {
|
||||
//HD mode 7 support
|
||||
if(!ppu.hdMosaic() || !self.mosaicEnable || !io.mosaicSize) {
|
||||
if(!ppu.hdMosaic() || !self.mosaicEnable || !io.mosaic.size) {
|
||||
if(ppu.hdScale() > 1) return renderMode7HD(self, source);
|
||||
}
|
||||
|
||||
int Y = self.mosaicEnable ? self.mosaicOffset : this->y;
|
||||
int Y = this->y;
|
||||
int y = !io.mode7.vflip ? Y : 255 - Y;
|
||||
if(self.mosaicEnable) y -= io.mosaic.size - io.mosaic.counter;
|
||||
|
||||
int a = (int16)io.mode7.a;
|
||||
int b = (int16)io.mode7.b;
|
||||
|
@ -50,8 +51,8 @@ auto PPU::Line::renderMode7(PPU::IO::Background& self, uint8 source) -> void {
|
|||
palette &= 0x7f;
|
||||
}
|
||||
|
||||
if(!self.mosaicEnable || --mosaicCounter == 0) {
|
||||
mosaicCounter = 1 + io.mosaicSize;
|
||||
if(--mosaicCounter == 0) {
|
||||
mosaicCounter = self.mosaicEnable ? io.mosaic.size : 1;
|
||||
mosaicPalette = palette;
|
||||
mosaicPriority = priority;
|
||||
if(io.col.directColor && source == Source::BG1) {
|
||||
|
|
|
@ -85,7 +85,6 @@ public:
|
|||
bool oamPriority = 0;
|
||||
bool bgPriority = 0;
|
||||
uint8 bgMode = 0;
|
||||
uint8 mosaicSize = 0;
|
||||
bool vramIncrementMode = 0;
|
||||
uint8 vramMapping = 0;
|
||||
uint8 vramIncrementSize = 0;
|
||||
|
@ -99,6 +98,15 @@ public:
|
|||
bool pseudoHires = 0;
|
||||
bool extbg = 0;
|
||||
|
||||
struct Mosaic {
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
uint8 enable = 0;
|
||||
uint8 size = 1;
|
||||
uint8 counter = 0;
|
||||
} mosaic;
|
||||
|
||||
struct Mode7 {
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
@ -161,8 +169,6 @@ public:
|
|||
bool aboveEnable = 0;
|
||||
bool belowEnable = 0;
|
||||
bool mosaicEnable = 0;
|
||||
uint16 mosaicCounter = 0;
|
||||
uint16 mosaicOffset = 0;
|
||||
uint16 tiledataAddress = 0;
|
||||
uint16 screenAddress = 0;
|
||||
uint8 screenSize = 0;
|
||||
|
@ -293,7 +299,6 @@ public:
|
|||
alwaysinline auto plotHD(Pixel*, uint x, uint8 source, uint8 priority, uint16 color, bool hires, bool subpixel) -> void;
|
||||
|
||||
//background.cpp
|
||||
auto cacheBackground(PPU::IO::Background&) -> void;
|
||||
auto renderBackground(PPU::IO::Background&, uint8 source) -> void;
|
||||
auto getTile(PPU::IO::Background&, uint hoffset, uint voffset) -> uint;
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ auto PPU::IO::serialize(serializer& s) -> void {
|
|||
s.integer(oamPriority);
|
||||
s.integer(bgPriority);
|
||||
s.integer(bgMode);
|
||||
s.integer(mosaicSize);
|
||||
s.integer(vramIncrementMode);
|
||||
s.integer(vramMapping);
|
||||
s.integer(vramIncrementSize);
|
||||
|
@ -58,6 +57,7 @@ auto PPU::IO::serialize(serializer& s) -> void {
|
|||
s.integer(pseudoHires);
|
||||
s.integer(extbg);
|
||||
|
||||
mosaic.serialize(s);
|
||||
mode7.serialize(s);
|
||||
window.serialize(s);
|
||||
bg1.serialize(s);
|
||||
|
@ -68,6 +68,12 @@ auto PPU::IO::serialize(serializer& s) -> void {
|
|||
col.serialize(s);
|
||||
}
|
||||
|
||||
auto PPU::IO::Mosaic::serialize(serializer& s) -> void {
|
||||
s.integer(enable);
|
||||
s.integer(size);
|
||||
s.integer(counter);
|
||||
}
|
||||
|
||||
auto PPU::IO::Mode7::serialize(serializer& s) -> void {
|
||||
s.integer(hflip);
|
||||
s.integer(vflip);
|
||||
|
@ -114,8 +120,6 @@ auto PPU::IO::Background::serialize(serializer& s) -> void {
|
|||
s.integer(aboveEnable);
|
||||
s.integer(belowEnable);
|
||||
s.integer(mosaicEnable);
|
||||
s.integer(mosaicCounter);
|
||||
s.integer(mosaicOffset);
|
||||
s.integer(tiledataAddress);
|
||||
s.integer(screenAddress);
|
||||
s.integer(screenSize);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "mode7.cpp"
|
||||
uint4 PPU::Background::Mosaic::size;
|
||||
|
||||
auto PPU::Background::hires() const -> bool {
|
||||
return ppu.io.bgMode == 5 || ppu.io.bgMode == 6;
|
||||
|
@ -11,26 +10,13 @@ auto PPU::Background::frame() -> void {
|
|||
|
||||
//H = 0
|
||||
auto PPU::Background::scanline() -> void {
|
||||
if(ppu.vcounter() == 1) {
|
||||
mosaic.vcounter = mosaic.size + 1;
|
||||
mosaic.voffset = 1;
|
||||
latch.hoffset = io.hoffset;
|
||||
latch.voffset = io.voffset;
|
||||
} else if(--mosaic.vcounter == 0) {
|
||||
mosaic.vcounter = mosaic.size + 1;
|
||||
mosaic.voffset += mosaic.size + 1;
|
||||
latch.hoffset = io.hoffset;
|
||||
latch.voffset = io.voffset;
|
||||
}
|
||||
|
||||
mosaic.hcounter = mosaic.size + 1;
|
||||
mosaic.hcounter = ppu.mosaic.size;
|
||||
mosaic.hoffset = 0;
|
||||
|
||||
if(io.mode == Mode::Mode7) return beginMode7();
|
||||
if(mosaic.size == 0) {
|
||||
latch.hoffset = io.hoffset;
|
||||
latch.voffset = io.voffset;
|
||||
}
|
||||
|
||||
latch.hoffset = io.hoffset;
|
||||
latch.voffset = io.voffset;
|
||||
|
||||
nameTableIndex = 0;
|
||||
characterIndex = 0;
|
||||
|
@ -52,13 +38,17 @@ auto PPU::Background::fetchNameTable() -> void {
|
|||
|
||||
int x = (ppu.hcounter() & ~31) >> 2;
|
||||
uint hpixel = x << hires();
|
||||
uint vpixel = mosaic.enable ? (uint)mosaic.voffset : ppu.vcounter();
|
||||
uint vpixel = ppu.vcounter();
|
||||
uint hscroll = latch.hoffset;
|
||||
uint vscroll = latch.voffset;
|
||||
|
||||
uint hscroll = mosaic.enable ? latch.hoffset : io.hoffset;
|
||||
uint vscroll = mosaic.enable ? latch.voffset : io.voffset;
|
||||
if(mosaic.enable) vpixel -= ppu.mosaic.voffset();
|
||||
if(hires()) {
|
||||
hscroll <<= 1;
|
||||
if(ppu.io.interlace) vpixel = vpixel << 1 | (ppu.field() && !mosaic.enable);
|
||||
if(ppu.io.interlace) {
|
||||
vpixel = vpixel << 1 | ppu.field();
|
||||
if(mosaic.enable) vpixel -= ppu.mosaic.voffset() + ppu.field();
|
||||
}
|
||||
}
|
||||
|
||||
bool repeated = false;
|
||||
|
@ -214,10 +204,10 @@ auto PPU::Background::run(bool screen) -> void {
|
|||
|
||||
uint x = ppu.hcounter() - 56 >> 2;
|
||||
if(x == 0) {
|
||||
mosaic.hcounter = mosaic.size + 1;
|
||||
mosaic.hcounter = ppu.mosaic.size;
|
||||
mosaic.pixel = pixel;
|
||||
} else if((!hires() || screen == Screen::Below) && --mosaic.hcounter == 0) {
|
||||
mosaic.hcounter = mosaic.size + 1;
|
||||
mosaic.hcounter = ppu.mosaic.size;
|
||||
mosaic.pixel = pixel;
|
||||
} else if(mosaic.enable) {
|
||||
pixel = mosaic.pixel;
|
||||
|
@ -246,6 +236,5 @@ auto PPU::Background::power() -> void {
|
|||
output.below = {};
|
||||
|
||||
mosaic = {};
|
||||
mosaic.size = random();
|
||||
mosaic.enable = random();
|
||||
}
|
||||
|
|
|
@ -61,15 +61,9 @@ struct Background {
|
|||
} output;
|
||||
|
||||
struct Mosaic {
|
||||
static uint4 size;
|
||||
uint1 enable;
|
||||
|
||||
uint16 vcounter;
|
||||
uint16 hcounter;
|
||||
|
||||
uint16 voffset;
|
||||
uint16 hoffset;
|
||||
|
||||
Pixel pixel;
|
||||
} mosaic;
|
||||
|
||||
|
|
|
@ -262,11 +262,15 @@ auto PPU::writeIO(uint addr, uint8 data) -> void {
|
|||
|
||||
//MOSAIC
|
||||
case 0x2106: {
|
||||
if(!mosaic.enable() && (data >> 0 & 15)) {
|
||||
//mosaic vcounter is reloaded when mosaic becomes enabled
|
||||
mosaic.vcounter = (data >> 4 & 15) + 2;
|
||||
}
|
||||
bg1.mosaic.enable = data >> 0 & 1;
|
||||
bg2.mosaic.enable = data >> 1 & 1;
|
||||
bg3.mosaic.enable = data >> 2 & 1;
|
||||
bg4.mosaic.enable = data >> 3 & 1;
|
||||
Background::Mosaic::size = data >> 4 & 15;
|
||||
mosaic.size = (data >> 4 & 15) + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ auto PPU::main() -> void {
|
|||
obj.frame();
|
||||
}
|
||||
|
||||
mosaic.scanline();
|
||||
bg1.scanline();
|
||||
bg2.scanline();
|
||||
bg3.scanline();
|
||||
|
|
|
@ -21,13 +21,12 @@ auto PPU::Background::runMode7() -> void {
|
|||
int voffset = (int13)latch.voffset;
|
||||
|
||||
uint x = mosaic.hoffset;
|
||||
uint y = !mosaic.enable ? ppu.vcounter() : ppu.bg1.mosaic.voffset; //BG2 vertical mosaic uses BG1 mosaic size
|
||||
uint y = ppu.vcounter();
|
||||
if(ppu.bg1.mosaic.enable) y -= ppu.mosaic.voffset(); //BG2 vertical mosaic uses BG1 mosaic enable
|
||||
|
||||
if(!mosaic.enable) {
|
||||
mosaic.hoffset += 1;
|
||||
} else if(--mosaic.hcounter == 0) {
|
||||
mosaic.hcounter = mosaic.size + 1;
|
||||
mosaic.hoffset += mosaic.size + 1;
|
||||
if(--mosaic.hcounter == 0) {
|
||||
mosaic.hcounter = ppu.mosaic.size;
|
||||
mosaic.hoffset += ppu.mosaic.size;
|
||||
}
|
||||
|
||||
if(ppu.io.hflipMode7) x = 255 - x;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
auto PPU::Mosaic::enable() const -> bool {
|
||||
if(ppu.bg1.mosaic.enable) return true;
|
||||
if(ppu.bg2.mosaic.enable) return true;
|
||||
if(ppu.bg3.mosaic.enable) return true;
|
||||
if(ppu.bg4.mosaic.enable) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto PPU::Mosaic::voffset() const -> uint {
|
||||
return size - vcounter;
|
||||
}
|
||||
|
||||
//H = 0
|
||||
auto PPU::Mosaic::scanline() -> void {
|
||||
if(ppu.vcounter() == 1) {
|
||||
vcounter = enable() ? size + 1 : 0;
|
||||
}
|
||||
if(vcounter && !--vcounter) {
|
||||
vcounter = enable() ? size + 0 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
auto PPU::Mosaic::power() -> void {
|
||||
size = (random() & 15) + 1;
|
||||
vcounter = 0;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
struct Mosaic {
|
||||
//mosaic.cpp
|
||||
alwaysinline auto enable() const -> bool;
|
||||
alwaysinline auto voffset() const -> uint;
|
||||
auto scanline() -> void;
|
||||
auto power() -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
uint5 size;
|
||||
uint5 vcounter;
|
||||
};
|
|
@ -5,6 +5,7 @@ namespace SuperFamicom {
|
|||
PPU ppu;
|
||||
#include "main.cpp"
|
||||
#include "io.cpp"
|
||||
#include "mosaic.cpp"
|
||||
#include "background.cpp"
|
||||
#include "object.cpp"
|
||||
#include "window.cpp"
|
||||
|
@ -173,6 +174,7 @@ auto PPU::power(bool reset) -> void {
|
|||
//$213d OPVCT
|
||||
io.vcounter = 0;
|
||||
|
||||
mosaic.power();
|
||||
bg1.power();
|
||||
bg2.power();
|
||||
bg3.power();
|
||||
|
|
|
@ -153,11 +153,13 @@ private:
|
|||
uint16 vcounter;
|
||||
} io;
|
||||
|
||||
#include "mosaic.hpp"
|
||||
#include "background.hpp"
|
||||
#include "object.hpp"
|
||||
#include "window.hpp"
|
||||
#include "screen.hpp"
|
||||
|
||||
Mosaic mosaic;
|
||||
Background bg1;
|
||||
Background bg2;
|
||||
Background bg3;
|
||||
|
|
|
@ -73,6 +73,7 @@ auto PPU::serialize(serializer& s) -> void {
|
|||
s.integer(io.hcounter);
|
||||
s.integer(io.vcounter);
|
||||
|
||||
mosaic.serialize(s);
|
||||
bg1.serialize(s);
|
||||
bg2.serialize(s);
|
||||
bg3.serialize(s);
|
||||
|
@ -82,6 +83,11 @@ auto PPU::serialize(serializer& s) -> void {
|
|||
screen.serialize(s);
|
||||
}
|
||||
|
||||
auto PPU::Mosaic::serialize(serializer& s) -> void {
|
||||
s.integer(size);
|
||||
s.integer(vcounter);
|
||||
}
|
||||
|
||||
auto PPU::Background::serialize(serializer& s) -> void {
|
||||
s.integer(io.tiledataAddress);
|
||||
s.integer(io.screenAddress);
|
||||
|
@ -105,11 +111,8 @@ auto PPU::Background::serialize(serializer& s) -> void {
|
|||
s.integer(output.below.palette);
|
||||
s.integer(output.below.paletteGroup);
|
||||
|
||||
s.integer(mosaic.size);
|
||||
s.integer(mosaic.enable);
|
||||
s.integer(mosaic.vcounter);
|
||||
s.integer(mosaic.hcounter);
|
||||
s.integer(mosaic.voffset);
|
||||
s.integer(mosaic.hoffset);
|
||||
|
||||
s.integer(mosaic.pixel.priority);
|
||||
|
|
Loading…
Reference in New Issue