mirror of https://github.com/bsnes-emu/bsnes.git
v114.2
Serialize SDD1 PEM (fixes run-ahead in Star Ocean) Dot PPU: calculate nameTableIndex and characterIndex from ppu.hcounter() (fixes scanline glitch in Great Battle IV) Dot PPU: do not latch BG H/V scroll registers (fixes Air Strike Patrol raster effects) (fixes Septentrion glitchy scanline)
This commit is contained in:
parent
358a3ceed7
commit
52d5b3e2a2
|
@ -29,13 +29,13 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "bsnes";
|
||||
static const string Version = "114.1";
|
||||
static const string Version = "114.2";
|
||||
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 = "114.1";
|
||||
static const string SerializerVersion = "114.2";
|
||||
|
||||
namespace Constants {
|
||||
namespace Colorburst {
|
||||
|
|
|
@ -6,9 +6,9 @@ auto SDD1::serialize(serializer& s) -> void {
|
|||
s.integer(r4806);
|
||||
s.integer(r4807);
|
||||
|
||||
for(auto n : range(8)) {
|
||||
s.integer(dma[n].addr);
|
||||
s.integer(dma[n].size);
|
||||
for(auto& channel : dma) {
|
||||
s.integer(channel.addr);
|
||||
s.integer(channel.size);
|
||||
}
|
||||
s.integer(dmaReady);
|
||||
|
||||
|
@ -26,6 +26,7 @@ auto SDD1::Decompressor::serialize(serializer& s) -> void {
|
|||
bg5.serialize(s);
|
||||
bg6.serialize(s);
|
||||
bg7.serialize(s);
|
||||
pem.serialize(s);
|
||||
cm.serialize(s);
|
||||
ol.serialize(s);
|
||||
}
|
||||
|
|
|
@ -13,13 +13,6 @@ auto PPU::Background::scanline() -> void {
|
|||
mosaic.hcounter = ppu.mosaic.size;
|
||||
mosaic.hoffset = 0;
|
||||
|
||||
if(io.mode == Mode::Mode7) return beginMode7();
|
||||
|
||||
latch.hoffset = io.hoffset;
|
||||
latch.voffset = io.voffset;
|
||||
|
||||
nameTableIndex = 0;
|
||||
characterIndex = 0;
|
||||
renderingIndex = 0;
|
||||
|
||||
opt.hoffset = 0;
|
||||
|
@ -36,11 +29,13 @@ auto PPU::Background::begin() -> void {
|
|||
auto PPU::Background::fetchNameTable() -> void {
|
||||
if(ppu.vcounter() == 0) return;
|
||||
|
||||
uint nameTableIndex = ppu.hcounter() >> 5 << hires();
|
||||
int x = (ppu.hcounter() & ~31) >> 2;
|
||||
|
||||
uint hpixel = x << hires();
|
||||
uint vpixel = ppu.vcounter();
|
||||
uint hscroll = latch.hoffset;
|
||||
uint vscroll = latch.voffset;
|
||||
uint hscroll = io.hoffset;
|
||||
uint vscroll = io.voffset;
|
||||
|
||||
if(mosaic.enable) vpixel -= ppu.mosaic.voffset();
|
||||
if(hires()) {
|
||||
|
@ -131,6 +126,7 @@ auto PPU::Background::fetchNameTable() -> void {
|
|||
auto PPU::Background::fetchOffset(uint y) -> void {
|
||||
if(ppu.vcounter() == 0) return;
|
||||
|
||||
uint characterIndex = ppu.hcounter() >> 5 << hires();
|
||||
uint x = characterIndex << 3;
|
||||
|
||||
uint hoffset = x + (io.hoffset & ~7);
|
||||
|
@ -152,13 +148,13 @@ auto PPU::Background::fetchOffset(uint y) -> void {
|
|||
uint16 address = io.screenAddress + offset;
|
||||
if(y == 0) opt.hoffset = ppu.vram[address];
|
||||
if(y == 8) opt.voffset = ppu.vram[address];
|
||||
|
||||
if(y == 0) characterIndex++;
|
||||
}
|
||||
|
||||
auto PPU::Background::fetchCharacter(uint index) -> void {
|
||||
auto PPU::Background::fetchCharacter(uint index, bool half) -> void {
|
||||
if(ppu.vcounter() == 0) return;
|
||||
|
||||
uint characterIndex = (ppu.hcounter() >> 5 << hires()) + half;
|
||||
|
||||
auto& tile = tiles[characterIndex];
|
||||
uint16 data = ppu.vram[tile.address + (index << 3)];
|
||||
|
||||
|
@ -174,8 +170,6 @@ auto PPU::Background::fetchCharacter(uint index) -> void {
|
|||
((uint8(data >> 0) * 0x0101010101010101ull & 0x8040201008040201ull) * 0x0102040810204081ull >> 49) & 0x5555
|
||||
| ((uint8(data >> 8) * 0x0101010101010101ull & 0x8040201008040201ull) * 0x0102040810204081ull >> 48) & 0xaaaa
|
||||
);
|
||||
|
||||
if(index == 0) characterIndex++;
|
||||
}
|
||||
|
||||
auto PPU::Background::run(bool screen) -> void {
|
||||
|
@ -230,8 +224,6 @@ auto PPU::Background::power() -> void {
|
|||
io.hoffset = random();
|
||||
io.voffset = random();
|
||||
|
||||
latch = {};
|
||||
|
||||
output.above = {};
|
||||
output.below = {};
|
||||
|
||||
|
|
|
@ -9,13 +9,12 @@ struct Background {
|
|||
auto begin() -> void;
|
||||
auto fetchNameTable() -> void;
|
||||
auto fetchOffset(uint y) -> void;
|
||||
auto fetchCharacter(uint index) -> void;
|
||||
auto fetchCharacter(uint index, bool half = 0) -> void;
|
||||
auto run(bool screen) -> void;
|
||||
auto power() -> void;
|
||||
|
||||
//mode7.cpp
|
||||
alwaysinline auto clip(int n) -> int;
|
||||
auto beginMode7() -> void;
|
||||
auto runMode7() -> void;
|
||||
|
||||
auto serialize(serializer&) -> void;
|
||||
|
@ -44,11 +43,6 @@ struct Background {
|
|||
uint16 voffset;
|
||||
} io;
|
||||
|
||||
struct Latch {
|
||||
uint16 hoffset;
|
||||
uint16 voffset;
|
||||
} latch;
|
||||
|
||||
struct Pixel {
|
||||
uint8 priority; //0 = none (transparent)
|
||||
uint8 palette;
|
||||
|
@ -84,8 +78,8 @@ struct Background {
|
|||
uint16 data[4];
|
||||
} tiles[66];
|
||||
|
||||
uint7 nameTableIndex;
|
||||
uint7 characterIndex;
|
||||
uint7 nameTableIndex2;
|
||||
uint7 characterIndex2;
|
||||
uint7 renderingIndex;
|
||||
uint3 pixelCounter;
|
||||
|
||||
|
|
|
@ -95,60 +95,60 @@ auto PPU::cycleBackgroundFetch() -> void {
|
|||
if constexpr(Cycle == 1) bg2.fetchNameTable();
|
||||
if constexpr(Cycle == 2) bg1.fetchNameTable();
|
||||
if constexpr(Cycle == 3) bg3.fetchCharacter(0);
|
||||
if constexpr(Cycle == 4) bg2.fetchCharacter(1);
|
||||
if constexpr(Cycle == 5) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 4) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 5) bg2.fetchCharacter(1);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(1);
|
||||
break;
|
||||
case 2:
|
||||
if constexpr(Cycle == 0) bg2.fetchNameTable();
|
||||
if constexpr(Cycle == 1) bg1.fetchNameTable();
|
||||
if constexpr(Cycle == 2) bg3.fetchOffset(8);
|
||||
if constexpr(Cycle == 3) bg3.fetchOffset(0);
|
||||
if constexpr(Cycle == 4) bg2.fetchCharacter(1);
|
||||
if constexpr(Cycle == 5) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 2) bg3.fetchOffset(0);
|
||||
if constexpr(Cycle == 3) bg3.fetchOffset(8);
|
||||
if constexpr(Cycle == 4) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 5) bg2.fetchCharacter(1);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(1);
|
||||
break;
|
||||
case 3:
|
||||
if constexpr(Cycle == 0) bg2.fetchNameTable();
|
||||
if constexpr(Cycle == 1) bg1.fetchNameTable();
|
||||
if constexpr(Cycle == 2) bg2.fetchCharacter(1);
|
||||
if constexpr(Cycle == 3) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(3);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(2);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 2) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 3) bg2.fetchCharacter(1);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(2);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(3);
|
||||
break;
|
||||
case 4:
|
||||
if constexpr(Cycle == 0) bg2.fetchNameTable();
|
||||
if constexpr(Cycle == 1) bg1.fetchNameTable();
|
||||
if constexpr(Cycle == 2) bg3.fetchOffset(0);
|
||||
if constexpr(Cycle == 3) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(3);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(2);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(2);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(3);
|
||||
break;
|
||||
case 5:
|
||||
if constexpr(Cycle == 0) bg2.fetchNameTable();
|
||||
if constexpr(Cycle == 1) bg1.fetchNameTable();
|
||||
if constexpr(Cycle == 2) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 3) bg2.fetchCharacter(0);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 2) bg2.fetchCharacter(0, 0);
|
||||
if constexpr(Cycle == 3) bg2.fetchCharacter(0, 1);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(0, 0);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(1, 0);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(0, 1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(1, 1);
|
||||
break;
|
||||
case 6:
|
||||
if constexpr(Cycle == 0) bg2.fetchNameTable();
|
||||
if constexpr(Cycle == 1) bg1.fetchNameTable();
|
||||
if constexpr(Cycle == 2) bg3.fetchOffset(8);
|
||||
if constexpr(Cycle == 3) bg3.fetchOffset(0);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(0);
|
||||
if constexpr(Cycle == 2) bg3.fetchOffset(0);
|
||||
if constexpr(Cycle == 3) bg3.fetchOffset(8);
|
||||
if constexpr(Cycle == 4) bg1.fetchCharacter(0, 0);
|
||||
if constexpr(Cycle == 5) bg1.fetchCharacter(1, 0);
|
||||
if constexpr(Cycle == 6) bg1.fetchCharacter(0, 1);
|
||||
if constexpr(Cycle == 7) bg1.fetchCharacter(1, 1);
|
||||
break;
|
||||
case 7:
|
||||
//handled separately by mode7.cpp
|
||||
|
|
|
@ -3,12 +3,6 @@ auto PPU::Background::clip(int n) -> int {
|
|||
return n & 0x2000 ? (n | ~1023) : (n & 1023);
|
||||
}
|
||||
|
||||
//H = 0
|
||||
auto PPU::Background::beginMode7() -> void {
|
||||
latch.hoffset = ppu.io.hoffsetMode7;
|
||||
latch.voffset = ppu.io.voffsetMode7;
|
||||
}
|
||||
|
||||
auto PPU::Background::runMode7() -> void {
|
||||
int a = (int16)ppu.io.m7a;
|
||||
int b = (int16)ppu.io.m7b;
|
||||
|
@ -17,14 +11,16 @@ auto PPU::Background::runMode7() -> void {
|
|||
|
||||
int hcenter = (int13)ppu.io.m7x;
|
||||
int vcenter = (int13)ppu.io.m7y;
|
||||
int hoffset = (int13)latch.hoffset;
|
||||
int voffset = (int13)latch.voffset;
|
||||
int hoffset = (int13)ppu.io.hoffsetMode7;
|
||||
int voffset = (int13)ppu.io.voffsetMode7;
|
||||
|
||||
uint x = mosaic.hoffset;
|
||||
uint y = ppu.vcounter();
|
||||
if(ppu.bg1.mosaic.enable) y -= ppu.mosaic.voffset(); //BG2 vertical mosaic uses BG1 mosaic enable
|
||||
|
||||
if(--mosaic.hcounter == 0) {
|
||||
if(!mosaic.enable) {
|
||||
mosaic.hoffset += 1;
|
||||
} else if(--mosaic.hcounter == 0) {
|
||||
mosaic.hcounter = ppu.mosaic.size;
|
||||
mosaic.hoffset += ppu.mosaic.size;
|
||||
}
|
||||
|
|
|
@ -100,9 +100,6 @@ auto PPU::Background::serialize(serializer& s) -> void {
|
|||
s.integer(io.hoffset);
|
||||
s.integer(io.voffset);
|
||||
|
||||
s.integer(latch.hoffset);
|
||||
s.integer(latch.voffset);
|
||||
|
||||
s.integer(output.above.priority);
|
||||
s.integer(output.above.palette);
|
||||
s.integer(output.above.paletteGroup);
|
||||
|
@ -133,8 +130,6 @@ auto PPU::Background::serialize(serializer& s) -> void {
|
|||
s.array(tile.data);
|
||||
}
|
||||
|
||||
s.integer(nameTableIndex);
|
||||
s.integer(characterIndex);
|
||||
s.integer(renderingIndex);
|
||||
s.integer(pixelCounter);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue