mirror of
https://github.com/Hunter-Raff/e-ReaderCardCreator.git
synced 2026-08-29 08:26:12 +01:00
Add project files.
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void exitTool()
|
||||
{
|
||||
printf("\n\nPress ENTER to exit...");
|
||||
while(1)
|
||||
{
|
||||
if (getchar())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short getDataChecksum(unsigned char *data, int dataSize)
|
||||
{
|
||||
unsigned short i, sum = 0;
|
||||
|
||||
for(i = 0; i < dataSize; i+=2)
|
||||
{
|
||||
sum += ((data[i] << 8) + data[i + 1]);
|
||||
}
|
||||
|
||||
return ~sum & 0xFFFF;
|
||||
}
|
||||
|
||||
unsigned char getHeaderChecksum(unsigned char *header)
|
||||
{
|
||||
unsigned short i, xor = 0;
|
||||
|
||||
xor ^= header[0xC];
|
||||
xor ^= header[0xD];
|
||||
xor ^= header[0x10];
|
||||
xor ^= header[0x11];
|
||||
for(i = 0x26; i < 0x2D; i++)
|
||||
{
|
||||
xor ^= header[i];
|
||||
}
|
||||
return xor & 0xFF;
|
||||
}
|
||||
|
||||
unsigned char getGlobalChecksum(unsigned char *header, unsigned char *data, int dataSize)
|
||||
{
|
||||
short i, j, sum = 0, xor = 0;
|
||||
|
||||
for(i = 0; i < 0x2F; i++)
|
||||
{
|
||||
sum += header[i];
|
||||
}
|
||||
|
||||
for(i = 0; i < dataSize/0x30; i++)
|
||||
{
|
||||
xor = 0;
|
||||
for(j = 0; j < 0x30; j++)
|
||||
{
|
||||
xor ^= data[(i * 0x30) + j];
|
||||
}
|
||||
sum += xor;
|
||||
}
|
||||
return ~sum & 0xFF;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FILE *card;
|
||||
unsigned char *data, *header;
|
||||
int headerSize = 0x30, cardSize = 0, dataSize = 0;
|
||||
|
||||
printf("e-Card Headerfix - fixes the header of decoded e-Cards\n");
|
||||
|
||||
if(argc != 2)
|
||||
{
|
||||
printf("\ndrop a decoded e-Card onto the exe\n");
|
||||
exitTool();
|
||||
return 0;
|
||||
}
|
||||
|
||||
card = fopen(argv[1], "rb+");
|
||||
if(!card)
|
||||
{
|
||||
printf("\ne-Card loading failed!\n");
|
||||
exitTool();
|
||||
return 0;
|
||||
}
|
||||
|
||||
fseek(card, 0, SEEK_END);
|
||||
cardSize = ftell(card);
|
||||
rewind(card);
|
||||
|
||||
if(cardSize % 0x30 != 0 || cardSize <= 0x30)
|
||||
{
|
||||
printf("\nInvalid card size!\n");
|
||||
exitTool();
|
||||
return 0;
|
||||
}
|
||||
|
||||
header = (unsigned char*)malloc(headerSize);
|
||||
if(header == NULL)
|
||||
{
|
||||
printf("\nMemory allocation error!\n");
|
||||
exitTool();
|
||||
return 0;
|
||||
}
|
||||
fread(header, 1, headerSize, card);
|
||||
rewind(card);
|
||||
|
||||
unsigned char signature[8] = {0x4E, 0x49, 0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F}; // NINTENDO
|
||||
int x;
|
||||
for(x = 0; x < 8; x++)
|
||||
{
|
||||
if(header[0x1A + x] != signature[x])
|
||||
{
|
||||
printf("\nInvalid e-Card signature!\n");
|
||||
exitTool();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dataSize = (header[0x06] << 8) + header[0x07];
|
||||
|
||||
data = (unsigned char*)malloc(dataSize);
|
||||
if(data == NULL)
|
||||
{
|
||||
printf("\nMemory allocation error!\n");
|
||||
exitTool();
|
||||
return 0;
|
||||
}
|
||||
fseek(card, 0x30, SEEK_SET);
|
||||
fread(data, 1, dataSize, card);
|
||||
rewind(card);
|
||||
|
||||
unsigned short dataChecksum = getDataChecksum(data, dataSize);
|
||||
header[0x13] = (unsigned char)(dataChecksum >> 8);
|
||||
header[0x14] = (unsigned char)(dataChecksum & 0xFF);
|
||||
|
||||
unsigned char headerChecksum = getHeaderChecksum(header);
|
||||
header[0x2E] = (unsigned char)headerChecksum;
|
||||
|
||||
unsigned char globalChecksum = getGlobalChecksum(header, data, dataSize);
|
||||
header[0x2F] = (unsigned char)globalChecksum;
|
||||
|
||||
fwrite(header, 1, headerSize, card);
|
||||
|
||||
free(data);
|
||||
free(header);
|
||||
fclose(card);
|
||||
|
||||
printf("\nChecksums updated!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
// nedcenc.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../nedclib/nedclib.h"
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int i,j,k,temp,hexinput;
|
||||
|
||||
int encode=0,decode=0,fix=0;
|
||||
int infile=0,outfile=0;
|
||||
|
||||
printf("Nintendo eReader Dotcode encoder/decoder v%d.%d\n",NEDCENC_MAJOR,NEDCENC_MINOR);
|
||||
printf("Copyright 2007 CaitSith2\n\n");
|
||||
nedclib_version();
|
||||
|
||||
if(argc<3)
|
||||
{
|
||||
printf("Usage: %s [options] [-i] infile [[-o] outfile]\n\n",argv[0]);
|
||||
printf("[options]\n");
|
||||
printf("\t-i\tIn file (required)\n");
|
||||
printf("\t-o\tOut file (required)\n");
|
||||
|
||||
printf("\t-e\tEncode bin 2 raw, Outfile required (Default operation)\n");
|
||||
printf("\t-d\tDecode raw 2 bin. Outfile required\n");
|
||||
printf("\t-f\tRepair raw file\n");
|
||||
printf("\t-s\tDot code signature (encoding only)\n\t\t< - Input hex.\n\t\t<< - ");
|
||||
printf("Input <\n\t\t> - If inputting hex, end hex input, otherwise input >");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(i=1;i<argc;i++)
|
||||
{
|
||||
if(argv[i][0]!='-')
|
||||
continue;
|
||||
switch(argv[i][1])
|
||||
{
|
||||
case 'e':
|
||||
encode=1;
|
||||
break;
|
||||
case 'd':
|
||||
decode=1;
|
||||
break;
|
||||
case 'f':
|
||||
fix=1;
|
||||
break;
|
||||
case 's':
|
||||
signature=i+1;
|
||||
i++;
|
||||
break;
|
||||
case 'i':
|
||||
infile=i+1;
|
||||
i++;
|
||||
break;
|
||||
case 'o':
|
||||
outfile=i+1;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if((encode+decode+fix)==0)
|
||||
{
|
||||
encode=1;
|
||||
}
|
||||
if((encode+decode+fix)>1)
|
||||
{
|
||||
printf("You cannot specify more than one operation\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(signature)
|
||||
{
|
||||
i=0;
|
||||
j=0;
|
||||
k=0;
|
||||
temp=0;
|
||||
hexinput=0;
|
||||
while((argv[signature][i])&&(j<0x2C))
|
||||
{
|
||||
switch(argv[signature][i])
|
||||
{
|
||||
case '<':
|
||||
if(hexinput)
|
||||
{
|
||||
hexinput = 0;
|
||||
signature_str[j++]=argv[signature][i];
|
||||
break;
|
||||
}
|
||||
hexinput=1;
|
||||
break;
|
||||
case '>':
|
||||
if(hexinput)
|
||||
{
|
||||
hexinput = 0;
|
||||
break;
|
||||
}
|
||||
signature_str[j++]=argv[signature][i];
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if(hexinput)
|
||||
{
|
||||
if(k)
|
||||
{
|
||||
temp += (argv[signature][i]-'0');
|
||||
signature_str[j++] = temp;
|
||||
k=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = ((argv[signature][i]-'0')<<4);
|
||||
k++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
signature_str[j++]=argv[signature][i];
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
if(hexinput)
|
||||
{
|
||||
if(k)
|
||||
{
|
||||
temp += (argv[signature][i]-'a')+10;
|
||||
signature_str[j++] = temp;
|
||||
k=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = (((argv[signature][i]-'a')+10)<<4);
|
||||
k++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
signature_str[j++]=argv[signature][i];
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
if(hexinput)
|
||||
{
|
||||
if(k)
|
||||
{
|
||||
temp += (argv[signature][i]-'A')+10;
|
||||
signature_str[j++] = temp;
|
||||
k=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = (((argv[signature][i]-'A')+10)<<4);
|
||||
k++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
signature_str[j++]=argv[signature][i];
|
||||
break;
|
||||
default:
|
||||
if(hexinput)
|
||||
break;
|
||||
signature_str[j++]=argv[signature][i];
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(encode)
|
||||
i=bin2raw(argv[infile],argv[outfile]);
|
||||
if(decode)
|
||||
i=raw2bin(argv[infile],argv[outfile]);
|
||||
if(fix)
|
||||
i=fixraw(argv[infile]);
|
||||
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
if(encode)
|
||||
printf("bin successfully encoded to raw\n");
|
||||
if(decode)
|
||||
printf("raw successfully decoded to bin\n");
|
||||
if(fix)
|
||||
printf("dotcode raw successfully repaired\n");
|
||||
break;
|
||||
case -1:
|
||||
printf("Unable to open input file %s\n",argv[infile]);
|
||||
break;
|
||||
case -2:
|
||||
if(encode)
|
||||
printf("Invalid bin file\n");
|
||||
if(decode)
|
||||
printf("Invalid raw file\n");
|
||||
if(fix)
|
||||
printf("Invalid raw file\n");
|
||||
break;
|
||||
case -3:
|
||||
if(encode)
|
||||
printf("Unable to encode bin file to raw\n");
|
||||
if(decode)
|
||||
printf("Unable to decode raw file to bin\n");
|
||||
if(fix)
|
||||
printf("Unable to repair raw file\n");
|
||||
break;
|
||||
case -4:
|
||||
printf("Unable to open output file %s\n",argv[outfile]);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown error\n");
|
||||
}
|
||||
if(i!=0)
|
||||
return i;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../nedclib/nedclib.h"
|
||||
|
||||
|
||||
// If compiling on VS 2005, comment out fopen_s and vsprintf_s completely.
|
||||
// It was easier to rewrite these fuctions rather than rewrite the code
|
||||
// to be compilable on older VS versions.
|
||||
|
||||
//int fopen_s(FILE ** f, char *name, char *spec)
|
||||
//{
|
||||
// if(f==NULL)
|
||||
// return 1;
|
||||
// *f=fopen(name,spec);
|
||||
// if(*f==NULL)
|
||||
// return 1;
|
||||
// else
|
||||
// return 0;
|
||||
//
|
||||
//}
|
||||
//
|
||||
//int vsprintf_s(char *string, int sizeinbytes, const char *format, va_list ap)
|
||||
//{
|
||||
//
|
||||
// vsprintf(string,format,ap);
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf("usage :\n");
|
||||
printf(" nvpktool [options]\n");
|
||||
printf("options :\n");
|
||||
printf(" -i <file> input file (Required)\n");
|
||||
printf(" -o <file> output file (Required)\n");
|
||||
printf(" -v verbose (Optional)\n");
|
||||
printf(" -c compress (Required *)\n");
|
||||
printf(" -d decompress (Required *)\n");
|
||||
printf(" -level <value> compression level (0=store 1=med 2=max (Default = 2)\n");
|
||||
printf(" 3 = Discover best lzwindow/lzsize/method)\n");
|
||||
printf(" -log <file> Decompression log (Default = none)\n");
|
||||
printf(" (following options are only valid for compression levels 1 & 2)\n");
|
||||
printf(" -method <value> compression method (0 or 1) (Default = 0)\n");
|
||||
printf(" -lzwindow <value> lz window size (Default = 4096)\n");
|
||||
printf(" -lzsize <value> lz max repeat size (Default = 256)\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int i,j,k;
|
||||
unsigned char *vpk_buf;
|
||||
FILE *f;
|
||||
|
||||
int file_in=0;
|
||||
int file_out=0;
|
||||
int operation=0;
|
||||
int level=2;
|
||||
int method=0;
|
||||
int lzwindow=4096;
|
||||
int lzsize=256;
|
||||
unsigned long bitsize = 0xFFFFFFFF;
|
||||
|
||||
printf("Nintendo e-Reader VPK Tool Version %d.%d\n",NEVPK_MAJOR,NEVPK_MINOR);
|
||||
printf("Copyright CaitSith2\n\n");
|
||||
nedclib_version();
|
||||
|
||||
if(argc==1)
|
||||
{
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(i=1;i<argc;i++)
|
||||
{
|
||||
if(!_stricmp(argv[i],"-i"))
|
||||
{
|
||||
i++;
|
||||
file_in=i;
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-o"))
|
||||
{
|
||||
i++;
|
||||
file_out=i;
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-c"))
|
||||
{
|
||||
if(operation == 2)
|
||||
{
|
||||
printf("You cannot use -c and -d at the same time\n");
|
||||
return 1;
|
||||
}
|
||||
operation = 1;
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-d"))
|
||||
{
|
||||
if(operation == 1)
|
||||
{
|
||||
printf("You cannot use -c and -d at the same time\n");
|
||||
return 1;
|
||||
}
|
||||
operation = 2;
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-level"))
|
||||
{
|
||||
level=strtoul(argv[++i],0,0);
|
||||
if(level>3)
|
||||
{
|
||||
printf("Max compression level is 3\n");
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-method"))
|
||||
{
|
||||
method=strtoul(argv[++i],0,0);
|
||||
if(method>1)
|
||||
{
|
||||
printf("Invalid compression method\n");
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-lzwindow"))
|
||||
{
|
||||
lzwindow=strtoul(argv[++i],0,0);
|
||||
/*if(lzwindow > 32768)
|
||||
{
|
||||
printf("Max lz window is 32768\n");
|
||||
return 1;
|
||||
}*/
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-lzsize"))
|
||||
{
|
||||
lzsize=strtoul(argv[++i],0,0);
|
||||
/*if(lzsize> 32768)
|
||||
{
|
||||
printf("Max lz size is 32768\n");
|
||||
return 1;
|
||||
}*/
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-verbose"))
|
||||
{
|
||||
verbose = 1;
|
||||
}
|
||||
|
||||
if(!_stricmp(argv[i],"-log"))
|
||||
{
|
||||
i++;
|
||||
if(fopen_s(&log,argv[i],"w")!=0)
|
||||
{
|
||||
printf("Failed to open log file\n");
|
||||
log=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(file_in == 0)
|
||||
{
|
||||
printf("Required parameter -i missing\n");
|
||||
return 1;
|
||||
}
|
||||
if(file_out == 0)
|
||||
{
|
||||
printf("Required parameter -o missing\n");
|
||||
return 1;
|
||||
}
|
||||
if(operation==0)
|
||||
{
|
||||
printf("-c or -d (not both) required\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
in=stream_open(argv[file_in],"rb");
|
||||
out=stream_open(argv[file_out],"wb");
|
||||
stream_seek(in,0,SEEK_END);
|
||||
i=stream_tell(in);
|
||||
stream_seek(in,0,SEEK_SET);
|
||||
lz77_encode(out,in,i,9);
|
||||
stream_close(in);
|
||||
stream_close(out);
|
||||
in=stream_open(argv[file_out],"rb");
|
||||
out=stream_open(argv[file_in],"wb");
|
||||
stream_seek(in,0,SEEK_END);
|
||||
i=stream_tell(in);
|
||||
stream_seek(in,0,SEEK_SET);
|
||||
lz77_decode(out,in,i);
|
||||
stream_close(in);
|
||||
stream_close(out);
|
||||
*/
|
||||
//return 0;
|
||||
|
||||
log_write("Input file: %s\n",argv[file_in]);
|
||||
log_write("Output file: %s\n",argv[file_out]);
|
||||
log_write("Operation: %s\n",(operation==1)?"Compress":"Decompress");
|
||||
if(operation == 1)
|
||||
{
|
||||
log_write("Compression Level: %d\n",level);
|
||||
if(level > 0)
|
||||
{
|
||||
if(level != 3)
|
||||
{
|
||||
log_write("Compression Method: %d\n",method);
|
||||
log_write("LZ Window: %d\n",lzwindow);
|
||||
log_write("LZ Size: %d\n",lzsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
log_write("\n");
|
||||
|
||||
|
||||
//f=;
|
||||
if(fopen_s(&f,argv[file_in],"rb")!=0)
|
||||
{
|
||||
printf("Unable to open input file %s\n",argv[file_in]);
|
||||
return 1;
|
||||
}
|
||||
fseek(f,0,SEEK_END);
|
||||
i = ftell(f);
|
||||
fseek(f,0,SEEK_SET);
|
||||
vpk_buf = (unsigned char *)malloc(i);
|
||||
if(vpk_buf==NULL)
|
||||
{
|
||||
printf("Not enough memory to allocate compression buffer\n");
|
||||
return 1;
|
||||
}
|
||||
fread(vpk_buf,1,i,f);
|
||||
fclose(f);
|
||||
//f=;
|
||||
|
||||
int b_move = 0;
|
||||
int b_size = 0;
|
||||
|
||||
if(operation == 1)
|
||||
{
|
||||
if(level==3)
|
||||
{
|
||||
int result;
|
||||
for(j=16;j<65536;j<<=1)
|
||||
{
|
||||
for(k=16;k<65536;k<<=1)
|
||||
{
|
||||
//best_move=0x80000000;
|
||||
//best_size=0x80000000;
|
||||
//skip_huffman=1;
|
||||
/*for(l=1;l<(65536*2);l+=2)
|
||||
{
|
||||
if((l>j)&&(l<65536))
|
||||
{
|
||||
l=65535;
|
||||
continue;
|
||||
}
|
||||
if((l>(65536+k)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(l==65536) continue;
|
||||
if(l<65536)
|
||||
{
|
||||
best_move = l;
|
||||
best_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
best_move = b_move;
|
||||
best_size = l - 65536;
|
||||
}*/
|
||||
printf("Filesize: %d, lzwindow: %d, lzsize: %d ",((bitsize==0xFFFFFFFF)?0:bitsize/8),k,j);
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
result=NVPK_compress(vpk_buf,i,level,k,j,method,NULL);
|
||||
if(result==0)
|
||||
{
|
||||
if(bitsize>bits_written)
|
||||
{
|
||||
lzwindow=k;
|
||||
lzsize=j;
|
||||
bitsize=bits_written;
|
||||
b_move=best_move;
|
||||
b_size=best_size;
|
||||
}
|
||||
}
|
||||
else if (result==3) //Window size is invalid, break out of the
|
||||
{ //Size loop, and try next window size.
|
||||
break;
|
||||
}
|
||||
else if (result==4) //Repeat size is invalid, try next repeat size.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (result==2) //Buffer overrun error. (Data execution prevention)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
if(bitsize==0xFFFFFFFF)
|
||||
{
|
||||
printf("Compression failed\n");
|
||||
return 1;
|
||||
}
|
||||
skip_huffman=0;
|
||||
NVPK_compress(vpk_buf,i,level,lzwindow,lzsize,method,NULL);
|
||||
|
||||
if(bitsize>bits_written)
|
||||
{
|
||||
bitsize=bits_written;
|
||||
}
|
||||
|
||||
//skip_size=1;
|
||||
skip_lz77=1;
|
||||
for(j=1;j<lzwindow;j+=2)
|
||||
{
|
||||
for(k=1;k<lzsize;k+=2)
|
||||
{
|
||||
printf("Filesize: %d, %d, %d ",((bitsize==0xFFFFFFFF)?0:bitsize/8),(lzwindow-1-j),(lzsize-1-k));
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
best_move=j;
|
||||
best_size=k;
|
||||
result=NVPK_compress(vpk_buf,i,level,lzwindow,lzsize,method,NULL);
|
||||
if(result==0)
|
||||
{
|
||||
if(bitsize>bits_written)
|
||||
{
|
||||
b_size=best_size;
|
||||
b_move=best_move;
|
||||
bitsize=bits_written;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*best_move=b_move;
|
||||
skip_size=0;
|
||||
for(j=1;j<lzsize;j++)
|
||||
{
|
||||
printf("Filesize: %d, %d ",((bitsize==0xFFFFFFFF)?0:bitsize/8),(lzsize-1-j));
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
best_size=j;
|
||||
result=NVPK_compress(vpk_buf,i,level,lzwindow,lzsize,method,NULL);
|
||||
if(result==0)
|
||||
{
|
||||
if(bitsize>bits_written)
|
||||
{
|
||||
b_size=best_size;
|
||||
bitsize=bits_written;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
best_size=b_size;
|
||||
best_move=b_move;
|
||||
best_size=b_size;
|
||||
log_write("Compression Method: %d\n",method);
|
||||
log_write("LZ Window: %d\n",lzwindow);
|
||||
log_write("LZ Size: %d\n",lzsize);
|
||||
}
|
||||
if(fopen_s(&f,argv[file_out],"wb")!=0)
|
||||
{
|
||||
printf("Unable to open output file %s\n",argv[file_out]);
|
||||
return 1;
|
||||
}
|
||||
i=NVPK_compress(vpk_buf,i,level,lzwindow,lzsize,method,f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fopen_s(&f,argv[file_out],"wb")!=0)
|
||||
{
|
||||
printf("Unable to open output file %s\n",argv[file_out]);
|
||||
return 1;
|
||||
}
|
||||
i=vpk_decompress(vpk_buf,f);
|
||||
}
|
||||
fclose(f);
|
||||
if(log!=NULL)
|
||||
fclose(log);
|
||||
|
||||
j=i;
|
||||
|
||||
free(vpk_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// raw2bmp.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "../nedclib/nedclib.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int InFileList[256],OutFileList[256];
|
||||
|
||||
void usage (void)
|
||||
{
|
||||
printf("Usage :\n DcsTool [options]\n");
|
||||
printf("Options :\n");
|
||||
printf(" -i <file>\t\tInput File\t\t\t(Required)\n");
|
||||
printf(" -o <file>\t\tOutput File\t\t\t(Required)\n");
|
||||
printf(" -dpi <dpi>\t\tDPI Setting\t\t\t(Optional, Default 300)\n");
|
||||
printf(" -MultiStrip\t\tMultistrip raw file mode\t\t(Optional)\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int i,j;
|
||||
int OptI=0;
|
||||
int OptO=0;
|
||||
int OptD=0;
|
||||
int OptR=0;
|
||||
|
||||
printf("Nintendo e-Reader dotcode strip tool Version %d.%d\n",RAW2BMP_MAJOR,RAW2BMP_MINOR);
|
||||
printf("Copyrighted by CaitSith2\n\n");
|
||||
nedclib_version();
|
||||
|
||||
for (i=1;i<argc;i++)
|
||||
{
|
||||
if(!_stricmp(argv[i],"-i"))
|
||||
{
|
||||
if((i+1)==argc) continue;
|
||||
i++;
|
||||
while(argv[i][0] != '-')
|
||||
{
|
||||
InFileList[OptI++] = i;
|
||||
i++;
|
||||
if((i)==argc) break;
|
||||
}
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-o"))
|
||||
{
|
||||
if((i+1)==argc) continue;
|
||||
i++;
|
||||
while(argv[i][0] != '-')
|
||||
{
|
||||
OutFileList[OptO++] = i;
|
||||
i++;
|
||||
if((i)==argc) break;
|
||||
}
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-dpi"))
|
||||
{
|
||||
if((i+1)==argc) continue;
|
||||
i++;
|
||||
switch(atoi(argv[i]))
|
||||
{
|
||||
case 300:
|
||||
case 360:
|
||||
default:
|
||||
dpi_multiplier = 1;
|
||||
break;
|
||||
case 600:
|
||||
case 720:
|
||||
dpi_multiplier = 2;
|
||||
break;
|
||||
case 1200:
|
||||
case 1440:
|
||||
dpi_multiplier = 4;
|
||||
break;
|
||||
case 2400:
|
||||
case 2880:
|
||||
dpi_multiplier = 8;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-multistrip"))
|
||||
{
|
||||
MultiStrip = 1;
|
||||
continue;
|
||||
}
|
||||
if(!_stricmp(argv[i],"-smooth"))
|
||||
{
|
||||
smooth = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if((OptI < 1) || (OptO < 1) || ((OptI != OptO) && (MultiStrip == 0)))
|
||||
{
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(i=0,j=0;(i<OptI)&&(j<OptO);i++)
|
||||
{
|
||||
if(is_bmp(argv[InFileList[i]]))
|
||||
{
|
||||
if(MultiStrip)
|
||||
if(is_bmp(argv[OutFileList[j]]))
|
||||
{
|
||||
i--;
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
if((i==0)&&(MultiStrip))
|
||||
{
|
||||
MultiStrip = 0;
|
||||
if(bmp2raw(argv[InFileList[i]],argv[OutFileList[j]]))
|
||||
{
|
||||
printf("Error converting %s to %s\n",argv[InFileList[i]],argv[OutFileList[j]]);
|
||||
}
|
||||
MultiStrip = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bmp2raw(argv[InFileList[i]],argv[OutFileList[j]]))
|
||||
{
|
||||
printf("Error converting %s to %s\n",argv[InFileList[i]],argv[OutFileList[j]]);
|
||||
}
|
||||
}
|
||||
if(!MultiStrip)
|
||||
j++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MultiStrip)
|
||||
j++;
|
||||
if(raw2bmp(argv[InFileList[i]],argv[OutFileList[j]]))
|
||||
{
|
||||
printf("Error converting %s to %s\n",argv[InFileList[i]],argv[OutFileList[j]]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,279 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using AC_e_Reader_Card_Creator.References;
|
||||
|
||||
namespace AC_e_Reader_Card_Creator.Decompression.Functions
|
||||
{
|
||||
internal class Compress
|
||||
{
|
||||
public static void DECtoVPK(string greeting, string body, string closing, string stationery, string sender, string gift)
|
||||
{
|
||||
string new_greeting = greeting;
|
||||
int player_index = greeting.IndexOf("<Player>");
|
||||
|
||||
if(player_index != -1)
|
||||
{
|
||||
new_greeting = greeting.Substring(0, player_index) + greeting.Substring(player_index + 8);
|
||||
}
|
||||
|
||||
new_greeting = ACAsciiToBytes(new_greeting.PadRight(24, ' '));
|
||||
|
||||
string new_body = body.Replace('\r'.ToString(), "").PadRight(192, ' ');
|
||||
new_body = ACAsciiToBytes(new_body);
|
||||
|
||||
// should only be true if letter uses special characters
|
||||
if(new_body.Length < 384)
|
||||
{
|
||||
while(new_body.Length < 384)
|
||||
{
|
||||
new_body += "20";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// failsafe -- if programmed correctly, this should never run
|
||||
new_body = new_body.Substring(0, 384);
|
||||
}
|
||||
|
||||
string new_closing = closing.PadRight(31, ' ');
|
||||
new_closing = ACAsciiToBytes(new_closing);
|
||||
|
||||
Dictionary<string, string> StationeryMappings = ReadMappings(Common.STATIONERY_LIST);
|
||||
string new_stationery = StationeryMappings[stationery].Substring(2);
|
||||
|
||||
Dictionary<string, string> SenderMappings = ReadMappings(Common.SENDER_LIST);
|
||||
string new_sender = SenderMappings[sender].Substring(2);
|
||||
|
||||
string final = player_index.ToString("X2") + Random2ByteHex();
|
||||
|
||||
string bytesToWrite = new_greeting + new_body + new_closing + new_stationery + gift + new_sender + final;
|
||||
|
||||
byte[] body_bytes = HexStringToByteArray(bytesToWrite);
|
||||
string filePath = Common.DECOMPRESSED_GCN;
|
||||
File.WriteAllBytes(filePath, body_bytes);
|
||||
|
||||
ProcessStartInfo dec_to_vpk = new ProcessStartInfo
|
||||
{
|
||||
FileName = Common.NEVPK,
|
||||
Arguments = Common.NEVPK_ARGS_COMP(Common.DECOMPRESSED_GCN),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using (Process process = Process.Start(dec_to_vpk)) { process.WaitForExit(); }
|
||||
|
||||
FixVPKChecksums();
|
||||
}
|
||||
|
||||
private static string Random2ByteHex()
|
||||
{
|
||||
Random random = new Random();
|
||||
int randomNumber = random.Next(0, 130);
|
||||
return randomNumber.ToString("X4");
|
||||
}
|
||||
|
||||
public static void VPKtoBIN()
|
||||
{
|
||||
if (File.Exists(Common.COMPRESSED_BIN))
|
||||
{
|
||||
File.Delete(Common.COMPRESSED_BIN);
|
||||
}
|
||||
|
||||
string[] VPKfiles = { Common.VPK_HEADER, Common.VPK_GBA, Common.VPK_GCN };
|
||||
|
||||
using (FileStream NewBIN = new FileStream(Common.COMPRESSED_BIN, FileMode.CreateNew))
|
||||
{
|
||||
foreach (var sourceFile in VPKfiles)
|
||||
{
|
||||
byte[] fileContent = File.ReadAllBytes(sourceFile);
|
||||
NewBIN.Write(fileContent, 0, fileContent.Length);
|
||||
}
|
||||
|
||||
long currentBINSize = NewBIN.Length;
|
||||
long paddingSize = 2112 - currentBINSize;
|
||||
|
||||
if (paddingSize > 0)
|
||||
{
|
||||
NewBIN.Seek(0, SeekOrigin.End);
|
||||
|
||||
// creating a padding buffer of 0x00 bytes to fill 2112 bytes
|
||||
byte[] padding = new byte[paddingSize];
|
||||
NewBIN.Write(padding, 0, padding.Length);
|
||||
}
|
||||
}
|
||||
|
||||
ProcessStartInfo fix_header_checksums = new ProcessStartInfo(Common.HEADERFIX, $"\"{Common.COMPRESSED_BIN}\"")
|
||||
{
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using (Process process = Process.Start(fix_header_checksums)) { process.WaitForExit(); }
|
||||
}
|
||||
|
||||
public static void BINtoRAW(bool custom)
|
||||
{
|
||||
if (custom)
|
||||
{
|
||||
SaveFileDialog saveRAWFile = new SaveFileDialog
|
||||
{
|
||||
Filter = "RAW files (*.raw)|*.raw",
|
||||
Title = "Save .RAW",
|
||||
FileName = "My-Custom-eCard.raw"
|
||||
};
|
||||
if (saveRAWFile.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
ProcessStartInfo bin_to_raw = new ProcessStartInfo
|
||||
{
|
||||
FileName = Common.NEDCENC,
|
||||
Arguments = Common.NEDCENC_ARGS_COMP(saveRAWFile.FileName),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using (Process process = Process.Start(bin_to_raw)) { process.WaitForExit(); }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessStartInfo bin_to_raw = new ProcessStartInfo
|
||||
{
|
||||
FileName = Common.NEDCENC,
|
||||
Arguments = Common.NEDCENC_ARGS_COMP(Common.RAW_ECARD),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
using (Process process = Process.Start(bin_to_raw)) { process.WaitForExit(); }
|
||||
}
|
||||
}
|
||||
|
||||
static Dictionary<string, string> ReadMappings(string filePath)
|
||||
{
|
||||
var map = new Dictionary<string, string>();
|
||||
foreach (var line in File.ReadAllLines(filePath))
|
||||
{
|
||||
var parts = line.Split(',');
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
string hexKey = parts[0].Trim();
|
||||
string value = parts[1].Trim().Trim('\'');
|
||||
map[value] = hexKey;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static void FixVPKChecksums()
|
||||
{
|
||||
try
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(Common.VPK_GCN);
|
||||
long GCN_VPK_Length = 0;
|
||||
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
GCN_VPK_Length = fileInfo.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("ERROR: Failed to fetch GCN VPK");
|
||||
return;
|
||||
}
|
||||
|
||||
string GCN_VPK_Hex_Length = GCN_VPK_Length.ToString("X").PadLeft(4, '0');
|
||||
|
||||
if (!File.Exists(Common.VPK_GBA))
|
||||
{
|
||||
MessageBox.Show("ERROR: Failed to fetch GBA VPK");
|
||||
return;
|
||||
}
|
||||
byte[] fileContents = File.ReadAllBytes(Common.VPK_GBA);
|
||||
|
||||
if (fileContents.Length < 2)
|
||||
{
|
||||
MessageBox.Show("ERROR: GBA VPK exists, but is smaller in size than expected");
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] GCN_FileSize_Checksum = HexStringToByteArray(GCN_VPK_Hex_Length);
|
||||
|
||||
fileContents[fileContents.Length - 2] = GCN_FileSize_Checksum[1];
|
||||
fileContents[fileContents.Length - 1] = GCN_FileSize_Checksum[0];
|
||||
|
||||
File.WriteAllBytes(Common.VPK_GBA, fileContents);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"An error occurred: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static string ACAsciiToBytes(string input)
|
||||
{
|
||||
Dictionary<string, string> map = ReadMappings(Common.SP_CHAR_LIST);
|
||||
var sb = new StringBuilder();
|
||||
var textElementEnumerator = StringInfo.GetTextElementEnumerator(input);
|
||||
|
||||
// a bit hacky and inefficient, but should work
|
||||
while (textElementEnumerator.MoveNext())
|
||||
{
|
||||
string textElement = textElementEnumerator.GetTextElement();
|
||||
if (textElement == "\n")
|
||||
{
|
||||
sb.Append("CD");
|
||||
}
|
||||
else if (textElement.Length == 1)
|
||||
{
|
||||
if (map.ContainsKey(textElement))
|
||||
{
|
||||
sb.Append(map[textElement].Substring(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
char c = textElement[0];
|
||||
if ((byte)c >= 32 && (byte)c <= 127)
|
||||
{
|
||||
byte char_byte = (byte)c;
|
||||
sb.Append(char_byte.ToString("X2"));
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("An unexpected error occurred!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (map.ContainsKey(textElement))
|
||||
{
|
||||
sb.Append(map[textElement].Substring(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Test!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
|
||||
static byte[] HexStringToByteArray(string hex)
|
||||
{
|
||||
int numberChars = hex.Length;
|
||||
byte[] bytes = new byte[numberChars / 2];
|
||||
for (int i = 0; i < numberChars; i += 2)
|
||||
{
|
||||
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using AC_e_Reader_Card_Creator.References;
|
||||
|
||||
namespace AC_e_Reader_Card_Creator.Decompression.Functions
|
||||
{
|
||||
internal class Decompress
|
||||
{
|
||||
public static void BINtoVPK(string filePath, byte[] delimiter, string outputDirectory)
|
||||
{
|
||||
List<byte> buffer = new List<byte>();
|
||||
int chunkNumber = 1;
|
||||
|
||||
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||
using (BinaryReader reader = new BinaryReader(fs))
|
||||
{
|
||||
while (reader.BaseStream.Position != reader.BaseStream.Length)
|
||||
{
|
||||
byte b = reader.ReadByte();
|
||||
buffer.Add(b);
|
||||
|
||||
if (buffer.Count >= delimiter.Length &&
|
||||
buffer.Skip(buffer.Count - delimiter.Length).SequenceEqual(delimiter))
|
||||
{
|
||||
WriteToFile(buffer.Take(buffer.Count - delimiter.Length).ToArray(), ref chunkNumber, outputDirectory, delimiter);
|
||||
buffer.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer.Count > 0)
|
||||
{
|
||||
WriteToFile(buffer.ToArray(), ref chunkNumber, outputDirectory, delimiter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RAWtoBIN(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessStartInfo raw_to_bin = new ProcessStartInfo
|
||||
{
|
||||
FileName = Common.NEDCENC,
|
||||
Arguments = Common.NEDCENCE_ARGS_DECOMP(filePath),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (Process process = Process.Start(raw_to_bin)) { process.WaitForExit(); }
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Error processing file {filePath}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void VPK_Decompress()
|
||||
{
|
||||
string folderPath = Common.VPK_OUTPUT;
|
||||
string[] vpk_file_paths = Directory.GetFiles(folderPath);
|
||||
|
||||
int iteration = 1;
|
||||
|
||||
foreach (string vpk_file in vpk_file_paths)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (iteration == 1)
|
||||
{
|
||||
iteration++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessStartInfo vpk_to_dec = new ProcessStartInfo
|
||||
{
|
||||
FileName = Common.NEVPK,
|
||||
Arguments = Common.NEVPK_ARGS_DECOMP(vpk_file, iteration),
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (Process process = Process.Start(vpk_to_dec)) { process.WaitForExit(); }
|
||||
|
||||
iteration++;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Error processing file {vpk_file}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteToFile(byte[] data, ref int chunkNumber, string outputDirectory, byte[] delimiter)
|
||||
{
|
||||
string fileName = "";
|
||||
|
||||
switch (chunkNumber)
|
||||
{
|
||||
case 1:
|
||||
fileName = Path.Combine(outputDirectory, $"1_VPK_Header.vpk");
|
||||
break;
|
||||
case 2:
|
||||
fileName = Path.Combine(outputDirectory, $"2_VPK_GBA.vpk");
|
||||
break;
|
||||
case 3:
|
||||
fileName = Path.Combine(outputDirectory, $"3_VPK_GCN.vpk");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
using (FileStream outFile = new FileStream(fileName, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
if (chunkNumber != 1)
|
||||
{
|
||||
outFile.Write(delimiter, 0, delimiter.Length);
|
||||
outFile.Write(data, 0, data.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
outFile.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
chunkNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using AC_e_Reader_Card_Creator.References;
|
||||
|
||||
namespace AC_e_Reader_Card_Creator.Decompression.Functions
|
||||
{
|
||||
internal class Decompressed
|
||||
{
|
||||
public static Dictionary<string, string> GetData()
|
||||
{
|
||||
byte[] GCN_Letter_Bytes = { };
|
||||
Dictionary<string, string> letterData = new Dictionary<string, string>();
|
||||
|
||||
try
|
||||
{
|
||||
GCN_Letter_Bytes = File.ReadAllBytes(Common.GCN_LETTER_DATA);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Console.WriteLine($"An error occurred while reading the file: {ex.Message}");
|
||||
}
|
||||
|
||||
string letter_contents = ConvertBytesToACAscii(GCN_Letter_Bytes);
|
||||
string full_greeting = GetGreeting(letter_contents);
|
||||
|
||||
// bunch of hardcoding with the exact byte positions - source these out to variables
|
||||
int player_index = Convert.ToInt32("0x" + GCN_Letter_Bytes[253].ToString("X2"), 16) - 1;
|
||||
string letter_greeting = InsertPlayerVar(full_greeting, player_index).Trim();
|
||||
letterData.Add("letter_greeting", letter_greeting);
|
||||
|
||||
string letter_body = GetStringInRange(letter_contents, 24, 207);
|
||||
letterData.Add("letter_body", letter_body);
|
||||
|
||||
string letter_closing = GetStringInRange(letter_contents, 216, 246).Trim();
|
||||
letterData.Add("letter_closing", letter_closing);
|
||||
|
||||
byte[] stationeryID_bytes = { GCN_Letter_Bytes[247], GCN_Letter_Bytes[248] };
|
||||
string stationeryID = BytesToHex(stationeryID_bytes).Replace(" ", "");
|
||||
letterData.Add("letter_stationery", stationeryID);
|
||||
|
||||
byte[] giftID_bytes = { GCN_Letter_Bytes[249], GCN_Letter_Bytes[250] };
|
||||
string giftID = BytesToHex(giftID_bytes).Replace(" ", "");
|
||||
letterData.Add("letter_gift", giftID);
|
||||
|
||||
byte[] senderID_bytes = { GCN_Letter_Bytes[251], GCN_Letter_Bytes[252] };
|
||||
string senderID = BytesToHex(senderID_bytes).Replace(" ","");
|
||||
letterData.Add("letter_sender", senderID);
|
||||
|
||||
return letterData;
|
||||
}
|
||||
|
||||
public static string ConvertBytesToACAscii(byte[] byteArray)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
foreach (byte b in byteArray)
|
||||
{
|
||||
// handles newline
|
||||
if (b == 0xCD)
|
||||
{
|
||||
result.Append("\n");
|
||||
}
|
||||
// handles standard ASCII conversion
|
||||
else if (b >= 32 && b <= 127)
|
||||
{
|
||||
result.Append((char)b);
|
||||
}
|
||||
// handles AC's special characters; standard ASCII char conversion is faster,
|
||||
// so only lookup special characters instead of doing this for every character
|
||||
else if (b < 32 || b > 127)
|
||||
{
|
||||
string special_char = "0x" + b.ToString("X2");
|
||||
special_char = Common.LookupListValue(special_char, Common.SP_CHAR_LIST);
|
||||
result.Append(special_char);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append("-");
|
||||
}
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public static int PlayerVarFinder(string greeting)
|
||||
{
|
||||
for (int i = greeting.Length - 2; i > 0; i--)
|
||||
{
|
||||
if (greeting[i] == ' ' && greeting[i + 1] != ' ')
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static string GetGreeting(string letter)
|
||||
{
|
||||
if (string.IsNullOrEmpty(letter) || letter.Length < 24)
|
||||
{
|
||||
return letter;
|
||||
}
|
||||
|
||||
return letter.Substring(0, 24);
|
||||
}
|
||||
|
||||
public static string GetStringInRange(string letter, int startIndex, int endIndex)
|
||||
{
|
||||
|
||||
if (string.IsNullOrEmpty(letter))
|
||||
{
|
||||
throw new ArgumentException("The letter is null or empty.");
|
||||
}
|
||||
|
||||
if (startIndex < 0 || endIndex >= letter.Length || startIndex > endIndex)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Start or end index is out of range.");
|
||||
}
|
||||
|
||||
int length = endIndex - startIndex + 1;
|
||||
return letter.Substring(startIndex, length);
|
||||
}
|
||||
|
||||
public static string InsertPlayerVar(string greeting, int index)
|
||||
{
|
||||
if (index == 0 || index < 0 || index > greeting.Length)
|
||||
{
|
||||
string revisedGreeting = greeting.Insert(0, "<Player>");
|
||||
return revisedGreeting;
|
||||
}
|
||||
|
||||
return greeting.Substring(0, index) + " <Player>" + greeting.Substring(index + 1);
|
||||
}
|
||||
|
||||
public static string BytesToHex(byte[] byteArray)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
foreach (byte b in byteArray)
|
||||
{
|
||||
result.AppendFormat("{0:X2} ", b);
|
||||
}
|
||||
|
||||
return result.ToString().TrimEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user