Last active
November 3, 2018 03:16
-
-
Save khang06/e407b25d86923bb881ff1923a4447667 to your computer and use it in GitHub Desktop.
terrible yaz0 c++ thing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <cstdint> | |
#include <cstring> | |
#include <cstdlib> | |
#include <iostream> | |
#include <fstream> | |
#include <vector> | |
namespace Yaz0 { | |
struct Header { | |
uint16_t magic[4]; | |
uint32_t decmp_size; | |
int32_t unknown[2]; | |
}; | |
int GetDecompressedSize(const char *src) { | |
Header header; | |
header = *reinterpret_cast<const Header*>(src); | |
if (memcmp(&header.magic, "Yaz0", 4)) { | |
throw "Input is not Yaz0!"; | |
} | |
return header.decmp_size; | |
} | |
void Decompress(const char *src, const uint32_t src_size, char *dst) { | |
Header header; | |
uint16_t code_byte; | |
uint32_t valid_bit_count = 0; | |
uint32_t src_pos = 16; | |
uint32_t dst_pos = 0; | |
uint16_t byte1; | |
uint16_t byte2; | |
uint32_t copy_src; | |
uint32_t copy_len; | |
if (src_size < 16) { | |
throw "Input is too small!"; | |
} | |
header = *reinterpret_cast<const Header*>(src); | |
if (memcmp(&header.magic, "Yaz0", 4)) { | |
// if (*reinterpret_cast<const int32_t*>(src) != *reinterpret_cast<const int32_t*>("Yaz0")) { // this looks like shit | |
// if (*(const int32_t*)src != *(const int32_t*)"Yaz0") { | |
throw "Input is not Yaz0!"; | |
} | |
code_byte = src[16]; | |
while (dst_pos < header.decmp_size) { | |
// printf("while loop hit\n"); | |
if (valid_bit_count == 0) { | |
code_byte = src[src_pos]; | |
src_pos++; | |
valid_bit_count = 8; | |
} | |
if ((code_byte & 0x80) != 0) { | |
//printf("no compression\n"); | |
dst[dst_pos] = src[src_pos]; | |
src_pos++; | |
dst_pos++; | |
} | |
else { | |
//printf("compression\n"); | |
byte1 = src[src_pos]; | |
//printf("byte1: %u\n", byte1); | |
src_pos++; | |
byte2 = src[src_pos]; | |
src_pos++; | |
copy_src = dst_pos - ((byte1 & 0x0f) << 8 | byte2) - 1; | |
//printf("byte1: %u\n", byte1); | |
copy_len = byte1 >> 4; | |
//printf("copy_len: %u\n", copy_len); | |
if (copy_len == 0) { | |
copy_len = src[src_pos] + 0x12; | |
//printf("copy_len 1: %u\n", copy_len); | |
src_pos++; | |
} | |
else { | |
copy_len += 2; | |
//printf("copy_len 2: %u\n", copy_len); | |
} | |
//printf("start copy run: %u\n", copy_len); | |
//if (copy_len > 128) | |
// printf("wtf\n"); | |
//copy_len = copy_len; // lol i just needed this for a breakpoint | |
for (uint32_t i = 0; i < copy_len; i++) { | |
if (copy_src > header.decmp_size) | |
printf("oob copy_src: %08X\n", copy_src); | |
if (dst_pos > header.decmp_size) | |
printf("oob dst_pos: %08X\n", dst_pos); | |
//printf("copy from %08X to %08X\n", copy_src, dst_pos); | |
dst[dst_pos] = dst[copy_src]; | |
copy_src++; | |
dst_pos++; | |
} | |
} | |
code_byte <<= 1; | |
valid_bit_count -= 1; | |
} | |
} | |
} | |
int main(int argc, char *argv[]) { | |
if (argc != 3) { | |
printf("Usage: %s [input] [output]\n", argv[0]); | |
return 1; | |
} | |
std::ifstream input; | |
std::ofstream output; | |
input.open(argv[1], std::ios::in | std::ios::binary | std::ios::ate); | |
output.open(argv[2], std::ios::out | std::ios::binary); | |
if (!input.is_open()) { | |
printf("Unable to open %s.\n", argv[1]); | |
return 2; | |
} | |
if (!output.is_open()) { | |
printf("Unable to open %s.\n", argv[2]); | |
return 3; | |
} | |
std::streamsize size = input.tellg(); | |
input.seekg(0, std::ios::beg); | |
std::vector<char> compressed_buffer(size); | |
if (!input.read(compressed_buffer.data(), size)) | |
{ | |
printf("Unable to read %s.\n", argv[1]); | |
} | |
try { | |
int decompressed_size = Yaz0::GetDecompressedSize(compressed_buffer.data()); | |
std::vector<char> decompressed_buffer(decompressed_size); | |
Yaz0::Decompress(compressed_buffer.data(), compressed_buffer.size(), decompressed_buffer.data()); | |
for (const auto &byte : decompressed_buffer) output << byte; | |
} | |
catch(const char *msg) { | |
printf("%s\n", msg); | |
return 4; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment