Completely disabled auto-joypad timing (happens immediately)
(fixes World Masters until this can be emulated fully)
Disabled fast PPU for Winter Olympic Games
(changes OAM tiledata address mid-frame)
Disabled fast PPU for World Cup Striker
(I'm not sure yet why it's not compatible)
Cleared overscan region when disabling overscan
(fixes World Class Service SNES Tester)
Added override for invalid SNES header in Yuyu no Quiz de Go! Go!
This commit is contained in:
byuu 2019-12-30 06:00:17 +09:00
parent cc4ab9bc25
commit 793f2e5bf4
6 changed files with 69 additions and 11 deletions

View File

@ -29,7 +29,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "bsnes";
static const string Version = "113.3";
static const string Version = "113.4";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org";

View File

@ -266,6 +266,9 @@ auto SuperFamicom::board() const -> string {
if(headerAddress == 0x40ffb0) mode = "EXHIROM-";
}
//this game's title ovewrites the map mode with '!' (0x21), but is a LOROM game
if(title() == "YUYU NO QUIZ DE GO!GO") mode = "LOROM-";
if(mode == "LOROM-" && headerAddress == 0x407fb0) mode = "EXLOROM-";
bool epsonRTC = false;

View File

@ -5,11 +5,7 @@ auto CPU::dmaCounter() const -> uint {
//joypad auto-poll clock divider
auto CPU::joypadCounter() const -> uint {
//todo: this should be &255, but it causes too many issues in games, due to incomplete emulation:
//Nuke (PD): inputs do not work (unless clearing $421x to $00)
//Taikyoku Igo - Goliath: start button not acknowledged (unless clearing $421x to $ff)
//Tatakae Genshijin 2: attract sequence ends early
return counter.cpu & 31;
return counter.cpu & 255;
}
auto CPU::stepOnce() -> void {
@ -206,6 +202,41 @@ auto CPU::dmaEdge() -> void {
//called every 256 clocks; see CPU::step()
auto CPU::joypadEdge() -> void {
//todo: auto-joypad polling should poll one bit every 256 clock cycles,
//but it causes too many issues in games, due to incomplete emulation:
//Nuke (PD): inputs do not work (unless clearing $421x to $00)
//Taikyoku Igo - Goliath: start button not acknowledged (unless clearing $421x to $ff)
//Tatakae Genshijin 2: attract sequence ends early
//Williams Arcade's Greatest Hits: verifies io.joy# should be set to 0 and not ~0
//World Masters Golf: inputs do not work at all
//immediate polling:
if(!status.autoJoypadCounter && vcounter() >= ppu.vdisp()) {
controllerPort1.device->latch(1);
controllerPort2.device->latch(1);
controllerPort1.device->latch(0);
controllerPort2.device->latch(0);
io.joy1 = 0;
io.joy2 = 0;
io.joy3 = 0;
io.joy4 = 0;
for(uint index : range(16)) {
uint2 port0 = controllerPort1.device->data();
uint2 port1 = controllerPort2.device->data();
io.joy1 = io.joy1 << 1 | port0.bit(0);
io.joy2 = io.joy2 << 1 | port1.bit(0);
io.joy3 = io.joy3 << 1 | port0.bit(1);
io.joy4 = io.joy4 << 1 | port1.bit(1);
}
status.autoJoypadCounter = 16;
}
return;
//disabled cycle-timed polling:
if(vcounter() >= ppu.vdisp()) {
//cache enable state at first iteration
if(status.autoJoypadCounter == 0) status.autoJoypadLatch = io.autoJoypadPoll;
@ -218,11 +249,11 @@ auto CPU::joypadEdge() -> void {
controllerPort1.device->latch(0);
controllerPort2.device->latch(0);
//shift registers are flushed at start of auto joypad polling
io.joy1 = ~0;
io.joy2 = ~0;
io.joy3 = ~0;
io.joy4 = ~0;
//shift registers are cleared at start of auto joypad polling
io.joy1 = 0;
io.joy2 = 0;
io.joy3 = 0;
io.joy4 = 0;
}
uint2 port0 = controllerPort1.device->data();

View File

@ -94,6 +94,15 @@ auto PPU::main() -> void {
auto PPU::scanline() -> void {
if(vcounter() == 0) {
if(latch.overscan && !io.overscan) {
//when disabling overscan, clear the overscan area that won't be rendered to:
for(uint y = 1; y <= 240; y++) {
if(y >= 8 && y <= 231) continue;
auto output = ppu.output + y * 1024;
memory::fill<uint16>(output, 1024);
}
}
ppubase.display.interlace = io.interlace;
ppubase.display.overscan = io.overscan;
latch.overscan = io.overscan;

View File

@ -1,5 +1,13 @@
auto PPU::main() -> void {
if(vcounter() == 0) {
if(display.overscan && !io.overscan) {
//when disabling overscan, clear the overscan area that won't be rendered to:
for(uint y = 1; y <= 240; y++) {
if(y >= 8 && y <= 231) continue;
auto output = ppu.output + y * 1024;
memory::fill<uint16>(output, 1024);
}
}
display.interlace = io.interlace;
display.overscan = io.overscan;
bg1.frame();

View File

@ -15,6 +15,13 @@ auto Program::hackCompatibility() -> void {
//stage 2 uses pseudo-hires in a way that's not compatible with the scanline-based renderer
if(title == "SFC クレヨンシンチャン") fastPPU = false;
//title screen game select (after choosing a game) changes OAM tiledata address mid-frame
//this is only supported by the cycle-based PPU renderer
if(title == "Winter olympics") fastPPU = false;
//title screen shows remnants of the flag after choosing a language with the scanline-based renderer
if(title == "WORLD CUP STRIKER") fastPPU = false;
//relies on cycle-accurate writes to the echo buffer
if(title == "KOUSHIEN_2") fastDSP = false;