mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-04-02 10:42:14 -04:00
byuu says: This release features many substantial Game Boy emulation improvements (all courtesy of Jonas Quinn), a new audio DSP class, and BPS patching support. Changelog (since v081): - added new DSP audio engine; supports sample-averaging for the Game Boy's high frequency rate - GB: MMM01 images with boot loader at bottom of ROM can now be loaded - GB: EI is delayed one cycle; fixes Bubble Bobble [Jonas Quinn] - GB: fixed window -7 offset behavior; fixes Contra 3 first boss [Jonas Quinn] - GB: disable LCD interrupts when rendering is off; fixes Super Mario Land 2 [Jonas Quinn] - GB: fixed noise channel LFSR; fixes Zelda: LA lightning sound [Jonas Quinn] - GB: square channels use initial_length like the noise channel [Jonas Quinn] - UI: added BPS patching support; removed UPS patching support - UI: when loading BS-X/Sufami Turbo/Game Boy games; display game title instead of BIOS title - UI: modified timestamps on screenshots for Windows/NTFS (which disallows use of ':')
110 lines
2.7 KiB
C++
Executable file
110 lines
2.7 KiB
C++
Executable file
#ifndef NALL_IPS_HPP
|
|
#define NALL_IPS_HPP
|
|
|
|
#include <nall/file.hpp>
|
|
#include <nall/stdint.hpp>
|
|
#include <nall/string.hpp>
|
|
|
|
namespace nall {
|
|
|
|
struct ips {
|
|
inline bool apply();
|
|
inline void source(const uint8_t *data, unsigned size);
|
|
inline void modify(const uint8_t *data, unsigned size);
|
|
inline bool source(const string &filename);
|
|
inline bool modify(const string &filename);
|
|
inline ips();
|
|
inline ~ips();
|
|
|
|
uint8_t *data;
|
|
unsigned size;
|
|
const uint8_t *sourceData;
|
|
unsigned sourceSize;
|
|
const uint8_t *modifyData;
|
|
unsigned modifySize;
|
|
};
|
|
|
|
bool ips::apply() {
|
|
if(modifySize < 8) return false;
|
|
if(modifyData[0] != 'P') return false;
|
|
if(modifyData[1] != 'A') return false;
|
|
if(modifyData[2] != 'T') return false;
|
|
if(modifyData[3] != 'C') return false;
|
|
if(modifyData[4] != 'H') return false;
|
|
|
|
if(data) delete[] data;
|
|
data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding
|
|
size = sourceSize;
|
|
memcpy(data, sourceData, sourceSize);
|
|
unsigned offset = 5;
|
|
|
|
while(true) {
|
|
unsigned address, length;
|
|
|
|
if(offset > modifySize - 3) break;
|
|
address = modifyData[offset++] << 16;
|
|
address |= modifyData[offset++] << 8;
|
|
address |= modifyData[offset++] << 0;
|
|
|
|
if(address == 0x454f46) { //EOF
|
|
if(offset == modifySize) return true;
|
|
if(offset == modifySize - 3) {
|
|
size = modifyData[offset++] << 16;
|
|
size |= modifyData[offset++] << 8;
|
|
size |= modifyData[offset++] << 0;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if(offset > modifySize - 2) break;
|
|
length = modifyData[offset++] << 8;
|
|
length |= modifyData[offset++] << 0;
|
|
|
|
if(length) { //Copy
|
|
if(offset > modifySize - length) break;
|
|
while(length--) data[address++] = modifyData[offset++];
|
|
} else { //RLE
|
|
if(offset > modifySize - 3) break;
|
|
length = modifyData[offset++] << 8;
|
|
length |= modifyData[offset++] << 0;
|
|
if(length == 0) break; //illegal
|
|
while(length--) data[address++] = modifyData[offset];
|
|
offset++;
|
|
}
|
|
|
|
size = max(size, address);
|
|
}
|
|
|
|
delete[] data;
|
|
data = 0;
|
|
return false;
|
|
}
|
|
|
|
void ips::source(const uint8_t *data, unsigned size) {
|
|
sourceData = data, sourceSize = size;
|
|
}
|
|
|
|
void ips::modify(const uint8_t *data, unsigned size) {
|
|
modifyData = data, modifySize = size;
|
|
}
|
|
|
|
bool ips::source(const string &filename) {
|
|
return file::read(filename, sourceData, sourceSize);
|
|
}
|
|
|
|
bool ips::modify(const string &filename) {
|
|
return file::read(filename, modifyData, modifySize);
|
|
}
|
|
|
|
ips::ips() : data(0), sourceData(0), modifyData(0) {
|
|
}
|
|
|
|
ips::~ips() {
|
|
if(data) delete[] data;
|
|
if(sourceData) delete[] sourceData;
|
|
if(modifyData) delete[] modifyData;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|