Rework the crunch encoding to be, hopefully, smaller and use less bandwidth for

HD disks.
This commit is contained in:
David Given
2020-02-18 21:37:32 +01:00
parent 2df9920209
commit 8acf8e181d
3 changed files with 59 additions and 17 deletions

View File

@@ -9,14 +9,37 @@ void crunch(crunch_state_t* state)
uint8_t data = *state->inputptr++;
state->inputlen--;
if (data & 0x80)
if (data == 0x80)
{
/* Multiple 0x80s in a row get swallowed as they're
* meaningless. */
state->haspending = true;
}
else if (data & 0x80)
{
state->fifo = (state->fifo << 2) | 2 | (data & 1);
state->fifolen += 2;
if (state->haspending)
{
state->fifo = (state->fifo << 3) | 4;
state->fifolen += 3;
state->haspending = false;
}
state->fifo = (state->fifo << 3) | 4 | (data & 1);
state->fifolen += 3;
}
else
{
state->fifo = (state->fifo << 8) | data;
if (state->haspending && (data >= 0x40))
{
state->fifo = (state->fifo << 3) | 4;
state->fifolen += 3;
state->haspending = false;
}
state->fifo = (state->fifo << 8) | data;
if (state->haspending)
state->fifo |= 0xc0;
state->haspending = false;
state->fifolen += 8;
}
@@ -45,6 +68,14 @@ void uncrunch(crunch_state_t* state)
{
while (state->inputlen && state->outputlen)
{
if (state->haspending)
{
*state->outputptr++ = state->pendingbyte;
state->outputlen--;
state->haspending = false;
continue;
}
if (state->fifolen < 8)
{
if (state->inputlen)
@@ -58,13 +89,21 @@ void uncrunch(crunch_state_t* state)
}
uint8_t data = state->fifo >> (state->fifolen - 8);
if (data & 0x80)
{
data = ((data >> 6) & 0x01) | 0x80;
state->fifolen -= 2;
}
else
state->fifolen -= 8;
switch (data & 0xc0)
{
case 0x80:
data = ((data >> 5) & 0x01) | 0x80;
state->fifolen -= 3;
break;
case 0xc0:
state->haspending = true;
state->pendingbyte = data & 0x3f;
data = 0x80;
/* fall through */
default:
state->fifolen -= 8;
}
if (data)
{

View File

@@ -11,7 +11,8 @@ extern "C" {
* sending it over USB. The encoding used is:
*
* 0nnn.nnnn: value 0x00..0x7f
* 1n : value 0x80|n
* 11nn.nnnn: value 0x80 then 0x00..0x3f
* 10n : value 0x80|n
*
* The end of the buffer is terminated with zeroes, which are ignored
* (not written to the output).
@@ -25,8 +26,10 @@ typedef struct crunch_state_t
uint32_t inputlen;
uint8_t* outputptr;
uint32_t outputlen;
uint16_t fifo;
uint32_t fifo;
uint8_t fifolen;
bool haspending;
uint8_t pendingbyte;
}
crunch_state_t;

View File

@@ -7,7 +7,7 @@ static uint8_t outputbuffer[64];
static void test_crunch()
{
crunch_state_t cs = {};
Bytes inputdata = { 0x01, 0x7f, 0x80, 0x81, 0x01 };
Bytes inputdata = { 0x01, 0x7f, 0x80, 0x05, 0x80, 0x81, 0x01 };
cs.inputptr = inputdata.begin();
cs.inputlen = inputdata.size();
cs.outputptr = outputbuffer;
@@ -16,13 +16,13 @@ static void test_crunch()
donecrunch(&cs);
Bytes outputdata(outputbuffer, cs.outputptr - outputbuffer);
assert((outputdata == Bytes{ 0x01, 0x7f, 0xb0, 0x10 }));
assert((outputdata == Bytes{ 0x01, 0x7f, 0xc5, 0x94, 0x04 }));
}
static void test_uncrunch()
{
crunch_state_t cs = {};
Bytes inputdata = { 0x01, 0x7f, 0xb0, 0x10 };
Bytes inputdata = { 0x01, 0x7f, 0xc5, 0x94, 0x04 };
cs.inputptr = inputdata.begin();
cs.inputlen = inputdata.size();
cs.outputptr = outputbuffer;
@@ -31,7 +31,7 @@ static void test_uncrunch()
doneuncrunch(&cs);
Bytes outputdata(outputbuffer, cs.outputptr - outputbuffer);
assert((outputdata == Bytes { 0x01, 0x7f, 0x80, 0x81, 0x01 }));
assert((outputdata == Bytes { 0x01, 0x7f, 0x80, 0x05, 0x80, 0x81, 0x01 }));
}
int main(int argc, const char* argv[])