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();
}