aboutsummaryrefslogtreecommitdiff
path: root/engines/adl/disk.cpp
diff options
context:
space:
mode:
authorAlyssa Milburn2016-12-09 09:34:59 +0100
committerAlyssa Milburn2016-12-09 09:34:59 +0100
commit2a01424f0e94e40f697bf748fad6e69a3ee4baa3 (patch)
treece9ed38f7180a5018086a2a248c8b8da8d9ab1f7 /engines/adl/disk.cpp
parent301ab51735cf8c8aac88a3df7e3f8d87b4122bc7 (diff)
downloadscummvm-rg350-2a01424f0e94e40f697bf748fad6e69a3ee4baa3.tar.gz
scummvm-rg350-2a01424f0e94e40f697bf748fad6e69a3ee4baa3.tar.bz2
scummvm-rg350-2a01424f0e94e40f697bf748fad6e69a3ee4baa3.zip
ADL: Support wrapped sectors in NIB files.
Diffstat (limited to 'engines/adl/disk.cpp')
-rw-r--r--engines/adl/disk.cpp66
1 files changed, 49 insertions, 17 deletions
diff --git a/engines/adl/disk.cpp b/engines/adl/disk.cpp
index d429556670..0de740eaec 100644
--- a/engines/adl/disk.cpp
+++ b/engines/adl/disk.cpp
@@ -39,11 +39,13 @@ static Common::SeekableReadStream *readImage(const Common::String &filename) {
return f;
}
+const uint trackLen = 256 * 26;
+
// 4-and-4 encoding (odd-even)
-static uint8 read44(Common::SeekableReadStream &f) {
+static uint8 read44(byte *buffer, uint &pos) {
// 1s in the other fields, so we can just AND
- uint8 ret = f.readByte();
- return ((ret << 1) | 1) & f.readByte();
+ uint8 ret = buffer[pos++ % trackLen];
+ return ((ret << 1) | 1) & buffer[pos++ % trackLen];
}
static Common::SeekableReadStream *readImage_NIB(const Common::String &filename) {
@@ -70,15 +72,27 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
uint8 volNo, track, sector;
bool newStyle;
- while (f.pos() < f.size()) {
+ byte buffer[trackLen];
+ uint firstGoodTrackPos = 0;
+ uint pos = trackLen; // force read
+
+ while (true) {
+ if (pos >= trackLen+firstGoodTrackPos) {
+ if (f.pos() == f.size())
+ break;
+ f.read(buffer, sizeof(buffer));
+ firstGoodTrackPos = 0;
+ pos = 0;
+ sawAddress = false;
+ }
+
// Read until we find two sync bytes.
- if (f.readByte() != 0xd5 || f.readByte() != 0xaa)
+ if (buffer[pos++ % trackLen] != 0xd5 || buffer[pos++ % trackLen] != 0xaa)
continue;
- byte prologue = f.readByte();
+ byte prologue = buffer[pos++ % trackLen];
if (sawAddress && (prologue == 0xb5 || prologue == 0x96)) {
- warning("NIB: data for %02x/%02x/%02x missing", volNo, track, sector);
sawAddress = false;
}
@@ -91,18 +105,24 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
// Accept a DOS 3.3(?) header at the start.
if (prologue == 0x96) {
newStyle = true;
+ } else if (prologue == 0xad || prologue == 0xfd) {
+ sawAddress = false;
+ continue;
} else {
error("unknown NIB field prologue %02x", prologue);
}
}
- volNo = read44(f);
- track = read44(f);
- sector = read44(f);
- uint8 checksum = read44(f);
+ volNo = read44(buffer, pos);
+ track = read44(buffer, pos);
+ sector = read44(buffer, pos);
+ uint8 checksum = read44(buffer, pos);
if ((volNo ^ track ^ sector) != checksum)
error("invalid NIB checksum");
+ if (!firstGoodTrackPos)
+ firstGoodTrackPos = pos;
+
// Epilogue is de/aa plus a gap, but we don't care.
continue;
}
@@ -121,7 +141,13 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
// 6-and-2 uses 342 on-disk bytes
byte inbuffer[342];
- f.read(inbuffer, 342);
+ uint z = trackLen - (pos % trackLen);
+ if (z < 342) {
+ memcpy(inbuffer, buffer + (pos % trackLen), z);
+ memcpy(inbuffer + z, buffer, 342 - z);
+ } else
+ memcpy(inbuffer, buffer + (pos % trackLen), 342);
+ pos += 342;
byte oldVal = 0;
for (uint n = 0; n < 342; ++n) {
@@ -136,7 +162,7 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
inbuffer[n] = oldVal;
}
- byte checksum = f.readByte();
+ byte checksum = buffer[pos++ % trackLen];
if (checksum < 0x96 || oldVal != c_6and2_lookup[checksum - 0x96])
warning("NIB: checksum mismatch @ (%x, %x)", track, sector);
@@ -156,7 +182,13 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
} else {
// 5-and-3 uses 410 on-disk bytes, decoding to just over 256 bytes
byte inbuffer[410];
- f.read(inbuffer, 410);
+ uint z = trackLen - (pos % trackLen);
+ if (z < 410) {
+ memcpy(inbuffer, buffer + (pos % trackLen), z);
+ memcpy(inbuffer + z, buffer, 410 - z);
+ } else
+ memcpy(inbuffer, buffer + (pos % trackLen), 410);
+ pos += 410;
bool truncated = false;
byte oldVal = 0;
@@ -166,7 +198,7 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
if (inbuffer[n] == 0xd5) {
// Early end of block.
truncated = true;
- f.seek(-(410 - n), SEEK_CUR);
+ pos -= (410 - n);
warning("NIB: early end of block @ 0x%x (%x, %x)", f.pos(), track, sector);
break;
}
@@ -175,7 +207,7 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
// Badly-encoded nibbles, stop trying to decode here.
truncated = true;
warning("NIB: bad nibble %02x @ 0x%x (%x, %x)", inbuffer[n], f.pos(), track, sector);
- f.seek(-(410 - n), SEEK_CUR);
+ pos -= (410 - n);
break;
}
// undo checksum
@@ -183,7 +215,7 @@ static Common::SeekableReadStream *readImage_NIB(const Common::String &filename)
inbuffer[n] = oldVal;
}
if (!truncated) {
- byte checksum = f.readByte();
+ byte checksum = buffer[pos++ % trackLen];
if (checksum < 0xaa || oldVal != c_5and3_lookup[checksum - 0xaa])
warning("NIB: checksum mismatch @ (%x, %x)", track, sector);
}