├── .gitignore ├── history (raw2bmp).txt ├── history (nedcmake).txt ├── history (nevpk).txt ├── src ├── lib │ ├── rawbin │ │ ├── rs.h │ │ ├── rs.cpp │ │ └── binraw.cpp │ ├── nes.cpp │ ├── nedclib2.h │ ├── rawbmp │ │ ├── dcs.h │ │ ├── rawbmp.cpp │ │ ├── address.cpp │ │ ├── dcs_encode.cpp │ │ └── dcs_decode.cpp │ ├── nedclib2.cpp │ └── vpk │ │ └── vpk.cpp ├── raw2bmp.cpp ├── nedcenc.cpp ├── nevpk.cpp └── nedcmake.cpp ├── nedclib_dll.txt ├── make ├── ReadMe (nedcenc).txt ├── ereader card info.txt ├── README.md └── LICENSE.md /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /history (raw2bmp).txt: -------------------------------------------------------------------------------- 1 | Version 1.0 2 | * Initial release 3 | 4 | Version 1.1 5 | * Added support for encoding short raw to bmp 6 | 7 | Version 1.2 (Name change from dcstool to raw2bmp) 8 | * Added support for decoding short bmp to raw 9 | * bug fixed decoding of bmps with swapped pallette 10 | 11 | Version 1.3 12 | * Ported to nedclib.dll 13 | * Now supports multistrip raw files. (Upcoming feature of no$gba) 14 | 15 | Version 1.4 16 | * Rewrote command line interface. Now can list multiple input/output files. 17 | * Added option to decode bmp to multistrip raw output. 18 | * Added DPI command line option. (300/600/1200 dpi) -------------------------------------------------------------------------------- /history (nedcmake).txt: -------------------------------------------------------------------------------- 1 | V1.0 2 | - Initial release 3 | 4 | V1.1 5 | - Ported to use nedclib.dll 6 | - Added automatic vpk compression (lzwindow 16384, lzsize 2048, level 2, method 0) 7 | - Added automatic conversion to raw (-raw option). 8 | - Added automatic conversion to bmp (-bmp option). 9 | - Output of bin files optional (specify -bin for output). 10 | - Added support for loading Mapper 0 16K prg 8K chr nes roms. 11 | 12 | V1.2 13 | - Fixed a title processing bug that happens when -region 14 | is specified after -name/-title. (oops) 15 | - Removed the requirement to specify a filetype option. raw is 16 | default output format now. 17 | - Short titles on japanese e-reader used 8 bit characters rather 18 | than 16 bit shift-jis characters. (Thanks Martin Korth). 19 | -------------------------------------------------------------------------------- /history (nevpk).txt: -------------------------------------------------------------------------------- 1 | Build 0 2 | * Initial release 3 | 4 | Build 1 5 | * Added preliminary level 2 compression 6 | * Added decompression 7 | 8 | Build 2 9 | * Improved level 2 compression. 10 | * Added lzsize option. 11 | 12 | Build 3 13 | * Added method 1 compression/decompression 14 | 15 | Build 4 16 | * Optimized LZ compressor 17 | * Optimized huffman tree builder 18 | 19 | Build 5 20 | * Broke decompressor while implementing verbose info. fixed. 21 | 22 | Build 6 23 | * Fixed bug that caused method 1 level 2 compressor to crash. 24 | 25 | Build 7 26 | * Fixed bug that caused level 0 compressed files to crash decompressor. 27 | * Added output logging of decompression. 28 | 29 | Build 8 30 | * Ported functions to nedclib.dll 31 | * added a brute force level 3 compressor. (Really slow) 32 | * Minimum lz77 run is 2 bytes (actually produces smaller files) 33 | (Thanks Martin Korth) -------------------------------------------------------------------------------- /src/lib/rawbin/rs.h: -------------------------------------------------------------------------------- 1 | //unsigned char pp [mm+1] = { 1,1,0,0,0,0,1,1,1} ; /* specify irreducible polynomial coeffts */ 2 | //unsigned char alpha_to [nn+1], index_of [nn+1], gg [nn-kk+1] ; 3 | //unsigned char recd [nn], data [kk], bb [nn-kk] ; 4 | 5 | void make_rev(unsigned char *data, int len); 6 | void make_pow(unsigned char *data, int len); 7 | void invert_error_bytes(unsigned char *data, int len); 8 | void reverse_byte_order(unsigned char *data, int len); 9 | void zerofill_error_bytes(unsigned char *data, int len); 10 | void generate_gf(); 11 | void gen_poly(); 12 | void append_error_info(unsigned char *data, int dtalen, int errlen); 13 | int verify_error_info(unsigned char *data, int dtalen, int errlen); 14 | 15 | int correct_errors(unsigned char *data, int dtalen, int errlen, unsigned char *erasure=NULL); 16 | int eras_dec_rs(int *eras_pos,int no_eras); 17 | void initialize_rs(int bits=8, int polynomial=0x187, int index=0x78, int errlen=16); 18 | void free_rs(); 19 | int is_rs_initialized(); -------------------------------------------------------------------------------- /src/lib/nes.cpp: -------------------------------------------------------------------------------- 1 | #include "nedclib2.h" 2 | 3 | static char DMCA_data[0x19] = "\0\0DMCA NINTENDO E-READER"; 4 | 5 | static uint16_t encode_nmi(uint16_t nmi) { 6 | for(int i=0; i<0x18; i++) { 7 | for(int j=0; j<8; j++) { 8 | if(nmi & 0x0001) { 9 | nmi >>= 1; 10 | nmi ^= 0x8646; 11 | } else { 12 | nmi >>= 1; 13 | } 14 | } 15 | nmi ^= (DMCA_data[0x17-i] << 8); 16 | } 17 | 18 | return nmi; 19 | } 20 | 21 | NEDCLIB_API int nedc_encode_nes(unsigned char *nesdata) { 22 | if(!is_nes(nesdata)) return 1; 23 | if(nesdata[4] != 1 || nesdata[5] != 1 || (nesdata[6] & 0xFE) != 0 || nesdata[7] != 0) 24 | return 2; 25 | 26 | uint16_t nmi = encode_nmi((nesdata[0x3FFB+16] << 8) + (nesdata[0x3FFA+16])); 27 | nesdata[0x3FFB+16] = (nmi >> 8) & 0xFF; 28 | nesdata[0x3FFA+16] = nmi & 0xFF; 29 | 30 | if(nesdata[6] & 1) nesdata[0x3FFD + 16] &= 0x7F; 31 | else nesdata[0x3FFD + 16] |= 0x80; 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /nedclib_dll.txt: -------------------------------------------------------------------------------- 1 | This DLL, and its lib file, is for the development of other nintendo e-reader related tools. THe source code is availble, under gpl. 2 | 3 | History 4 | Version 1.0 5 | * Initial release 6 | 7 | Version 1.1 8 | * added is_nes(unsigned char *nesdata) 9 | * added is_vpk(unsigned char *bindata) 10 | * added make_nes(unsigned char *nesdata) 11 | * added nes_enc(unsigned short NMI_vector) 12 | * added nes_dec(unsigned short NMI_vector) 13 | 14 | Version 1.2 15 | * added is_bmp(char *bmpfile) 16 | * added MultiStrip flag; 17 | * made dpi_multiplier available externally; 18 | Version 1.3 19 | * Finally ditched the emulation core code for actual 20 | reed-solomon encoding/decoding functions. 21 | (Thanks Martin Korth for finding the code, and 22 | Simon Rockcliff, Robert Morelos-Zaragoza and Hari Thirumoorthy for 23 | writing that code.) 24 | * Added multistrip bin support. 25 | * Upgraded bin format to 0x840/0x540 byte format. (Still need to rebuild 26 | the rest of my tools for both multistrip bin and multistrip raw format. 27 | (The tools being nedcprint, and vba e-reader)) 28 | -------------------------------------------------------------------------------- /make: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -rfv build 3 | mkdir build 4 | 5 | build_os() { 6 | case "$1" in 7 | win32) 8 | CC="gcc" 9 | CXX="g++" 10 | CC_PREFIX="i686-w64-mingw32-" 11 | SO_EXTENSION=".dll" 12 | EXE_EXTENSION=".exe" 13 | CFLAGS="-static-libgcc" 14 | ;; 15 | linux) 16 | CC="gcc" 17 | CXX="g++" 18 | ;; 19 | mac) 20 | CC="clang" 21 | CXX="clang++" 22 | CFLAGS="-L/opt/local/lib" 23 | ;; 24 | custom) 25 | ;; 26 | *) 27 | echo "invalid target platform" 28 | exit 1 29 | esac 30 | 31 | if [ "$SO_EXTENSION" = "" ]; then 32 | SO_EXTENSION=".so" 33 | fi 34 | if [ "$EXE_EXTENSION" = "" ]; then 35 | EXE_EXTENSION="" 36 | fi 37 | 38 | mkdir build/$1 39 | mkdir build/$1/obj 40 | for file in $(find src/lib | grep "\.cpp$"); do 41 | ${CC_PREFIX}${CXX} $CFLAGS -flto -DNEDCLIB2_EXPORTS -c -g -fPIC -o build/$1/obj/$(basename $file).o -Wall -O2 -std=c++0x -I src/lib -I src/lib/rawbmp $file 42 | done 43 | ar rcs build/$1/nedclib2.a build/$1/obj/* 44 | ${CC_PREFIX}${CXX} $LDFLAGS -flto -fPIC -o build/$1/nedclib2${SO_EXTENSION} -shared -Wall -O2 -std=c++0x build/$1/obj/* 45 | 46 | for prog in nedcenc raw2bmp nedcmake nevpk; do 47 | ${CC_PREFIX}${CXX} $CFLAGS -flto -O2 -Wall -o build/$1/${prog}${EXE_EXTENSION} -I src/lib src/$prog.cpp build/$1/nedclib2.a 48 | done 49 | } 50 | 51 | if [ ! "$1" = "" ]; then 52 | build_os $1 53 | else 54 | build_os linux 55 | build_os win32 56 | fi 57 | -------------------------------------------------------------------------------- /ReadMe (nedcenc).txt: -------------------------------------------------------------------------------- 1 | Nintendo eReader Dotcode encoder/decoder 2 | Copyright (C) 2007 by CaitSith2 3 | 4 | This is a command line tool. As such, basic command line usage is assumed. if you don't 5 | know how to use the command line, then you should look up how. 6 | 7 | Usage is "nedcenc [options]" 8 | 9 | [options] 10 | -i (Required) 11 | -o 12 | 13 | -e Encodes bin dotcode files to raw (-o option required) (default) 14 | -d Decodes raw dotcode files to bin (-o option required) 15 | -f Fixes dotcode raw files. 16 | 17 | -s There are either 40 or 44 bytes unused in a dotcode raw 18 | file, depending on if the raw is for a long dotcode or 19 | short dotcode. You can input any string or hex value. 20 | to input spaces, quote the string or use <20>. To insert 21 | quotes, use <22>. To insert <, use << or <3C>. 22 | To input any hex string, start with <. then input the 23 | hex string, then end with >. 24 | Example. 25 | 26 | "< -=<<65027110>" 27 | 28 | If -s is not specified, dotcodes will be filled with either 29 | <2425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F> 30 | <404142434445464748494A4B4C4D4E4F> (short) 31 | or 32 | <38393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F50515253> 33 | <5455565758595A5B5C5D5E5F> (long). 34 | 35 | 36 | 37 | Release history 38 | v1.0 39 | -Initial release. 40 | -(No longer need to use VBA e-reader for encoding needs) 41 | 42 | v1.1 43 | -Added signature option 44 | -Encoding bin2raw is now default operation. 45 | 46 | v1.2 47 | -Functions ported to nedclib.dll. (Source code available seperately) -------------------------------------------------------------------------------- /src/raw2bmp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "nedclib2.h" 6 | 7 | int InFileList[256],OutFileList[256]; 8 | 9 | void usage (void) 10 | { 11 | printf("Usage :\n DcsTool [options]\n"); 12 | printf("Options :\n"); 13 | printf(" -i \t\tInput File\t\t\t(Required)\n"); 14 | printf(" -o \t\tOutput File\t\t\t(Required)\n"); 15 | printf(" -dpi \t\tDPI Setting\t\t\t(Optional, Default 300)\n"); 16 | printf(" -MultiStrip\t\tMultistrip raw file mode\t\t(Optional)\n"); 17 | printf("\n"); 18 | } 19 | 20 | int main(int argc, char* argv[]) 21 | { 22 | int i,j; 23 | int OptI=0; 24 | int OptO=0; 25 | 26 | printf("Nintendo e-Reader dotcode strip tool Version %d.%d\n",RAW2BMP_MAJOR,RAW2BMP_MINOR); 27 | printf("Copyrighted by CaitSith2\n\n"); 28 | nedclib_version(); 29 | 30 | for (i=1;i 28 | #include 29 | 30 | //Common internal functions/variables 31 | int count_raw(FILE *f); 32 | int read_next_raw(FILE *f, unsigned char *rawdata); 33 | 34 | extern int bin_type; 35 | #define BIN_TYPE_NEDC_SINGLE 0 36 | #define BIN_TYPE_NEDC_MULTI 1 37 | #define BIN_TYPE_DRPD_MULTI 2 38 | //There is no DRPD single format, as there is no way to know how big each of them will be 39 | //with certainty. 40 | 41 | int count_bin(FILE *f); 42 | int read_next_bin(FILE *f, unsigned char *bindata); 43 | 44 | void backtrack_raw(FILE *f); 45 | int close_raw(FILE *f, int return_res); 46 | 47 | //--- common external functions --- 48 | NEDCLIB_API void nedclib_version(void); 49 | NEDCLIB_API bool is_vpk(unsigned char *bindata); 50 | NEDCLIB_API bool is_nes(unsigned char *nesdata); 51 | NEDCLIB_API bool is_bmp(char *bmpfile); 52 | 53 | NEDCLIB_API int nedc_fopen(FILE** f, const char* name, const char* mode); 54 | 55 | extern NEDCLIB_API int version_major; 56 | extern NEDCLIB_API int version_minor; 57 | extern NEDCLIB_API int MultiStrip; 58 | 59 | //--- RAW2BMP FUNCTIONS --- 60 | NEDCLIB_API int raw2bmp(char *rawfile, char *bmpfile); 61 | NEDCLIB_API int bmp2raw(char *bmpfile, char *rawfile); 62 | NEDCLIB_API int raw2bmp_f(unsigned char *rawdata, char *bmpfile); 63 | extern NEDCLIB_API int smooth; 64 | 65 | //--- BIN2RAW FUNCTIONS --- 66 | NEDCLIB_API int bin2raw(char *binfile, char *rawfile); 67 | NEDCLIB_API int raw2bin(char *rawfile, char *binfile); 68 | NEDCLIB_API int fixraw(char *rawfile); 69 | NEDCLIB_API int bin2raw_d(unsigned char *bindata, unsigned char *rawdata, int size); 70 | NEDCLIB_API int bin2raw_f(unsigned char *bin, char *rawfile, int size); 71 | extern NEDCLIB_API int signature; 72 | extern NEDCLIB_API unsigned char signature_str[]; 73 | extern NEDCLIB_API int dpi_multiplier; 74 | 75 | //--- NEVPK FUNCTIONS --- 76 | 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); 77 | NEDCLIB_API int vpk_decompress (unsigned char *vpk, FILE *f); 78 | NEDCLIB_API void log_write(const char* str, ...); 79 | extern NEDCLIB_API FILE *log; 80 | extern NEDCLIB_API int verbose; 81 | extern NEDCLIB_API unsigned long bits_written; 82 | extern NEDCLIB_API int best_move; 83 | extern NEDCLIB_API int best_size; 84 | extern NEDCLIB_API int skip_huffman; 85 | extern NEDCLIB_API int skip_lz77; 86 | 87 | //--- NES Functions --- 88 | NEDCLIB_API int nedc_encode_nes(unsigned char *nesdata); 89 | 90 | #define VERSION_MAJOR 1 91 | #define VERSION_MINOR 4 92 | 93 | #define NEDCENC_MAJOR 1 94 | #define NEDCENC_MINOR 4 95 | #define NEDCMAKE_MAJOR 1 96 | #define NEDCMAKE_MINOR 4 97 | #define NEVPK_MAJOR 1 98 | #define NEVPK_MINOR 4 99 | #define RAW2BMP_MAJOR 1 100 | #define RAW2BMP_MINOR 4 101 | 102 | #define NEDCLIB_DOWNLOAD "http://www.caitsith2.net/ereader/tools/nedclib_dll.rar" 103 | 104 | #endif /* NEDCLIB2_H */ 105 | -------------------------------------------------------------------------------- /src/lib/rawbmp/dcs.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #ifndef DCS 5 | #define DCS 6 | 7 | 8 | 9 | unsigned short dotcodelen; 10 | unsigned short bmplen; 11 | 12 | unsigned long addr[2] = { 0,0x3FF }; 13 | 14 | unsigned char raw[28][104]; 15 | unsigned char dcsbmp[7912][352]; 16 | 17 | unsigned char _810mod[28][130]; 18 | 19 | unsigned char bmpheader[62] = 20 | { 21 | 0x42, 0x4D, 0x8E, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, 22 | 0x00, 0x00, 0xDD, 0x03, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 23 | 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x02, 0x00, 24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 25 | }; 26 | /* 27 | unsigned char bmpheader2[62] = 28 | { 29 | 0x42, 0x4D, 0xFE, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, 30 | 0x00, 0x00, 0x7F, 0x02, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 31 | 0x00, 0x00, 0xC0, 0x0D, 0x00, 0x00, 0xC2, 0x1E, 0x00, 0x00, 0xC2, 0x1E, 0x00, 0x00, 0x02, 0x00, 32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 33 | } ;*/ 34 | 35 | unsigned char bmpdata[352][992]; 36 | 37 | 38 | //unsigned char bmpdata1[44][0x7C]; 39 | //unsigned char bmpdata2[44][0x50]; 40 | 41 | int bmp_invert; 42 | 43 | 44 | 45 | 46 | unsigned char modtable[16] = { 47 | 0x00, //00000 48 | 0x01, //00001 49 | 0x02, //00010 50 | 0x12, //10010 51 | 0x04, //00100 52 | 0x05, //00101 53 | 0x06, //00110 54 | 0x16, //10110 55 | 0x08, //01000 56 | 0x09, //01001 57 | 0x0A, //01010 58 | 0x14, //10100 59 | 0x0C, //01100 60 | 0x0D, //01101 61 | 0x11, //10001 62 | 0x10, //10000 63 | }; 64 | 65 | unsigned char demodtable[32] = { 66 | //{ 67 | 0x00,0x01,0x02,0xFF,0x04,0x05,0x06,0xFF,0x08,0x09,0x0A,0xFF,0x0C,0x0D,0xFF,0xFF, 68 | 0x0F,0x0E,0x03,0xFF,0x0B,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 69 | /*}, 70 | { 71 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0x0B,0xFF,0x03,0x0E,0x0F, 72 | 0xFF,0xFF,0x0D,0x0C,0xFF,0x0A,0x09,0x08,0xFF,0x06,0x05,0x04,0xFF,0x02,0x01,0x00, 73 | }*/}; 74 | 75 | /* 76 | unsigned short addressbar[2][29] = { { 77 | 0x9866, //Left most address bar 78 | 0xD316, 79 | 0x45F6, 80 | 0x604E, 81 | 0xF6AE, 82 | 0xBDDE, 83 | 0x2B3E, 84 | 0x4141, 85 | 0xD7A1, 86 | 0x9CD1, 87 | 0x0A31, 88 | 0x2F89, 89 | 0xB969, 90 | 0xF219, 91 | 0x64F9, 92 | 0xE0C5, 93 | 0x7625, 94 | 0x3D55, 95 | 0xABB5, 96 | 0x8E0D, 97 | 0x18ED, 98 | 0x539D, 99 | 0xC57D, 100 | 0x1183, 101 | 0x8763, 102 | 0xCC13, 103 | 0x5AF3, 104 | 0x7F4B, 105 | 0xE9AB, //Right most address bar 106 | }, { 107 | 0x6920, 108 | 0x2250, 109 | 0xB4B0, 110 | 0x9108, 111 | 0x07E8, 112 | 0x4C98, 113 | 0xDA78, 114 | 0x5E44, 115 | 0xC8A4, 116 | 0x83D4, 117 | 0x1534, 118 | 0x308C, 119 | 0xA66C, 120 | 0xED1C, 121 | 0x7BFC, 122 | 0xAF02, 123 | 0x39E2, 124 | 0x7292, 125 | 0xE472, 126 | 127 | }, 128 | };*/ 129 | 130 | #endif 131 | 132 | extern unsigned short dotcodelen; 133 | extern unsigned short bmplen; 134 | 135 | extern int dpi_multiplier; 136 | 137 | extern unsigned long addr[2]; 138 | extern unsigned char raw[28][104]; 139 | extern unsigned char dcsbmp[7912][352]; 140 | extern unsigned char _810mod[28][130]; 141 | extern unsigned char bmpheader1[]; 142 | extern unsigned char bmpheader2[]; 143 | extern unsigned char bmpdata[352][992]; 144 | extern unsigned char bmpdata1[44][0x7C]; 145 | extern unsigned char bmpdata2[44][80]; 146 | extern unsigned char modtable[]; 147 | extern unsigned char demodtable[32]; 148 | //extern unsigned short addressbar[2][29]; 149 | 150 | extern int bmp_invert; 151 | 152 | void clear_dcs(void); 153 | void eight_ten_modulate(void); 154 | void init_dcs(void); 155 | void flipbmp(void); 156 | void makebmp(void); 157 | void make_dcs(void); 158 | 159 | void eight_ten_demodulate(void); 160 | void reversebmp(void); 161 | void reverse_dcs(void); 162 | int read_bmp(FILE *f); 163 | 164 | int correct_address(unsigned long *addr_data); 165 | void calc_addr(unsigned long address); 166 | -------------------------------------------------------------------------------- /src/lib/rawbmp/rawbmp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "nedclib2.h" 6 | 7 | #include "dcs.h" //RAW2BMP, BMP2RAW 8 | 9 | void write_bmp(FILE *f) 10 | { 11 | int i,j; 12 | int length,width; 13 | length=((dotcodelen*35)+9)*dpi_multiplier; 14 | width=44*dpi_multiplier; 15 | 16 | i=length; 17 | bmpheader[0x12] = i & 0xFF; 18 | bmpheader[0x13] = i >> 8; 19 | bmpheader[0x14] = i >> 16; 20 | bmpheader[0x15] = i >> 24; 21 | bmpheader[0x16] = width & 0xFF; 22 | bmpheader[0x17] = (width >> 8) & 0xFF; 23 | bmpheader[0x18] = (width >> 16) & 0xFF; 24 | bmpheader[0x19] = (width >> 24) & 0xFF; 25 | i/=32; 26 | if((length%32)>0) 27 | i++; 28 | i*=4; 29 | i*=(44*dpi_multiplier); 30 | bmpheader[2] = (i + 0x3E) & 0xFF; 31 | bmpheader[3] = ((i + 0x3E) >> 8) & 0xFF; 32 | bmpheader[4] = ((i + 0x3E) >> 16) & 0xFF; 33 | bmpheader[5] = ((i + 0x3E) >> 24) & 0xFF; 34 | bmpheader[0x22] = i & 0xFF; 35 | bmpheader[0x23] = (i >> 8) & 0xFF; 36 | bmpheader[0x24] = (i >> 16) & 0xFF; 37 | bmpheader[0x24] = (i >> 24) & 0xFF; 38 | 39 | i=0x2E23*dpi_multiplier; 40 | bmpheader[0x26] = (i >> 0) & 0xFF; 41 | bmpheader[0x27] = (i >> 8) & 0xFF; 42 | bmpheader[0x28] = (i >> 16) & 0xFF; 43 | bmpheader[0x29] = (i >> 24) & 0xFF; 44 | bmpheader[0x2A] = (i >> 0) & 0xFF; 45 | bmpheader[0x2B] = (i >> 8) & 0xFF; 46 | bmpheader[0x2C] = (i >> 16) & 0xFF; 47 | bmpheader[0x2D] = (i >> 24) & 0xFF; 48 | 49 | 50 | fwrite(bmpheader,1,62,f); 51 | for(j=0;j0) 87 | bmplen+=(32-(bmplen%32)); 88 | bmplen/=32; 89 | bmplen*=4; 90 | /* 91 | { 92 | case 0xB60: 93 | dotcodelen = 28; 94 | bmplen = 0x7C; 95 | break; 96 | case 0x750: 97 | dotcodelen = 18; 98 | bmplen = 0x50; 99 | break; 100 | }*/ 101 | clear_dcs(); 102 | init_dcs(); 103 | eight_ten_modulate(); 104 | make_dcs(); 105 | //flipbmp(); 106 | makebmp(); 107 | if(num_raw==1) 108 | snprintf(filename,sizeof(filename),"%s.bmp",bmpfile); 109 | else 110 | snprintf(filename,sizeof(filename),"%s-%.2d.bmp",bmpfile,i+1); 111 | if(!nedc_fopen(&g,filename,"wb")) 112 | { 113 | write_bmp(g); 114 | fclose(g); 115 | } 116 | } 117 | 118 | if(f!=NULL) 119 | { 120 | fclose(f); 121 | } 122 | 123 | return 0; 124 | } 125 | 126 | NEDCLIB_API int raw2bmp_f(unsigned char *rawdata, char *bmpfile) 127 | { 128 | int i; 129 | FILE *g; 130 | char filename[256]; 131 | 132 | memcpy(&raw[0][0],rawdata,0xB60); 133 | 134 | //f=fopen(rawfile,"rb"); 135 | //if(f==NULL) 136 | //{ 137 | // return 1; 138 | //} 139 | 140 | int num_raw=1; 141 | for(i=0;i 2 | 3 | #include "nedclib2.h" 4 | 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | int i,j,k,temp,hexinput; 9 | 10 | int encode=0,decode=0,fix=0; 11 | int infile=0,outfile=0; 12 | 13 | printf("Nintendo eReader Dotcode encoder/decoder v%d.%d\n",NEDCENC_MAJOR,NEDCENC_MINOR); 14 | printf("Copyright 2007 CaitSith2\n\n"); 15 | nedclib_version(); 16 | 17 | if(argc<3) 18 | { 19 | printf("Usage: %s [options] [-i] infile [[-o] outfile]\n\n",argv[0]); 20 | printf("[options]\n"); 21 | printf("\t-i\tIn file (required)\n"); 22 | printf("\t-o\tOut file (required)\n"); 23 | 24 | printf("\t-e\tEncode bin 2 raw, Outfile required (Default operation)\n"); 25 | printf("\t-d\tDecode raw 2 bin. Outfile required\n"); 26 | printf("\t-f\tRepair raw file\n"); 27 | printf("\t-s\tDot code signature (encoding only)\n\t\t< - Input hex.\n\t\t<< - "); 28 | printf("Input <\n\t\t> - If inputting hex, end hex input, otherwise input >\n"); 29 | return 1; 30 | } 31 | 32 | for(i=1;i1) 66 | { 67 | printf("You cannot specify more than one operation\n"); 68 | return 1; 69 | } 70 | 71 | if(signature) 72 | { 73 | i=0; 74 | j=0; 75 | k=0; 76 | temp=0; 77 | hexinput=0; 78 | while((argv[signature][i])&&(j<0x2C)) 79 | { 80 | switch(argv[signature][i]) 81 | { 82 | case '<': 83 | if(hexinput) 84 | { 85 | hexinput = 0; 86 | signature_str[j++]=argv[signature][i]; 87 | break; 88 | } 89 | hexinput=1; 90 | break; 91 | case '>': 92 | if(hexinput) 93 | { 94 | hexinput = 0; 95 | break; 96 | } 97 | signature_str[j++]=argv[signature][i]; 98 | break; 99 | case '0': 100 | case '1': 101 | case '2': 102 | case '3': 103 | case '4': 104 | case '5': 105 | case '6': 106 | case '7': 107 | case '8': 108 | case '9': 109 | if(hexinput) 110 | { 111 | if(k) 112 | { 113 | temp += (argv[signature][i]-'0'); 114 | signature_str[j++] = temp; 115 | k=0; 116 | } 117 | else 118 | { 119 | temp = ((argv[signature][i]-'0')<<4); 120 | k++; 121 | } 122 | break; 123 | } 124 | signature_str[j++]=argv[signature][i]; 125 | break; 126 | case 'a': 127 | case 'b': 128 | case 'c': 129 | case 'd': 130 | case 'e': 131 | case 'f': 132 | if(hexinput) 133 | { 134 | if(k) 135 | { 136 | temp += (argv[signature][i]-'a')+10; 137 | signature_str[j++] = temp; 138 | k=0; 139 | } 140 | else 141 | { 142 | temp = (((argv[signature][i]-'a')+10)<<4); 143 | k++; 144 | } 145 | break; 146 | } 147 | signature_str[j++]=argv[signature][i]; 148 | break; 149 | case 'A': 150 | case 'B': 151 | case 'C': 152 | case 'D': 153 | case 'E': 154 | case 'F': 155 | if(hexinput) 156 | { 157 | if(k) 158 | { 159 | temp += (argv[signature][i]-'A')+10; 160 | signature_str[j++] = temp; 161 | k=0; 162 | } 163 | else 164 | { 165 | temp = (((argv[signature][i]-'A')+10)<<4); 166 | k++; 167 | } 168 | break; 169 | } 170 | signature_str[j++]=argv[signature][i]; 171 | break; 172 | default: 173 | if(hexinput) 174 | break; 175 | signature_str[j++]=argv[signature][i]; 176 | break; 177 | } 178 | i++; 179 | } 180 | } 181 | 182 | if(encode) 183 | i=bin2raw(argv[infile],argv[outfile]); 184 | if(decode) 185 | i=raw2bin(argv[infile],argv[outfile]); 186 | if(fix) 187 | i=fixraw(argv[infile]); 188 | 189 | switch(i) 190 | { 191 | case 0: 192 | if(encode) 193 | printf("bin successfully encoded to raw\n"); 194 | if(decode) 195 | printf("raw successfully decoded to bin\n"); 196 | if(fix) 197 | printf("dotcode raw successfully repaired\n"); 198 | break; 199 | case -1: 200 | printf("Unable to open input file %s\n",argv[infile]); 201 | break; 202 | case -2: 203 | if(encode) 204 | printf("Invalid bin file\n"); 205 | if(decode) 206 | printf("Invalid raw file\n"); 207 | if(fix) 208 | printf("Invalid raw file\n"); 209 | break; 210 | case -3: 211 | if(encode) 212 | printf("Unable to encode bin file to raw\n"); 213 | if(decode) 214 | printf("Unable to decode raw file to bin\n"); 215 | if(fix) 216 | printf("Unable to repair raw file\n"); 217 | break; 218 | case -4: 219 | printf("Unable to open output file %s\n",argv[outfile]); 220 | break; 221 | default: 222 | printf("Unknown error\n"); 223 | } 224 | if(i!=0) 225 | return i; 226 | 227 | 228 | 229 | 230 | 231 | return 0; 232 | } 233 | 234 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nintendo e-Reader Tools ported to multi-platform 2 | 3 | Included tools (see [here](#documentation) for documentation): 4 | 5 | - raw2bmp 6 | - nevpk 7 | - nedcmake 8 | - nedcenc 9 | - A ported version of nedclib.dll to be used as a C/C++ library. This can be imported into any number of languages that support C/C++ libraries such as Python, Rust, C/C++, Node (not vanilla JS), etc 10 | 11 | ## Why? 12 | 13 | Because the e-Reader was a simple device to reverse engineer. These tools allow you to write ARMv7, thumb, Z80, 6502 assembly and inject code into a number of GBA games. For example, you could inject custom events into the Pokemon games. 14 | 15 | ## Documentation 16 | 17 | ### raw2bmp 18 | 19 | ```txt 20 | Nintendo e-Reader dotcode strip tool Version 1.4 21 | Copyrighted by CaitSith2 22 | 23 | Usage : 24 | DcsTool [options] 25 | Options : 26 | -i Input File (Required) 27 | -o Output File (Required) 28 | -dpi DPI Setting (Optional, Default 300) 29 | -MultiStrip Multistrip raw file mode (Optional) 30 | ``` 31 | 32 | ### nevpk 33 | 34 | ```txt 35 | Nintendo e-Reader VPK Tool Version 1.4 36 | Copyright CaitSith2 37 | 38 | usage : 39 | nvpktool [options] 40 | options : 41 | -i input file (Required) 42 | -o output file (Required) 43 | -v verbose (Optional) 44 | -c compress (Required *) 45 | -d decompress (Required *) 46 | -level compression level (0=store 1=med 2=max (Default = 2) 47 | 3 = Discover best lzwindow/lzsize/method) 48 | -log Decompression log (Default = none) 49 | (following options are only valid for compression levels 1 & 2) 50 | -method compression method (0 or 1) (Default = 0) 51 | -lzwindow lz window size (Default = 4096) 52 | -lzsize lz max repeat size (Default = 256) 53 | ``` 54 | 55 | ### nedcmake 56 | 57 | ```txt 58 | Nintendo E-Reader Dotcode bin maker tool Version 1.4 59 | Copyright CaitSith2 60 | 61 | usage : 62 | nedcmaker [options] 63 | options : 64 | -i input file (required) 65 | -o output name (optional) 66 | -type type (0=nes 1=z80 (required) 67 | 2 = gba 3 = raw 68 | -region region (0=jap 1=usa 2=jap+) (default = usa) 69 | -name Application name (default = none) 70 | -title Individual Card Titles (default = none) 71 | -dcsize dcsize (0=long 1=short) (default = long) 72 | -fill fill (0=none 1=filled) (default = none) 73 | -save save (0=no 1=yes) (default = no) 74 | -titlemode titlemode (0=short, no individual titles) 75 | (1=short, individual card titles) 76 | (2=long, no individual titles (default)) 77 | (3=long, individual card titles) 78 | -bin Output bin files At least one 79 | -raw Output raw files of these options 80 | -bin Output bmp files is required 81 | -music music (0=Normal 1=cheery) (default = normal) 82 | -help (or -?) Print extended usage info 83 | ``` 84 | 85 | ### nedcenc 86 | 87 | ```txt 88 | Nintendo eReader Dotcode encoder/decoder v1.4 89 | Copyright 2007 CaitSith2 90 | 91 | Usage: ./build/mac/nedcenc [options] [-i] infile [[-o] outfile] 92 | 93 | [options] 94 | -i In file (required) 95 | -o Out file (required) 96 | -e Encode bin 2 raw, Outfile required (Default operation) 97 | -d Decode raw 2 bin. Outfile required 98 | -f Repair raw file 99 | -s Dot code signature (encoding only) 100 | < - Input hex. 101 | << - Input < 102 | > - If inputting hex, end hex input, otherwise input > 103 | ``` 104 | 105 | ### nedclib2 library (.o / .dll) 106 | 107 | #### Docs 108 | 109 | Please read the header file in `src/lib/nedclib2.h` 110 | 111 | #### Hello, World! 112 | 113 | GBA: https://web.archive.org/web/20210514055343/http://users.skynet.be/firefly/gba/download/example/ereader_gba_example_hello_world.zip 114 | 115 | Z80: https://web.archive.org/web/20210514055343/http://users.skynet.be/firefly/gba/download/example/ereader_z80_example_hello_world.zip 116 | 117 | #### Mario Sprite 118 | 119 | GBA: https://web.archive.org/web/20210514055343/http://users.skynet.be/firefly/gba/download/example/ereader_gba_example_mario_sprite.zip 120 | 121 | Z80: https://web.archive.org/web/20210514055343/http://users.skynet.be/firefly/gba/download/example/ereader_z80_example_mario_sprite.zip 122 | 123 | #### Custom Background 124 | 125 | GBA: https://web.archive.org/web/20210514055343/http://users.skynet.be/firefly/gba/download/example/ereader_gba_example_custom_background.zip 126 | 127 | Z80: https://web.archive.org/web/20210514055343/http://users.skynet.be/firefly/gba/download/example/ereader_z80_example_custom_background.zip 128 | -------------------------------------------------------------------------------- /src/lib/nedclib2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "nedclib2.h" 5 | #include "rawbin/rs.h" 6 | 7 | int raw_pos; 8 | int bin_pos; 9 | 10 | int bin_type=0; //0 = Single File NEDC bin. 1 = Multi file NEDC bin. 2 = Multi file DRPD bin. 11 | 12 | NEDCLIB_API int nedc_fopen(FILE** f, const char* name, const char* mode) { 13 | FILE* handle = fopen(name, mode); 14 | *f = handle; 15 | return !handle; 16 | } 17 | 18 | int count_bin(FILE *f) 19 | { 20 | int count=0; 21 | int i; 22 | unsigned char *data; 23 | 24 | fseek(f,0,SEEK_END); 25 | i=ftell(f); 26 | fseek(f,0,SEEK_SET); 27 | if((i==0x81C)||(i==0x51C)) 28 | { 29 | bin_type=0; //Nintendo e-Reader, old style bin format. 30 | return 1; //Count is one dotcode bin. 31 | } 32 | else 33 | { 34 | bin_type = 1; 35 | fseek(f,0,SEEK_SET); 36 | } 37 | data = (unsigned char*)malloc(0x840); //Worst case bin file size, no error correction. 38 | if(data==NULL) 39 | return 0; //Couldn't allocate the memory for dotcode bins. 40 | while(read_next_bin(f,data)) 41 | count++; 42 | fseek(f,0,SEEK_SET); //Rewind back to first bin. 43 | 44 | 45 | free(data); 46 | return count; 47 | } 48 | 49 | int read_next_bin(FILE *f, unsigned char *bindata) 50 | { 51 | int result; 52 | bin_pos=ftell(f); 53 | switch(bin_type) 54 | { 55 | case 0: 56 | result = (int)fread(bindata,1,0x81C,f); 57 | break; 58 | case 1: 59 | result = (int)fread(bindata,1,0x30,f); 60 | result += (int)fread(&bindata[0x30],1,(bindata[6]==8)?0x810:0x510,f); 61 | break; 62 | } 63 | 64 | return result; 65 | } 66 | 67 | 68 | int count_raw(FILE *f) 69 | { 70 | int count=0; 71 | unsigned char *data; 72 | 73 | data = (unsigned char*)malloc(0xB60); //Worst case raw file size. 74 | if(data==NULL) 75 | return 0; //Unable to allocate memory (and therefore count the raw data files.) 76 | fseek(f,0,SEEK_SET); 77 | while(read_next_raw(f,data)) 78 | count++; 79 | free(data); 80 | fseek(f,0,SEEK_SET); 81 | return count; 82 | } 83 | 84 | 85 | 86 | int read_next_raw(FILE *f, unsigned char *rawdata) 87 | { 88 | size_t result; 89 | 90 | raw_pos = ftell(f); 91 | 92 | unsigned char rawheader[24]; 93 | int i = 0, j = 0, k = 0, l = 0; 94 | 95 | if(is_rs_initialized()) 96 | l=1; 97 | else 98 | initialize_rs(); 99 | 100 | for(i=0,result=0;i<24;i+=2) 101 | { 102 | result+=fread(&rawheader[i],1,2,f); 103 | fseek(f,0x66,SEEK_CUR); 104 | } 105 | if(result==24) 106 | { 107 | fseek(f,raw_pos,SEEK_SET); 108 | //int rs_decode(unsigned char *data, unsigned char *erasure, int size, int parity, int encoder) 109 | //if(rs_decode(rawheader,(unsigned char*)erasuredata,24,16,0)>=0) 110 | if(correct_errors(rawheader,24,16)>=0) 111 | { 112 | i=rawheader[4]*rawheader[7]; 113 | if((i%0x66)>0) 114 | i+=(0x66-(i%0x66)); 115 | i/=0x66; 116 | k=i; 117 | i*=0x68; 118 | if(i>0xB60) 119 | { 120 | if(l==0) free_rs(); 121 | return 0; 122 | } 123 | result = fread(rawdata,1,i,f); 124 | if(i!=result) 125 | { 126 | if(l==0) free_rs(); 127 | return 0; //Raw data shorter than calculated. 128 | } 129 | j=0; 130 | while((j*12)> 10) < address) 41 | { 42 | start = (addr[1] >> 10) + 1; 43 | } 44 | if(((addr[0] >> 10) == address)&&(address!=0)) 45 | return; //No need to calculate anything. 46 | if(((addr[0] >> 10) > address) || (addr[1] == 0x3FF)) 47 | { 48 | //Must recalculate the address starting from 0. 49 | start = 1; 50 | addr[1] = 0x3FF; 51 | } 52 | 53 | for(unsigned long i=start,base=0x769;i<=(address+1);i++,base=0x769) 54 | { 55 | addr[0] = addr[1]; 56 | addr[1] = addr[0] ^ ((i & (-i)) * base); 57 | for(mask=0x1FFF,bits=0x651;bits>0;mask>>=1,bits>>=1) 58 | { 59 | if((i & mask)==0) 60 | { 61 | if(bits & 1) 62 | addr[1] ^= base; 63 | base <<= 1; 64 | } 65 | } 66 | } 67 | } 68 | 69 | /* ---- ADDRESS BAR REED SOLOMON VERIFICATION ---- */ 70 | 71 | int addr_init=0; 72 | 73 | unsigned char Alpha_to[32]; 74 | unsigned char Index_of[32]; 75 | 76 | unsigned char multiply_table[2][24] = { 77 | { 78 | 0x0F, 0x15, 0x18, 0x0C, 0x06, 0x03, 0x13, 0x1B, 79 | 0x1F, 0x1D, 0x1C, 0x0E, 0x07, 0x11, 0x1A, 0x0D, 80 | 0x14, 0x0A, 0x05, 0x10, 0x08, 0x04, 0x02, 0x01 81 | }, 82 | { 83 | 0x14, 0x10, 0x02, 0x09, 0x17, 0x0F, 0x0C, 0x13, 84 | 0x1D, 0x07, 0x0D, 0x05, 0x04, 0x12, 0x0B, 0x1E, 85 | 0x18, 0x03, 0x1F, 0x0E, 0x1A, 0x0A, 0x08, 0x01 86 | } 87 | }; 88 | 89 | unsigned char syndrome[2]; 90 | 91 | void init_tables() 92 | { 93 | int i,j; 94 | Alpha_to[0x1F] = 0; 95 | Index_of[0x00] = 0x1F; 96 | for(i=0,j=1;i<0x1E;i++) 97 | { 98 | Alpha_to[i]=j; 99 | Index_of[j]=i; 100 | j<<=1; 101 | if(j>0x1F) 102 | j^=0x25; 103 | } 104 | } 105 | 106 | 107 | int generate_syndrome(unsigned long addr_data) 108 | { 109 | int i,j,error=0; 110 | unsigned long address = addr_data ^ 0x3FF; 111 | for(i=0;i<2;i++) 112 | { 113 | syndrome[i] = 0; 114 | for(j=0;j<24;j++) 115 | { 116 | if(address & (1 << (23-j))) 117 | { 118 | syndrome[i] ^= multiply_table[i][j]; 119 | } 120 | } 121 | syndrome[i] = Index_of[syndrome[i]]; 122 | if(syndrome[i] != 0x1F) 123 | error=1; 124 | } 125 | return error; 126 | } 127 | 128 | int rs_add(unsigned char num1, unsigned char num2) 129 | { 130 | int i,j; 131 | if((num1==0x1F)||(num2==0x1F)) 132 | return 0x1F; 133 | i=num1+num2; 134 | j=i-0x1F; 135 | if(i>0x1E) 136 | return j; 137 | else 138 | return i; 139 | } 140 | 141 | int rs_multiply(int num1, int num2) 142 | { 143 | int i,j; 144 | for(i=0,j=0;i=0;h--) 175 | { 176 | m=Alpha_to[rsdata[0]]; 177 | for(i=1;i<=numloops;i++) 178 | { 179 | k=rsdata[i]; 180 | j=rs_multiply(h,i); 181 | j=rs_add(k,j); 182 | l=Alpha_to[j]; 183 | m^=l; 184 | } 185 | if(m==0) 186 | { 187 | location[n++] = h; 188 | if(n==numloops) 189 | return 0; 190 | } 191 | } 192 | return -1; 193 | } 194 | 195 | int correct_address(unsigned long *addr_data) 196 | { 197 | int i,j; 198 | int num_loops=2; 199 | if(addr_init==0) 200 | init_tables(); 201 | generate_syndrome(addr_data[0]); 202 | unsigned long address = addr_data[0] ^ 0x3FF; 203 | for(i=0,j=0;i 2 | #define DCS 3 | #include "dcs.h" 4 | 5 | #include "nedclib2.h" 6 | 7 | void eight_ten_modulate(void) 8 | { 9 | int i, j; 10 | unsigned char raw0,raw1,raw2,raw3; 11 | unsigned char mod0,mod1,mod2,mod3,mod4,mod5,mod6,mod7; 12 | for (i=0;i>4]; 21 | mod1 = modtable[(raw0 & 0x0F)]; 22 | mod2 = modtable[(raw1 & 0xF0)>>4]; 23 | mod3 = modtable[(raw1 & 0x0F)]; 24 | mod4 = modtable[(raw2 & 0xF0)>>4]; 25 | mod5 = modtable[(raw2 & 0x0F)]; 26 | mod6 = modtable[(raw3 & 0xF0)>>4]; 27 | mod7 = modtable[(raw3 & 0x0F)]; 28 | 29 | _810mod[i][((j*10)/8)+0] = ((mod0 & 0x1F) << 3) + ((mod1 & 0x1C) >> 2); 30 | _810mod[i][((j*10)/8)+1] = ((mod1 & 0x03) << 6) + ((mod2 & 0x1F) << 1) + ((mod3 & 0x10) >> 4); 31 | _810mod[i][((j*10)/8)+2] = ((mod3 & 0x0F) << 4) + ((mod4 & 0x1E) >> 1); 32 | _810mod[i][((j*10)/8)+3] = ((mod4 & 0x01) << 7) + ((mod5 & 0x1F) << 2) + ((mod6 & 0x18) >> 3); 33 | _810mod[i][((j*10)/8)+4] = ((mod6 & 0x07) << 5) + ((mod7 & 0x1F)); 34 | } 35 | } 36 | } 37 | 38 | NEDCLIB_API int dpi_multiplier = 1; 39 | NEDCLIB_API int smooth = 0; 40 | int fill=0; 41 | 42 | void draw_dcs_pixel(int x, int y) 43 | { 44 | int i,j; 45 | 46 | switch(dpi_multiplier) 47 | { 48 | case 1: //300 DPI 49 | dcsbmp[x][y] = 1; 50 | break; 51 | case 2: //600 DPI 52 | if(fill!=0) 53 | { 54 | for(i=0;i<2;i++) 55 | for(j=0;j<2;j++) 56 | dcsbmp[(x*2)+i][(y*2)+j] = 1; 57 | } 58 | else 59 | { 60 | dcsbmp[(x*2)][(y*2)] = 1; 61 | } 62 | break; 63 | case 4: //1200 DPI 64 | if(fill!=0) 65 | { 66 | for(i=0;i<4;i++) 67 | for(j=0;j<4;j++) 68 | dcsbmp[(x*4)+i][(y*4)+j] = 1; 69 | } 70 | else 71 | { 72 | for(i=1;i<3;i++) 73 | for(j=1;j<3;j++) 74 | dcsbmp[(x*4)+i][(y*4)+j] = 1; 75 | } 76 | break; 77 | case 8: //2400 DPI 78 | if(fill!=0) 79 | { 80 | for(i=0;i<8;i++) 81 | for(j=0;j<8;j++) 82 | dcsbmp[(x*8)+i][(y*8)+j] = 1; 83 | } 84 | else 85 | { 86 | for(i=2;i<5;i++) 87 | { 88 | dcsbmp[(x*8)+i][(y*8)+1] = 1; 89 | dcsbmp[(x*8)+i][(y*8)+5] = 1; 90 | } 91 | for(i=1;i<6;i++) 92 | for(j=2;j<5;j++) 93 | dcsbmp[(x*8)+i][(y*8)+j] = 1; 94 | } 95 | break; 96 | } 97 | } 98 | 99 | void draw_sync_marker(int x, int y) 100 | { 101 | int xx, yy; 102 | int i,j,k, l, m; 103 | 104 | xx=(x*dpi_multiplier); 105 | yy=(y*dpi_multiplier); 106 | l=(5*dpi_multiplier); 107 | 108 | if((dpi_multiplier==1)||(smooth==0)) 109 | { 110 | fill = 1; 111 | for(i=1;i<4;i++) 112 | for(j=1;j<4;j++) 113 | { 114 | draw_dcs_pixel(x,y+j); 115 | draw_dcs_pixel(x+4,y+j); 116 | draw_dcs_pixel(x+i,y+j); 117 | draw_dcs_pixel(x+i,y); 118 | draw_dcs_pixel(x+i,y+4); 119 | } 120 | fill = 0; 121 | } 122 | else 123 | { 124 | k = (l/2)*(l/2); 125 | for(i=(l/2);i>=0;i--) 126 | for(j=(l/2);j>=0;j--) 127 | { 128 | m=((i*i)+(j*j))<=k ? 1 : 0; 129 | if(((i+j)==(l/2))&&((i==0)||(j==0))) 130 | m=0; 131 | dcsbmp[xx+((l/2)-1)+i][yy+((l/2)-1)+j] = m; 132 | dcsbmp[xx+((l/2)-1)+i][yy+((l/2)-1)-j] = m; 133 | dcsbmp[xx+((l/2)-1)-i][yy+((l/2)-1)-j] = m; 134 | dcsbmp[xx+((l/2)-1)-i][yy+((l/2)-1)+j] = m; 135 | //dcsbmp[xx+((l/2)-1)][yy+((l/2)-1)] = 1; 136 | } 137 | } 138 | } 139 | 140 | void draw_address_bar(int dotcodeblock, int address) 141 | { 142 | int i,j=dotcodeblock; 143 | draw_dcs_pixel((j*35)+4,9); //Render the T pixel 144 | draw_dcs_pixel(((j+1)*35)+4,9); //The B pixel is not rendered. 145 | 146 | calc_addr(j+address); //Calculate Error info for Address. 147 | 148 | for (i=0;i<16;i++) //Render the A pixels and E pixels. (A = Address, E = Error correction info.) 149 | { 150 | if(((((0x0001 << (i)) & addr[0]) >> (i)))==1) 151 | { 152 | draw_dcs_pixel((j*35)+4,33-i); 153 | } 154 | if(((((0x0001 << (i)) & addr[1]) >> (i)))==1) 155 | { 156 | draw_dcs_pixel(((j+1)*35)+4,33-i); 157 | } 158 | } 159 | } 160 | 161 | 162 | void init_dcs(void) 163 | { 164 | /* Purpose - Draw the bmp template for Dotcodes. */ 165 | /* 166 | XXX XXX 167 | YYYYY YYYYY 168 | YYYYY Z Z Z Z Z Z Z Z Z Z Z Z YYYYY 169 | YYYYY YYYYY 170 | XXX XXX 171 | 172 | 173 | T T 174 | A A 175 | A A 176 | . . 177 | . . 178 | . . 179 | A A 180 | A A 181 | E E 182 | E E 183 | E E 184 | . . 185 | . . 186 | . . 187 | E E 188 | E E 189 | B B 190 | 191 | 192 | XXX XXX 193 | YYYYY YYYYY 194 | YYYYY Z Z Z Z Z Z Z Z Z Z Z Z YYYYY 195 | YYYYY YYYYY 196 | XXX XXX 197 | */ 198 | int i, j; 199 | 200 | int start_address; 201 | 202 | /*if(dotcodelen==28) 203 | start_address=25; 204 | else 205 | start_address=1;*/ 206 | start_address=raw[1][1]; 207 | 208 | for (j=0;j> (7 - (count % 8))) & 0x01) 299 | draw_dcs_pixel((i*35)+9+k,j+6); 300 | //dcsbmp[(i*35)+9+k][j+6] = (_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01; 301 | } 302 | for (j=0;j<26;j++) 303 | for (k=0;k<34;k++,count++) 304 | { 305 | if((_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01) 306 | draw_dcs_pixel((i*35)+5+k,j+9); 307 | //dcsbmp[(i*35)+5+k][j+9] = (_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01; 308 | } 309 | for (j=0;j<3;j++) 310 | for (k=0;k<26;k++,count++) 311 | { 312 | //if(((_810mod[i][(int)(count/8)] >> (7 - (count % 8))))>0) 313 | if((_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01) 314 | draw_dcs_pixel((i*35)+9+k,j+35); 315 | //dcsbmp[(i*35)+9+k][j+35] = (_810mod[i][(int)(count/8)] >> (7 - (count % 8))) & 0x01; 316 | } 317 | 318 | count=0; 319 | } 320 | 321 | } 322 | -------------------------------------------------------------------------------- /src/nevpk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "nedclib2.h" 7 | 8 | void usage(void) 9 | { 10 | printf("usage :\n"); 11 | printf(" nvpktool [options]\n"); 12 | printf("options :\n"); 13 | printf(" -i input file (Required)\n"); 14 | printf(" -o output file (Required)\n"); 15 | printf(" -v verbose (Optional)\n"); 16 | printf(" -c compress (Required *)\n"); 17 | printf(" -d decompress (Required *)\n"); 18 | printf(" -level compression level (0=store 1=med 2=max (Default = 2)\n"); 19 | printf(" 3 = Discover best lzwindow/lzsize/method)\n"); 20 | printf(" -log Decompression log (Default = none)\n"); 21 | printf(" (following options are only valid for compression levels 1 & 2)\n"); 22 | printf(" -method compression method (0 or 1) (Default = 0)\n"); 23 | printf(" -lzwindow lz window size (Default = 4096)\n"); 24 | printf(" -lzsize lz max repeat size (Default = 256)\n"); 25 | } 26 | 27 | int main(int argc, char* argv[]) 28 | { 29 | int i,j,k; 30 | unsigned char *vpk_buf; 31 | FILE *f; 32 | 33 | int file_in=0; 34 | int file_out=0; 35 | int operation=0; 36 | int level=2; 37 | int method=0; 38 | int lzwindow=4096; 39 | int lzsize=256; 40 | unsigned long bitsize = 0xFFFFFFFF; 41 | 42 | printf("Nintendo e-Reader VPK Tool Version %d.%d\n",NEVPK_MAJOR,NEVPK_MINOR); 43 | printf("Copyright CaitSith2\n\n"); 44 | nedclib_version(); 45 | 46 | if(argc==1) 47 | { 48 | usage(); 49 | return 1; 50 | } 51 | 52 | for(i=1;i3) 90 | { 91 | printf("Max compression level is 3\n"); 92 | return 1; 93 | } 94 | continue; 95 | } 96 | if(!strcasecmp(argv[i],"-method")) 97 | { 98 | method=strtoul(argv[++i],0,0); 99 | if(method>1) 100 | { 101 | printf("Invalid compression method\n"); 102 | return 1; 103 | } 104 | continue; 105 | } 106 | if(!strcasecmp(argv[i],"-lzwindow")) 107 | { 108 | lzwindow=strtoul(argv[++i],0,0); 109 | /*if(lzwindow > 32768) 110 | { 111 | printf("Max lz window is 32768\n"); 112 | return 1; 113 | }*/ 114 | continue; 115 | } 116 | if(!strcasecmp(argv[i],"-lzsize")) 117 | { 118 | lzsize=strtoul(argv[++i],0,0); 119 | /*if(lzsize> 32768) 120 | { 121 | printf("Max lz size is 32768\n"); 122 | return 1; 123 | }*/ 124 | continue; 125 | } 126 | if(!strcasecmp(argv[i],"-verbose")) 127 | { 128 | verbose = 1; 129 | } 130 | 131 | if(!strcasecmp(argv[i],"-log")) 132 | { 133 | i++; 134 | if(nedc_fopen(&log,argv[i],"w")!=0) 135 | { 136 | printf("Failed to open log file\n"); 137 | log=NULL; 138 | } 139 | } 140 | 141 | } 142 | 143 | if(file_in == 0) 144 | { 145 | printf("Required parameter -i missing\n"); 146 | return 1; 147 | } 148 | if(file_out == 0) 149 | { 150 | printf("Required parameter -o missing\n"); 151 | return 1; 152 | } 153 | if(operation==0) 154 | { 155 | printf("-c or -d (not both) required\n"); 156 | return 1; 157 | } 158 | 159 | /* 160 | in=stream_open(argv[file_in],"rb"); 161 | out=stream_open(argv[file_out],"wb"); 162 | stream_seek(in,0,SEEK_END); 163 | i=stream_tell(in); 164 | stream_seek(in,0,SEEK_SET); 165 | lz77_encode(out,in,i,9); 166 | stream_close(in); 167 | stream_close(out); 168 | in=stream_open(argv[file_out],"rb"); 169 | out=stream_open(argv[file_in],"wb"); 170 | stream_seek(in,0,SEEK_END); 171 | i=stream_tell(in); 172 | stream_seek(in,0,SEEK_SET); 173 | lz77_decode(out,in,i); 174 | stream_close(in); 175 | stream_close(out); 176 | */ 177 | //return 0; 178 | 179 | log_write("Input file: %s\n",argv[file_in]); 180 | log_write("Output file: %s\n",argv[file_out]); 181 | log_write("Operation: %s\n",(operation==1)?"Compress":"Decompress"); 182 | if(operation == 1) 183 | { 184 | log_write("Compression Level: %d\n",level); 185 | if(level > 0) 186 | { 187 | if(level != 3) 188 | { 189 | log_write("Compression Method: %d\n",method); 190 | log_write("LZ Window: %d\n",lzwindow); 191 | log_write("LZ Size: %d\n",lzsize); 192 | } 193 | } 194 | } 195 | log_write("\n"); 196 | 197 | 198 | //f=; 199 | if(nedc_fopen(&f,argv[file_in],"rb")!=0) 200 | { 201 | printf("Unable to open input file %s\n",argv[file_in]); 202 | return 1; 203 | } 204 | fseek(f,0,SEEK_END); 205 | i = ftell(f); 206 | fseek(f,0,SEEK_SET); 207 | vpk_buf = (unsigned char *)malloc(i); 208 | if(vpk_buf==NULL) 209 | { 210 | printf("Not enough memory to allocate compression buffer\n"); 211 | return 1; 212 | } 213 | fread(vpk_buf,1,i,f); 214 | fclose(f); 215 | //f=; 216 | 217 | int b_move = 0; 218 | int b_size = 0; 219 | 220 | if(operation == 1) 221 | { 222 | if(level==3) 223 | { 224 | int result; 225 | for(j=16;j<65536;j<<=1) 226 | { 227 | for(k=16;k<65536;k<<=1) 228 | { 229 | //best_move=0x80000000; 230 | //best_size=0x80000000; 231 | //skip_huffman=1; 232 | /*for(l=1;l<(65536*2);l+=2) 233 | { 234 | if((l>j)&&(l<65536)) 235 | { 236 | l=65535; 237 | continue; 238 | } 239 | if((l>(65536+k))) 240 | { 241 | break; 242 | } 243 | if(l==65536) continue; 244 | if(l<65536) 245 | { 246 | best_move = l; 247 | best_size = 0; 248 | } 249 | else 250 | { 251 | best_move = b_move; 252 | best_size = l - 65536; 253 | }*/ 254 | printf("Filesize: %ld, lzwindow: %d, lzsize: %d ",((bitsize==0xFFFFFFFF)?0:bitsize/8),k,j); 255 | printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 256 | printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 257 | printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 258 | result=NVPK_compress(vpk_buf,i,level,k,j,method,NULL); 259 | if(result==0) 260 | { 261 | if(bitsize>bits_written) 262 | { 263 | lzwindow=k; 264 | lzsize=j; 265 | bitsize=bits_written; 266 | b_move=best_move; 267 | b_size=best_size; 268 | } 269 | } 270 | else if (result==3) //Window size is invalid, break out of the 271 | { //Size loop, and try next window size. 272 | break; 273 | } 274 | else if (result==4) //Repeat size is invalid, try next repeat size. 275 | { 276 | continue; 277 | } 278 | else if (result==2) //Buffer overrun error. (Data execution prevention) 279 | { 280 | continue; 281 | } 282 | //} 283 | } 284 | } 285 | if(bitsize==0xFFFFFFFF) 286 | { 287 | printf("Compression failed\n"); 288 | return 1; 289 | } 290 | skip_huffman=0; 291 | NVPK_compress(vpk_buf,i,level,lzwindow,lzsize,method,NULL); 292 | 293 | if(bitsize>bits_written) 294 | { 295 | bitsize=bits_written; 296 | } 297 | 298 | //skip_size=1; 299 | skip_lz77=1; 300 | for(j=1;jbits_written) 314 | { 315 | b_size=best_size; 316 | b_move=best_move; 317 | bitsize=bits_written; 318 | } 319 | } 320 | } 321 | } 322 | /*best_move=b_move; 323 | skip_size=0; 324 | for(j=1;jbits_written) 335 | { 336 | b_size=best_size; 337 | bitsize=bits_written; 338 | } 339 | } 340 | }*/ 341 | best_size=b_size; 342 | best_move=b_move; 343 | best_size=b_size; 344 | log_write("Compression Method: %d\n",method); 345 | log_write("LZ Window: %d\n",lzwindow); 346 | log_write("LZ Size: %d\n",lzsize); 347 | } 348 | if(nedc_fopen(&f,argv[file_out],"wb")!=0) 349 | { 350 | printf("Unable to open output file %s\n",argv[file_out]); 351 | return 1; 352 | } 353 | i=NVPK_compress(vpk_buf,i,level,lzwindow,lzsize,method,f); 354 | } 355 | else 356 | { 357 | if(nedc_fopen(&f,argv[file_out],"wb")!=0) 358 | { 359 | printf("Unable to open output file %s\n",argv[file_out]); 360 | return 1; 361 | } 362 | i=vpk_decompress(vpk_buf,f); 363 | } 364 | fclose(f); 365 | if(log!=NULL) 366 | fclose(log); 367 | 368 | j=i; 369 | 370 | free(vpk_buf); 371 | 372 | return 0; 373 | } 374 | -------------------------------------------------------------------------------- /src/lib/rawbmp/dcs_decode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define DCS 5 | #include "dcs.h" 6 | 7 | #include "nedclib2.h" 8 | 9 | unsigned char mod0,mod1,mod2,mod3,mod4,mod5,mod6,mod7; 10 | 11 | int read_bmp(FILE *f) 12 | { 13 | int filelen,i,j; 14 | unsigned short k; 15 | int x,xx,y; 16 | int bmp_start; 17 | fseek(f,0,SEEK_END); 18 | filelen = ftell(f); 19 | fseek(f,0,SEEK_SET); 20 | fread(&i,1,2,f); 21 | if((i&0xFFFF)!=0x4D42) 22 | return 0; //Not a bmp file 23 | fread(&i,1,4,f); 24 | if(i!=filelen) 25 | return 0; //Not a bmp file 26 | fread(&i,1,4,f); 27 | if(i!=0) 28 | return 0; //Not a bmp file 29 | fread(&bmp_start,1,4,f); 30 | 31 | fseek(f,4,SEEK_CUR); 32 | fread(&x,1,4,f); 33 | fread(&y,1,4,f); 34 | fseek(f,2,SEEK_CUR); 35 | fread(&k,1,2,f); 36 | if(k!=1) 37 | return 0; //Not a dotcode bmp 38 | fread(&i,1,4,f); 39 | if(i!=0) 40 | return 0; //Compressed bmp not supported. 41 | 42 | fseek(f,0x36,SEEK_SET); 43 | fread(&bmp_invert,1,4,f); 44 | 45 | 46 | switch(y) 47 | { 48 | case 44: 49 | dpi_multiplier = 1; 50 | break; 51 | case 88: 52 | dpi_multiplier = 2; 53 | break; 54 | case 176: 55 | dpi_multiplier = 4; 56 | break; 57 | case 352: 58 | dpi_multiplier = 8; 59 | break; 60 | default: 61 | return 0; //Not a dotcode bmp. 62 | } 63 | 64 | 65 | fseek(f,0x36,SEEK_SET); 66 | fread(&bmp_invert,1,4,f); 67 | fseek(f,62,SEEK_SET); 68 | 69 | for(i=0;i0;j+=4,xx-=32) 72 | { 73 | fread(&bmpdata[i][j],1,4,f); 74 | } 75 | } 76 | bmplen = j; 77 | for(dotcodelen=0,xx=x-5;xx>(35*dpi_multiplier);dotcodelen++,xx-=(35*dpi_multiplier)); 78 | 79 | /*if (filelen == 0x158E) 80 | { 81 | fseek(f,62,SEEK_SET); 82 | fread(bmpdata1,0x7C,44,f); 83 | dotcodelen = 28; 84 | bmplen = 0x7C; 85 | } 86 | else 87 | { 88 | fseek(f,62,SEEK_SET); 89 | fread(bmpdata2,0x50,44,f); 90 | dotcodelen = 18; 91 | bmplen = 0x50; 92 | }*/ 93 | 94 | return 1; //Dotcode bmp read successfully 95 | } 96 | 97 | int read_dcs_pixel(int x, int y, int source=1) 98 | { 99 | int xx,yy; 100 | switch (dpi_multiplier) 101 | { 102 | case 1: 103 | xx = x; 104 | yy = y; 105 | break; 106 | case 2: 107 | xx = x * 2; 108 | yy = y * 2; 109 | break; 110 | case 4: 111 | xx = (x * 4) + 1; 112 | yy = (y * 4) + 1; 113 | break; 114 | case 8: 115 | xx = (x * 8) + 2; 116 | yy = (y * 8) + 2; 117 | break; 118 | } 119 | switch (source) 120 | { 121 | case 0: //From bmpdata 122 | return (bmpdata[yy][xx/8] & (1 << (7 - (xx%8)))) >> (7-(xx%8)); 123 | break; 124 | case 1: //From dcsbmp 125 | default: 126 | return dcsbmp[xx][yy]; 127 | } 128 | 129 | } 130 | 131 | unsigned char bitflip(unsigned char byte) 132 | { 133 | int i,j=0; 134 | for(i=0;i<5;i++) 135 | { 136 | if(byte&(1<>i; 138 | } 139 | return j; 140 | } 141 | 142 | void invertmod(void) 143 | { 144 | mod7^=0x1F; 145 | mod6^=0x1F; 146 | mod5^=0x1F; 147 | mod4^=0x1F; 148 | mod3^=0x1F; 149 | mod2^=0x1F; 150 | mod1^=0x1F; 151 | mod0^=0x1F; 152 | } 153 | 154 | void read_reverse(int ii, int jj, int inverse) 155 | { 156 | int i=(dotcodelen-1-ii); 157 | int j=(104-4-jj); 158 | mod0 = _810mod[i][((j*10)/8)+4] & 0x1F; 159 | mod1 = (_810mod[i][((j*10)/8)+4] >> 5) & 0x07; 160 | mod1 += (_810mod[i][((j*10)/8)+3] << 3) & 0x18; 161 | mod2 = (_810mod[i][((j*10)/8)+3] >> 2) & 0x1F; 162 | mod3 = (_810mod[i][((j*10)/8)+3] >> 7) & 0x01; 163 | mod3 += (_810mod[i][((j*10)/8)+2] << 1) & 0x1E; 164 | mod4 = (_810mod[i][((j*10)/8)+2] >> 4) & 0x0F; 165 | mod4 += (_810mod[i][((j*10)/8)+1] << 4) & 0x10; 166 | mod5 = (_810mod[i][((j*10)/8)+1] >> 1) & 0x1F; 167 | mod6 = (_810mod[i][((j*10)/8)+1] >> 6) & 0x03; 168 | mod6 += (_810mod[i][((j*10)/8)+0] << 2) & 0x1C; 169 | mod7 = (_810mod[i][((j*10)/8)+0] >> 3) & 0x1F; 170 | mod0=bitflip(mod0); 171 | mod1=bitflip(mod1); 172 | mod2=bitflip(mod2); 173 | mod3=bitflip(mod3); 174 | mod4=bitflip(mod4); 175 | mod5=bitflip(mod5); 176 | mod6=bitflip(mod6); 177 | mod7=bitflip(mod7); 178 | 179 | if(inverse) 180 | invertmod(); 181 | } 182 | void read_forward(int i, int j, int inverse) 183 | { 184 | mod7 = _810mod[i][((j*10)/8)+4] & 0x1F; 185 | mod6 = (_810mod[i][((j*10)/8)+4] >> 5) & 0x07; 186 | mod6 += (_810mod[i][((j*10)/8)+3] << 3) & 0x18; 187 | mod5 = (_810mod[i][((j*10)/8)+3] >> 2) & 0x1F; 188 | mod4 = (_810mod[i][((j*10)/8)+3] >> 7) & 0x01; 189 | mod4 += (_810mod[i][((j*10)/8)+2] << 1) & 0x1E; 190 | mod3 = (_810mod[i][((j*10)/8)+2] >> 4) & 0x0F; 191 | mod3 += (_810mod[i][((j*10)/8)+1] << 4) & 0x10; 192 | mod2 = (_810mod[i][((j*10)/8)+1] >> 1) & 0x1F; 193 | mod1 = (_810mod[i][((j*10)/8)+1] >> 6) & 0x03; 194 | mod1 += (_810mod[i][((j*10)/8)+0] << 2) & 0x1C; 195 | mod0 = (_810mod[i][((j*10)/8)+0] >> 3) & 0x1F; 196 | 197 | if(inverse) 198 | invertmod(); 199 | } 200 | 201 | int checkmod(void) 202 | { 203 | read_forward(0,0,0); 204 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) 205 | { 206 | read_forward(1,0,0); 207 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) 208 | { 209 | return 0; 210 | } 211 | } 212 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) 213 | { 214 | read_forward(1,0,0); 215 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) 216 | { 217 | return 0; 218 | } 219 | } 220 | read_forward(0,0,1); 221 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) 222 | { 223 | read_forward(1,0,1); 224 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) 225 | { 226 | return 1; 227 | } 228 | } 229 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) 230 | { 231 | read_forward(1,0,1); 232 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) 233 | { 234 | return 1; 235 | } 236 | } 237 | read_reverse(0,0,0); 238 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) 239 | { 240 | read_reverse(1,0,0); 241 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) 242 | { 243 | return 2; 244 | } 245 | } 246 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) 247 | { 248 | read_reverse(1,0,0); 249 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) 250 | { 251 | return 2; 252 | } 253 | } 254 | read_reverse(0,0,1); 255 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x12)) 256 | { 257 | read_reverse(1,0,1); 258 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x01)&&(mod3==0x09)) 259 | { 260 | return 3; 261 | } 262 | } 263 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x02)) 264 | { 265 | read_reverse(1,0,1); 266 | if((mod0==0x00)&&(mod1==0x00)&&(mod2==0x00)&&(mod3==0x01)) 267 | { 268 | return 3; 269 | } 270 | } 271 | 272 | return -1; 273 | 274 | } 275 | 276 | 277 | void eight_ten_demodulate(void) 278 | { 279 | int i, j; 280 | unsigned char raw0,raw1,raw2,raw3; 281 | int modtype=0; 282 | 283 | modtype=checkmod(); 284 | if(modtype==-1) 285 | { 286 | printf("This is not a nintendo e-reader dotcode\n"); 287 | exit(1); 288 | } 289 | for (i=0;i>3)==0; 335 | else 336 | bmp_flip = ((bmpdata2[9][0] & 0x08)>>3)==0;*/ 337 | bmp_flip = (read_dcs_pixel(4,9,0)==0); 338 | } 339 | else 340 | { 341 | /*if(bmplen == 0x7C) 342 | bmp_flip = ((bmpdata1[9][0] & 0x08)>>3)==1; 343 | else 344 | bmp_flip = ((bmpdata2[9][0] & 0x08)>>3)==1;*/ 345 | bmp_flip = (read_dcs_pixel(4,9,0)==1); 346 | } 347 | 348 | //if (bmplen == 0x7C) 349 | //{ 350 | for (i=0;i> 7) & 0x01; 356 | dcsbmp[(i*8)+1][j] = (bmpdata[(width-1)-j][i] >> 6) & 0x01; 357 | dcsbmp[(i*8)+2][j] = (bmpdata[(width-1)-j][i] >> 5) & 0x01; 358 | dcsbmp[(i*8)+3][j] = (bmpdata[(width-1)-j][i] >> 4) & 0x01; 359 | dcsbmp[(i*8)+4][j] = (bmpdata[(width-1)-j][i] >> 3) & 0x01; 360 | dcsbmp[(i*8)+5][j] = (bmpdata[(width-1)-j][i] >> 2) & 0x01; 361 | dcsbmp[(i*8)+6][j] = (bmpdata[(width-1)-j][i] >> 1) & 0x01; 362 | dcsbmp[(i*8)+7][j] = (bmpdata[(width-1)-j][i] >> 0) & 0x01; 363 | } 364 | } 365 | 366 | if (bmp_flip) 367 | { 368 | for (i=0;i> 7) & 0x01; 390 | dcsbmp[(i*8)+1][j] = (bmpdata2[43-j][i] >> 6) & 0x01; 391 | dcsbmp[(i*8)+2][j] = (bmpdata2[43-j][i] >> 5) & 0x01; 392 | dcsbmp[(i*8)+3][j] = (bmpdata2[43-j][i] >> 4) & 0x01; 393 | dcsbmp[(i*8)+4][j] = (bmpdata2[43-j][i] >> 3) & 0x01; 394 | dcsbmp[(i*8)+5][j] = (bmpdata2[43-j][i] >> 2) & 0x01; 395 | dcsbmp[(i*8)+6][j] = (bmpdata2[43-j][i] >> 1) & 0x01; 396 | } 397 | else 398 | { 399 | bmpdata2[43-j][i] ^= ((bmp_invert == 0) ? 0xFF : 0); 400 | dcsbmp[(i*8)+0][j] = (bmpdata2[43-j][i] >> 7) & 0x01; 401 | dcsbmp[(i*8)+1][j] = (bmpdata2[43-j][i] >> 6) & 0x01; 402 | dcsbmp[(i*8)+2][j] = (bmpdata2[43-j][i] >> 5) & 0x01; 403 | dcsbmp[(i*8)+3][j] = (bmpdata2[43-j][i] >> 4) & 0x01; 404 | dcsbmp[(i*8)+4][j] = (bmpdata2[43-j][i] >> 3) & 0x01; 405 | dcsbmp[(i*8)+5][j] = (bmpdata2[43-j][i] >> 2) & 0x01; 406 | dcsbmp[(i*8)+6][j] = (bmpdata2[43-j][i] >> 1) & 0x01; 407 | dcsbmp[(i*8)+7][j] = (bmpdata2[43-j][i] >> 0) & 0x01; 408 | } 409 | } 410 | } 411 | if (bmp_flip) 412 | { 413 | for (i=0;i<44/2;i++) 414 | { 415 | for(j=0;j<639;j++) 416 | { 417 | dcsbmp[j][i] ^= dcsbmp[639-1-j][44-1-i]; 418 | dcsbmp[639-1-j][44-1-i] ^= dcsbmp[j][i]; 419 | dcsbmp[j][i] ^= dcsbmp[639-1-j][44-1-i]; 420 | } 421 | } 422 | } 423 | 424 | }*/ 425 | 426 | } 427 | 428 | void reverse_dcs(void) 429 | { 430 | int i, j, k, count=0; 431 | for(i=0;i 2 | #include 3 | #include 4 | #include 5 | 6 | #define d_mm 8 /* RS code over GF(2**4) - change to suit */ 7 | #define d_nn 255 /* nn=2**mm -1 length of codeword */ 8 | #define d_tt 127 /* number of errors that can be corrected */ 9 | #define d_kk (d_nn - (2*d_tt)) /* kk = nn-2*tt */ 10 | 11 | #include "rs.h" 12 | 13 | #define NO_PRINT 14 | 15 | unsigned char mm=8; 16 | unsigned char nn=255; 17 | unsigned char tt=16; 18 | unsigned char kk=239; 19 | 20 | int pp=0x187; 21 | unsigned char *alpha_to = NULL, *index_of = NULL, *gg = NULL; 22 | unsigned char *recd = NULL; 23 | unsigned char b0 = 0x78; 24 | 25 | int rs_init=-1; 26 | int curr_errlen=0; 27 | 28 | void make_rev(unsigned char *data, int len) 29 | { 30 | for(int i=0;i>1);i++) 46 | { 47 | x=data[i]; 48 | data[i]=data[len-i-1]; 49 | data[len-i-1]=x; 50 | } 51 | } 52 | 53 | void zerofill(unsigned char *data, int len) 54 | { 55 | for(int i=0;i=(nn+1)) 83 | mask^=pp; 84 | } 85 | } 86 | 87 | void gen_poly(int errlen=16) 88 | /* Obtain the generator polynomial of the tt-error correcting, length 89 | nn=(2**mm -1) Reed Solomon code from the product of (X+alpha**i), i=1..2*tt 90 | */ 91 | { 92 | register int i,j,x,y ; 93 | if(gg != NULL) { 94 | free(gg); 95 | gg = NULL; 96 | } 97 | gg=(unsigned char*)malloc(errlen); 98 | gg[0]=alpha_to[b0]; 99 | for(i=1;i=0;j--) 103 | { 104 | if(j==0) 105 | y=0; 106 | else 107 | y=gg[j-1]; 108 | x=gg[j]; 109 | if(x!=0) 110 | { 111 | x=index_of[x]+b0+i; 112 | if(x>=0xFF) 113 | x-=0xFF; 114 | y^=alpha_to[x]; 115 | } 116 | gg[j]=y; 117 | } 118 | } 119 | make_rev(gg,errlen); 120 | } 121 | 122 | void initialize_rs(int bits, int polynomial, int index, int errlen) 123 | { 124 | int i, j; 125 | 126 | mm=bits; 127 | if(rs_init!=mm) 128 | { 129 | for(i=0,j=1;i=errlen;i--) 192 | { 193 | z = index_of[data[i] ^ data[errlen-1]]; 194 | for(j=errlen-1;j>=0;j--) 195 | { 196 | if(j==0) 197 | x=0; 198 | else 199 | x=data[j-1]; 200 | if(z!=0xFF) 201 | { 202 | y=gg[j]; 203 | if(y!=0xFF) 204 | { 205 | y+=z; if(y>=0xFF) y-=0xFF; 206 | x^=alpha_to[y]; 207 | } 208 | } 209 | data[j]=x; 210 | } 211 | } 212 | invert_error_bytes(data,errlen); 213 | reverse_byte_order(data,dtalen); 214 | } 215 | 216 | int correct_errors(unsigned char *data, int dtalen, int errlen, unsigned char *erasure) 217 | { 218 | int i,j=0,result; 219 | int erase_pos[2*d_tt]; 220 | for(i=0;i0) 235 | if(eras_dec_rs(erase_pos,0)!=0) //0 syndrome should be returned now. 236 | return -1; //Otherwise errors not correctable. 237 | 238 | for(i=0;i 0){ 271 | phi[0] = 1; /* index form */ 272 | phi[1] = alpha_to[eras_pos[0]]; 273 | for (i=1;i < no_eras;i++) 274 | { 275 | U = eras_pos[i]; 276 | for (j=1;j < i+2;j++) 277 | { 278 | tmp1 = index_of[phi[j-1]]; 279 | tmp_pol[j] = (tmp1 == 0xFF)? 0 : alpha_to[(U+tmp1)%0xFF]; 280 | } 281 | for (j=1;j < i+2;j++) 282 | phi[j] = phi[j]^tmp_pol[j]; 283 | } 284 | /* put phi[x] in index form */ 285 | make_rev(phi,nn-kk+1); 286 | } 287 | 288 | /* recd[] is in polynomial form, convert to index form */ 289 | make_rev(recd,nn); 290 | 291 | /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x) namely 292 | @**(b0+i), i = 0, ... ,(2*tt-1) */ 293 | for (i=1; i <= nn-kk; i++) 294 | { s[i] = 0 ; 295 | for (j=0; j < nn; j++) 296 | if (recd[j] != 0xFF) 297 | s[i] ^= alpha_to[(recd[j]+(b0+i-1)*j)%0xFF] ; /* recd[j] in index form */ 298 | /* convert syndrome from polynomial form to index form */ 299 | if (s[i] != 0) syn_error = 1 ; /* set flag if non-zero syndrome => error */ 300 | s[i] = index_of[s[i]] ; 301 | }; 302 | 303 | 304 | if (syn_error) 305 | { /* if syndrome is zero, modified recd[] is a codeword */ 306 | /* Begin Berlekamp-Massey algorithm to determine error+erasure locator polynomial */ 307 | r = no_eras; 308 | deg_phi = no_eras; 309 | L = no_eras; 310 | if (no_eras > 0) 311 | { 312 | /* Initialize lambda(x) and b(x) (in poly-form) to phi(x) */ 313 | for (i=0;i < deg_phi+1;i++) lambda[i] = (phi[i] == 0xFF)? 0 : alpha_to[phi[i]]; 314 | for (i=deg_phi+1;i < 2*tt+1;i++) lambda[i] = 0; 315 | deg_lambda = deg_phi; 316 | for (i=0;i < 2*tt+1;i++) b[i] = lambda[i]; 317 | } 318 | else 319 | { 320 | lambda[0] = 1; 321 | for (i=1;i < 2*tt+1;i++) lambda[i] = 0; 322 | for (i=0;i < 2*tt+1;i++) b[i] = lambda[i]; 323 | } 324 | while (++r <= 2*tt) /* r is the step number */ 325 | { 326 | /* Compute discrepancy at the r-th step in poly-form */ 327 | discr_r = 0; 328 | for (i=0;i < 2*tt+1;i++) 329 | { 330 | if ((lambda[i] != 0) && (s[r-i] != 0xFF)) 331 | { 332 | tmp = alpha_to[(index_of[lambda[i]]+s[r-i])%0xFF]; 333 | discr_r ^= tmp; 334 | } 335 | } 336 | if (discr_r == 0) 337 | { 338 | /* 3 lines below: B(x) <-- x*B(x) */ 339 | tmp_pol[0] = 0; 340 | for (i=1;i < 2*tt+1;i++) tmp_pol[i] = b[i-1]; 341 | for (i=0;i < 2*tt+1;i++) b[i] = tmp_pol[i]; 342 | } 343 | else 344 | { 345 | /* 5 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ 346 | T[0] = lambda[0]; 347 | for (i=1;i < 2*tt+1;i++) 348 | { 349 | tmp = (b[i-1] == 0)? 0 : alpha_to[(index_of[discr_r]+index_of[b[i-1]])%0xFF]; 350 | T[i] = lambda[i]^tmp; 351 | } 352 | 353 | if (2*L <= r+no_eras-1) 354 | { 355 | L = r+no_eras-L; 356 | /* 2 lines below: B(x) <-- inv(discr_r) * lambda(x) */ 357 | for (i=0;i < 2*tt+1;i++) 358 | b[i] = (lambda[i] == 0)? 0 : alpha_to[(index_of[lambda[i]]-index_of[discr_r]+nn)%0xFF]; 359 | for (i=0;i < 2*tt+1;i++) lambda[i] = T[i]; 360 | } 361 | else 362 | { 363 | for (i=0;i < 2*tt+1;i++) lambda[i] = T[i]; 364 | /* 3 lines below: B(x) <-- x*B(x) */ 365 | tmp_pol[0] = 0; 366 | for (i=1;i < 2*tt+1;i++) tmp_pol[i] = b[i-1]; 367 | for (i=0;i < 2*tt+1;i++) b[i] = tmp_pol[i]; 368 | } 369 | } 370 | } 371 | /* Put lambda(x) into index form */ 372 | make_rev(lambda,2*tt+1); 373 | 374 | /* Compute deg(lambda(x)) */ 375 | deg_lambda = 2*tt; 376 | while ((lambda[deg_lambda] == 0xFF) && (deg_lambda > 0)) 377 | --deg_lambda; 378 | if (deg_lambda <= 2*tt) 379 | { 380 | /* Find roots of the error+erasure locator polynomial. By Chien Search */ 381 | for (i=1; i < 2*tt+1; i++) reg[i] = lambda[i] ; 382 | count = 0 ; /* Number of roots of lambda(x) */ 383 | for (i=1; i <= nn; i++) 384 | { 385 | q = 1 ; 386 | for (j=1; j <= deg_lambda; j++) 387 | if (reg[j] != 0xFF) 388 | { 389 | reg[j] = (reg[j]+j)%0xFF ; 390 | q ^= alpha_to[(reg[j])%0xFF] ; 391 | } ; 392 | if (!q) /* store root (index-form) and error location number */ 393 | { 394 | root[count] = i; 395 | loc[count] = nn-i; 396 | count++; 397 | }; 398 | } ; 399 | 400 | if (deg_lambda == count) /* correctable error */ 401 | { 402 | /* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo x**(nn-kk)). in poly-form */ 403 | for (i=0;i < 2*tt;i++) 404 | { 405 | omega[i] = 0; 406 | for (j=0;(j < deg_lambda+1) && (j < i+1);j++) 407 | { 408 | if ((s[i+1-j] != 0xFF) && (lambda[j] != 0xFF)) 409 | tmp = alpha_to[(s[i+1-j]+lambda[j])%0xFF]; 410 | else 411 | tmp = 0; 412 | omega[i] ^= tmp; 413 | } 414 | } 415 | omega[2*tt] = 0; 416 | /* Compute lambda_pr(x) = formal derivative of lambda(x) in poly-form */ 417 | for (i=0;i < tt;i++) 418 | { 419 | lambda_pr[2*i+1] = 0; 420 | lambda_pr[2*i] = (lambda[2*i+1] == 0xFF)? 0 : alpha_to[lambda[2*i+1]]; 421 | } 422 | lambda_pr[2*tt] = 0; 423 | /* Compute deg(omega(x)) */ 424 | deg_omega = 2*tt; 425 | while ((omega[deg_omega] == 0) && (deg_omega > 0)) 426 | --deg_omega; 427 | /* Compute error values in poly-form. num1 = omega(inv(X(l))), 428 | num2 = inv(X(l))**(b0-1) and den = lambda_pr(inv(X(l))) all in poly-form */ 429 | for (j=0;j < count;j++) 430 | { 431 | pres_root = root[j]; 432 | pres_loc = loc[j]; 433 | num1 = 0; 434 | for (i=0;i < deg_omega+1;i++) 435 | { 436 | if (omega[i] != 0) 437 | tmp = alpha_to[(index_of[omega[i]]+i*pres_root)%0xFF]; 438 | else 439 | tmp = 0; 440 | num1 ^= tmp; 441 | } 442 | num2 = alpha_to[(pres_root*(b0-1))%0xFF]; 443 | den = 0; 444 | for (i=0;i < deg_lambda+1;i++) 445 | { 446 | if (lambda_pr[i] != 0) 447 | tmp = alpha_to[(index_of[lambda_pr[i]]+i*pres_root)%0xFF]; 448 | else 449 | tmp = 0; 450 | den ^= tmp; 451 | } 452 | if (den == 0) 453 | { 454 | printf("\n ERROR: denominator = 0\n"); 455 | } 456 | err[pres_loc] = 0; 457 | if (num1 != 0) 458 | { 459 | err[pres_loc] = alpha_to[(index_of[num1]+index_of[num2]+(nn-index_of[den]))%0xFF]; 460 | } 461 | } 462 | /* Correct word by subtracting out error bytes. First convert recd[] into poly-form */ 463 | make_pow(recd,nn); 464 | for (j=0;j < count;j++) 465 | recd[loc[j]] ^= err[loc[j]]; 466 | 467 | return(count); 468 | } 469 | else /* deg(lambda) unequal to number of roots => uncorrectable error detected */ 470 | return(-2); 471 | } 472 | else /* deg(lambda) > 2*tt => uncorrectable error detected */ 473 | return(-3); 474 | } 475 | else 476 | { /* no non-zero syndromes => no errors: output received codeword */ 477 | make_pow(recd,nn); 478 | return(0); 479 | } 480 | } 481 | -------------------------------------------------------------------------------- /src/lib/rawbin/binraw.cpp: -------------------------------------------------------------------------------- 1 | #include "nedclib2.h" 2 | #include "rs.h" 3 | 4 | unsigned char ShortDotCodeHeader[0x30] = { 5 | 0x00, 0x30, 0x01, 0x01, 6 | 0x00, 0x01, 0x05, 0x10, 7 | 0x00, 0x00, 0x10, 0x12, //Constant data 8 | 9 | 0x00, 0x00, //Header First 2 bytes 10 | 11 | 0x02, 0x00, //Constant data 12 | 13 | 0x00, 0x00, //Header Second 2 bytes 14 | 15 | 0x10, 0x47, 0xEF, //Global Checksum 1 16 | 17 | 0x19, 0x00, 0x00, 0x00, 0x08, 0x4E, 0x49, 18 | 0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F, 0x00, 0x22, 19 | 0x00, 0x09, //Constant data 20 | 21 | 0x00, 0x00, //Header, last 8 bytes 22 | 0x00, 0x00, 0x00, 0x00, 23 | 0x00, 0x00, 24 | 0x00, //Header Checksum 25 | 0x57 //Global Checksum 2 26 | }; 27 | 28 | unsigned char LongDotCodeHeader[0x30] = { 29 | 0x00, 0x30, 0x01, 0x02, 30 | 0x00, 0x01, 0x08, 0x10, 31 | 0x00, 0x00, 0x10, 0x12, //Constant Data 32 | 33 | 0x00, 0x00, //Header, first 2 bytes 34 | 35 | 0x01, 0x00, //Constant data 36 | 37 | 0x00, 0x00, //Header, second 2 bytes 38 | 0x10, 0x9A, 0x99, //Global Checksum 1 39 | 40 | 0x19, 0x00, 0x00, 0x00, 0x08, 0x4E, 0x49, 41 | 0x4E, 0x54, 0x45, 0x4E, 0x44, 0x4F, 0x00, 0x22, 42 | 0x00, 0x09, //Constant data 43 | 44 | 45 | 0x00, 0x00, //Header, last 8 bytes 46 | 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 48 | 0x00, //Header Checksum 49 | 0x57 //Global Checksum 2 50 | }; 51 | 52 | unsigned char shortheader[0x18] = { 53 | 0x00, 0x02, 0x00, 0x01, 0x40, 0x10, 0x00, 0x1C, 54 | 0x10, 0x6F, 0x40, 0xDA, 0x39, 0x25, 0x8E, 0xE0, 55 | 0x7B, 0xB5, 0x98, 0xB6, 0x5B, 0xCF, 0x7F, 0x72 56 | }; 57 | unsigned char longheader[0x18] = { 58 | 0x00, 0x03, 0x00, 0x19, 0x40, 0x10, 0x00, 0x2C, 59 | 0x0E, 0x88, 0xED, 0x82, 0x50, 0x67, 0xFB, 0xD1, 60 | 0x43, 0xEE, 0x03, 0xC6, 0xC6, 0x2B, 0x2C, 0x93 61 | }; 62 | 63 | NEDCLIB_API int signature=0; 64 | NEDCLIB_API unsigned char signature_str[0x30]; 65 | 66 | static int dotcodelen; 67 | unsigned char bin_header[24]; 68 | 69 | void raw_header(unsigned char *bindata, unsigned char *data, int size) 70 | { 71 | int i,j,k; 72 | int global1, global2; 73 | 74 | for(i=0;i<0x30;i++) 75 | data[i]=((size==0x81c)?LongDotCodeHeader[i]:ShortDotCodeHeader[i]); 76 | 77 | 78 | for(i=0,j=0;i<12;i++) 79 | j ^= bindata[i]; 80 | 81 | data[0x2E] = j; 82 | data[0x0D] = bindata[0]; 83 | data[0x0C] = bindata[1]; 84 | data[0x11] = bindata[2]; 85 | data[0x10] = bindata[3]; 86 | 87 | data[0x26] = bindata[4]; 88 | data[0x27] = bindata[5]; 89 | data[0x28] = bindata[6]; 90 | data[0x29] = bindata[7]; 91 | data[0x2A] = bindata[8]; 92 | data[0x2B] = bindata[9]; 93 | data[0x2C] = bindata[10]; 94 | data[0x2D] = bindata[11]; 95 | 96 | 97 | data[0x12] = 0x10; //calculate Global Checksum 1 98 | data[0x02] = 1; //Do not calculate Global Checksum 2 99 | 100 | for(i=0x0C,j=0;i<0x81C;i++) 101 | { 102 | if(i&1) 103 | j += bindata[i]; 104 | else 105 | j += (bindata[i] << 8); 106 | } 107 | j &= 0xFFFF; 108 | j ^= 0xFFFF; 109 | data[0x13] = (j & 0xFF00) >> 8; 110 | data[0x14] = (j & 0x00FF); 111 | 112 | for(i=0,j=0;i<0x2F;i++) 113 | j+=data[i]; 114 | j &= 0xFF; 115 | for(i=1,global2=0;i<0x2C;i++) 116 | { 117 | for(k=0,global1=0;k<0x30;k++) 118 | { 119 | global1 ^= bindata[((i-1)*0x30)+k+0x0C]; 120 | } 121 | global2 += global1; 122 | } 123 | global2 += j; 124 | global2 &= 0xFF; 125 | global2 ^= 0xFF; 126 | data[0x2F] = global2; 127 | } 128 | 129 | void interleave_dotcode(unsigned char *data, unsigned char *interleave, int dotcodepointer, int size) 130 | { 131 | int i; 132 | int dotcodeinterleave; 133 | 134 | if(bin_type==2) 135 | { 136 | dotcodeinterleave = bin_header[7]; 137 | for(i=0;i0) 512 | j++; 513 | 514 | dotcodeinterleave=bin_header[7]; 515 | dotcodepointer=0; 516 | 517 | for(i=2;i1)&&(MultiStrip==0)) 561 | snprintf(filename,sizeof(filename),"%s-%.2d.bin",binfile,k+1); 562 | else 563 | snprintf(filename,sizeof(filename),"%s",binfile); 564 | 565 | if(MultiStrip) 566 | { 567 | if(nedc_fopen(&g,filename,"rb+")) 568 | if(nedc_fopen(&g,filename,"wb")) 569 | return -4; 570 | if(!count_bin(g)) 571 | { 572 | fseek(g,0,SEEK_SET); 573 | bin_type=1; 574 | } 575 | else 576 | { 577 | fseek(g,0,SEEK_END); 578 | } 579 | } 580 | else 581 | { 582 | bin_type=0; 583 | if(nedc_fopen(&g,filename,"wb")) 584 | return -4; 585 | } 586 | //fwrite(raw,1,j+k,g); 587 | //fclose(g); 588 | if(g!=NULL) 589 | { 590 | //return -4; 591 | switch(bin_type) 592 | { 593 | case 0: //Will not covert to this old style format. 594 | case 1: //All 48 bytes of the header is now included 595 | //from now on. 596 | fwrite(bin,1,((size==0xB60)?0x840:0x540),g); 597 | break; 598 | case 2: 599 | fwrite(bin_header,1,8,g); 600 | fwrite(bin,1,((bin_header[4]-bin_header[5])*bin_header[7]),g); 601 | break; 602 | } 603 | 604 | fclose(g); 605 | numbin++; 606 | } 607 | } 608 | 609 | free_rs(); 610 | 611 | return (numbin>0)?0:-1; 612 | } 613 | 614 | NEDCLIB_API int fixraw(char *rawfile) 615 | { 616 | unsigned char data[255]; 617 | 618 | unsigned char dotcodetemp[0xB60]; 619 | unsigned char raw[0xB60]; 620 | int dotcodepointer=0; 621 | int dotcodeinterleave; 622 | 623 | int num_dotcodes; 624 | 625 | int result; 626 | int i,j,k; 627 | int x,y; 628 | 629 | int temp; 630 | int size; 631 | FILE *f; 632 | 633 | initialize_rs(); 634 | 635 | if(nedc_fopen(&f,rawfile,"rb+")) 636 | return -1; //Input file not opened. 637 | num_dotcodes = count_raw(f); 638 | 639 | for(k=0;k0) 675 | j++; 676 | dotcodeinterleave=bin_header[7]; 677 | dotcodepointer=0; 678 | 679 | for(i=2;i 2 | #include 3 | #include 4 | 5 | #include "nedclib2.h" 6 | 7 | unsigned char carddata[0x81C]; 8 | unsigned char rawdata[0xB60]; 9 | 10 | unsigned char bindata[0x20000]; 11 | unsigned char vpkdata[24564]; 12 | 13 | char title[13][33]; 14 | 15 | char title_store[13][33]; 16 | 17 | unsigned char cardheader[0x0C] = { 18 | 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 19 | // reg, type, numc, data size flags 20 | }; 21 | 22 | #define REGION_JAPAN 0 23 | #define REGION_US 1 24 | #define REGION_JAPANPLUS 2 25 | 26 | #define APPTYPE_NES 0 27 | #define APPTYPE_Z80 1 28 | #define APPTYPE_GBA 2 29 | #define APPTYPE_RAW 3 30 | 31 | #define CARD_SHORT_NO 0 32 | #define CARD_SHORT_YES 1 33 | #define CARD_LONG_NO 2 34 | #define CARD_LONG_YES 3 35 | 36 | //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}]... 37 | // {-jp, -us, -jep} - Region (default US) 38 | // {-Z80 -GBA -NES} - Application Type (default Z80) 39 | // {-stn, -sty, -ltn, -lty} - Application/Card Titling mode (default Long title, no individual names) 40 | // {-long, -short} - Dotcode size; (default, long) 41 | // {-mus1, -mus2} - Music to be played during card loading, if in short titling mode. (default music 1) 42 | // {-save} - Allows the scanned dotcodes to be saved, (default disallowed) 43 | 44 | void usage(int extended=0) 45 | { 46 | 47 | printf("usage :\n"); 48 | printf(" nedcmaker [options]\n"); 49 | printf("options :\n"); 50 | // " | | |-123456789-123456789-12345678" 51 | printf(" -i input file (required)\n"); 52 | printf(" -o output name (optional)\n"); 53 | printf(" -type type (0=nes 1=z80 (required)\n"); 54 | printf(" 2 = gba 3 = raw\n"); 55 | printf(" -region region (0=jap 1=usa 2=jap+) (default = usa)\n"); 56 | printf(" -name Application name (default = none)\n"); 57 | printf(" -title Individual Card Titles (default = none)\n"); 58 | printf(" -dcsize dcsize (0=long 1=short) (default = long)\n"); 59 | printf(" -fill fill (0=none 1=filled) (default = none)\n"); 60 | printf(" -save save (0=no 1=yes) (default = no)\n"); 61 | printf(" -titlemode titlemode (0=short, no individual titles)\n"); 62 | printf(" (1=short, individual card titles)\n"); 63 | printf(" (2=long, no individual titles (default))\n"); 64 | printf(" (3=long, individual card titles)\n"); 65 | printf(" -bin Output bin files At least one\n"); 66 | printf(" -raw Output raw files of these options\n"); 67 | printf(" -bin Output bmp files is required\n"); 68 | printf(" -music music (0=Normal 1=cheery) (default = normal)\n"); 69 | printf(" -help (or -?) Print extended usage info\n"); 70 | 71 | if(extended) 72 | { 73 | printf("\n"); 74 | printf("The music option is only valid for title modes 0 and 1\n\n"); 75 | 76 | printf("This tool can auto compress bins to vpks, using default options of\n"); 77 | printf("lzwindow 16384, lzsize 2048, compression method 0, and compression level 2\n"); 78 | printf("if the input file is not already vpk compressed\n"); 79 | 80 | printf("additionally, if you supply an iNES standard .nes file, mapper 0, 1 PRG rom\n"); 81 | printf("1 CHR rom, the rom will be encoded for you.\n"); 82 | 83 | printf("If titlemode 1 is specified, you can add a pokemon serial# and hitpoints \n"); 84 | printf("to the individual titles, in the form of [hitpoint]:X-YY-Z:[title]\n"); 85 | printf(" [Hitpoint] = 0-150\n"); 86 | printf(" X = A-Z,-,_\n"); 87 | printf(" Y = 01-99,A0-A9,B0-B9,C0-C8\n"); 88 | printf(" Z = A-G,#\n"); 89 | printf(" [title] = Whatever you want here\n"); 90 | printf(" For example: \"50:D-35-#:Aipom\"\n"); 91 | printf("If your using this program in a makefile, please replace # with H, as # causes the\n"); 92 | printf("rest of the line to be treated as a comment in a makefile.\n"); 93 | printf("If titlemode is 3, then you only need to specify the [title] with each -title\n"); 94 | printf("Title modes 0-1 do not have the english character set for regions 0 or 2.\n\n"); 95 | 96 | printf("If you specify a region of 0, then Titlemode automatically becomes 1 or 3\n"); 97 | printf("Also, the only valid application type for region 0 is z80\n\n"); 98 | 99 | printf("If -o is not specified, the output files will be 01.bin - 12.bin\n"); 100 | printf("Otherwise it will be -01.bin - -12.bin\n\n"); 101 | 102 | printf("Short title mode is not compatible with short dotcodes\n"); 103 | 104 | printf("The Following max size tables assume your using apptype nes or z80.\n"); 105 | printf("If your using apptype gba, then subtract 4 from each of these values\n"); 106 | printf("If using raw, then the max size is 1998 bytes for long and 1230 bytes\n"); 107 | printf("for short dotcodes\n\n"); 108 | 109 | printf("Max size of Long dotcodes in order of title modes (US/Jap+)\n"); 110 | printf("0=24564, 2=24372, 1=21540, 3=19620\n\n"); 111 | 112 | printf("Max size of Short dotcodes in order of title modes (US/Jap+)\n"); 113 | //printf("0=15348, 2=15156, 1=12324, 3=10404\n\n"); 114 | printf("2=15156, 3=10404\n\n"); 115 | 116 | printf("Max size of Long dotcodes in order of title modes (Jap)\n"); 117 | printf("1=%d, 3=%d\n\n", (((0x81C - 0x1D)-(0x15*(8)))*(8)),(((0x81C - 0x2D)-(0x21*(8)))*(8))); 118 | 119 | printf("Max size of Short dotcodes in order of title modes (Jap)\n"); 120 | printf("1=%d, 3=%d\n\n", (((0x51C - 0x1D)-(0x15*(8)))*(8)),(((0x51C - 0x2D)-(0x21*(8)))*(8))); 121 | } 122 | 123 | } 124 | 125 | unsigned char jistable [] = 126 | { 127 | 0x40, 0x49, 0x00, 0x94, 0x90, 0x93, 0x95, 0x66, 0x69, 0x6A, 128 | 0x96, 0x7B, 0x43, 0x5D, 0x44, 0x5E, 0x4F, 0x50, 0x51, 0x52, 129 | 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x46, 0x47, 0x83, 0x81, 130 | 0x84, 0x48, 0x97, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 131 | 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 132 | 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x6D, 133 | 0x5F, 0x6E, 0x4F, 0x51, 0x4D, 0x81, 0x82, 0x83, 0x84, 0x85, 134 | 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 135 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 136 | 0x9A, 0x6F, 0x62, 0x70, 0x60 137 | } ; 138 | 139 | unsigned char shorttitle_table[] = { 140 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 141 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 142 | 0x01,0xB5,0xB6,0x00,0x00,0xB7,0xB8,0xC0,0x00,0x00,0x00,0xBC,0xB3,0xBD,0xBF,0xBB, 143 | 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0xBE,0x00,0x00,0x00,0x00,0xBA, 144 | 0x00,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, 145 | 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0x00,0x00,0x00,0x00,0x00, 146 | 0x00,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4, 147 | 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,0x00,0x00,0x00,0xB9,0x00, 148 | }; 149 | 150 | void shiftJIS(char *str, char *output, int len, int cardmode) 151 | { 152 | int i; 153 | if(cardmode >= 2) 154 | { 155 | for(i=0;i<(len/2);i++) 156 | { 157 | if (str[i] == 0) 158 | break; 159 | else if (((str[i] >= 'a') && (str[i] <= 'z')) || \ 160 | ((str[i] >= 'A') && (str[i] <= 'Z')) || \ 161 | ((str[i] >= '0') && (str[i] <= '9')) ) 162 | { 163 | output[(i*2)+1] = jistable[str[i]-0x20]; 164 | output[(i*2)] = (char)0x82; 165 | } 166 | else 167 | { 168 | output[(i*2)+1] = jistable[str[i]-0x20]; 169 | output[(i*2)] = (char)0x81; 170 | } 171 | } 172 | output[(i*2)] = 0; 173 | } 174 | else 175 | { 176 | for(i=0;i> 2; 290 | } 291 | j = titlestr[2]; 292 | k = titlestr[3]; 293 | if((j=='a')||(j=='b')||(j=='c')) 294 | { 295 | j -= 'a'; 296 | j *= 10; 297 | j += 100; 298 | } 299 | else if((j=='A')||(j=='B')||(j=='C')) 300 | { 301 | j -= 'A'; 302 | j *= 10; 303 | j += 100; 304 | } 305 | else 306 | { 307 | j -= '0'; 308 | j *= 10; 309 | } 310 | k -= '0'; 311 | j += k; 312 | j--; 313 | j &= 0x7F; 314 | 315 | title[titlenum][0] |= j << 7; 316 | title[titlenum][1] |= j >> 1; 317 | 318 | if((titlestr[5] == '#') || (titlestr[5] == 'H')) 319 | title[titlenum][0] |= 0x70; 320 | else 321 | { 322 | k = titlestr[5]; 323 | if ((k - 'A') < 7) 324 | k -= 'A'; 325 | else 326 | k -= 'a'; 327 | k &= 0x07; 328 | title[titlenum][0] |= k << 4; 329 | } 330 | 331 | 332 | 333 | 334 | } 335 | i++; 336 | if(region!=1) 337 | { 338 | shiftJIS(str+i,jistitle,0x12,cardmode); 339 | for(j=0;j<0x12;j++) 340 | { 341 | title[titlenum][j+3] = jistitle[j]; 342 | if(jistitle[j]==0) 343 | break; 344 | } 345 | if(j==0x12) 346 | { 347 | printf("Warning: Title %s will be truncated to \n\t",str); 348 | for(j=0;j<(0x12/2);i++,j++) 349 | jistitle[j]=str[i]; 350 | jistitle[j] = 0; 351 | printf("\"%s\"\n",jistitle); 352 | } 353 | } 354 | else 355 | { 356 | for(j=0;j<0x12;j++,i++) 357 | { 358 | title[titlenum][j+3] = str[i]; 359 | if(str[i]==0) 360 | break; 361 | } 362 | if(j==0x12) 363 | { 364 | i-=0x12; 365 | printf("Warning: Title %s will be truncated to \n\t",str); 366 | for(j=0;j<0x12;i++,j++) 367 | jistitle[j]=str[i]; 368 | printf("\"%s\"\n",jistitle); 369 | } 370 | } 371 | 372 | 373 | } 374 | } 375 | 376 | int main(int argc, char* argv[]) 377 | { 378 | int i,j,k; 379 | FILE *f; 380 | int region=REGION_US; 381 | int apptype=-1; 382 | int cardsize=0x81C; 383 | int headersize=0x2D; 384 | int settitlesize=33; 385 | int cardtitlesize=0; 386 | int allowsave=0; 387 | int mode=CARD_LONG_NO; 388 | int numtitles=1; 389 | int numcards; 390 | int filename; 391 | char fn[256]; 392 | char fn2[256]; 393 | int filesize; 394 | int basename=0; 395 | int music=0; 396 | int fill=0; 397 | int bin=0; 398 | int raw=0; 399 | int bmp=0; 400 | int compress=0; 401 | 402 | for(i=0;i<13;i++) 403 | for(j=0;j<33;j++) 404 | title[i][j]=0; 405 | 406 | printf("Nintendo E-Reader Dotcode bin maker tool Version %d.%d\n",NEDCMAKE_MAJOR,NEDCMAKE_MINOR); 407 | printf("Copyright CaitSith2\n\n"); 408 | nedclib_version(); 409 | 410 | for(i=1;i\n"); 582 | return 1; 583 | } 584 | if(apptype==-1) 585 | { 586 | printf("Required paramete missing: -type \n"); 587 | return 1; 588 | } 589 | if(apptype>3) 590 | { 591 | printf("Invalid application type\n"); 592 | return 1; 593 | } 594 | if(mode>3) 595 | { 596 | printf("Invalid Title mode\n"); 597 | return 1; 598 | } 599 | 600 | 601 | //f=fopen(argv[filename],"rb"); 602 | //if(f==NULL) 603 | if(nedc_fopen(&f,argv[filename],"rb")) 604 | { 605 | printf("Error: VPK file could not be opened for reading\n"); 606 | //Could not open vpk file 607 | return 1; 608 | } 609 | fseek(f,0,SEEK_END); 610 | filesize=ftell(f); 611 | fseek(f,0,SEEK_SET); 612 | fread(bindata,1,4,f); 613 | fseek(f,0,SEEK_SET); 614 | 615 | if(!is_vpk(bindata)) 616 | { 617 | compress = 1; 618 | if(apptype==APPTYPE_NES) 619 | { 620 | if(is_nes(bindata)) 621 | { 622 | fread(bindata,1,filesize,f); 623 | nedc_encode_nes(bindata); 624 | filesize-=16; 625 | for(i=0;i24562)&&(apptype!=APPTYPE_GBA))||((filesize>24558)&&(apptype==APPTYPE_GBA))) 675 | { 676 | printf("Error: VPK data too large for even Title mode 0\n"); 677 | //VPK file is too large for ereader card sets 678 | return 1; 679 | } 680 | } 681 | else 682 | { 683 | if(filesize>(0x81C-0x0C-33-33)) 684 | { 685 | printf("Error: Data too large for this dotcode type\n"); 686 | return 1; 687 | } 688 | } 689 | 690 | fclose(f); 691 | 692 | if(region!=0) 693 | { 694 | j = 12; 695 | } 696 | else 697 | { 698 | j = 8; 699 | } 700 | for(i=0;i>3; 736 | cardheader[5] |= (filesize & 0xFF); 737 | cardheader[6] = filesize >> 8; 738 | 739 | if(region==0) 740 | cardheader[8] = 0; 741 | 742 | int cardoffset; 743 | 744 | int l = 0; 745 | for(i=1,cardoffset=0;i<=numcards;i++,cardoffset=0) 746 | { 747 | switch(fill) 748 | { 749 | case 0: 750 | memset(carddata,0,0x81C); 751 | break; 752 | case 1: 753 | for(j=0;j<0x81C;j++) 754 | carddata[j] = j & 0xFF; 755 | break; 756 | } 757 | cardheader[4] += 2; 758 | for(j=0;j<0x0C;j++) 759 | carddata[cardoffset++] = cardheader[j]; 760 | 761 | for(j=0;j 2 | #include 3 | #include 4 | #include 5 | 6 | #include "nedclib2.h" 7 | 8 | NEDCLIB_API FILE *log; 9 | NEDCLIB_API int verbose=0; 10 | 11 | unsigned char *bitstore=NULL; 12 | 13 | #define MAX_LOG_STR 256 14 | void log_only_write(const char* str, ...) 15 | { 16 | char tmpstr[MAX_LOG_STR]; 17 | va_list args; 18 | va_start(args,str); 19 | vsnprintf(tmpstr,sizeof(tmpstr),str,args); 20 | va_end(args); 21 | if(log!=NULL) 22 | fprintf(log,tmpstr); 23 | } 24 | 25 | NEDCLIB_API void log_write(const char* str, ...) 26 | { 27 | char tmpstr[MAX_LOG_STR]; 28 | va_list args; 29 | va_start(args,str); 30 | vsnprintf(tmpstr,sizeof(tmpstr),str,args); 31 | va_end(args); 32 | if(verbose==1) 33 | printf(tmpstr); 34 | if(log!=NULL) 35 | fprintf(log,tmpstr); 36 | } 37 | 38 | struct tree_node { 39 | int node; 40 | int data; 41 | int count; 42 | int value; 43 | tree_node *look_up[32]; 44 | tree_node *left; 45 | tree_node *right; 46 | }; 47 | 48 | struct tree_node *movetree; 49 | struct tree_node *sizetree; 50 | 51 | int get_bitsize(unsigned long data) 52 | { 53 | 54 | int i=data; 55 | 56 | int size=0; 57 | while(i > 0) 58 | { 59 | size++; 60 | i >>= 1; 61 | } 62 | return size; 63 | 64 | } 65 | 66 | int bitsleft_w = 32; 67 | int bitsleft_r = 0; 68 | unsigned long bits_w=0; 69 | unsigned long bits_r=0; 70 | 71 | NEDCLIB_API unsigned long bits_written=0; 72 | 73 | 74 | int bits_buf=0; 75 | 76 | inline unsigned long read_bits(int count, unsigned char *buf) 77 | { 78 | int i; 79 | unsigned long tmp=0; 80 | 81 | for(i=0;i> (bitsleft_r)) & 1) << (count-1-i)); 93 | } 94 | return tmp; 95 | 96 | } 97 | 98 | inline void write_bits(unsigned long data, int count, FILE *f) 99 | { 100 | int i; 101 | 102 | bits_written+=count; 103 | if((f==NULL)&&(bitstore==NULL)) 104 | { 105 | return; 106 | } 107 | for(i=0;i> (count-1-i)) & 1) << bitsleft_w); 111 | if(bitsleft_w==0) 112 | { 113 | if(f!=NULL) 114 | { 115 | fputc(((bits_w & 0xFF000000) >> 24),f); 116 | fputc(((bits_w & 0x00FF0000) >> 16),f); 117 | fputc(((bits_w & 0x0000FF00) >> 8),f); 118 | fputc(((bits_w & 0x000000FF) >> 0),f); 119 | } 120 | 121 | if(bitstore!=NULL) 122 | { 123 | *bitstore++ = (unsigned char)((bits_w & 0xFF000000) >> 24); 124 | *bitstore++ = (unsigned char)((bits_w & 0x00FF0000) >> 16); 125 | *bitstore++ = (unsigned char)((bits_w & 0x0000FF00) >> 8); 126 | *bitstore++ = (unsigned char)((bits_w & 0x000000FF) >> 0); 127 | } 128 | 129 | bitsleft_w = 32; 130 | bits_w = 0; 131 | } 132 | } 133 | } 134 | 135 | inline void flush_bits(FILE *f) 136 | { 137 | int i; 138 | 139 | i=32-bitsleft_w; 140 | bits_written+=i; 141 | if(f!=NULL) 142 | { 143 | if(i>0) 144 | fputc(((bits_w & 0xFF000000) >> 24),f); 145 | if(i>8) 146 | fputc(((bits_w & 0x00FF0000) >> 16),f); 147 | if(i>16) 148 | fputc(((bits_w & 0x0000FF00) >> 8),f); 149 | if(i>24) 150 | fputc(((bits_w & 0x000000FF) >> 0),f); 151 | } 152 | if(bitstore != NULL) 153 | { 154 | if(i>0) 155 | *bitstore++ = (unsigned char)((bits_w & 0xFF000000) >> 24); 156 | if(i>8) 157 | *bitstore++ = (unsigned char)((bits_w & 0x00FF0000) >> 16); 158 | if(i>16) 159 | *bitstore++ = (unsigned char)((bits_w & 0x0000FF00) >> 8); 160 | if(i>24) 161 | *bitstore++ = (unsigned char)((bits_w & 0x000000FF) >> 0); 162 | } 163 | bitsleft_w = 32; 164 | bits_w = 0; 165 | } 166 | 167 | 168 | void sort_tree(tree_node *tree[], int count) 169 | { 170 | int i,j; 171 | tree_node *swap1, *swap2; 172 | 173 | for(i=0;i> i) & 1) << ((numbits - 1) - i)); 244 | tree[0].value |= (numbits << 24); 245 | 246 | return tree; 247 | } 248 | else 249 | return NULL; 250 | } 251 | } 252 | else 253 | { 254 | return tree[0].look_up[bitcount]; 255 | } 256 | } 257 | 258 | void print_huffman_tree(tree_node *tree, int root=1) 259 | { 260 | if(tree==NULL) 261 | { 262 | log_write("0\n"); 263 | return; 264 | } 265 | if(tree[0].node == 1) 266 | { 267 | log_write("("); 268 | print_huffman_tree(tree[0].left,0); 269 | log_write(","); 270 | print_huffman_tree(tree[0].right,0); 271 | log_write(")"); 272 | 273 | if(root==1) 274 | log_write("\n"); 275 | } 276 | else 277 | { 278 | log_write("%d",tree[0].data); 279 | } 280 | } 281 | 282 | void write_huffman_tree(tree_node *tree, FILE *f, int root=1) 283 | { 284 | if(tree[0].node == 1) 285 | { 286 | if(f!=NULL) 287 | log_write("("); 288 | 289 | write_huffman_tree(tree[0].left,f,0); 290 | 291 | if(f!=NULL) 292 | log_write(","); 293 | 294 | write_huffman_tree(tree[0].right,f,0); 295 | 296 | if(f!=NULL) 297 | log_write(")"); 298 | write_bits(1,1,f); 299 | 300 | if(root==1) 301 | { 302 | write_bits(1,1,f); 303 | if(f!=NULL) 304 | log_write("\n"); 305 | } 306 | } 307 | else 308 | { 309 | 310 | write_bits(0,1,f); 311 | write_bits(tree[0].data,8,f); 312 | if(root) 313 | write_bits(1,1,f); 314 | if(f!=NULL) 315 | log_write("%d",tree[0].data); 316 | if(root) 317 | if(f!=NULL) 318 | log_write("\n"); 319 | } 320 | 321 | } 322 | 323 | NEDCLIB_API int best_move=0; 324 | NEDCLIB_API int best_size=0; 325 | 326 | NEDCLIB_API int skip_huffman=0; 327 | int skip_size=0; 328 | 329 | tree_node* create_huffman_tree(unsigned short *buf, int count, FILE *f, int method=0, int type=0) 330 | { 331 | int i,j,k; 332 | int treenodes=0; 333 | struct tree_node *ptr; 334 | struct tree_node *temp1; 335 | struct tree_node *treeroot; 336 | struct tree_node *pointer[256]; 337 | 338 | int max_bitcount = 0; 339 | 340 | int bitcounts[32] = { 341 | 0, 0, 0, 0, 0, 0, 0, 0, 342 | 0, 0, 0, 0, 0, 0, 0, 0, 343 | 0, 0, 0, 0, 0, 0, 0, 0, 344 | 0, 0, 0, 0, 0, 0, 0, 0 345 | }; 346 | 347 | for(i=0;i 0) 418 | { 419 | if((i < max_bitcount)) 420 | { 421 | j = 0; 422 | 423 | if((((best_move==0)&&(type==0)) || ((best_size==0)&&(type==1)&&(!skip_size)))&&(!skip_huffman)) 424 | { 425 | if((bitcounts[i+1] * 2) >= bitcounts[i]) 426 | j=1; 427 | 428 | if(i<(max_bitcount-3)) 429 | { 430 | if((bitcounts[i] < 25)) 431 | j=1; 432 | } 433 | else 434 | { 435 | if(bitcounts[i] < 100) 436 | j=1; 437 | } 438 | } 439 | else 440 | { 441 | if(k&1) 442 | j=0; 443 | else 444 | j=1; 445 | } 446 | k>>=1; 447 | 448 | //j=0; 449 | if(j==1) 450 | { 451 | bitcounts[i+1] += bitcounts[i]; 452 | treeroot[0].look_up[i] = NULL; 453 | continue; 454 | } 455 | } 456 | if(f!=NULL) 457 | log_write("%.5d:%.3d\n",bitcounts[i],i); 458 | 459 | 460 | ptr = create_treenode(); 461 | ptr[0].count = bitcounts[i]; 462 | ptr[0].data = i; 463 | ptr[0].left = NULL; 464 | ptr[0].right = NULL; 465 | ptr[0].node = 0; 466 | pointer[treenodes++] = ptr; 467 | treeroot[0].look_up[i] = ptr; 468 | for(j=(i-1);j>=0;j--) 469 | { 470 | if(treeroot[0].look_up[j] == NULL) 471 | { 472 | treeroot[0].look_up[j] = ptr; 473 | continue; 474 | } 475 | break; 476 | } 477 | 478 | } 479 | else 480 | treeroot[0].look_up[i] = (tree_node*)(NULL + 1); 481 | } 482 | if(f!=NULL) 483 | log_write("\n"); 484 | sort_tree(pointer,treenodes); 485 | 486 | while(treenodes > 1) 487 | { 488 | if(treenodes == 2) 489 | ptr = treeroot; 490 | else 491 | ptr = create_treenode(); 492 | ptr[0].node = 1; 493 | ptr[0].data = 0; 494 | treenodes--; 495 | ptr[0].right = pointer[treenodes]; 496 | for(i=treenodes;i>=0;i--) 497 | { 498 | temp1 = pointer[i]; 499 | if(temp1[0].count < ptr[0].right[0].count) 500 | ptr[0].right = temp1; 501 | } 502 | for(i=treenodes;i>=0;i--) 503 | { 504 | if(ptr[0].right == pointer[i]) 505 | continue; 506 | ptr[0].left = pointer[i]; 507 | break; 508 | } 509 | for(i=treenodes;i>=0;i--) 510 | { 511 | temp1 = pointer[i]; 512 | if((temp1[0].count < ptr[0].left[0].count) && (temp1 != ptr[0].right)) 513 | ptr[0].left = temp1; 514 | } 515 | ptr[0].count = ptr[0].right[0].count + ptr[0].left[0].count; 516 | 517 | for(i=0;i<(treenodes);i++) 518 | { 519 | if((ptr[0].left == pointer[i]) || (pointer[i] == NULL)) 520 | { 521 | pointer[i] = pointer[i+1]; 522 | pointer[i+1] = NULL; 523 | } 524 | } 525 | for(i=0;i<(treenodes);i++) 526 | { 527 | if((ptr[0].right == pointer[i]) || (pointer[i] == NULL)) 528 | { 529 | pointer[i] = pointer[i+1]; 530 | pointer[i+1] = NULL; 531 | } 532 | } 533 | 534 | 535 | pointer[treenodes-1] = ptr; 536 | } 537 | 538 | for(i=0;i<32;i++) 539 | { 540 | if(treeroot[0].look_up[i] == (tree_node*)(NULL + 1)) 541 | treeroot[0].look_up[i] = NULL; 542 | else 543 | get_treenode(treeroot,i,0,0,1); 544 | } 545 | 546 | write_huffman_tree(pointer[0],f); 547 | 548 | return pointer[0]; 549 | 550 | } 551 | 552 | tree_node* read_huffman_tree(unsigned char *buf) 553 | { 554 | int tree_pointer=0; 555 | int tree; 556 | struct tree_node *ptr; 557 | struct tree_node *pointer[256]; 558 | 559 | int tree_nodes=0; 560 | int i; 561 | // memset(huffman_tree,0,sizeof(huffman_tree)); 562 | 563 | pointer[0] = NULL; 564 | 565 | do 566 | { 567 | i=read_bits(1,buf); 568 | if(i==0) 569 | { 570 | tree_nodes=1; 571 | tree = read_bits(8,buf); 572 | ptr = create_treenode(); 573 | ptr[0].node = i; 574 | ptr[0].data = tree; 575 | ptr[0].count = 0; 576 | ptr[0].left = NULL; 577 | ptr[0].right = NULL; 578 | 579 | //ptr[0].left = create_treenode(); 580 | pointer[tree_pointer++] = ptr; 581 | } 582 | else 583 | { 584 | tree_pointer--; 585 | if(tree_pointer >= 1) 586 | { 587 | 588 | ptr = create_treenode(); 589 | ptr[0].data = 0; 590 | ptr[0].node = 1; 591 | ptr[0].left = pointer[tree_pointer - 1]; 592 | ptr[0].right = pointer[tree_pointer]; 593 | pointer[tree_pointer-1] = ptr; 594 | 595 | // huffman_tree[tree_pointer-1].left = tree_pointer - 1; 596 | // huffman_tree[tree_pointer-1].right = tree_pointer; 597 | } 598 | //tree_pointer--; 599 | } 600 | 601 | 602 | 603 | } while (tree_pointer > 0); 604 | 605 | if(tree_nodes > 0) 606 | { 607 | for(i=0;i<32;i++) 608 | ptr[0].look_up[i] = NULL; 609 | return ptr; 610 | } 611 | else 612 | { 613 | ptr = create_treenode(); 614 | ptr[0].data = 0; 615 | ptr[0].node = 0; 616 | ptr[0].left = NULL; 617 | ptr[0].right = NULL; 618 | ptr[0].value = 0; 619 | ptr[0].count = 0; 620 | for(i=0;i<32;i++) 621 | ptr[0].look_up[i] = NULL; 622 | return ptr; 623 | } 624 | 625 | 626 | 627 | } 628 | 629 | #define NUM_BITS get_bitsize(lzsize - 1) 630 | 631 | #define MAX_TABLE_SIZE 0x10000 632 | #define MAX_LITERALS 0x10000 633 | 634 | NEDCLIB_API int skip_lz77 = 0; 635 | 636 | NEDCLIB_API int NVPK_compress (unsigned char *buf, int size, int compression_level, int lzwindow, int lzsize, int method, FILE *f, unsigned char *bitdata) 637 | { 638 | static unsigned short literals[MAX_LITERALS], move_t[MAX_TABLE_SIZE], size_t[MAX_TABLE_SIZE]; 639 | int literals_offset=0,move_offset=0,size_offset=0; 640 | int buf_offset, buf_back_offset; 641 | int i, j, k, l, m, n; 642 | 643 | int lookahead; 644 | 645 | tree_node *tmp; 646 | 647 | int window_bitsize; 648 | 649 | window_bitsize = get_bitsize(lzwindow-1); 650 | 651 | if((f==NULL)&&(bitdata==NULL)&&(compression_level<3)) 652 | { 653 | return -1; 654 | } 655 | 656 | if((lzwindow<16)||(lzwindow>32768)) 657 | return -3; 658 | if((lzsize<16)||(lzsize>32768)) 659 | return -4; 660 | 661 | if(size>0x40000) //GBA Ram is 256KB. Can't exceed this. 662 | return -5; 663 | 664 | if(!skip_lz77) 665 | { 666 | 667 | if(compression_level != 0) 668 | { 669 | 670 | if(f!=NULL) 671 | log_write("LZ compressing data\n"); 672 | 673 | for(buf_offset=0;buf_offset MAX_TABLE_SIZE) || (size_offset > MAX_TABLE_SIZE)) 677 | { 678 | return -2; //Compressor failure, buffer overrun error 679 | } 680 | 681 | l=m=n=0; 682 | 683 | //for(buf_back_offset=0;(buf_back_offset=0;buf_back_offset--) 685 | { 686 | i=buf_offset; 687 | j=buf_back_offset; 688 | k=0; 689 | while((buf[i-(j+1)]==buf[i])&&(i=2) 695 | { 696 | if(k>=l) 697 | { 698 | l=k; 699 | m=j; 700 | n=1; 701 | //if(k==(lzsize-1)) 702 | // break; 703 | } 704 | } 705 | } 706 | 707 | // Look ahead one more byte, for a run, just in case there is a better run to use. 708 | while((n==1)&&(l<(lzsize-1))) 709 | { 710 | n=0; 711 | if(l>=2) 712 | { 713 | lookahead = l; 714 | buf_offset++; 715 | for(buf_back_offset=0;(buf_back_offset=2) 726 | { 727 | if(k>l) 728 | { 729 | l=k; 730 | m=j; 731 | } 732 | } 733 | } 734 | buf_offset--; 735 | if(l > lookahead) 736 | { 737 | n=1; 738 | literals[literals_offset++] = buf[buf_offset++]; 739 | } 740 | else 741 | l = lookahead; 742 | } 743 | } 744 | if(l>=2) 745 | { 746 | literals[literals_offset++] = 0x100; 747 | move_t[move_offset++] = m + 1; 748 | size_t[size_offset++] = l; 749 | buf_offset+=(l-1); 750 | } 751 | else 752 | literals[literals_offset++] = buf[buf_offset]; 753 | } 754 | literals[literals_offset++] = 0x1FF; 755 | } 756 | else 757 | { 758 | for(buf_offset = 0;buf_offset= 2) 866 | { 867 | if(f!=NULL) 868 | log_write("Writing huffman trees\n"); 869 | if(f!=NULL) 870 | log_write("----- Move Tree Structure/Frequency Counts-----\n"); 871 | movetree = create_huffman_tree(move_t,move_offset,f,method,0); 872 | if(f!=NULL) 873 | log_write("----- Size Tree Structure/Frequency Counts-----\n"); 874 | sizetree = create_huffman_tree(size_t,size_offset,f,0,1); 875 | if(f!=NULL) 876 | log_write("Writing vpk data\n"); 877 | 878 | move_offset = 0; 879 | size_offset = 0; 880 | 881 | while(literals[literals_offset] != 0x1FF) 882 | { 883 | if(literals[literals_offset] == 0x100) 884 | { 885 | write_bits(1,1,f); 886 | 887 | if(method==1) 888 | { 889 | j=move_t[move_offset]; 890 | if(j%4==0) 891 | { 892 | j+=8; 893 | j/=4; 894 | 895 | /* if(get_bitsize(j)<3) 896 | { 897 | tmp = get_treenode(movetree,3); 898 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 899 | write_bits(j,tmp[0].data,f); 900 | } 901 | else 902 | {*/ 903 | tmp = get_treenode(movetree,get_bitsize(j)); 904 | if(tmp!=NULL) 905 | { 906 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 907 | write_bits(j,tmp[0].data,f); 908 | } 909 | else 910 | { 911 | write_bits(j,movetree[0].data,f); 912 | } 913 | 914 | 915 | // } 916 | 917 | } 918 | else 919 | { 920 | j%=4; 921 | j--; 922 | /* if(get_bitsize(j)<3) 923 | { 924 | tmp = get_treenode(movetree,3); 925 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 926 | write_bits(j,tmp[0].data,f); 927 | } 928 | else 929 | {*/ 930 | tmp = get_treenode(movetree,get_bitsize(j)); 931 | if(tmp==NULL) 932 | { 933 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 934 | write_bits(j,tmp[0].data,f); 935 | } 936 | else 937 | write_bits(j,movetree[0].data,f); 938 | 939 | // } 940 | 941 | j=move_t[move_offset]; 942 | j+=8; 943 | j/=4; 944 | 945 | /* if(get_bitsize(j)<3) 946 | { 947 | tmp = get_treenode(movetree,3); 948 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 949 | write_bits(j,tmp[0].data,f); 950 | } 951 | else 952 | {*/ 953 | tmp = get_treenode(movetree,get_bitsize(j)); 954 | if(tmp==NULL) 955 | { 956 | return -3; //movetree failure 957 | } 958 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 959 | write_bits(j,tmp[0].data,f); 960 | // } 961 | } 962 | move_offset++; 963 | 964 | } 965 | else 966 | { 967 | j = get_bitsize(move_t[move_offset]); 968 | //if(j<3) 969 | // j = 3; 970 | tmp = get_treenode(movetree,j); 971 | if(tmp!=NULL) 972 | { 973 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 974 | write_bits(move_t[move_offset++],tmp[0].data,f); 975 | } 976 | else 977 | write_bits(move_t[move_offset++],movetree[0].data,f); 978 | 979 | } 980 | 981 | j = get_bitsize(size_t[size_offset]); 982 | //if(j<3) 983 | // j = 3; 984 | tmp = get_treenode(sizetree,j); 985 | if(tmp!=NULL) 986 | { 987 | write_bits(tmp[0].value & 0x00FFFFFF,(tmp[0].value>>24),f); 988 | write_bits(size_t[size_offset++],tmp[0].data,f); 989 | } 990 | else 991 | write_bits(size_t[size_offset++],sizetree[0].data,f); 992 | 993 | } 994 | else 995 | { 996 | write_bits(0,1,f); 997 | write_bits(literals[literals_offset],8,f); 998 | } 999 | literals_offset++; 1000 | } 1001 | 1002 | 1003 | flush_bits(f); 1004 | 1005 | free_huffman_tree(movetree); 1006 | free_huffman_tree(sizetree); 1007 | } 1008 | 1009 | 1010 | 1011 | bitstore=NULL; 1012 | 1013 | if(bitdata!=NULL) 1014 | return (bits_written/8)+1; 1015 | else 1016 | return 0; 1017 | } 1018 | 1019 | 1020 | 1021 | 1022 | unsigned char decompress_buffer[0x100000]; 1023 | 1024 | int read_tree_value(tree_node *tree, unsigned char *buf) 1025 | { 1026 | tree_node *ptr; 1027 | int tmp; 1028 | 1029 | ptr = tree; 1030 | if(ptr==NULL) 1031 | { 1032 | return 0; 1033 | } 1034 | else 1035 | { 1036 | while(ptr[0].node == 1) 1037 | { 1038 | tmp = read_bits(1,buf); 1039 | if(tmp == 0) 1040 | ptr = ptr[0].left; 1041 | else 1042 | ptr = ptr[0].right; 1043 | } 1044 | ptr[0].count++; 1045 | tree[0].look_up[ptr[0].data] = ptr; 1046 | return read_bits(ptr[0].data,buf); 1047 | } 1048 | } 1049 | 1050 | NEDCLIB_API int vpk_decompress (unsigned char *vpk, FILE *f) 1051 | { 1052 | int bitcountsmove[32] = { 1053 | 0, 0, 0, 0, 0, 0, 0, 0, 1054 | 0, 0, 0, 0, 0, 0, 0, 0, 1055 | 0, 0, 0, 0, 0, 0, 0, 0, 1056 | 0, 0, 0, 0, 0, 0, 0, 0, 1057 | }; 1058 | 1059 | int bitcountssize[32] = { 1060 | 0, 0, 0, 0, 0, 0, 0, 0, 1061 | 0, 0, 0, 0, 0, 0, 0, 0, 1062 | 0, 0, 0, 0, 0, 0, 0, 0, 1063 | 0, 0, 0, 0, 0, 0, 0, 0, 1064 | }; 1065 | 1066 | struct tree_node *ptr; 1067 | 1068 | int size,method; 1069 | 1070 | int i; 1071 | 1072 | int tmp; 1073 | 1074 | int move_tt,size_tt; 1075 | 1076 | i=0; 1077 | 1078 | if(read_bits(8,vpk)!='v') 1079 | i=1; 1080 | if(read_bits(8,vpk)!='p') 1081 | i=1; 1082 | if(read_bits(8,vpk)!='k') 1083 | i=1; 1084 | if(read_bits(8,vpk)!='0') 1085 | i=1; 1086 | 1087 | if(i!=0) 1088 | { 1089 | printf("Error: Invalid vpk data\n"); 1090 | return 1; 1091 | } 1092 | 1093 | size=read_bits(32,vpk); 1094 | method=read_bits(8,vpk); 1095 | 1096 | if(method>1) 1097 | { 1098 | printf("Error: Invalid vpk data\n"); 1099 | return 1; 1100 | } 1101 | 1102 | movetree = read_huffman_tree(vpk); 1103 | sizetree = read_huffman_tree(vpk); 1104 | 1105 | 1106 | if((movetree[0].node != 0) || (movetree[0].data != 0)) 1107 | { 1108 | log_write("***** Move Tree Structure *****\n"); 1109 | print_huffman_tree(movetree); 1110 | log_write("\n"); 1111 | } 1112 | if((sizetree[0].node != 0) || (sizetree[0].data != 0)) 1113 | { 1114 | log_write("***** Size Tree Structure *****\n"); 1115 | print_huffman_tree(sizetree); 1116 | log_write("\n"); 1117 | } 1118 | 1119 | log_only_write("***** Decompression Log ******\n"); 1120 | 1121 | for(i=0;i 0) && (i < size)) 1158 | { 1159 | decompress_buffer[i] = \ 1160 | decompress_buffer[i - move_tt]; 1161 | log_only_write("%.2X ",decompress_buffer[i - move_tt]); 1162 | i++; 1163 | size_tt--; 1164 | } 1165 | log_only_write("\n"); 1166 | 1167 | 1168 | 1169 | } 1170 | } 1171 | 1172 | for(i=0;i0) 1182 | log_write("%.5d:%.3d\n",bitcountsmove[i],i);*/ 1183 | for(i=0;i<32;i++) 1184 | { 1185 | if(movetree == NULL) 1186 | break; 1187 | ptr = movetree[0].look_up[i]; 1188 | if(ptr == NULL) 1189 | continue; 1190 | log_write("%.5d:%.3d\n",ptr[0].count,i); 1191 | } 1192 | log_write("\n"); 1193 | } 1194 | 1195 | if((sizetree[0].node != 0) || (sizetree[0].data != 0)) 1196 | { 1197 | log_write("***** Frequency Table (size) *****\n"); 1198 | /*for(i=0;i<32;i++) 1199 | if(bitcountssize[i]>0) 1200 | log_write("%.5d:%.3d\n",bitcountssize[i],i);*/ 1201 | for(i=0;i<32;i++) 1202 | { 1203 | if(sizetree == NULL) 1204 | break; 1205 | ptr = sizetree[0].look_up[i]; 1206 | if(ptr == NULL) 1207 | continue; 1208 | log_write("%.5d:%.3d\n",ptr[0].count,i); 1209 | } 1210 | log_write("\n"); 1211 | } 1212 | 1213 | 1214 | free_huffman_tree(movetree); 1215 | free_huffman_tree(sizetree); 1216 | 1217 | return 0; 1218 | } 1219 | --------------------------------------------------------------------------------