13 if ((charIn() !=
'P') || (charIn() !=
'C') ||
14 (charIn() !=
'K') || (charIn() !=
'\010')) {
26 return std::move(output);
30uint8_t XSAExtractor::charIn()
33 throw MSXException(
"Corrupt XSA image: unexpected end of file");
35 auto result = file.front();
36 file = file.subspan(1);
41void XSAExtractor::chkHeader()
44 unsigned outBufLen = 0;
46 outBufLen |= charIn() << (8 * i);
48 auto sectors = (outBufLen + 511) / 512;
49 output.resize(sectors);
52 repeat(4, [&]{ (void)charIn(); });
59void XSAExtractor::unLz77()
63 size_t remaining = output.size() *
sizeof(SectorBuffer);
64 std::span out{output.data()->raw.data(), remaining};
69 unsigned strLen = rdStrLen();
70 if (strLen == (MAX_STR_LEN + 1)) {
73 unsigned strPos = rdStrPos();
74 if ((strPos == 0) || (strPos > outIdx)) {
76 "Corrupt XSA image: invalid offset");
78 if (remaining < strLen) {
80 "Invalid XSA image: too small output buffer");
84 out[outIdx] = out[outIdx - strPos];
91 "Invalid XSA image: too small output buffer");
94 out[outIdx++] = charIn();
100unsigned XSAExtractor::rdStrLen()
102 if (!bitIn())
return 2;
103 if (!bitIn())
return 3;
104 if (!bitIn())
return 4;
107 while ((nrBits != 7) && bitIn()) {
113 len = (len << 1) | (bitIn() ? 1 : 0);
119int XSAExtractor::rdStrPos()
121 HufNode* hufPos = &hufTbl[2 * TBL_SIZE - 2];
123 while (hufPos->child1) {
125 hufPos = hufPos->child2;
127 hufPos = hufPos->child1;
130 auto cpdIndex = narrow<uint8_t>(hufPos - &hufTbl[0]);
131 ++tblSizes[cpdIndex];
133 auto getNBits = [&](
unsigned n) {
137 result = uint8_t((result << 1) | (bitIn() ? 1 : 0));
142 if (cpdExt[cpdIndex] >= 8) {
143 uint8_t strPosLsb = charIn();
144 uint8_t strPosMsb = getNBits(narrow_cast<uint8_t>(cpdExt[cpdIndex] - 8));
145 return strPosLsb + 256 * strPosMsb;
147 return int(getNBits(cpdExt[cpdIndex]));
150 if ((updHufCnt--) == 0) {
153 return strPos + cpDist[cpdIndex];
157bool XSAExtractor::bitIn()
163 bool temp = bitFlg & 1;
171void XSAExtractor::initHufInfo()
174 for (
auto i :
xrange(TBL_SIZE)) {
176 offs += 1 << cpdExt[i];
178 cpDist[TBL_SIZE] = offs;
180 for (
auto i :
xrange(TBL_SIZE)) {
182 hufTbl[i].child1 =
nullptr;
188void XSAExtractor::mkHufTbl()
191 HufNode* hufPos = &hufTbl[0];
192 for (
auto i :
xrange(TBL_SIZE)) {
193 (hufPos++)->weight = 1 + (tblSizes[i] >>= 1);
195 for (
int i = TBL_SIZE; i != 2 * TBL_SIZE - 1; ++i) {
196 (hufPos++)->weight = -1;
199 while (hufTbl[2 * TBL_SIZE - 2].weight == -1) {
200 for (hufPos = &hufTbl[0]; !(hufPos->weight); ++hufPos) {
203 HufNode* l1Pos = hufPos++;
204 while (!(hufPos->weight)) {
207 HufNode* l2Pos = [&] {
208 if (hufPos->weight < l1Pos->weight) {
217 while ((tempW = hufPos->weight) != -1) {
219 if (tempW < l1Pos->weight) {
222 }
else if (tempW < l2Pos->weight) {
228 hufPos->weight = l1Pos->weight + l2Pos->weight;
229 (hufPos->child1 = l1Pos)->weight = 0;
230 (hufPos->child2 = l2Pos)->weight = 0;
232 updHufCnt = MAX_HUF_CNT;
This file implemented 3 utility functions:
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto xrange(T e)