mirror of https://github.com/bsnes-emu/bsnes.git
Update to v081r04 release.
byuu says: - GB: square channels cache initial_length and invert the length value on writes [Jonas Quinn] - GB: updated LCD disable to just ignore interrupts and pixel writes, fixes Contra - BPS patch information and cartridge sections are now copied from the patch metadata, if it is present - fixed bpslinear out-of-bounds issue, which will be in snespurify v11 official [Danish] - simplified Makefile again since command-line trumps manual assignments
This commit is contained in:
parent
b28c54770c
commit
095181af62
|
@ -2,14 +2,8 @@ include nall/Makefile
|
|||
|
||||
snes := snes
|
||||
gameboy := gameboy
|
||||
|
||||
ifeq ($(profile),)
|
||||
profile := accuracy
|
||||
endif
|
||||
|
||||
ifeq ($(ui),)
|
||||
ui := ui
|
||||
endif
|
||||
profile := accuracy
|
||||
ui := ui
|
||||
|
||||
# options += debugger
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ void APU::Noise::clock_envelope() {
|
|||
void APU::Noise::write(unsigned r, uint8 data) {
|
||||
if(r == 1) {
|
||||
initial_length = 64 - (data & 0x3f);
|
||||
|
||||
length = initial_length;
|
||||
}
|
||||
|
||||
|
@ -45,7 +44,6 @@ void APU::Noise::write(unsigned r, uint8 data) {
|
|||
narrow_lfsr = data & 0x08;
|
||||
divisor = (data & 0x07) << 4;
|
||||
if(divisor == 0) divisor = 8;
|
||||
|
||||
period = divisor << frequency;
|
||||
}
|
||||
|
||||
|
@ -63,7 +61,6 @@ void APU::Noise::write(unsigned r, uint8 data) {
|
|||
}
|
||||
|
||||
void APU::Noise::power() {
|
||||
initial_length = 0;
|
||||
envelope_volume = 0;
|
||||
envelope_direction = 0;
|
||||
envelope_frequency = 0;
|
||||
|
@ -73,6 +70,7 @@ void APU::Noise::power() {
|
|||
counter = 0;
|
||||
|
||||
output = 0;
|
||||
initial_length = 0;
|
||||
length = 0;
|
||||
envelope_period = 0;
|
||||
volume = 0;
|
||||
|
@ -81,7 +79,6 @@ void APU::Noise::power() {
|
|||
}
|
||||
|
||||
void APU::Noise::serialize(serializer &s) {
|
||||
s.integer(initial_length);
|
||||
s.integer(envelope_volume);
|
||||
s.integer(envelope_direction);
|
||||
s.integer(envelope_frequency);
|
||||
|
@ -91,6 +88,7 @@ void APU::Noise::serialize(serializer &s) {
|
|||
s.integer(counter);
|
||||
|
||||
s.integer(output);
|
||||
s.integer(initial_length);
|
||||
s.integer(length);
|
||||
s.integer(envelope_period);
|
||||
s.integer(volume);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
struct Noise {
|
||||
unsigned initial_length;
|
||||
unsigned envelope_volume;
|
||||
bool envelope_direction;
|
||||
unsigned envelope_frequency;
|
||||
|
@ -9,6 +8,7 @@ struct Noise {
|
|||
bool counter;
|
||||
|
||||
int16 output;
|
||||
unsigned initial_length;
|
||||
unsigned length;
|
||||
unsigned envelope_period;
|
||||
unsigned volume;
|
||||
|
|
|
@ -66,7 +66,8 @@ void APU::Square1::write(unsigned r, uint8 data) {
|
|||
|
||||
if(r == 1) {
|
||||
duty = data >> 6;
|
||||
length = data & 0x3f;
|
||||
initial_length = 64 - (data & 0x3f);
|
||||
length = initial_length;
|
||||
}
|
||||
|
||||
if(r == 2) {
|
||||
|
@ -85,6 +86,7 @@ void APU::Square1::write(unsigned r, uint8 data) {
|
|||
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
|
||||
|
||||
if(initialize) {
|
||||
length = initial_length;
|
||||
envelope_period = envelope_frequency;
|
||||
volume = envelope_volume;
|
||||
frequency_shadow = frequency;
|
||||
|
@ -102,6 +104,7 @@ void APU::Square1::power() {
|
|||
sweep_direction = 0;
|
||||
sweep_shift = 0;
|
||||
duty = 0;
|
||||
initial_length = 0;
|
||||
length = 0;
|
||||
envelope_volume = 0;
|
||||
envelope_direction = 0;
|
||||
|
@ -125,6 +128,7 @@ void APU::Square1::serialize(serializer &s) {
|
|||
s.integer(sweep_direction);
|
||||
s.integer(sweep_shift);
|
||||
s.integer(duty);
|
||||
s.integer(initial_length);
|
||||
s.integer(length);
|
||||
s.integer(envelope_volume);
|
||||
s.integer(envelope_direction);
|
||||
|
|
|
@ -3,6 +3,7 @@ struct Square1 {
|
|||
unsigned sweep_direction;
|
||||
unsigned sweep_shift;
|
||||
unsigned duty;
|
||||
unsigned initial_length;
|
||||
unsigned length;
|
||||
unsigned envelope_volume;
|
||||
unsigned envelope_direction;
|
||||
|
|
|
@ -33,7 +33,8 @@ void APU::Square2::clock_envelope() {
|
|||
void APU::Square2::write(unsigned r, uint8 data) {
|
||||
if(r == 1) {
|
||||
duty = data >> 6;
|
||||
length = data & 0x3f;
|
||||
initial_length = 64 - (data & 0x3f);
|
||||
length = initial_length;
|
||||
}
|
||||
|
||||
if(r == 2) {
|
||||
|
@ -52,6 +53,7 @@ void APU::Square2::write(unsigned r, uint8 data) {
|
|||
frequency = ((data & 7) << 8) | (frequency & 0x00ff);
|
||||
|
||||
if(initialize) {
|
||||
length = initial_length;
|
||||
envelope_period = envelope_frequency;
|
||||
volume = envelope_volume;
|
||||
}
|
||||
|
@ -62,6 +64,7 @@ void APU::Square2::write(unsigned r, uint8 data) {
|
|||
|
||||
void APU::Square2::power() {
|
||||
duty = 0;
|
||||
initial_length = 0;
|
||||
length = 0;
|
||||
envelope_volume = 0;
|
||||
envelope_direction = 0;
|
||||
|
@ -79,6 +82,7 @@ void APU::Square2::power() {
|
|||
|
||||
void APU::Square2::serialize(serializer &s) {
|
||||
s.integer(duty);
|
||||
s.integer(initial_length);
|
||||
s.integer(length);
|
||||
s.integer(envelope_volume);
|
||||
s.integer(envelope_direction);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
struct Square2 {
|
||||
unsigned duty;
|
||||
unsigned initial_length;
|
||||
unsigned length;
|
||||
unsigned envelope_volume;
|
||||
unsigned envelope_direction;
|
||||
|
|
|
@ -28,7 +28,6 @@ void APU::Wave::write(unsigned r, uint8 data) {
|
|||
|
||||
if(r == 1) {
|
||||
initial_length = 256 - data;
|
||||
|
||||
length = initial_length;
|
||||
}
|
||||
|
||||
|
@ -68,7 +67,6 @@ void APU::Wave::write_pattern(unsigned p, uint8 data) {
|
|||
|
||||
void APU::Wave::power() {
|
||||
dac_enable = 0;
|
||||
initial_length = 0;
|
||||
volume = 0;
|
||||
frequency = 0;
|
||||
counter = 0;
|
||||
|
@ -78,6 +76,7 @@ void APU::Wave::power() {
|
|||
|
||||
output = 0;
|
||||
enable = 0;
|
||||
initial_length = 0;
|
||||
length = 0;
|
||||
period = 0;
|
||||
pattern_offset = 0;
|
||||
|
@ -86,7 +85,6 @@ void APU::Wave::power() {
|
|||
|
||||
void APU::Wave::serialize(serializer &s) {
|
||||
s.integer(dac_enable);
|
||||
s.integer(initial_length);
|
||||
s.integer(volume);
|
||||
s.integer(frequency);
|
||||
s.integer(counter);
|
||||
|
@ -94,6 +92,7 @@ void APU::Wave::serialize(serializer &s) {
|
|||
|
||||
s.integer(output);
|
||||
s.integer(enable);
|
||||
s.integer(initial_length);
|
||||
s.integer(length);
|
||||
s.integer(period);
|
||||
s.integer(pattern_offset);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
struct Wave {
|
||||
bool dac_enable;
|
||||
unsigned initial_length;
|
||||
unsigned volume;
|
||||
unsigned frequency;
|
||||
bool counter;
|
||||
|
@ -8,6 +7,7 @@ struct Wave {
|
|||
|
||||
int16 output;
|
||||
bool enable;
|
||||
unsigned initial_length;
|
||||
unsigned length;
|
||||
unsigned period;
|
||||
unsigned pattern_offset;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
namespace GameBoy {
|
||||
namespace Info {
|
||||
static const char Name[] = "bgameboy";
|
||||
static const char Version[] = "000.20";
|
||||
static const char Version[] = "000.21";
|
||||
static unsigned SerializerVersion = 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,16 +18,14 @@ void LCD::main() {
|
|||
}
|
||||
|
||||
add_clocks(4);
|
||||
if(status.display_enable == false) continue;
|
||||
|
||||
status.lx += 4;
|
||||
if(status.lx >= 456) scanline();
|
||||
|
||||
if(status.lx == 0) {
|
||||
if(status.display_enable && status.lx == 0) {
|
||||
if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat);
|
||||
}
|
||||
|
||||
if(status.lx == 252) {
|
||||
if(status.display_enable && status.lx == 252) {
|
||||
if(status.interrupt_hblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
|
||||
}
|
||||
}
|
||||
|
@ -44,13 +42,13 @@ void LCD::scanline() {
|
|||
status.lx -= 456;
|
||||
if(++status.ly == 154) frame();
|
||||
|
||||
if(status.interrupt_lyc == true) {
|
||||
if(status.display_enable && status.interrupt_lyc == true) {
|
||||
if(status.ly == status.lyc) cpu.interrupt_raise(CPU::Interrupt::Stat);
|
||||
}
|
||||
|
||||
if(status.ly < 144) render();
|
||||
|
||||
if(status.ly == 144) {
|
||||
if(status.display_enable && status.ly == 144) {
|
||||
cpu.interrupt_raise(CPU::Interrupt::Vblank);
|
||||
if(status.interrupt_vblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
|
||||
}
|
||||
|
|
|
@ -17,8 +17,7 @@ uint8 LCD::mmio_read(uint16 addr) {
|
|||
|
||||
if(addr == 0xff41) { //STAT
|
||||
unsigned mode;
|
||||
if(status.display_enable == false) mode = 1; //force blank
|
||||
else if(status.ly >= 144) mode = 1; //Vblank
|
||||
if(status.ly >= 144) mode = 1; //Vblank
|
||||
else if(status.lx < 80) mode = 2; //OAM
|
||||
else if(status.lx < 252) mode = 3; //LCD
|
||||
else mode = 0; //Hblank
|
||||
|
@ -84,6 +83,10 @@ void LCD::mmio_write(uint16 addr, uint8 data) {
|
|||
if(addr >= 0xfe00 && addr <= 0xfe9f) { oam[addr & 0xff] = data; return; }
|
||||
|
||||
if(addr == 0xff40) { //LCDC
|
||||
if(status.display_enable == false && (data & 0x80)) {
|
||||
status.lx = 0; //unverified behavior; fixes Super Mario Land 2 - Tree Zone
|
||||
}
|
||||
|
||||
status.display_enable = data & 0x80;
|
||||
status.window_tilemap_select = data & 0x40;
|
||||
status.window_display_enable = data & 0x20;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "081.03";
|
||||
static const char Version[] = "081.04";
|
||||
static const unsigned SerializerVersion = 21;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,8 @@ bool Cartridge::loadSuperGameBoy(const char *basename, const char *slotname) {
|
|||
}
|
||||
|
||||
void Cartridge::unload() {
|
||||
patchApplied = false;
|
||||
patch.applied = false;
|
||||
patch.information = "";
|
||||
if(SNES::cartridge.loaded() == false) return;
|
||||
|
||||
foreach(memory, SNES::cartridge.nvram) saveMemory(memory);
|
||||
|
@ -112,20 +113,36 @@ bool Cartridge::loadCartridge(SNES::MappedRAM &memory, string &XML, const char *
|
|||
|
||||
string patchName = { nall::basename(filename), ".bps" };
|
||||
if(file::exists(patchName)) {
|
||||
bpspatch patch;
|
||||
patch.modify(patchName);
|
||||
bpspatch bps;
|
||||
bps.modify(patchName);
|
||||
|
||||
unsigned targetSize = patch.size();
|
||||
unsigned targetSize = bps.size();
|
||||
uint8_t *targetData = new uint8_t[targetSize];
|
||||
|
||||
patch.source(data, size);
|
||||
patch.target(targetData, targetSize);
|
||||
bps.source(data, size);
|
||||
bps.target(targetData, targetSize);
|
||||
|
||||
if(patch.apply() == bpspatch::result::success) {
|
||||
if(bps.apply() == bpspatch::result::success) {
|
||||
delete[] data;
|
||||
data = targetData;
|
||||
size = targetSize;
|
||||
patchApplied = true;
|
||||
patch.applied = true;
|
||||
|
||||
xml_element document = xml_parse(bps.metadata());
|
||||
foreach(root, document.element) {
|
||||
if(root.name == "metadata") {
|
||||
if(auto x = root.content.position("<information>")) {
|
||||
if(auto y = root.content.position("</information>")) {
|
||||
patch.information = substr(root.content, x(), y() - x() + 14);
|
||||
}
|
||||
}
|
||||
if(auto x = root.content.position("<cartridge ")) {
|
||||
if(auto y = root.content.position("</cartridge>")) {
|
||||
XML = substr(root.content, x(), y() - x() + 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
delete[] targetData;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,11 @@ struct Cartridge {
|
|||
|
||||
string baseName, bsxName, sufamiTurboAName, sufamiTurboBName, gameBoyName;
|
||||
string baseXML, bsxXML, sufamiTurboAXML, sufamiTurboBXML, gameBoyXML;
|
||||
bool patchApplied;
|
||||
|
||||
struct Patch {
|
||||
bool applied;
|
||||
string information;
|
||||
} patch;
|
||||
|
||||
private:
|
||||
bool loadCartridge(SNES::MappedRAM &memory, string &XML, const char *filename);
|
||||
|
|
|
@ -165,7 +165,7 @@ void Utility::cartridgeLoaded() {
|
|||
utility.setTitle(notdir(name));
|
||||
utility.showMessage({
|
||||
"Loaded ", notdir(name),
|
||||
cartridge.patchApplied ? ", and applied BPS patch" : ""
|
||||
cartridge.patch.applied ? ", and applied BPS patch" : ""
|
||||
});
|
||||
|
||||
//NSS
|
||||
|
|
Loading…
Reference in New Issue