7#include "absl/status/status.h"
8#include "absl/status/statusor.h"
9#include "absl/strings/str_cat.h"
13#define DEBUG_LOG(msg) std::cout << msg << std::endl
24 std::cout <<
"Command: " << std::to_string(piece->command) <<
"\n";
25 std::cout <<
"Command Length: " << piece->length <<
"\n";
26 std::cout <<
"Argument: ";
27 auto arg_size = piece->argument.size();
28 for (
int i = 0; i < arg_size; ++i) {
29 printf(
"%02X ", piece->argument.at(i));
31 std::cout <<
"\nArgument Length: " << piece->argument_length <<
"\n";
35 auto compressed_chain = chain_head->next;
36 while (compressed_chain !=
nullptr) {
37 std::cout <<
"- Compression Piece -\n";
39 compressed_chain = compressed_chain->next;
45 const uint last_pos) {
46 uint pos = src_data_pos;
47 char byte_to_repeat = rom_data[pos];
48 while (pos <= last_pos && rom_data[pos] == byte_to_repeat) {
57 const uint last_pos) {
58 if (src_data_pos + 2 <= last_pos &&
59 rom_data[src_data_pos] != rom_data[src_data_pos + 1]) {
60 uint pos = src_data_pos;
61 char byte1 = rom_data[pos];
62 char byte2 = rom_data[pos + 1];
65 while (pos + 1 <= last_pos) {
66 if (rom_data[pos] == byte1 && rom_data[pos + 1] == byte2)
79 const uint last_pos) {
80 uint pos = src_data_pos;
81 char byte = rom_data[pos];
85 while (pos <= last_pos &&
byte == rom_data[pos]) {
96 if (src_data_pos != start) {
97 uint searching_pos = start;
98 uint current_pos_u = src_data_pos;
100 uint search_start = start;
102 while (searching_pos < src_data_pos && current_pos_u <= last_pos) {
103 while (rom_data[current_pos_u] != rom_data[searching_pos] &&
104 searching_pos < src_data_pos)
106 search_start = searching_pos;
107 while (current_pos_u <= last_pos &&
108 rom_data[current_pos_u] == rom_data[searching_pos] &&
109 searching_pos < src_data_pos) {
114 if (copied_size > data_size_taken[kCommandRepeatingBytes]) {
115 search_start -= start;
116 printf(
"- Found repeat of %d at %d\n", copied_size, search_start);
121 current_pos_u = src_data_pos;
131 uint& cmd_with_max) {
132 for (
uint cmd_i = 1; cmd_i < 5; cmd_i++) {
133 uint cmd_size_taken = data_size_taken[cmd_i];
137 !(cmd_i == kCommandRepeatingBytes && cmd_size_taken == 3);
138 if (cmd_size_taken > max_win && cmd_size_taken > cmd_size[cmd_i] &&
140 printf(
"==> C:%d / S:%d\n", cmd_i, cmd_size_taken);
141 cmd_with_max = cmd_i;
142 max_win = cmd_size_taken;
151 uint& src_data_pos,
uint& comp_accumulator,
152 uint& cmd_with_max,
uint& max_win) {
153 printf(
"- Ok we get a gain from %d\n", cmd_with_max);
155 buffer.push_back(cmd_args[cmd_with_max][0]);
156 if (cmd_size[cmd_with_max] == 2) {
157 buffer.push_back(cmd_args[cmd_with_max][1]);
160 auto new_comp_piece = std::make_shared<CompressionPiece>(
161 cmd_with_max, max_win, buffer, cmd_size[cmd_with_max]);
164 if (comp_accumulator != 0) {
165 std::string copy_buff;
166 copy_buff.resize(comp_accumulator);
167 for (
int i = 0; i < comp_accumulator; ++i) {
168 copy_buff[i] = rom_data[i + src_data_pos - comp_accumulator];
170 auto copy_chunk = std::make_shared<CompressionPiece>(
171 kCommandDirectCopy, comp_accumulator, copy_buff, comp_accumulator);
172 compressed_chain->next = copy_chunk;
173 compressed_chain = copy_chunk;
175 compressed_chain->next = new_comp_piece;
176 compressed_chain = new_comp_piece;
178 src_data_pos += max_win;
179 comp_accumulator = 0;
188 while (src_pos + i < last_pos && data[src_pos] == data[src_pos + i]) {
197 if (src_pos + 2 <= last_pos && data[src_pos] != data[src_pos + 1]) {
199 char byte1 = data[pos];
200 char byte2 = data[pos + 1];
203 while (pos + 1 <= last_pos) {
204 if (data[pos] == byte1 && data[pos + 1] == byte2)
217 uint pos = src_data_pos;
218 char byte = rom_data[pos];
222 while (pos <= last_pos &&
byte == rom_data[pos]) {
233 if (src_data_pos != start) {
234 uint searching_pos = start;
235 uint current_pos_u = src_data_pos;
236 uint copied_size = 0;
237 uint search_start = start;
239 while (searching_pos < src_data_pos && current_pos_u <= last_pos) {
240 while (rom_data[current_pos_u] != rom_data[searching_pos] &&
241 searching_pos < src_data_pos)
243 search_start = searching_pos;
244 while (current_pos_u <= last_pos &&
245 rom_data[current_pos_u] == rom_data[searching_pos] &&
246 searching_pos < src_data_pos) {
251 if (copied_size > cmd.
data_size[kCommandRepeatingBytes]) {
252 search_start -= start;
253 printf(
"- Found repeat of %d at %d\n", copied_size, search_start);
258 current_pos_u = src_data_pos;
269 uint& cmd_with_max) {
270 for (
uint cmd_i = 1; cmd_i < 5; cmd_i++) {
275 if (cmd_size_taken > max_win && cmd_size_taken >
kCommandSizes[cmd_i] &&
276 !(cmd_i == kCommandRepeatingBytes && cmd_size_taken == 3)) {
277 printf(
"==> C:%d / S:%d\n", cmd_i, cmd_size_taken);
278 cmd_with_max = cmd_i;
279 max_win = cmd_size_taken;
287 uint& src_data_pos,
uint& comp_accumulator,
288 uint& cmd_with_max,
uint& max_win) {
289 printf(
"- Ok we get a gain from %d\n", cmd_with_max);
291 buffer.push_back(cmd.
arguments[cmd_with_max][0]);
292 if (cmd.
cmd_size[cmd_with_max] == 2) {
293 buffer.push_back(cmd.
arguments[cmd_with_max][1]);
296 auto new_comp_piece = std::make_shared<CompressionPiece>(
297 cmd_with_max, max_win, buffer, cmd.
cmd_size[cmd_with_max]);
300 if (comp_accumulator != 0) {
301 std::string copy_buff;
302 copy_buff.resize(comp_accumulator);
303 for (
int i = 0; i < comp_accumulator; ++i) {
304 copy_buff[i] = rom_data[i + src_data_pos - comp_accumulator];
306 auto copy_chunk = std::make_shared<CompressionPiece>(
307 kCommandDirectCopy, comp_accumulator, copy_buff, comp_accumulator);
308 compressed_chain->next = copy_chunk;
309 compressed_chain = copy_chunk;
311 compressed_chain->next = new_comp_piece;
312 compressed_chain = new_comp_piece;
314 src_data_pos += max_win;
315 comp_accumulator = 0;
321 uint& uncompressed_data_size,
uint& best_command,
uint& best_command_gain) {
322 std::cout <<
"- Identified a gain from command: " << best_command
326 std::string argument_buffer;
327 argument_buffer.push_back(command.
arguments[best_command][0]);
328 if (command.
cmd_size[best_command] == 2) {
329 argument_buffer.push_back(command.
arguments[best_command][1]);
333 auto new_compression_piece = std::make_shared<CompressionPiece>(
334 best_command, best_command_gain, argument_buffer,
340 if (uncompressed_data_size != 0) {
341 std::string copy_buffer(uncompressed_data_size, 0);
342 for (
int i = 0; i < uncompressed_data_size; ++i) {
344 rom_data[i + source_data_position - uncompressed_data_size];
346 auto direct_copy_piece = std::make_shared<CompressionPiece>(
347 kCommandDirectCopy, uncompressed_data_size, copy_buffer,
348 uncompressed_data_size);
351 compressed_chain->next = direct_copy_piece;
352 compressed_chain = direct_copy_piece;
356 compressed_chain->next = new_compression_piece;
357 compressed_chain = new_compression_piece;
361 source_data_position += best_command_gain;
362 uncompressed_data_size = 0;
371 switch (piece->command) {
374 new_piece = std::make_shared<CompressionPiece>(
375 piece->command, length_left, piece->argument, piece->argument_length);
378 new_piece = std::make_shared<CompressionPiece>(
379 piece->command, length_left, piece->argument, piece->argument_length);
380 new_piece->argument[0] =
385 new_piece = std::make_shared<CompressionPiece>(
386 piece->command, length_left,
nullptr, length_left);
388 for (
int i = 0; i < length_left; ++i) {
394 uint offset = piece->argument[0] + (piece->argument[1] << 8);
395 new_piece = std::make_shared<CompressionPiece>(
396 piece->command, length_left, piece->argument, piece->argument_length);
398 new_piece->argument[0] =
403 new_piece->argument[1] =
409 return absl::InvalidArgumentError(
410 "SplitCompressionCommand: Invalid Command");
420 std::vector<uint8_t> output;
422 while (piece !=
nullptr) {
424 output.push_back(
BUILD_HEADER(piece->command, piece->length));
429 (((piece->length - 1) & 0xFF00) >> 8));
431 printf(
"Building extended header : cmd: %d, length: %d - %02X\n",
432 piece->command, piece->length, output[pos - 1]);
433 output.push_back(((piece->length - 1) & 0x00FF));
438 if (!new_piece.ok()) {
439 std::cout << new_piece.status().ToString() << std::endl;
441 printf(
"New added piece\n");
442 auto piece_data = new_piece.value();
444 piece_data->next = piece->next;
445 piece->next = piece_data;
450 if (piece->command == kCommandRepeatingBytes) {
452 tmp[0] = piece->argument[0];
453 tmp[1] = piece->argument[1];
455 tmp[0] = piece->argument[1];
456 tmp[1] = piece->argument[0];
458 for (
const auto& each : tmp) {
459 output.push_back(each);
463 for (
int i = 0; i < piece->argument_length; ++i) {
464 output.push_back(piece->argument[i]);
468 pos += piece->argument_length;
476 int mode,
int start,
int src_data_pos) {
477 if (chain_head->next !=
nullptr) {
483 if (!std::equal(decomp_data.begin() + start, decomp_data.end(),
485 return absl::InternalError(absl::StrFormat(
486 "Compressed data does not match uncompressed data at %d\n",
487 (
uint)(src_data_pos - start)));
490 return absl::OkStatus();
497 while (piece !=
nullptr) {
498 if (piece->command == kCommandDirectCopy && piece->next !=
nullptr &&
499 piece->next->command == kCommandDirectCopy &&
501 uint previous_length = piece->length;
502 piece->length = piece->length + piece->next->length;
504 for (
int i = 0; i < piece->next->argument_length; ++i) {
505 piece->argument[i + previous_length] = piece->next->argument[i];
507 piece->argument_length = piece->length;
510 auto p_next_next = piece->next->next;
511 piece->next = p_next_next;
521 const int length,
int mode,
525 return std::vector<uint8_t>();
529 auto compressed_chain = std::make_shared<CompressionPiece>(1, 1,
"aaa", 2);
530 auto compressed_chain_start = compressed_chain;
536 uint src_pos = start;
537 uint last_pos = start + length - 1;
538 uint comp_accumulator = 0;
555 if (cmd_with_max == kCommandDirectCopy) {
563 if (comp_accumulator == 32 || src_pos > last_pos) {
564 std::string buffer =
SetBuffer(data, src_pos, comp_accumulator);
565 auto new_comp_piece = std::make_shared<CompressionPiece>(
566 kCommandDirectCopy, comp_accumulator, buffer, comp_accumulator);
567 compressed_chain->next = new_comp_piece;
568 comp_accumulator = 0;
572 src_pos, comp_accumulator, cmd_with_max,
576 if (src_pos > last_pos) {
577 printf(
"Breaking compression loop\n");
594uint8_t*
Compress(uint8_t
const*
const src,
int const oldsize,
int*
const size,
597 (
unsigned char*)malloc(0x1000);
599 int i, j, k, l, m = 0, n, o = 0, bd = 0, p, q = 0, r;
601 for (i = 0; i < oldsize;) {
609 for (j = 0; j < i - 1; j++) {
613 for (n = 0; n < m; n++)
614 if (src[n + j] != src[n + i])
break;
616 if (n > k) k = n, o = j;
620 for (n = i + 1; n < oldsize; n++) {
637 for (n = i + 2; n < oldsize; n++) {
638 if (src[n] != l)
break;
642 if (src[n] != m)
break;
652 for (n = 1; n < m; n++)
653 if (src[i + n] != l + n)
break;
662 if (k > 3 + r && k > n + (p & 1)) p = 4, n = k;
671 b2[bd++] = (
unsigned char)(224 + (q >> 8));
674 b2[bd++] = (
unsigned char)q;
677 memcpy(b2 + bd, src + i - q, q);
687 b2[bd++] = (
unsigned char)(224 + (n >> 8) + (p << 2));
688 b2[bd++] = (
unsigned char)n;
690 b2[bd++] = (
unsigned char)((p << 5) + n);
695 b2[bd++] = (
unsigned char)l;
699 b2[bd++] = (
unsigned char)l;
700 b2[bd++] = (
unsigned char)m;
706 b2[bd++] = (
unsigned char)(o >> 8);
707 b2[bd++] = (
unsigned char)o;
709 b2[bd++] = (
unsigned char)o;
710 b2[bd++] = (
unsigned char)(o >> 8);
722 b2[bd++] = (
unsigned char)(224 + (q >> 8));
725 b2[bd++] = (
unsigned char)q;
728 memcpy(b2 + bd, src + i - q, q);
734 b2 = (
unsigned char*)realloc(b2, bd);
741 int const p_big_endian) {
742 unsigned char* b2 = (
unsigned char*)malloc(1024);
744 int bd = 0, bs = 1024;
755 if (a == 0xff)
break;
766 c = ((a & 0x0003) << 8);
770 c = (uint16_t)(a & 31);
774 if ((bd + c) > (bs - 512)) {
777 b2 = (uint8_t*)realloc(b2, bs);
789 memcpy(b2 + bd, src, c);
803 memset(b2 + bd, *(src++), c);
851 d = (*src << 8) + src[1];
865 b2 = (
unsigned char*)realloc(b2, bd);
867 if (size) (*size) = bd;
886 const std::vector<uint8_t> data,
const int pos,
const int length) {
897 if (pos == 0 || context.
data[pos - 1] != context.
data[pos]) {
898 char byte_to_repeat = context.
data[pos];
899 while (pos <= context.
last_pos && context.
data[pos] == byte_to_repeat) {
907 DEBUG_LOG(
"CheckByteRepeatV3: byte_to_repeat = "
908 << (
int)byte_to_repeat <<
", size = "
916 char byte1 = context.
data[pos];
917 char byte2 = context.
data[pos + 1];
920 while (pos + 1 <= context.
last_pos) {
921 if (context.
data[pos] == byte1 && context.
data[pos + 1] == byte2)
941 uint8_t
byte = context.
data[pos];
946 while (pos <= context.
last_pos &&
byte == context.
data[pos]) {
955 context.
src_pos > 0 && pos < context.
data.size() &&
972 const int window_size =
978 context.
src_pos + window_size <= context.
data.size()) {
979 uint max_copied_size = 0;
980 uint best_search_start = 0;
983 for (
int win_pos = 1; win_pos < window_size && win_pos < context.
src_pos;
985 auto start_search_from = context.
data.begin() + context.
src_pos - win_pos;
986 auto search_end = context.
data.begin() + context.
src_pos;
990 auto found_pos = std::search(
991 start_search_from, search_end, context.
data.begin() + context.
src_pos,
994 if (found_pos != search_end) {
997 while (context.
src_pos + len < context.
data.size() &&
998 context.
data[context.
src_pos + len] == *(found_pos + len)) {
1002 if (len > max_copied_size) {
1003 max_copied_size = len;
1004 best_search_start = found_pos - context.
data.begin();
1009 if (max_copied_size >
1011 DEBUG_LOG(
"CheckIntraCopyV3: Detected repeating sequence of length "
1012 << max_copied_size <<
" starting from " << best_search_start);
1017 best_search_start >> 8;
1020 DEBUG_LOG(
"CheckIntraCopyV3: max_copied_size = " << max_copied_size
1021 <<
", best_search_start = "
1022 << best_search_start);
1043 DEBUG_LOG(
"CheckAvailableCompressionCommands: src_pos = " << context.
src_pos);
1047 int max_net_savings = -1;
1052 for (
uint cmd_i = 1; cmd_i < 5; cmd_i++) {
1057 if (cmd_size_taken <= 2 && cmd_i != kCommandDirectCopy) {
1063 context.
src_pos + cmd_size_taken < context.
data.size()) {
1064 char prev_byte = context.
data[context.
src_pos - 1];
1065 char next_byte = context.
data[context.
src_pos + cmd_size_taken];
1066 if (prev_byte != next_byte && cmd_size_taken == 3) {
1072 if (net_savings > max_net_savings) {
1074 max_net_savings = net_savings;
1078 DEBUG_LOG(
"DetermineBestCompression: cmd_with_max = "
1090 std::vector<uint8_t> uncompressed_data(
1094 uncompressed_data.begin(),
1095 uncompressed_data.end());
1121 std::vector<uint8_t> uncompressed_data(
1125 uncompressed_data.begin(),
1126 uncompressed_data.end());
1131 <<
", compressed_data size = "
1136 DEBUG_LOG(
"AddCompressionToChain: Adding command arguments: ");
1143 std::vector<uint8_t> uncompressed_data(
1147 uncompressed_data.begin(),
1148 uncompressed_data.end());
1158 DEBUG_LOG(
"AddCompressionToChain: (Before) src_pos = "
1173 DEBUG_LOG(
"AddCompressionToChain: (After) src_pos = "
1185 if (!std::equal(decomp_data.begin() + context.
start, decomp_data.end(),
1186 temp_rom.
begin())) {
1187 return absl::InternalError(absl::StrFormat(
1188 "Compressed data does not match uncompressed data at %d\n",
1192 return absl::OkStatus();
1217 for (
int i = 0; i < length_left; ++i) {
1236 return absl::InvalidArgumentError(
1237 "SplitCompressionCommand: Invalid Command");
1256 (((piece.
length - 1) & 0xFF00) >> 8));
1258 std::cout <<
"Building extended header : cmd: " << piece.
command
1259 <<
", length: " << piece.
length <<
" - "
1262 ((piece.
length - 1) & 0x00FF));
1266 if (!new_piece.ok()) {
1267 std::cout << new_piece.status().ToString() << std::endl;
1275 if (piece.
command == kCommandRepeatingBytes) {
1283 for (
const auto& each : tmp) {
1307 DEBUG_LOG(
"FinalizeCompression: compressed_data size = "
1312 const std::vector<uint8_t>& data,
const int start,
const int length,
1313 int mode,
bool check) {
1315 return std::vector<uint8_t>();
1347 for (
int i = 0; i < comp_accumulator; ++i) {
1348 buffer.push_back(data[i + src_pos - comp_accumulator]);
1353std::string
SetBuffer(
const std::vector<uint8_t>& data,
int src_pos,
1354 int comp_accumulator) {
1356 for (
int i = 0; i < comp_accumulator; ++i) {
1357 buffer.push_back(data[i + src_pos - comp_accumulator]);
1362void memfill(
const uchar* data, std::vector<uint8_t>& buffer,
int buffer_pos,
1363 int offset,
int length) {
1364 auto a = data[offset];
1365 auto b = data[offset + 1];
1366 for (
int i = 0; i < length; i = i + 2) {
1367 buffer[buffer_pos + i] = a;
1368 if ((i + 1) < length) buffer[buffer_pos + i + 1] = b;
1373 int size,
int mode) {
1375 return std::vector<uint8_t>();
1378 std::vector<uint8_t> buffer(size, 0);
1380 uint buffer_pos = 0;
1382 uchar header = data[offset];
1400 memcpy(buffer.data() + buffer_pos, data + offset, length);
1401 buffer_pos += length;
1405 memset(buffer.data() + buffer_pos, (
int)(data[offset]), length);
1406 buffer_pos += length;
1410 memfill(data, buffer, buffer_pos, offset, length);
1411 buffer_pos += length;
1415 auto inc_byte = data[offset];
1416 for (
int i = 0; i < length; i++) {
1417 buffer[buffer_pos] = inc_byte++;
1425 int addr = (s1 | s2);
1431 if (addr > offset) {
1432 return absl::InternalError(
1433 absl::StrFormat(
"Decompress: Offset for command copy exceeds "
1435 "(Offset : %#04x | Pos : %#06x)\n",
1438 if (buffer_pos + length >= size) {
1440 buffer.resize(size);
1442 memcpy(buffer.data() + buffer_pos, buffer.data() + addr, length);
1443 buffer_pos += length;
1447 std::cout << absl::StrFormat(
1448 "Decompress: Invalid header (Offset : %#06x, Command: %#04x)\n",
1453 header = data[offset];
1460 int pos,
int size) {
1465 int pos,
int size) {
1470 const std::vector<uint8_t> data,
int pos,
int size) {
The Rom class is used to load, save, and modify Rom data.
absl::Status LoadFromBytes(const std::vector< uint8_t > &data)
#define BUILD_HEADER(command, length)
#define RETURN_IF_ERROR(expression)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
void stle16b(uint8_t *const p_arr, uint16_t const p_val)
uint16_t ldle16b(uint8_t const *const p_arr)
constexpr int kCommandMod
constexpr int kExpandedMod
void DetermineBestCompression(CompressionContext &context)
std::vector< uint8_t > CreateCompressionString(CompressionPiecePointer &start, int mode)
absl::StatusOr< std::vector< uint8_t > > CompressOverworld(const uchar *data, const int pos, const int length)
void ValidateForByteGain(const DataSizeArray &data_size_taken, const CommandSizeArray &cmd_size, uint &max_win, uint &cmd_with_max)
constexpr int kNintendoMode2
constexpr int kSnesByteMax
void CheckIntraCopyV2(const uchar *rom_data, uint &src_data_pos, const uint last_pos, uint start, CompressionCommand &cmd)
constexpr int kCommandByteFill
constexpr int kNormalLengthMod
constexpr int kCompressionStringMod
absl::StatusOr< std::vector< uint8_t > > DecompressGraphics(const uchar *data, int pos, int size)
void CheckIntraCopy(const uchar *rom_data, DataSizeArray &data_size_taken, CommandArgumentArray &cmd_args, uint &src_data_pos, const uint last_pos, uint start)
void CheckWordRepeatV3(CompressionContext &context)
absl::StatusOr< std::vector< uint8_t > > CompressV3(const std::vector< uint8_t > &data, const int start, const int length, int mode, bool check)
Compresses a buffer of data using the LC_LZ2 algorithm.
void CheckIncByteV3(CompressionContext &context)
void CheckIncByteV2(const uchar *rom_data, uint &src_data_pos, const uint last_pos, CompressionCommand &cmd)
absl::StatusOr< std::vector< uint8_t > > DecompressOverworld(const uchar *data, int pos, int size)
void AddCompressionToChain(CompressionContext &context)
void PrintCompressionPiece(const CompressionPiecePointer &piece)
void InitializeCompression(CompressionContext &context)
constexpr int kCommandIncreasingFill
constexpr int kCommandDirectCopy
std::array< uint, 5 > CommandSizeArray
constexpr int kMaxLengthNormalHeader
void CheckIntraCopyV3(CompressionContext &context)
void CheckWordRepeat(const uchar *rom_data, DataSizeArray &data_size_taken, CommandArgumentArray &cmd_args, uint &src_data_pos, const uint last_pos)
absl::Status ValidateCompressionResult(CompressionPiecePointer &chain_head, int mode, int start, int src_data_pos)
void AddAlternativeCompressionCommand(const uchar *rom_data, CompressionPiecePointer &compressed_chain, const CompressionCommand &command, uint &source_data_position, uint &uncompressed_data_size, uint &best_command, uint &best_command_gain)
absl::StatusOr< std::vector< uint8_t > > CompressV2(const uchar *data, const int start, const int length, int mode, bool check)
Compresses a buffer of data using the LC_LZ2 algorithm.
void memfill(const uchar *data, std::vector< uint8_t > &buffer, int buffer_pos, int offset, int length)
CompressionPiecePointer MergeCopy(CompressionPiecePointer &start)
std::array< std::array< char, 2 >, 5 > CommandArgumentArray
absl::StatusOr< std::vector< uint8_t > > DecompressV2(const uchar *data, int offset, int size, int mode)
Decompresses a buffer of data using the LC_LZ2 algorithm.
void CheckByteRepeat(const uchar *rom_data, DataSizeArray &data_size_taken, CommandArgumentArray &cmd_args, uint &src_data_pos, const uint last_pos)
absl::StatusOr< CompressionPiecePointer > SplitCompressionPiece(CompressionPiecePointer &piece, int mode)
void CheckWordRepeatV2(const uchar *data, uint &src_pos, const uint last_pos, CompressionCommand &cmd)
constexpr int kNintendoMode1
constexpr int kCommandRepeatingBytes
constexpr int kExpandedLengthMod
uint8_t * Uncompress(uint8_t const *src, int *const size, int const p_big_endian)
constexpr int kCommandWordFill
void CheckAvailableCompressionCommands(CompressionContext &context)
uint8_t * Compress(uint8_t const *const src, int const oldsize, int *const size, int const flag)
constexpr int kMaxLengthCompression
void CheckByteRepeatV2(const uchar *data, uint &src_pos, const uint last_pos, CompressionCommand &cmd)
void CompressionCommandAlternativeV2(const uchar *rom_data, const CompressionCommand &cmd, CompressionPiecePointer &compressed_chain, uint &src_data_pos, uint &comp_accumulator, uint &cmd_with_max, uint &max_win)
std::array< uint, 5 > DataSizeArray
absl::StatusOr< CompressionPiece > SplitCompressionPieceV3(CompressionPiece &piece, int mode)
void ValidateForByteGainV2(const CompressionCommand &cmd, uint &max_win, uint &cmd_with_max)
void CheckIncByte(const uchar *rom_data, DataSizeArray &data_size_taken, CommandArgumentArray &cmd_args, uint &src_data_pos, const uint last_pos)
absl::StatusOr< std::vector< uint8_t > > CompressGraphics(const uchar *data, const int pos, const int length)
void HandleDirectCopy(CompressionContext &context)
std::string SetBuffer(const uchar *data, int src_pos, int comp_accumulator)
const std::array< int, 5 > kCommandSizes
void CompressionCommandAlternative(const uchar *rom_data, CompressionPiecePointer &compressed_chain, const CommandSizeArray &cmd_size, const CommandArgumentArray &cmd_args, uint &src_data_pos, uint &comp_accumulator, uint &cmd_with_max, uint &max_win)
void FinalizeCompression(CompressionContext &context)
void PrintCompressionChain(const CompressionPiecePointer &chain_head)
void CheckByteRepeatV3(CompressionContext &context)
std::shared_ptr< CompressionPiece > CompressionPiecePointer
struct CompressionPiece CompressionPiece
absl::Status ValidateCompressionResultV3(const CompressionContext &context)
std::array< std::array< char, 2 >, 5 > arguments
std::array< uint, 5 > data_size
std::array< uint, 5 > cmd_size
CompressionCommand current_cmd
std::vector< uint8_t > data
std::vector< uint8_t > compressed_data
std::vector< uint8_t > compression_string
std::vector< CompressionPiece > compression_pieces