nibblizing

git-svn-id: https://profuse.googlecode.com/svn/branches/v2@268 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
ksherlock 2010-05-23 21:27:11 +00:00
parent 624af11ca1
commit 5f252e4dac
2 changed files with 422 additions and 0 deletions

View File

@ -4,6 +4,8 @@
#include <cstring>
#include <Device/Adaptor.h>
#include <ProFUSE/Exception.h>
using namespace Device;
@ -73,5 +75,392 @@ void DOAdaptor::writeBlock(unsigned block, const void *bp)
#pragma mark -
#pragma mark NibbleAdaptor
uint8_t NibbleAdaptor::decode44(uint8_t x, uint8_t y)
{
return ((x << 1) | 0x01) & y;
}
std::pair<uint8_t, uint8_t> NibbleAdaptor::encode44(uint8_t val)
{
uint8_t x = (val >> 1) | 0xaa;
uint8_t y = val | 0xaa;
return std::make_pair(x,y);
}
uint8_t NibbleAdaptor::encode62(uint8_t val)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::encode62"
static uint8_t table[64] = {
0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6,
0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3,
0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc,
0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3,
0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec,
0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
if (val > 0x3f)
throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 value.");
return table[val];
}
uint8_t NibbleAdaptor::decode62(uint8_t val)
{
#undef __METHOD__
#define __METHOD__ "decode62"
// auto-generated via perl.
static uint8_t table[] = {
-1, -1, -1, -1, -1, -1, 0, 1, -1, -1, 2, 3, -1, 4, 5, 6,
-1, -1, -1, -1, -1, -1, 7, 8, -1, -1, -1, 9, 10, 11, 12, 13,
-1, -1, 14, 15, 16, 17, 18, 19, -1, 20, 21, 22, 23, 24, 25, 26,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, 28, 29, 30,
-1, -1, -1, 31, -1, -1, 32, 33, -1, 34, 35, 36, 37, 38, 39, 40,
-1, -1, -1, -1, -1, 41, 42, 43, -1, 44, 45, 46, 47, 48, 49, 50,
-1, -1, 51, 52, 53, 54, 55, 56, -1, 57, 58, 59, 60, 61, 62, 63
};
if ((val < 0x90) || (table[val - 0x90] == 0xff))
throw ProFUSE::Exception(__METHOD__ ": Invalid 6-2 encoding.");
return table[val - 0x90];
}
static int FindByte(void *address, uint8_t c, unsigned length, unsigned offset = 0)
{
for (unsigned i = offset; i < length; ++i)
{
if ( *((uint8_t *)address) == c) return i;
}
return -1;
}
static void LoadBytes(void *src, unsigned length, unsigned offset, void *dest, unsigned count)
{
// load with wrap-around.
if (offset + count < length)
{
std::memcpy(dest, (uint8_t *)src + offset, count);
return;
}
unsigned x = length - offset;
std::memcpy(dest, (uint8_t *)src + offset, x);
std::memcpy((uint8_t *)dest + x, src, count - x);
}
class CircleBuffer {
public:
CircleBuffer(void *address, unsigned length)
{
_address = (uint8_t *)address;
_length = length;
}
uint8_t operator[](unsigned i) const
{
if (i >= _length) i %= _length;
return _address[i];
}
uint8_t& operator[](unsigned i)
{
if (i >= _length) i %= _length;
return _address[i];
}
private:
uint8_t *_address;
unsigned _length;
};
/*
* Address Field:
* prologue volume track sector checksum epilogue
* D5 AA 96 XX YY XX YY XX YY XX YY DE AA EB
*/
/*
* Data Field:
* prologue user data checksum epilogue
* D5 AA AD [6+2 encoded] XX DE AA EB
*/
/*
* 0x00
*------------------------
* A7 A6 A5 A4 A3 A2 A1 A0
* B7 B6 B5 B4 B3 B2 B1 B0
* C7 C6 C5 C4 C3 C2 C1 C0
* D7 D6 D5 D4 D3 D2 D1 D0
* E7 E6 E5 E4 E3 E2 E1 E0
* F7 F6 F5 F4 F3 F2 F1 F0
* ...
*------------------------
* 0x100
* ||
* \/
* 0x00
* -----------------------
* 0 0 A7 A6 A5 A4 A3 A2
* 0 0 B7 B6 B5 B4 B3 B2
* 0 0 C7 C6 C5 C4 C3 C2
* 0 0 D7 D6 D5 D4 D3 D2
* 0 0 E7 E6 E5 E4 E3 E2
* 0 0 F7 F6 F5 F4 F3 F2
* ...
* 0x100 (256):
* -----------------------
* ...
* 0 0 x x x x F0 F1
* 0 0 x x x x E0 E1
* 0 0 x x x x D0 D1
* 0 0 x x x x C0 C1
* 0 0 x x x x B0 B1
* 0 0 x x x x A0 A1
* -----------------------
* 0x156 (342)
*
*
*
*
*
*
*
*/
NibbleAdaptor::NibbleAdaptor(void *address, unsigned length)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::NibbleAdaptor"
_address = (uint8_t *)address;
_length = length;
// build a map of track/sectors.
unsigned state = 0;
_index.resize(35 * 16, -1);
int offset = 0;
unsigned track = 0;
unsigned sector = 0;
unsigned volume = 0;
unsigned checksum = 0;
CircleBuffer buffer(_address, _length);
for (;;)
{
offset = FindByte(address, 0xd5, length, offset);
if (offset < 0) break;
if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0x96)
{
state = 1;
volume = decode44(buffer[offset + 3], buffer[offset + 4]);
track = decode44(buffer[offset + 5], buffer[offset + 6]);
sector = decode44(buffer[offset + 7], buffer[offset + 8]);
checksum = decode44(buffer[offset + 9], buffer[offset + 10]);
if (volume ^ track ^ sector ^ checksum)
throw ProFUSE::Exception(__METHOD__ ": Invalid address checksum.");
if (track > 35 || sector > 16)
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
// epilogue is not always de aa eb
continue;
}
if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0xad && state == 1)
{
_index[track * 16 + sector] = (offset + 3) % _length;
state = 0;
continue;
}
// ????
}
// possible wraparound.
if (state == 1)
{
offset = FindByte(address, 0xd5, length, 0);
if (offset >= 0)
{
if (buffer[offset + 1] == 0xaa && buffer[offset + 2] == 0xad)
{
_index[track * 16 + sector] = (offset + 3) % _length;
}
}
}
// now check _index for offset = -1, which means the sector/track wasn't found.
for (std::vector<unsigned>::iterator iter = _index.begin(); iter != _index.end(); ++iter)
{
if (*iter == -1)
throw ProFUSE::Exception(__METHOD__ ": Sector missing.");
}
}
void NibbleAdaptor::readTrackSector(TrackSector ts, void *bp)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::readTrackSector"
if (ts.track > 35 || ts.sector > 16)
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
CircleBuffer buffer(_address, _length);
uint8_t bits[86 * 3];
uint8_t checksum = 0;
unsigned offset = _index[ts.track * 16 + ts.sector];
// first 86 bytes are in the auxbuffer, backwards.
for (unsigned i = 0; i < 86; ++i)
{
uint8_t x = buffer[offset + i];
x = decode62(x);
checksum ^= x;
uint8_t y = checksum;
for (unsigned j = 0; j < 3; ++i)
{
bits[i + j * 86] = ((y & 0x01) << 1) | ((y & 0x02) >> 1);
y >>= 2;
}
}
for (unsigned i = 0; i < 256; ++i)
{
uint8_t x = buffer[offset + 86 + i];
x = decode62(x);
checksum ^= x;
uint8_t y = (checksum << 2) | bits[i];
((uint8_t *)bp)[i] = y;
}
if (checksum != buffer[342])
throw ProFUSE::Exception(__METHOD__ ": Invalid field checksum.");
}
void NibbleAdaptor::writeTrackSector(TrackSector ts, const void *bp)
{
#undef __METHOD__
#define __METHOD__ "NibbleAdaptor::readTrackSector"
if (ts.track > 35 || ts.sector > 16)
throw ProFUSE::Exception(__METHOD__ ": Invalid track/sector.");
uint8_t auxBuffer[86];
uint8_t checksum = 0;
// create the aux buffer.
std::memset(auxBuffer, 0, sizeof(auxBuffer));
for (unsigned i = 0, j = 86, shift = 0; i < 256; ++i)
{
uint8_t x = ((const uint8_t *)bp)[i];
// grab the bottom 2 bytes and reverse them.
uint8_t y = ((x & 0x01) << 1) | ((x & 0x02) >> 1);
auxBuffer[--j] |= (y << shift);
if (j == 0)
{
j = 86;
shift += 2;
}
}
unsigned offset = _index[ts.track * 16 + ts.sector];
CircleBuffer buffer(_address, _length);
// create the checksum while writing to disk..
// aux buffer
for (unsigned i = 0; i < 86; ++i)
{
uint8_t x = auxBuffer[i];
buffer[offset + i] = encode62(x ^ checksum);
checksum = x;
}
for (unsigned i = 0; i < 256; ++i)
{
uint8_t x = ((const uint8_t *)bp)[i];
x >>= 2;
buffer[offset + 86 + i] = encode62(x ^ checksum);
checksum = x;
}
buffer[offset + 342] = checksum;
}

View File

@ -1,8 +1,13 @@
#ifndef __DEVICE_ADAPTOR_H__
#define __DEVICE_ADAPTOR_H__
#include <utility>
#include <vector>
#include <stdint.h>
#include <Device/TrackSector.h>
namespace Device {
class Adaptor
@ -38,6 +43,34 @@ namespace Device {
// TODO -- nibble adaptor.
class NibbleAdaptor : public Adaptor
{
public:
NibbleAdaptor(void *address, unsigned length);
virtual ~NibbleAdaptor();
virtual void readBlock(unsigned block, void *bp);
virtual void writeBlock(unsigned block, const void *bp);
virtual void readTrackSector(TrackSector ts, void *bp);
virtual void writeTrackSector(TrackSector ts, const void *bp);
static std::pair<uint8_t, uint8_t>encode44(uint8_t);
static uint8_t decode44(uint8_t, uint8_t);
static uint8_t encode62(uint8_t);
static uint8_t decode62(uint8_t);
private:
uint8_t *_address;
unsigned _length;
std::vector<unsigned> _index;
};
}