14 std::pair<MemBuffer<SectorBuffer>,
unsigned>
extractData();
17 static constexpr
int MAXSTRLEN = 254;
18 static constexpr
int TBLSIZE = 16;
19 static constexpr
int MAXHUFCNT = 127;
21 [[nodiscard]]
inline byte charIn();
24 [[nodiscard]]
unsigned rdStrLen();
25 [[nodiscard]]
int rdStrPos();
26 [[nodiscard]]
bool bitIn();
38 std::span<const byte>::iterator inBufPos;
39 std::span<const byte>::iterator inBufEnd;
43 int cpDist[TBLSIZE + 1];
44 int cpdBmask[TBLSIZE];
45 int tblSizes[TBLSIZE];
46 HufNode hufTbl[2 * TBLSIZE - 1];
51 static constexpr
int cpdExt[TBLSIZE] = {
52 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
68 void XSADiskImage::readSectorsImpl(
71 memcpy(buffers, &data[startSector], num *
sizeof(
SectorBuffer));
74 void XSADiskImage::writeSectorImpl(
size_t ,
const SectorBuffer& )
76 throw WriteProtectedException(
"Write protected");
79 bool XSADiskImage::isWriteProtectedImpl()
const
89 auto mmap = file.
mmap();
90 inBufPos = mmap.begin();
91 inBufEnd = mmap.end();
93 if ((charIn() !=
'P') || (charIn() !=
'C') ||
94 (charIn() !=
'K') || (charIn() !=
'\010')) {
106 return {std::move(outBuf), sectors};
110 byte XSAExtractor::charIn()
112 if (inBufPos >= inBufEnd) {
113 throw MSXException(
"Corrupt XSA image: unexpected end of file");
119 void XSAExtractor::chkHeader()
122 unsigned outBufLen = 0;
123 for (
auto i :
xrange(4)) {
124 outBufLen |= charIn() << (8 * i);
126 sectors = (outBufLen + 511) / 512;
127 outBuf.resize(sectors);
137 void XSAExtractor::unLz77()
141 size_t remaining = sectors *
sizeof(SectorBuffer);
142 byte* out = outBuf.data()->raw;
147 unsigned strLen = rdStrLen();
148 if (strLen == (MAXSTRLEN + 1)) {
151 unsigned strPos = rdStrPos();
152 if ((strPos == 0) || (strPos > outIdx)) {
154 "Corrupt XSA image: invalid offset");
156 if (remaining < strLen) {
158 "Invalid XSA image: too small output buffer");
162 out[outIdx] = out[outIdx - strPos];
167 if (remaining == 0) {
169 "Invalid XSA image: too small output buffer");
172 out[outIdx++] = charIn();
178 unsigned XSAExtractor::rdStrLen()
180 if (!bitIn())
return 2;
181 if (!bitIn())
return 3;
182 if (!bitIn())
return 4;
185 while ((nrBits != 7) && bitIn()) {
191 len = (len << 1) | (bitIn() ? 1 : 0);
197 int XSAExtractor::rdStrPos()
199 HufNode* hufPos = &hufTbl[2 * TBLSIZE - 2];
201 while (hufPos->child1) {
203 hufPos = hufPos->child2;
205 hufPos = hufPos->child1;
208 byte cpdIndex =
byte(hufPos - hufTbl);
209 ++tblSizes[cpdIndex];
212 if (cpdBmask[cpdIndex] >= 256) {
213 byte strPosLsb = charIn();
215 for (
byte nrBits = cpdExt[cpdIndex] - 8; nrBits--;
216 strPosMsb |= (bitIn() ? 1 : 0)) {
219 return strPosLsb + 256 * strPosMsb;
222 for (
byte nrBits = cpdExt[cpdIndex]; nrBits--;
223 pos |= (bitIn() ? 1 : 0)) {
229 if ((updHufCnt--) == 0) {
232 return strPos + cpDist[cpdIndex];
236 bool XSAExtractor::bitIn()
242 bool temp = bitFlg & 1;
250 void XSAExtractor::initHufInfo()
253 for (
auto i :
xrange(TBLSIZE)) {
255 cpdBmask[i] = 1 << cpdExt[i];
258 cpDist[TBLSIZE] = offs;
260 for (
auto i :
xrange(TBLSIZE)) {
262 hufTbl[i].child1 =
nullptr;
268 void XSAExtractor::mkHufTbl()
271 HufNode* hufPos = hufTbl;
272 for (
auto i :
xrange(TBLSIZE)) {
273 (hufPos++)->weight = 1 + (tblSizes[i] >>= 1);
275 for (
int i = TBLSIZE; i != 2 * TBLSIZE - 1; ++i) {
276 (hufPos++)->weight = -1;
279 while (hufTbl[2 * TBLSIZE - 2].weight == -1) {
280 for (hufPos = hufTbl; !(hufPos->weight); ++hufPos) {
283 HufNode* l1Pos = hufPos++;
284 while (!(hufPos->weight)) {
287 HufNode* l2Pos = [&] {
288 if (hufPos->weight < l1Pos->weight) {
297 while ((tempW = hufPos->weight) != -1) {
299 if (tempW < l1Pos->weight) {
302 }
else if (tempW < l2Pos->weight) {
308 hufPos->weight = l1Pos->weight + l2Pos->weight;
309 (hufPos->child1 = l1Pos)->weight = 0;
310 (hufPos->child2 = l2Pos)->weight = 0;
312 updHufCnt = MAXHUFCNT;
std::span< const uint8_t > mmap()
Map file in memory.
This class represents a filename.
This class manages the lifetime of a block of memory.
Abstract class for disk images that only represent the logical sector information (so not the raw tra...
void setNbSectors(size_t num)
XSADiskImage(Filename &filename, File &file)
This file implemented 3 utility functions:
uint8_t byte
8 bit unsigned integer
constexpr const char *const filename
constexpr auto xrange(T e)