hacktools 0.33.1__tar.gz → 0.35.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {hacktools-0.33.1 → hacktools-0.35.0}/LICENSE +1 -1
  2. {hacktools-0.33.1/hacktools.egg-info → hacktools-0.35.0}/PKG-INFO +2 -2
  3. {hacktools-0.33.1 → hacktools-0.35.0}/README.md +1 -1
  4. hacktools-0.35.0/hacktools/__init__.py +1 -0
  5. hacktools-0.35.0/hacktools/c_ext/cmp_racjin.c +227 -0
  6. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/common.py +13 -3
  7. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/nds.py +10 -4
  8. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/psp.py +2 -2
  9. {hacktools-0.33.1 → hacktools-0.35.0/hacktools.egg-info}/PKG-INFO +2 -2
  10. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools.egg-info/SOURCES.txt +1 -0
  11. {hacktools-0.33.1 → hacktools-0.35.0}/setup.py +1 -0
  12. {hacktools-0.33.1 → hacktools-0.35.0}/tests/test_cmp.py +8 -1
  13. hacktools-0.33.1/hacktools/__init__.py +0 -1
  14. {hacktools-0.33.1 → hacktools-0.35.0}/MANIFEST.in +0 -0
  15. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/arch.py +0 -0
  16. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/assets/icon.png +0 -0
  17. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/c_ext/cmp_cri.c +0 -0
  18. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/c_ext/cmp_lzss.c +0 -0
  19. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/c_ext/cmp_misc.c +0 -0
  20. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/c_ext/inc.h +0 -0
  21. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/compression.py +0 -0
  22. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/cpk.py +0 -0
  23. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/gb.py +0 -0
  24. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/gui.py +0 -0
  25. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/nasm.py +0 -0
  26. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/nitro.py +0 -0
  27. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/psx.py +0 -0
  28. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/wii.py +0 -0
  29. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools/ws.py +0 -0
  30. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools.egg-info/dependency_links.txt +0 -0
  31. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools.egg-info/requires.txt +0 -0
  32. {hacktools-0.33.1 → hacktools-0.35.0}/hacktools.egg-info/top_level.txt +0 -0
  33. {hacktools-0.33.1 → hacktools-0.35.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2023 Illidan
3
+ Copyright (c) 2020-2024 Illidan
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hacktools
3
- Version: 0.33.1
3
+ Version: 0.35.0
4
4
  Summary: A set of utilities and tools for rom hacking and translations.
5
5
  Home-page: https://github.com/Illidanz/hacktools
6
6
  Author: Illidan
@@ -96,7 +96,7 @@ External dependencies not included are marked as `(through *dependency*)`
96
96
  ### Other / Generic
97
97
  - CPK archives
98
98
  - ARCH archives
99
- - LZ10, LZ11, Huffman and CRILAYLA compression/decompression
99
+ - LZ10, LZ11, Huffman, CRILAYLA and RACJIN compression/decompression
100
100
  - ARM/MIPS binary patching
101
101
  - xdelta patch creation
102
102
  - IPS patch creation
@@ -47,7 +47,7 @@ External dependencies not included are marked as `(through *dependency*)`
47
47
  ### Other / Generic
48
48
  - CPK archives
49
49
  - ARCH archives
50
- - LZ10, LZ11, Huffman and CRILAYLA compression/decompression
50
+ - LZ10, LZ11, Huffman, CRILAYLA and RACJIN compression/decompression
51
51
  - ARM/MIPS binary patching
52
52
  - xdelta patch creation
53
53
  - IPS patch creation
@@ -0,0 +1 @@
1
+ __version__ = "0.35.0"
@@ -0,0 +1,227 @@
1
+ #include "inc.h"
2
+
3
+ // https://github.com/Raw-man/Racjin-de-compression/blob/master/src/encode.cpp
4
+ static PyObject* compressRACJIN(PyObject* module, PyObject* args, PyObject* kwargs)
5
+ {
6
+ static char *kwlist[] = { "indata", NULL };
7
+
8
+ unsigned char* src;
9
+ size_t srclen;
10
+
11
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#", kwlist, &src, &srclen))
12
+ return NULL;
13
+
14
+ unsigned char* compressed_buffer = PyMem_Malloc(srclen * 2);
15
+ MALLOC_CHECK(compressed_buffer);
16
+ unsigned int destlen = 0;
17
+
18
+ unsigned int index = 0; //position of an element from the input buffer
19
+ unsigned char last_enc_byte = 0;//last encoded byte
20
+ unsigned char bit_shift = 0; //shift by bitShift (used to fold codes)
21
+ unsigned char* frequencies = PyMem_Calloc(256, sizeof(unsigned char));
22
+ MALLOC_CHECK(frequencies);
23
+ for (int i = 0; i < 256; ++i)
24
+ frequencies[i] = 0;
25
+ unsigned int* seq_indices = PyMem_Calloc(8192, sizeof(unsigned int));
26
+ MALLOC_CHECK(seq_indices);
27
+ for (int i = 0; i < 8192; ++i)
28
+ seq_indices[i] = 0;
29
+ unsigned short* codes = PyMem_Calloc(srclen, sizeof(unsigned short));
30
+ MALLOC_CHECK(codes);
31
+ for (int i = 0; i < srclen; ++i)
32
+ codes[i] = 0;
33
+ unsigned int codeslen = 0;
34
+
35
+ while (index < srclen)
36
+ {
37
+ unsigned char best_freq = 0;
38
+ unsigned char best_match = 0;
39
+
40
+ // To get the exact same compression for CDDATA.DIG files uncomment the following:
41
+ if (frequencies[last_enc_byte] == 256)
42
+ frequencies[last_enc_byte] = 0x00;
43
+
44
+ unsigned char positions_to_check = frequencies[last_enc_byte] < 32 ? (frequencies[last_enc_byte] & 0x1F) : 32;
45
+ unsigned int seq_index = index;
46
+
47
+ for (unsigned char freq = 0; freq < positions_to_check; freq++)
48
+ {
49
+ unsigned short key = freq + last_enc_byte * 32; //0x1F + 0xFF*32 = 8191
50
+ unsigned int src_index = seq_indices[key];
51
+ unsigned char matched = 0;
52
+ unsigned char max_length = index + 8 < srclen ? 8 : srclen - index;
53
+
54
+ for (unsigned char offset = 0; offset < max_length; ++offset)
55
+ {
56
+ if (src[src_index + offset] == src[index + offset])
57
+ ++matched;
58
+ else
59
+ break;
60
+ }
61
+
62
+ if (matched > best_match)
63
+ {
64
+ best_freq = freq;
65
+ best_match = matched;
66
+ }
67
+ }
68
+
69
+ unsigned short code = 0x00;
70
+ if (best_match > 0) //found a better match?
71
+ {
72
+ code = code | (best_freq << 3); //f|ooooolll //f=0 (flag), o - occurrences/frequency, l -length
73
+ code = code | (best_match - 1); //encode a reference
74
+ index += best_match;
75
+ }
76
+ else //encode byte literal
77
+ {
78
+ code = 0x100 | src[index]; //f|bbbbbbbb //f=1
79
+ ++index;
80
+ }
81
+
82
+ code = code << bit_shift; //prepare for folding
83
+ codes[codeslen] = code;
84
+ codeslen++;
85
+
86
+ ++bit_shift;
87
+ if (bit_shift == 8)
88
+ bit_shift = 0;
89
+
90
+ unsigned int key = (frequencies[last_enc_byte] & 0x1F) + last_enc_byte * 32; //0x1F + 0xFF*32 = 8191
91
+ seq_indices[key] = seq_index;
92
+ frequencies[last_enc_byte] = frequencies[last_enc_byte] + 1; //increase by 1 (up to 31)
93
+ last_enc_byte = src[index - 1];
94
+ }
95
+ //Fold codes (8 codes, 16 bytes -> 8 codes, 9 bytes)
96
+ for (unsigned int i = 0; i < codeslen; i = i + 8)
97
+ {
98
+ unsigned char group_size = i + 8 < codeslen ? 8 : codeslen - i;
99
+ for (unsigned char s = 0; s <= group_size; s += 2)
100
+ {
101
+ unsigned short first = s > 0 ? codes[s + i - 1] : 0x00;
102
+ unsigned short middle = s < group_size ? codes[s + i] : 0x00;
103
+ unsigned short last = s < group_size - 1 ? codes[s + i + 1] : 0x00;
104
+ unsigned short result = middle | (first >> 8) | (last << 8);
105
+ compressed_buffer[destlen] = result & 0xFF;
106
+ ++destlen;
107
+ if (s < group_size)
108
+ {
109
+ compressed_buffer[destlen] = result >> 8;
110
+ ++destlen;
111
+ }
112
+ }
113
+ }
114
+
115
+ PyObject *output = PyBytes_FromStringAndSize(compressed_buffer, destlen);
116
+ PyMem_Free(compressed_buffer);
117
+ PyMem_Free(frequencies);
118
+ PyMem_Free(seq_indices);
119
+ PyMem_Free(codes);
120
+ return output;
121
+ }
122
+
123
+ // https://github.com/Raw-man/Racjin-de-compression/blob/master/src/decode.cpp
124
+ static PyObject* decompressRACJIN(PyObject* m, PyObject* args, PyObject* kwargs)
125
+ {
126
+ static char *kwlist[] = { "indata", "decomplength", NULL };
127
+
128
+ unsigned char* input_buffer;
129
+ size_t input_size;
130
+ unsigned int decomplength;
131
+
132
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#I", kwlist, &input_buffer, &input_size, &decomplength))
133
+ return NULL;
134
+
135
+ unsigned int index = 0; //position of a byte from the input buffer
136
+ unsigned int dest_index = 0; //position (destination) of a decoded byte in the output buffer
137
+ unsigned char last_dec_byte = 0; //last decoded byte of the previus decoding iteration
138
+ unsigned char bit_shift = 0; //shift right by bitShift
139
+
140
+ // Allocate buffers
141
+ unsigned char* frequencies = PyMem_Malloc(256);
142
+ MALLOC_CHECK(frequencies);
143
+ for (int i = 0; i < 256; ++i)
144
+ frequencies[i] = 0;
145
+ unsigned int* seq_indices = PyMem_Calloc(8192, sizeof(unsigned int));
146
+ MALLOC_CHECK(seq_indices);
147
+ for (int i = 0; i < 8192; ++i)
148
+ seq_indices[i] = 0;
149
+ unsigned char* decompressed_buffer = PyMem_Malloc(decomplength);
150
+ MALLOC_CHECK(decompressed_buffer);
151
+
152
+ while (index < input_size)
153
+ {
154
+ unsigned short next_code = input_buffer[index + 1]; //next pair of bytes to decode from the input buffer
155
+ next_code = next_code << 8;
156
+ next_code = next_code | input_buffer[index];
157
+ next_code = next_code >> bit_shift; //unfold 9 bit token
158
+
159
+ //The result can be interpreted as follows:
160
+ // iiiiiiif|ooooolll //f=0
161
+ // iiiiiiif|bbbbbbbb //f=1
162
+ //i - ignore
163
+ //f - flag (is literal or offset/length pair)
164
+ //l - length (add 1 to get the real length)
165
+ //o - occurrences/frequency
166
+ //b - byte literal
167
+
168
+ ++bit_shift;
169
+ ++index;
170
+
171
+ if (bit_shift == 8)
172
+ {
173
+ bit_shift = 0;
174
+ ++index;
175
+ }
176
+
177
+ unsigned int seq_index = dest_index; //start of a byte sequence
178
+ if ((next_code & 0x100) != 0) // bit flag: is nextToken a literal or a reference?
179
+ {
180
+ decompressed_buffer[dest_index] = (unsigned char)(next_code & 0xFF); //store the literal
181
+ ++dest_index;
182
+ }
183
+ else
184
+ {
185
+ unsigned int key = ((next_code >> 3) & 0x1F) + last_dec_byte * 32; //0x1F + 0xFF*32 = 8191
186
+ unsigned int src_index = seq_indices[key]; //get a reference to a previously decoded sequence
187
+
188
+ for (unsigned char length = 0; length < (next_code & 0x07) + 1; ++length, ++dest_index, ++src_index)
189
+ {
190
+ decompressed_buffer[dest_index] = decompressed_buffer[src_index]; //copy a previously decoded byte sequence (up to 8)
191
+ }
192
+ }
193
+
194
+ if (dest_index >= decomplength)
195
+ break;
196
+
197
+ unsigned int key = frequencies[last_dec_byte] + last_dec_byte * 32; //0x1F + 0xFF*32 = 8191
198
+ seq_indices[key] = seq_index;
199
+ frequencies[last_dec_byte] = (unsigned char)((frequencies[last_dec_byte] + 1) & 0x1F); //increase by 1 (up to 31)
200
+ last_dec_byte = decompressed_buffer[dest_index - 1];
201
+ }
202
+
203
+ PyObject *output = PyBytes_FromStringAndSize(decompressed_buffer, decomplength);
204
+ PyMem_Free(frequencies);
205
+ PyMem_Free(seq_indices);
206
+ PyMem_Free(decompressed_buffer);
207
+ return output;
208
+ }
209
+
210
+ static PyMethodDef Cmp_racjinMethods[] = {
211
+ {"compressRACJIN", (PyCFunction)compressRACJIN, METH_VARARGS | METH_KEYWORDS, "Compress RACJIN data."},
212
+ {"decompressRACJIN", (PyCFunction)decompressRACJIN, METH_VARARGS | METH_KEYWORDS, "Decompress RACJIN data."},
213
+ {NULL, NULL, 0, NULL}
214
+ };
215
+
216
+ static struct PyModuleDef cmp_racjinmodule = {
217
+ PyModuleDef_HEAD_INIT,
218
+ "cmp_racjin",
219
+ "RACJIN functions.",
220
+ -1,
221
+ Cmp_racjinMethods
222
+ };
223
+
224
+ PyMODINIT_FUNC PyInit_cmp_racjin(void)
225
+ {
226
+ return PyModule_Create(&cmp_racjinmodule);
227
+ }
@@ -756,7 +756,7 @@ class TranslationFile:
756
756
  note = ET.SubElement(unit, "note")
757
757
  note.text = comment
758
758
 
759
- def preloadLookup(self):
759
+ def preloadLookup(self, comments="#"):
760
760
  self.lookup = {}
761
761
  self.chartot = 0
762
762
  self.transtot = 0
@@ -764,6 +764,8 @@ class TranslationFile:
764
764
  for unit in self.files[file][0]:
765
765
  self.chartot += len(unit[0].text)
766
766
  if unit[1].text is not None and unit[1].text != "":
767
+ if comments in unit[1].text:
768
+ unit[1].text = unit[1].text.split(comments)[0]
767
769
  self.lookup[unit[0].text] = unit[1].text
768
770
  self.transtot += len(unit[0].text)
769
771
 
@@ -1030,7 +1032,7 @@ class BinaryPointer:
1030
1032
  self.str = str
1031
1033
 
1032
1034
 
1033
- def repackBinaryStrings(section, infile, outfile, binranges, freeranges=None, readfunc=detectEncodedString, writefunc=writeEncodedString, encoding="shift_jis", pointerstart=0, injectstart=0, fallbackf=None, injectfallback=0, sectionname="bin"):
1035
+ def repackBinaryStrings(section, infile, outfile, binranges, freeranges=None, readfunc=detectEncodedString, writefunc=writeEncodedString, encoding="shift_jis", pointerstart=0, injectstart=0, fallbackf=None, injectfallback=0, sectionname="bin", preformat=None, postformat=None):
1034
1036
  insize = os.path.getsize(infile)
1035
1037
  notfound = []
1036
1038
  with Stream(infile, "rb") as fi:
@@ -1045,6 +1047,9 @@ def repackBinaryStrings(section, infile, outfile, binranges, freeranges=None, re
1045
1047
  pos = fi.tell()
1046
1048
  check = readfunc(fi, encoding)
1047
1049
  if check != "":
1050
+ pre = post = ""
1051
+ if preformat != None:
1052
+ check, pre, post = preformat(check)
1048
1053
  if isinstance(section, TranslationFile):
1049
1054
  newsjis = section.getEntry(check, sectionname, pos)
1050
1055
  else:
@@ -1055,6 +1060,8 @@ def repackBinaryStrings(section, infile, outfile, binranges, freeranges=None, re
1055
1060
  if newsjis != "":
1056
1061
  if newsjis == "!":
1057
1062
  newsjis = ""
1063
+ if postformat != None:
1064
+ newsjis = postformat(newsjis, pre, post)
1058
1065
  newsjislog = newsjis.encode("ascii", "ignore")
1059
1066
  logDebug("Replacing string at", toHex(pos), "with", newsjislog)
1060
1067
  fo.seek(pos)
@@ -1104,7 +1111,10 @@ def repackBinaryStrings(section, infile, outfile, binranges, freeranges=None, re
1104
1111
  newpointer = range[0]
1105
1112
  # For the injected range, add injectstart, otherwise add pointerstart
1106
1113
  if (len(range) == 3):
1107
- newpointer += injectstart
1114
+ if isinstance(range[2], bool):
1115
+ newpointer += injectstart
1116
+ else:
1117
+ newpointer += int(range[2])
1108
1118
  else:
1109
1119
  newpointer += pointerstart
1110
1120
  range[0] = fo.tell()
@@ -134,7 +134,7 @@ def extractBIN(binrange, readfunc=common.detectEncodedString, encoding="shift_ji
134
134
 
135
135
 
136
136
  def repackBIN(binrange, freeranges=[], readfunc=common.detectEncodedString, writefunc=common.writeEncodedString, encoding="shift_jis", comments="#",
137
- binin="data/extract/arm9.bin", binout="data/repack/arm9.bin", binfile="data/bin_input.txt", fixchars=[], pointerstart=0x02000000, injectstart=0x02000000, fallbackf=None, injectfallback=0, nocopy=False, sectionname="bin"):
137
+ binin="data/extract/arm9.bin", binout="data/repack/arm9.bin", binfile="data/bin_input.txt", fixchars=[], pointerstart=0x02000000, injectstart=0x02000000, fallbackf=None, injectfallback=0, nocopy=False, sectionname="bin", preformat=None, postformat=None):
138
138
  if not os.path.isfile(binfile):
139
139
  common.logError("Input file", binfile, "not found")
140
140
  return False
@@ -152,7 +152,7 @@ def repackBIN(binrange, freeranges=[], readfunc=common.detectEncodedString, writ
152
152
  section.preloadLookup()
153
153
  if type(binrange) == tuple:
154
154
  binrange = [binrange]
155
- notfound = common.repackBinaryStrings(section, binin, binout, binrange, freeranges, readfunc, writefunc, encoding, pointerstart, injectstart, fallbackf, injectfallback, sectionname)
155
+ notfound = common.repackBinaryStrings(section, binin, binout, binrange, freeranges, readfunc, writefunc, encoding, pointerstart, injectstart, fallbackf, injectfallback, sectionname, preformat, postformat)
156
156
  for pointer in notfound:
157
157
  common.logError("Pointer", common.toHex(pointer.old), "->", common.toHex(pointer.new), "not found for string", pointer.str)
158
158
  if binfile.endswith(".txt"):
@@ -176,13 +176,17 @@ class BINSection:
176
176
  self.data = bytearray(ramlen)
177
177
 
178
178
 
179
- def expandBIN(binin, binout, headerin, headerout, newlength, injectpos):
179
+ def expandBIN(binin, binout, headerin, headerout, newlengths, injectpos):
180
180
  if not os.path.isfile(binin):
181
181
  common.logError("Input file", binin, "not found")
182
182
  return False
183
183
  if not os.path.isfile(headerin):
184
184
  common.logError("Header file", headerin, "not found")
185
185
  return False
186
+ if not isinstance(newlengths, list):
187
+ newlengths = [newlengths]
188
+ if not isinstance(injectpos, list):
189
+ injectpos = [injectpos]
186
190
  codesettings = -1
187
191
  with common.Stream(headerin, "rb") as fin:
188
192
  fin.seek(0x20)
@@ -225,13 +229,15 @@ def expandBIN(binin, binout, headerin, headerout, newlength, injectpos):
225
229
  sections.append(BINSection(fin, start, size, datastart, bsssize))
226
230
  datastart += size
227
231
  # Write the new extended arm9.bin
228
- sections.append(BINSection(None, injectpos, newlength, 0, 0))
232
+ for i in range(len(newlengths)):
233
+ sections.append(BINSection(None, injectpos[i], newlengths[i], 0, 0, True if i < len(newlengths) - 1 else False))
229
234
  with common.Stream(binout, "wb") as f:
230
235
  # Write the section data first
231
236
  f.write(sections[0].data)
232
237
  datastart = f.tell()
233
238
  for i in range(1, len(sections)):
234
239
  sections[i].offset = f.tell()
240
+ common.logDebug("Section", i, "offset:", common.toHex(f.tell()))
235
241
  f.write(sections[i].data)
236
242
  # Write the new copytable
237
243
  copytablestart = f.tell()
@@ -31,7 +31,7 @@ def extractIso(isofile, extractfolder, workfolder="", fixfilename=False):
31
31
  common.logMessage("Done!")
32
32
 
33
33
 
34
- def repackIso(isofile, isopatch, workfolder, patchfile=""):
34
+ def repackIso(isofile, isopatch, workfolder, patchfile="", fixfilename=False):
35
35
  try:
36
36
  import pycdlib
37
37
  except ImportError:
@@ -45,7 +45,7 @@ def repackIso(isofile, isopatch, workfolder, patchfile=""):
45
45
  for file in common.showProgress(files):
46
46
  filelen = os.path.getsize(workfolder + file)
47
47
  with open(workfolder + file, "rb") as f:
48
- iso.modify_file_in_place(f, filelen, "/" + file)
48
+ iso.modify_file_in_place(f, filelen, "/" + file + (";1" if fixfilename and not file.endswith(".") else ""))
49
49
  iso.close()
50
50
  common.logMessage("Done!")
51
51
  # Create xdelta patch
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hacktools
3
- Version: 0.33.1
3
+ Version: 0.35.0
4
4
  Summary: A set of utilities and tools for rom hacking and translations.
5
5
  Home-page: https://github.com/Illidanz/hacktools
6
6
  Author: Illidan
@@ -96,7 +96,7 @@ External dependencies not included are marked as `(through *dependency*)`
96
96
  ### Other / Generic
97
97
  - CPK archives
98
98
  - ARCH archives
99
- - LZ10, LZ11, Huffman and CRILAYLA compression/decompression
99
+ - LZ10, LZ11, Huffman, CRILAYLA and RACJIN compression/decompression
100
100
  - ARM/MIPS binary patching
101
101
  - xdelta patch creation
102
102
  - IPS patch creation
@@ -25,5 +25,6 @@ hacktools/assets/icon.png
25
25
  hacktools/c_ext/cmp_cri.c
26
26
  hacktools/c_ext/cmp_lzss.c
27
27
  hacktools/c_ext/cmp_misc.c
28
+ hacktools/c_ext/cmp_racjin.c
28
29
  hacktools/c_ext/inc.h
29
30
  tests/test_cmp.py
@@ -41,6 +41,7 @@ setup(
41
41
  Extension("hacktools.cmp_lzss", sources=["hacktools/c_ext/cmp_lzss.c"]),
42
42
  Extension("hacktools.cmp_cri", sources=["hacktools/c_ext/cmp_cri.c"]),
43
43
  Extension("hacktools.cmp_misc", sources=["hacktools/c_ext/cmp_misc.c"]),
44
+ Extension("hacktools.cmp_racjin", sources=["hacktools/c_ext/cmp_racjin.c"]),
44
45
  ],
45
46
  classifiers=[
46
47
  "Programming Language :: Python :: 3.7",
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
  import os.path
3
- from hacktools import cmp_lzss, cmp_cri
3
+ from hacktools import cmp_lzss, cmp_cri, cmp_racjin
4
4
 
5
5
  @pytest.fixture
6
6
  def data():
@@ -28,3 +28,10 @@ def test_cmp_cri(data):
28
28
  decmp = cmp_cri.decompressCRILAYLA(cmp)
29
29
  assert len(data) == len(decmp)
30
30
  assert data == decmp
31
+
32
+
33
+ def test_cmp_racjin(data):
34
+ cmp = cmp_racjin.compressRACJIN(data)
35
+ decmp = cmp_racjin.decompressRACJIN(cmp, len(data))
36
+ assert len(data) == len(decmp)
37
+ assert data == decmp
@@ -1 +0,0 @@
1
- __version__ = "0.33.1"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes