summaryrefslogtreecommitdiff
path: root/ZAPD/yaz0
diff options
context:
space:
mode:
authorbriaguya <70942617+briaguya-ai@users.noreply.github.com>2023-10-17 22:04:12 -0400
committerbriaguya <70942617+briaguya-ai@users.noreply.github.com>2023-10-17 22:04:12 -0400
commite9f4fc638ed904cc0dcdac24ea7708c9a220a702 (patch)
tree114c3d432697e04831741e623ae2340f6239bbe9 /ZAPD/yaz0
parentdcf56d93ecbd4db3bfd8a4832d7f991467964b98 (diff)
update to latest version used by SoH
Diffstat (limited to 'ZAPD/yaz0')
-rw-r--r--ZAPD/yaz0/readwrite.h29
-rw-r--r--ZAPD/yaz0/yaz0.cpp227
-rw-r--r--ZAPD/yaz0/yaz0.h6
3 files changed, 262 insertions, 0 deletions
diff --git a/ZAPD/yaz0/readwrite.h b/ZAPD/yaz0/readwrite.h
new file mode 100644
index 0000000..af34715
--- /dev/null
+++ b/ZAPD/yaz0/readwrite.h
@@ -0,0 +1,29 @@
+#ifndef __READWRITE_H__
+#define __READWRITE_H__
+
+#include <stdint.h>
+
+/* variables */
+union {
+ uint32_t u;
+ float f;
+} __u32_f32_union__;
+
+#define U32(x) \
+ ((uint32_t)((((uint8_t*)(x))[0] << 24) | (((uint8_t*)(x))[1] << 16) | \
+ (((uint8_t*)(x))[2] << 8) | ((uint8_t*)(x))[3]))
+#define U16(x) ((uint16_t)(((*((uint8_t*)(x))) << 8) | ((uint8_t*)(x))[1]))
+#define U8(x) ((uint8_t)((uint8_t*)(x))[0])
+#define S32(x) ((int32_t)(U32(x)))
+#define S16(x) ((int16_t)(U16(x)))
+#define F32(x) (((__u32_f32_union__.u = U32(x)) & 0) + __u32_f32_union__.f)
+
+#define W32(x, v) \
+ { \
+ *((uint8_t*)x + 3) = ((v)&0xFF); \
+ *((uint8_t*)x + 2) = (((v) >> 8) & 0xFF); \
+ *((uint8_t*)x + 1) = (((v) >> 16) & 0xFF); \
+ *((uint8_t*)x + 0) = (((v) >> 24) & 0xFF); \
+ }
+
+#endif \ No newline at end of file
diff --git a/ZAPD/yaz0/yaz0.cpp b/ZAPD/yaz0/yaz0.cpp
new file mode 100644
index 0000000..885f41d
--- /dev/null
+++ b/ZAPD/yaz0/yaz0.cpp
@@ -0,0 +1,227 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <list>
+#include "readwrite.h"
+
+#include "yaz0.h"
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+
+/* internal declarations */
+int yaz0_encode_internal(const u8* src, int srcSize, u8* Data);
+
+int yaz0_get_size(u8* src) { return U32(src + 0x4); }
+
+u32 toDWORD(u32 d) {
+ u8 w1 = d & 0xFF;
+ u8 w2 = (d >> 8) & 0xFF;
+ u8 w3 = (d >> 16) & 0xFF;
+ u8 w4 = d >> 24;
+ return (w1 << 24) | (w2 << 16) | (w3 << 8) | w4;
+}
+
+// simple and straight encoding scheme for Yaz0
+u32 longest_match_brute(const u8* src, int size, int pos, u32* pMatchPos) {
+ int startPos = pos - 0x1000;
+ int max_match_size = size - pos;
+ u32 best_match_size = 0;
+ u32 best_match_pos = 0;
+
+ if (max_match_size < 3) return 0;
+
+ if (startPos < 0) startPos = 0;
+
+ if (max_match_size > 0x111) max_match_size = 0x111;
+
+ for (int i = startPos; i < pos; i++) {
+ int current_size;
+ for (current_size = 0; current_size < max_match_size; current_size++) {
+ if (src[i + current_size] != src[pos + current_size]) {
+ break;
+ }
+ }
+ if (current_size > best_match_size) {
+ best_match_size = current_size;
+ best_match_pos = i;
+ if (best_match_size == 0x111) break;
+ }
+ }
+ *pMatchPos = best_match_pos;
+ return best_match_size;
+}
+
+u32 longest_match_rabinkarp(const u8* src, int size, int pos, u32* match_pos) {
+ int startPos = pos - 0x1000;
+ int max_match_size = size - pos;
+ u32 best_match_size = 0;
+ u32 best_match_pos = 0;
+
+ if (max_match_size < 3) return 0;
+
+ if (startPos < 0) startPos = 0;
+
+ if (max_match_size > 0x111) max_match_size = 0x111;
+
+ int find_hash = src[pos] << 16 | src[pos + 1] << 8 | src[pos + 2];
+ int current_hash = src[startPos] << 16 | src[startPos + 1] << 8 | src[startPos + 2];
+
+ for (int i = startPos; i < pos; i++) {
+ if(current_hash == find_hash) {
+ int current_size;
+ for (current_size = 3; current_size < max_match_size; current_size++) {
+ if (src[i + current_size] != src[pos + current_size]) {
+ break;
+ }
+ }
+ if (current_size > best_match_size) {
+ best_match_size = current_size;
+ best_match_pos = i;
+ if (best_match_size == 0x111) break;
+ }
+ }
+ current_hash = (current_hash << 8 | src[i + 3]) & 0xFFFFFF;
+ }
+ *match_pos = best_match_pos;
+
+ return best_match_size;
+}
+
+int yaz0_encode_internal(const u8* src, int srcSize, u8* Data) {
+ int srcPos = 0;
+
+ int bitmask = 0x80;
+ u8 currCodeByte = 0;
+ int currCodeBytePos = 0;
+ int pos = currCodeBytePos + 1;
+
+ while (srcPos < srcSize) {
+ u32 numBytes;
+ u32 matchPos;
+
+ numBytes = longest_match_rabinkarp(src, srcSize, srcPos, &matchPos);
+ //fprintf(stderr, "pos %x len %x pos %x\n", srcPos, (int)numBytes, (int)matchPos);
+ if (numBytes < 3) {
+ //fprintf(stderr, "single byte %02x\n", src[srcPos]);
+ Data[pos++] = src[srcPos++];
+ currCodeByte |= bitmask;
+ } else {
+ // RLE part
+ u32 dist = srcPos - matchPos - 1;
+
+ if (numBytes >= 0x12) // 3 byte encoding
+ {
+ Data[pos++] = dist >> 8; // 0R
+ Data[pos++] = dist & 0xFF; // FF
+ if (numBytes > 0xFF + 0x12) numBytes = 0xFF + 0x12;
+ Data[pos++] = numBytes - 0x12;
+ } else // 2 byte encoding
+ {
+ Data[pos++] = ((numBytes - 2) << 4) | (dist >> 8);
+ Data[pos++] = dist & 0xFF;
+ }
+ srcPos += numBytes;
+ }
+ bitmask >>= 1;
+ // write eight codes
+ if (!bitmask) {
+ Data[currCodeBytePos] = currCodeByte;
+ currCodeBytePos = pos++;
+
+ currCodeByte = 0;
+ bitmask = 0x80;
+ }
+ }
+ if (bitmask) {
+ Data[currCodeBytePos] = currCodeByte;
+ }
+
+ return pos;
+}
+
+std::vector<uint8_t> yaz0_encode_fast(const u8* src, int src_size) {
+ std::vector<uint8_t> buffer;
+ std::vector<std::list<uint32_t>> lut;
+ lut.resize(0x1000000);
+
+ for (int i = 0; i < src_size - 3; ++i) {
+ lut[src[i + 0] << 16 | src[i + 1] << 8 | src[i + 2]].push_back(i);
+ }
+
+ return buffer;
+}
+
+std::vector<uint8_t> yaz0_encode(const u8* src, int src_size) {
+ std::vector<uint8_t> buffer(src_size * 10 / 8 + 16);
+ u8* dst = buffer.data();
+
+ // write 4 bytes yaz0 header
+ memcpy(dst, "Yaz0", 4);
+
+ // write 4 bytes uncompressed size
+ W32(dst + 4, src_size);
+
+ // encode
+ int dst_size = yaz0_encode_internal(src, src_size, dst + 16);
+ int aligned_size = (dst_size + 31) & -16;
+ buffer.resize(aligned_size);
+
+#if 0
+ std::vector<uint8_t> decompressed(src_size);
+ yaz0_decode(buffer.data(), decompressed.data(), src_size);
+ if(memcmp(src, decompressed.data(), src_size)) {
+ fprintf(stderr, "Decompressed buffer is different from original\n");
+ }
+#endif
+
+ return buffer;
+}
+
+void yaz0_decode(const uint8_t* source, uint8_t* decomp, int32_t decompSize) {
+ uint32_t srcPlace = 0, dstPlace = 0;
+ uint32_t i, dist, copyPlace, numBytes;
+ uint8_t codeByte, byte1, byte2;
+ uint8_t bitCount = 0;
+
+ source += 0x10;
+ while (dstPlace < decompSize) {
+ /* If there are no more bits to test, get a new byte */
+ if (!bitCount) {
+ codeByte = source[srcPlace++];
+ bitCount = 8;
+ }
+
+ /* If bit 7 is a 1, just copy 1 byte from source to destination */
+ /* Else do some decoding */
+ if (codeByte & 0x80) {
+ decomp[dstPlace++] = source[srcPlace++];
+ } else {
+ /* Get 2 bytes from source */
+ byte1 = source[srcPlace++];
+ byte2 = source[srcPlace++];
+
+ /* Calculate distance to move in destination */
+ /* And the number of bytes to copy */
+ dist = ((byte1 & 0xF) << 8) | byte2;
+ copyPlace = dstPlace - (dist + 1);
+ numBytes = byte1 >> 4;
+
+ /* Do more calculations on the number of bytes to copy */
+ if (!numBytes)
+ numBytes = source[srcPlace++] + 0x12;
+ else
+ numBytes += 2;
+
+ /* Copy data from a previous point in destination */
+ /* to current point in destination */
+ for (i = 0; i < numBytes; i++) decomp[dstPlace++] = decomp[copyPlace++];
+ }
+
+ /* Set up for the next read cycle */
+ codeByte = codeByte << 1;
+ bitCount--;
+ }
+} \ No newline at end of file
diff --git a/ZAPD/yaz0/yaz0.h b/ZAPD/yaz0/yaz0.h
new file mode 100644
index 0000000..0d5cc3c
--- /dev/null
+++ b/ZAPD/yaz0/yaz0.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <vector>
+
+void yaz0_decode(const uint8_t* src, uint8_t* dest, int32_t destsize);
+std::vector<uint8_t> yaz0_encode(const uint8_t* src, int src_size); \ No newline at end of file