2019-08-25 10:56:09 +00:00
|
|
|
#include <ResourceFile.h>
|
|
|
|
#include <BinaryIO.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <cassert>
|
|
|
|
#include <vector>
|
|
|
|
|
2019-09-29 19:51:04 +00:00
|
|
|
void decompressADC(std::vector<uint8_t>& outbuf, const std::vector<uint8_t>& inbuf)
|
2019-08-25 10:56:09 +00:00
|
|
|
{
|
|
|
|
outbuf.reserve(0x40000);
|
|
|
|
auto p = inbuf.begin();
|
|
|
|
|
|
|
|
while(p != inbuf.end())
|
|
|
|
{
|
|
|
|
auto cmd = *p++;
|
|
|
|
if(cmd & 0x80)
|
|
|
|
{
|
|
|
|
int n = (cmd & 0x7f) + 1;
|
|
|
|
outbuf.insert(outbuf.end(), p, p + n);
|
|
|
|
p += n;
|
2019-09-29 19:51:04 +00:00
|
|
|
assert(p <= inbuf.end());
|
2019-08-25 10:56:09 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int off;
|
|
|
|
int n;
|
|
|
|
if(cmd & 0x40)
|
|
|
|
{
|
|
|
|
n = (cmd & 0x3f) + 4;
|
|
|
|
off = *p++ << 8;
|
|
|
|
off |= *p++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
n = ((cmd & 0x3c) >> 2) + 3;
|
|
|
|
off = ((cmd & 3) << 8) | *p++;
|
|
|
|
}
|
|
|
|
++off;
|
|
|
|
|
2019-09-29 19:51:04 +00:00
|
|
|
assert(n > 0);
|
|
|
|
assert(off > 0);
|
|
|
|
assert(outbuf.size() - off >= 0);
|
|
|
|
outbuf.resize(outbuf.size() + n);
|
|
|
|
auto dst = outbuf.end() - n;
|
|
|
|
auto src = dst - off;
|
|
|
|
while(n--)
|
|
|
|
*dst++ = *src++;
|
2019-08-25 10:56:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
if(argc != 3)
|
|
|
|
{
|
|
|
|
std::cerr << "Usage: ConvertDiskImage input.img output.dsk\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-08-25 15:48:02 +00:00
|
|
|
ResourceFile file;
|
|
|
|
if(!file.read(argv[1]))
|
2019-08-25 10:56:09 +00:00
|
|
|
{
|
|
|
|
std::cerr << "Couldn't read input.\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::istringstream bcem(file.resources.resources[ResRef("bcem",128)].getData());
|
|
|
|
std::istringstream ndif(file.data);
|
|
|
|
std::ofstream output(argv[2], std::ios::binary | std::ios::trunc);
|
|
|
|
|
|
|
|
word(bcem);
|
|
|
|
word(bcem);
|
|
|
|
for(int i = 0; i<64; i++)
|
|
|
|
byte(bcem); // volume name
|
|
|
|
|
|
|
|
int blockCount [[maybe_unused]] = longword(bcem);
|
|
|
|
int blockSize = longword(bcem) & ~1; // ???
|
|
|
|
std::cout << blockCount << " blocks of " << blockSize << std::endl;
|
|
|
|
int hhBSZeroOffset [[maybe_unused]] = longword(bcem);
|
|
|
|
int checksum [[maybe_unused]] = longword(bcem);
|
|
|
|
int unknown1 [[maybe_unused]] = longword(bcem);
|
|
|
|
int unknown2 [[maybe_unused]] = longword(bcem);
|
|
|
|
int unknown3 [[maybe_unused]] = longword(bcem);
|
|
|
|
|
|
|
|
for(int i = 0; i < 7; i++)
|
|
|
|
longword(bcem); // reserved
|
|
|
|
|
|
|
|
int nChunks = longword(bcem);
|
|
|
|
|
|
|
|
std::vector<uint8_t> inbuf;
|
|
|
|
std::vector<uint8_t> outbuf;
|
|
|
|
|
|
|
|
for(int i = 0; i < nChunks; i++)
|
|
|
|
{
|
|
|
|
unsigned tmp = longword(bcem);
|
|
|
|
unsigned dstStartOffset = blockSize * (tmp >> 8);
|
|
|
|
unsigned compression = tmp & 0xFF;
|
|
|
|
unsigned offset = longword(bcem);
|
|
|
|
unsigned size = longword(bcem);
|
|
|
|
|
|
|
|
std::cout << std::hex << "starting at " << dstStartOffset << " from " << offset << " size " << size << " compression " << compression << std::endl;
|
|
|
|
|
|
|
|
if(output.tellp() < dstStartOffset)
|
|
|
|
{
|
|
|
|
std::cout << std::hex << "zero bytes from " << output.tellp() << std::endl;
|
|
|
|
|
|
|
|
output.seekp(dstStartOffset - 1);
|
|
|
|
output.put(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
inbuf.clear();
|
|
|
|
outbuf.clear();
|
|
|
|
|
|
|
|
inbuf.resize(size);
|
|
|
|
ndif.seekg(offset);
|
|
|
|
ndif.read((char*)inbuf.data(), size);
|
|
|
|
|
|
|
|
switch(compression)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
case 0xFF:
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
outbuf = std::move(inbuf);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x83:
|
2019-09-29 19:51:04 +00:00
|
|
|
decompressADC(outbuf, inbuf);
|
2019-08-25 10:56:09 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
output.write((char*)outbuf.data(), outbuf.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|