BSNESv115+: update from upstream

This commit is contained in:
Morilli 2025-07-05 21:48:25 +02:00
parent c9bbb81c15
commit 8f01fb755e
7 changed files with 62 additions and 32 deletions

Binary file not shown.

View File

@ -35,7 +35,7 @@ namespace Emulator {
static const string Website = "https://bsnes.dev";
//incremented only when serialization format changes
static const string SerializerVersion = "115";
static const string SerializerVersion = "115.1";
namespace Constants {
namespace Colorburst {

View File

@ -121,6 +121,12 @@ private:
bool hdmaMode = 0; //0 = init, 1 = run
uint autoJoypadCounter = 33; //state machine; 4224 / 128 = 33 (inactive)
uint2 autoJoypadPort1 = 0;
uint2 autoJoypadPort2 = 0;
bool cpuLatch = false;
bool autoJoypadLatch = false;
} status;
struct IO {

View File

@ -132,13 +132,22 @@ auto CPU::writeCPU(uint addr, uint8 data) -> void {
//bit 0 is shared between JOYSER0 and JOYSER1:
//strobing $4016.d0 affects both controller port latches.
//$4017 bit 0 writes are ignored.
controllerPort1.device->latch(data & 1);
controllerPort2.device->latch(data & 1);
status.cpuLatch = data & 1;
controllerPort1.device->latch(status.autoJoypadLatch | status.cpuLatch);
controllerPort2.device->latch(status.autoJoypadLatch | status.cpuLatch);
return;
case 0x4200: //NMITIMEN
io.autoJoypadPoll = data & 1;
if(!io.autoJoypadPoll) status.autoJoypadCounter = 33; // Disable auto-joypad read
if(status.autoJoypadCounter == 0) {
// allow controller latches during this time
status.autoJoypadLatch = io.autoJoypadPoll;
controllerPort1.device->latch(status.autoJoypadLatch | status.cpuLatch);
controllerPort2.device->latch(status.autoJoypadLatch | status.cpuLatch);
} else if (!io.autoJoypadPoll && status.autoJoypadCounter >= 2) {
status.autoJoypadCounter = 33;
}
nmitimenUpdate(data);
return;

View File

@ -45,6 +45,12 @@ auto CPU::serialize(serializer& s) -> void {
s.integer(status.autoJoypadCounter);
s.integer(status.autoJoypadPort1);
s.integer(status.autoJoypadPort2);
s.boolean(status.cpuLatch);
s.boolean(status.autoJoypadLatch);
s.integer(io.wramAddress);
s.boolean(io.hirqEnable);

View File

@ -211,45 +211,54 @@ auto CPU::dmaEdge() -> void {
//called every 128 clocks from inside the CPU::stepOnce() function
auto CPU::joypadEdge() -> void {
//it is not yet confirmed if polling can be stopped early and/or (re)started later
if(!io.autoJoypadPoll) return;
if(vcounter() == ppu.vdisp() && hcounter() >= 130 && hcounter() <= 256) {
if(vcounter() == ppu.vdisp() && (counter.cpu & 255) == 0 && hcounter() >= 130 && hcounter() <= 384) {
//begin new polling sequence
status.autoJoypadCounter = 0;
}
} else {
//stop after polling has been completed for this frame
if(status.autoJoypadCounter >= 33) return;
//stop after polling has been completed for this frame
if(status.autoJoypadCounter >= 33) return;
status.autoJoypadCounter++;
}
if(status.autoJoypadCounter == 0) {
//latch controller states on the first polling cycle
controllerPort1.device->latch(1);
controllerPort2.device->latch(1);
status.autoJoypadLatch = io.autoJoypadPoll;
controllerPort1.device->latch(status.autoJoypadLatch | status.cpuLatch);
controllerPort2.device->latch(status.autoJoypadLatch | status.cpuLatch);
if(io.autoJoypadPoll) {
//shift registers are cleared to zero at start of auto-joypad polling
io.joy1 = 0;
io.joy2 = 0;
io.joy3 = 0;
io.joy4 = 0;
}
}
if(status.autoJoypadCounter == 1) {
//release latch and begin reading on the second cycle
controllerPort1.device->latch(0);
controllerPort2.device->latch(0);
//shift registers are cleared to zero at start of auto-joypad polling
io.joy1 = 0;
io.joy2 = 0;
io.joy3 = 0;
io.joy4 = 0;
status.autoJoypadLatch = 0;
controllerPort1.device->latch(status.autoJoypadLatch | status.cpuLatch);
controllerPort2.device->latch(status.autoJoypadLatch | status.cpuLatch);
}
if(status.autoJoypadCounter >= 2 && !(status.autoJoypadCounter & 1)) {
if(status.autoJoypadCounter != 1 && !io.autoJoypadPoll) {
// if auto-joypad polling is disabled at this point skip the rest of the polling
status.autoJoypadCounter = 33;
return;
}
if(status.autoJoypadCounter >= 2) {
//sixteen bits are shifted into joy{1-4}, one bit per 256 clocks
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);
//the bits are read on one 128-clock cycle and written on the next
if ((status.autoJoypadCounter & 1) == 0) {
status.autoJoypadPort1 = controllerPort1.device->data();
status.autoJoypadPort2 = controllerPort2.device->data();
} else {
io.joy1 = io.joy1 << 1 | status.autoJoypadPort1.bit(0);
io.joy2 = io.joy2 << 1 | status.autoJoypadPort2.bit(0);
io.joy3 = io.joy3 << 1 | status.autoJoypadPort1.bit(1);
io.joy4 = io.joy4 << 1 | status.autoJoypadPort2.bit(1);
}
}
status.autoJoypadCounter++;
}

View File

@ -61,7 +61,7 @@ auto PPU::Background::fetchNameTable() -> void {
if(!(hlookup & 0x8000)) {
hoffset = hpixel + (hlookup & ~7) + (hscroll & 7);
} else {
voffset = vpixel + (vlookup);
voffset = vpixel + (hlookup);
}
}
} else {