Initial re-upload of spice2x-24-08-24
This commit is contained in:
40
acio2emu/internal/crc.h
Normal file
40
acio2emu/internal/crc.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
namespace acio2emu::detail {
|
||||
inline uint8_t crc4_lgp_c(uint8_t crc, const uint8_t *data, size_t len) {
|
||||
static constexpr uint8_t tbl[] = {
|
||||
0x00, 0x0D, 0x03, 0x0E,
|
||||
0x06, 0x0B, 0x05, 0x08,
|
||||
0x0C, 0x01, 0x0F, 0x02,
|
||||
0x0A, 0x07, 0x09, 0x04,
|
||||
};
|
||||
|
||||
crc &= 15;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
auto b = data[i];
|
||||
crc = (((crc >> 4) ^ (tbl[(b ^ crc) & 0x0F])) >> 4) ^ tbl[(((crc >> 4) ^ (tbl[(b ^ crc) & 0x0F])) ^ (b >> 4)) & 0x0F];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
inline uint8_t crc7_lgp_48(uint8_t crc, const uint8_t *data, size_t len) {
|
||||
static constexpr uint8_t tbl[] = {
|
||||
0x00, 0x09, 0x12, 0x1B,
|
||||
0x24, 0x2D, 0x36, 0x3F,
|
||||
0x48, 0x41, 0x5A, 0x53,
|
||||
0x6C, 0x65, 0x7E, 0x77
|
||||
};
|
||||
|
||||
crc &= 127;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
auto b = data[i];
|
||||
crc = (((crc >> 4) ^ (tbl[(b ^ crc) & 0x0F])) >> 4) ^ tbl[(((crc >> 4) ^ (tbl[(b ^ crc) & 0x0F])) ^ (b >> 4)) & 0x0F];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
140
acio2emu/internal/lz.h
Normal file
140
acio2emu/internal/lz.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <cstdint>
|
||||
|
||||
namespace acio2emu::detail {
|
||||
class InflateTransformer {
|
||||
private:
|
||||
std::queue<uint8_t> output_;
|
||||
|
||||
uint8_t flags_ = 0, flag_shift_ = 0;
|
||||
|
||||
uint8_t window_[85] = {};
|
||||
int window_offset_ = 81;
|
||||
|
||||
enum class inflateStep {
|
||||
readFlags,
|
||||
processFlags,
|
||||
copyStored,
|
||||
copyFromWindow,
|
||||
} step_ = inflateStep::readFlags;
|
||||
|
||||
void window_put_(uint8_t b) {
|
||||
window_[window_offset_++] = b;
|
||||
window_offset_ %= sizeof(window_);
|
||||
}
|
||||
|
||||
uint8_t window_get_(int offset) {
|
||||
return window_[offset % sizeof(window_)];
|
||||
}
|
||||
|
||||
public:
|
||||
void put(uint8_t b) {
|
||||
auto consumed = false;
|
||||
|
||||
while (true) {
|
||||
switch (step_) {
|
||||
case inflateStep::readFlags:
|
||||
if (consumed) {
|
||||
// need more data
|
||||
return;
|
||||
}
|
||||
consumed = true;
|
||||
|
||||
flags_ = b;
|
||||
flag_shift_ = 0;
|
||||
|
||||
step_ = inflateStep::processFlags;
|
||||
break;
|
||||
|
||||
case inflateStep::processFlags:
|
||||
// have we processed every flag?
|
||||
if (flag_shift_ > 6) {
|
||||
step_ = inflateStep::readFlags;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags_ & (1 << flag_shift_)) {
|
||||
flag_shift_++;
|
||||
|
||||
if (flags_ & (1 << flag_shift_)) {
|
||||
// emit 0xAA when both bits are set
|
||||
output_.push(0xAA);
|
||||
}
|
||||
else {
|
||||
// copy from the window when only the lower bit is set
|
||||
step_ = inflateStep::copyFromWindow;
|
||||
}
|
||||
}
|
||||
else {
|
||||
step_ = inflateStep::copyStored;
|
||||
}
|
||||
flag_shift_++;
|
||||
|
||||
break;
|
||||
|
||||
case inflateStep::copyFromWindow: {
|
||||
if (consumed) {
|
||||
// need more data
|
||||
return;
|
||||
}
|
||||
consumed = true;
|
||||
|
||||
// determine the match size, default is 2-bytes
|
||||
auto offset = b;
|
||||
auto size = 2;
|
||||
|
||||
if (offset >= 0xAA) {
|
||||
// 4-byte match
|
||||
size = 4;
|
||||
offset -= 0xAB;
|
||||
}
|
||||
else if (offset >= 0x55) {
|
||||
// 3-byte match
|
||||
size = 3;
|
||||
offset -= 0x55;
|
||||
}
|
||||
|
||||
for (auto i = 0; i < size; i ++) {
|
||||
auto cur = window_get_(offset + i);
|
||||
|
||||
window_put_(cur);
|
||||
output_.push(cur);
|
||||
}
|
||||
|
||||
// continue processing flags
|
||||
step_ = inflateStep::processFlags;
|
||||
break;
|
||||
}
|
||||
|
||||
case inflateStep::copyStored:
|
||||
if (consumed) {
|
||||
// need more data
|
||||
return;
|
||||
}
|
||||
consumed = true;
|
||||
|
||||
window_put_(b);
|
||||
output_.push(b);
|
||||
|
||||
// continue processing flags
|
||||
step_ = inflateStep::processFlags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get() {
|
||||
if (output_.empty()) {
|
||||
// output queue is empty
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto b = output_.front();
|
||||
output_.pop();
|
||||
|
||||
return b;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user