mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-09 03:20:49 +02:00
Update to v106r59 release.
byuu says: Changelog: - fixed bug in Emulator::Game::Memory::operator bool() - nall: renamed view<string> back to `string_view` - nall:: implemented `array_view` - Game Boy: split cartridge-specific input mappings (rumble, accelerometer) to their own separate ports - Game Boy: fixed MBC7 accelerometer x-axis - icarus: Game Boy, Super Famicom, Mega Drive cores output internal header game titles to heuristics manifests - higan, icarus, hiro/gtk: improve viewport geometry configuration; fixed higan crashing bug with XShm driver - higan: connect Video::poll(),update() functionality - hiro, ruby: several compilation / bugfixes, should get the macOS port compiling again, hopefully [Sintendo] - ruby/video/xshm: fix crashing bug on window resize - a bit hacky; it's throwing BadAccess Xlib warnings, but they're not fatal, so I am catching and ignoring them - bsnes: removed Application::Windows::onModalChange hook that's no longer needed [Screwtape]
This commit is contained in:
@@ -2,22 +2,19 @@
|
||||
|
||||
namespace nall { namespace Beat { namespace Single {
|
||||
|
||||
inline auto apply(
|
||||
const uint8_t* sourceData, uint64_t sourceSize,
|
||||
const uint8_t* beatData, uint64_t beatSize,
|
||||
maybe<string&> manifest = {}, maybe<string&> result = {}
|
||||
) -> maybe<vector<uint8_t>> {
|
||||
inline auto apply(array_view<uint8_t> source, array_view<uint8_t> beat, maybe<string&> manifest = {}, maybe<string&> result = {}) -> maybe<vector<uint8_t>> {
|
||||
#define error(text) { if(result) *result = {"error: ", text}; return {}; }
|
||||
#define warning(text) { if(result) *result = {"warning: ", text}; return targetData; }
|
||||
#define success() { if(result) *result = ""; return targetData; }
|
||||
if(beatSize < 19) error("beat size mismatch");
|
||||
#define warning(text) { if(result) *result = {"warning: ", text}; return target; }
|
||||
#define success() { if(result) *result = ""; return target; }
|
||||
if(beat.size() < 19) error("beat size mismatch");
|
||||
|
||||
vector<uint8_t> targetData;
|
||||
vector<uint8_t> target;
|
||||
|
||||
uint beatOffset = 0;
|
||||
auto read = [&]() -> uint8_t {
|
||||
return beatData[beatOffset++];
|
||||
return beat[beatOffset++];
|
||||
};
|
||||
|
||||
auto decode = [&]() -> uint64_t {
|
||||
uint64_t data = 0, shift = 1;
|
||||
while(true) {
|
||||
@@ -30,19 +27,18 @@ inline auto apply(
|
||||
return data;
|
||||
};
|
||||
|
||||
auto targetOffset = 0;
|
||||
auto write = [&](uint8_t data) {
|
||||
targetData.append(data);
|
||||
target.append(data);
|
||||
};
|
||||
|
||||
if(read() != 'B') error("beat header invalid");
|
||||
if(read() != 'P') error("beat header invalid");
|
||||
if(read() != 'S') error("beat header invalid");
|
||||
if(read() != '1') error("beat version mismatch");
|
||||
if(decode() != sourceSize) error("source size mismatch");
|
||||
if(decode() != source.size()) error("source size mismatch");
|
||||
uint targetSize = decode();
|
||||
targetData.reserve(targetSize);
|
||||
auto metadataSize = decode();
|
||||
target.reserve(targetSize);
|
||||
uint metadataSize = decode();
|
||||
for(uint n : range(metadataSize)) {
|
||||
auto data = read();
|
||||
if(manifest) manifest->append((char)data);
|
||||
@@ -51,13 +47,13 @@ inline auto apply(
|
||||
enum : uint { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
||||
|
||||
uint sourceRelativeOffset = 0, targetRelativeOffset = 0;
|
||||
while(beatOffset < beatSize - 12) {
|
||||
while(beatOffset < beat.size() - 12) {
|
||||
uint length = decode();
|
||||
uint mode = length & 3;
|
||||
length = (length >> 2) + 1;
|
||||
|
||||
if(mode == SourceRead) {
|
||||
while(length--) write(sourceData[targetOffset]);
|
||||
while(length--) write(source[target.size()]);
|
||||
} else if(mode == TargetRead) {
|
||||
while(length--) write(read());
|
||||
} else {
|
||||
@@ -65,10 +61,10 @@ inline auto apply(
|
||||
offset = offset & 1 ? -(offset >> 1) : (offset >> 1);
|
||||
if(mode == SourceCopy) {
|
||||
sourceRelativeOffset += offset;
|
||||
while(length--) write(sourceData[sourceRelativeOffset++]);
|
||||
while(length--) write(source[sourceRelativeOffset++]);
|
||||
} else {
|
||||
targetRelativeOffset += offset;
|
||||
while(length--) write(targetData[targetRelativeOffset++]);
|
||||
while(length--) write(target[targetRelativeOffset++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,12 +72,12 @@ inline auto apply(
|
||||
uint32_t sourceHash = 0, targetHash = 0, beatHash = 0;
|
||||
for(uint shift : range(0, 32, 8)) sourceHash |= read() << shift;
|
||||
for(uint shift : range(0, 32, 8)) targetHash |= read() << shift;
|
||||
for(uint shift : range(0, 32, 8)) beatHash |= read() << shift;
|
||||
for(uint shift : range(0, 32, 8)) beatHash |= read() << shift;
|
||||
|
||||
if(targetOffset != targetSize) warning("target size mismatch");
|
||||
if(sourceHash != Hash::CRC32(sourceData, sourceSize).value()) warning("source hash mismatch");
|
||||
if(targetHash != Hash::CRC32(targetData).value()) warning("target hash mismatch");
|
||||
if(beatHash != Hash::CRC32(beatData, beatSize - 4).value()) warning("beat hash mismatch");
|
||||
if(target.size() != targetSize) warning("target size mismatch");
|
||||
if(sourceHash != Hash::CRC32(source).value()) warning("source hash mismatch");
|
||||
if(targetHash != Hash::CRC32(target).value()) warning("target hash mismatch");
|
||||
if(beatHash != Hash::CRC32({beat.data(), beat.size() - 4}).value()) warning("beat hash mismatch");
|
||||
|
||||
success();
|
||||
#undef error
|
||||
|
@@ -1,18 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <nall/encode/dictionary.hpp>
|
||||
#include <nall/suffix-array.hpp>
|
||||
|
||||
namespace nall { namespace Beat { namespace Single {
|
||||
|
||||
inline auto create(
|
||||
const uint8_t* sourceData, uint64_t sourceSize,
|
||||
const uint8_t* targetData, uint64_t targetSize,
|
||||
const string& manifest = {}
|
||||
) -> maybe<vector<uint8_t>> {
|
||||
vector<uint8_t> beatData;
|
||||
inline auto create(array_view<uint8_t> source, array_view<uint8_t> target, string_view manifest = {}) -> vector<uint8_t> {
|
||||
vector<uint8_t> beat;
|
||||
|
||||
auto write = [&](uint8_t data) {
|
||||
beatData.append(data);
|
||||
beat.append(data);
|
||||
};
|
||||
|
||||
auto encode = [&](uint64_t data) {
|
||||
@@ -26,18 +22,11 @@ inline auto create(
|
||||
};
|
||||
|
||||
write('B'), write('P'), write('S'), write('1');
|
||||
encode(sourceSize), encode(targetSize), encode(manifest.size());
|
||||
encode(source.size()), encode(target.size()), encode(manifest.size());
|
||||
for(auto& byte : manifest) write(byte);
|
||||
|
||||
auto read = [&](const uint8_t* data, uint size, uint offset) -> uint {
|
||||
if(offset + 3 >= size) return 0;
|
||||
return data[offset + 0] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3] << 0;
|
||||
};
|
||||
|
||||
Encode::Dictionary sourceDictionary(sourceData, sourceSize);
|
||||
Encode::Dictionary targetDictionary(targetData, targetSize);
|
||||
sourceDictionary.scan();
|
||||
targetDictionary.scan();
|
||||
auto sourceArray = SuffixArray(source).lrcp();
|
||||
auto targetArray = SuffixArray(target).lpf();
|
||||
|
||||
enum : uint { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
||||
uint outputOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0;
|
||||
@@ -47,46 +36,30 @@ inline auto create(
|
||||
if(!targetReadLength) return;
|
||||
encode(TargetRead | ((targetReadLength - 1) << 2));
|
||||
uint offset = outputOffset - targetReadLength;
|
||||
while(targetReadLength) write(targetData[offset++]), targetReadLength--;
|
||||
while(targetReadLength) write(target[offset++]), targetReadLength--;
|
||||
};
|
||||
|
||||
uint longestSize = max(sourceSize, targetSize);
|
||||
while(outputOffset < targetSize) {
|
||||
uint longestSize = max(source.size(), target.size());
|
||||
while(outputOffset < target.size()) {
|
||||
uint mode = TargetRead, longestLength = 3, longestOffset = 0;
|
||||
uint prefix = read(targetData, targetSize, outputOffset), lower, upper;
|
||||
int length = 0, offset = outputOffset;
|
||||
|
||||
uint length = 0, offset = outputOffset;
|
||||
while(offset < longestOffset) {
|
||||
if(sourceData[offset] != targetData[offset]) break;
|
||||
while(offset < longestSize) {
|
||||
if(source[offset] != target[offset]) break;
|
||||
length++, offset++;
|
||||
}
|
||||
if(length > longestLength) {
|
||||
mode = SourceRead, longestLength = length;
|
||||
}
|
||||
|
||||
sourceDictionary.find(prefix, lower, upper);
|
||||
for(uint index = lower; index <= upper; index++) {
|
||||
uint length = 0, sourceOffset = sourceDictionary[index], targetOffset = outputOffset;
|
||||
while(sourceOffset < sourceSize && targetOffset < targetSize) {
|
||||
if(sourceData[sourceOffset++] != targetData[targetOffset++]) break;
|
||||
length++;
|
||||
}
|
||||
if(length > longestLength) {
|
||||
mode = SourceCopy, longestLength = length, longestOffset = sourceDictionary[index];
|
||||
}
|
||||
sourceArray.find(length, offset, {target.data() + outputOffset, target.size() - outputOffset});
|
||||
if(length > longestLength) {
|
||||
mode = SourceCopy, longestLength = length, longestOffset = offset;
|
||||
}
|
||||
|
||||
targetDictionary.find(prefix, lower, upper);
|
||||
for(uint index = lower; index <= upper; index++) {
|
||||
uint length = 0, sourceOffset = targetDictionary[index], targetOffset = outputOffset;
|
||||
if(sourceOffset >= outputOffset) continue;
|
||||
while(targetOffset < targetSize) {
|
||||
if(targetData[sourceOffset++] != targetData[targetOffset++]) break;
|
||||
length++;
|
||||
}
|
||||
if(length > longestLength) {
|
||||
mode = TargetCopy, longestLength = length, longestOffset = targetDictionary[index];
|
||||
}
|
||||
targetArray.previous(length, offset, outputOffset);
|
||||
if(length > longestLength) {
|
||||
mode = TargetCopy, longestLength = length, longestOffset = offset;
|
||||
}
|
||||
|
||||
if(mode == TargetRead) {
|
||||
@@ -110,14 +83,14 @@ inline auto create(
|
||||
}
|
||||
flush();
|
||||
|
||||
auto sourceHash = Hash::CRC32(sourceData, sourceSize);
|
||||
auto sourceHash = Hash::CRC32(source);
|
||||
for(uint shift : range(0, 32, 8)) write(sourceHash.value() >> shift);
|
||||
auto targetHash = Hash::CRC32(targetData, targetSize);
|
||||
auto targetHash = Hash::CRC32(target);
|
||||
for(uint shift : range(0, 32, 8)) write(targetHash.value() >> shift);
|
||||
auto beatHash = Hash::CRC32(beatData);
|
||||
auto beatHash = Hash::CRC32(beat);
|
||||
for(uint shift : range(0, 32, 8)) write(beatHash.value() >> shift);
|
||||
|
||||
return beatData;
|
||||
return beat;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
Reference in New Issue
Block a user