diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..df9771e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,27 @@ +on: + push: + branches: ["*"] + pull_request: + branches: ["*"] + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + - name: Build + run: | + nuget restore + msbuild -p:Configuration=Release -m + - name: Package + run: | + cd AC_e-Reader_Card_Creator/bin/Release/net*-windows/ + Copy-Item -Destination . '${{ github.workspace }}/x64/Release/nedclib.dll' + 7z -tzip a '${{ github.workspace }}/e-ReaderCardCreator.zip' . + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: e-ReaderCardCreator + path: e-ReaderCardCreator.zip diff --git a/AC_e-Reader_Card_Creator.sln b/AC_e-Reader_Card_Creator.sln index 3438837..df21d1d 100644 --- a/AC_e-Reader_Card_Creator.sln +++ b/AC_e-Reader_Card_Creator.sln @@ -1,20 +1,45 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AC_e-Reader_Card_Creator", "AC_e-Reader_Card_Creator\AC_e-Reader_Card_Creator.csproj", "{61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nedclib", "AC_e-Reader_Card_Creator\Decompression\External\nedclib\nedclib.vcxproj", "{7B2D1D08-D33C-41F0-83FE-2A92173DDF94}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Debug|x64.ActiveCfg = Debug|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Debug|x64.Build.0 = Debug|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Debug|x86.ActiveCfg = Debug|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Debug|x86.Build.0 = Debug|Any CPU {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Release|Any CPU.Build.0 = Release|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Release|x64.ActiveCfg = Release|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Release|x64.Build.0 = Release|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Release|x86.ActiveCfg = Release|Any CPU + {61E3E092-ADF9-4613-B6FB-205DD4F5A7E9}.Release|x86.Build.0 = Release|Any CPU + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Debug|Any CPU.ActiveCfg = Debug|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Debug|Any CPU.Build.0 = Debug|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Debug|x64.ActiveCfg = Debug|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Debug|x64.Build.0 = Debug|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Debug|x86.ActiveCfg = Debug|Win32 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Debug|x86.Build.0 = Debug|Win32 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Release|Any CPU.ActiveCfg = Release|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Release|Any CPU.Build.0 = Release|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Release|x64.ActiveCfg = Release|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Release|x64.Build.0 = Release|x64 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Release|x86.ActiveCfg = Release|Win32 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AC_e-Reader_Card_Creator/AC_e-Reader_Card_Creator.csproj b/AC_e-Reader_Card_Creator/AC_e-Reader_Card_Creator.csproj index 9c82e59..c1d0c0b 100644 --- a/AC_e-Reader_Card_Creator/AC_e-Reader_Card_Creator.csproj +++ b/AC_e-Reader_Card_Creator/AC_e-Reader_Card_Creator.csproj @@ -21,6 +21,7 @@ true true true + SystemAware true @@ -34,10 +35,10 @@ e-reader-ccc.ico + true - %(RecursiveDir)\Project Files\References\%(Filename)%(Extension) @@ -47,14 +48,6 @@ %(RecursiveDir)\Project Files\References\%(Filename)%(Extension) PreserveNewest - - %(RecursiveDir)\Project Files\Decompression\External\%(Filename)%(Extension) - PreserveNewest - - - %(RecursiveDir)\Project Files\Decompression\External\%(Filename)%(Extension) - PreserveNewest - %(RecursiveDir)\Project Files\Resources\%(Filename)%(Extension) PreserveNewest @@ -65,6 +58,13 @@ + + + + + + + False diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/CMakeLists.txt b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/CMakeLists.txt new file mode 100644 index 0000000..d71810c --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.12) +project(nedclib VERSION 1.4.0 LANGUAGES C CXX) + +option(BUILD_TOOLS "Build standalone tools" OFF) + +set(CMAKE_CXX_VISIBILITY_PRESET "hidden") +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +set(NEDCLIB_SRCS + nedclib.cpp + nes.cpp + rawbin/binraw.cpp + rawbin/rs.cpp + rawbmp/address.cpp + rawbmp/dcs_decode.cpp + rawbmp/dcs_encode.cpp + rawbmp/rawbmp.cpp + stdafx.cpp + vpk/vpk.cpp + nedclib.h + rawbin/rs.h + rawbmp/dcs.h + stdafx.h +) +add_library(nedclib SHARED "${NEDCLIB_SRCS}") +target_include_directories(nedclib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/rawbmp") +target_compile_definitions(nedclib PRIVATE "NEDCLIB_EXPORTS=1") + +if(BUILD_TOOLS) + add_executable(raw2bmp "raw2bmp.cpp") + target_link_libraries(raw2bmp PRIVATE nedclib) + add_executable(nedcenc "nedcenc.cpp") + target_link_libraries(nedcenc PRIVATE nedclib) + add_executable(nevpk "nevpk.cpp") + target_link_libraries(nevpk PRIVATE nedclib) + add_executable(nedcmaker "nedcmake/nedcmaker.cpp") + if(UNIX) + target_compile_definitions(nedcmaker PRIVATE "stricmp=strcmp") + endif() + # Special tool: headerfix, which is outside this project + set(HEADER_FIX_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/../Source Code/headerfix.c") + if(EXISTS "${HEADER_FIX_SOURCE}") + add_executable(headerfix "${HEADER_FIX_SOURCE}") + endif() +endif() diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/ReadMe.txt b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/ReadMe.txt new file mode 100644 index 0000000..b206c38 --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/ReadMe.txt @@ -0,0 +1,33 @@ +======================================================================== + DYNAMIC LINK LIBRARY : nedclib Project Overview +======================================================================== + +AppWizard has created this nedclib DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your nedclib application. + + +nedclib.vcproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +nedclib.cpp + This is the main DLL source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named nedclib.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/AC_e-Reader_Card_Creator/Decompression/External/Source Code/nedcenc.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcenc.cpp similarity index 100% rename from AC_e-Reader_Card_Creator/Decompression/External/Source Code/nedcenc.cpp rename to AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcenc.cpp diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.cpp new file mode 100644 index 0000000..74787e8 --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.cpp @@ -0,0 +1,267 @@ +// nedclib.cpp : Defines the entry point for the DLL application. +// + +#include "stdafx.h" +#include +#include + + +#include "nedclib.h" +#include "rawbin/rs.h" + +int raw_pos; +int bin_pos; + +int bin_type=0; //0 = Single File NEDC bin. 1 = Multi file NEDC bin. 2 = Multi file DRPD bin. + +int count_bin(FILE *f) +{ + int count=0; + int i; + char header[9] = {0,0,0,0,0,0,0,0,0}; + unsigned char *data; + + fseek(f,0,SEEK_END); + i=ftell(f); + fseek(f,0,SEEK_SET); + if((i==0x81C)||(i==0x51C)) + { + bin_type=0; //Nintendo e-Reader, old style bin format. + return 1; //Count is one dotcode bin. + } + else + { + bin_type = 1; + fseek(f,0,SEEK_SET); + } + data = (unsigned char*)malloc(0x840); //Worst case bin file size, no error correction. + if(data==NULL) + return 0; //Couldn't allocate the memory for dotcode bins. + while(read_next_bin(f,data)) + count++; + fseek(f,0,SEEK_SET); //Rewind back to first bin. + + + free(data); + return count; +} + +int read_next_bin(FILE *f, unsigned char *bindata) +{ + int result; + int i,j,k; + bin_pos=ftell(f); + switch(bin_type) + { + case 0: + result = (int)fread(bindata,1,0x81C,f); + break; + case 1: + result = (int)fread(bindata,1,0x30,f); + result += (int)fread(&bindata[0x30],1,(bindata[6]==8)?0x810:0x510,f); + break; + } + + return result; +} + + +int count_raw(FILE *f) +{ + int i=0,count=0; + unsigned char *data; + + + data = (unsigned char*)malloc(0xB60); //Worst case raw file size. + if(data==NULL) + return 0; //Unable to allocate memory (and therefore count the raw data files.) + fseek(f,0,SEEK_SET); + while(read_next_raw(f,data)) + count++; + free(data); + fseek(f,0,SEEK_SET); + return count; +} + + + +int read_next_raw(FILE *f, unsigned char *rawdata) +{ + size_t result; + + raw_pos = ftell(f); + + unsigned char rawheader[24]; + int i,j,k,l; + + if(is_rs_initialized()) + l=1; + else + initialize_rs(); + + for(i=0,result=0;i<24;i+=2) + { + result+=fread(&rawheader[i],1,2,f); + fseek(f,0x66,SEEK_CUR); + } + if(result==24) + { + fseek(f,raw_pos,SEEK_SET); + //int rs_decode(unsigned char *data, unsigned char *erasure, int size, int parity, int encoder) + //if(rs_decode(rawheader,(unsigned char*)erasuredata,24,16,0)>=0) + if(correct_errors(rawheader,24,16)>=0) + { + i=rawheader[4]*rawheader[7]; + if((i%0x66)>0) + i+=(0x66-(i%0x66)); + i/=0x66; + k=i; + i*=0x68; + if(i>0xB60) + { + if(l==0) free_rs(); + return 0; + } + result = fread(rawdata,1,i,f); + if(i!=result) + { + if(l==0) free_rs(); + return 0; //Raw data shorter than calculated. + } + j=0; + while((j*12) + +/* +// This class is exported from the nedclib.dll +class NEDCLIB_API Cnedclib { +public: + Cnedclib(void); + // TODO: add your methods here. +};*/ + +//Common internal functions/variables +int count_raw(FILE *f); +int read_next_raw(FILE *f, unsigned char *rawdata); + +extern int bin_type; +#define BIN_TYPE_NEDC_SINGLE 0 +#define BIN_TYPE_NEDC_MULTI 1 +#define BIN_TYPE_DRPD_MULTI 2 +//There is no DRPD single format, as there is no way to know how big each of them will be +//with certainty. + +int count_bin(FILE *f); +int read_next_bin(FILE *f, unsigned char *bindata); + +void backtrack_raw(FILE *f); +int close_raw(FILE *f, int return_res); + +#ifdef __cplusplus +extern "C" { +#endif +//--- common external functions --- +NEDCLIB_API void nedclib_version(void); +NEDCLIB_API int is_vpk(unsigned char *bindata); +NEDCLIB_API int is_nes(unsigned char *nesdata); +NEDCLIB_API int is_bmp(char *bmpfile); + +extern NEDCLIB_API int version_major; +extern NEDCLIB_API int version_minor; +extern NEDCLIB_API int MultiStrip; + +//--- RAW2BMP FUNCTIONS --- +NEDCLIB_API int raw2bmp(char *rawfile, char *bmpfile); +NEDCLIB_API int bmp2raw(char *bmpfile, char *rawfile); +NEDCLIB_API int raw2bmp_f(unsigned char *rawdata, char *bmpfile); +extern NEDCLIB_API int smooth; + +//--- BIN2RAW FUNCTIONS --- +NEDCLIB_API int bin2raw(char *binfile, char *rawfile); +NEDCLIB_API int raw2bin(char *rawfile, char *binfile); +NEDCLIB_API int fixraw(char *rawfile); +NEDCLIB_API int bin2raw_d(unsigned char *bindata, unsigned char *rawdata, int size); +NEDCLIB_API int bin2raw_f(unsigned char *bin, char *rawfile, int size); +extern NEDCLIB_API int signature; +extern NEDCLIB_API unsigned char signature_str[]; +extern NEDCLIB_API int dpi_multiplier; + +//--- NEVPK FUNCTIONS --- +NEDCLIB_API int NVPK_compress (unsigned char *buf, int size, int compression_level, int lzwindow, int lzsize, int method, FILE *f, unsigned char *bitdata=NULL); +NEDCLIB_API int vpk_decompress (unsigned char *vpk, FILE *f); +NEDCLIB_API void log_write(const char* str, ...); +extern NEDCLIB_API FILE *log_stream; +extern NEDCLIB_API int verbose; +extern NEDCLIB_API unsigned long bits_written; +extern NEDCLIB_API int best_move; +extern NEDCLIB_API int best_size; +extern NEDCLIB_API int skip_huffman; +extern NEDCLIB_API int skip_lz77; + +//--- NES Functions --- +NEDCLIB_API int make_nes(unsigned char *nesdata); +NEDCLIB_API unsigned short nes_enc(unsigned short NMI_vector); +NEDCLIB_API unsigned short nes_dec(unsigned short NMI_vector); + +// -- Binding functions --- +NEDCLIB_API FILE* nedc_fopen(const char* filename, const char* mode); +NEDCLIB_API int nedc_fclose(FILE *handle); + +#ifdef __cplusplus +} +#endif + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 4 + +#define NEDCENC_MAJOR 1 +#define NEDCENC_MINOR 4 +#define NEDCMAKE_MAJOR 1 +#define NEDCMAKE_MINOR 4 +#define NEVPK_MAJOR 1 +#define NEVPK_MINOR 4 +#define RAW2BMP_MAJOR 1 +#define RAW2BMP_MINOR 4 + +#define NEDCLIB_DOWNLOAD "http://www.caitsith2.net/ereader/tools/nedclib_dll.rar" diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.vcxproj b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.vcxproj new file mode 100644 index 0000000..c972e9c --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.vcxproj @@ -0,0 +1,111 @@ + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {7B2D1D08-D33C-41F0-83FE-2A92173DDF94} + Win32Proj + nedclib + 10.0 + + + + DynamicLibrary + v143 + + + DynamicLibrary + v143 + + + DynamicLibrary + v143 + + + DynamicLibrary + v143 + + + + + + + + + stdc11 + true + $(ProjectDir);%(AdditionalIncludeDirectories) + NEDCLIB_EXPORTS=1;%(PreprocessorDefinitions) + + + + + true + $(ProjectDir);%(AdditionalIncludeDirectories) + NEDCLIB_EXPORTS=1;%(PreprocessorDefinitions) + stdc11 + Speed + true + + + UseLinkTimeCodeGeneration + + + + + true + $(ProjectDir);%(AdditionalIncludeDirectories) + NEDCLIB_EXPORTS=1;%(PreprocessorDefinitions) + stdc11 + + + + + true + $(ProjectDir);%(AdditionalIncludeDirectories) + NEDCLIB_EXPORTS=1;%(PreprocessorDefinitions) + stdc11 + Speed + true + + + UseLinkTimeCodeGeneration + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.vcxproj.filters b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.vcxproj.filters new file mode 100644 index 0000000..e754af3 --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedclib.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcmake/ereader card info.txt b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcmake/ereader card info.txt new file mode 100644 index 0000000..ba3c4aa --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcmake/ereader card info.txt @@ -0,0 +1,98 @@ +E-Reader card info + + +Offset Size Description +0x000 1 xxxxyyyy - xxxx unknown, yyyy region +0x001 1 xxxxyyyy - xxxx card type, yyyy unknown + +If the region is 0 or 2, then all titles/text have to be in shift-jis format. +If the region is 1, then all titles/text are in ascii format. + +Card Types 0,1 - Pokemon Viewer + +Card Types 2,3,4,5,E - Dotcode Application + +Offset Size Description +0x000 0x0C Header + +Valid application headers + +x = don't care +A = number of cards +B = card number +C = Data length * 2 +D = Application Type - 0 = GBA/Z80 type, 1 = NES type +E = Individual card title mode bit +F = Permission to save bit + +xxxx0000 - Jap original (will also run on Jap plus) +xxxx0001 - US +xxxx0010 - Jap plus + 001xxxxx - Pokemon name/stat mode, load music A + 010xxxxx - Pokemon name/stat mode, load music B + 1110xxxx - Longer title mode, load music A + xxxxxxxx xxxxxxxx AAABBBBx CCCCCCCA CCCCCCCC 00000010 00000DEF 00000000 00000000 00000000 + + + If the type is 2,3,4, or 5, then the Maximum title length is 16 characters, + Otherwise, if it is E, then the maximum is 32 characters. + The header format is identical between the two. + + If the card is in individual card title mode, then the number of titles that have to + follow the application title depends on how many cards are in the set. If the number + of cards in the set exceeds 8, no individual card titles are displayed, instead, the + ereader logo is displayed. Even though this is the case, you still have to specify + the individual card titles. Therefore, it is best not to use this mode if the set + is going to require 9 or more cards. What might fit on 8 cards in normal title mode, + may just require 9 cards in individual title mode, depending on how many bytes are + required by the compressed application vpk data. + + Formats 2,3,4,5 - Card titles follow a format of 3 bytes stats, followed by an 17 + character title. + ABBBCCCC DDAAAAAA EFFFFDDD + 0 654321 - Order of A bits + 210 - Order of B bits + 3210 - Order of C bits + 10 432 - Order of D bits + 0 - Order of E bits + 3210 - Order of F bits + + A = ID: 01-99,A0-A9,B0-B9,C0-C8 (x-AA-x) + B = ID: A-G,# (x-xx-B) + C = HP: 10-150. A value of 0 means no HP is displayed. + D = ID: A-Z,-,_,{HP},.,{ID},: (D-xx-x) + E = Stat display control. 1 = no stat display. + F = unknown. + + Format E - Card titles are 32 bytes each. + + If the title is NULL, and there is only one card in the application, then the + application is started immediately, upon successful scanning. A NULL titled + application cannot be saved, as the e-reader treats that as having no application + on the save. + + If the vpk length - 2 immediately follows the vpk data, then the application + is either Z80 code type, or NES code type, depending on whether the Application + type bit was set or cleered. + However, if the vpk length - 6 follows 4 bytes of 0s, then the vpk data, the + application is GBA code type. The application type bit must remain cleared. + + The max number of application cards is 8 on the original japan ereader, and 12 on + the US ereader and Japan ereader plus. + + The original jap E-Reader does not support the GBA/NES application types. Title + formats have to always be individual title mode. Z80 application controller input + is on a different register. Title length in short title mode is 4 bytes less. + Those 4 bytes must be 0 filled. + + +Card Types 6,7 - Pokemon Attacks + +Card Types 8,9 - Construction Escape + +Card Types A,B - Construction Action + +Card Types C,D - Construction Melody Box + +Card Types F - Game specific cards. + diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcmake/nedcmaker.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcmake/nedcmaker.cpp new file mode 100644 index 0000000..6895d04 --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nedcmake/nedcmaker.cpp @@ -0,0 +1,626 @@ +// necmaker.cpp : Defines the entry point for the console application. +// + +#include +#include +#include + +unsigned char carddata[0x81C]; + +unsigned char vpkdata[24564]; + +char title[13][33]; + +unsigned char cardheader[0x0C] = { + 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 +// reg, type, numc, data size flags +}; + +#define REGION_JAPAN 0 +#define REGION_US 1 +#define REGION_JAPANPLUS 2 + +#define APPTYPE_NES 0 +#define APPTYPE_Z80 1 +#define APPTYPE_GBA 2 +#define APPTYPE_RAW 3 + +#define CARD_SHORT_NO 0 +#define CARD_SHORT_YES 1 +#define CARD_LONG_NO 2 +#define CARD_LONG_YES 3 + +//Usage: necmaker [-jp, -us, -jep] [-Z80 -GBA -NES] [-stn, -sty, -ltn, -lty] [-long, -short] [-mus1, -mus2] -F {vpk file name} -B {output base name} [-T {Application Title}] [-T {Card Title/stats}]... +// {-jp, -us, -jep} - Region (default US) +// {-Z80 -GBA -NES} - Application Type (default Z80) +// {-stn, -sty, -ltn, -lty} - Application/Card Titling mode (default Long title, no individual names) +// {-long, -short} - Dotcode size; (default, long) +// {-mus1, -mus2} - Music to be played during card loading, if in short titling mode. (default music 1) +// {-save} - Allows the scanned dotcodes to be saved, (default disallowed) + +void usage(int extended=0) +{ + + printf("usage :\n"); + printf(" nedcmaker [options]\n"); + printf("options :\n"); + // " | | |-123456789-123456789-12345678" + printf(" -i input file (required)\n"); + printf(" -o output name (optional)\n"); + printf(" -type type (0=nes 1=z80 2=gba) (required)\n"); + printf(" -region region (0=jap 1=usa 2=jap+) (default = usa)\n"); + printf(" -name Application name (default = none)\n"); + printf(" -title Individual Card Titles (default = none)\n"); + printf(" -dcsize dcsize (0=long 1=short) (default = long)\n"); + printf(" -fill fill (0=none 1=filled) (default = none)\n"); + printf(" -save save (0=no 1=yes) (default = no)\n"); + printf(" -titlemode titlemode (0=short, no individual titles)\n"); + printf(" (1=short, individual card titles)\n"); + printf(" (2=long, no individual titles (default))\n"); + printf(" (3=long, individual card titles)\n"); + printf(" -music music (0=Normal 1=cheery) (default = normal)\n"); + printf(" -help (or -?) Print extended usage info\n"); + + if(extended) + { + printf("\n"); + printf("The music option is only valid for title modes 0 and 1\n\n"); + + printf("If titlemode 1 is specified, you can add a pokemon serial# and hitpoints \n"); + printf("to the individual titles, in the form of [hitpoint]:X-YY-Z:[title]\n"); + printf(" [Hitpoint] = 0-150\n"); + printf(" X = A-Z,-,_\n"); + printf(" Y = 01-99,A0-A9,B0-B9,C0-C8\n"); + printf(" Z = A-G,#\n"); + printf(" [title] = Whatever you want here\n"); + printf(" For example: \"50:D-35-#:Aipom\"\n"); + printf("If your using this program in a makefile, please replace # with H, as # causes the\n"); + printf("rest of the line to be treated as a comment in a makefile.\n"); + printf("If titlemode is 3, then you only need to specify the [title] with each -title\n"); + printf("Title modes 0-1 do not have the english character set for regions 0 or 2.\n\n"); + + printf("If you specify a region of 0, then Titlemode automatically becomes 1 or 3\n"); + printf("Also, the only valid application type for region 0 is z80\n\n"); + + printf("If -o is not specified, the output files will be 01.bin - 12.bin\n"); + printf("Otherwise it will be -01.bin - -12.bin\n\n"); + + + printf("The Following max size tables assume your using apptype nes or z80.\n"); + printf("If your using apptype gba, then subtract 4 from each of these values\n\n"); + + printf("Max size of Long dotcodes in order of title modes (US/Jap+)\n"); + printf("0=24564, 2=24372, 1=21540, 3=19620\n\n"); + + printf("Max size of Short dotcodes in order of title modes (US/Jap+)\n"); + printf("0=15348, 2=15156, 1=12324, 3=10404\n\n"); + + printf("Max size of Long dotcodes in order of title modes (Jap)\n"); + printf("1=%d, 3=%d\n\n", (((0x81C - 0x1D)-(0x15*(8)))*(8)),(((0x81C - 0x2D)-(0x21*(8)))*(8))); + + printf("Max size of Short dotcodes in order of title modes (Jap)\n"); + printf("1=%d, 3=%d\n\n", (((0x51C - 0x1D)-(0x15*(8)))*(8)),(((0x51C - 0x2D)-(0x21*(8)))*(8))); + } + +} + +unsigned char jistable [] = +{ + 0x40, 0x49, 0x00, 0x94, 0x90, 0x93, 0x95, 0x66, 0x69, 0x6A, + 0x96, 0x7B, 0x43, 0x5D, 0x44, 0x5E, 0x4F, 0x50, 0x51, 0x52, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x46, 0x47, 0x83, 0x81, + 0x84, 0x48, 0x97, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x6D, + 0x5F, 0x6E, 0x4F, 0x51, 0x4D, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0x6F, 0x62, 0x70, 0x60 +} ; + +void shiftJIS(char *str, char *output, int len) +{ + int i; + for(i=0;i<(len/2);i++) + { + if (str[i] == 0) + break; + else if (((str[i] >= 'a') && (str[i] <= 'z')) || \ + ((str[i] >= 'A') && (str[i] <= 'Z')) || \ + ((str[i] >= '0') && (str[i] <= '9')) ) + { + output[(i*2)+1] = jistable[str[i]-0x20]; + output[(i*2)] = (char)0x82; + } + else + { + output[(i*2)+1] = jistable[str[i]-0x20]; + output[(i*2)] = (char)0x81; + } + } + output[(i*2)] = 0; +} + +void process_title(char *str, int titlenum, int cardmode, int region) +{ + int i,j,k; + char titlestr[8]; + char jistitle[34]; + + memset(titlestr,0,8); + memset(jistitle,0,34); + + if((titlenum==0)||(cardmode==CARD_LONG_NO)||(cardmode==CARD_LONG_YES)) + { + if(region!=1) + { + shiftJIS(str,jistitle,33); + for(i=0;i<33;i++) + { + title[titlenum][i] = jistitle[i]; + if(jistitle[i]==0) + break; + } + } + else + { + for(i=0;i<33;i++) + { + title[titlenum][i] = str[i]; + if(str[i]==0) + break; + } + } + if(i==33) + { + printf("Warning: Title \"%s\" will be truncated to \n\t",str); + if(region != 1) + { + for(i=0;i<(33/2);i++) + { + if(str[i]==0) + break; + jistitle[i]=str[i]; + } + jistitle[i]=0; + printf("\"%s\"\n",jistitle); + } + else + { + for(i=0;i<33;i++) + jistitle[i]=str[i]; + printf("\"%s\"\n",jistitle); + } + } + } + else + { + i = 0; j=0; + while(str[i]!=':') + { + titlestr[j]=str[i]; + i++;j++; + } + titlestr[j] = 0; + if(i!=0) + { + k=atoi(titlestr); + title[titlenum][0] = (k / 10); + } + i++; j=0; + while(str[i]!=':') + { + titlestr[j]=str[i]; + i++;j++; + } + if ((str[i] == ':') && (str[i-1] == ':')) + title[titlenum][2] = (char)0x80; + else + { + k = titlestr[0]; + if((k == '-')) + { + title[titlenum][1] = (char)0x80; + title[titlenum][2] = 0x06; + } + else if ((k == '_')) + { + title[titlenum][1] = (char)0xC0; + title[titlenum][2] = 0x06; + } + else + { + k -= 'A'; + title[titlenum][1] = k << 6; + title[titlenum][2] = k >> 2; + } + j = titlestr[2]; + k = titlestr[3]; + if((j=='a')||(j=='b')||(j=='c')) + { + j -= 'a'; + j *= 10; + j += 100; + } + else if((j=='A')||(j=='B')||(j=='C')) + { + j -= 'A'; + j *= 10; + j += 100; + } + else + { + j -= '0'; + j *= 10; + } + k -= '0'; + j += k; + j--; + j &= 0x7F; + + title[titlenum][0] |= j << 7; + title[titlenum][1] |= j >> 1; + + if((titlestr[5] == '#') || (titlestr[5] == 'H')) + title[titlenum][0] |= 0x70; + else + { + k = titlestr[5]; + if ((k - 'A') < 7) + k -= 'A'; + else + k -= 'a'; + k &= 0x07; + title[titlenum][0] |= k << 4; + } + + + + + } + i++; + if(region!=1) + { + shiftJIS(str+i,jistitle,0x12); + for(j=0;j<0x12;j++) + { + title[titlenum][j+3] = jistitle[j]; + if(jistitle[j]==0) + break; + } + if(j==0x12) + { + printf("Warning: Title %s will be truncated to \n\t",str); + for(j=0;j<(0x12/2);i++,j++) + jistitle[j]=str[i]; + jistitle[j] = 0; + printf("\"%s\"\n",jistitle); + } + } + else + { + for(j=0;j<0x12;j++,i++) + { + title[titlenum][j+3] = str[i]; + if(str[i]==0) + break; + } + if(j==0x12) + { + i-=0x12; + printf("Warning: Title %s will be truncated to \n\t",str); + for(j=0;j<0x12;i++,j++) + jistitle[j]=str[i]; + printf("\"%s\"\n",jistitle); + } + } + + + } +} + +int main(int argc, char* argv[]) +{ + int i,j,k; + FILE *f; + int region=REGION_US; + int apptype=-1; + int cardsize=0x81C; + int headersize=0x2D; + int settitlesize=33; + int cardtitlesize=0; + int allowsave=0; + int mode=CARD_LONG_NO; + int numtitles=1; + int numcards; + int filename; + char fn[256]; + int filesize; + int basename=0; + int music=0; + int fill=0; + + for(i=0;i<13;i++) + for(j=0;j<33;j++) + title[i][j]=0; + + + + printf("Nintendo E-Reader Dotcode bin maker tool\n"); + printf("Copyright CaitSith2\n\n"); + + for(i=1;i\n"); + return 1; + } + if(apptype==-1) + { + printf("Required paramete missing: -type \n"); + return 1; + } + + + f=fopen(argv[filename],"rb"); + if(f==NULL) + { + printf("Error: VPK file could not be opened for reading\n"); + //Could not open vpk file + return 1; + } + fseek(f,0,SEEK_END); + filesize=ftell(f); + fseek(f,0,SEEK_SET); + + if(((filesize>24562)&&(apptype!=APPTYPE_GBA))||((filesize>24558)&&(apptype==APPTYPE_GBA))) + { + printf("Error: VPK data too large for even Title mode 0\n"); + //VPK file is too large for ereader card sets + return 1; + } + + + + if(apptype==APPTYPE_GBA) + { + fread(vpkdata+6,1,filesize,f); + memcpy(vpkdata,&filesize,2); + memset(vpkdata+2,0,4); + filesize+=6; + } + else + { + fread(vpkdata+2,1,filesize,f); + memcpy(vpkdata,&filesize,2); + filesize+=2; + } + fclose(f); + + if(region!=0) + { + j = 12; + } + else + { + j = 8; + } + for(i=0;i>3; + cardheader[5] |= (filesize & 0xFF); + cardheader[6] = filesize >> 8; + + if(region==0) + cardheader[8] = 0; + + int cardoffset; + + int l = 0; + for(i=1,cardoffset=0;i<=numcards;i++,cardoffset=0) + { + switch(fill) + { + case 0: + memset(carddata,0,0x81C); + break; + case 1: + for(j=0;j<0x81C;j++) + carddata[j] = j & 0xFF; + break; + } + cardheader[4] += 2; + for(j=0;j<0x0C;j++) + carddata[cardoffset++] = cardheader[j]; + + for(j=0;j>= 1; + NMI ^= 0x8646; + } + else + { + NMI >>= 1; + } + } + NMI ^= (DMCA_data[0x17-i] << 8); + } + + return NMI; +} + +NEDCLIB_API int make_nes(unsigned char *nesdata) +{ + unsigned short nmi; + if((nesdata[0]!='N')||(nesdata[1]!='E')||(nesdata[2]!='S')||(nesdata[3]!=0x1A)) + return 1; + if((nesdata[4] != 1) || (nesdata[5] != 1) || ((nesdata[6] & 0xFE) != 0) || (nesdata[7] != 0)) + return 2; + + nmi = (nesdata[0x3FFB+16] << 8) + (nesdata[0x3FFA+16]); + nmi = nes_enc(nmi); + nesdata[0x3FFB+16] = (nmi >> 8) & 0xFF; + nesdata[0x3FFA+16] = nmi & 0xFF; + + if(nesdata[6] & 1) + nesdata[0x3FFD + 16] &= 0x7F; + else + nesdata[0x3FFD + 16] |= 0x80; + + return 0; + +} \ No newline at end of file diff --git a/AC_e-Reader_Card_Creator/Decompression/External/Source Code/nevpk.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nevpk.cpp similarity index 98% rename from AC_e-Reader_Card_Creator/Decompression/External/Source Code/nevpk.cpp rename to AC_e-Reader_Card_Creator/Decompression/External/nedclib/nevpk.cpp index 3d3dd39..bf3d1e7 100644 --- a/AC_e-Reader_Card_Creator/Decompression/External/Source Code/nevpk.cpp +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/nevpk.cpp @@ -23,12 +23,12 @@ // return 1; // else // return 0; -// +// //} // //int vsprintf_s(char *string, int sizeinbytes, const char *format, va_list ap) //{ -// +// // vsprintf(string,format,ap); // return 0; //} @@ -163,10 +163,10 @@ int main(int argc, char* argv[]) if(!_stricmp(argv[i],"-log")) { i++; - if(fopen_s(&log,argv[i],"w")!=0) + if(fopen_s(&log_stream,argv[i],"w")!=0) { printf("Failed to open log file\n"); - log=NULL; + log_stream=NULL; } } @@ -207,7 +207,7 @@ int main(int argc, char* argv[]) 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"); @@ -225,7 +225,7 @@ int main(int argc, char* argv[]) } } log_write("\n"); - + //f=; if(fopen_s(&f,argv[file_in],"rb")!=0) @@ -299,7 +299,7 @@ int main(int argc, char* argv[]) b_size=best_size; } } - else if (result==3) //Window size is invalid, break out of the + else if (result==3) //Window size is invalid, break out of the { //Size loop, and try next window size. break; } @@ -385,7 +385,7 @@ int main(int argc, char* argv[]) 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]); @@ -394,12 +394,12 @@ int main(int argc, char* argv[]) i=vpk_decompress(vpk_buf,f); } fclose(f); - if(log!=NULL) - fclose(log); + if(log_stream!=NULL) + fclose(log_stream); j=i; free(vpk_buf); - + return 0; } diff --git a/AC_e-Reader_Card_Creator/Decompression/External/Source Code/raw2bmp.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/raw2bmp.cpp similarity index 100% rename from AC_e-Reader_Card_Creator/Decompression/External/Source Code/raw2bmp.cpp rename to AC_e-Reader_Card_Creator/Decompression/External/nedclib/raw2bmp.cpp diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/raw2dcs.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/raw2dcs.cpp new file mode 100644 index 0000000..0f2b3c7 --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/raw2dcs.cpp @@ -0,0 +1,325 @@ +/* Credits to Tim Schurewegen for his original raw2bmp tool, which I reverse engineered this tool +from. The main difference between his original tool and mine, is file dependency. this one does +not need the file dcslong.bmp, since the file is 100% generated by the tool, right down to the +address bars. Like his tool though, this one cannot generate short dcs files, since the short +dcs address bar info is missing. The other thing reversed from his tool, is 8/10 data modulation. +*/ + +/* I decided to Rewrite this program, so that it can also be used to convert dcs files, back into raw +files. While there is not much use for the raw files at this point, if a GBA emulator in the future +is released with some e-reader support, then the raw files will be useful then. +*/ + +#include +#include "dcs.h" +extern int dpi_multiplier; + +#define TYPE_LONG 0 +#define TYPE_SHORT 1 + +int OptV=0; + +#define VERBOSE(a) if(OptV) \ + { \ + printf(a); \ + } + +void usage (void) +{ + printf("Usage :\n DcsTool [options]\n"); + printf("Options :\n"); + printf(" -i \t\tInput File\t\t\t(Required)\n"); + printf(" -o \t\tOutput File\t\t\t(Required)\n"); + printf(" -v\t\t\tVebose\t\t\t(Optional)\n"); + printf(" -d\t\t\tConvert DCS to Raw\t\t\t(Required *)\n"); + printf(" -r\t\t\tConvert Raw to DCS\t\t\t(Required *)\n"); + printf("\n"); + printf(" * Options \"-d\" and \"-r\" cannont be used at the same time\n"); +} + +static int count_raw(FILE *f) +{ + unsigned short i=0,j=0; + int count=0; + int result; + result=fread(&i,1,2,f); + while(((i==0x0200) || (i==0x0300)) && (result == 2)) + { + fseek(f,0x66, SEEK_CUR); + result=fread(&j,1,2,f); + if(j==0x0100) + { + fseek(f,0x6E6,SEEK_CUR); + result=fread(&i,1,2,f); + count++; + } + else if(j==0x1900) + { + fseek(f,0xAF6, SEEK_CUR); + result=fread(&i,1,2,f); + count++; + } + + } + fseek(f,0,SEEK_SET); + return count; +} + +void read_next_raw(FILE *f) +{ + int result; + /* + if (filelen == 0xB60) + { + fread(raw,1,0xB60,f); + dotcodelen = 28; + bmplen = 0x7C; + } + else if (filelen == 0x750) + { + fread(raw,1,0x750,f); + dotcodelen = 18; + bmplen = 0x50; + } + */ + + result = fread(raw,1,2,f); + if(result) + { + if(raw[0][1]==3) + { + fread(&raw[0][2],1,0xB60-2,f); + dotcodelen = 28; + bmplen = 0x7C; + } + else if(raw[0][1] == 2) + { + fread(&raw[0][2],1,0x750-2,f); + dotcodelen = 18; + bmplen = 0x50; + } + else + { + fclose(f); + } + } + else + { + fclose(f); + } + + +} + +void write_bmp(FILE *f) +{ + int i,j; + VERBOSE("Writing BMP file\n") + /*if(dotcodelen == 28) + {*/ + if(dotcodelen == 28) + i=989*dpi_multiplier; + else + i=639*dpi_multiplier; + bmpheader[0x12] = i & 0xFF; + bmpheader[0x13] = i >> 8; + i/=32; + i++; + i*=4; + i*=(44*dpi_multiplier); + bmpheader[2] = (i + 0x3E) & 0xFF; + bmpheader[3] = ((i + 0x3E) >> 8) & 0xFF; + bmpheader[4] = ((i + 0x3E) >> 16) & 0xFF; + bmpheader[0x22] = i & 0xFF; + bmpheader[0x23] = (i >> 8) & 0xFF; + bmpheader[0x24] = (i >> 16) & 0xFF; + bmpheader[0x16] = (44 * dpi_multiplier); + + fwrite(bmpheader,1,62,f); + for(j=0;j<(44*dpi_multiplier);j++) + for(i=0;i<(bmplen*dpi_multiplier);i++) + fputc(bmpdata[j][i],f); + + //fwrite(bmpdata1,bmplen,44,f); + /*} + else + { + fwrite(bmpheader2,1,62,f); + fwrite(bmpdata2,bmplen,44,f); + }*/ +} + + +int main(int argc, char **argv) +{ + //int i, j; + long filelen; + FILE *f,*g; + + char filename[256]; + + int i,j; + int OptI=0; + int InFile; + int OptO=0; + int OutFile; + int OptD=0; + int OptR=0; + + printf("DcsTool Nintendo dotcode strip tool.\n"); + printf("Copyrighted by CaitSith2\n\n"); + + for (i=1;i > + /*for (i=0;i<(989*dpi_multiplier);i++) + { + for (j=0;j<(44*dpi_multiplier);j++) + { + if(j>1000) + break; + if (dcsbmp[i][j]) + { + printf("X"); + } + else + printf(" "); + } + printf("\n"); + } +*/ + VERBOSE("Done\n") + + return 0; + +} + + + + + +void clear_dcs(void) +{ + int i, j; + for (i=0;i<3956;i++) + for (j=0;j<176;j++) + dcsbmp[i][j] = 0; + for (i=0;i<28;i++) + for(j=0;j<130;j++) + _810mod[i][j]=0; +} diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbin/binraw.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbin/binraw.cpp new file mode 100644 index 0000000..1744cce --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbin/binraw.cpp @@ -0,0 +1,735 @@ + +#include "stdafx.h" +#include "../nedclib.h" +#include "rs.h" + +unsigned char ShortDotCodeHeader[0x30] = { + 0x00, 0x30, 0x01, 0x01, + 0x00, 0x01, 0x05, 0x10, + 0x00, 0x00, 0x10, 0x12, //Constant data + + 0x00, 0x00, //Header First 2 bytes + + 0x02, 0x00, //Constant data + + 0x00, 0x00, //Header Second 2 bytes + + 0x10, 0x47, 0xEF, //Global Checksum 1 + + 0x19, 0x00, 0x00, 0x00, 0x08, 0x4E, 0x49, + 0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F, 0x00, 0x22, + 0x00, 0x09, //Constant data + + 0x00, 0x00, //Header, last 8 bytes + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, //Header Checksum + 0x57 //Global Checksum 2 +}; + +unsigned char LongDotCodeHeader[0x30] = { + 0x00, 0x30, 0x01, 0x02, + 0x00, 0x01, 0x08, 0x10, + 0x00, 0x00, 0x10, 0x12, //Constant Data + + 0x00, 0x00, //Header, first 2 bytes + + 0x01, 0x00, //Constant data + + 0x00, 0x00, //Header, second 2 bytes + 0x10, 0x9A, 0x99, //Global Checksum 1 + + 0x19, 0x00, 0x00, 0x00, 0x08, 0x4E, 0x49, + 0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F, 0x00, 0x22, + 0x00, 0x09, //Constant data + + + 0x00, 0x00, //Header, last 8 bytes + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, //Header Checksum + 0x57 //Global Checksum 2 +}; + +unsigned char shortheader[0x18] = { + 0x00, 0x02, 0x00, 0x01, 0x40, 0x10, 0x00, 0x1C, + 0x10, 0x6F, 0x40, 0xDA, 0x39, 0x25, 0x8E, 0xE0, + 0x7B, 0xB5, 0x98, 0xB6, 0x5B, 0xCF, 0x7F, 0x72 +}; +unsigned char longheader[0x18] = { + 0x00, 0x03, 0x00, 0x19, 0x40, 0x10, 0x00, 0x2C, + 0x0E, 0x88, 0xED, 0x82, 0x50, 0x67, 0xFB, 0xD1, + 0x43, 0xEE, 0x03, 0xC6, 0xC6, 0x2B, 0x2C, 0x93 +}; + +NEDCLIB_API int signature=0; +NEDCLIB_API unsigned char signature_str[0x30]; + +extern unsigned short dotcodelen; +unsigned char bin_header[24]; + +void raw_header(unsigned char *bindata, unsigned char *data, int size) +{ + int i,j,k; + int global1, global2; + + for(i=0;i<0x30;i++) + data[i]=((size==0x81c)?LongDotCodeHeader[i]:ShortDotCodeHeader[i]); + + + for(i=0,j=0;i<12;i++) + j ^= bindata[i]; + + data[0x2E] = j; + data[0x0D] = bindata[0]; + data[0x0C] = bindata[1]; + data[0x11] = bindata[2]; + data[0x10] = bindata[3]; + + data[0x26] = bindata[4]; + data[0x27] = bindata[5]; + data[0x28] = bindata[6]; + data[0x29] = bindata[7]; + data[0x2A] = bindata[8]; + data[0x2B] = bindata[9]; + data[0x2C] = bindata[10]; + data[0x2D] = bindata[11]; + + + data[0x12] = 0x10; //calculate Global Checksum 1 + data[0x02] = 1; //Do not calculate Global Checksum 2 + + for(i=0x0C,j=0;i<0x81C;i++) + { + if(i&1) + j += bindata[i]; + else + j += (bindata[i] << 8); + } + j &= 0xFFFF; + j ^= 0xFFFF; + data[0x13] = (j & 0xFF00) >> 8; + data[0x14] = (j & 0x00FF); + + for(i=0,j=0;i<0x2F;i++) + j+=data[i]; + j &= 0xFF; + for(i=1,global2=0;i<0x2C;i++) + { + for(k=0,global1=0;k<0x30;k++) + { + global1 ^= bindata[((i-1)*0x30)+k+0x0C]; + } + global2 += global1; + } + global2 += j; + global2 &= 0xFF; + global2 ^= 0xFF; + data[0x2F] = global2; +} + +void interleave_dotcode(unsigned char *data, unsigned char *interleave, int dotcodepointer, int size) +{ + int i; + int dotcodeinterleave; + + if(bin_type==2) + { + dotcodeinterleave = bin_header[7]; + for(i=0;i0) + j++; + + dotcodeinterleave=bin_header[7]; + dotcodepointer=0; + + for(i=2;i1)&&(MultiStrip==0)) + sprintf_s(filename,255,"%s-%.2d.bin",binfile,k+1); + else + sprintf_s(filename,255,"%s",binfile); + + if(MultiStrip) + { + if(fopen_s(&g,filename,"rb+")) + if(fopen_s(&g,filename,"wb")) + return -4; + if(!count_bin(g)) + { + fseek(g,0,SEEK_SET); + bin_type=1; + } + else + { + fseek(g,0,SEEK_END); + } + } + else + { + bin_type=0; + if(fopen_s(&g,filename,"wb")) + return -4; + } + //fwrite(raw,1,j+k,g); + //fclose(g); + if(g!=NULL) + { + //return -4; + switch(bin_type) + { + case 0: //Will not covert to this old style format. + case 1: //All 48 bytes of the header is now included + //from now on. + fwrite(bin,1,((size==0xB60)?0x840:0x540),g); + break; + case 2: + fwrite(bin_header,1,8,g); + fwrite(bin,1,((bin_header[4]-bin_header[5])*bin_header[7]),g); + break; + } + + fclose(g); + numbin++; + } + } + + free_rs(); + + return (numbin>0)?0:-1; +} + +NEDCLIB_API int fixraw(char *rawfile) +{ + unsigned char data[255]; + + unsigned char dotcodetemp[0xB60]; + unsigned char raw[0xB60]; + int dotcodepointer=0; + int dotcodeinterleave; + + int num_dotcodes; + + int result; + int i,j,k; + int x,y; + + int temp; + int size; + FILE *f; + + initialize_rs(); + + if(fopen_s(&f,rawfile,"rb+")) + return -1; //Input file not opened. + num_dotcodes = count_raw(f); + + for(k=0;k0) + j++; + dotcodeinterleave=bin_header[7]; + dotcodepointer=0; + + for(i=2;i +#include +#include +#include + +#define d_mm 8 /* RS code over GF(2**4) - change to suit */ +#define d_nn 255 /* nn=2**mm -1 length of codeword */ +#define d_tt 127 /* number of errors that can be corrected */ +#define d_kk (d_nn - (2*d_tt)) /* kk = nn-2*tt */ + +#include "rs.h" + +#define NO_PRINT + +unsigned char mm=8; +unsigned char nn=255; +unsigned char tt=16; +unsigned char kk=239; + +int pp=0x187; +unsigned char *alpha_to, *index_of, *gg; +unsigned char *recd; +unsigned char b0 = 0x78; + +int rs_init=-1; +int curr_errlen=0; + +void make_rev(unsigned char *data, int len) +{ + for(int i=0;i>1);i++) + { + x=data[i]; + data[i]=data[len-i-1]; + data[len-i-1]=x; + } +} + +void zerofill(unsigned char *data, int len) +{ + for(int i=0;i=(nn+1)) + mask^=pp; + } +} + +void gen_poly(int errlen=16) +/* Obtain the generator polynomial of the tt-error correcting, length + nn=(2**mm -1) Reed Solomon code from the product of (X+alpha**i), i=1..2*tt +*/ + { + int i,j,x,y ; + if(gg!=NULL) + free(gg); + gg=(unsigned char*)malloc(errlen); + gg[0]=alpha_to[b0]; + for(i=1;i=0;j--) + { + if(j==0) + y=0; + else + y=gg[j-1]; + x=gg[j]; + if(x!=0) + { + x=index_of[x]+b0+i; + if(x>=0xFF) + x-=0xFF; + y^=alpha_to[x]; + } + gg[j]=y; + } + } + make_rev(gg,errlen); + } + +void initialize_rs(int bits, int polynomial, int index, int errlen) +{ + int i, j; + + mm=bits; + if(rs_init!=mm) + { + for(i=0,j=1;i=errlen;i--) + { + z = index_of[data[i] ^ data[errlen-1]]; + for(j=errlen-1;j>=0;j--) + { + if(j==0) + x=0; + else + x=data[j-1]; + if(z!=0xFF) + { + y=gg[j]; + if(y!=0xFF) + { + y+=z; if(y>=0xFF) y-=0xFF; + x^=alpha_to[y]; + } + } + data[j]=x; + } + } + invert_error_bytes(data,errlen); + reverse_byte_order(data,dtalen); +} + +int correct_errors(unsigned char *data, int dtalen, int errlen, unsigned char *erasure) +{ + int i,j=0,result; + int erase_pos[2*d_tt]; + for(i=0;i0) + if(eras_dec_rs(erase_pos,0)!=0) //0 syndrome should be returned now. + return -1; //Otherwise errors not correctable. + + for(i=0;i 0){ + phi[0] = 1; /* index form */ + phi[1] = alpha_to[eras_pos[0]]; + for (i=1;i < no_eras;i++) + { + U = eras_pos[i]; + for (j=1;j < i+2;j++) + { + tmp1 = index_of[phi[j-1]]; + tmp_pol[j] = (tmp1 == 0xFF)? 0 : alpha_to[(U+tmp1)%0xFF]; + } + for (j=1;j < i+2;j++) + phi[j] = phi[j]^tmp_pol[j]; + } + /* put phi[x] in index form */ + make_rev(phi,nn-kk+1); + } + +/* recd[] is in polynomial form, convert to index form */ + make_rev(recd,nn); + +/* first form the syndromes; i.e., evaluate recd(x) at roots of g(x) namely + @**(b0+i), i = 0, ... ,(2*tt-1) */ + for (i=1; i <= nn-kk; i++) + { s[i] = 0 ; + for (j=0; j < nn; j++) + if (recd[j] != 0xFF) + s[i] ^= alpha_to[(recd[j]+(b0+i-1)*j)%0xFF] ; /* recd[j] in index form */ +/* convert syndrome from polynomial form to index form */ + if (s[i] != 0) syn_error = 1 ; /* set flag if non-zero syndrome => error */ + s[i] = index_of[s[i]] ; + }; + + + if (syn_error) + { /* if syndrome is zero, modified recd[] is a codeword */ +/* Begin Berlekamp-Massey algorithm to determine error+erasure locator polynomial */ + r = no_eras; + deg_phi = no_eras; + L = no_eras; + if (no_eras > 0) + { + /* Initialize lambda(x) and b(x) (in poly-form) to phi(x) */ + for (i=0;i < deg_phi+1;i++) lambda[i] = (phi[i] == 0xFF)? 0 : alpha_to[phi[i]]; + for (i=deg_phi+1;i < 2*tt+1;i++) lambda[i] = 0; + deg_lambda = deg_phi; + for (i=0;i < 2*tt+1;i++) b[i] = lambda[i]; + } + else + { + lambda[0] = 1; + for (i=1;i < 2*tt+1;i++) lambda[i] = 0; + for (i=0;i < 2*tt+1;i++) b[i] = lambda[i]; + } + while (++r <= 2*tt) /* r is the step number */ + { + /* Compute discrepancy at the r-th step in poly-form */ + discr_r = 0; + for (i=0;i < 2*tt+1;i++) + { + if ((lambda[i] != 0) && (s[r-i] != 0xFF)) + { + tmp = alpha_to[(index_of[lambda[i]]+s[r-i])%0xFF]; + discr_r ^= tmp; + } + } + if (discr_r == 0) + { + /* 3 lines below: B(x) <-- x*B(x) */ + tmp_pol[0] = 0; + for (i=1;i < 2*tt+1;i++) tmp_pol[i] = b[i-1]; + for (i=0;i < 2*tt+1;i++) b[i] = tmp_pol[i]; + } + else + { + /* 5 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ + T[0] = lambda[0]; + for (i=1;i < 2*tt+1;i++) + { + tmp = (b[i-1] == 0)? 0 : alpha_to[(index_of[discr_r]+index_of[b[i-1]])%0xFF]; + T[i] = lambda[i]^tmp; + } + + if (2*L <= r+no_eras-1) + { + L = r+no_eras-L; + /* 2 lines below: B(x) <-- inv(discr_r) * lambda(x) */ + for (i=0;i < 2*tt+1;i++) + b[i] = (lambda[i] == 0)? 0 : alpha_to[(index_of[lambda[i]]-index_of[discr_r]+nn)%0xFF]; + for (i=0;i < 2*tt+1;i++) lambda[i] = T[i]; + } + else + { + for (i=0;i < 2*tt+1;i++) lambda[i] = T[i]; + /* 3 lines below: B(x) <-- x*B(x) */ + tmp_pol[0] = 0; + for (i=1;i < 2*tt+1;i++) tmp_pol[i] = b[i-1]; + for (i=0;i < 2*tt+1;i++) b[i] = tmp_pol[i]; + } + } + } +/* Put lambda(x) into index form */ + make_rev(lambda,2*tt+1); + +/* Compute deg(lambda(x)) */ + deg_lambda = 2*tt; + while ((lambda[deg_lambda] == 0xFF) && (deg_lambda > 0)) + --deg_lambda; + if (deg_lambda <= 2*tt) + { + /* Find roots of the error+erasure locator polynomial. By Chien Search */ + for (i=1; i < 2*tt+1; i++) reg[i] = lambda[i] ; + count = 0 ; /* Number of roots of lambda(x) */ + for (i=1; i <= nn; i++) + { + q = 1 ; + for (j=1; j <= deg_lambda; j++) + if (reg[j] != 0xFF) + { + reg[j] = (reg[j]+j)%0xFF ; + q ^= alpha_to[(reg[j])%0xFF] ; + } ; + if (!q) /* store root (index-form) and error location number */ + { + root[count] = i; + loc[count] = nn-i; + count++; + }; + } ; + + if (deg_lambda == count) /* correctable error */ + { +/* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo x**(nn-kk)). in poly-form */ + for (i=0;i < 2*tt;i++) + { + omega[i] = 0; + for (j=0;(j < deg_lambda+1) && (j < i+1);j++) + { + if ((s[i+1-j] != 0xFF) && (lambda[j] != 0xFF)) + tmp = alpha_to[(s[i+1-j]+lambda[j])%0xFF]; + else + tmp = 0; + omega[i] ^= tmp; + } + } + omega[2*tt] = 0; +/* Compute lambda_pr(x) = formal derivative of lambda(x) in poly-form */ + for (i=0;i < tt;i++) + { + lambda_pr[2*i+1] = 0; + lambda_pr[2*i] = (lambda[2*i+1] == 0xFF)? 0 : alpha_to[lambda[2*i+1]]; + } + lambda_pr[2*tt] = 0; +/* Compute deg(omega(x)) */ + deg_omega = 2*tt; + while ((omega[deg_omega] == 0) && (deg_omega > 0)) + --deg_omega; +/* Compute error values in poly-form. num1 = omega(inv(X(l))), + num2 = inv(X(l))**(b0-1) and den = lambda_pr(inv(X(l))) all in poly-form */ + for (j=0;j < count;j++) + { + pres_root = root[j]; + pres_loc = loc[j]; + num1 = 0; + for (i=0;i < deg_omega+1;i++) + { + if (omega[i] != 0) + tmp = alpha_to[(index_of[omega[i]]+i*pres_root)%0xFF]; + else + tmp = 0; + num1 ^= tmp; + } + num2 = alpha_to[(pres_root*(b0-1))%0xFF]; + den = 0; + for (i=0;i < deg_lambda+1;i++) + { + if (lambda_pr[i] != 0) + tmp = alpha_to[(index_of[lambda_pr[i]]+i*pres_root)%0xFF]; + else + tmp = 0; + den ^= tmp; + } + if (den == 0) + { + printf("\n ERROR: denominator = 0\n"); + } + err[pres_loc] = 0; + if (num1 != 0) + { + err[pres_loc] = alpha_to[(index_of[num1]+index_of[num2]+(nn-index_of[den]))%0xFF]; + } + } +/* Correct word by subtracting out error bytes. First convert recd[] into poly-form */ + make_pow(recd,nn); + for (j=0;j < count;j++) + recd[loc[j]] ^= err[loc[j]]; + + return(count); + } + else /* deg(lambda) unequal to number of roots => uncorrectable error detected */ + return(-2); + } + else /* deg(lambda) > 2*tt => uncorrectable error detected */ + return(-3); + } + else + { /* no non-zero syndromes => no errors: output received codeword */ + make_pow(recd,nn); + return(0); + } +} diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbin/rs.h b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbin/rs.h new file mode 100644 index 0000000..9f83200 --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbin/rs.h @@ -0,0 +1,19 @@ +//unsigned char pp [mm+1] = { 1,1,0,0,0,0,1,1,1} ; /* specify irreducible polynomial coeffts */ +//unsigned char alpha_to [nn+1], index_of [nn+1], gg [nn-kk+1] ; +//unsigned char recd [nn], data [kk], bb [nn-kk] ; + +void make_rev(unsigned char *data, int len); +void make_pow(unsigned char *data, int len); +void invert_error_bytes(unsigned char *data, int len); +void reverse_byte_order(unsigned char *data, int len); +void zerofill_error_bytes(unsigned char *data, int len); +void generate_gf(); +void gen_poly(); +void append_error_info(unsigned char *data, int dtalen, int errlen); +int verify_error_info(unsigned char *data, int dtalen, int errlen); + +int correct_errors(unsigned char *data, int dtalen, int errlen, unsigned char *erasure=NULL); +int eras_dec_rs(int *eras_pos,int no_eras); +void initialize_rs(int bits=8, int polynomial=0x187, int index=0x78, int errlen=16); +void free_rs(); +int is_rs_initialized(); \ No newline at end of file diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/address.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/address.cpp new file mode 100644 index 0000000..b9c2fd8 --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/address.cpp @@ -0,0 +1,248 @@ +#include "stdafx.h" + +#define DCS +#include "dcs.h" + +void calc_addr(int address) +{ + int start; + + int mask,bits; + + /* Thanks to Martin Korth, The method to calculate the error + correction info on the address bars is now known. As a result + it is now possible to calculate what should be in the long and + short dotcodes rather than have a defined table. */ + + /* This is an Address bar calculator, for "Dot Code Technology", + which is made by Olympus Optical Co. Ltd. The address bars consist + of a 14 bit address, and 10 bits of reed-solomon error correction + information. The first valid address bar as far as I know, is 1. + + On a dotcode strip, there is 30 dots in between the top and bottom + sync marker, that the address bar is contained in. Top 2 dots are dead + space, and should be always white. Next dot down, is black, to indicate + that this is the top of the dotcode strip. + Next 24 dots is the address and reed-solomon error correction info. + Next Dot is white, to indicate this is bottom of the dotcode strip + Last 2 dots are dead space, and should be white, for proper sync marker + recognition. */ + + /* The reed-solomon error correction on the address bar, is capable of + correcting up to 2 bits of error in the address bar. */ + + /* Nintendo e-Reader dotcodes use Addresss 1 (on left) to 19 (on right) + for short dotcodes, and address 25 (on left) to 53 (on right) for long + dotcodes. Any other address ranges will cause the dotcode to be rejected + by the Nintendo e-Reader. The upper address limit that is decoded for + is 60 (61 on right hand side.) Anything higher is not decoded by nintendo + e-Reader. */ + + //addr[0] = 0x3FF; + if((addr[0] >> 10) < address) + { + start = (addr[1] >> 10) + 1; + } + if(((addr[0] >> 10) == address)&&(address!=0)) + return; //No need to calculate anything. + if(((addr[0] >> 10) > address) || (addr[1] == 0x3FF)) + { + //Must recalculate the address starting from 0. + start = 1; + addr[1] = 0x3FF; + } + + for(int i=start,base=0x769;i<=(address+1);i++,base=0x769) + { + addr[0] = addr[1]; + addr[1] = addr[0] ^ ((i & (-i)) * base); + for(mask=0x1FFF,bits=0x651;bits>0;mask>>=1,bits>>=1) + { + if((i & mask)==0) + { + if(bits & 1) + addr[1] ^= base; + base <<= 1; + } + } + } +} + +/* ---- ADDRESS BAR REED SOLOMON VERIFICATION ---- */ + +int addr_init=0; + +unsigned char Alpha_to[32]; +unsigned char Index_of[32]; + +unsigned char multiply_table[2][24] = { + { + 0x0F, 0x15, 0x18, 0x0C, 0x06, 0x03, 0x13, 0x1B, + 0x1F, 0x1D, 0x1C, 0x0E, 0x07, 0x11, 0x1A, 0x0D, + 0x14, 0x0A, 0x05, 0x10, 0x08, 0x04, 0x02, 0x01 + }, + { + 0x14, 0x10, 0x02, 0x09, 0x17, 0x0F, 0x0C, 0x13, + 0x1D, 0x07, 0x0D, 0x05, 0x04, 0x12, 0x0B, 0x1E, + 0x18, 0x03, 0x1F, 0x0E, 0x1A, 0x0A, 0x08, 0x01 + } +}; + +unsigned char syndrome[2]; + +void init_tables() +{ + int i,j; + Alpha_to[0x1F] = 0; + Index_of[0x00] = 0x1F; + for(i=0,j=1;i<0x1E;i++) + { + Alpha_to[i]=j; + Index_of[j]=i; + j<<=1; + if(j>0x1F) + j^=0x25; + } +} + + +int generate_syndrome(unsigned long addr_data) +{ + int i,j,error=0; + unsigned long address = addr_data ^ 0x3FF; + for(i=0;i<2;i++) + { + syndrome[i] = 0; + for(j=0;j<24;j++) + { + if(address & (1 << (23-j))) + { + syndrome[i] ^= multiply_table[i][j]; + } + } + syndrome[i] = Index_of[syndrome[i]]; + if(syndrome[i] != 0x1F) + error=1; + } + return error; +} + +int rs_add(unsigned char num1, unsigned char num2) +{ + int i,j; + if((num1==0x1F)||(num2==0x1F)) + return 0x1F; + i=num1+num2; + j=i-0x1F; + if(i>0x1E) + return j; + else + return i; +} + +int rs_multiply(int num1, int num2) +{ + int i,j; + for(i=0,j=0;i=0;h--) + { + m=Alpha_to[rsdata[0]]; + for(i=1;i<=numloops;i++) + { + k=rsdata[i]; + j=rs_multiply(h,i); + j=rs_add(k,j); + l=Alpha_to[j]; + m^=l; + } + if(m==0) + { + location[n++] = h; + if(n==numloops) + return 0; + } + } + return -1; +} + +int correct_address(unsigned long *addr_data) +{ + int i,j; + int num_loops=2; + if(addr_init==0) + init_tables(); + generate_syndrome(addr_data[0]); + unsigned long address = addr_data[0] ^ 0x3FF; + for(i=0,j=0;i + +#ifndef DCS +#define DCS + + + +unsigned short bmplen; + +unsigned long addr[2] = { 0,0x3FF }; + +unsigned char raw[28][104]; +unsigned char dcsbmp[7912][352]; + +unsigned char _810mod[28][130]; + +unsigned char bmpheader[62] = +{ + 0x42, 0x4D, 0x8E, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0xDD, 0x03, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, +}; +/* +unsigned char bmpheader2[62] = +{ + 0x42, 0x4D, 0xFE, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x7F, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0x0D, 0x00, 0x00, 0xC2, 0x1E, 0x00, 0x00, 0xC2, 0x1E, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, +} ;*/ + +unsigned char bmpdata[352][992]; + + +//unsigned char bmpdata1[44][0x7C]; +//unsigned char bmpdata2[44][0x50]; + +int bmp_invert; + + + + +unsigned char modtable[16] = { +0x00, //00000 +0x01, //00001 +0x02, //00010 +0x12, //10010 +0x04, //00100 +0x05, //00101 +0x06, //00110 +0x16, //10110 +0x08, //01000 +0x09, //01001 +0x0A, //01010 +0x14, //10100 +0x0C, //01100 +0x0D, //01101 +0x11, //10001 +0x10, //10000 +}; + +unsigned char demodtable[32] = { +//{ +0x00,0x01,0x02,0xFF,0x04,0x05,0x06,0xFF,0x08,0x09,0x0A,0xFF,0x0C,0x0D,0xFF,0xFF, +0x0F,0x0E,0x03,0xFF,0x0B,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +/*}, +{ +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0x0B,0xFF,0x03,0x0E,0x0F, +0xFF,0xFF,0x0D,0x0C,0xFF,0x0A,0x09,0x08,0xFF,0x06,0x05,0x04,0xFF,0x02,0x01,0x00, +}*/}; + +/* +unsigned short addressbar[2][29] = { { +0x9866, //Left most address bar +0xD316, +0x45F6, +0x604E, +0xF6AE, +0xBDDE, +0x2B3E, +0x4141, +0xD7A1, +0x9CD1, +0x0A31, +0x2F89, +0xB969, +0xF219, +0x64F9, +0xE0C5, +0x7625, +0x3D55, +0xABB5, +0x8E0D, +0x18ED, +0x539D, +0xC57D, +0x1183, +0x8763, +0xCC13, +0x5AF3, +0x7F4B, +0xE9AB, //Right most address bar +}, { +0x6920, +0x2250, +0xB4B0, +0x9108, +0x07E8, +0x4C98, +0xDA78, +0x5E44, +0xC8A4, +0x83D4, +0x1534, +0x308C, +0xA66C, +0xED1C, +0x7BFC, +0xAF02, +0x39E2, +0x7292, +0xE472, + +}, +};*/ + +#endif + +extern unsigned short dotcodelen; +extern unsigned short bmplen; + +//extern int dpi_multiplier; + +extern unsigned long addr[2]; +extern unsigned char raw[28][104]; +extern unsigned char dcsbmp[7912][352]; +extern unsigned char _810mod[28][130]; +extern unsigned char bmpheader1[]; +extern unsigned char bmpheader2[]; +extern unsigned char bmpdata[352][992]; +extern unsigned char bmpdata1[44][0x7C]; +extern unsigned char bmpdata2[44][80]; +extern unsigned char modtable[]; +extern unsigned char demodtable[32]; +//extern unsigned short addressbar[2][29]; + +extern int bmp_invert; + +void clear_dcs(void); +void eight_ten_modulate(void); +void init_dcs(void); +void flipbmp(void); +void makebmp(void); +void make_dcs(void); + +void eight_ten_demodulate(void); +void reversebmp(void); +void reverse_dcs(void); +int read_bmp(FILE *f); + +int correct_address(unsigned long *addr_data); +void calc_addr(int address); diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/dcs_decode.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/dcs_decode.cpp new file mode 100644 index 0000000..bb3ba9c --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/dcs_decode.cpp @@ -0,0 +1,453 @@ +#include "stdafx.h" +#include +#include + +#define DCS +#include "dcs.h" + +#include "../nedclib.h" + +unsigned char mod0,mod1,mod2,mod3,mod4,mod5,mod6,mod7; +unsigned short dotcodelen; +unsigned char bmpdata1[44][0x7C]; +unsigned char bmpdata2[44][0x50]; + +int read_bmp(FILE *f) +{ + int filelen,i,j; + unsigned short k; + int x,xx,y; + int bmp_start; + fseek(f,0,SEEK_END); + filelen = ftell(f); + fseek(f,0,SEEK_SET); + fread(&i,1,2,f); + if((i&0xFFFF)!=0x4D42) + return 0; //Not a bmp file + fread(&i,1,4,f); + if(i!=filelen) + return 0; //Not a bmp file + fread(&i,1,4,f); + if(i!=0) + return 0; //Not a bmp file + fread(&bmp_start,1,4,f); + + fseek(f,4,SEEK_CUR); + fread(&x,1,4,f); + fread(&y,1,4,f); + fseek(f,2,SEEK_CUR); + fread(&k,1,2,f); + if(k!=1) + return 0; //Not a dotcode bmp + fread(&i,1,4,f); + if(i!=0) + return 0; //Compressed bmp not supported. + + fseek(f,0x36,SEEK_SET); + fread(&bmp_invert,1,4,f); + + + switch(y) + { + case 44: + dpi_multiplier = 1; + break; + case 88: + dpi_multiplier = 2; + break; + case 176: + dpi_multiplier = 4; + break; + case 352: + dpi_multiplier = 8; + break; + default: + return 0; //Not a dotcode bmp. + } + + + fseek(f,0x36,SEEK_SET); + fread(&bmp_invert,1,4,f); + fseek(f,62,SEEK_SET); + + for(i=0;i0;j+=4,xx-=32) + { + fread(&bmpdata[i][j],1,4,f); + } + } + bmplen = j; + for(dotcodelen=0,xx=x-5;xx>(35*dpi_multiplier);dotcodelen++,xx-=(35*dpi_multiplier)); + + /*if (filelen == 0x158E) + { + fseek(f,62,SEEK_SET); + fread(bmpdata1,0x7C,44,f); + dotcodelen = 28; + bmplen = 0x7C; + } + else + { + fseek(f,62,SEEK_SET); + fread(bmpdata2,0x50,44,f); + dotcodelen = 18; + bmplen = 0x50; + }*/ + + return 1; //Dotcode bmp read successfully +} + +int read_dcs_pixel(int x, int y, int source=1) +{ + int xx,yy; + switch (dpi_multiplier) + { + case 1: + xx = x; + yy = y; + break; + case 2: + xx = x * 2; + yy = y * 2; + break; + case 4: + xx = (x * 4) + 1; + yy = (y * 4) + 1; + break; + case 8: + xx = (x * 8) + 2; + yy = (y * 8) + 2; + break; + } + switch (source) + { + case 0: //From bmpdata + return (bmpdata[yy][xx/8] & (1 << (7 - (xx%8)))) >> (7-(xx%8)); + break; + case 1: //From dcsbmp + default: + return dcsbmp[xx][yy]; + } + +} + +unsigned char bitflip(unsigned char byte) +{ + int i,j=0; + for(i=0;i<5;i++) + { + if(byte&(1<>i; + } + return j; +} + +void invertmod(void) +{ + mod7^=0x1F; + mod6^=0x1F; + mod5^=0x1F; + mod4^=0x1F; + mod3^=0x1F; + mod2^=0x1F; + mod1^=0x1F; + mod0^=0x1F; +} + +void read_reverse(int ii, int jj, int inverse) +{ + int i=(dotcodelen-1-ii); + int j=(104-4-jj); + mod0 = _810mod[i][((j*10)/8)+4] & 0x1F; + mod1 = (_810mod[i][((j*10)/8)+4] >> 5) & 0x07; + mod1 += (_810mod[i][((j*10)/8)+3] << 3) & 0x18; + mod2 = (_810mod[i][((j*10)/8)+3] >> 2) & 0x1F; + mod3 = (_810mod[i][((j*10)/8)+3] >> 7) & 0x01; + mod3 += (_810mod[i][((j*10)/8)+2] << 1) & 0x1E; + mod4 = (_810mod[i][((j*10)/8)+2] >> 4) & 0x0F; + mod4 += (_810mod[i][((j*10)/8)+1] << 4) & 0x10; + mod5 = (_810mod[i][((j*10)/8)+1] >> 1) & 0x1F; + mod6 = (_810mod[i][((j*10)/8)+1] >> 6) & 0x03; + mod6 += (_810mod[i][((j*10)/8)+0] << 2) & 0x1C; + mod7 = (_810mod[i][((j*10)/8)+0] >> 3) & 0x1F; + mod0=bitflip(mod0); + mod1=bitflip(mod1); + mod2=bitflip(mod2); + mod3=bitflip(mod3); + mod4=bitflip(mod4); + mod5=bitflip(mod5); + mod6=bitflip(mod6); + mod7=bitflip(mod7); + + if(inverse) + invertmod(); +} +void read_forward(int i, int j, int inverse) +{ + mod7 = _810mod[i][((j*10)/8)+4] & 0x1F; + mod6 = (_810mod[i][((j*10)/8)+4] >> 5) & 0x07; + mod6 += (_810mod[i][((j*10)/8)+3] << 3) & 0x18; + mod5 = (_810mod[i][((j*10)/8)+3] >> 2) & 0x1F; + mod4 = (_810mod[i][((j*10)/8)+3] >> 7) & 0x01; + mod4 += (_810mod[i][((j*10)/8)+2] << 1) & 0x1E; + mod3 = (_810mod[i][((j*10)/8)+2] >> 4) & 0x0F; + mod3 += (_810mod[i][((j*10)/8)+1] << 4) & 0x10; + mod2 = (_810mod[i][((j*10)/8)+1] >> 1) & 0x1F; + mod1 = (_810mod[i][((j*10)/8)+1] >> 6) & 0x03; + mod1 += (_810mod[i][((j*10)/8)+0] << 2) & 0x1C; + mod0 = (_810mod[i][((j*10)/8)+0] >> 3) & 0x1F; + + if(inverse) + invertmod(); +} + +int checkmod(void) +{ + read_forward(0,0,0); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) + { + read_forward(1,0,0); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) + { + return 0; + } + } + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) + { + read_forward(1,0,0); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) + { + return 0; + } + } + read_forward(0,0,1); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) + { + read_forward(1,0,1); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) + { + return 1; + } + } + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) + { + read_forward(1,0,1); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) + { + return 1; + } + } + read_reverse(0,0,0); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) + { + read_reverse(1,0,0); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) + { + return 2; + } + } + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) + { + read_reverse(1,0,0); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) + { + return 2; + } + } + read_reverse(0,0,1); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) + { + read_reverse(1,0,1); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) + { + return 3; + } + } + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) + { + read_reverse(1,0,1); + if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) + { + return 3; + } + } + + return -1; + +} + + +void eight_ten_demodulate(void) +{ + int i, j; + unsigned char raw0,raw1,raw2,raw3; + int modtype=0; + + modtype=checkmod(); + if(modtype==-1) + { + printf("This is not a nintendo e-reader dotcode\n"); + exit(1); + } + for (i=0;i>3)==0; + else + bmp_flip = ((bmpdata2[9][0] & 0x08)>>3)==0;*/ + bmp_flip = (read_dcs_pixel(4,9,0)==0); + } + else + { + /*if(bmplen == 0x7C) + bmp_flip = ((bmpdata1[9][0] & 0x08)>>3)==1; + else + bmp_flip = ((bmpdata2[9][0] & 0x08)>>3)==1;*/ + bmp_flip = (read_dcs_pixel(4,9,0)==1); + } + + //if (bmplen == 0x7C) + //{ + for (i=0;i> 7) & 0x01; + dcsbmp[(i*8)+1][j] = (bmpdata[(width-1)-j][i] >> 6) & 0x01; + dcsbmp[(i*8)+2][j] = (bmpdata[(width-1)-j][i] >> 5) & 0x01; + dcsbmp[(i*8)+3][j] = (bmpdata[(width-1)-j][i] >> 4) & 0x01; + dcsbmp[(i*8)+4][j] = (bmpdata[(width-1)-j][i] >> 3) & 0x01; + dcsbmp[(i*8)+5][j] = (bmpdata[(width-1)-j][i] >> 2) & 0x01; + dcsbmp[(i*8)+6][j] = (bmpdata[(width-1)-j][i] >> 1) & 0x01; + dcsbmp[(i*8)+7][j] = (bmpdata[(width-1)-j][i] >> 0) & 0x01; + } + } + + if (bmp_flip) + { + for (i=0;i> 7) & 0x01; + dcsbmp[(i*8)+1][j] = (bmpdata2[43-j][i] >> 6) & 0x01; + dcsbmp[(i*8)+2][j] = (bmpdata2[43-j][i] >> 5) & 0x01; + dcsbmp[(i*8)+3][j] = (bmpdata2[43-j][i] >> 4) & 0x01; + dcsbmp[(i*8)+4][j] = (bmpdata2[43-j][i] >> 3) & 0x01; + dcsbmp[(i*8)+5][j] = (bmpdata2[43-j][i] >> 2) & 0x01; + dcsbmp[(i*8)+6][j] = (bmpdata2[43-j][i] >> 1) & 0x01; + } + else + { + bmpdata2[43-j][i] ^= ((bmp_invert == 0) ? 0xFF : 0); + dcsbmp[(i*8)+0][j] = (bmpdata2[43-j][i] >> 7) & 0x01; + dcsbmp[(i*8)+1][j] = (bmpdata2[43-j][i] >> 6) & 0x01; + dcsbmp[(i*8)+2][j] = (bmpdata2[43-j][i] >> 5) & 0x01; + dcsbmp[(i*8)+3][j] = (bmpdata2[43-j][i] >> 4) & 0x01; + dcsbmp[(i*8)+4][j] = (bmpdata2[43-j][i] >> 3) & 0x01; + dcsbmp[(i*8)+5][j] = (bmpdata2[43-j][i] >> 2) & 0x01; + dcsbmp[(i*8)+6][j] = (bmpdata2[43-j][i] >> 1) & 0x01; + dcsbmp[(i*8)+7][j] = (bmpdata2[43-j][i] >> 0) & 0x01; + } + } + } + if (bmp_flip) + { + for (i=0;i<44/2;i++) + { + for(j=0;j<639;j++) + { + dcsbmp[j][i] ^= dcsbmp[639-1-j][44-1-i]; + dcsbmp[639-1-j][44-1-i] ^= dcsbmp[j][i]; + dcsbmp[j][i] ^= dcsbmp[639-1-j][44-1-i]; + } + } + } + + }*/ + +} + +void reverse_dcs(void) +{ + int i, j, k, count=0; + for(i=0;i +#define DCS +#include "dcs.h" + +#include "../nedclib.h" + +void eight_ten_modulate(void) +{ + int i, j; + unsigned char raw0,raw1,raw2,raw3; + unsigned char mod0,mod1,mod2,mod3,mod4,mod5,mod6,mod7; + for (i=0;i>4]; + mod1 = modtable[(raw0 & 0x0F)]; + mod2 = modtable[(raw1 & 0xF0)>>4]; + mod3 = modtable[(raw1 & 0x0F)]; + mod4 = modtable[(raw2 & 0xF0)>>4]; + mod5 = modtable[(raw2 & 0x0F)]; + mod6 = modtable[(raw3 & 0xF0)>>4]; + mod7 = modtable[(raw3 & 0x0F)]; + + _810mod[i][((j*10)/8)+0] = ((mod0 & 0x1F) << 3) + ((mod1 & 0x1C) >> 2); + _810mod[i][((j*10)/8)+1] = ((mod1 & 0x03) << 6) + ((mod2 & 0x1F) << 1) + ((mod3 & 0x10) >> 4); + _810mod[i][((j*10)/8)+2] = ((mod3 & 0x0F) << 4) + ((mod4 & 0x1E) >> 1); + _810mod[i][((j*10)/8)+3] = ((mod4 & 0x01) << 7) + ((mod5 & 0x1F) << 2) + ((mod6 & 0x18) >> 3); + _810mod[i][((j*10)/8)+4] = ((mod6 & 0x07) << 5) + ((mod7 & 0x1F)); + } + } +} + +NEDCLIB_API int dpi_multiplier = 1; +NEDCLIB_API int smooth = 0; +int fill=0; + +void draw_dcs_pixel(int x, int y) +{ + int i,j; + + switch(dpi_multiplier) + { + case 1: //300 DPI + dcsbmp[x][y] = 1; + break; + case 2: //600 DPI + if(fill!=0) + { + for(i=0;i<2;i++) + for(j=0;j<2;j++) + dcsbmp[(x*2)+i][(y*2)+j] = 1; + } + else + { + dcsbmp[(x*2)][(y*2)] = 1; + } + break; + case 4: //1200 DPI + if(fill!=0) + { + for(i=0;i<4;i++) + for(j=0;j<4;j++) + dcsbmp[(x*4)+i][(y*4)+j] = 1; + } + else + { + for(i=1;i<3;i++) + for(j=1;j<3;j++) + dcsbmp[(x*4)+i][(y*4)+j] = 1; + } + break; + case 8: //2400 DPI + if(fill!=0) + { + for(i=0;i<8;i++) + for(j=0;j<8;j++) + dcsbmp[(x*8)+i][(y*8)+j] = 1; + } + else + { + for(i=2;i<5;i++) + { + dcsbmp[(x*8)+i][(y*8)+1] = 1; + dcsbmp[(x*8)+i][(y*8)+5] = 1; + } + for(i=1;i<6;i++) + for(j=2;j<5;j++) + dcsbmp[(x*8)+i][(y*8)+j] = 1; + } + break; + } +} + +void draw_sync_marker(int x, int y) +{ + int xx, yy; + int i,j,k, l, m; + + xx=(x*dpi_multiplier); + yy=(y*dpi_multiplier); + l=(5*dpi_multiplier); + + if((dpi_multiplier==1)||(smooth==0)) + { + fill = 1; + for(i=1;i<4;i++) + for(j=1;j<4;j++) + { + draw_dcs_pixel(x,y+j); + draw_dcs_pixel(x+4,y+j); + draw_dcs_pixel(x+i,y+j); + draw_dcs_pixel(x+i,y); + draw_dcs_pixel(x+i,y+4); + } + fill = 0; + } + else + { + k = (l/2)*(l/2); + for(i=(l/2);i>=0;i--) + for(j=(l/2);j>=0;j--) + { + m=((i*i)+(j*j))<=k ? 1 : 0; + if(((i+j)==(l/2))&&((i==0)||(j==0))) + m=0; + dcsbmp[xx+((l/2)-1)+i][yy+((l/2)-1)+j] = m; + dcsbmp[xx+((l/2)-1)+i][yy+((l/2)-1)-j] = m; + dcsbmp[xx+((l/2)-1)-i][yy+((l/2)-1)-j] = m; + dcsbmp[xx+((l/2)-1)-i][yy+((l/2)-1)+j] = m; + //dcsbmp[xx+((l/2)-1)][yy+((l/2)-1)] = 1; + } + } +} + +void draw_address_bar(int dotcodeblock, int address) +{ + int i,j=dotcodeblock; + draw_dcs_pixel((j*35)+4,9); //Render the T pixel + draw_dcs_pixel(((j+1)*35)+4,9); //The B pixel is not rendered. + + calc_addr(j+address); //Calculate Error info for Address. + + for (i=0;i<16;i++) //Render the A pixels and E pixels. (A = Address, E = Error correction info.) + { + if(((((0x0001 << (i)) & addr[0]) >> (i)))==1) + { + draw_dcs_pixel((j*35)+4,33-i); + } + if(((((0x0001 << (i)) & addr[1]) >> (i)))==1) + { + draw_dcs_pixel(((j+1)*35)+4,33-i); + } + } +} + + +void init_dcs(void) +{ + /* Purpose - Draw the bmp template for Dotcodes. */ + /* + XXX XXX + YYYYY YYYYY + YYYYY Z Z Z Z Z Z Z Z Z Z Z Z YYYYY + YYYYY YYYYY + XXX XXX + + + T T + A A + A A + . . + . . + . . + A A + A A + E E + E E + E E + . . + . . + . . + E E + E E + B B + + + XXX XXX + YYYYY YYYYY + YYYYY Z Z Z Z Z Z Z Z Z Z Z Z YYYYY + YYYYY YYYYY + XXX XXX + */ + int i, j; + + int start_address; + + /*if(dotcodelen==28) + start_address=25; + else + start_address=1;*/ + start_address=raw[1][1]; + + for (j=0;j> (7 - (count % 8))) & 0x01) + draw_dcs_pixel((i*35)+9+k,j+6); + //dcsbmp[(i*35)+9+k][j+6] = (_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01; + } + for (j=0;j<26;j++) + for (k=0;k<34;k++,count++) + { + if((_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01) + draw_dcs_pixel((i*35)+5+k,j+9); + //dcsbmp[(i*35)+5+k][j+9] = (_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01; + } + for (j=0;j<3;j++) + for (k=0;k<26;k++,count++) + { + //if(((_810mod[i][(int)(count/8)] >> (7 - (count % 8))))>0) + if((_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01) + draw_dcs_pixel((i*35)+9+k,j+35); + //dcsbmp[(i*35)+9+k][j+35] = (_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01; + } + + count=0; + } + +} \ No newline at end of file diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/rawbmp.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/rawbmp.cpp new file mode 100644 index 0000000..d7935bf --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/rawbmp/rawbmp.cpp @@ -0,0 +1,220 @@ + +#include "stdafx.h" +#include +#include + + +#include "../nedclib.h" + +#include "dcs.h" //RAW2BMP, BMP2RAW + +void write_bmp(FILE *f) +{ + int i,j; + int length,width; + length=((dotcodelen*35)+9)*dpi_multiplier; + width=44*dpi_multiplier; + + i=length; + bmpheader[0x12] = i & 0xFF; + bmpheader[0x13] = i >> 8; + bmpheader[0x14] = i >> 16; + bmpheader[0x15] = i >> 24; + bmpheader[0x16] = width & 0xFF; + bmpheader[0x17] = (width >> 8) & 0xFF; + bmpheader[0x18] = (width >> 16) & 0xFF; + bmpheader[0x19] = (width >> 24) & 0xFF; + i/=32; + if((length%32)>0) + i++; + i*=4; + i*=(44*dpi_multiplier); + bmpheader[2] = (i + 0x3E) & 0xFF; + bmpheader[3] = ((i + 0x3E) >> 8) & 0xFF; + bmpheader[4] = ((i + 0x3E) >> 16) & 0xFF; + bmpheader[5] = ((i + 0x3E) >> 24) & 0xFF; + bmpheader[0x22] = i & 0xFF; + bmpheader[0x23] = (i >> 8) & 0xFF; + bmpheader[0x24] = (i >> 16) & 0xFF; + bmpheader[0x24] = (i >> 24) & 0xFF; + + i=0x2E23*dpi_multiplier; + bmpheader[0x26] = (i >> 0) & 0xFF; + bmpheader[0x27] = (i >> 8) & 0xFF; + bmpheader[0x28] = (i >> 16) & 0xFF; + bmpheader[0x29] = (i >> 24) & 0xFF; + bmpheader[0x2A] = (i >> 0) & 0xFF; + bmpheader[0x2B] = (i >> 8) & 0xFF; + bmpheader[0x2C] = (i >> 16) & 0xFF; + bmpheader[0x2D] = (i >> 24) & 0xFF; + + + fwrite(bmpheader,1,62,f); + for(j=0;j0) + bmplen+=(32-(bmplen%32)); + bmplen/=32; + bmplen*=4; + /* + { + case 0xB60: + dotcodelen = 28; + bmplen = 0x7C; + break; + case 0x750: + dotcodelen = 18; + bmplen = 0x50; + break; + }*/ + clear_dcs(); + init_dcs(); + eight_ten_modulate(); + make_dcs(); + //flipbmp(); + makebmp(); + if(num_raw==1) + sprintf_s(filename,255,"%s.bmp",bmpfile); + else + sprintf_s(filename,255,"%s-%.2d.bmp",bmpfile,i+1); + if(!fopen_s(&g,filename,"wb")) + { + write_bmp(g); + fclose(g); + } + } + + if(f!=NULL) + { + fclose(f); + } + + return 0; +} + +NEDCLIB_API int raw2bmp_f(unsigned char *rawdata, char *bmpfile) +{ + int i; + FILE *g; + char filename[256]; + + memcpy(&raw[0][0],rawdata,0xB60); + + //f=fopen(rawfile,"rb"); + //if(f==NULL) + //{ + // return 1; + //} + + int num_raw=1; + for(i=0;i +#include +#include + +#ifndef _WIN32 +inline int fopen_s(FILE **handle, const char *path, const char *mode) { + FILE *h = fopen(path, mode); + if (!h) + return 1; + *handle = h; + return 0; +} +#define sprintf_s(buf, n, format, ...) snprintf(buf, n, format, __VA_ARGS__) +#define vsprintf_s(buf, n, format, args) vsnprintf(buf, n, format, args) +#define _stricmp(a, b) strcmp(a, b) +#define stricmp(a, b) strcmp(a, b) +#else +#include +#endif +// TODO: reference additional headers your program requires here diff --git a/AC_e-Reader_Card_Creator/Decompression/External/nedclib/vpk/vpk.cpp b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/vpk/vpk.cpp new file mode 100644 index 0000000..633969f --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/External/nedclib/vpk/vpk.cpp @@ -0,0 +1,1235 @@ + +#include "stdafx.h" + +#include +#include +#include +#include +#include + +#include "../nedclib.h" + +NEDCLIB_API FILE *log_stream; +NEDCLIB_API int verbose=0; + +unsigned char *bitstore=NULL; + +#define MAX_LOG_STR 256 +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +void log_only_write(const char* str, ...) +{ + char tmpstr[MAX_LOG_STR]; + va_list args; + va_start(args,str); + vsprintf_s(tmpstr,MAX_LOG_STR-1,str,args); + va_end(args); + if(log_stream!=NULL) + fprintf(log_stream,tmpstr); +} + +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +NEDCLIB_API void log_write(const char* str, ...) +{ + char tmpstr[MAX_LOG_STR]; + va_list args; + va_start(args,str); + vsprintf_s(tmpstr,MAX_LOG_STR-1,str,args); + va_end(args); + if(verbose==1) + printf(tmpstr); + if(log_stream!=NULL) + fprintf(log_stream,tmpstr); +} + +struct tree_node { + int node; + int data; + int count; + int value; + tree_node *look_up[32]; + tree_node *left; + tree_node *right; +}; + +struct tree_node *movetree; +struct tree_node *sizetree; + +int get_bitsize(unsigned long data) +{ + + int i=data; + + int size=0; + while(i > 0) + { + size++; + i >>= 1; + } + return size; + +} + +int bitsleft_w = 32; +int bitsleft_r = 0; +unsigned long bits_w=0; +unsigned long bits_r=0; + +NEDCLIB_API unsigned long bits_written=0; + + +int bits_buf=0; + +inline unsigned long read_bits(int count, unsigned char *buf) +{ + int i; + unsigned long tmp=0; + + for(i=0;i> (bitsleft_r)) & 1) << (count-1-i)); + } + return tmp; + +} + +inline void write_bits(unsigned long data, int count, FILE *f) +{ + int i; + + bits_written+=count; + if((f==NULL)&&(bitstore==NULL)) + { + return; + } + for(i=0;i> (count-1-i)) & 1) << bitsleft_w); + if(bitsleft_w==0) + { + if(f!=NULL) + { + fputc(((bits_w & 0xFF000000) >> 24),f); + fputc(((bits_w & 0x00FF0000) >> 16),f); + fputc(((bits_w & 0x0000FF00) >> 8),f); + fputc(((bits_w & 0x000000FF) >> 0),f); + } + + if(bitstore!=NULL) + { + *bitstore++ = (unsigned char)((bits_w & 0xFF000000) >> 24); + *bitstore++ = (unsigned char)((bits_w & 0x00FF0000) >> 16); + *bitstore++ = (unsigned char)((bits_w & 0x0000FF00) >> 8); + *bitstore++ = (unsigned char)((bits_w & 0x000000FF) >> 0); + } + + bitsleft_w = 32; + bits_w = 0; + } + } +} + +inline void flush_bits(FILE *f) +{ + int i; + + i=32-bitsleft_w; + bits_written+=i; + if(f!=NULL) + { + if(i>0) + fputc(((bits_w & 0xFF000000) >> 24),f); + if(i>8) + fputc(((bits_w & 0x00FF0000) >> 16),f); + if(i>16) + fputc(((bits_w & 0x0000FF00) >> 8),f); + if(i>24) + fputc(((bits_w & 0x000000FF) >> 0),f); + } + if(bitstore != NULL) + { + if(i>0) + *bitstore++ = (unsigned char)((bits_w & 0xFF000000) >> 24); + if(i>8) + *bitstore++ = (unsigned char)((bits_w & 0x00FF0000) >> 16); + if(i>16) + *bitstore++ = (unsigned char)((bits_w & 0x0000FF00) >> 8); + if(i>24) + *bitstore++ = (unsigned char)((bits_w & 0x000000FF) >> 0); + } + bitsleft_w = 32; + bits_w = 0; +} + + +void sort_tree(tree_node *tree[], int count) +{ + int i,j; + tree_node *swap1, *swap2; + + for(i=0;i> i) & 1) << ((numbits - 1) - i)); + tree[0].value |= (numbits << 24); + + return tree; + } + else + return NULL; + } + } + else + { + return tree[0].look_up[bitcount]; + } +} + +void print_huffman_tree(tree_node *tree, int root=1) +{ + if(tree==NULL) + { + log_write("0\n"); + return; + } + if(tree[0].node == 1) + { + log_write("("); + print_huffman_tree(tree[0].left,0); + log_write(","); + print_huffman_tree(tree[0].right,0); + log_write(")"); + + if(root==1) + log_write("\n"); + } + else + { + log_write("%d",tree[0].data); + } +} + +void write_huffman_tree(tree_node *tree, FILE *f, int root=1) +{ + if(tree[0].node == 1) + { + if(f!=NULL) + log_write("("); + + write_huffman_tree(tree[0].left,f,0); + + if(f!=NULL) + log_write(","); + + write_huffman_tree(tree[0].right,f,0); + + if(f!=NULL) + log_write(")"); + write_bits(1,1,f); + + if(root==1) + { + write_bits(1,1,f); + if(f!=NULL) + log_write("\n"); + } + } + else + { + + write_bits(0,1,f); + write_bits(tree[0].data,8,f); + if(root) + write_bits(1,1,f); + if(f!=NULL) + log_write("%d",tree[0].data); + if(root) + if(f!=NULL) + log_write("\n"); + } + +} + +NEDCLIB_API int best_move=0; +NEDCLIB_API int best_size=0; + +NEDCLIB_API int skip_huffman=0; +int skip_size=0; + +tree_node* create_huffman_tree(unsigned short *buf, int count, FILE *f, int method=0, int type=0) +{ + int i,j,k; + int treenodes=0; + struct tree_node *ptr; + struct tree_node *temp1; + struct tree_node *treeroot; + struct tree_node *pointer[256]; + + int max_bitcount = 0; + + int count1, count2; + + int bitcounts[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + + for(i=0;i 0) + { + if((i < max_bitcount)) + { + j = 0; + + if((((best_move==0)&&(type==0)) || ((best_size==0)&&(type==1)&&(!skip_size)))&&(!skip_huffman)) + { + if((bitcounts[i+1] * 2) >= bitcounts[i]) + j=1; + + if(i<(max_bitcount-3)) + { + if((bitcounts[i] < 25)) + j=1; + } + else + { + if(bitcounts[i] < 100) + j=1; + } + } + else + { + if(k&1) + j=0; + else + j=1; + } + k>>=1; + + //j=0; + if(j==1) + { + bitcounts[i+1] += bitcounts[i]; + treeroot[0].look_up[i] = NULL; + continue; + } + } + if(f!=NULL) + log_write("%.5d:%.3d\n",bitcounts[i],i); + + + ptr = create_treenode(); + ptr[0].count = bitcounts[i]; + ptr[0].data = i; + ptr[0].left = NULL; + ptr[0].right = NULL; + ptr[0].node = 0; + pointer[treenodes++] = ptr; + treeroot[0].look_up[i] = ptr; + for(j=(i-1);j>=0;j--) + { + if(treeroot[0].look_up[j] == NULL) + { + treeroot[0].look_up[j] = ptr; + continue; + } + break; + } + + } + else + treeroot[0].look_up[i] = (tree_node*)(NULL + 1); + } + if(f!=NULL) + log_write("\n"); + sort_tree(pointer,treenodes); + + while(treenodes > 1) + { + count1 = count2 = -1; + if(treenodes == 2) + ptr = treeroot; + else + ptr = create_treenode(); + ptr[0].node = 1; + ptr[0].data = 0; + treenodes--; + ptr[0].right = pointer[treenodes]; + for(i=treenodes;i>=0;i--) + { + temp1 = pointer[i]; + if(temp1[0].count < ptr[0].right[0].count) + ptr[0].right = temp1; + } + for(i=treenodes;i>=0;i--) + { + if(ptr[0].right == pointer[i]) + continue; + ptr[0].left = pointer[i]; + break; + } + for(i=treenodes;i>=0;i--) + { + temp1 = pointer[i]; + if((temp1[0].count < ptr[0].left[0].count) && (temp1 != ptr[0].right)) + ptr[0].left = temp1; + } + ptr[0].count = ptr[0].right[0].count + ptr[0].left[0].count; + + for(i=0;i<(treenodes);i++) + { + if((ptr[0].left == pointer[i]) || (pointer[i] == NULL)) + { + pointer[i] = pointer[i+1]; + pointer[i+1] = NULL; + } + } + for(i=0;i<(treenodes);i++) + { + if((ptr[0].right == pointer[i]) || (pointer[i] == NULL)) + { + pointer[i] = pointer[i+1]; + pointer[i+1] = NULL; + } + } + + + pointer[treenodes-1] = ptr; + } + + for(i=0;i<32;i++) + { + if(treeroot[0].look_up[i] == (tree_node*)(NULL + 1)) + treeroot[0].look_up[i] = NULL; + else + get_treenode(treeroot,i,0,0,1); + } + + write_huffman_tree(pointer[0],f); + + return pointer[0]; + +} + +tree_node* read_huffman_tree(unsigned char *buf) +{ + int tree_pointer=0; + int tree; + struct tree_node *ptr; + struct tree_node *pointer[256]; + + int tree_nodes=0; + int node_pointer = 255; + int i; +// memset(huffman_tree,0,sizeof(huffman_tree)); + + pointer[0] = NULL; + + do + { + i=read_bits(1,buf); + if(i==0) + { + tree_nodes=1; + tree = read_bits(8,buf); + ptr = create_treenode(); + ptr[0].node = i; + ptr[0].data = tree; + ptr[0].count = 0; + ptr[0].left = NULL; + ptr[0].right = NULL; + + //ptr[0].left = create_treenode(); + pointer[tree_pointer++] = ptr; + } + else + { + tree_pointer--; + if(tree_pointer >= 1) + { + + ptr = create_treenode(); + ptr[0].data = 0; + ptr[0].node = 1; + ptr[0].left = pointer[tree_pointer - 1]; + ptr[0].right = pointer[tree_pointer]; + pointer[tree_pointer-1] = ptr; + +// huffman_tree[tree_pointer-1].left = tree_pointer - 1; +// huffman_tree[tree_pointer-1].right = tree_pointer; + } + //tree_pointer--; + } + + + + } while (tree_pointer > 0); + + if(tree_nodes > 0) + { + for(i=0;i<32;i++) + ptr[0].look_up[i] = NULL; + return ptr; + } + else + { + ptr = create_treenode(); + ptr[0].data = 0; + ptr[0].node = 0; + ptr[0].left = NULL; + ptr[0].right = NULL; + ptr[0].value = 0; + ptr[0].count = 0; + for(i=0;i<32;i++) + ptr[0].look_up[i] = NULL; + return ptr; + } + + + +} + +#define NUM_BITS get_bitsize(lzsize - 1) + +#define MAX_TABLE_SIZE 0x10000 +#define MAX_LITERALS 0x10000 + +NEDCLIB_API int skip_lz77 = 0; + +NEDCLIB_API int NVPK_compress (unsigned char *buf, int size, int compression_level, int lzwindow, int lzsize, int method, FILE *f, unsigned char *bitdata) +{ + static unsigned short literals[MAX_LITERALS], move_t[MAX_TABLE_SIZE], size_t[MAX_TABLE_SIZE]; + int literals_offset=0,move_offset=0,size_offset=0; + int buf_offset, buf_back_offset; + int i, j, k, l, m, n; + + int lookahead; + + tree_node *tmp; + + int window_bitsize; + + window_bitsize = get_bitsize(lzwindow-1); + + if((f==NULL)&&(bitdata==NULL)&&(compression_level<3)) + { + return -1; + } + + if((lzwindow<16)||(lzwindow>32768)) + return -3; + if((lzsize<16)||(lzsize>32768)) + return -4; + + if(size>0x40000) //GBA Ram is 256KB. Can't exceed this. + return -5; + + if(!skip_lz77) + { + + if(compression_level != 0) + { + + if(f!=NULL) + log_write("LZ compressing data\n"); + + for(buf_offset=0;buf_offset MAX_TABLE_SIZE) || (size_offset > MAX_TABLE_SIZE)) + { + return -2; //Compressor failure, buffer overrun error + } + + l=m=n=0; + + //for(buf_back_offset=0;(buf_back_offset=0;buf_back_offset--) + { + i=buf_offset; + j=buf_back_offset; + k=0; + while((buf[i-(j+1)]==buf[i])&&(i=2) + { + if(k>=l) + { + l=k; + m=j; + n=1; + //if(k==(lzsize-1)) + // break; + } + } + } + + // Look ahead one more byte, for a run, just in case there is a better run to use. + while((n==1)&&(l<(lzsize-1))) + { + n=0; + if(l>=2) + { + lookahead = l; + buf_offset++; + for(buf_back_offset=0;(buf_back_offset=2) + { + if(k>l) + { + l=k; + m=j; + } + } + } + buf_offset--; + if(l > lookahead) + { + n=1; + literals[literals_offset++] = buf[buf_offset++]; + } + else + l = lookahead; + } + } + if(l>=2) + { + literals[literals_offset++] = 0x100; + move_t[move_offset++] = m + 1; + size_t[size_offset++] = l; + buf_offset+=(l-1); + } + else + literals[literals_offset++] = buf[buf_offset]; + } + literals[literals_offset++] = 0x1FF; + } + else + { + for(buf_offset = 0;buf_offset= 2) + { + if(f!=NULL) + log_write("Writing huffman trees\n"); + if(f!=NULL) + log_write("----- Move Tree Structure/Frequency Counts-----\n"); + movetree = create_huffman_tree(move_t,move_offset,f,method,0); + if(f!=NULL) + log_write("----- Size Tree Structure/Frequency Counts-----\n"); + sizetree = create_huffman_tree(size_t,size_offset,f,0,1); + if(f!=NULL) + log_write("Writing vpk data\n"); + + move_offset = 0; + size_offset = 0; + + while(literals[literals_offset] != 0x1FF) + { + if(literals[literals_offset] == 0x100) + { + write_bits(1,1,f); + + if(method==1) + { + j=move_t[move_offset]; + if(j%4==0) + { + j+=8; + j/=4; + + /* if(get_bitsize(j)<3) + { + tmp = get_treenode(movetree,3); + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(j,tmp[0].data,f); + } + else + {*/ + tmp = get_treenode(movetree,get_bitsize(j)); + if(tmp!=NULL) + { + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(j,tmp[0].data,f); + } + else + { + write_bits(j,movetree[0].data,f); + } + + + // } + + } + else + { + j%=4; + j--; + /* if(get_bitsize(j)<3) + { + tmp = get_treenode(movetree,3); + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(j,tmp[0].data,f); + } + else + {*/ + tmp = get_treenode(movetree,get_bitsize(j)); + if(tmp==NULL) + { + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(j,tmp[0].data,f); + } + else + write_bits(j,movetree[0].data,f); + + // } + + j=move_t[move_offset]; + j+=8; + j/=4; + + /* if(get_bitsize(j)<3) + { + tmp = get_treenode(movetree,3); + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(j,tmp[0].data,f); + } + else + {*/ + tmp = get_treenode(movetree,get_bitsize(j)); + if(tmp==NULL) + { + return -3; //movetree failure + } + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(j,tmp[0].data,f); + // } + } + move_offset++; + + } + else + { + j = get_bitsize(move_t[move_offset]); + //if(j<3) + // j = 3; + tmp = get_treenode(movetree,j); + if(tmp!=NULL) + { + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(move_t[move_offset++],tmp[0].data,f); + } + else + write_bits(move_t[move_offset++],movetree[0].data,f); + + } + + j = get_bitsize(size_t[size_offset]); + //if(j<3) + // j = 3; + tmp = get_treenode(sizetree,j); + if(tmp!=NULL) + { + write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); + write_bits(size_t[size_offset++],tmp[0].data,f); + } + else + write_bits(size_t[size_offset++],sizetree[0].data,f); + + } + else + { + write_bits(0,1,f); + write_bits(literals[literals_offset],8,f); + } + literals_offset++; + } + + + flush_bits(f); + + free_huffman_tree(movetree); + free_huffman_tree(sizetree); + } + + + + bitstore=NULL; + + if(bitdata!=NULL) + return (bits_written/8)+1; + else + return 0; +} + + + + +unsigned char decompress_buffer[0x100000]; + +int read_tree_value(tree_node *tree, unsigned char *buf) +{ + tree_node *ptr; + int tmp; + + int count=0; + + ptr = tree; + if(ptr==NULL) + { + return 0; + } + else + { + while(ptr[0].node == 1) + { + tmp = read_bits(1,buf); + if(tmp == 0) + ptr = ptr[0].left; + else + ptr = ptr[0].right; + } + ptr[0].count++; + tree[0].look_up[ptr[0].data] = ptr; + return read_bits(ptr[0].data,buf); + } +} + +NEDCLIB_API int vpk_decompress (unsigned char *vpk, FILE *f) +{ + int bitcountsmove[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + + int bitcountssize[32] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + + struct tree_node *ptr; + + int decompress_buffer_pointer=0; + int size,method; + + int i; + + int tmp; + + int move_tt,size_tt; + + i=0; + + if(read_bits(8,vpk)!='v') + i=1; + if(read_bits(8,vpk)!='p') + i=1; + if(read_bits(8,vpk)!='k') + i=1; + if(read_bits(8,vpk)!='0') + i=1; + + if(i!=0) + { + printf("Error: Invalid vpk data\n"); + return 1; + } + + size=read_bits(32,vpk); + method=read_bits(8,vpk); + + if(method>1) + { + printf("Error: Invalid vpk data\n"); + return 1; + } + + movetree = read_huffman_tree(vpk); + sizetree = read_huffman_tree(vpk); + + + if((movetree[0].node != 0) || (movetree[0].data != 0)) + { + log_write("***** Move Tree Structure *****\n"); + print_huffman_tree(movetree); + log_write("\n"); + } + if((sizetree[0].node != 0) || (sizetree[0].data != 0)) + { + log_write("***** Size Tree Structure *****\n"); + print_huffman_tree(sizetree); + log_write("\n"); + } + + log_only_write("***** Decompression Log ******\n"); + + for(i=0;i 0) && (i < size)) + { + decompress_buffer[i] = \ + decompress_buffer[i - move_tt]; + log_only_write("%.2X ",decompress_buffer[i - move_tt]); + i++; + size_tt--; + } + log_only_write("\n"); + + + + } + } + + for(i=0;i0) + log_write("%.5d:%.3d\n",bitcountsmove[i],i);*/ + for(i=0;i<32;i++) + { + if(movetree == NULL) + break; + ptr = movetree[0].look_up[i]; + if(ptr == NULL) + continue; + log_write("%.5d:%.3d\n",ptr[0].count,i); + } + log_write("\n"); + } + + if((sizetree[0].node != 0) || (sizetree[0].data != 0)) + { + log_write("***** Frequency Table (size) *****\n"); + /*for(i=0;i<32;i++) + if(bitcountssize[i]>0) + log_write("%.5d:%.3d\n",bitcountssize[i],i);*/ + for(i=0;i<32;i++) + { + if(sizetree == NULL) + break; + ptr = sizetree[0].look_up[i]; + if(ptr == NULL) + continue; + log_write("%.5d:%.3d\n",ptr[0].count,i); + } + log_write("\n"); + } + + + free_huffman_tree(movetree); + free_huffman_tree(sizetree); + + return 0; +} diff --git a/AC_e-Reader_Card_Creator/Decompression/Functions/Compress.cs b/AC_e-Reader_Card_Creator/Decompression/Functions/Compress.cs index 24f84b3..5ea9e73 100644 --- a/AC_e-Reader_Card_Creator/Decompression/Functions/Compress.cs +++ b/AC_e-Reader_Card_Creator/Decompression/Functions/Compress.cs @@ -16,7 +16,7 @@ public static void DECtoVPK(string greeting, string body, string closing, string string new_greeting = greeting; int player_index = greeting.IndexOf(""); - if(player_index != -1) + if (player_index != -1) { new_greeting = string.Concat(greeting.AsSpan(0, player_index), greeting.AsSpan(player_index + 8)); } @@ -27,9 +27,9 @@ public static void DECtoVPK(string greeting, string body, string closing, string new_body = ACAsciiToBytes(new_body); // should only be true if letter uses special characters - if(new_body.Length < 384) + if (new_body.Length < 384) { - while(new_body.Length < 384) + while (new_body.Length < 384) { new_body += "20"; } @@ -57,15 +57,7 @@ public static void DECtoVPK(string greeting, string body, string closing, string string filePath = Common.DECOMPRESSED_GCN; File.WriteAllBytes(filePath, body_bytes); - ProcessStartInfo dec_to_vpk = new() - { - 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(); } + NedcLib.VpkCompress(Common.DECOMPRESSED_GCN, Common.VPK_GCN); FixVPKChecksums(); } @@ -105,16 +97,29 @@ public static void VPKtoBIN() byte[] padding = new byte[paddingSize]; NewBIN.Write(padding, 0, padding.Length); } + + HeaderFix.FixHeaderChecksums(NewBIN); } + } - ProcessStartInfo fix_header_checksums = new(Common.HEADERFIX, $"\"{Common.COMPRESSED_BIN}\"") + private static void BINtoRAW(string inputFilePath, string outputFilePath) + { + int result = NedcLib.bin2raw(inputFilePath, outputFilePath); + switch (result) { - UseShellExecute = false, - RedirectStandardOutput = true, - CreateNoWindow = true - }; - using Process process = Process.Start(fix_header_checksums); - process.WaitForExit(); + case 0: + break; + case -1: + throw new Exception("Unable to open input file"); + case -2: + throw new Exception("Invalid bin file"); + case -3: + throw new Exception("Unable to encode bin file to raw"); + case -4: + throw new Exception("Unable to write to output file"); + default: + throw new Exception($"bin2raw failed with error code {result}"); + } } public static void BINtoRAW(bool custom) @@ -129,30 +134,12 @@ public static void BINtoRAW(bool custom) }; if (saveRAWFile.ShowDialog() == DialogResult.OK) { - ProcessStartInfo bin_to_raw = new() - { - 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(); + BINtoRAW(Common.COMPRESSED_BIN, saveRAWFile.FileName); } } else { - ProcessStartInfo bin_to_raw = new() - { - 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(); + BINtoRAW(Common.COMPRESSED_BIN, Common.RAW_ECARD); } } @@ -205,7 +192,7 @@ private static void FixVPKChecksums() } byte[] GCN_FileSize_Checksum = HexStringToByteArray(GCN_VPK_Hex_Length); - + fileContents[^2] = GCN_FileSize_Checksum[1]; fileContents[^1] = GCN_FileSize_Checksum[0]; diff --git a/AC_e-Reader_Card_Creator/Decompression/Functions/Decompress.cs b/AC_e-Reader_Card_Creator/Decompression/Functions/Decompress.cs index ba81636..9d34776 100644 --- a/AC_e-Reader_Card_Creator/Decompression/Functions/Decompress.cs +++ b/AC_e-Reader_Card_Creator/Decompression/Functions/Decompress.cs @@ -40,17 +40,22 @@ public static void RAWtoBIN(string filePath) { try { - ProcessStartInfo raw_to_bin = new() + int result = NedcLib.raw2bin(filePath, Common.COMPRESSED_BIN); + switch (result) { - 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(); + case 0: + break; + case -1: + throw new Exception("Unable to open input file"); + case -2: + throw new Exception("Invalid raw file"); + case -3: + throw new Exception("Unable to decode raw file to bin"); + case -4: + throw new Exception("Unable to write to output file"); + default: + throw new Exception($"raw2bin failed with error code {result}"); + } } catch (Exception ex) { @@ -66,7 +71,7 @@ public static void VPK_Decompress() int iteration = 1; foreach (string vpk_file in vpk_file_paths) - { + { try { if (iteration == 1) @@ -74,22 +79,20 @@ public static void VPK_Decompress() iteration++; continue; } - else + else if (iteration == 2) { - ProcessStartInfo vpk_to_dec = new() - { - 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(); } - + NedcLib.VpkDecompress(vpk_file, Common.DECOMPRESSED_GBA); iteration++; } - + else if (iteration == 3) + { + NedcLib.VpkDecompress(vpk_file, Common.DECOMPRESSED_GCN); + iteration++; + } + else + { + throw new Exception("Too many VPK files found"); + } } catch (Exception ex) { @@ -116,7 +119,7 @@ private static void WriteToFile(byte[] data, ref int chunkNumber, string outputD default: break; } - + using (FileStream outFile = new(fileName, FileMode.Create, FileAccess.Write)) { if (chunkNumber != 1) diff --git a/AC_e-Reader_Card_Creator/Decompression/Functions/HeaderFix.cs b/AC_e-Reader_Card_Creator/Decompression/Functions/HeaderFix.cs new file mode 100644 index 0000000..59d041b --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/Functions/HeaderFix.cs @@ -0,0 +1,91 @@ +using System; +using System.IO; + +namespace AC_e_Reader_Card_Creator.Decompression.Functions +{ + internal class HeaderFix + { + private static ushort GetDataChecksum(byte[] data) + { + ushort sum = 0; + for (int i = 0; i < data.Length; i += 2) + { + sum += BitConverter.ToUInt16(data, i); + } + return (ushort)(~sum & 0xFFFF); + } + + private static byte GetHeaderChecksum(byte[] header) + { + ushort xor = 0; + xor ^= header[0xC]; + xor ^= header[0xD]; + xor ^= header[0x10]; + xor ^= header[0x11]; + for (int i = 0x26; i < 0x2D; i++) + { + xor ^= header[i]; + } + return (byte)(xor & 0xFF); + } + + private static byte GetGlobalChecksum(byte[] header, byte[] data) + { + short sum = 0; + + for (int i = 0; i < 0x2F; i++) + { + sum += header[i]; + } + + for (int i = 0; i < data.Length / 0x30; i++) + { + short xor = 0; + for (int j = 0; j < 0x30; j++) + { + xor ^= data[(i * 0x30) + j]; + } + sum += xor; + } + return (byte)(~sum & 0xFF); + } + + public static void FixHeaderChecksums(FileStream fileStream) + { + long cardSize = fileStream.Seek(0, SeekOrigin.End); + const int headerSize = 0x30; + fileStream.Seek(0, SeekOrigin.Begin); + if (cardSize % 0x30 != 0 || cardSize <= 0x30) + { + throw new Exception("Invalid card size"); + } + byte[] header = new byte[headerSize]; + fileStream.Read(header, 0, headerSize); + fileStream.Seek(0, SeekOrigin.Begin); + byte[] signature = [0x4E, 0x49, 0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F]; // NINTENDO + for (int i = 0; i < 8; i++) + { + if (header[0x1A + i] != signature[i]) + { + throw new Exception("Invalid e-Card signature"); + } + } + int dataSize = (header[0x06] << 8) + header[0x07]; + byte[] data = new byte[dataSize]; + fileStream.Seek(headerSize, SeekOrigin.Begin); + fileStream.Read(data, 0, dataSize); + + ushort dataChecksum = GetDataChecksum(data); + header[0x13] = (byte)(dataChecksum >> 8); + header[0x14] = (byte)(dataChecksum & 0xFF); + + byte headerChecksum = GetHeaderChecksum(header); + header[0x2E] = headerChecksum; + + byte globalChecksum = GetGlobalChecksum(header, data); + header[0x2F] = globalChecksum; + fileStream.Seek(0, SeekOrigin.Begin); + fileStream.Write(header, 0, headerSize); + } + } +} \ No newline at end of file diff --git a/AC_e-Reader_Card_Creator/Decompression/Functions/NedcLib.cs b/AC_e-Reader_Card_Creator/Decompression/Functions/NedcLib.cs new file mode 100644 index 0000000..5e0f4ed --- /dev/null +++ b/AC_e-Reader_Card_Creator/Decompression/Functions/NedcLib.cs @@ -0,0 +1,102 @@ +using System; +using System.Runtime.InteropServices; +using System.IO; + +namespace AC_e_Reader_Card_Creator.Decompression.Functions +{ + internal partial class NedcLib + { + [LibraryImport("nedclib", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] + internal static partial int is_bmp(string path); + [LibraryImport("nedclib", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] + internal static partial int bin2raw(string binfile, string rawfile); + [LibraryImport("nedclib", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] + internal static partial int raw2bin(string rawfile, string binfile); + [LibraryImport("nedclib", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] + private static partial int vpk_decompress(IntPtr buf, IntPtr fileHandle); + [LibraryImport("nedclib", StringMarshalling = StringMarshalling.Utf8, SetLastError = true)] + private static partial int NVPK_compress(IntPtr buf, int size, int compression_level, int lzwindow, int lzsize, int method, IntPtr fileHandle, IntPtr bitdata); + [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true)] + private delegate int raw2bmp(string rawfile, string bmpfile); + + internal class UnmanagedFile : SafeHandle + { + [DllImport("nedclib", SetLastError = true, CharSet = CharSet.Ansi)] + private static extern IntPtr nedc_fopen(string filename, string mode); + [DllImport("nedclib", SetLastError = true, CharSet = CharSet.Ansi)] + private static extern int nedc_fclose(IntPtr Handle); + public UnmanagedFile(string path, string mode) : base(IntPtr.Zero, true) + { + if (string.IsNullOrEmpty(path)) throw new ArgumentException("File path cannot be null or empty."); + if ((handle = nedc_fopen(path, mode)) == IntPtr.Zero) + { + throw new IOException($"Failed to open file '{path}'."); + } + } + + public override bool IsInvalid { get => handle == IntPtr.Zero; } + + protected override bool ReleaseHandle() + { + if (handle == IntPtr.Zero) + { + return true; + } + return nedc_fclose(handle) == 0; + } + } + + internal enum CompressionMethod + { + Store = 0, + Fast = 1, + Max = 2 + } + + internal static void Raw2Bmp(string rawfile, string bmpfile, int DPI) + { + IntPtr nedclib = NativeLibrary.Load("nedclib"); + IntPtr raw2bmpHandle = NativeLibrary.GetExport(nedclib, "raw2bmp"); + IntPtr dpiHandle = NativeLibrary.GetExport(nedclib, "dpi_multiplier"); + int dpiMultiplier = (int)Math.Pow(2.0, Math.Floor(Math.Log2(DPI / 300))); + Marshal.WriteInt32(dpiHandle, dpiMultiplier); + raw2bmp raw2bmpDelegate = Marshal.GetDelegateForFunctionPointer(raw2bmpHandle); + int result = raw2bmpDelegate(rawfile, bmpfile); + NativeLibrary.Free(nedclib); + if (result != 0) + { + throw new Exception($"raw2bmp failed with error code {result}"); + } + } + + internal static void VpkCompress(string inputFilePath, string outputFilePath, int compressionLevel = 2, int lzwindow = 4096, int lzsize = 256, CompressionMethod method = CompressionMethod.Max) + { + byte[] inputBytes = File.ReadAllBytes(inputFilePath); + File.Create(outputFilePath).Close(); + using (UnmanagedFile fileHandle = new(outputFilePath, "wb")) + { + var inputBytesHandle = GCHandle.Alloc(inputBytes, GCHandleType.Pinned); + int result = NVPK_compress(inputBytesHandle.AddrOfPinnedObject(), inputBytes.Length, compressionLevel, lzwindow, lzsize, (int)method, fileHandle.DangerousGetHandle(), IntPtr.Zero); + inputBytesHandle.Free(); + if (result != 0) + { + throw new Exception($"VPK_compress failed with error code {result}"); + } + }; + } + + internal static void VpkDecompress(string inputFilePath, string outputFilePath) + { + byte[] inputBytes = File.ReadAllBytes(inputFilePath); + File.Create(outputFilePath).Close(); + using UnmanagedFile fileHandle = new UnmanagedFile(outputFilePath, "wb"); + var inputBytesHandle = GCHandle.Alloc(inputBytes, GCHandleType.Pinned); + int result = vpk_decompress(inputBytesHandle.AddrOfPinnedObject(), fileHandle.DangerousGetHandle()); + inputBytesHandle.Free(); + if (result != 0) + { + throw new Exception($"vpk_decompress failed with error code {result}"); + } + } + } +} \ No newline at end of file diff --git a/AC_e-Reader_Card_Creator/Print-Frontend.cs b/AC_e-Reader_Card_Creator/Print-Frontend.cs index 73a9f91..24c0c20 100644 --- a/AC_e-Reader_Card_Creator/Print-Frontend.cs +++ b/AC_e-Reader_Card_Creator/Print-Frontend.cs @@ -3,6 +3,7 @@ using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; +using AC_e_Reader_Card_Creator.Decompression.Functions; using AC_e_Reader_Card_Creator.References; namespace AC_e_Reader_Card_Creator @@ -77,16 +78,7 @@ private void SaveBMP(object sender, EventArgs e) if (saveRAWFile.ShowDialog() == DialogResult.OK) { - ProcessStartInfo raw_to_bmp = new() - { - FileName = Common.RAW2BMP, - Arguments = Common.RAW2BMP_ARGS(saveRAWFile.FileName.Replace(".bmp", ""), DPI), - UseShellExecute = false, - RedirectStandardOutput = true, - CreateNoWindow = true - }; - using Process process = Process.Start(raw_to_bmp); - process.WaitForExit(); + NedcLib.Raw2Bmp(Common.RAW_ECARD, saveRAWFile.FileName.Replace(".bmp", ""), DPI); } } @@ -101,16 +93,7 @@ private void Print(object sender, EventArgs e) int DPI = int.Parse(comboBox_DPI.Text[..^4]); MessageBox.Show($"{DPI}"); - ProcessStartInfo raw_to_bmp = new() - { - FileName = Common.RAW2BMP, - Arguments = Common.RAW2BMP_ARGS(Common.BMP_DOTCODE, DPI), - UseShellExecute = false, - RedirectStandardOutput = true, - CreateNoWindow = true - }; - using (Process process = Process.Start(raw_to_bmp)) { process.WaitForExit(); } - + NedcLib.Raw2Bmp(Common.RAW_ECARD, Common.BMP_DOTCODE, DPI); PrintDotCode(); }