mirror of https://github.com/bsnes-emu/bsnes.git
Fix an IRQ regression from a few releases back.
Add fast PPU render cycle position setting.
This commit is contained in:
parent
db1c37c799
commit
f9ca7a4927
|
@ -6,6 +6,7 @@ struct SuperFamicom {
|
||||||
|
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
auto region() const -> string;
|
auto region() const -> string;
|
||||||
|
auto videoRegion() const -> string;
|
||||||
auto revision() const -> string;
|
auto revision() const -> string;
|
||||||
auto board() const -> string;
|
auto board() const -> string;
|
||||||
auto title() const -> string;
|
auto title() const -> string;
|
||||||
|
@ -186,6 +187,11 @@ auto SuperFamicom::region() const -> string {
|
||||||
return region ? region : "NTSC";
|
return region ? region : "NTSC";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto SuperFamicom::videoRegion() const -> string {
|
||||||
|
auto region = data[headerAddress + 0x29];
|
||||||
|
return (region <= 0x01 || region >= 0x12) ? "NTSC" : "PAL";
|
||||||
|
}
|
||||||
|
|
||||||
auto SuperFamicom::revision() const -> string {
|
auto SuperFamicom::revision() const -> string {
|
||||||
string revision;
|
string revision;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ N push(PC.b);
|
||||||
IF = 1;
|
IF = 1;
|
||||||
DF = 0;
|
DF = 0;
|
||||||
PC.l = read(r.vector + 0);
|
PC.l = read(r.vector + 0);
|
||||||
PC.h = read(r.vector + 1);
|
L PC.h = read(r.vector + 1);
|
||||||
PC.b = 0x00;
|
PC.b = 0x00;
|
||||||
idleJump();
|
idleJump();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ auto CPU::irq(bool line) -> void {
|
||||||
WDC65816::irq(line);
|
WDC65816::irq(line);
|
||||||
if(line) {
|
if(line) {
|
||||||
status.irqTransition = 1;
|
status.irqTransition = 1;
|
||||||
r.wai = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ auto CPU::pollInterrupts() -> void {
|
||||||
//NMI hold
|
//NMI hold
|
||||||
if(status.nmiHold.lower() && io.nmiEnable) {
|
if(status.nmiHold.lower() && io.nmiEnable) {
|
||||||
status.nmiTransition = 1;
|
status.nmiTransition = 1;
|
||||||
r.wai = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//NMI test
|
//NMI test
|
||||||
|
@ -28,7 +26,6 @@ auto CPU::pollInterrupts() -> void {
|
||||||
status.irqHold = 0;
|
status.irqHold = 0;
|
||||||
if(status.irqLine && io.irqEnable) {
|
if(status.irqLine && io.irqEnable) {
|
||||||
status.irqTransition = 1;
|
status.irqTransition = 1;
|
||||||
r.wai = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//IRQ test
|
//IRQ test
|
||||||
|
@ -46,7 +43,6 @@ auto CPU::nmitimenUpdate(uint8 data) -> void {
|
||||||
|
|
||||||
if(io.virqEnable && !io.hirqEnable && status.irqLine) {
|
if(io.virqEnable && !io.hirqEnable && status.irqLine) {
|
||||||
status.irqTransition = 1;
|
status.irqTransition = 1;
|
||||||
r.wai = 0;
|
|
||||||
} else if(!io.irqEnable) {
|
} else if(!io.irqEnable) {
|
||||||
status.irqLine = 0;
|
status.irqLine = 0;
|
||||||
status.irqTransition = 0;
|
status.irqTransition = 0;
|
||||||
|
@ -54,7 +50,6 @@ auto CPU::nmitimenUpdate(uint8 data) -> void {
|
||||||
|
|
||||||
if(io.nmiEnable.raise(data & 0x80) && status.nmiLine) {
|
if(io.nmiEnable.raise(data & 0x80) && status.nmiLine) {
|
||||||
status.nmiTransition = 1;
|
status.nmiTransition = 1;
|
||||||
r.wai = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status.irqLock = 1;
|
status.irqLock = 1;
|
||||||
|
@ -80,12 +75,14 @@ auto CPU::timeup() -> bool {
|
||||||
auto CPU::nmiTest() -> bool {
|
auto CPU::nmiTest() -> bool {
|
||||||
if(!status.nmiTransition) return 0;
|
if(!status.nmiTransition) return 0;
|
||||||
status.nmiTransition = 0;
|
status.nmiTransition = 0;
|
||||||
|
r.wai = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::irqTest() -> bool {
|
auto CPU::irqTest() -> bool {
|
||||||
if(!status.irqTransition) return 0;
|
if(!status.irqTransition) return 0;
|
||||||
status.irqTransition = 0;
|
status.irqTransition = 0;
|
||||||
|
r.wai = 0;
|
||||||
return !r.p.i;
|
return !r.p.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ auto Configuration::process(Markup::Node document, bool load) -> void {
|
||||||
bind(natural, "Hacks/CPU/Overclock", hacks.cpu.overclock);
|
bind(natural, "Hacks/CPU/Overclock", hacks.cpu.overclock);
|
||||||
bind(boolean, "Hacks/PPU/Fast", hacks.ppu.fast);
|
bind(boolean, "Hacks/PPU/Fast", hacks.ppu.fast);
|
||||||
bind(boolean, "Hacks/PPU/Deinterlace", hacks.ppu.deinterlace);
|
bind(boolean, "Hacks/PPU/Deinterlace", hacks.ppu.deinterlace);
|
||||||
|
bind(natural, "Hacks/PPU/RenderCycle", hacks.ppu.renderCycle);
|
||||||
bind(boolean, "Hacks/PPU/NoSpriteLimit", hacks.ppu.noSpriteLimit);
|
bind(boolean, "Hacks/PPU/NoSpriteLimit", hacks.ppu.noSpriteLimit);
|
||||||
bind(natural, "Hacks/PPU/Mode7/Scale", hacks.ppu.mode7.scale);
|
bind(natural, "Hacks/PPU/Mode7/Scale", hacks.ppu.mode7.scale);
|
||||||
bind(boolean, "Hacks/PPU/Mode7/Perspective", hacks.ppu.mode7.perspective);
|
bind(boolean, "Hacks/PPU/Mode7/Perspective", hacks.ppu.mode7.perspective);
|
||||||
|
|
|
@ -32,6 +32,7 @@ struct Configuration {
|
||||||
bool fast = true;
|
bool fast = true;
|
||||||
bool deinterlace = true;
|
bool deinterlace = true;
|
||||||
bool noSpriteLimit = false;
|
bool noSpriteLimit = false;
|
||||||
|
uint renderCycle = 512;
|
||||||
struct Mode7 {
|
struct Mode7 {
|
||||||
uint scale = 1;
|
uint scale = 1;
|
||||||
bool perspective = true;
|
bool perspective = true;
|
||||||
|
|
|
@ -29,6 +29,7 @@ auto PPU::hdPerspective() const -> bool { return configuration.hacks.ppu.mode7.p
|
||||||
auto PPU::hdSupersample() const -> bool { return configuration.hacks.ppu.mode7.supersample; }
|
auto PPU::hdSupersample() const -> bool { return configuration.hacks.ppu.mode7.supersample; }
|
||||||
auto PPU::hdMosaic() const -> bool { return configuration.hacks.ppu.mode7.mosaic; }
|
auto PPU::hdMosaic() const -> bool { return configuration.hacks.ppu.mode7.mosaic; }
|
||||||
auto PPU::deinterlace() const -> bool { return configuration.hacks.ppu.deinterlace; }
|
auto PPU::deinterlace() const -> bool { return configuration.hacks.ppu.deinterlace; }
|
||||||
|
auto PPU::renderCycle() const -> uint { return configuration.hacks.ppu.renderCycle; }
|
||||||
#define ppu ppufast
|
#define ppu ppufast
|
||||||
|
|
||||||
PPU::PPU() {
|
PPU::PPU() {
|
||||||
|
@ -88,7 +89,7 @@ auto PPU::main() -> void {
|
||||||
|
|
||||||
if(system.frameCounter == 0) {
|
if(system.frameCounter == 0) {
|
||||||
uint y = vcounter();
|
uint y = vcounter();
|
||||||
step(512);
|
step(renderCycle());
|
||||||
if(y >= 1 && y <= 239) {
|
if(y >= 1 && y <= 239) {
|
||||||
if(io.displayDisable || y >= vdisp()) {
|
if(io.displayDisable || y >= vdisp()) {
|
||||||
lines[y].io.displayDisable = true;
|
lines[y].io.displayDisable = true;
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct PPU : PPUcounter {
|
||||||
alwaysinline auto hdSupersample() const -> bool;
|
alwaysinline auto hdSupersample() const -> bool;
|
||||||
alwaysinline auto hdMosaic() const -> bool;
|
alwaysinline auto hdMosaic() const -> bool;
|
||||||
alwaysinline auto deinterlace() const -> bool;
|
alwaysinline auto deinterlace() const -> bool;
|
||||||
|
alwaysinline auto renderCycle() const -> uint;
|
||||||
|
|
||||||
//ppu.cpp
|
//ppu.cpp
|
||||||
PPU();
|
PPU();
|
||||||
|
|
|
@ -130,6 +130,7 @@ auto Program::loadSuperFamicom(string location) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
superFamicom.title = heuristics.title();
|
superFamicom.title = heuristics.title();
|
||||||
|
superFamicom.region = heuristics.videoRegion();
|
||||||
superFamicom.manifest = manifest ? manifest : heuristics.manifest();
|
superFamicom.manifest = manifest ? manifest : heuristics.manifest();
|
||||||
hackPatchMemory(rom);
|
hackPatchMemory(rom);
|
||||||
superFamicom.document = BML::unserialize(superFamicom.manifest);
|
superFamicom.document = BML::unserialize(superFamicom.manifest);
|
||||||
|
|
|
@ -3,14 +3,26 @@ auto Program::hackCompatibility() -> void {
|
||||||
bool fastPPUNoSpriteLimit = emulatorSettings.noSpriteLimit.checked();
|
bool fastPPUNoSpriteLimit = emulatorSettings.noSpriteLimit.checked();
|
||||||
bool fastDSP = emulatorSettings.fastDSP.checked();
|
bool fastDSP = emulatorSettings.fastDSP.checked();
|
||||||
bool coprocessorDelayedSync = emulatorSettings.coprocessorDelayedSyncOption.checked();
|
bool coprocessorDelayedSync = emulatorSettings.coprocessorDelayedSyncOption.checked();
|
||||||
|
uint renderCycle = 512;
|
||||||
|
|
||||||
auto title = superFamicom.title;
|
auto title = superFamicom.title;
|
||||||
|
auto region = superFamicom.region;
|
||||||
|
|
||||||
|
//relies on mid-scanline rendering techniques
|
||||||
if(title == "AIR STRIKE PATROL" || title == "DESERT FIGHTER") fastPPU = false;
|
if(title == "AIR STRIKE PATROL" || title == "DESERT FIGHTER") fastPPU = false;
|
||||||
|
|
||||||
|
//relies on cycle-accurate writes to the echo buffer
|
||||||
if(title == "KOUSHIEN_2") fastDSP = false;
|
if(title == "KOUSHIEN_2") fastDSP = false;
|
||||||
|
|
||||||
|
//extremely timing sensitive
|
||||||
if(title == "RENDERING RANGER R2") fastDSP = false;
|
if(title == "RENDERING RANGER R2") fastDSP = false;
|
||||||
|
|
||||||
|
//fixes an errant scanline on the title screen due to writing to PPU registers too late
|
||||||
|
if(title == "ADVENTURES OF FRANKEN" && region == "PAL") renderCycle = 32;
|
||||||
|
|
||||||
emulator->configure("Hacks/PPU/Fast", fastPPU);
|
emulator->configure("Hacks/PPU/Fast", fastPPU);
|
||||||
emulator->configure("Hacks/PPU/NoSpriteLimit", fastPPUNoSpriteLimit);
|
emulator->configure("Hacks/PPU/NoSpriteLimit", fastPPUNoSpriteLimit);
|
||||||
|
emulator->configure("Hacks/PPU/RenderCycle", renderCycle);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Scale", settings.emulator.hack.ppu.mode7.scale);
|
emulator->configure("Hacks/PPU/Mode7/Scale", settings.emulator.hack.ppu.mode7.scale);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Perspective", settings.emulator.hack.ppu.mode7.perspective);
|
emulator->configure("Hacks/PPU/Mode7/Perspective", settings.emulator.hack.ppu.mode7.perspective);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Supersample", settings.emulator.hack.ppu.mode7.supersample);
|
emulator->configure("Hacks/PPU/Mode7/Supersample", settings.emulator.hack.ppu.mode7.supersample);
|
||||||
|
|
|
@ -150,6 +150,7 @@ public:
|
||||||
|
|
||||||
struct SuperFamicom : Game {
|
struct SuperFamicom : Game {
|
||||||
string title;
|
string title;
|
||||||
|
string region;
|
||||||
vector<uint8_t> program;
|
vector<uint8_t> program;
|
||||||
vector<uint8_t> data;
|
vector<uint8_t> data;
|
||||||
vector<uint8_t> expansion;
|
vector<uint8_t> expansion;
|
||||||
|
|
Loading…
Reference in New Issue