View difference between Paste ID: JZxXBCKW and GJNGa77L
SHOW: | | - or go back to the newest paste.
1
/*
2
 * Copyright © 2013 stag019 <stag019@gmail.com>
3
 *
4
 * Permission to use, copy, modify, and distribute this software for any
5
 * purpose with or without fee is hereby granted, provided that the above
6
 * copyright notice and this permission notice appear in all copies.
7
 *
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
 */
16
17
#include <stdlib.h>
18
#include <stdio.h>
19
#include <stdint.h>
20
#include <string.h>
21
22
uint8_t *compressed;
23
int xrows;
24
int xwidth;
25
int curbit;
26
int curbyte;
27
28
void writebit(int bit)
29
{
30
	if(++curbit == 8)
31
	{
32
		curbyte++;
33
		curbit = 0;
34
	}
35
	compressed[curbyte] |= bit << (7 - curbit);
36
}
37
38
void method_1(uint8_t *RAM)
39
{
40
	int i;
41
	int j;
42
	int nibble_1;
43
	int nibble_2;
44
	int code_1;
45
	int code_2;
46
	int table;
47
	static int method_1[2][0x10] = {{0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4, 0xC, 0xD, 0xF, 0xE, 0xA, 0xB, 0x9, 0x8}, {0x8, 0x9, 0xB, 0xA, 0xE, 0xF, 0xD, 0xC, 0x4, 0x5, 0x7, 0x6, 0x2, 0x3, 0x1, 0x0}};
48
49
	for(i = 0; i < xrows * xwidth * 8; i++)
50
	{
51
		j = i / xrows;
52
		j += i % xrows * xwidth * 8;
53
		if(!(i % xrows))
54
		{
55
			nibble_2 = 0;
56
		}
57
		nibble_1 = (RAM[j] >> 4) & 0x0F;
58
		table = 0;
59
		if(nibble_2 & 1)
60
		{
61
			table = 1;
62
		}
63
		code_1 = method_1[table][nibble_1];
64
		nibble_2 = RAM[j] & 0x0F;
65
		table = 0;
66
		if(nibble_1 & 1)
67
		{
68
			table = 1;
69
		}
70
		code_2 = method_1[table][nibble_2];
71
		RAM[j] = (code_1 << 4) | code_2;
72
	}
73
}
74
75
void RLE(int nums)
76
{
77
	int search;
78
	int i;
79
	int j;
80
	int bitcount;
81
	int number;
82
	static unsigned int RLE[0x10] = {0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
83
84
	bitcount = -1;
85
	search = ++nums;
86
	while(search > 0)
87
	{
88
		for(i = 0; i < 0xF; i++)
89
		{
90
			if(RLE[i] == search)
91
			{
92
				bitcount = i;
93
				break;
94
			}
95
		}
96
		if(bitcount != -1)
97
		{
98
			break;
99
		}
100
		search--;
101
	}
102
	number = nums - RLE[bitcount];
103
	for(j = 0; j < bitcount; j++)
104
	{
105
		writebit(1);
106
	}
107
	writebit(0);
108
	for(j = bitcount; j >= 0; j--)
109
	{
110
		writebit((number >> j) & 1);
111
	}
112
}
113
114
void data_packet(uint8_t *bitgroups, int bgi)
115
{
116
	int i;
117
	for(i = 0; i < bgi; i++)
118
	{
119
		writebit((bitgroups[i] >> 1) & 1);
120
		writebit(bitgroups[i] & 1);
121
	}
122
}
123
124
int interpret_compress(uint8_t *RAM_1, uint8_t *RAM_2, int interpretation, int switchram)
125
{
126
	uint8_t *_1_RAM;
127
	uint8_t *_2_RAM;
128
	int i;
129
	int ram;
130
	int type;
131
	int nums;
132
	uint8_t *bitgroups;
133
	int byte;
134
	int bit;
135
	int bitgroup;
136
	int bgi = 0;
137
138
	_1_RAM = (uint8_t*) calloc(0x188, 1);
139
	_2_RAM = (uint8_t*) calloc(0x188, 1);
140
	if(switchram)
141
	{
142
		memcpy(_1_RAM, RAM_2, 0x188);
143
		memcpy(_2_RAM, RAM_1, 0x188);
144
	}
145
	else
146
	{
147
		memcpy(_1_RAM, RAM_1, 0x188);
148
		memcpy(_2_RAM, RAM_2, 0x188);
149
	}
150
151
	switch(interpretation)
152
	{
153
		case 1:
154
			method_1(_1_RAM);
155
			method_1(_2_RAM);
156
		break;
157
		case 2:
158
		case 3:
159
			for(i = 0; i < xrows * xwidth * 8; i++)
160
			{
161
				_2_RAM[i] ^= _1_RAM[i];
162
			}
163
			method_1(_1_RAM);
164
		break;
165
	}
166
	if(interpretation == 3)
167
	{
168
		method_1(_2_RAM);
169
	}
170
171
	curbit = 7;
172
	curbyte = 0;
173
	compressed = (uint8_t*) calloc(0x310, 1);
174
	compressed[0] = (xrows << 4) | xwidth;
175
	writebit(switchram);
176
177
	for(ram = 0; ram < 2; ram++)
178
	{
179
		type = 0;
180
		nums = 0;
181
		bitgroups = (uint8_t*) calloc(0x1000, 1);
182
		for(i = 0; i < xrows * xwidth * 32; i++)
183
		{
184
			byte = i / (xwidth * 32);
185
			byte = byte * xwidth * 8 + i % (xwidth * 8);
186
			bit = i / (xwidth * 8);
187
			bit = (bit * 2) % 8;
188
			if(ram)
189
			{
190
				bitgroup = (_2_RAM[byte] >> (6 - bit)) & 3;
191
			}
192
			else
193
			{
194
				bitgroup = (_1_RAM[byte] >> (6 - bit)) & 3;
195
			}
196
			if(!bitgroup)
197
			{
198
				if(!type)
199
				{
200
					writebit(0);
201
				}
202
				else if(type == 1)
203
				{
204
					nums++;
205
				}
206
				else
207
				{
208
					data_packet(bitgroups, bgi);
209
					writebit(0);
210
					writebit(0);
211
				}
212
				type = 1;
213
				free(bitgroups);
214
				bitgroups = (uint8_t*) calloc(0x1000, 1);
215
				bgi = 0;
216
			}
217
			else
218
			{
219
				if(!type)
220
				{
221
					writebit(1);
222
				}
223
				else if(type == 1)
224
				{
225
					RLE(nums);
226
				}
227
				type = -1;
228
				bitgroups[bgi++] = bitgroup;
229
				nums = 0;
230
			}
231
		}
232
		if(type == 1)
233
		{
234
			RLE(nums);
235
		}
236
		else
237
		{
238
			data_packet(bitgroups, bgi);
239
		}
240
		if(!ram)
241
		{
242
			if(interpretation < 2)
243
			{
244
				writebit(0);
245
			}
246
			else
247
			{
248
				writebit(1);
249
				writebit(interpretation - 2);
250
			}
251
		}
252
	}
253
	free(bitgroups);
254
	free(_1_RAM);
255
	free(_2_RAM);
256
	return curbyte + 1;
257
}
258
259
int compress(uint8_t *data, int width, int height)
260
{
261
	uint8_t *RAM_1;
262
	uint8_t *RAM_2;
263
	int i;
264
	int newsize;
265
	int size = -1;
266
	uint8_t *current = NULL;
267
268
	xrows = height;
269
	xwidth = width;
270
271
	RAM_1 = (uint8_t*) calloc(0x188, 1);
272
	RAM_2 = (uint8_t*) calloc(0x188, 1);
273
274
	for(i = 0; i < xrows * xwidth * 8; i++)
275
	{
276
		RAM_1[i] = data[(i << 1)];
277
		RAM_2[i] = data[(i << 1) | 1];
278
	}
279
280
	for(i = 0; i < 6; i++)
281
	{
282
		newsize = interpret_compress(RAM_1, RAM_2, i / 2 + 1, i % 2);
283
		if(size == -1 || newsize < size)
284
		{
285
			if(current != NULL)
286
			{
287
				free(current);
288
			}
289
			current = (uint8_t*) calloc(0x310, 1);
290
			memcpy(current, compressed, newsize);
291
			free(compressed);
292
			size = newsize;
293
		}
294
	}
295
	compressed = (uint8_t*) calloc(0x310, 1);
296
	memcpy(compressed, current, size);
297-
	if(argc < 3)
297+
298
299-
		printf("Usage: pkmncompress infile.2bpp outfile.bin\n");
299+
300-
		/*fputs("Usage: pkmncompress infile.2bpp outfile.bin\n", stderr);*/
300+
301
302
	return size;
303
}
304
305
int main(int argc, char *argv[])
306
{
307
	FILE *f;
308
	int fz;
309
	int size;
310
	uint8_t *contents;
311
	int tiles;
312
	int *chloc;
313
	char outfile[256];
314
315
	if(argc < 2)
316
	{
317
		fputs("Usage: pkmncompress infile.2bpp [outfile.bin]\n", stderr);
318
		return EXIT_FAILURE;
319
	}
320
321
	if(argc == 2)
322
	{
323
		strcpy(outfile, argv[1]);
324
		if((chloc = (int *) strrchr(outfile, '.')) != NULL)
325
		{
326
			strcpy((char *) chloc, ".bin");
327
		}
328
		else
329
		{
330
			strcat(outfile, ".bin");
331
		}
332-
		printf("Error: wrong file size.\n");
332+
333-
		/*fputs("Error: wrong file size.\n", stderr);*/
333+
334
	{
335
		strcpy(outfile, argv[2]);
336
	}
337
338
	f = fopen(argv[1], "rb");
339
340
	if(!f)
341
	{
342
		perror("Opening file failed");
343
		return EXIT_FAILURE;
344
	}
345
346-
	f = fopen(argv[2], "wb");
346+
347
	fz = ftell(f);
348
	if(fz == 0x310)
349
	{
350
		tiles = 7;
351
	}
352
	else if(fz == 0x240)
353
	{
354
		tiles = 6;
355
	}
356
	else if(fz == 0x190)
357
	{
358
		tiles = 5;
359
	}
360
	else if(fz == 0x100)
361
	{
362
		tiles = 4;
363
	}
364
	else
365
	{
366
		fputs("Error: wrong file size.\n", stderr);
367
		return EXIT_FAILURE;
368
	}
369
370
	contents = (uint8_t*) calloc(0x310, 1);
371
	fseek(f, 0, SEEK_SET);
372
	fread(contents, 1, fz, f);
373
	fclose(f);
374
375
	size = compress(contents, tiles, tiles);
376
377
	free(contents);
378
379
	f = fopen(outfile, "wb");
380
	fwrite(compressed, 1, size, f);
381
382
	free(compressed);
383
384
	printf("Success! File size: %i bytes\n", size);
385
386
	return EXIT_SUCCESS;
387
}