├── README.md ├── bin-to-raw.bat ├── bin-to-vpk.py ├── cards ├── bin │ └── bin-files-go-here.txt ├── dec │ └── decompiled-files-go-here.txt ├── raw │ └── raw-files-go-here.txt └── vpk │ └── vpk-files-go-here.txt ├── dec-to-vpk.bat ├── raw-to-bin.bat ├── vpk-to-bin.py └── vpk-to-dec.bat /README.md: -------------------------------------------------------------------------------- 1 | # e-Reader Decompiler and Compression Tools 2 | This code, originally started by [RollingStar](https://github.com/RollingStar/CardShark), is designed to work in combination with tools created by CaitSith2 and Tim Schuerewegen in order to decompile and re-compress Nintendo's e-Reader card data for the Game Boy Advance. 3 | 4 | 5 | ## Important Information 6 | These tools are designed **specifically for use with Animal Crossing e-Reader cards**. Other e-Reader cards exist, such as those for Mario Party and Pokémon, but as of right now this tool is formatted for Animal Crossing only. As it is possible to update this tool in the future to incorporate other games, I've left the project name as-is to remain general. 7 | 8 | Further, these tools are merely assists that automate processes and make the effort of modifying e-Reader data less troublesome. That is to say, while these tools do decode fully automatically, these tools **do not** accurately replicate HAL Laboratory's `vpk0` compression methods when encoding. This is because HAL's specific compression settings are not known. Nevertheless, it is still possible to get e-Reader card data to read properly through clever manual editing of specific e-Reader header data, which is detailed in the tutorial. In theory, this process could be automated for specific card data, but there are too many e-Reader cards with differing flags and data to make it worth writing automation to detect each type. Regardless, if only interested in modifying Animal Crossing e-Reader card data, these tools are still essential for the process to work. 9 | 10 | 11 | ## Requirements 12 | These tools are part of a larger project detailed in this tutorial, where more requirements are necessary for editing the files. However, for these tools specifically for decoding/encoding only, you will need: 13 | 14 | - Windows 10 or higher (no Mac or Linux, sorry) 15 | - Python 3 16 | - [CaitSith2's Dot Dode Dev Package](https://www.caitsith2.com/ereader/devtools.htm) 17 | - Access to e-Reader card data in `.raw` format 18 | 19 | 20 | ## Workflow 21 | **IMPORTANT:** *The code hosted here is part of a larger project designed to allow users to modify decompressed e-Reader card data. Without following this larger tutorial, these tools merely decode and encode e-Reader data through specific file-structures without explaining how to do much with them.* 22 | 23 | 1. Clone the Git repository to a new folder of your choosing. 24 | 2. Enter the folder `/eReader-Compression/`. This will be your root folder. 25 | 3. Download and extract [CaitSith2's Dot Dode Dev Package](https://www.caitsith2.com/ereader/devtools.htm) to the root folder. 26 | 4. Your root folder should now contain several new files, but you can delete all the new files **except** `nedcenc.exe`, `nedclib.dll`, and `nevpk.exe`. Alternatively, you can download these separately from CaitSith2's site and put them in the root folder. 27 | 5. Place your `.raw` e-Reader card data in the `/cards/raw/` folder. 28 | 6. Run `raw-to-bin.bat` to automatically decode the `.raw` files in said folder into `.bin`. These new `.bin` files are placed in `/cards/bin/`. 29 | 7. Run `bin_to_vpk.py` to automatically decode the `.bin` files into separate `.header` and `.vpk` chunks. These files are placed in `/cards/vpk/` 30 | 8. Run `vpk-to-dec.bat` to automatically decode the `.vpk` chunks into readable, decompressed you can modify with a hex editor. 31 | 9. When finished modifying, run `dec-to-vpk.bat` and `vpk-to-bin.py` to compress through the files back to `.bin`. This will overwrite the original files in the folder. 32 | 10. Run `bin-to-raw.bat` to convert back to `.raw` for use in e-Reader scanning or dot code printing. 33 | 34 | 35 | ## Known Bugs 36 | - The code will occasionally fail to decode when dealing with multiple `.raw` files. I recommend doing one at a time for now. 37 | 38 | 39 | ## Acknowledgements 40 | Huge thanks to [RollingStar](https://github.com/RollingStar/CardShark) for starting this project and giving me the motivation to finish it. A large portion of this codebase belongs to them. 41 | 42 | -------------------------------------------------------------------------------- /bin-to-raw.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cd %~dp0 3 | for %%A IN (%~dp0\cards\bin\*.bin) DO nedcenc.exe -e -i "%%A" -o "%~dp0\cards\raw\%%~nA-custom.raw" -------------------------------------------------------------------------------- /bin-to-vpk.py: -------------------------------------------------------------------------------- 1 | '''Split Game Boy Advance e-Reader binaries into their component VPK files.''' 2 | 3 | import os 4 | from bitstring import BitArray 5 | CARD_TYPE = 'Animal Crossing' 6 | # CARD_TYPE could be expanded to other cards later; 7 | # only Animal Crossing is currently supported. 8 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + '/cards' 9 | IN_DIR = BASE_DIR + '/bin/' 10 | OUT_DIR = BASE_DIR + '/vpk/' 11 | for file in os.listdir(IN_DIR): 12 | if file.endswith(".bin"): 13 | full_path = IN_DIR + file 14 | a = BitArray(filename=full_path) 15 | 16 | # vpk0 = 0x76706B30. vpk0 is the header for each chunk of data we want 17 | for chunk_num, chunk in enumerate( 18 | a.split('0x76706B30', bytealigned=True)): 19 | card_extension = '.vpk' 20 | note = '_' 21 | # skip chunk 0 (when batch processing *.vpk files). 22 | # it's a header rather than a compressed VPK chunk 23 | if chunk_num == 0: 24 | card_extension = '.header' 25 | if CARD_TYPE == 'Animal Crossing': 26 | if chunk_num == 1: 27 | # hunch, bigger because of graphics data 28 | note = note + "GBA" 29 | if chunk_num == 2: 30 | note = note + "GC" 31 | if note == '_': 32 | note = '' 33 | out_name = OUT_DIR + file[:-4] + '_' + \ 34 | str(chunk_num) + note + card_extension 35 | open(out_name, 'wb').write(chunk.tobytes()) 36 | -------------------------------------------------------------------------------- /cards/bin/bin-files-go-here.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HunterRDev/eReader-Compression/03b36ac772c974b65a0efeafa427355b58ad840a/cards/bin/bin-files-go-here.txt -------------------------------------------------------------------------------- /cards/dec/decompiled-files-go-here.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HunterRDev/eReader-Compression/03b36ac772c974b65a0efeafa427355b58ad840a/cards/dec/decompiled-files-go-here.txt -------------------------------------------------------------------------------- /cards/raw/raw-files-go-here.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HunterRDev/eReader-Compression/03b36ac772c974b65a0efeafa427355b58ad840a/cards/raw/raw-files-go-here.txt -------------------------------------------------------------------------------- /cards/vpk/vpk-files-go-here.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HunterRDev/eReader-Compression/03b36ac772c974b65a0efeafa427355b58ad840a/cards/vpk/vpk-files-go-here.txt -------------------------------------------------------------------------------- /dec-to-vpk.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cd %~dp0 3 | for %%A IN (%~dp0\cards\dec\*) DO nevpk.exe -i "%%A" -o "%~dp0\cards\vpk\%%~nA.vpk" -v -c -------------------------------------------------------------------------------- /raw-to-bin.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cd %~dp0 3 | for %%A IN (%~dp0\cards\raw\*.raw) DO nedcenc.exe -d -i "%%A" -o "%~dp0\cards\bin\%%~nA.bin" -------------------------------------------------------------------------------- /vpk-to-bin.py: -------------------------------------------------------------------------------- 1 | '''Combines VPK files into a single .bin file for use with the e-Reader.''' 2 | 3 | import os 4 | import glob 5 | import warnings 6 | import bitstring 7 | CARD_ID_DELIMITER = '_' 8 | CHUNKS_PER_CARD = 3 9 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) + '/cards' 10 | IN_DIR = BASE_DIR + '/vpk/' 11 | OUT_DIR = BASE_DIR + '/bin/' 12 | 13 | directory = os.listdir(IN_DIR) 14 | groups = set() 15 | for file in directory: 16 | card_id = file.partition(CARD_ID_DELIMITER)[0] 17 | groups.add(card_id) 18 | 19 | for group in groups.copy(): 20 | card_glob = glob.glob(IN_DIR + group + "*") 21 | 22 | if len(card_glob) < CHUNKS_PER_CARD: 23 | length_warn = "less than" + \ 24 | str(CHUNKS_PER_CARD) + \ 25 | " files/folders with similar names found; check the vpk folder." 26 | if len(card_glob) > CHUNKS_PER_CARD: 27 | length_warn = "more than" + \ 28 | str(CHUNKS_PER_CARD) + \ 29 | " files/folders with similar names found; check the vpk folder." 30 | if len(card_glob) != CHUNKS_PER_CARD: 31 | warnings.warn(length_warn) 32 | groups.discard(group) 33 | 34 | # Combining VPK to .bin 35 | for group in groups.copy(): 36 | print(group) 37 | header_num = 0 38 | head_path = glob.glob(IN_DIR + group + "_" + str(header_num) + "*")[0] 39 | print(head_path) 40 | card = bitstring.BitArray(filename=head_path) 41 | print("head len: ", hex(card.len)) 42 | for num in range(1, CHUNKS_PER_CARD): 43 | chunk_path = glob.glob(IN_DIR + group + "_" + str(num) + "*")[0] 44 | print(glob.glob(IN_DIR + group + "_" + str(num) + "*")) 45 | print(chunk_path) 46 | chunk = bitstring.Bits(filename=chunk_path) 47 | print("chunk lenth: ", chunk.length) 48 | card.append(chunk) 49 | print("fl cl: ", card.length, " ", hex(card.length), 50 | " ", int(str(card.length), 16) / 2) 51 | 52 | # Attempting to automatically add some padding, but likely need to manually add more 53 | proper_length = 0x81c 54 | print("prop len: ", proper_length, hex(proper_length)) 55 | pad_length = int(proper_length - (card.length / 8)) 56 | print("card l: ", card.length, " ", hex(card.length)) 57 | print("pad l: ", pad_length, "\n") 58 | print(b"\00" * pad_length) 59 | card.append(b"\00" * pad_length) 60 | out_name = OUT_DIR + group + ".bin" 61 | open(out_name, 'wb').write(card.tobytes()) 62 | -------------------------------------------------------------------------------- /vpk-to-dec.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cd %~dp0 3 | for %%A IN (%~dp0\cards\vpk\*.vpk) DO nevpk.exe -i "%%A" -o "%~dp0\cards\dec\%%~nA" -v -d --------------------------------------------------------------------------------