#include <stdio.h>
#include <stdint.h>

#include "../h/rgblde.h"

int main(int argc, char **argv)
{
	int i, j, k, o, oo;
	int h = open("loader", 0);
	if (h < 0)
		return 2;
	int l = lseek(h, 0, 2);
	lseek(h, 0, 0);
	unsigned char loader[l + 4];
	bzero(loader, l + 4);
	if (read(h, loader, l) != l)
		return 2;
	puts("void mk_data(uint8_t *loader, uint8_t *length)\n{");

	/* get length */
	char length[l];
	bzero(length, l);
	for (k = 0, i = 0; i < l; ) {
		if ((j = RGBLDE(loader + i)) == 0)
			return 2;
		if (loader[i] == 0x68 && *(uint32_t*)(loader + i + 1) == 0) {
			o = k;
			oo = i + 1;
		}
		length[k / 2] |= k % 2 == 0 ? j << 4 : j;
		k++;
		i += j;
	}
	fprintf(stderr, "#define	PATCH_OFFSET	%d\n", oo);
	fprintf(stderr, "#define	NCMDS	%d\t/* number of commands */\n", k);
	fprintf(stderr, "#define	PATCH	%d\t/* number of command to patch offset */\n", o);
	fprintf(stderr, "#define	CSIZE	%d\t/* size of code (bytes) */\n", l);
	k = (k + 1) >> 1;
	fprintf(stderr, "#define	LSIZE	%d\t/*size of insns lengths array (bytes) */\n", k);

	FILE *f1, *f2;
	f1 = fopen("loader1.c", "w+");
	f2 = fopen("loader2.c", "w+");
	if (f1 == NULL || f2 == NULL)
		return 2;
	/* dump code */
	for (i = 0; i < (l + 3) / 4; i++) {
		printf("\t*(uint32_t*)(loader + 0x%02x) = 0x%08x;\n", i << 2, *((uint32_t*)loader + i));
		fprintf(f1, "\t*(uint32_t*)(loader + 0x%02x) = 0x%08x;\n", i << 2, *((uint32_t*)loader + i));
	}
	for (i = 0; i < k / 4; i++) {
		printf("\t*(uint32_t*)(length + 0x%02x) = 0x%08x;\n", i << 2, *((uint32_t*)length + i));	
		fprintf(f2, "\t*(uint32_t*)(length + 0x%02x) = 0x%08x;\n", i << 2, *((uint32_t*)length + i));	
	}
	switch (k % 4) {
		case 0:
			break;
		case 1:
			printf("\t*(uint8_t *)(length + 0x%02x) = 0x%02x;\n", i << 2, *((uint8_t*)length + i * 4));
			fprintf(f2, "\t*(uint8_t *)(length + 0x%02x) = 0x%02x;\n", i << 2, *((uint8_t*)length + i * 4));
			break;
		case 2:
			printf("\t*(uint16_t*)(length + 0x%02x) = 0x%04x;\n", i << 2, *((uint16_t*)length + i * 2));
			fprintf(f2, "\t*(uint16_t*)(length + 0x%02x) = 0x%04x;\n", i << 2, *((uint16_t*)length + i * 2));
			break;
		case 3:
			printf("\t*(uint32_t*)(length + 0x%02x) = 0x%08x;\n", i << 2, *((uint32_t*)length + i));	
			fprintf(f2, "\t*(uint32_t*)(length + 0x%02x) = 0x%08x;\n", i << 2, *((uint32_t*)length + i));	
	}
	puts("}");
	fclose(f1);
	fclose(f2);
	return 0;
}
