mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Rework the crunch encoding to be, hopefully, smaller and use less bandwidth for
HD disks.
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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[])
|
||||
|
||||
Reference in New Issue
Block a user