12 std::vector<IPSPatch::Chunk> IPSPatch::parseChunks()
const
14 std::vector<Chunk> result;
16 File ipsFile(filename);
20 if (memcmp(buf,
"PATCH", 5) != 0) {
21 throw MSXException(
"Invalid IPS file: ", filename.
getOriginal());
24 while (memcmp(buf,
"EOF", 3) != 0) {
25 size_t offset = 0x10000 * buf[0] + 0x100 * buf[1] + buf[2];
27 size_t length = 0x100 * buf[0] + buf[1];
32 length = 0x100 * buf[0] + buf[1];
37 ipsFile.read(&v.front(),
length);
41 if (b !=
begin(result)) {
43 if (b->stopAddress() < offset) ++b;
49 auto start =
std::min(b->startAddress, offset);
54 for (
auto it :
xrange(b, e)) {
55 memcpy(&tmp[it->startAddress - start],
56 it->data(), it->size());
58 memcpy(&tmp[offset - start], v.data(), v.size());
59 *b = Chunk{start, std::move(tmp)};
60 result.erase(b + 1, e);
63 result.emplace(b, Chunk{offset, std::move(v)});
71 size_t IPSPatch::calcSize()
const
75 :
std::max(parent->getSize(), chunks.back().stopAddress());
79 std::unique_ptr<const PatchInterface> parent_)
81 , parent(std::move(parent_))
82 , chunks(parseChunks())
89 parent->copyBlock(src, dst, num);
92 if (b !=
begin(chunks)) --b;
94 for (
auto it :
xrange(b, e)) {
95 auto chunkStart = it->startAddress;
96 int chunkSize = int(it->size());
98 int chunkOffset = int(src - chunkStart);
99 if (chunkOffset < 0) {
101 assert(-chunkOffset <
int(num));
103 }
else if (chunkOffset >= chunkSize) {
108 chunkSize -= chunkOffset;
109 chunkStart += chunkOffset;
112 assert(src <= chunkStart);
113 int overflow = int(chunkStart - src + chunkSize - num);
115 assert(chunkSize > overflow);
116 chunkSize -= overflow;
119 assert(chunkOffset <
int(it->size()));
120 assert((chunkOffset + chunkSize) <=
int(it->size()));
121 assert(src <= chunkStart);
122 assert((chunkStart + chunkSize) <= (src + num));
123 memcpy(dst + chunkStart - src, it->data() + chunkOffset,
130 auto result = parent->getFilenames();
131 result.push_back(filename);
This class represents a filename.
const std::string & getOriginal() const
IPSPatch(Filename filename, std::unique_ptr< const PatchInterface > parent)
std::vector< Filename > getFilenames() const override
void copyBlock(size_t src, byte *dst, size_t num) const override
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
T length(const vecN< N, T > &x)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr T length2(const vecN< N, T > &x)
This file implemented 3 utility functions:
constexpr const char *const filename
auto upper_bound(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})
auto lower_bound(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})
size_t size(std::string_view utf8)
constexpr auto xrange(T e)
constexpr auto begin(const zstring_view &x)