mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-10-05 08:21:35 +02:00
Update to bsnes v050 release.
I always regret having to post new releases so quickly, but a semi-major bug crept into v049. I'd rather fix it now, before I start making major changes that will need testing again. The problem was that the S-PPU was not being synchronized as often as it should have been, resulting in titles such as F-Zero and Super Mario Kart showing flickering lines here and there. This release fixes that. This release also adds savestate support for Mega Man X2 and Mega Man X3, which utilize the Cx4 coprocessor; and it fixes a bug where input was still accepted even when the main window was minimized.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
static const char bsnesVersion[] = "0.049";
|
static const char bsnesVersion[] = "0.050";
|
||||||
static const char bsnesTitle[] = "bsnes";
|
static const char bsnesTitle[] = "bsnes";
|
||||||
static const unsigned bsnesSaveStateVersion = 2;
|
static const unsigned bsnesSaveStateVersion = 2;
|
||||||
|
|
||||||
|
@@ -11,10 +11,11 @@ namespace SNES {
|
|||||||
|
|
||||||
Cx4 cx4;
|
Cx4 cx4;
|
||||||
|
|
||||||
#include "cx4data.cpp"
|
#include "serialization.cpp"
|
||||||
#include "cx4fn.cpp"
|
#include "data.cpp"
|
||||||
#include "cx4oam.cpp"
|
#include "functions.cpp"
|
||||||
#include "cx4ops.cpp"
|
#include "oam.cpp"
|
||||||
|
#include "opcodes.cpp"
|
||||||
|
|
||||||
void Cx4::init() {
|
void Cx4::init() {
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,15 @@
|
|||||||
class Cx4 : public Memory {
|
class Cx4 : public Memory {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8 read(unsigned addr);
|
||||||
|
void write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
|
void serialize(serializer&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8 ram[0x0c00];
|
uint8 ram[0x0c00];
|
||||||
uint8 reg[0x0100];
|
uint8 reg[0x0100];
|
||||||
@@ -15,6 +26,7 @@ private:
|
|||||||
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
|
||||||
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
|
||||||
|
|
||||||
|
//todo: get rid of floating-point values, replace with integers
|
||||||
double tanval;
|
double tanval;
|
||||||
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
|
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
|
||||||
|
|
||||||
@@ -82,16 +94,6 @@ public:
|
|||||||
void writeb(uint16 addr, uint8 data);
|
void writeb(uint16 addr, uint8 data);
|
||||||
void writew(uint16 addr, uint16 data);
|
void writew(uint16 addr, uint16 data);
|
||||||
void writel(uint16 addr, uint32 data);
|
void writel(uint16 addr, uint32 data);
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
void init();
|
|
||||||
void enable();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
uint8 read (unsigned addr);
|
|
||||||
void write(unsigned addr, uint8 data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Cx4 cx4;
|
extern Cx4 cx4;
|
||||||
|
47
src/chip/cx4/serialization.cpp
Normal file
47
src/chip/cx4/serialization.cpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifdef CX4_CPP
|
||||||
|
|
||||||
|
void Cx4::serialize(serializer &s) {
|
||||||
|
s.array(ram);
|
||||||
|
s.array(reg);
|
||||||
|
|
||||||
|
s.integer(r0);
|
||||||
|
s.integer(r1);
|
||||||
|
s.integer(r2);
|
||||||
|
s.integer(r3);
|
||||||
|
s.integer(r4);
|
||||||
|
s.integer(r5);
|
||||||
|
s.integer(r6);
|
||||||
|
s.integer(r7);
|
||||||
|
s.integer(r8);
|
||||||
|
s.integer(r9);
|
||||||
|
s.integer(r10);
|
||||||
|
s.integer(r11);
|
||||||
|
s.integer(r12);
|
||||||
|
s.integer(r13);
|
||||||
|
s.integer(r14);
|
||||||
|
s.integer(r15);
|
||||||
|
|
||||||
|
s.integer(C4WFXVal);
|
||||||
|
s.integer(C4WFYVal);
|
||||||
|
s.integer(C4WFZVal);
|
||||||
|
s.integer(C4WFX2Val);
|
||||||
|
s.integer(C4WFY2Val);
|
||||||
|
s.integer(C4WFDist);
|
||||||
|
s.integer(C4WFScale);
|
||||||
|
|
||||||
|
s.integer(C41FXVal);
|
||||||
|
s.integer(C41FYVal);
|
||||||
|
s.integer(C41FAngleRes);
|
||||||
|
s.integer(C41FDist);
|
||||||
|
s.integer(C41FDistVal);
|
||||||
|
|
||||||
|
s.floatingpoint(tanval);
|
||||||
|
s.floatingpoint(c4x);
|
||||||
|
s.floatingpoint(c4y);
|
||||||
|
s.floatingpoint(c4z);
|
||||||
|
s.floatingpoint(c4x2);
|
||||||
|
s.floatingpoint(c4y2);
|
||||||
|
s.floatingpoint(c4z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -17,7 +17,7 @@ namespace nall {
|
|||||||
//
|
//
|
||||||
//caveats:
|
//caveats:
|
||||||
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
||||||
//- floating-point values are not supported.
|
//- floating-point usage is not portable across platforms
|
||||||
|
|
||||||
class serializer {
|
class serializer {
|
||||||
public:
|
public:
|
||||||
@@ -33,6 +33,20 @@ namespace nall {
|
|||||||
return icapacity;
|
return icapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T> void floatingpoint(T &value) {
|
||||||
|
enum { size = sizeof(T) };
|
||||||
|
//this is rather dangerous, and not cross-platform safe;
|
||||||
|
//but there is no standardized way to export FP-values
|
||||||
|
uint8_t *p = (uint8_t*)&value;
|
||||||
|
if(mode == Save) {
|
||||||
|
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
|
||||||
|
} else if(mode == Load) {
|
||||||
|
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
|
||||||
|
} else {
|
||||||
|
isize += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> void integer(T &value) {
|
template<typename T> void integer(T &value) {
|
||||||
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
|
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
|
||||||
if(mode == Save) {
|
if(mode == Save) {
|
||||||
|
@@ -15,9 +15,7 @@ void bPPU::enter() {
|
|||||||
if(scheduler.sync == Scheduler::SyncAll) scheduler.exit();
|
if(scheduler.sync == Scheduler::SyncAll) scheduler.exit();
|
||||||
|
|
||||||
//H = 0 (initialize)
|
//H = 0 (initialize)
|
||||||
scheduler.sync_ppucpu();
|
|
||||||
scanline();
|
scanline();
|
||||||
if(vcounter() == 0) frame();
|
|
||||||
add_clocks(10);
|
add_clocks(10);
|
||||||
|
|
||||||
//H = 10 (OAM address reset)
|
//H = 10 (OAM address reset)
|
||||||
@@ -47,12 +45,15 @@ void bPPU::enter() {
|
|||||||
void bPPU::add_clocks(unsigned clocks) {
|
void bPPU::add_clocks(unsigned clocks) {
|
||||||
tick(clocks);
|
tick(clocks);
|
||||||
scheduler.addclocks_ppu(clocks);
|
scheduler.addclocks_ppu(clocks);
|
||||||
|
scheduler.sync_ppucpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bPPU::scanline() {
|
void bPPU::scanline() {
|
||||||
line = vcounter();
|
line = vcounter();
|
||||||
|
|
||||||
if(line == 0) {
|
if(line == 0) {
|
||||||
|
frame();
|
||||||
|
|
||||||
//RTO flag reset
|
//RTO flag reset
|
||||||
regs.time_over = false;
|
regs.time_over = false;
|
||||||
regs.range_over = false;
|
regs.range_over = false;
|
||||||
|
@@ -52,6 +52,7 @@ void System::serialize_all(serializer &s) {
|
|||||||
dsp.serialize(s);
|
dsp.serialize(s);
|
||||||
|
|
||||||
if(cartridge.has_spc7110()) spc7110.serialize(s);
|
if(cartridge.has_spc7110()) spc7110.serialize(s);
|
||||||
|
if(cartridge.has_cx4()) cx4.serialize(s);
|
||||||
if(cartridge.has_obc1()) obc1.serialize(s);
|
if(cartridge.has_obc1()) obc1.serialize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -271,6 +271,10 @@ void MainWindow::syncUi() {
|
|||||||
settings_emulationSpeed_syncAudio->setChecked(config.audio.synchronize);
|
settings_emulationSpeed_syncAudio->setChecked(config.audio.synchronize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainWindow::isActive() {
|
||||||
|
return window->isActiveWindow() && !window->isMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::loadCartridge() {
|
void MainWindow::loadCartridge() {
|
||||||
string filename = utility.selectCartridge();
|
string filename = utility.selectCartridge();
|
||||||
if(filename.length() > 0) utility.loadCartridge(filename);
|
if(filename.length() > 0) utility.loadCartridge(filename);
|
||||||
|
@@ -86,6 +86,7 @@ public:
|
|||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
void syncUi();
|
void syncUi();
|
||||||
|
bool isActive();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void loadCartridge();
|
void loadCartridge();
|
||||||
|
@@ -76,7 +76,7 @@ void InputManager::bind() {
|
|||||||
|
|
||||||
void InputManager::poll() {
|
void InputManager::poll() {
|
||||||
if(config.input.focusPolicy == Configuration::Input::FocusPolicyIgnoreInput
|
if(config.input.focusPolicy == Configuration::Input::FocusPolicyIgnoreInput
|
||||||
&& mainWindow->window->isActiveWindow() == false) {
|
&& mainWindow->isActive() == false) {
|
||||||
inputPool.clear();
|
inputPool.clear();
|
||||||
} else {
|
} else {
|
||||||
inputPool.poll(stateTable[activeState]);
|
inputPool.poll(stateTable[activeState]);
|
||||||
|
@@ -9,7 +9,6 @@ bool Utility::saveStatesSupported() {
|
|||||||
if(SNES::cartridge.has_sa1()) return false;
|
if(SNES::cartridge.has_sa1()) return false;
|
||||||
if(SNES::cartridge.has_srtc()) return false;
|
if(SNES::cartridge.has_srtc()) return false;
|
||||||
if(SNES::cartridge.has_sdd1()) return false;
|
if(SNES::cartridge.has_sdd1()) return false;
|
||||||
if(SNES::cartridge.has_cx4()) return false;
|
|
||||||
if(SNES::cartridge.has_dsp1()) return false;
|
if(SNES::cartridge.has_dsp1()) return false;
|
||||||
if(SNES::cartridge.has_dsp2()) return false;
|
if(SNES::cartridge.has_dsp2()) return false;
|
||||||
if(SNES::cartridge.has_dsp3()) return false;
|
if(SNES::cartridge.has_dsp3()) return false;
|
||||||
|
@@ -42,7 +42,7 @@ void Utility::inputEvent(uint16_t code) {
|
|||||||
|
|
||||||
for(unsigned i = 0; i < keyboard<>::count; i++) {
|
for(unsigned i = 0; i < keyboard<>::count; i++) {
|
||||||
if(code == keyboard<>::index(i, keyboard<>::escape) && inputManager.state(code)) {
|
if(code == keyboard<>::index(i, keyboard<>::escape) && inputManager.state(code)) {
|
||||||
if(mainWindow->window->isActiveWindow() && input.acquired()) {
|
if(mainWindow->isActive() && input.acquired()) {
|
||||||
//release mouse capture
|
//release mouse capture
|
||||||
input.unacquire();
|
input.unacquire();
|
||||||
return; //do not trigger other UI actions that may be bound to escape key
|
return; //do not trigger other UI actions that may be bound to escape key
|
||||||
@@ -56,7 +56,7 @@ void Utility::inputEvent(uint16_t code) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mainWindow->window->isActiveWindow()) {
|
if(mainWindow->isActive()) {
|
||||||
bool resizeWindow = false;
|
bool resizeWindow = false;
|
||||||
|
|
||||||
if(isButtonDown(code, inputUiGeneral.loadCartridge)) {
|
if(isButtonDown(code, inputUiGeneral.loadCartridge)) {
|
||||||
|
Reference in New Issue
Block a user