add a utility to convert NDIF disk images (WIP)

This commit is contained in:
Wolfgang Thaller 2019-08-25 12:56:09 +02:00
parent 057768eedf
commit 14570ffa1f
3 changed files with 133 additions and 0 deletions

View File

@ -77,4 +77,5 @@ add_subdirectory(ConvertObj)
add_subdirectory(PEFTools)
add_subdirectory(Elf2Mac)
add_subdirectory(LaunchAPPL)
add_subdirectory(ConvertDiskImage)
endif()

View File

@ -0,0 +1,2 @@
add_executable(ConvertDiskImage ConvertDiskImage.cc)
target_link_libraries(ConvertDiskImage ResourceFiles)

View File

@ -0,0 +1,130 @@
#include <ResourceFile.h>
#include <BinaryIO.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cassert>
#include <vector>
void decompreassADC(std::vector<uint8_t>& outbuf, const std::vector<uint8_t>& inbuf)
{
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;
}
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;
outbuf.reserve(outbuf.size() + n);
outbuf.insert(outbuf.end(), outbuf.end() - off, outbuf.end() - off + n);
}
}
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
std::cerr << "Usage: ConvertDiskImage input.img output.dsk\n";
return 1;
}
ResourceFile file(argv[1]);
if(!file.read())
{
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:
decompreassADC(outbuf, inbuf);
break;
}
output.write((char*)outbuf.data(), outbuf.size());
}
return 0;
}