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:
Tim Allen
2018-08-26 16:49:54 +10:00
parent f9adb4d2c6
commit bd814f0358
89 changed files with 1079 additions and 2241 deletions

View File

@@ -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

View File

@@ -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;
}
}}}