1.3 Refactor

* Added DSOnei kernel to included nds files for Stage2 menu.
* Added N-Card rom dump to included nds files for Stage2 menu.
* Added CycloDS, and DSTWo bootloader dumps to included nds files for
Stage2 menu.
* DSTwo now boots correctly from cart launcher.
* R4 SDHC Gold and other similar DEMON time bomb DSTTi clones now boot
correctly from cart launcher.
* Added back option for enabling/disabling TWL ram.
* Added fixes to allow DS only carts to run with TWL ram enabled.
* Initial modcrypt code added for TWL carts. Currently works in
emulation however TWL carts will fail to boot on hardware (when twl
mode, ram, etc is enabled).
* If TWL mode and ram is enabled, cart loader will now load the DSi
extended binaries into ram. Currently however they will only boot in
emulation. Have not resolved why it's not working on hardware yet.
* Stage2 menu now allowed to load dsi extended binaries of SRLs if TWL
mode and TWL ram is enabled. Booting rom dumps as a method of booting
into TWL carts is confirmed working. At least for System Flaw it does.
:D
* Despite the improvents Acekard 2i still appears to require using the
stage2 menu to boot into.
* Fixes that allowed Demon timebomb carts to boot from cart
launcher/autoboot may allow other non working carts to work. Further
testing needed.
This commit is contained in:
ApacheThunder 2024-11-27 21:50:32 -06:00
parent 3c362f527f
commit de31f9cb2b
74 changed files with 8982 additions and 778 deletions

2
.gitignore vendored
View File

@ -2,6 +2,8 @@
*.app
*.exe
*.cia
*.rar
*.zip
/*.nds
*.app
*.tmd

View File

@ -14,8 +14,8 @@ endif
#---------------------------------------------------------------------------------
TARGET := load
BUILD := build
SOURCES := source source/patches
INCLUDES := build ../include
SOURCES := source source/patches source/modcrypt
INCLUDES := build ../include source/modcrypt
DATA := ../data
SPECS := specs
@ -24,10 +24,9 @@ SPECS := specs
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi
CFLAGS := -g -Wall -O2 \
CFLAGS := -g -Wall -Wextra -Werror -O2 \
-fomit-frame-pointer \
-ffast-math \
-Wall -Wextra -Werror \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM7

View File

@ -3,10 +3,8 @@ OUTPUT_ARCH(arm)
ENTRY(_start)
MEMORY {
vram : ORIGIN = 0x06020000, LENGTH = 128K
/* arm9ram : ORIGIN = 0x026FD800, LENGTH = 4K Used for the ARM9's functions */
arm9ram : ORIGIN = 0x027FC800, LENGTH = 4K /* Used for the ARM9's functions */
arm9ram : ORIGIN = 0x02FFD000, LENGTH = 4K /* Used for the ARM9's functions */
}
__vram_start = ORIGIN(vram);

View File

@ -41,5 +41,28 @@ BEGIN_ASM_FUNC arm9_clearCache
mcr p15, 0, r3, c7, c6, 0 @ Flush DCache
mcr p15, 0, r3, c7, c10, 4 @ empty write buffer
mcr p15, 0, r3, c3, c0, 0 @ disable write buffer (def = 0)
mcr p15, 0, r3, c2, c0, 0 @ disable DTCM and protection unit
mcr p15, 0, r3, c6, c0, 0 @ disable protection unit 0 (def = 0)
mcr p15, 0, r3, c6, c1, 0 @ disable protection unit 1 (def = 0)
mcr p15, 0, r3, c6, c2, 0 @ disable protection unit 2 (def = 0)
mcr p15, 0, r3, c6, c3, 0 @ disable protection unit 3 (def = 0)
mcr p15, 0, r3, c6, c4, 0 @ disable protection unit 4 (def = ?)
mcr p15, 0, r3, c6, c5, 0 @ disable protection unit 5 (def = ?)
mcr p15, 0, r3, c6, c6, 0 @ disable protection unit 6 (def = ?)
mcr p15, 0, r3, c6, c7, 0 @ disable protection unit 7 (def = ?)
mcr p15, 0, r3, c5, c0, 3 @ IAccess
mcr p15, 0, r3, c5, c0, 2 @ DAccess
mov r3, #0x00800000
add r3, r3, #0x00A
mcr p15, 0, r3, c9, c1, 0 @ DTCM base (def = 0x0080000A) ???
mov r3, #0x0000000C
mcr p15, 0, r3, c9, c1, 1 @ ITCM base (def = 0x0000000C) ???
bx lr

View File

@ -25,46 +25,38 @@
#define resetCpu() \
__asm volatile("swi 0x000000")
typedef struct sLauncherSettings {
u8 language;
u8 scfgUnlock;
u8 twlMode;
u8 twlCLK;
u8 twlVRAM;
u8 debugMode;
u8 fastBoot;
u8 unused2;
} tLauncherSettings;
extern volatile tLauncherSettings* launchData;
extern volatile int language;
extern volatile bool scfgUnlock;
extern volatile bool twlMode;
extern volatile bool twlCLK;
extern volatile bool debugMode;
#include "../../arm9/common/launcherData.h"
#define CartHeaderCopy 0x02000000
#define CartChipIDCopy 0x02000180
ALIGN(4) extern volatile u16 arm9_errorCode;
ALIGN(4) extern volatile tLauncherSettings* launchData;
ALIGN(4) extern volatile u16 language;
ALIGN(4) extern volatile u16 scfgUnlock;
ALIGN(4) extern volatile u16 twlMode;
// ALIGN(4) extern volatile u16 twlVRAM;
ALIGN(4) extern volatile u16 twlRAM;
ALIGN(4) extern volatile u16 twlCLK;
ALIGN(4) extern volatile u16 isTWLSRL;
ALIGN(4) extern volatile u16 debugMode;
enum ERROR_CODES {
ERR_NONE = 0x00,
ERR_STS_CLR_MEM = 0x01,
ERR_STS_LOAD_BIN = 0x02,
ERR_STS_HOOK_BIN = 0x03,
ERR_STS_START = 0x04,
ALIGN(4) enum ERROR_CODES {
ERR_NONE = (u16)0x00,
ERR_STS_STARTBIN = (u16)0x01,
ERR_STS_CLR_MEM = (u16)0x02,
ERR_STS_LOAD_BIN = (u16)0x03,
ERR_STS_START = (u16)0x04,
// initCard error codes:
ERR_LOAD_NORM = 0x11,
ERR_LOAD_OTHR = 0x12,
ERR_SEC_NORM = 0x13,
ERR_SEC_OTHR = 0x14,
ERR_LOGO_CRC = 0x15,
ERR_HEAD_CRC = 0x16,
ERR_STS_STARTBIN = 0x21,
ERR_LOAD_NORM = (u16)0x05,
ERR_LOAD_OTHR = (u16)0x06,
ERR_SEC_NORM = (u16)0x07,
ERR_SEC_OTHR = (u16)0x08,
ERR_HEAD_CRC = (u16)0x09,
ERR_UNKNOWN = (u16)0x10,
ERR_UNKNOWN2 = (u16)0x11
};
// Values fixed so they can be shared with ASM code
enum ARM9_STATE {
ALIGN(4) enum ARM9_STATE {
ARM9_BOOT = 0,
ARM9_START = 1,
ARM9_RESET = 2,
@ -72,7 +64,7 @@ enum ARM9_STATE {
ARM9_MEMCLR = 4
};
enum ARM7_STATE {
ALIGN(4) enum ARM7_STATE {
ARM7_BOOT = 0,
ARM7_START = 1,
ARM7_RESET = 2,
@ -84,27 +76,152 @@ enum ARM7_STATE {
ARM7_ERR = 8
};
extern volatile u32 arm9_errorCode;
static inline void dmaFill(const void* src, void* dest, uint32 size) {
ALIGN(4) static inline void dmaFill(const void* src, void* dest, uint32 size) {
DMA_SRC(3) = (uint32)src;
DMA_DEST(3) = (uint32)dest;
DMA_CR(3) = DMA_COPY_WORDS | DMA_SRC_FIX | (size>>2);
while(DMA_CR(3) & DMA_BUSY);
}
static inline void copyLoop (u32* dest, const u32* src, size_t size) {
ALIGN(4) static inline void copyLoop (u32* dest, const u32* src, size_t size) {
do { *dest++ = *src++; } while (size -= 4);
}
static inline void ipcSendState(uint8_t state) {
ALIGN(4) static inline void ipcSendState(uint8_t state) {
REG_IPC_SYNC = (state & 0x0f) << 8;
}
static inline uint8_t ipcRecvState(void) {
ALIGN(4) static inline uint8_t ipcRecvState(void) {
return (uint8_t)(REG_IPC_SYNC & 0x0f);
}
typedef struct sTWLHeader {
char gameTitle[12]; //!< 12 characters for the game title.
char gameCode[4]; //!< 4 characters for the game code.
char makercode[2]; //!< identifies the (commercial) developer.
u8 unitCode; //!< identifies the required hardware.
u8 deviceType; //!< type of device in the game card
u8 deviceSize; //!< capacity of the device (1 << n Mbit)
u8 reserved1[7];
u8 twlHeaderSettings;
u8 jumpSettings;
u8 romversion; //!< version of the ROM.
u8 flags; //!< bit 2: auto-boot flag.
u32 arm9romOffset; //!< offset of the arm9 binary in the nds file.
void *arm9executeAddress; //!< adress that should be executed after the binary has been copied.
void *arm9destination; //!< destination address to where the arm9 binary should be copied.
u32 arm9binarySize; //!< size of the arm9 binary.
u32 arm7romOffset; //!< offset of the arm7 binary in the nds file.
void *arm7executeAddress; //!< adress that should be executed after the binary has been copied.
void *arm7destination; //!< destination address to where the arm7 binary should be copied.
u32 arm7binarySize; //!< size of the arm7 binary.
u32 filenameOffset; //!< File Name Table (FNT) offset.
u32 filenameSize; //!< File Name Table (FNT) size.
u32 fatOffset; //!< File Allocation Table (FAT) offset.
u32 fatSize; //!< File Allocation Table (FAT) size.
u32 arm9overlaySource; //!< File arm9 overlay offset.
u32 arm9overlaySize; //!< File arm9 overlay size.
u32 arm7overlaySource; //!< File arm7 overlay offset.
u32 arm7overlaySize; //!< File arm7 overlay size.
u32 cardControl13; //!< Port 40001A4h setting for normal commands (used in modes 1 and 3)
u32 cardControlBF; //!< Port 40001A4h setting for KEY1 commands (used in mode 2)
u32 bannerOffset; //!< offset to the banner with icon and titles etc.
u16 secureCRC16; //!< Secure Area Checksum, CRC-16.
u16 readTimeout; //!< Secure Area Loading Timeout.
u32 unknownRAM1; //!< ARM9 Auto Load List RAM Address (?)
u32 unknownRAM2; //!< ARM7 Auto Load List RAM Address (?)
u32 bfPrime1; //!< Secure Area Disable part 1.
u32 bfPrime2; //!< Secure Area Disable part 2.
u32 romSize; //!< total size of the ROM.
u32 headerSize; //!< ROM header size.
u32 zeros88[14];
u8 gbaLogo[156]; //!< Nintendo logo needed for booting the game.
u16 logoCRC16; //!< Nintendo Logo Checksum, CRC-16.
u16 headerCRC16; //!< header checksum, CRC-16.
u32 debugRomSource; //!< debug ROM offset.
u32 debugRomSize; //!< debug size.
u32 debugRomDestination; //!< debug RAM destination.
u32 offset_0x16C; //reserved?
u8 zero[0x10];
u32 arm9MBK1;
u32 arm9MBK2;
u32 arm9MBK3;
u32 arm9MBK4;
u32 arm9MBK5;
u32 arm9MBK6;
u32 arm9MBK7;
u32 arm9MBK8;
u32 arm7MBK6;
u32 arm7MBK7;
u32 arm7MBK8;
u32 arm9MBKMaster;
u32 region;
u32 accessControl;
u32 arm7SCFGSettings;
u16 dsi_unk1;
u8 dsi_unk2;
u8 dsi_flags;
u32 arm9iromOffset; //!< offset of the arm9 binary in the nds file.
u32 arm9iexecuteAddress;
u32 arm9idestination; //!< destination address to where the arm9 binary should be copied.
u32 arm9ibinarySize; //!< size of the arm9 binary.
u32 arm7iromOffset; //!< offset of the arm7 binary in the nds file.
u32 deviceListDestination;
u32 arm7idestination; //!< destination address to where the arm7 binary should be copied.
u32 arm7ibinarySize; //!< size of the arm7 binary.
u8 zero2[0x20];
// 0x200
// TODO: More DSi-specific fields.
u32 dsi1[0x10/4];
u32 twlRomSize;
u32 dsi_unk3;
u32 dsi_unk4;
u32 dsi_unk5;
u32 modCrypt1Offset;
u32 modcrypt1Size;
u32 modcrypt2Offset;
u32 modcrypt2Size;
u32 dsi_tid;
u32 dsi_tid2;
u32 pubSavSize;
u32 prvSavSize;
u8 reserved3[176];
u8 age_ratings[0x10];
unsigned char hmac_arm9[16];
unsigned char hmac_arm7[16];
u8 hmac_digest_master[0x14];
u8 hmac_icon_title[0x14];
u8 hmac_arm9i[0x14];
u8 hmac_arm7i[0x14];
u8 reserved4[0x28];
u8 hmac_arm9_no_secure[0x14];
u8 reserved5[0xA4C];
u8 debug_args[0x180];
u8 rsa_signature[0x80];
} tTWLHeader;
#endif // _COMMON_H

View File

@ -18,7 +18,9 @@
#include <string.h>
#include "encryption.h"
#include "read_bios.h"
#include "key1.h"
#include "key2.h"
#include "tonccpy.h"
#define KEYSIZE 0x1048
@ -84,7 +86,7 @@ void apply_keycode (u32 modulo) {
crypt_64bit_up (&keycode[1]);
crypt_64bit_up (&keycode[0]);
memset (scratch, 0, 8);
toncset (scratch, 0, 8);
for (i = 0; i < 0x12; i+=1) {
keybuf[i] = keybuf[i] ^ bswap_32bit (keycode[i % modulo]);
@ -96,8 +98,8 @@ void apply_keycode (u32 modulo) {
}
}
void init_keycode (u32 idcode, u32 level, u32 modulo) {
readBios ((u8*)keybuf, 0x30, KEYSIZE);
void init_keycode (u32 idcode, u32 level, u32 modulo, int iCardDevice) {
tonccpy ((u8*)keybuf, (iCardDevice ? gEncrDataTwl : gEncrData), KEYSIZE);
keycode[0] = idcode;
keycode[1] = idcode/2;
keycode[2] = idcode*2;

View File

@ -20,7 +20,7 @@
#define ENCRYPTION_H
#include <nds/ndstypes.h>
void init_keycode (u32 idcode, u32 level, u32 modulo);
void init_keycode (u32 idcode, u32 level, u32 modulo, int iCardDevice);
void crypt_64bit_down (u32* ptr);
void crypt_64bit_up (u32* ptr);

264
BootLoader/source/key1.h Normal file
View File

@ -0,0 +1,264 @@
const unsigned char gEncrData[] =
{
0x99,0xD5,0x20,0x5F,0x57,0x44,0xF5,0xB9,0x6E,0x19,0xA4,0xD9,0x9E,0x6A,0x5A,0x94,
0xD8,0xAE,0xF1,0xEB,0x41,0x75,0xE2,0x3A,0x93,0x82,0xD0,0x32,0x33,0xEE,0x31,0xD5,
0xCC,0x57,0x61,0x9A,0x37,0x06,0xA2,0x1B,0x79,0x39,0x72,0xF5,0x55,0xAE,0xF6,0xBE,
0x5F,0x1B,0x69,0xFB,0xE5,0x9D,0xF1,0xE9,0xCE,0x2C,0xD9,0xA1,0x5E,0x32,0x05,0xE6,
0xFE,0xD3,0xFE,0xCF,0xD4,0x62,0x04,0x0D,0x8B,0xF5,0xEC,0xB7,0x2B,0x60,0x79,0xBB,
0x12,0x95,0x31,0x0D,0x6E,0x3F,0xDA,0x2B,0x88,0x84,0xF0,0xF1,0x3D,0x12,0x7E,0x25,
0x45,0x22,0xF1,0xBB,0x24,0x06,0x1A,0x06,0x11,0xAD,0xDF,0x28,0x8B,0x64,0x81,0x34,
0x2B,0xEB,0x33,0x29,0x99,0xAA,0xF2,0xBD,0x9C,0x14,0x95,0x9D,0x9F,0xF7,0xF5,0x8C,
0x72,0x97,0xA1,0x29,0x9D,0xD1,0x5F,0xCF,0x66,0x4D,0x07,0x1A,0xDE,0xD3,0x4A,0x4B,
0x85,0xC9,0xA7,0xA3,0x17,0x95,0x05,0x3A,0x3D,0x49,0x0A,0xBF,0x0A,0x89,0x8B,0xA2,
0x4A,0x82,0x49,0xDD,0x27,0x90,0xF1,0x0B,0xE9,0xEB,0x1C,0x6A,0x83,0x76,0x45,0x05,
0xBA,0x81,0x70,0x61,0x17,0x3F,0x4B,0xDE,0xAE,0xCF,0xAB,0x39,0x57,0xF2,0x3A,0x56,
0x48,0x11,0xAD,0x8A,0x40,0xE1,0x45,0x3F,0xFA,0x9B,0x02,0x54,0xCA,0xA6,0x93,0xFB,
0xEF,0x4D,0xFE,0x6F,0xA3,0xD8,0x87,0x9C,0x08,0xBA,0xD5,0x48,0x6A,0x8D,0x2D,0xFD,
0x6E,0x15,0xF8,0x74,0xBD,0xBE,0x52,0x8B,0x18,0x22,0x8A,0x9E,0xFB,0x74,0x37,0x07,
0x1B,0x36,0x6C,0x4A,0x19,0xBA,0x42,0x62,0xB9,0x79,0x91,0x10,0x7B,0x67,0x65,0x96,
0xFE,0x02,0x23,0xE8,0xEE,0x99,0x8C,0x77,0x3E,0x5C,0x86,0x64,0x4D,0x6D,0x78,0x86,
0xA5,0x4F,0x65,0xE2,0x1E,0xB2,0xDF,0x5A,0x0A,0xD0,0x7E,0x08,0x14,0xB0,0x71,0xAC,
0xBD,0xDB,0x83,0x1C,0xB9,0xD7,0xA1,0x62,0xCD,0xC6,0x63,0x7C,0x52,0x69,0xC3,0xE6,
0xBF,0x75,0xCE,0x12,0x44,0x5D,0x21,0x04,0xFA,0xFB,0xD3,0x3C,0x38,0x11,0x63,0xD4,
0x95,0x85,0x41,0x49,0x46,0x09,0xF2,0x08,0x43,0x11,0xDC,0x1F,0x76,0xC0,0x15,0x6D,
0x1F,0x3C,0x63,0x70,0xEA,0x87,0x80,0x6C,0xC3,0xBD,0x63,0x8B,0xC2,0x37,0x21,0x37,
0xDC,0xEE,0x09,0x23,0x2E,0x37,0x6A,0x4D,0x73,0x90,0xF7,0x50,0x30,0xAC,0x1C,0x92,
0x04,0x10,0x23,0x91,0x4F,0xD2,0x07,0xAA,0x68,0x3E,0x4F,0x9A,0xC9,0x64,0x60,0x6A,
0xC8,0x14,0x21,0xF3,0xD6,0x22,0x41,0x12,0x44,0x24,0xCF,0xE6,0x8A,0x56,0xDD,0x0D,
0x53,0x4D,0xE1,0x85,0x1E,0x8C,0x52,0x5A,0x9C,0x19,0x84,0xC2,0x03,0x57,0xF1,0x6F,
0xE3,0x00,0xBE,0x58,0xF6,0x4C,0xED,0xD5,0x21,0x64,0x9C,0x1F,0xBE,0x55,0x03,0x3C,
0x4A,0xDC,0xFF,0xAA,0xC9,0xDA,0xE0,0x5D,0x5E,0xBF,0xE6,0xDE,0xF5,0xD8,0xB1,0xF8,
0xFF,0x36,0xB3,0xB9,0x62,0x67,0x95,0xDB,0x31,0x5F,0x37,0xED,0x4C,0x70,0x67,0x99,
0x90,0xB5,0x18,0x31,0x6C,0x3D,0x99,0x99,0xE4,0x42,0xDA,0xD3,0x25,0x42,0x13,0xA0,
0xAE,0xD7,0x70,0x6C,0xB1,0x55,0xCF,0xC7,0xD7,0x46,0xD5,0x43,0x61,0x17,0x3D,0x44,
0x28,0xE9,0x33,0x85,0xD5,0xD0,0xA2,0x93,0xAA,0x25,0x12,0x1F,0xFB,0xC5,0x0B,0x46,
0xF5,0x97,0x76,0x56,0x45,0xA6,0xBE,0x87,0xB1,0x94,0x6B,0xE8,0xB1,0xFE,0x33,0x99,
0xAE,0x1F,0x3E,0x6C,0x39,0x71,0x1D,0x09,0x00,0x90,0x37,0xE4,0x10,0x3E,0x75,0x74,
0xFF,0x8C,0x83,0x3B,0xB0,0xF1,0xB0,0xF9,0x01,0x05,0x47,0x42,0x95,0xF1,0xD6,0xAC,
0x7E,0x38,0xE6,0x9E,0x95,0x74,0x26,0x3F,0xB4,0x68,0x50,0x18,0xD0,0x43,0x30,0xB4,
0x4C,0x4B,0xE3,0x68,0xBF,0xE5,0x4D,0xB6,0x95,0x8B,0x0A,0xA0,0x74,0x25,0x32,0x77,
0xCF,0xA1,0xF7,0x2C,0xD8,0x71,0x13,0x5A,0xAB,0xEA,0xC9,0x51,0xE8,0x0D,0xEE,0xEF,
0xE9,0x93,0x7E,0x19,0xA7,0x1E,0x43,0x38,0x81,0x16,0x2C,0xA1,0x48,0xE3,0x73,0xCC,
0x29,0x21,0x6C,0xD3,0x5D,0xCE,0xA0,0xD9,0x61,0x71,0x43,0xA0,0x15,0x13,0xB5,0x64,
0x92,0xCF,0x2A,0x19,0xDC,0xAD,0xB7,0xA5,0x9F,0x86,0x65,0xF8,0x1A,0x9F,0xE7,0xFB,
0xF7,0xFD,0xB8,0x13,0x6C,0x27,0xDB,0x6F,0xDF,0x35,0x1C,0xF7,0x8D,0x2C,0x5B,0x9B,
0x12,0xAB,0x38,0x64,0x06,0xCC,0xDE,0x31,0xE8,0x4E,0x75,0x11,0x64,0xE3,0xFA,0xEA,
0xEB,0x34,0x54,0xC2,0xAD,0x3F,0x34,0xEB,0x93,0x2C,0x7D,0x26,0x36,0x9D,0x56,0xF3,
0x5A,0xE1,0xF6,0xB3,0x98,0x63,0x4A,0x9E,0x32,0x83,0xE4,0x9A,0x84,0x60,0x7D,0x90,
0x2E,0x13,0x0E,0xEE,0x93,0x4B,0x36,0xA2,0x85,0xEC,0x16,0x38,0xE8,0x88,0x06,0x02,
0xBF,0xF0,0xA0,0x3A,0xED,0xD7,0x6A,0x9A,0x73,0xE1,0x57,0xCF,0xF8,0x44,0xB8,0xDC,
0x2E,0x23,0x59,0xD1,0xDF,0x95,0x52,0x71,0x99,0x61,0xA0,0x4B,0xD5,0x7F,0x6E,0x78,
0xBA,0xA9,0xC5,0x30,0xD3,0x40,0x86,0x32,0x9D,0x32,0x0C,0x9C,0x37,0xB7,0x02,0x2F,
0xBA,0x54,0x98,0xA9,0xC4,0x13,0x04,0xC9,0x8D,0xBE,0xC8,0xE7,0x5D,0x97,0x50,0x2E,
0x93,0xD6,0x22,0x59,0x0C,0x27,0xBC,0x22,0x92,0xE0,0xA7,0x20,0x0F,0x93,0x6F,0x7F,
0x4C,0x9F,0xD3,0xB5,0xA6,0x2A,0x0B,0x74,0x67,0x49,0x7D,0x10,0x26,0xCB,0xD1,0xC5,
0x86,0x71,0xE7,0x8C,0xA0,0x9C,0xE9,0x5B,0xB2,0x1A,0xF6,0x01,0xEE,0x8C,0x9E,0x5E,
0x83,0xF2,0x1A,0xDB,0xE6,0xE5,0xEA,0x84,0x59,0x76,0xD2,0x7C,0xF6,0x8D,0xA5,0x49,
0x36,0x48,0xC2,0x16,0x52,0xBB,0x83,0xA3,0x74,0xB9,0x07,0x0C,0x3B,0xFF,0x61,0x28,
0xE1,0x61,0xE9,0xE4,0xEF,0x6E,0x15,0xAA,0x4E,0xBA,0xE8,0x5D,0x05,0x96,0xBB,0x32,
0x56,0xB0,0xFB,0x72,0x52,0x0F,0x0E,0xC8,0x42,0x25,0x65,0x76,0x89,0xAF,0xF2,0xDE,
0x10,0x27,0xF0,0x01,0x4B,0x74,0xA7,0x97,0x07,0xD5,0x26,0x54,0x54,0x09,0x1F,0x82,
0x0A,0x86,0x7D,0x30,0x39,0x0E,0xB3,0x26,0x9B,0x0B,0x57,0xBB,0x36,0x06,0x31,0xAF,
0xFD,0x79,0xFC,0xD9,0x30,0x10,0x2B,0x0C,0xB3,0xE1,0x9B,0xD7,0x7B,0xDC,0x5F,0xEF,
0xD2,0xF8,0x13,0x45,0x4D,0x47,0x75,0xBD,0x46,0x96,0x3C,0x7E,0x75,0xF3,0x3E,0xB5,
0x67,0xC5,0x9A,0x3B,0xB0,0x5B,0x29,0x6B,0xDE,0x80,0x5B,0xC8,0x15,0x05,0xB1,0x31,
0xB6,0xCE,0x49,0xDD,0xAD,0x84,0xB5,0xAE,0x60,0xDC,0x67,0x31,0x34,0x30,0xFE,0x4E,
0xBD,0x80,0x2F,0xA6,0xBF,0x63,0x39,0x21,0x86,0xD9,0x35,0x7F,0x16,0x68,0x22,0x05,
0x54,0xE9,0x90,0x26,0x8C,0x07,0x6C,0x51,0xA4,0x31,0x55,0xD7,0x09,0x07,0xA8,0x3E,
0x2E,0x53,0x66,0xC1,0xF8,0xF2,0x7B,0xC4,0xF2,0x58,0xCF,0xF1,0x87,0xC5,0xA2,0xE7,
0x27,0x8F,0x30,0x87,0x58,0xA0,0x64,0x62,0x23,0x18,0xB9,0x88,0x7C,0xFA,0xCE,0xC4,
0x98,0xAE,0xAD,0x17,0xCC,0x4A,0x5B,0xF3,0xE9,0x48,0xD5,0x56,0xD3,0x0D,0xF2,0xC8,
0x92,0x73,0x8C,0xDB,0xD7,0x2F,0x56,0xAC,0x81,0xF9,0x92,0x69,0x4D,0xC6,0x32,0xF6,
0xE6,0xC0,0x8D,0x21,0xE2,0x76,0x80,0x61,0x11,0xBC,0xDC,0x6C,0x93,0xAF,0x19,0x69,
0x9B,0xD0,0xBF,0xB9,0x31,0x9F,0x02,0x67,0xA3,0x51,0xEE,0x83,0x06,0x22,0x7B,0x0C,
0xAB,0x49,0x42,0x40,0xB8,0xD5,0x01,0x7D,0xCE,0x5E,0xF7,0x55,0x53,0x39,0xC5,0x99,
0x46,0xD8,0x87,0x9F,0xBA,0xF7,0x64,0xB4,0xE3,0x9A,0xFA,0xA1,0x6D,0x90,0x68,0x10,
0x30,0xCA,0x8A,0x54,0xA7,0x9F,0x60,0xC3,0x19,0xF5,0x6B,0x0D,0x7A,0x51,0x98,0xE6,
0x98,0x43,0x51,0xB4,0xD6,0x35,0xE9,0x4F,0xC3,0xDF,0x0F,0x7B,0xD6,0x2F,0x5C,0xBD,
0x3A,0x15,0x61,0x19,0xF1,0x4B,0xCB,0xAA,0xDC,0x6D,0x64,0xC9,0xD3,0xC6,0x1E,0x56,
0xEF,0x38,0x4C,0x50,0x71,0x86,0x75,0xCC,0x0D,0x0D,0x4E,0xE9,0x28,0xF6,0x06,0x5D,
0x70,0x1B,0xAA,0xD3,0x45,0xCF,0xA8,0x39,0xAC,0x95,0xA6,0x2E,0xB4,0xE4,0x22,0xD4,
0x74,0xA8,0x37,0x5F,0x48,0x7A,0x04,0xCC,0xA5,0x4C,0x40,0xD8,0x28,0xB4,0x28,0x08,
0x0D,0x1C,0x72,0x52,0x41,0xF0,0x7D,0x47,0x19,0x3A,0x53,0x4E,0x58,0x84,0x62,0x6B,
0x93,0xB5,0x8A,0x81,0x21,0x4E,0x0D,0xDC,0xB4,0x3F,0xA2,0xC6,0xFC,0xC9,0x2B,0x40,
0xDA,0x38,0x04,0xE9,0x5E,0x5A,0x86,0x6B,0x0C,0x22,0x25,0x85,0x68,0x11,0x8D,0x7C,
0x92,0x1D,0x95,0x55,0x4D,0xAB,0x8E,0xBB,0xDA,0xA6,0xE6,0xB7,0x51,0xB6,0x32,0x5A,
0x05,0x41,0xDD,0x05,0x2A,0x0A,0x56,0x50,0x91,0x17,0x47,0xCC,0xC9,0xE6,0x7E,0xB5,
0x61,0x4A,0xDB,0x73,0x67,0x51,0xC8,0x33,0xF5,0xDA,0x6E,0x74,0x2E,0x54,0xC3,0x37,
0x0D,0x6D,0xAF,0x08,0xE8,0x15,0x8A,0x5F,0xE2,0x59,0x21,0xCD,0xA8,0xDE,0x0C,0x06,
0x5A,0x77,0x6B,0x5F,0xDB,0x18,0x65,0x3E,0xC8,0x50,0xDE,0x78,0xE0,0xB8,0x82,0xB3,
0x5D,0x4E,0x72,0x32,0x07,0x4F,0xC1,0x34,0x23,0xBA,0x96,0xB7,0x67,0x4E,0xA4,0x28,
0x1E,0x34,0x62,0xEB,0x2D,0x6A,0x70,0xE9,0x2F,0x42,0xC4,0x70,0x4E,0x5A,0x31,0x9C,
0xF9,0x5B,0x47,0x28,0xAA,0xDA,0x71,0x6F,0x38,0x1F,0xB3,0x78,0xC4,0x92,0x6B,0x1C,
0x9E,0xF6,0x35,0x9A,0xB7,0x4D,0x0E,0xBF,0xCC,0x18,0x29,0x41,0x03,0x48,0x35,0x5D,
0x55,0xD0,0x2B,0xC6,0x29,0xAF,0x5C,0x60,0x74,0x69,0x8E,0x5E,0x9B,0x7C,0xD4,0xBD,
0x7B,0x44,0x64,0x7D,0x3F,0x92,0x5D,0x69,0xB6,0x1F,0x00,0x4B,0xD4,0x83,0x35,0xCF,
0x7E,0x64,0x4E,0x17,0xAE,0x8D,0xD5,0x2E,0x9A,0x28,0x12,0x4E,0x2E,0x2B,0x49,0x08,
0x5C,0xAE,0xC6,0x46,0x85,0xAE,0x41,0x61,0x1E,0x6F,0x82,0xD2,0x51,0x37,0x16,0x1F,
0x0B,0xF6,0x59,0xA4,0x9A,0xCA,0x5A,0xAF,0x0D,0xD4,0x33,0x8B,0x20,0x63,0xF1,0x84,
0x80,0x5C,0xCB,0xCF,0x08,0xB4,0xB9,0xD3,0x16,0x05,0xBD,0x62,0x83,0x31,0x9B,0x56,
0x51,0x98,0x9F,0xBA,0xB2,0x5B,0xAA,0xB2,0x22,0x6B,0x2C,0xB5,0xD4,0x48,0xFA,0x63,
0x2B,0x5F,0x58,0xFA,0x61,0xFA,0x64,0x09,0xBB,0x38,0xE0,0xB8,0x9D,0x92,0x60,0xA8,
0x0D,0x67,0x6F,0x0E,0x37,0xF5,0x0D,0x01,0x9F,0xC2,0x77,0xD4,0xFE,0xEC,0xF1,0x73,
0x30,0x39,0xE0,0x7D,0xF5,0x61,0x98,0xE4,0x2C,0x28,0x55,0x04,0x56,0x55,0xDB,0x2F,
0x6B,0xEC,0xE5,0x58,0x06,0xB6,0x64,0x80,0x6A,0x2A,0x1A,0x4E,0x5B,0x0F,0xD8,0xC4,
0x0A,0x2E,0x52,0x19,0xD9,0x62,0xF5,0x30,0x48,0xBE,0x8C,0x7B,0x4F,0x38,0x9B,0xA2,
0xC3,0xAF,0xC9,0xD3,0xC7,0xC1,0x62,0x41,0x86,0xB9,0x61,0x21,0x57,0x6F,0x99,0x4F,
0xC1,0xBA,0xCE,0x7B,0xB5,0x3B,0x4D,0x5E,0x8A,0x8B,0x44,0x57,0x5F,0x13,0x5F,0x70,
0x6D,0x5B,0x29,0x47,0xDC,0x38,0xE2,0xEC,0x04,0x55,0x65,0x12,0x2A,0xE8,0x17,0x43,
0xE1,0x8E,0xDD,0x2A,0xB3,0xE2,0x94,0xF7,0x09,0x6E,0x5C,0xE6,0xEB,0x8A,0xF8,0x6D,
0x89,0x49,0x54,0x48,0xF5,0x2F,0xAD,0xBF,0xEA,0x94,0x4B,0xCA,0xFC,0x39,0x87,0x82,
0x5F,0x8A,0x01,0xF2,0x75,0xF2,0xE6,0x71,0xD6,0xD8,0x42,0xDE,0xF1,0x2D,0x1D,0x28,
0xA6,0x88,0x7E,0xA3,0xA0,0x47,0x1D,0x30,0xD9,0xA3,0x71,0xDF,0x49,0x1C,0xCB,0x01,
0xF8,0x36,0xB1,0xF2,0xF0,0x22,0x58,0x5D,0x45,0x6B,0xBD,0xA0,0xBB,0xB2,0x88,0x42,
0xC7,0x8C,0x28,0xCE,0x93,0xE8,0x90,0x63,0x08,0x90,0x7C,0x89,0x3C,0xF5,0x7D,0xB7,
0x04,0x2D,0x4F,0x55,0x51,0x16,0xFD,0x7E,0x79,0xE8,0xBE,0xC1,0xF2,0x12,0xD4,0xF8,
0xB4,0x84,0x05,0x23,0xA0,0xCC,0xD2,0x2B,0xFD,0xE1,0xAB,0xAD,0x0D,0xD1,0x55,0x6C,
0x23,0x41,0x94,0x4D,0x77,0x37,0x4F,0x05,0x28,0x0C,0xBF,0x17,0xB3,0x12,0x67,0x6C,
0x8C,0xC3,0x5A,0xF7,0x41,0x84,0x2A,0x6D,0xD0,0x94,0x12,0x27,0x2C,0xB4,0xED,0x9C,
0x4D,0xEC,0x47,0x82,0x97,0xD5,0x67,0xB9,0x1B,0x9D,0xC0,0x55,0x07,0x7E,0xE5,0x8E,
0xE2,0xA8,0xE7,0x3E,0x12,0xE4,0x0E,0x3A,0x2A,0x45,0x55,0x34,0xA2,0xF9,0x2D,0x5A,
0x1B,0xAB,0x52,0x7C,0x83,0x10,0x5F,0x55,0xD2,0xF1,0x5A,0x43,0x2B,0xC6,0xA7,0xA4,
0x89,0x15,0x95,0xE8,0xB4,0x4B,0x9D,0xF8,0x75,0xE3,0x9F,0x60,0x78,0x5B,0xD6,0xE6,
0x0D,0x44,0xE6,0x21,0x06,0xBD,0x47,0x22,0x53,0xA4,0x00,0xAD,0x8D,0x43,0x13,0x85,
0x39,0xF7,0xAA,0xFC,0x38,0xAF,0x7B,0xED,0xFC,0xE4,0x2B,0x54,0x50,0x98,0x4C,0xFC,
0x85,0x80,0xF7,0xDF,0x3C,0x80,0x22,0xE1,0x94,0xDA,0xDE,0x24,0xC6,0xB0,0x7A,0x39,
0x38,0xDC,0x0F,0xA1,0xA7,0xF4,0xF9,0x6F,0x63,0x18,0x57,0x8B,0x84,0x41,0x2A,0x2E,
0xD4,0x53,0xF2,0xD9,0x00,0x0F,0xD0,0xDD,0x99,0x6E,0x19,0xA6,0x0A,0xD0,0xEC,0x5B,
0x58,0x24,0xAB,0xC0,0xCB,0x06,0x65,0xEC,0x1A,0x13,0x38,0x94,0x0A,0x67,0x03,0x2F,
0x3F,0xF7,0xE3,0x77,0x44,0x77,0x33,0xC6,0x14,0x39,0xD0,0xE3,0xC0,0xA2,0x08,0x79,
0xBB,0x40,0x99,0x57,0x41,0x0B,0x01,0x90,0xCD,0xE1,0xCC,0x48,0x67,0xDB,0xB3,0xAF,
0x88,0x74,0xF3,0x4C,0x82,0x8F,0x72,0xB1,0xB5,0x23,0x29,0xC4,0x12,0x6C,0x19,0xFC,
0x8E,0x46,0xA4,0x9C,0xC4,0x25,0x65,0x87,0xD3,0x6D,0xBE,0x8A,0x93,0x11,0x03,0x38,
0xED,0x83,0x2B,0xF3,0x46,0xA4,0x93,0xEA,0x3B,0x53,0x85,0x1D,0xCE,0xD4,0xF1,0x08,
0x83,0x27,0xED,0xFC,0x9B,0x1A,0x18,0xBC,0xF9,0x8B,0xAE,0xDC,0x24,0xAB,0x50,0x38,
0xE9,0x72,0x4B,0x10,0x22,0x17,0x7B,0x46,0x5D,0xAB,0x59,0x64,0xF3,0x40,0xAE,0xF8,
0xBB,0xE5,0xC8,0xF9,0x26,0x03,0x4E,0x55,0x7D,0xEB,0xEB,0xFE,0xF7,0x39,0xE6,0xE0,
0x0A,0x11,0xBE,0x2E,0x28,0xFF,0x98,0xED,0xC0,0xC9,0x42,0x56,0x42,0xC3,0xFD,0x00,
0xF6,0xAF,0x87,0xA2,0x5B,0x01,0x3F,0x32,0x92,0x47,0x95,0x9A,0x72,0xA5,0x32,0x3D,
0xAE,0x6B,0xD0,0x9B,0x07,0xD2,0x49,0x92,0xE3,0x78,0x4A,0xFA,0xA1,0x06,0x7D,0xF2,
0x41,0xCF,0x77,0x74,0x04,0x14,0xB2,0x0C,0x86,0x84,0x64,0x16,0xD5,0xBB,0x51,0xA1,
0xE5,0x6F,0xF1,0xD1,0xF2,0xE2,0xF7,0x5F,0x58,0x20,0x4D,0xB8,0x57,0xC7,0xCF,0xDD,
0xC5,0xD8,0xBE,0x76,0x3D,0xF6,0x5F,0x7E,0xE7,0x2A,0x8B,0x88,0x24,0x1B,0x38,0x3F,
0x0E,0x41,0x23,0x77,0xF5,0xF0,0x4B,0xD4,0x0C,0x1F,0xFA,0xA4,0x0B,0x80,0x5F,0xCF,
0x45,0xF6,0xE0,0xDA,0x2F,0x34,0x59,0x53,0xFB,0x20,0x3C,0x52,0x62,0x5E,0x35,0xB5,
0x62,0xFE,0x8B,0x60,0x63,0xE3,0x86,0x5A,0x15,0x1A,0x6E,0xD1,0x47,0x45,0xBC,0x32,
0xB4,0xEB,0x67,0x38,0xAB,0xE4,0x6E,0x33,0x3A,0xB5,0xED,0xA3,0xAD,0x67,0xE0,0x4E,
0x41,0x95,0xEE,0x62,0x62,0x71,0x26,0x1D,0x31,0xEF,0x62,0x30,0xAF,0xD7,0x82,0xAC,
0xC2,0xDC,0x05,0x04,0xF5,0x97,0x07,0xBF,0x11,0x59,0x23,0x07,0xC0,0x64,0x02,0xE8,
0x97,0xE5,0x3E,0xAF,0x18,0xAC,0x59,0xA6,0x8B,0x4A,0x33,0x90,0x1C,0x6E,0x7C,0x9C,
0x20,0x7E,0x4C,0x3C,0x3E,0x61,0x64,0xBB,0xC5,0x6B,0x7C,0x7E,0x3E,0x9F,0xC5,0x4C,
0x9F,0xEA,0x73,0xF5,0xD7,0x89,0xC0,0x4C,0xF4,0xFB,0xF4,0x2D,0xEC,0x14,0x1B,0x51,
0xD5,0xC1,0x12,0xC8,0x10,0xDF,0x0B,0x4A,0x8B,0x9C,0xBC,0x93,0x45,0x6A,0x3E,0x3E,
0x7D,0xC1,0xA9,0xBA,0xCD,0xC1,0xB4,0x07,0xE4,0xE1,0x68,0x86,0x43,0xB2,0x6D,0x38,
0xF3,0xFB,0x0C,0x5C,0x66,0x37,0x71,0xDE,0x56,0xEF,0x6E,0xA0,0x10,0x40,0x65,0xA7,
0x98,0xF7,0xD0,0xBE,0x0E,0xC8,0x37,0x36,0xEC,0x10,0xCA,0x7C,0x9C,0xAB,0x84,0x1E,
0x05,0x17,0x76,0x02,0x1C,0x4F,0x52,0xAA,0x5F,0xC1,0xC6,0xA0,0x56,0xB9,0xD8,0x04,
0x84,0x44,0x4D,0xA7,0x59,0xD8,0xDE,0x60,0xE6,0x38,0x0E,0x05,0x8F,0x03,0xE1,0x3B,
0x6D,0x81,0x04,0x33,0x6F,0x30,0x0B,0xCE,0x69,0x05,0x21,0x33,0xFB,0x26,0xBB,0x89,
0x7D,0xB6,0xAE,0x87,0x7E,0x51,0x07,0xE0,0xAC,0xF7,0x96,0x0A,0x6B,0xF9,0xC4,0x5C,
0x1D,0xE4,0x44,0x47,0xB8,0x5E,0xFA,0xE3,0x78,0x84,0x55,0x42,0x4B,0x48,0x5E,0xF7,
0x7D,0x47,0x35,0x86,0x1D,0x2B,0x43,0x05,0x03,0xEC,0x8A,0xB8,0x1E,0x06,0x3C,0x76,
0x0C,0x48,0x1A,0x43,0xA7,0xB7,0x8A,0xED,0x1E,0x13,0xC6,0x43,0xEE,0x10,0xEF,0xDB,
0xEC,0xFB,0x3C,0x83,0xB2,0x95,0x44,0xEF,0xD8,0x54,0x51,0x4E,0x2D,0x11,0x44,0x1D,
0xFB,0x36,0x59,0x1E,0x7A,0x34,0xC1,0xC3,0xCA,0x57,0x00,0x61,0xEA,0x67,0xA5,0x16,
0x9B,0x55,0xD0,0x55,0xE1,0x7F,0xD9,0x36,0xD2,0x40,0x76,0xAE,0xDC,0x01,0xCE,0xB0,
0x7A,0x83,0xD5,0xCB,0x20,0x98,0xEC,0x6B,0xC1,0x72,0x92,0x34,0xF3,0x82,0x57,0x37,
0x62,0x8A,0x32,0x36,0x0C,0x90,0x43,0xAE,0xAE,0x5C,0x9B,0x78,0x8E,0x13,0x65,0x02,
0xFD,0x68,0x71,0xC1,0xFE,0xB0,0x31,0xA0,0x24,0x82,0xB0,0xC3,0xB1,0x79,0x69,0xA7,
0xF5,0xD2,0xEB,0xD0,0x82,0xC0,0x32,0xDC,0x9E,0xC7,0x26,0x3C,0x6D,0x8D,0x98,0xC1,
0xBB,0x22,0xD4,0xD0,0x0F,0x33,0xEC,0x3E,0xB9,0xCC,0xE1,0xDC,0x6A,0x4C,0x77,0x36,
0x14,0x1C,0xF9,0xBF,0x81,0x9F,0x28,0x5F,0x71,0x85,0x32,0x29,0x90,0x75,0x48,0xC4,
0xB3,0x4A,0xCE,0xD8,0x44,0x8F,0x14,0x2F,0xFD,0x40,0x57,0xEF,0xAA,0x08,0x75,0xD9,
0x46,0xD1,0xD6,0x6E,0x32,0x55,0x1F,0xC3,0x18,0xFE,0x84,0x1F,0xFC,0x84,0xD5,0xFF,
0x71,0x5E,0x1B,0x48,0xC3,0x86,0x95,0x0E,0x28,0x08,0x27,0xD3,0x38,0x83,0x71,0x7B,
0x4C,0x80,0x63,0x54,0x9A,0x56,0xB0,0xAC,0xCF,0x80,0xCA,0x31,0x09,0xEF,0xFE,0xF3,
0xBE,0xAF,0x24,0x7E,0xA6,0xFE,0x53,0x3F,0xC2,0x8D,0x4A,0x33,0x68,0xD1,0x22,0xA6,
0x66,0xAD,0x7B,0xEA,0xDE,0xB6,0x43,0xB0,0xA1,0x25,0x95,0x00,0xA3,0x3F,0x75,0x46,
0x14,0x11,0x44,0xEC,0xD7,0x95,0xBC,0x92,0xF0,0x4F,0xA9,0x16,0x53,0x62,0x97,0x60,
0x2A,0x0F,0x41,0xF1,0x71,0x24,0xBE,0xEE,0x94,0x7F,0x08,0xCD,0x60,0x93,0xB3,0x85,
0x5B,0x07,0x00,0x3F,0xD8,0x0F,0x28,0x83,0x9A,0xD1,0x69,0x9F,0xD1,0xDA,0x2E,0xC3,
0x90,0x01,0xA2,0xB9,0x6B,0x4E,0x2A,0x66,0x9D,0xDA,0xAE,0xA6,0xEA,0x2A,0xD3,0x68,
0x2F,0x0C,0x0C,0x9C,0xD2,0x8C,0x4A,0xED,0xE2,0x9E,0x57,0x65,0x9D,0x09,0x87,0xA3,
0xB4,0xC4,0x32,0x5D,0xC9,0xD4,0x32,0x2B,0xB1,0xE0,0x71,0x1E,0x64,0x4D,0xE6,0x90,
0x71,0xE3,0x1E,0x40,0xED,0x7D,0xF3,0x84,0x0E,0xED,0xC8,0x78,0x76,0xAE,0xC0,0x71,
0x27,0x72,0xBB,0x05,0xEA,0x02,0x64,0xFB,0xF3,0x48,0x6B,0xB5,0x42,0x93,0x3F,0xED,
0x9F,0x13,0x53,0xD2,0xF7,0xFE,0x2A,0xEC,0x1D,0x47,0x25,0xDB,0x3C,0x91,0x86,0xC6,
0x8E,0xF0,0x11,0xFD,0x23,0x74,0x36,0xF7,0xA4,0xF5,0x9E,0x7A,0x7E,0x53,0x50,0x44,
0xD4,0x47,0xCA,0xD3,0xEB,0x38,0x6D,0xE6,0xD9,0x71,0x94,0x7F,0x4A,0xC6,0x69,0x4B,
0x11,0xF4,0x52,0xEA,0x22,0xFE,0x8A,0xB0,0x36,0x67,0x8B,0x59,0xE8,0xE6,0x80,0x2A,
0xEB,0x65,0x04,0x13,0xEE,0xEC,0xDC,0x9E,0x5F,0xB1,0xEC,0x05,0x6A,0x59,0xE6,0x9F,
0x5E,0x59,0x6B,0x89,0xBF,0xF7,0x1A,0xCA,0x44,0xF9,0x5B,0x6A,0x71,0x85,0x03,0xE4,
0x29,0x62,0xE0,0x70,0x6F,0x41,0xC4,0xCF,0xB2,0xB1,0xCC,0xE3,0x7E,0xA6,0x07,0xA8,
0x87,0xE7,0x7F,0x84,0x93,0xDB,0x52,0x4B,0x6C,0xEC,0x7E,0xDD,0xD4,0x24,0x48,0x10,
0x69,0x9F,0x04,0x60,0x74,0xE6,0x48,0x18,0xF3,0xE4,0x2C,0xB9,0x4F,0x2E,0x50,0x7A,
0xDF,0xD4,0x54,0x69,0x2B,0x8B,0xA7,0xF3,0xCE,0xFF,0x1F,0xF3,0x3E,0x26,0x01,0x39,
0x17,0x95,0x84,0x89,0xB0,0xF0,0x4C,0x4B,0x82,0x91,0x9F,0xC4,0x4B,0xAC,0x9D,0xA5,
0x74,0xAF,0x17,0x25,0xC9,0xCA,0x32,0xD3,0xBC,0x89,0x8A,0x84,0x89,0xCC,0x0D,0xAE,
0x7C,0xA2,0xDB,0x9C,0x6A,0x78,0x91,0xEE,0xEA,0x76,0x5D,0x4E,0x87,0x60,0xF5,0x69,
0x15,0x67,0xD4,0x02,0xCF,0xAF,0x48,0x36,0x07,0xEA,0xBF,0x6F,0x66,0x2D,0x06,0x8F,
0xC4,0x9A,0xFE,0xF9,0xF6,0x90,0x87,0x75,0xB8,0xF7,0xAD,0x0F,0x76,0x10,0x5A,0x3D,
0x59,0xB0,0x2E,0xB3,0xC7,0x35,0x2C,0xCC,0x70,0x56,0x2B,0xCB,0xE3,0x37,0x96,0xC5,
0x2F,0x46,0x1B,0x8A,0x22,0x46,0xC7,0x88,0xA7,0x26,0x32,0x98,0x61,0xDF,0x86,0x22,
0x8A,0xF4,0x1C,0x2F,0x87,0xA1,0x09,0xAA,0xCC,0xA9,0xAE,0xD3,0xBD,0x00,0x45,0x1C,
0x9A,0x54,0x87,0x86,0x52,0x87,0xEF,0xFF,0x1E,0x8F,0xA1,0x8F,0xC1,0x89,0x5C,0x35,
0x1B,0xDA,0x2D,0x3A,0x2C,0x16,0xB2,0xC2,0xF1,0x56,0xE2,0x78,0xC1,0x6B,0x63,0x97,
0xC5,0x56,0x8F,0xC9,0x32,0x7F,0x2C,0xAA,0xAF,0xA6,0xA8,0xAC,0x20,0x91,0x22,0x88,
0xDE,0xE4,0x60,0x8B,0xF9,0x4B,0x42,0x25,0x1A,0xE3,0x7F,0x9C,0x2C,0x19,0x89,0x3A,
0x7E,0x05,0xD4,0x36,0xCC,0x69,0x58,0xC2,0xC1,0x32,0x8B,0x2F,0x90,0x85,0xEB,0x7A,
0x39,0x50,0xA5,0xA1,0x27,0x92,0xC5,0x66,0xB0,0x20,0x4F,0x58,0x7E,0x55,0x83,0x43,
0x2B,0x45,0xE2,0x9C,0xE4,0xD8,0x12,0x90,0x2C,0x16,0x83,0x56,0x16,0x79,0x03,0xB3,
0xAD,0x2D,0x61,0x18,0x1A,0x13,0x1F,0x37,0xE2,0xE1,0x9C,0x73,0x7B,0x80,0xD5,0xFD,
0x2D,0x51,0x87,0xFC,0x7B,0xAA,0xD7,0x1F,0x2C,0x7A,0x8E,0xAF,0xF4,0x8D,0xBB,0xCD,
0x95,0x11,0x7C,0x72,0x0B,0xEE,0x6F,0xE2,0xB9,0xAF,0xDE,0x37,0x83,0xDE,0x8C,0x8D,
0x62,0x05,0x67,0xB7,0x96,0xC6,0x8D,0x56,0xB6,0x0D,0xD7,0x62,0xBA,0xD6,0x46,0x36,
0xBD,0x8E,0xC8,0xE6,0xEA,0x2A,0x6C,0x10,0x14,0xFF,0x6B,0x5B,0xFA,0x82,0x3C,0x46,
0xB1,0x30,0x43,0x46,0x51,0x8A,0x7D,0x9B,0x92,0x3E,0x83,0x79,0x5B,0x55,0x5D,0xB2,
0x6C,0x5E,0xCE,0x90,0x62,0x8E,0x53,0x98,0xC9,0x0D,0x6D,0xE5,0x2D,0x57,0xCD,0xC5,
0x81,0x57,0xBA,0xE1,0xE8,0xB8,0x8F,0x72,0xE5,0x4F,0x13,0xDC,0xEA,0x9D,0x71,0x15,
0x10,0xB2,0x11,0x88,0xD5,0x09,0xD4,0x7F,0x5B,0x65,0x7F,0x2C,0x3B,0x38,0x4C,0x11,
0x68,0x50,0x8D,0xFB,0x9E,0xB0,0x59,0xBF,0x94,0x80,0x89,0x4A,0xC5,0x1A,0x18,0x12,
0x89,0x53,0xD1,0x4A,0x10,0x29,0xE8,0x8C,0x1C,0xEC,0xB6,0xEA,0x46,0xC7,0x17,0x8B,
0x25,0x15,0x31,0xA8,0xA2,0x6B,0x43,0xB1,0x9D,0xE2,0xDB,0x0B,0x87,0x9B,0xB0,0x11,
0x04,0x0E,0x71,0xD2,0x29,0x77,0x89,0x82,0x0A,0x66,0x41,0x7F,0x1D,0x0B,0x48,0xFF,
0x72,0xBB,0x24,0xFD,0xC2,0x48,0xA1,0x9B,0xFE,0x7B,0x7F,0xCE,0x88,0xDB,0x86,0xD9,
0x85,0x3B,0x1C,0xB0,0xDC,0xA8,0x33,0x07,0xBF,0x51,0x2E,0xE3,0x0E,0x9A,0x00,0x97,
0x1E,0x06,0xC0,0x97,0x43,0x9D,0xD8,0xB6,0x45,0xC4,0x86,0x67,0x5F,0x00,0xF8,0x88,
0x9A,0xA4,0x52,0x9E,0xC7,0xAA,0x8A,0x83,0x75,0xEC,0xC5,0x18,0xAE,0xCE,0xC3,0x2F,
0x1A,0x2B,0xF9,0x18,0xFF,0xAE,0x1A,0xF5,0x53,0x0B,0xB5,0x33,0x51,0xA7,0xFD,0xE8,
0xA8,0xE1,0xA2,0x64,0xB6,0x22,0x17,0x43,0x80,0xCC,0x0A,0xD8,0xAE,0x3B,0xBA,0x40,
0xD7,0xD9,0x92,0x4A,0x89,0xDF,0x04,0x10,0xEE,0x9B,0x18,0x2B,0x6A,0x77,0x69,0x8A,
0x68,0xF4,0xF9,0xB9,0xA2,0x21,0x15,0x6E,0xE6,0x1E,0x3B,0x03,0x62,0x30,0x9B,0x60,
0x41,0x7E,0x25,0x9B,0x9E,0x8F,0xC5,0x52,0x10,0x08,0xF8,0xC2,0x69,0xA1,0x21,0x11,
0x88,0x37,0x5E,0x79,0x35,0x66,0xFF,0x10,0x42,0x18,0x6E,0xED,0x97,0xB6,0x6B,0x1C,
0x4E,0x36,0xE5,0x6D,0x7D,0xB4,0xE4,0xBF,0x20,0xB9,0xE0,0x05,0x3A,0x69,0xD5,0xB8,
0xE3,0xD5,0xDC,0xE0,0xB9,0xAC,0x53,0x3E,0x07,0xA4,0x57,0xAD,0x77,0xFF,0x48,0x18,
0x76,0x2A,0xAC,0x49,0x2A,0x8E,0x47,0x75,0x6D,0x9F,0x67,0x63,0x30,0x35,0x8C,0x39,
0x05,0x39,0xD5,0x6F,0x64,0x3A,0x5B,0xAD,0xCA,0x0B,0xBB,0x82,0x52,0x99,0x45,0xB1,
0x93,0x36,0x36,0x99,0xAF,0x13,0x20,0x44,0x36,0xD8,0x02,0x44,0x09,0x39,0x92,0x85,
0xFF,0x4A,0x4A,0x97,0x87,0xA6,0x63,0xD7,0xC7,0xB5,0xB5,0x24,0xED,0x0F,0xB4,0x6F,
0x0C,0x58,0x52,0x14,0xD9,0xA6,0x7B,0xD3,0x79,0xBC,0x38,0x58,0xA1,0xBD,0x3B,0x84,
0x06,0xD8,0x1A,0x06,0xFD,0x6B,0xA8,0xEA,0x4B,0x69,0x28,0x04,0x37,0xAD,0x82,0x99,
0xFB,0x0E,0x1B,0x85,0xBD,0xA8,0x5D,0x73,0xCD,0xDC,0x58,0x75,0x0A,0xBE,0x63,0x6C,
0x48,0xE7,0x4C,0xE4,0x30,0x2B,0x04,0x60,0xB9,0x15,0xD8,0xDA,0x86,0x81,0x75,0x8F,
0x96,0xD4,0x8D,0x1C,0x5D,0x70,0x85,0x7C,0x1C,0x67,0x7B,0xD5,0x08,0x67,0xA6,0xCE,
0x4B,0x0A,0x66,0x70,0xB7,0xE5,0x63,0xD4,0x5B,0x8A,0x82,0xEA,0x10,0x67,0xCA,0xE2,
0xF4,0xEF,0x17,0x85,0x2F,0x2A,0x5F,0x8A,0x97,0x82,0xF8,0x6A,0xD6,0x34,0x10,0xEA,
0xEB,0xC9,0x5C,0x3C,0xE1,0x49,0xF8,0x46,0xEB,0xDE,0xBD,0xF6,0xA9,0x92,0xF1,0xAA,
0xA6,0xA0,0x18,0xB0,0x3A,0xD3,0x0F,0x1F,0xF3,0x6F,0xFF,0x31,0x45,0x43,0x44,0xD3,
0x50,0x9A,0xF7,0x88,0x09,0x96,0xC1,0xCE,0x76,0xCC,0xF2,0x2C,0x2C,0xBA,0xAD,0x82,
0x77,0x8F,0x18,0x84,0xC0,0xD2,0x07,0x9C,0x36,0x90,0x83,0x4E,0x0B,0xA5,0x4F,0x43,
0x3E,0x04,0xAB,0x78,0x4F,0xD6,0xFB,0x09,0x01,0x24,0x90,0xDA,0x6F,0x3C,0x3A,0x61,
0x0D,0x7F,0x69,0x4A,0xEB,0x2B,0x30,0x02,0xB4,0xDB,0xE0,0x84,0xA9,0xEC,0xD7,0x35,
0xBF,0x37,0x7D,0x85,0x58,0xCE,0xA9,0x4E,0xE4,0x80,0xC7,0xA8,0xD3,0x30,0x67,0x48,
0xEB,0x29,0xAF,0x2F,0x74,0x6A,0xB4,0xA7,0x3F,0x0F,0x3F,0x92,0xAF,0xF3,0xCA,0xAC,
0xAF,0x4B,0xD9,0x94,0xC0,0x43,0xCA,0x81,0x0D,0x2F,0x48,0xA1,0xB0,0x27,0xD5,0xD2,
0xEF,0x4B,0x05,0x85,0xA3,0xDE,0x4D,0x93,0x30,0x3C,0xF0,0xBB,0x4A,0x8F,0x30,0x27,
0x4C,0xEB,0xE3,0x3E,0x64,0xED,0x9A,0x2F,0x3B,0xF1,0x82,0xF0,0xBA,0xF4,0xCF,0x7F,
0x40,0xCB,0xB0,0xE1,0x7F,0xBC,0xAA,0x57,0xD3,0xC9,0x74,0xF2,0xFA,0x43,0x0D,0x22,
0xD0,0xF4,0x77,0x4E,0x93,0xD7,0x85,0x70,0x1F,0x99,0xBF,0xB6,0xDE,0x35,0xF1,0x30,
0xA7,0x5E,0x71,0xF0,0x6B,0x01,0x2D,0x7B,0x64,0xF0,0x33,0x53,0x0A,0x39,0x88,0xF3,
0x6B,0x3A,0xA6,0x6B,0x35,0xD2,0x2F,0x43,0xCD,0x02,0xFD,0xB5,0xE9,0xBC,0x5B,0xAA,
0xD8,0xA4,0x19,0x7E,0x0E,0x5D,0x94,0x81,0x9E,0x6F,0x77,0xAD,0xD6,0x0E,0x74,0x93,
0x96,0xE7,0xC4,0x18,0x5F,0xAD,0xF5,0x19
};

350
BootLoader/source/key2.h Normal file
View File

@ -0,0 +1,350 @@
const unsigned char gEncrDataTwl[] = {
0x59, 0xaa, 0x56, 0x8e, 0x90, 0xd7, 0x11, 0x55, 0x4d, 0xea, 0xbf, 0xfe,
0xbd, 0x0d, 0x75, 0x91, 0xf7, 0x85, 0x39, 0x98, 0xd0, 0x9c, 0xc3, 0x58,
0xc4, 0x15, 0x6f, 0xf1, 0x90, 0xf9, 0xe4, 0xc3, 0x8e, 0xc0, 0x9b, 0x0e,
0x5d, 0xe1, 0x87, 0x94, 0xb9, 0x07, 0x2c, 0xba, 0xa6, 0x4f, 0x75, 0x74,
0xc1, 0xe3, 0x1c, 0x86, 0xe6, 0xed, 0xf8, 0x09, 0x3b, 0xbb, 0x37, 0x7a,
0x4e, 0xf0, 0xf0, 0x92, 0xf6, 0x55, 0xfa, 0x47, 0xfb, 0x1b, 0xc5, 0x16,
0x06, 0x74, 0x4e, 0x56, 0x20, 0xdd, 0xb6, 0xd1, 0x42, 0xcf, 0xcf, 0xf1,
0x55, 0x7e, 0x17, 0x18, 0xa1, 0x93, 0xff, 0x09, 0xda, 0x36, 0xa6, 0x9a,
0x43, 0x3d, 0xf4, 0x65, 0xed, 0x40, 0x97, 0x6c, 0xd5, 0xa6, 0xdd, 0x6d,
0x6c, 0x23, 0xbf, 0x94, 0xe7, 0x51, 0xa6, 0x68, 0x3c, 0xe8, 0xe6, 0x65,
0xd6, 0xbc, 0x9e, 0x92, 0x78, 0x26, 0x46, 0xa1, 0x73, 0xdc, 0xe5, 0x36,
0x8e, 0xcd, 0xec, 0xa1, 0xf1, 0xee, 0x8b, 0x68, 0xf4, 0xac, 0xc1, 0xdc,
0xc8, 0x84, 0x95, 0x31, 0xe8, 0xed, 0xc7, 0x5e, 0xe4, 0x5a, 0x37, 0xca,
0xec, 0x55, 0xbe, 0x2a, 0xfc, 0xf6, 0x45, 0x67, 0xa9, 0xb4, 0x7d, 0x7d,
0x9b, 0x6e, 0xe9, 0x2c, 0xff, 0x3f, 0xeb, 0x69, 0xb7, 0x2e, 0x68, 0xa8,
0x94, 0xef, 0x7b, 0xbd, 0x88, 0x93, 0x15, 0x66, 0x3a, 0xb7, 0x7f, 0xfe,
0x1d, 0xc3, 0x89, 0x08, 0xd7, 0x74, 0x59, 0xfa, 0xaf, 0x91, 0x41, 0x9e,
0x57, 0xd5, 0x67, 0x84, 0xba, 0x00, 0xe9, 0x63, 0x58, 0x07, 0x4d, 0xec,
0xdf, 0xc6, 0xda, 0x1e, 0x62, 0x52, 0xd9, 0x14, 0xbc, 0x03, 0xc3, 0xb0,
0xa5, 0xfd, 0xb7, 0x27, 0xde, 0xb1, 0x6f, 0x1b, 0x7c, 0x72, 0x4a, 0xcd,
0x09, 0xe5, 0x82, 0x70, 0xd3, 0x9f, 0xb6, 0xd6, 0xa4, 0x6a, 0x2f, 0xc2,
0x32, 0xbd, 0xb5, 0x39, 0xe4, 0xea, 0xb9, 0x71, 0x1c, 0x70, 0x67, 0x21,
0x92, 0x21, 0xac, 0xf4, 0x9e, 0x63, 0xe8, 0x5e, 0x83, 0x02, 0xcc, 0x0c,
0xf8, 0xf8, 0x9e, 0x87, 0x89, 0xfc, 0x03, 0x85, 0xfa, 0xcc, 0x77, 0x07,
0x44, 0x5f, 0x4d, 0xe5, 0x19, 0xd3, 0x12, 0xee, 0xca, 0xe1, 0xe0, 0xbf,
0x1e, 0xbe, 0xe7, 0x12, 0x1f, 0x6a, 0x93, 0x1e, 0x38, 0x4b, 0xa7, 0x9f,
0x81, 0xa9, 0x77, 0x85, 0x0c, 0xc6, 0x39, 0x02, 0x55, 0xd2, 0x62, 0x56,
0x19, 0x85, 0xa6, 0x38, 0x85, 0xe1, 0x2d, 0x3c, 0x38, 0x3b, 0x5b, 0xa0,
0x24, 0x18, 0xe9, 0x29, 0x6c, 0x9f, 0xe4, 0x4d, 0x4e, 0x23, 0x5f, 0xb1,
0xe2, 0xa0, 0x6f, 0x97, 0xb2, 0x41, 0xd1, 0xea, 0xdb, 0xa7, 0x37, 0x81,
0xeb, 0x06, 0x8d, 0x77, 0xc2, 0x68, 0xfc, 0x5a, 0x65, 0x97, 0x33, 0x58,
0xa1, 0xb8, 0x35, 0x0f, 0xf4, 0x25, 0xbc, 0x3b, 0x4f, 0x18, 0x0f, 0x0e,
0x60, 0x25, 0x3d, 0xd8, 0x77, 0x1a, 0xd0, 0x8a, 0xb0, 0x61, 0x57, 0x16,
0x0b, 0x55, 0xf2, 0x58, 0xb9, 0x91, 0x52, 0x30, 0x33, 0xab, 0x29, 0x9b,
0x03, 0x62, 0xe5, 0xcc, 0xdf, 0x6e, 0x62, 0x86, 0x9d, 0x76, 0xe5, 0xdd,
0x6f, 0xca, 0x3e, 0x75, 0xd8, 0x88, 0x58, 0x06, 0x8d, 0xa4, 0x58, 0xf5,
0xaa, 0x7c, 0xce, 0x17, 0xdd, 0xde, 0xca, 0x0a, 0x72, 0x87, 0x6f, 0x29,
0x6c, 0x0c, 0xe9, 0xc0, 0x3d, 0x32, 0x2e, 0x55, 0xf3, 0xa7, 0x27, 0xda,
0xfc, 0x86, 0x0c, 0x9e, 0x33, 0x83, 0xb5, 0x47, 0xeb, 0xe8, 0xf6, 0xc9,
0xf4, 0x24, 0x72, 0xee, 0xaf, 0xf8, 0xb5, 0x59, 0x70, 0x06, 0x85, 0x71,
0xbb, 0x3c, 0xbe, 0xbb, 0x2c, 0x24, 0xad, 0x67, 0xba, 0x42, 0xb9, 0xee,
0x68, 0xec, 0x0b, 0xe6, 0x5b, 0x26, 0x0f, 0x2b, 0xb6, 0x3a, 0x93, 0x4f,
0x9f, 0xe6, 0x9f, 0xb9, 0x1a, 0xa0, 0xb9, 0x51, 0x1c, 0x8d, 0x66, 0x37,
0xd2, 0x50, 0xcc, 0xae, 0x10, 0x30, 0x16, 0x60, 0x56, 0x3b, 0x99, 0x0e,
0x90, 0x7b, 0x28, 0xde, 0x93, 0xf4, 0x16, 0x87, 0x1f, 0xd0, 0x9b, 0xc2,
0x33, 0x42, 0x2c, 0x2c, 0xf1, 0x36, 0xc3, 0x39, 0xf8, 0x4f, 0xa4, 0x1e,
0x00, 0x43, 0xb1, 0xac, 0xdf, 0x08, 0xbb, 0xfe, 0x5e, 0x2a, 0xdc, 0x2a,
0x10, 0xf3, 0x7b, 0xc5, 0x2f, 0x96, 0xc9, 0x1d, 0x51, 0x4f, 0xc0, 0xde,
0x6e, 0x93, 0x9a, 0x35, 0x19, 0xb8, 0x58, 0xb5, 0x19, 0xba, 0xaf, 0x2a,
0xb1, 0xb5, 0xb2, 0xff, 0xc1, 0x89, 0xbc, 0x3f, 0xd8, 0x8f, 0x34, 0x07,
0x63, 0x60, 0xa5, 0xed, 0xdb, 0xff, 0x9e, 0xf5, 0x5b, 0x23, 0xc0, 0x1b,
0x13, 0x96, 0xd4, 0x2f, 0x07, 0x51, 0x1b, 0xac, 0x90, 0x72, 0x71, 0x28,
0x65, 0x98, 0xe1, 0xff, 0x6a, 0x9d, 0xe7, 0x30, 0x6d, 0xb1, 0x2c, 0x21,
0xfa, 0xcb, 0xbc, 0x6a, 0x3c, 0x25, 0xe8, 0x50, 0x5c, 0x53, 0xd8, 0xd5,
0xcb, 0xa2, 0x53, 0x53, 0xa5, 0x64, 0x3f, 0x78, 0x61, 0x77, 0x1d, 0x8d,
0x16, 0xe4, 0xe4, 0xa1, 0x32, 0x9c, 0x00, 0x52, 0x5f, 0x2a, 0xd7, 0xf5,
0x3c, 0xfd, 0x09, 0xd7, 0x1b, 0x3b, 0x99, 0x01, 0x4d, 0xdc, 0x91, 0xe4,
0x6d, 0xe8, 0x9e, 0xa3, 0x18, 0xad, 0x43, 0x27, 0xba, 0xc1, 0x5f, 0x37,
0xa6, 0x12, 0x61, 0xf5, 0x1c, 0x63, 0x0c, 0x25, 0x2d, 0x90, 0xf8, 0x52,
0xcb, 0x2c, 0x37, 0x4b, 0xde, 0x1e, 0x6c, 0x36, 0x1d, 0x47, 0xf5, 0xdf,
0x87, 0xca, 0x79, 0x98, 0x80, 0x09, 0x59, 0xd7, 0x14, 0xfd, 0xf7, 0xf9,
0xf4, 0xce, 0x69, 0x23, 0xd2, 0xf8, 0xc4, 0xee, 0xa0, 0x7e, 0xf8, 0x36,
0x8e, 0x35, 0x93, 0x45, 0x82, 0xae, 0x0d, 0xfc, 0x65, 0xbc, 0xaa, 0xf5,
0x58, 0xa9, 0x65, 0xba, 0xc6, 0x08, 0x4b, 0x63, 0xc3, 0x3f, 0xa6, 0x8a,
0xf4, 0xc1, 0x9b, 0x8f, 0x02, 0x45, 0x1b, 0x13, 0x78, 0x28, 0x9f, 0xd6,
0x53, 0xb1, 0xc2, 0x7e, 0x4e, 0x71, 0x17, 0xe7, 0x55, 0x09, 0x62, 0xc7,
0xad, 0xd5, 0x91, 0x1a, 0xc0, 0xfa, 0x49, 0x4a, 0xef, 0x00, 0xd6, 0xf6,
0xf1, 0xd0, 0xc9, 0x40, 0x1b, 0xb1, 0xfd, 0x0e, 0xd3, 0x95, 0xf1, 0xcd,
0x95, 0x60, 0x08, 0x73, 0xd2, 0xe0, 0x56, 0xfa, 0xd0, 0x65, 0x51, 0xfd,
0xc4, 0x48, 0xd1, 0xaa, 0x5a, 0xba, 0xcb, 0x8f, 0x76, 0x22, 0xe3, 0x60,
0x6f, 0x4a, 0x3c, 0x86, 0x35, 0xee, 0xe9, 0x88, 0x9a, 0x4a, 0x36, 0x34,
0x74, 0xe3, 0x6d, 0x3f, 0xe4, 0x2a, 0x93, 0x0b, 0xe2, 0xc6, 0x47, 0x4d,
0xf2, 0xb6, 0x8e, 0x78, 0x14, 0x91, 0x61, 0xcf, 0xfa, 0xb6, 0x1b, 0x39,
0xca, 0x88, 0x0c, 0x04, 0x65, 0xd3, 0x3b, 0xd1, 0xc6, 0xda, 0xe5, 0xf4,
0xe9, 0x1a, 0x38, 0x0f, 0xa5, 0xca, 0x32, 0x29, 0x78, 0x6c, 0x91, 0x9d,
0xd8, 0xc1, 0x8c, 0x3d, 0x6e, 0x82, 0x49, 0x10, 0x38, 0x4c, 0x95, 0xe3,
0xf1, 0x69, 0x30, 0x2e, 0x3e, 0xbf, 0xaf, 0x7d, 0x5e, 0x51, 0x3c, 0x6a,
0x15, 0x04, 0xbd, 0x8f, 0xcf, 0xeb, 0x3f, 0xe0, 0xe0, 0xa7, 0xb3, 0x3e,
0xf3, 0xf7, 0xd8, 0x1d, 0x15, 0x74, 0xef, 0x4e, 0x5b, 0xa0, 0x1e, 0x3a,
0x45, 0xec, 0x98, 0x8b, 0xe4, 0x0c, 0xfb, 0x77, 0xfd, 0xcf, 0xde, 0x88,
0x4d, 0x42, 0x18, 0x81, 0x14, 0x0d, 0xe2, 0x20, 0x4e, 0xcf, 0x0d, 0x3b,
0xc8, 0x41, 0x36, 0x9d, 0x99, 0xab, 0x47, 0xcb, 0x55, 0xf0, 0x79, 0x77,
0x32, 0x85, 0xa4, 0xe4, 0x11, 0x14, 0x42, 0x8d, 0x03, 0x8c, 0x76, 0xba,
0x05, 0xcf, 0xe8, 0x40, 0x47, 0xcf, 0xbd, 0xe7, 0x22, 0xe6, 0x72, 0xce,
0xa0, 0x13, 0xe4, 0x59, 0x5e, 0x68, 0xc2, 0x53, 0x7a, 0x4d, 0x4b, 0x4c,
0xcd, 0xbf, 0xe2, 0xb0, 0xa3, 0x63, 0x77, 0xf2, 0x1e, 0xc3, 0x21, 0xca,
0xd2, 0xb6, 0x7b, 0x01, 0x79, 0x02, 0x43, 0xec, 0x6d, 0x98, 0x97, 0x86,
0x27, 0x41, 0x67, 0xe7, 0x04, 0xcf, 0x71, 0x0e, 0xfc, 0xc8, 0x3d, 0x32,
0x99, 0x35, 0x4d, 0x2c, 0x94, 0xd7, 0x82, 0xb5, 0x2e, 0x20, 0x73, 0xd8,
0xa4, 0xf9, 0xae, 0x6c, 0xd6, 0x12, 0x57, 0xe9, 0x44, 0x86, 0x6a, 0x9e,
0xe0, 0x72, 0x84, 0x97, 0xb3, 0x8d, 0x56, 0x28, 0x66, 0xdb, 0xec, 0x25,
0xbf, 0x01, 0x11, 0x76, 0x9b, 0xe1, 0x43, 0x8d, 0x6d, 0x0b, 0xfa, 0x3d,
0x45, 0x15, 0x4a, 0xb4, 0xac, 0x76, 0x2a, 0x4a, 0xfb, 0x8d, 0xa5, 0x03,
0xe4, 0x36, 0xe6, 0xd9, 0xfd, 0xc1, 0x20, 0x63, 0xe3, 0x5c, 0x9a, 0x0e,
0x0f, 0x99, 0x49, 0xc6, 0x10, 0x9a, 0x08, 0x47, 0xff, 0x3d, 0xaa, 0x0c,
0x9f, 0x46, 0x57, 0x5a, 0xe5, 0xc5, 0x24, 0xc5, 0xf1, 0xca, 0x1a, 0xa2,
0xb0, 0x29, 0x78, 0xdd, 0x7a, 0x72, 0x49, 0x54, 0xac, 0xc4, 0x22, 0x04,
0x97, 0xa2, 0xa1, 0x1a, 0x2f, 0x57, 0xfd, 0x9b, 0xaf, 0xc9, 0x30, 0x10,
0x4a, 0xf4, 0x5e, 0x52, 0xf8, 0x25, 0x32, 0x48, 0xcb, 0x02, 0x6c, 0x3b,
0xa7, 0xe3, 0xbd, 0xe9, 0x54, 0xd5, 0xbe, 0x46, 0x6b, 0xea, 0x0b, 0x43,
0x13, 0x1d, 0x6f, 0x9c, 0xf5, 0xeb, 0x0e, 0xba, 0x28, 0x4f, 0x98, 0x84,
0xb2, 0x19, 0x9c, 0xfe, 0xa0, 0x4a, 0xf6, 0x07, 0xcc, 0x0c, 0x8f, 0x75,
0x6a, 0x16, 0xa1, 0x1c, 0x4e, 0x42, 0x51, 0xdc, 0x17, 0xb0, 0xa4, 0x2c,
0x86, 0x87, 0x55, 0xf5, 0x7a, 0x5a, 0xd0, 0x0d, 0x4b, 0x9f, 0xb9, 0xcb,
0xf3, 0x23, 0x5b, 0xaa, 0x81, 0x0e, 0x74, 0x56, 0x96, 0xbb, 0x65, 0x14,
0x3e, 0xb2, 0x17, 0x53, 0x7e, 0x71, 0xf1, 0x9b, 0xfd, 0x1c, 0x5c, 0xfe,
0xee, 0x6b, 0x58, 0xc7, 0xb5, 0x82, 0xed, 0x14, 0x47, 0xb0, 0x62, 0xe8,
0xad, 0x34, 0x9c, 0xe6, 0x12, 0x29, 0x3b, 0x91, 0x2b, 0x83, 0xe6, 0x5c,
0xd4, 0xf1, 0x5b, 0x7f, 0xe0, 0x58, 0xc8, 0x29, 0xa4, 0x17, 0x76, 0xa0,
0x95, 0x9d, 0xb1, 0xad, 0xa1, 0x01, 0xa2, 0xce, 0xd0, 0xa3, 0x14, 0x1e,
0xb7, 0x22, 0x98, 0x9d, 0xcd, 0x7f, 0x8c, 0xb8, 0x0f, 0x5b, 0x5b, 0x36,
0x3f, 0xce, 0xca, 0xce, 0x5b, 0x54, 0x8b, 0xbd, 0xde, 0x82, 0x7e, 0xf1,
0xf9, 0xa0, 0x30, 0xfe, 0xbd, 0xe7, 0x35, 0x84, 0x29, 0x1e, 0x41, 0x8e,
0x55, 0x3f, 0xf7, 0x40, 0x23, 0xaa, 0x2d, 0x5a, 0xe5, 0xc4, 0x32, 0x9e,
0xbf, 0x22, 0xb0, 0xc1, 0xe7, 0x8c, 0x7d, 0x5d, 0x0b, 0x28, 0xb4, 0x57,
0x8e, 0xe7, 0x56, 0x3d, 0x1f, 0x35, 0x1e, 0x98, 0xa9, 0x0d, 0xd7, 0xb7,
0x20, 0xe2, 0x89, 0x90, 0x04, 0xa7, 0x56, 0xea, 0x84, 0x16, 0x6f, 0xff,
0xa9, 0x38, 0x5e, 0xa0, 0xaf, 0x2d, 0xc1, 0xb6, 0xc1, 0x77, 0x72, 0xe1,
0x21, 0xc7, 0x2f, 0x3f, 0x85, 0x51, 0x4b, 0x83, 0xca, 0x33, 0x50, 0xb1,
0x4c, 0x58, 0x0c, 0x54, 0x7c, 0x70, 0xfe, 0x23, 0xef, 0xc7, 0xc7, 0xaf,
0xaf, 0xbf, 0xe5, 0x7b, 0x05, 0x90, 0x6c, 0x7a, 0x9f, 0x66, 0xb9, 0xc6,
0x44, 0xd5, 0x99, 0x6c, 0xd5, 0xac, 0x74, 0xce, 0x00, 0x49, 0x4b, 0xcf,
0x51, 0x01, 0xda, 0x24, 0xc5, 0x42, 0xba, 0x6f, 0x8a, 0x73, 0x20, 0x11,
0xbc, 0x4a, 0x4f, 0xdb, 0xa6, 0x40, 0x27, 0xbc, 0x93, 0xa3, 0x30, 0xb2,
0xcc, 0x6e, 0x78, 0xa0, 0x28, 0x7d, 0xe7, 0x34, 0x11, 0x4c, 0x00, 0x8b,
0x04, 0x3d, 0x93, 0x7f, 0x2a, 0x3c, 0x67, 0x56, 0xad, 0xc5, 0xdd, 0x2a,
0x75, 0xe1, 0x96, 0x02, 0x8d, 0x66, 0x0e, 0xd8, 0xc1, 0x83, 0xdf, 0x27,
0x42, 0xc4, 0x47, 0x18, 0x24, 0xac, 0x99, 0x8b, 0x22, 0x28, 0x68, 0x74,
0xb2, 0x7e, 0x58, 0x19, 0x19, 0xda, 0xd4, 0x96, 0x36, 0x26, 0xc7, 0x53,
0x37, 0xdb, 0x53, 0xa5, 0xd3, 0x98, 0xb4, 0x65, 0x80, 0xde, 0x73, 0xcb,
0x97, 0x7e, 0x59, 0x80, 0xf6, 0x25, 0x60, 0x6f, 0x77, 0x20, 0x4c, 0xc7,
0x35, 0xc6, 0x80, 0xe3, 0x56, 0x2c, 0xba, 0x62, 0xf7, 0x56, 0xf9, 0x63,
0x3e, 0xf9, 0x91, 0x7b, 0x9c, 0x35, 0x02, 0x04, 0xd8, 0x3d, 0x35, 0xfd,
0xb7, 0x85, 0xba, 0x04, 0x19, 0x7f, 0xb9, 0xe6, 0x6a, 0x65, 0x51, 0x9e,
0xde, 0x21, 0xec, 0xf0, 0x6b, 0xfd, 0x41, 0x90, 0xdc, 0x32, 0x08, 0x4d,
0x9b, 0x43, 0x2a, 0x61, 0x5b, 0x35, 0x61, 0xc1, 0xfd, 0xa2, 0xde, 0x30,
0xd3, 0x93, 0xc6, 0x0d, 0xad, 0x76, 0xac, 0xfb, 0xb0, 0xee, 0x85, 0x5f,
0xde, 0x4e, 0x2b, 0xe8, 0x8f, 0x67, 0xa0, 0x12, 0x00, 0x3f, 0xcf, 0x04,
0xe4, 0xb1, 0x2b, 0xa0, 0xda, 0xbb, 0x33, 0x5a, 0x58, 0x9b, 0x7c, 0x05,
0xea, 0x2b, 0x7b, 0x40, 0x9c, 0xc3, 0xe0, 0x99, 0x9e, 0xe0, 0x91, 0x67,
0xa5, 0x63, 0x6b, 0x9f, 0x15, 0xb6, 0x3c, 0xda, 0x17, 0x90, 0x8f, 0x05,
0x7e, 0x61, 0x7c, 0xc7, 0x25, 0xdf, 0xbb, 0xd6, 0x96, 0xba, 0x45, 0xa8,
0x84, 0xa0, 0x7d, 0x0f, 0x41, 0xdd, 0xba, 0xe5, 0x5a, 0x09, 0x3d, 0xe7,
0x20, 0x22, 0xc6, 0x8e, 0x0d, 0xd5, 0xc5, 0x75, 0x38, 0x8c, 0x6e, 0x4f,
0xa0, 0x42, 0xf7, 0x5e, 0xb1, 0x35, 0xe5, 0xfc, 0x93, 0x13, 0x58, 0x2b,
0xa7, 0xe0, 0xfe, 0xff, 0x1a, 0xdd, 0x30, 0x27, 0x9e, 0x69, 0xdd, 0x05,
0x18, 0xf7, 0x23, 0x5d, 0x9c, 0x64, 0xbe, 0x47, 0xf0, 0xa8, 0xe1, 0xf5,
0xde, 0x67, 0x8a, 0xcc, 0x18, 0xed, 0x4a, 0x76, 0xa0, 0x23, 0x96, 0x55,
0xd0, 0x84, 0x22, 0xce, 0xe1, 0xe2, 0x11, 0x80, 0x95, 0x61, 0x0d, 0x75,
0x12, 0x86, 0xb9, 0x3c, 0x10, 0x9d, 0x4d, 0x39, 0x93, 0x42, 0x7d, 0x83,
0xa5, 0xf4, 0xe4, 0xaa, 0x9b, 0x59, 0x22, 0x5e, 0xd3, 0xfd, 0xad, 0xf9,
0xa0, 0xf2, 0xb2, 0x70, 0x86, 0x29, 0xcd, 0x71, 0x61, 0x98, 0xb8, 0x21,
0x15, 0x5d, 0xf5, 0xde, 0x4d, 0x65, 0x27, 0x09, 0x8c, 0xed, 0xd0, 0xc8,
0xe7, 0xed, 0x0b, 0x0c, 0x13, 0x9e, 0x78, 0xea, 0xf8, 0x3c, 0x10, 0xda,
0xcd, 0xfc, 0xaf, 0x33, 0x96, 0x62, 0x31, 0x9c, 0xb6, 0x9d, 0xc8, 0x7a,
0x35, 0xe6, 0xff, 0x75, 0xa8, 0x30, 0x98, 0xd4, 0xaa, 0xcf, 0x9c, 0xef,
0xda, 0xb9, 0x64, 0xe8, 0x3b, 0xa6, 0x2f, 0xc1, 0xbd, 0x7e, 0x6b, 0xfc,
0x1a, 0xef, 0x62, 0xad, 0x90, 0x5e, 0x7d, 0x29, 0x12, 0x4d, 0x76, 0x86,
0x5c, 0x29, 0x7c, 0x61, 0x1d, 0x1e, 0x63, 0x97, 0x21, 0xcd, 0x77, 0xbd,
0xc2, 0x32, 0x45, 0xca, 0x7a, 0xdc, 0x0b, 0x16, 0xa4, 0x10, 0xac, 0x37,
0xba, 0xf5, 0xf6, 0xbc, 0x26, 0x66, 0x67, 0x2b, 0xb8, 0x2e, 0x22, 0xc0,
0xea, 0x90, 0x78, 0xf0, 0x0d, 0x0f, 0x80, 0x69, 0x60, 0xd2, 0x89, 0xa5,
0x1a, 0xb0, 0xcf, 0x5e, 0x57, 0x6f, 0x79, 0xdc, 0xd8, 0x2c, 0x51, 0x92,
0xd6, 0x62, 0x41, 0xf9, 0xf7, 0x26, 0xf0, 0x59, 0x93, 0xe2, 0x76, 0x82,
0x21, 0xf6, 0xab, 0x7a, 0xd2, 0x7b, 0x81, 0xcb, 0x8c, 0xe8, 0x87, 0x77,
0x76, 0xce, 0xf2, 0xaa, 0x00, 0xdc, 0xec, 0xd1, 0xc1, 0x8d, 0xf8, 0x42,
0x41, 0x8c, 0x35, 0xd1, 0x70, 0x97, 0xf4, 0x82, 0x2f, 0x3a, 0x2f, 0x4a,
0x18, 0x8f, 0xac, 0x41, 0xfa, 0x29, 0xc2, 0x9d, 0x0a, 0xfa, 0x0c, 0x44,
0xdd, 0xea, 0xc6, 0x2b, 0xd3, 0x2e, 0x28, 0xee, 0xca, 0x6e, 0x84, 0x90,
0xec, 0xaf, 0xf4, 0x8f, 0xbd, 0xc7, 0xd1, 0x2d, 0xf6, 0x9a, 0xd2, 0x00,
0xaa, 0x5c, 0x38, 0xc5, 0x11, 0x43, 0x7c, 0xf4, 0x0d, 0xbd, 0x57, 0x6d,
0x42, 0x62, 0xa5, 0xd8, 0x05, 0xa7, 0xe9, 0x30, 0xc0, 0x81, 0x9b, 0xfc,
0x30, 0xda, 0x16, 0x2f, 0x54, 0x61, 0x08, 0xaa, 0xf7, 0xc0, 0x1e, 0x4d,
0xf2, 0xd4, 0xed, 0x5c, 0x96, 0x30, 0xad, 0x9f, 0xc5, 0xe3, 0xf0, 0x91,
0xff, 0xf0, 0xb1, 0xe4, 0x93, 0x7b, 0x67, 0x11, 0xba, 0xef, 0xb7, 0xf4,
0x29, 0x93, 0x6d, 0x32, 0x1f, 0x88, 0xd1, 0x6c, 0x7c, 0x5a, 0x7e, 0x0a,
0xef, 0x6a, 0xe9, 0x23, 0x2c, 0xde, 0x4c, 0x68, 0x36, 0xcb, 0xaa, 0x1f,
0xd3, 0x71, 0xce, 0x31, 0x8b, 0x2b, 0x51, 0x16, 0xe6, 0x65, 0xd1, 0x30,
0xaf, 0xb8, 0xbe, 0x02, 0x21, 0x61, 0x36, 0xbc, 0x19, 0x7c, 0x0e, 0x9d,
0x9c, 0xd6, 0xa9, 0xc7, 0x5c, 0x2f, 0xb6, 0x23, 0x4b, 0x64, 0x3b, 0x99,
0x74, 0x83, 0x51, 0xda, 0x3e, 0xf8, 0xcf, 0x0f, 0xa3, 0x7a, 0xfb, 0xaa,
0xd1, 0xe2, 0x09, 0x05, 0x3a, 0xf5, 0xa8, 0x61, 0x51, 0x59, 0xf6, 0xb3,
0x3d, 0xe9, 0xa3, 0xc7, 0x3a, 0xe6, 0xff, 0x2d, 0x96, 0xaf, 0xe4, 0x41,
0xb8, 0x7d, 0xca, 0xdf, 0x42, 0x16, 0x5c, 0xee, 0xd0, 0x9d, 0xa3, 0x74,
0xa9, 0xae, 0xfd, 0x6d, 0x3b, 0x15, 0xb9, 0x89, 0x19, 0xa8, 0xf8, 0x48,
0xfe, 0x3a, 0xf6, 0xd7, 0x44, 0x4b, 0x96, 0x07, 0x37, 0x4b, 0xf9, 0x33,
0x62, 0x4f, 0x08, 0x38, 0xfc, 0x02, 0xfc, 0x8d, 0x3d, 0x65, 0x83, 0x02,
0xed, 0xd7, 0x48, 0x40, 0x51, 0x99, 0x0a, 0x20, 0xb2, 0xda, 0x9d, 0xca,
0xbf, 0xb7, 0xcf, 0xa8, 0x32, 0x67, 0x2f, 0x31, 0xa3, 0x00, 0xe3, 0xcb,
0x09, 0x7e, 0x0a, 0xb0, 0x7a, 0x34, 0x7b, 0xfc, 0x1d, 0x97, 0x8c, 0xa6,
0x17, 0xcb, 0x62, 0xc7, 0x28, 0xf4, 0xb8, 0x21, 0xdb, 0x51, 0xc9, 0xef,
0x69, 0xb6, 0xac, 0x36, 0x90, 0x74, 0x90, 0xb7, 0xdb, 0xcb, 0xfd, 0xdb,
0x17, 0x81, 0xed, 0x94, 0x4d, 0xe5, 0x4e, 0xe5, 0xf6, 0x01, 0x4a, 0x99,
0x9f, 0x5e, 0xe0, 0x45, 0x70, 0x41, 0x45, 0xa2, 0x2b, 0x4e, 0xd6, 0xab,
0xdc, 0x06, 0x15, 0x2d, 0x48, 0x88, 0x17, 0x43, 0x39, 0x94, 0xb4, 0x3a,
0x23, 0xce, 0xbb, 0xda, 0x0e, 0xb0, 0x5c, 0x1e, 0x0d, 0x0b, 0x31, 0x8e,
0x9b, 0x04, 0x80, 0x78, 0x75, 0x1c, 0x9b, 0x97, 0xac, 0xc7, 0xad, 0xde,
0x2b, 0x7f, 0x48, 0xb2, 0x29, 0xae, 0x76, 0x59, 0x27, 0xee, 0x79, 0xb8,
0x8e, 0x30, 0xe7, 0xf2, 0x84, 0x44, 0x40, 0x79, 0x25, 0xce, 0x13, 0x87,
0x8e, 0xfa, 0x08, 0x18, 0x8d, 0x71, 0xac, 0xeb, 0xf2, 0x7c, 0xa6, 0x69,
0x29, 0x1b, 0xd8, 0x02, 0xea, 0x64, 0x40, 0x7d, 0xa1, 0xb2, 0x05, 0xd3,
0x2b, 0x9d, 0x98, 0xa4, 0x2c, 0xee, 0xc9, 0x2c, 0x52, 0x5a, 0xd9, 0x3e,
0xd4, 0xcc, 0x6b, 0xf5, 0x11, 0x4a, 0x0a, 0x84, 0x4b, 0x6e, 0xa4, 0xab,
0x16, 0x46, 0x31, 0xb2, 0x84, 0x32, 0x43, 0x43, 0xe3, 0x21, 0x09, 0x33,
0x53, 0x9d, 0x93, 0x60, 0xd4, 0x18, 0xef, 0x71, 0xc8, 0xd1, 0x97, 0x2b,
0x2d, 0xa0, 0xe3, 0xc3, 0xb7, 0x54, 0x5b, 0xa2, 0xbf, 0x92, 0xa0, 0x48,
0x15, 0xef, 0x8e, 0x25, 0x02, 0x49, 0x35, 0x20, 0x9e, 0x1b, 0x52, 0xfa,
0xf9, 0x33, 0x99, 0x31, 0x2c, 0x1b, 0x04, 0x92, 0x8d, 0x19, 0xdb, 0x7d,
0xad, 0x61, 0x29, 0xe3, 0x5c, 0xb7, 0x94, 0xa6, 0x8b, 0x2e, 0xc5, 0x2e,
0xbd, 0xe0, 0x60, 0xae, 0xea, 0x93, 0x08, 0x64, 0x98, 0x9e, 0x8e, 0xa1,
0x2e, 0xf1, 0xe0, 0x31, 0x57, 0x87, 0xd4, 0x77, 0x81, 0x6d, 0xf5, 0xa6,
0x4c, 0x9b, 0x89, 0x8d, 0x08, 0x96, 0xc5, 0x96, 0xbe, 0x59, 0xcc, 0xbd,
0x58, 0x7b, 0x21, 0x08, 0x19, 0xc0, 0x55, 0x33, 0x80, 0x44, 0x0d, 0x8e,
0x59, 0xf9, 0xe8, 0x00, 0x50, 0x98, 0xa2, 0x30, 0xa6, 0xfd, 0xa8, 0x46,
0xc5, 0x05, 0x65, 0x59, 0xe7, 0x25, 0x1a, 0x17, 0x32, 0x8a, 0xc0, 0x2a,
0x15, 0x7e, 0x69, 0x11, 0xe9, 0x6d, 0xff, 0x96, 0x52, 0x98, 0xa3, 0xfa,
0x43, 0x7b, 0x33, 0x79, 0x56, 0xc4, 0xe3, 0x27, 0x40, 0xd6, 0x33, 0xea,
0xac, 0x87, 0x4e, 0x74, 0xbb, 0xe0, 0x52, 0xab, 0x56, 0x8a, 0xed, 0x3e,
0xd2, 0x25, 0xb2, 0xbe, 0x58, 0x4c, 0xdf, 0x0e, 0x8f, 0xca, 0x57, 0xdc,
0x00, 0xfa, 0xb0, 0xc0, 0xf3, 0x7b, 0x6e, 0x41, 0x17, 0x07, 0xcb, 0x08,
0xe3, 0xd8, 0xa5, 0x04, 0xdb, 0x42, 0x99, 0x67, 0x73, 0xd5, 0xd7, 0x1f,
0x22, 0x9e, 0xea, 0x66, 0x5f, 0x44, 0x7d, 0xf4, 0xbf, 0x50, 0xb2, 0x3e,
0x2f, 0x9f, 0x7a, 0xca, 0x80, 0x95, 0x59, 0x83, 0x69, 0x05, 0xec, 0x70,
0x71, 0x12, 0x97, 0xaf, 0xdb, 0xfd, 0xe8, 0x11, 0x44, 0x8a, 0x6e, 0x09,
0x90, 0xd5, 0x59, 0x8c, 0x6a, 0x65, 0xf9, 0xa9, 0x3d, 0x3c, 0x0c, 0xf3,
0x2f, 0xa0, 0xb1, 0x8e, 0xf0, 0x3f, 0x16, 0x63, 0xf6, 0xe8, 0x80, 0x27,
0x64, 0x56, 0x99, 0x94, 0x93, 0xc8, 0x36, 0x00, 0x21, 0xeb, 0x7c, 0x41,
0x86, 0xae, 0xb2, 0x4b, 0x7d, 0xac, 0xac, 0x90, 0x8b, 0x99, 0x18, 0x25,
0xa4, 0x0d, 0x9c, 0x96, 0x53, 0x0c, 0xfa, 0x7e, 0x61, 0xba, 0x7f, 0xca,
0x61, 0x7b, 0xba, 0x2f, 0x96, 0x2f, 0x75, 0x29, 0x84, 0xb7, 0x32, 0xca,
0x3b, 0x1f, 0xe6, 0x57, 0x34, 0xf3, 0xf1, 0x58, 0x61, 0xc9, 0x04, 0xa2,
0x20, 0xea, 0x77, 0xa7, 0x83, 0xed, 0x3e, 0x14, 0x87, 0x8f, 0x82, 0x86,
0x88, 0xc3, 0xf9, 0x10, 0x7e, 0x03, 0xa4, 0x33, 0xe0, 0x4e, 0x97, 0xef,
0x66, 0x91, 0x9f, 0xce, 0x85, 0xc8, 0xca, 0x04, 0x3a, 0x8b, 0xf6, 0xc7,
0xdf, 0xeb, 0x75, 0x31, 0xf4, 0x1a, 0x9a, 0x67, 0xc7, 0xb1, 0xd0, 0x33,
0x97, 0xea, 0xd2, 0x52, 0xc3, 0x81, 0xdb, 0x63, 0x64, 0x31, 0x0f, 0x9e,
0x75, 0x5f, 0xde, 0xe7, 0x46, 0x01, 0x19, 0x03, 0xe5, 0x0b, 0xf8, 0x9f,
0xab, 0x4f, 0x1a, 0x1f, 0xe0, 0xb0, 0x75, 0x96, 0xf2, 0x15, 0x49, 0x63,
0xa7, 0xae, 0x26, 0xe5, 0x41, 0x82, 0x1b, 0x1e, 0xd0, 0x8b, 0x2e, 0xcc,
0xf7, 0x30, 0xb3, 0xb5, 0x1b, 0xd9, 0xe7, 0x65, 0x1e, 0x60, 0x3b, 0x74,
0xfa, 0x52, 0x03, 0xe9, 0x0f, 0x45, 0x87, 0x8c, 0x1a, 0x4d, 0x0d, 0xb9,
0x90, 0xec, 0xa3, 0x59, 0xad, 0xa2, 0x33, 0xfb, 0xd3, 0xac, 0xf0, 0x58,
0x0c, 0x6f, 0x27, 0xa9, 0x1b, 0x18, 0xcb, 0x5d, 0x70, 0xcd, 0x14, 0xd9,
0xe3, 0x9f, 0x42, 0xf7, 0x82, 0x3e, 0x47, 0x39, 0xe4, 0xa2, 0x9e, 0x03,
0x7c, 0x2f, 0x5d, 0x18, 0x55, 0x20, 0x63, 0x68, 0x38, 0xc8, 0x0b, 0x3d,
0xf3, 0xc7, 0x91, 0x72, 0x70, 0x4c, 0x8a, 0x0d, 0xc0, 0x80, 0x7d, 0xde,
0xa3, 0x7f, 0x0a, 0x54, 0xb5, 0xd0, 0x49, 0x42, 0xc3, 0x27, 0x69, 0x19,
0x1c, 0xbc, 0xf9, 0x5e, 0x16, 0x19, 0xab, 0xdb, 0x99, 0x1e, 0x90, 0x8c,
0x6e, 0xb9, 0x17, 0x95, 0xad, 0xde, 0x70, 0x93, 0x7f, 0x5f, 0x26, 0xb0,
0x9f, 0x86, 0xb3, 0x82, 0x9d, 0x30, 0x24, 0x19, 0x83, 0x7d, 0x20, 0x70,
0x29, 0xe1, 0xb3, 0x22, 0x99, 0xb5, 0xef, 0x8f, 0x7a, 0x66, 0xbc, 0x86,
0x18, 0x85, 0x39, 0x56, 0x9b, 0x5f, 0xf6, 0x63, 0xc8, 0x24, 0xbc, 0x54,
0xc3, 0xc3, 0xa3, 0x27, 0xad, 0x80, 0xa9, 0x8f, 0x3b, 0x4b, 0xa0, 0x08,
0xcc, 0xf9, 0xde, 0x0b, 0x92, 0xa3, 0x26, 0x79, 0x42, 0xa2, 0xd0, 0x7c,
0xd4, 0x2e, 0x8f, 0x63, 0x4b, 0xaf, 0x6b, 0x7a, 0x58, 0x99, 0xb2, 0xb4,
0x01, 0x55, 0x75, 0x4a, 0xca, 0x9d, 0xd7, 0x85, 0xa8, 0x28, 0x97, 0x3d,
0xa6, 0x3c, 0xd1, 0xf6, 0x97, 0xd4, 0x15, 0x45, 0xc4, 0x25, 0x48, 0xd5,
0xa6, 0x10, 0x00, 0xa4, 0x3e, 0xc4, 0xb4, 0x1d, 0x08, 0xf0, 0xf7, 0x6d,
0x91, 0xc9, 0xc4, 0x4e, 0xb5, 0xd5, 0x45, 0x07, 0x3e, 0x05, 0x34, 0x44,
0x14, 0xe1, 0x11, 0x1e, 0xa2, 0xba, 0x37, 0x18, 0xea, 0x16, 0x78, 0x58,
0x83, 0xfd, 0x98, 0x42, 0xd3, 0x83, 0xac, 0x77, 0x65, 0xc9, 0x5b, 0x36,
0x8b, 0x9d, 0x76, 0x25, 0x5d, 0xfc, 0x80, 0x21, 0x0e, 0xd8, 0xcb, 0xc4,
0xcc, 0x59, 0x4e, 0x85, 0x51, 0x3b, 0xc0, 0xa8, 0x0b, 0x5d, 0x60, 0xa2,
0xc3, 0x2f, 0x2e, 0x8a, 0x18, 0x3c, 0x9d, 0x18, 0x0d, 0xd5, 0xa7, 0x32,
0x72, 0xf0, 0xef, 0xdf, 0xa4, 0x35, 0x09, 0x75, 0x2f, 0xb0, 0xe0, 0xec,
0xb2, 0x2d, 0x54, 0xeb, 0x22, 0x01, 0x67, 0x73, 0x61, 0x2d, 0x00, 0x8e,
0x2a, 0x59, 0xc5, 0xa0, 0xf1, 0xb4, 0x20, 0x15, 0xeb, 0xe5, 0x0b, 0x7d,
0x6b, 0x70, 0x45, 0x64, 0x3a, 0xc6, 0xbf, 0x34, 0x6a, 0x33, 0x35, 0xf2,
0x88, 0x47, 0x4d, 0x95, 0x3d, 0x76, 0x7c, 0x56, 0x7a, 0x6a, 0x72, 0x48,
0xa9, 0x28, 0x32, 0xf6, 0x25, 0xf5, 0x2a, 0x52, 0x40, 0x70, 0x46, 0x93,
0x4e, 0x86, 0x58, 0xde, 0x11, 0x66, 0x2f, 0xa6, 0x75, 0xbd, 0x24, 0x05,
0x3c, 0x5e, 0xf4, 0xbc, 0x88, 0xda, 0x69, 0xd0, 0x9d, 0x7f, 0xfa, 0x6b,
0xf4, 0x50, 0x51, 0x03, 0x26, 0xf6, 0xaa, 0x11, 0xa6, 0x3d, 0x2a, 0xa3,
0x18, 0x0e, 0xb1, 0x0b, 0x8c, 0x5a, 0x3a, 0xc4, 0x14, 0xd3, 0x9b, 0xea,
0x2f, 0xf9, 0x5f, 0xbc, 0x9a, 0x94, 0x92, 0x2b, 0xaa, 0xf7, 0x62, 0x0c,
0xf0, 0xf9, 0xcc, 0x20, 0x1b, 0x5b, 0x56, 0xed, 0xe4, 0x5f, 0xef, 0xa0,
0x5d, 0xe2, 0xe7, 0x50, 0x0d, 0x13, 0x92, 0x7f, 0x70, 0x68, 0x81, 0x3c,
0x5d, 0x71, 0x12, 0x14, 0xba, 0xe9, 0xf1, 0x24, 0x70, 0xc3, 0xea, 0x3a,
0x8e, 0x19, 0xab, 0x4f, 0x5f, 0x20, 0x38, 0xcb, 0xd8, 0x91, 0x3d, 0x47,
0x8a, 0xb8, 0xe0, 0x81, 0x73, 0x57, 0x19, 0xc4, 0xb6, 0xd7, 0x6e, 0x01,
0xad, 0xb7, 0x80, 0xb2, 0x44, 0xe7, 0x77, 0x3a, 0x55, 0x9f, 0x36, 0x77,
0x4c, 0x88, 0x69, 0x6b, 0xc6, 0x67, 0x2f, 0xbd, 0x37, 0x0c, 0xf2, 0x9f,
0x88, 0x6e, 0xa6, 0xa0, 0xd7, 0x5a, 0x53, 0xf3, 0xc0, 0xaa, 0x7b, 0xca,
0xc3, 0x07, 0xf4, 0x08, 0xc9, 0x84, 0x0c, 0x36, 0x49, 0x15, 0x71, 0x8c,
0x60, 0x6f, 0xd5, 0x91, 0xc5, 0x3a, 0x33, 0x3b, 0xde, 0x8c, 0xe0, 0xf4,
0x08, 0x42, 0x6d, 0xf7, 0x3b, 0xae, 0xd0, 0x06, 0xe5, 0x1b, 0x60, 0x24,
0xc4, 0xaa, 0xcf, 0x54, 0x0e, 0x78, 0xa6, 0xf9, 0x40, 0x3b, 0xca, 0xed,
0x5f, 0xa4, 0xd3, 0x13, 0x6e, 0x0a, 0x59, 0x3c, 0xda, 0xdb, 0xc6, 0x6f,
0x8f, 0x89, 0x31, 0x8c, 0x87, 0x1e, 0xfe, 0x01, 0x16, 0x5b, 0xac, 0x1a,
0x62, 0x85, 0x39, 0x61, 0xe1, 0x4c, 0xae, 0xae, 0x85, 0xd9, 0x5d, 0x9c,
0x2a, 0x6e, 0x6b, 0xec, 0xef, 0x2b, 0xc6, 0x32, 0xd6, 0x62, 0x7e, 0x46,
0x67, 0xe8, 0x6f, 0x4a, 0x50, 0x05, 0x75, 0xda, 0xe0, 0x6b, 0x47, 0xb6,
0x2a, 0x48, 0x56, 0x3e, 0x22, 0x18, 0xfb, 0xf5, 0x66, 0xf1, 0x42, 0xd6,
0xf3, 0x3d, 0x26, 0xc8, 0x44, 0xea, 0xa7, 0x9f, 0x90, 0xd8, 0x8f, 0xeb,
0x45, 0x50, 0x99, 0xf8, 0x86, 0x5f, 0x70, 0x03, 0x89, 0x06, 0x08, 0x92,
0x02, 0x6a, 0x93, 0x90, 0xce, 0xf2, 0xb5, 0x06, 0x78, 0x1e, 0x96, 0x1d,
0xa2, 0x20, 0x27, 0x90, 0xfc, 0x07, 0x50, 0x84, 0xf8, 0x19, 0xd0, 0xb1,
0x0c, 0x75, 0xb6, 0x3b, 0xb2, 0xaa, 0x73, 0x34, 0x49, 0xc9, 0xb2, 0xc2,
0x58, 0x7e, 0x40, 0x19, 0xa6, 0x08, 0x6b, 0x9e, 0x87, 0xce, 0x7a, 0x27,
0x3d, 0x7e, 0xe3, 0xe4, 0x12, 0x7c, 0x39, 0x24, 0x16, 0x80, 0x97, 0xbb,
0x94, 0x9e, 0xa6, 0x0f, 0x5f, 0x42, 0xa1, 0xca, 0x37, 0xa0, 0xbe, 0x1c,
0x4f, 0x62, 0x68, 0x6a, 0x50, 0x1e, 0x77, 0xe2, 0xb6, 0xdf, 0xa8, 0x89,
0xdf, 0x98, 0x9b, 0x80, 0xc2, 0x00, 0x21, 0x6a, 0xf6, 0x82, 0xb3, 0x5f,
0x8b, 0x98, 0x68, 0xe1, 0x76, 0xef, 0x06, 0x8c, 0x24, 0x07, 0xd2, 0xe5,
0x86, 0xc1, 0xc0, 0x26, 0x94, 0x2d, 0x96, 0xb1, 0xa4, 0x77, 0x11, 0xcb,
0xa9, 0xf9, 0x46, 0xe8, 0xfd, 0x91, 0x61, 0x9d, 0xce, 0xd1, 0x24, 0x27,
0xbb, 0xae, 0x68, 0x04, 0x44, 0xc9, 0x44, 0x69, 0x52, 0x05, 0x10, 0x4d,
0x96, 0x56, 0x98, 0x69, 0x46, 0x49, 0xc2, 0x75, 0xb9, 0xd8, 0x1c, 0x46,
0xdc, 0x71, 0x86, 0x71, 0x07, 0xea, 0x18, 0x5d, 0x7c, 0x3f, 0x81, 0x97,
0xfc, 0xc8, 0x88, 0xe4, 0xe7, 0x5e, 0xb2, 0xf8, 0x04, 0x17, 0x14, 0xcf,
0x24, 0x4c, 0x35, 0x1e, 0x0d, 0xba, 0xf6, 0x0d, 0x29, 0x1c, 0x3c, 0x5a,
0x0f, 0xd0, 0xf8, 0xf8, 0xdb, 0xa6, 0xa5, 0xf2, 0x83, 0x3d, 0xa0, 0x16,
0x5d, 0xf4, 0xb7, 0xc0, 0xc5, 0xf1, 0x0f, 0x09, 0x7d, 0x6a, 0x24, 0xf0,
0x94, 0x03, 0x7d, 0xc0, 0x96, 0x61, 0xa7, 0x44, 0xe2, 0xa3, 0x40, 0xa5,
0x00, 0x06, 0x13, 0x45, 0xba, 0x60, 0xc3, 0x15, 0x75, 0x6a, 0xe6, 0xd9,
0x21, 0x37, 0x15, 0x80, 0xfd, 0x68, 0xdf, 0xab, 0x9f, 0xde, 0xcf, 0x4a,
0x98, 0xf8, 0xa9, 0x27, 0xd3, 0x2d, 0x3d, 0x5c, 0xdc, 0xff, 0x8c, 0x61,
0x4d, 0x25, 0xc8, 0xdf, 0x66, 0xf6, 0xde, 0xf0, 0x21, 0x5a, 0x27, 0x36,
0x38, 0x1f, 0xfe, 0x89, 0x33, 0x52, 0x4e, 0x99, 0x55, 0x9b, 0xd0, 0x4f,
0x15, 0xba, 0x91, 0xdd, 0x95, 0xeb, 0x57, 0x18, 0xc4, 0x21, 0x86, 0x24,
0x67, 0x38, 0xf0, 0x2f, 0xd2, 0x66, 0x0b, 0x92, 0xb9, 0xc3, 0xcb, 0x8e,
0x7f, 0x6c, 0x44, 0xbc, 0xcb, 0x45, 0x71, 0x51, 0x61, 0x35, 0xf2, 0x9f,
0xbf, 0xf2, 0x8f, 0x5a, 0xdb, 0xaa, 0x54, 0x20, 0x1d, 0x52, 0xce, 0x89,
0xd4, 0xe7, 0x79, 0x75, 0xa7, 0xff, 0x1f, 0x6a, 0xfd, 0xb9, 0x56, 0xee,
0xca, 0x2c, 0x9f, 0xf3, 0x6d, 0xdf, 0xce, 0x96, 0x0c, 0xaf, 0x2c, 0x2c,
0x7d, 0x35, 0x79, 0x5d, 0x43, 0xbb, 0x27, 0xaf, 0x07, 0x17, 0x9a, 0x67,
0xde, 0x3b, 0x35, 0xf1, 0xd9, 0x98, 0x92, 0xf8, 0x3d, 0x35, 0xf1, 0x25,
0xf8, 0x15, 0xcc, 0x6f, 0x49, 0x9e, 0xba, 0x52, 0xd8, 0x76, 0x71, 0x8d,
0x90, 0x2c, 0x73, 0x3f, 0xef, 0xa2, 0xef, 0x43, 0x19, 0x2d, 0x83, 0xb9,
0xde, 0xc6, 0x33, 0x00, 0xd9, 0x9d, 0x50, 0x58, 0xa7, 0xaa, 0x07, 0xa6,
0x81, 0x8c, 0x1b, 0xe7, 0x9a, 0x3f, 0x11, 0x4c, 0xef, 0x96, 0x07, 0xb3,
0x48, 0x3e, 0x95, 0x2e, 0xb1, 0x27, 0x2d, 0xf9, 0x50, 0x49, 0x91, 0x7e,
0x91, 0xd2, 0xcc, 0xf0, 0x36, 0xe8, 0xcd, 0x69, 0x05, 0x68, 0x50, 0xe6,
0x4d, 0xbe, 0xd7, 0x55, 0xd5, 0xd2, 0xe4, 0x96, 0xd0, 0xa8, 0x1b, 0x4b,
0x28, 0x54, 0xcb, 0x95, 0x4c, 0xb5, 0xe7, 0x1c, 0x95, 0x2e, 0x11, 0xda,
0x30, 0x0e, 0x87, 0xfe, 0x5e, 0x34, 0x80, 0x59, 0x9d, 0x70, 0x09, 0x48,
0x9e, 0xe8, 0x31, 0x12, 0x3f, 0xe2, 0x07, 0x35, 0x74, 0x79, 0x43, 0x68,
0x42, 0x85, 0x09, 0x85, 0x42, 0x99, 0x5a, 0x92, 0x8c, 0xe9, 0x14, 0x6c,
0xf3, 0x06, 0x50, 0x2a, 0x6d, 0xd8, 0xd5, 0x06, 0xdc, 0x8c, 0x4d, 0x60,
0x84, 0x98, 0x6a, 0xf6, 0x30, 0xb9, 0x06, 0xe3, 0xcd, 0x75, 0xd7, 0xaa,
0xbc, 0x56, 0x8d, 0x2f, 0x6b, 0x0d, 0x2e, 0x26, 0x40, 0x86, 0x08, 0xf5,
0xc6, 0xee, 0x12, 0xd6, 0x06, 0x59, 0x7f, 0xa6, 0xac, 0x3f, 0xef, 0x15,
0xd6, 0x20, 0x55, 0x21, 0xa9, 0x29, 0xdb, 0xf4, 0x1f, 0xa6, 0x79, 0x3c,
0x13, 0xf0, 0x32, 0x7f, 0x25, 0x27, 0x7a, 0x64, 0xe1, 0x64, 0x3b, 0x86,
0x14, 0x4e, 0xfd, 0x29, 0xbc, 0x6e, 0x9f, 0x1b, 0xaa, 0xdf, 0xe3, 0x77,
0xd7, 0xb8, 0x7f, 0x61, 0x2f, 0xbc, 0xea, 0xfe, 0x18, 0xc6, 0x54, 0x91,
0x85, 0xaa, 0x55, 0xa7, 0xca, 0x00, 0x8f, 0x56, 0xaf, 0xa8, 0x49, 0x02,
0xcb, 0xbe, 0x20, 0x5a
};

View File

@ -36,7 +36,7 @@ _start:
bl CopyMem
@ Start ARM9 binary
ldr r0, =0x027FFE24
ldr r0, =0x02FFFE24
ldr r1, =_arm9_start
str r1, [r0]

View File

@ -25,7 +25,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARM7
# define ARM7
#endif
@ -44,31 +43,44 @@
#define NULL 0
#endif
#include "common.h"
#include "../../arm9/common/launcherData.h"
#include "read_card.h"
#include "tonccpy.h"
#include "crypto.h"
#include "f_xy.h"
#include "dsi.h"
#include "u128_math.h"
/*-------------------------------------------------------------------------
External functions
--------------------------------------------------------------------------*/
extern void arm7_clearmem (void* loc, size_t len);
extern void arm7_reset (void);
static bool useTwlCfg = false;
static int twlCfgLang = 0;
// static bool useShortInit = false;
volatile u16 useTwlCfg = 0;
volatile int twlCfgLang = 0;
// volatile bool useShortInit = false;
// ALIGN(4) char modcrypt_shared_key[8] = "Nintendo";
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Important things
#define NDS_HEADER 0x027FFE00
#define NDS_HEADER_POKEMON 0x027FF000
#define TWL_HEADER 0x027FE000
#define TMP_HEADER 0x027FC000
#define NDS_HEADER 0x02FFFE00
#define NDS_HEADER_POKEMON 0x02FFF000
#define TWL_HEADER 0x02FFE000
#define TMP_HEADER 0x02FFC000
tNDSHeader* ndsHeader;
tNDSHeader* tmpHeader;
tTWLHeader* twlHeader;
#define REG_GPIO_WIFI *(vu16*)0x4004C04
static u32 chipID;
// ALIGN(4) u32 chipID = 0;
// static void memset_addrs_arm7(u32 start, u32 end) { toncset((u32*)start, 0, ((int)end - (int)start)); }
static tNDSHeader* loadHeader(tDSiHeader* twlHeaderTemp) {
tNDSHeader* ntrHeader = (tNDSHeader*)NDS_HEADER;
@ -80,9 +92,22 @@ static tNDSHeader* loadHeader(tDSiHeader* twlHeaderTemp) {
return ntrHeader;
}
static void decrypt_modcrypt_area(dsi_context* ctx, u8 *buffer, unsigned int size) {
uint32_t len = size / 0x10;
u8 block[0x10];
while (len>0) {
toncset(block, 0, 0x10);
dsi_crypt_ctr_block(ctx, buffer, block);
tonccpy(buffer, block, 0x10);
buffer+=0x10;
len--;
}
}
static void NDSTouchscreenMode(void) {
bool specialSetting = false;
u16 specialSetting = 0;
u8 volLevel;
static const char list[][4] = {
@ -146,12 +171,12 @@ static void NDSTouchscreenMode(void) {
for (unsigned int i = 0; i < sizeof(list) / sizeof(list[0]); i++) {
if (memcmp(ndsHeader->gameCode, list[i], 3) == 0) {
// Found a match.
specialSetting = true; // Special setting (when found special gamecode)
specialSetting = 0xFFFF; // Special setting (when found special gamecode)
break;
}
}
if (specialSetting) {
if (specialSetting > 0) {
// special setting (when found special gamecode)
volLevel = 0xAC;
} else {
@ -318,9 +343,9 @@ const char* getRomTid(const tNDSHeader* ndsHeader) {
return romTid;
}
static void errorOutput (u32 code, bool isError) {
ALIGN(4) static void errorOutput (u16 code, u16 isError) {
arm9_errorCode = code;
if (isError) {
if (isError > 0) {
ipcSendState(ARM7_ERR);
while(1); // Stop
}
@ -369,16 +394,16 @@ static void arm7_readFirmware(tNDSHeader* ndsHeader) {
tonccpy(PersonalData, currentSettings, sizeof(PERSONAL_DATA));
if (useTwlCfg && (language == 0xFF)) { language = twlCfgLang; }
if ((useTwlCfg > 0) && (language == 0xFF)) { language = twlCfgLang; }
if (language >= 0 && language <= 7) {
if ((language != 0) && (language <= 7)) {
// Change language
personalData->language = language; //*(u8*)((u32)ndsHeader - 0x11C) = language;
personalData->language = (unsigned int)language; //*(u8*)((u32)ndsHeader - 0x11C) = language;
}
if (personalData->language != 6 && ndsHeader->reserved1[8] == 0x80) {
if ((unsigned int)personalData->language != 6 && ndsHeader->reserved1[8] == 0x80) {
ndsHeader->reserved1[8] = 0; // Patch iQue game to be region-free
ndsHeader->headerCRC16 = swiCRC16(0xFFFF, ndsHeader, 0x15E); // Fix CRC
ndsHeader->headerCRC16 = swiCRC16(0xFFFF, ndsHeader, 0x015E); // Fix CRC
}
}
@ -393,6 +418,7 @@ static void arm7_resetMemory (void) {
SCHANNEL_SOURCE(i) = 0;
SCHANNEL_LENGTH(i) = 0;
}
REG_SOUNDCNT = 0;
// Clear out ARM7 DMA channels and timers
@ -411,7 +437,7 @@ static void arm7_resetMemory (void) {
REG_IPC_FIFO_CR = 0;
// clear IWRAM - 037F:8000 to 0380:FFFF, total 96KiB
arm7_clearmem ((void*)0x037F8000, 96*1024);
// arm7_clearmem ((void*)0x037F8000, 96*1024);
// clear most of EXRAM - except after 0x022FD800, which has the ARM9 code
// Skip 0x0200000 region if fastBoot enabled. (cart header copy stored here)
@ -420,24 +446,100 @@ static void arm7_resetMemory (void) {
} else {
arm7_clearmem ((void*)0x02000000, 0x002FD800);
}*/
arm7_clearmem ((void*)0x02000000, 0x002FD800);
// arm7_clearmem ((void*)0x02000000, 0x002FD000);
// clear last part of EXRAM, skipping the ARM9's section
arm7_clearmem ((void*)0x023FE000, 0x2000);
// arm7_clearmem ((void*)0x023FF800, 0x800);
// Clear tmp header region previously used by custom struct
arm7_clearmem ((void*)TMP_HEADER, 0x160);
// arm7_clearmem ((void*)TMP_HEADER, 0x160);
/*if ((REG_SNDEXTCNT != 0) && (REG_SCFG_EXT & BIT(31)) && (REG_SCFG_ROM != 0x703)) {
memset_addrs_arm7(0x03000000, 0x0380FFC0);
memset_addrs_arm7(0x0380FFD0, 0x03800000 + 0x10000);
} else {
memset_addrs_arm7(0x03800000 - 0x8000, 0x03800000 + 0x10000);
}*/
// memset_addrs_arm7(0x03000000, 0x0380FFC0);
// memset_addrs_arm7(0x0380FFD0, 0x03800000 + 0x10000);
arm7_clearmem((void*)0x03000000, 0x80FFC0);
arm7_clearmem((void*)0x0380FFD0, 0x30);
// clear most of EXRAM
arm7_clearmem((void*)0x02000000, 0x3FD000); // clear more of EXRAM, skipping the arm9 temp area used by bootloader
// memset_addrs_arm7(0x02000000, 0x023FD000); // clear more of EXRAM, skipping the arm9 temp area used by bootloader
// memset_addrs_arm7(0x023FD000, 0x023FD7BC); // Leave eMMC CID Mirror intact
// memset_addrs_arm7(0x023FD7CC, 0x02400000);
arm7_clearmem((void*)0x023FE000, 0x2000);
if (twlRAM > 0) {
arm7_clearmem((void*)0x02FFE000, 0x2000);
// memset_addrs_arm7(0x02400000, 0x02800000); // Clear the rest of EXRAM
// clear last part of EXRAM
// memset_addrs_arm7(0x02800000, 0x02FFD000); // Leave arm9 temp area intact (used by bootloader)
// memset_addrs_arm7(0x02FFD000, 0x02FFD7BC); // Leave eMMC CID intact
// memset_addrs_arm7(0x02FFD7CC, 0x03000000);
// memset_addrs_arm7(0x02FFE000, 0x03000000);
}
REG_IE = 0;
REG_IF = ~0;
REG_AUXIE = 0;
REG_AUXIF = ~0;
REG_POWERCNT = 1; //turn off power to stuffs
(*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version
(*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version
}
static void setMemoryAddress(const tNDSHeader* ndsHeader) {
if (ndsHeader->unitCode > 0) {
static void setMemoryAddress(const tNDSHeader* ndsHeader, u32 ChipID) {
if (ndsHeader->unitCode & BIT(1)) {
copyLoop((u32*)0x02FFFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header
*(u32*)(0x02FFA680) = 0x02FD4D80;
*(u32*)(0x02FFA684) = 0x00000000;
*(u32*)(0x02FFA688) = 0x00001980;
*(u32*)(0x02FFF00C) = 0x0000007F;
*(u32*)(0x02FFF010) = 0x550E25B8;
*(u32*)(0x02FFF014) = 0x02FF4000;
// Set region flag
if (strncmp(getRomTid(ndsHeader)+3, "J", 1) == 0) {
*(u8*)(0x02FFFD70) = 0;
} else if (strncmp(getRomTid(ndsHeader)+3, "E", 1) == 0) {
*(u8*)(0x02FFFD70) = 1;
} else if (strncmp(getRomTid(ndsHeader)+3, "P", 1) == 0) {
*(u8*)(0x02FFFD70) = 2;
} else if (strncmp(getRomTid(ndsHeader)+3, "U", 1) == 0) {
*(u8*)(0x02FFFD70) = 3;
} else if (strncmp(getRomTid(ndsHeader)+3, "C", 1) == 0) {
*(u8*)(0x02FFFD70) = 4;
} else if (strncmp(getRomTid(ndsHeader)+3, "K", 1) == 0) {
*(u8*)(0x02FFFD70) = 5;
}
}
// Set memory values expected by loaded NDS
// from NitroHax, thanks to Chism
*((u32*)0x02FFF800) = ChipID; // CurrentCardID
// *((u32*)0x02FFF804) = ChipID; // Command10CardID // This does not result in correct v
*((u16*)0x02FFF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x02FFF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x02FFF850) = 0x5835;
// Copies of above
*((u32*)0x02FFFC00) = ChipID; // CurrentCardID
// *((u32*)0x02FFFC04) = ChipID; // Command10CardID
*((u16*)0x02FFFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x02FFFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x02FFFC10) = 0x5835;
*((u16*)0x02FFFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr
}
static void setMemoryAddressTWL(const tNDSHeader* ndsHeader, u32 ChipID) {
if (ndsHeader->unitCode & BIT(1)) {
copyLoop((u32*)0x027FFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header
*(u32*)(0x027FA680) = 0x02FD4D80;
@ -466,23 +568,90 @@ static void setMemoryAddress(const tNDSHeader* ndsHeader) {
// Set memory values expected by loaded NDS
// from NitroHax, thanks to Chism
*((u32*)0x027FF800) = chipID; // CurrentCardID
*((u32*)0x027FF804) = chipID; // Command10CardID
*((u32*)0x027FF800) = ChipID; // CurrentCardID
// *((u32*)0x027FF804) = ChipID; // Command10CardID
*((u16*)0x027FF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x027FF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x027FF850) = 0x5835;
// Copies of above
*((u32*)0x027FFC00) = chipID; // CurrentCardID
*((u32*)0x027FFC04) = chipID; // Command10CardID
*((u32*)0x027FFC00) = ChipID; // CurrentCardID
// *((u32*)0x027FFC04) = ChipID; // Command10CardID
*((u16*)0x027FFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x027FFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x027FFC10) = 0x5835;
*((u16*)0x027FFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr
tonccpy((u32*)0x027FC000, (u32*)TMP_HEADER, 0x1000);
tonccpy((u32*)0x027FF000, (u32*)NDS_HEADER_POKEMON, 0x170);
tonccpy((u32*)0x027FFE00, (u32*)NDS_HEADER, 0x160);
tonccpy((u32*)0x027FE000, (u32*)TWL_HEADER, 0x1000);
tonccpy((u32*)0x027FF830, (u32*)0x02FFF830, 0x20);
tonccpy((u32*)0x027FFC80, (u32*)0x02FFFC80, 0x70);
tonccpy((u32*)0x027FFD80, (u32*)0x02FFFD80, 0x70);
}
static u32 arm7_loadBinary (void) {
u32 errorCode;
static void arm7_loadExtendedBinary(sNDSHeaderExt* ndsHeader) {
twlHeader = (tTWLHeader*)TWL_HEADER;
*(vu32*)REG_MBK1 = *(u32*)0x02FFE180;
*(vu32*)REG_MBK2 = *(u32*)0x02FFE184;
*(vu32*)REG_MBK3 = *(u32*)0x02FFE188;
*(vu32*)REG_MBK4 = *(u32*)0x02FFE18C;
*(vu32*)REG_MBK5 = *(u32*)0x02FFE190;
REG_MBK6 = *(u32*)0x02FFE1A0;
REG_MBK7 = *(u32*)0x02FFE1A4;
REG_MBK8 = *(u32*)0x02FFE1A8;
REG_MBK9 = *(u32*)0x02FFE1AC;
/*REG_MBK9 = twlHeader->arm9MBKMaster;
REG_MBK6 = twlHeader->arm7MBK6;
REG_MBK7 = twlHeader->arm7MBK7;
REG_MBK8 = twlHeader->arm7MBK8;*/
cardRead(ndsHeader, twlHeader->arm9iromOffset, (u32*)twlHeader->arm9idestination, twlHeader->arm9ibinarySize);
cardRead(ndsHeader, twlHeader->arm7iromOffset, (u32*)twlHeader->arm7idestination, twlHeader->arm7ibinarySize);
if (twlHeader->twlHeaderSettings & BIT(1)) {
char modcrypt_shared_key[9] = { 'N', 'i', 'n', 't', 'e', 'n', 'd', 'o', '\0' };
int i;
u8 key[16];
u8 keyp[16];
for (i = 0; i < 16; i++) {
key[i] = 0;
keyp[i] = 0;
}
if (twlHeader->twlHeaderSettings & BIT(3)) {
// Debug Key
tonccpy(key, (u8*)twlHeader, 16);
} else {
u8 *target = (u8*)twlHeader;
tonccpy(keyp, modcrypt_shared_key, 8);
for (int i=0;i<4;i++) { keyp[8+i] = target[0x0c+i]; keyp[15-i] = target[0x0c+i]; }
tonccpy(key, target+0x350, 16);
u128_xor(key, keyp);
u128_add(key, DSi_KEY_MAGIC);
u128_lrot(key, 42);
}
u32 rk[4];
tonccpy(rk, key, 16);
dsi_context ctx;
dsi_set_key(&ctx, key);
dsi_set_ctr(&ctx, twlHeader->hmac_arm9);
if (twlHeader->modcrypt1Size != 0) { decrypt_modcrypt_area(&ctx, (u8*)twlHeader->arm9idestination, twlHeader->modcrypt1Size); }
dsi_set_key(&ctx, key);
dsi_set_ctr(&ctx, twlHeader->hmac_arm7);
if (twlHeader->modcrypt2Size != 0) { decrypt_modcrypt_area(&ctx, (u8*)twlHeader->arm7idestination, twlHeader->modcrypt2Size); }
}
}
static u16 arm7_loadBinary (void) {
u16 errorCode;
tDSiHeader* twlHeaderTemp = (tDSiHeader*)TMP_HEADER; // Use same region cheat engine goes. Cheat engine will replace this later when it's not needed.
// Init card
@ -493,14 +662,16 @@ static u32 arm7_loadBinary (void) {
errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, &chipID);
}*/
errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, &chipID);
errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, (u32*)InitialCartChipID);
if (errorCode)return errorCode;
ndsHeader = loadHeader(twlHeaderTemp); // copy twlHeaderTemp to ndsHeader location
cardRead(ndsHeader->arm9romOffset, (u32*)ndsHeader->arm9destination, ndsHeader->arm9binarySize);
cardRead(ndsHeader->arm7romOffset, (u32*)ndsHeader->arm7destination, ndsHeader->arm7binarySize);
cardRead((sNDSHeaderExt*)twlHeaderTemp, ndsHeader->arm9romOffset, (u32*)ndsHeader->arm9destination, ndsHeader->arm9binarySize);
cardRead((sNDSHeaderExt*)twlHeaderTemp, ndsHeader->arm7romOffset, (u32*)ndsHeader->arm7destination, ndsHeader->arm7binarySize);
if ((ndsHeader->unitCode & BIT(1)) && (twlMode > 0) && (twlRAM > 0))arm7_loadExtendedBinary((sNDSHeaderExt*)twlHeaderTemp);
// Fix Pokemon games needing header data.
copyLoop((u32*)NDS_HEADER_POKEMON, (u32*)NDS_HEADER, 0x170);
@ -524,7 +695,7 @@ static u32 arm7_loadBinary (void) {
// Main function
void arm7_main (void) {
u32 errorCode;
u16 errorCode;
// Synchronise start
while (ipcRecvState() != ARM9_START);
@ -533,54 +704,44 @@ void arm7_main (void) {
// Wait until ARM9 is ready
while (ipcRecvState() != ARM9_READY);
if (language != 0xFF)language = (int)launchData->language;
if (launchData->scfgUnlock > 0x00)scfgUnlock = true;
if (launchData->twlMode > 0x00)twlMode = true;
if (launchData->twlCLK > 0x00)twlCLK = true;
if (launchData->debugMode > 0x00)debugMode = true;
// if (launchData->fastBoot > 0x00)useShortInit = true;
if (twlMode) {
REG_MBK9=0x0300000F;
REG_MBK6=0x080037C0;
REG_MBK7=0x07C03740;
REG_MBK8=0x07403700;
} else {
if ((twlMode == 0) || (twlRAM == 0) || (isTWLSRL == 0)) {
REG_MBK9=0xFCFFFF0F;
REG_MBK6=0x09403900;
REG_MBK7=0x09803940;
REG_MBK8=0x09C03980;
}
errorOutput(ERR_STS_CLR_MEM, false);
errorOutput(ERR_STS_CLR_MEM, 0);
ipcSendState(ARM7_MEMCLR);
// Get ARM7 to clear RAM
arm7_resetMemory();
tmpHeader = (tNDSHeader*)TMP_HEADER;
if (!twlMode)REG_SCFG_ROM = 0x703;
if (twlMode == 0)REG_SCFG_ROM = 0x703;
errorOutput(ERR_STS_LOAD_BIN, false);
errorOutput(ERR_STS_LOAD_BIN, 0);
ipcSendState(ARM7_LOADBIN);
// Load the NDS file
errorCode = arm7_loadBinary();
if (errorCode)errorOutput(errorCode, true);
if (errorCode)errorOutput(errorCode, 0xFFFF);
errorOutput(ERR_STS_STARTBIN, false);
errorOutput(ERR_STS_STARTBIN, 0);
tonccpy((u32*)0x023FF000, (u32*)0x027FF000, 0x1000);
if (twlRAM == 0)tonccpy((u32*)0x023FF000, (u32*)0x02FFF000, 0x1000);
arm7_readFirmware(ndsHeader); // Header has to be loaded first
if (twlMode) {
REG_SCFG_EXT = 0x92FBFB06;
if (twlMode > 0) {
REG_SCFG_CLK = 0x187;
// REG_SCFG_ROM = 0x501;
// REG_SCFG_EXT = 0x92FBFB06;
// REG_SCFG_EXT = 0x9307F100;
REG_SCFG_EXT = 0x93FFFB06;
} else {
REG_SCFG_CLK = 0x107;
if (cdcReadReg(CDC_SOUND, 0x22) == 0xF0) {
// Switch touch mode to NTR
*(u16*)0x4004700 = 0x800F;
@ -588,19 +749,18 @@ void arm7_main (void) {
*(u16*)0x4000500 = 0x807F;
}
REG_GPIO_WIFI |= BIT(8); // Old NDS-Wifi mode
REG_SCFG_EXT = 0x92A00000;
REG_SCFG_EXT = 0x92A40000;
}
if (twlCLK) { REG_SCFG_CLK = 0x0187; } else { REG_SCFG_CLK = 0x0101; }
if (scfgUnlock) { REG_SCFG_EXT |= BIT(18); } else { REG_SCFG_EXT &= ~(1UL << 31); }
// if (twlCLK > 0) { REG_SCFG_CLK = 0x187; } else { REG_SCFG_CLK = 0x107; }
if (scfgUnlock == 0)REG_SCFG_EXT &= ~(1UL << 31); /// REG_SCFG_EXT |= BIT(18);
setMemoryAddress(ndsHeader);
setMemoryAddress(ndsHeader, *(u32*)InitialCartChipID);
if ((twlRAM > 0) && ((twlMode == 0) || (isTWLSRL == 0)))setMemoryAddressTWL(ndsHeader, *(u32*)InitialCartChipID);
ipcSendState(ARM7_BOOTBIN);
// Moved here to prevent interfering with arm9main's new console
REG_POWERCNT = 1; //turn off power to stuffs
arm7_reset();
}

View File

@ -40,39 +40,41 @@
#include "common.h"
#include "miniconsole.h"
#define LAUNCH_DATA 0x020007F0
volatile int arm9_stateFlag = ARM9_BOOT;
volatile u32 arm9_errorCode = 0xFFFFFFFF;
volatile bool arm9_errorClearBG = false;
volatile bool consoleDebugMode = false;
volatile u32 arm9_BLANK_RAM = 0;
volatile u32 defaultFontPalSlot = 0;
#include "../../arm9/common/launcherData.h"
volatile tLauncherSettings* launchData = (tLauncherSettings*)LAUNCH_DATA;
volatile int language = -1;
volatile bool scfgUnlock = false;
volatile bool twlMode = false;
volatile bool twlCLK = false;
volatile bool TWLVRAM = false;
volatile bool debugMode = false;
volatile bool consoleInit = false;
ALIGN(4) volatile int arm9_stateFlag = ARM9_BOOT;
ALIGN(4) volatile u16 arm9_errorCode = 0xFFFF;
ALIGN(4) volatile u16 consoleDebugMode = 0;
ALIGN(4) volatile u32 arm9_BLANK_RAM = 0;
ALIGN(4) volatile u32 defaultFontPalSlot = 0;
ALIGN(4) volatile u32 arm9_cachedChipID = 0xFFFFFFFF;
static char TXT_STATUS[] = "STATUS: ";
static char TXT_ERROR[] = "ERROR: ";
static char ERRTXT_NONE[] = "NONE";
static char ERRTXT_STS_CLRMEM[] = "CLEAR MEMORY";
static char ERRTXT_STS_LOAD_BIN[] = "LOAD CART";
static char ERRTXT_STS_STARTBIN[] = "START BINARY";
static char ERRTXT_STS_START[] = "BOOTLOADER STARTUP";
static char ERRTXT_LOAD_NORM[] = "LOAD NORMAL";
static char ERRTXT_LOAD_OTHR[] = "LOAD OTHER";
static char ERRTXT_SEC_NORM[] = "SECURE NORMAL";
static char ERRTXT_SEC_OTHR[] = "SECURE OTHER";
static char ERRTXT_LOGO_CRC[] = "LOGO CRC";
static char ERRTXT_HEAD_CRC[] = "HEADER CRC";
static char NEW_LINE[] = "\n";
ALIGN(4) volatile u16 language = 0xFFFF;
ALIGN(4) volatile u16 scfgUnlock = 0;
ALIGN(4) volatile u16 twlMode = 0;
ALIGN(4) volatile u16 twlCLK = 0;
ALIGN(4) volatile u16 isTWLSRL = 0;
// ALIGN(4) volatile u16 twlVRAM = 0;
ALIGN(4) volatile u16 twlRAM = 0;
ALIGN(4) volatile u16 debugMode = 0;
ALIGN(4) volatile u16 consoleInit = 0;
ALIGN(4) const u16 redFont = 0x801B;
ALIGN(4) const u16 greenFont = 0x8360;
ALIGN(4) char ERRTXT_NONE[14] = "\nSTATUS: NONE";
ALIGN(4) char ERRTXT_STS_START[22] = "\nSTATUS: LOADER START";
ALIGN(4) char ERRTXT_STS_CLRMEM[22] = "\nSTATUS: CLEAR MEMORY";
ALIGN(4) char ERRTXT_STS_LOAD_BIN[19] = "\nSTATUS: LOAD CART";
ALIGN(4) char ERRTXT_STS_STARTBIN[21] = "\nSTATUS: START BINARY";
ALIGN(4) char ERRTXT_LOAD_NORM[20] = "\nERROR: LOAD NORMAL";
ALIGN(4) char ERRTXT_LOAD_OTHR[19] = "\nERROR: LOAD OTHER";
ALIGN(4) char ERRTXT_SEC_NORM[22] = "\nERROR: SECURE NORMAL";
ALIGN(4) char ERRTXT_SEC_OTHR[21] = "\nERROR: SECURE OTHER";
ALIGN(4) char ERRTXT_HEAD_CRC[19] = "\nERROR: HEADER CRC";
/*-------------------------------------------------------------------------
External functions
@ -81,72 +83,58 @@ extern void arm9_clearCache (void);
extern void arm9_reset (void);
extern void Print(char *str);
static void waitForVBlank() { while (REG_VCOUNT!=191); while (REG_VCOUNT==191); }
/*-------------------------------------------------------------------------
arm9_errorOutput
Displays an error code on screen.
Each box is 2 bits, and left-to-right is most-significant bits to least.
Red = 00, Yellow = 01, Green = 10, Blue = 11
Written by Chishm
Displays an error text on screen.
Rewritten by Apache Thunder.
--------------------------------------------------------------------------*/
static void arm9_errorOutput (u32 code) {
Print(NEW_LINE);
static void arm9_errorOutput (u16 code) {
switch (code) {
case (ERR_NONE) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360;
Print(TXT_STATUS);
Print(ERRTXT_NONE);
case ERR_NONE: {
BG_PALETTE_SUB[defaultFontPalSlot] = greenFont;
Print((char*)ERRTXT_NONE);
} break;
case (ERR_STS_CLR_MEM) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360;
Print(TXT_STATUS);
Print(ERRTXT_STS_CLRMEM);
case ERR_STS_START: {
BG_PALETTE_SUB[defaultFontPalSlot] = greenFont;
Print((char*)ERRTXT_STS_START);
} break;
case (ERR_STS_LOAD_BIN) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360;
Print(TXT_STATUS);
Print(ERRTXT_STS_LOAD_BIN);
case ERR_STS_CLR_MEM: {
BG_PALETTE_SUB[defaultFontPalSlot] = greenFont;
Print((char*)ERRTXT_STS_CLRMEM);
} break;
case (ERR_STS_STARTBIN) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360;
Print(TXT_STATUS);
Print(ERRTXT_STS_STARTBIN);
case ERR_STS_LOAD_BIN: {
BG_PALETTE_SUB[defaultFontPalSlot] = greenFont;
Print((char*)ERRTXT_STS_LOAD_BIN);
} break;
case (ERR_STS_START) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360;
Print(TXT_STATUS);
Print(ERRTXT_STS_START);
case ERR_STS_STARTBIN: {
BG_PALETTE_SUB[defaultFontPalSlot] = greenFont;
Print((char*)ERRTXT_STS_STARTBIN);
} break;
case (ERR_LOAD_NORM) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B;
Print(TXT_ERROR);
Print(ERRTXT_LOAD_NORM);
case ERR_LOAD_NORM: {
BG_PALETTE_SUB[defaultFontPalSlot] = redFont;
Print((char*)ERRTXT_LOAD_NORM);
} break;
case (ERR_LOAD_OTHR) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B;
Print(TXT_ERROR);
Print(ERRTXT_LOAD_OTHR);
case ERR_LOAD_OTHR: {
BG_PALETTE_SUB[defaultFontPalSlot] = redFont;
Print((char*)ERRTXT_LOAD_OTHR);
} break;
case (ERR_SEC_NORM) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B;
Print(TXT_ERROR);
Print(ERRTXT_SEC_NORM);
case ERR_SEC_NORM: {
BG_PALETTE_SUB[defaultFontPalSlot] = redFont;
Print((char*)ERRTXT_SEC_NORM);
} break;
case (ERR_SEC_OTHR) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B;
Print(TXT_ERROR);
Print(ERRTXT_SEC_OTHR);
case ERR_SEC_OTHR: {
BG_PALETTE_SUB[defaultFontPalSlot] = redFont;
Print((char*)ERRTXT_SEC_OTHR);
} break;
case (ERR_LOGO_CRC) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B;
Print(TXT_ERROR);
Print(ERRTXT_LOGO_CRC);
case ERR_HEAD_CRC: {
BG_PALETTE_SUB[defaultFontPalSlot] = redFont;
Print((char*)ERRTXT_HEAD_CRC);
} break;
case (ERR_HEAD_CRC) : {
BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B;
Print(TXT_ERROR);
Print(ERRTXT_HEAD_CRC);
default: {
BG_PALETTE_SUB[defaultFontPalSlot] = greenFont;
Print((char*)ERR_NONE);
} break;
}
}
@ -159,26 +147,40 @@ Jumps to the ARM9 NDS binary in sync with the ARM7
Written by Darkain, modified by Chishm
--------------------------------------------------------------------------*/
void arm9_main (void) {
register int i;
language = 0xFFFF;
scfgUnlock = 0;
twlMode = 0;
twlCLK = 0;
// twlVRAM = 0;
twlRAM = 0;
isTWLSRL = 0;
debugMode = 0;
consoleInit = 0;
if (launchData->language != 0xFF)language = (u16)launchData->language;
if (launchData->scfgUnlock > 0)scfgUnlock = 0xFFFF;
if (launchData->twlMode > 0)twlMode = 0xFFFF;
// if (launchData->twlVRAM > 0)twlVRAM = 0xFFFF;
if (launchData->twlRAM > 0)twlRAM = 0xFFFF;
if (launchData->twlCLK > 0)twlCLK = 0xFFFF;
if (launchData->isTWLSRL > 0)isTWLSRL = 0xFFFF;
if (launchData->debugMode > 0)debugMode = 0xFFFF;
arm9_cachedChipID = launchData->cachedChipID;
if (launchData->language != 0xFF)language = (u8)launchData->language;
if (launchData->scfgUnlock == 0x01)scfgUnlock = true;
if (launchData->twlMode == 0x01)twlMode = true;
if (launchData->twlVRAM == 0x01)TWLVRAM = true;
if (launchData->twlCLK == 0x01)twlCLK = true;
if (launchData->debugMode == 0x01)debugMode = true;
if (twlMode) {
*((vu32*)REG_MBK1)=0x8D898581;
*((vu32*)REG_MBK2)=0x8C888480;
*((vu32*)REG_MBK3)=0x9C989490;
*((vu32*)REG_MBK4)=0x8C888480;
*((vu32*)REG_MBK5)=0x9C989490;
REG_MBK6=0x00000000;
REG_MBK7=0x07C03740;
REG_MBK8=0x07403700;
if ((isTWLSRL > 0) && (twlMode > 0) && (twlRAM > 0)) {
*(vu32*)REG_MBK1 = *(u32*)0x02FFE180;
*(vu32*)REG_MBK2 = *(u32*)0x02FFE184;
*(vu32*)REG_MBK3 = *(u32*)0x02FFE188;
*(vu32*)REG_MBK4 = *(u32*)0x02FFE18C;
*(vu32*)REG_MBK5 = *(u32*)0x02FFE190;
REG_MBK6 = *(u32*)0x02FFE194;
REG_MBK7 = *(u32*)0x02FFE198;
REG_MBK8 = *(u32*)0x02FFE19C;
REG_MBK9 = *(u32*)0x02FFE1AC;
WRAM_CR = *(u8*)0x02FFE1AF;
scfgUnlock = 0x01;
} else {
// MBK settings for NTR mode games
*((vu32*)REG_MBK1)=0x8D898581;
@ -200,7 +202,7 @@ void arm9_main (void) {
REG_IE = 0;
REG_IF = ~0;
if (debugMode)arm9_errorCode = ERR_STS_START;
if (debugMode > 0)arm9_errorCode = ERR_STS_START;
// Synchronise start
ipcSendState(ARM9_START);
@ -276,8 +278,8 @@ void arm9_main (void) {
}
arm9_errorOutput (arm9_errorCode);
// Halt after displaying error code
while(1);
} else if ((arm9_errorCode != ERR_NONE) && debugMode) {
while(1)waitForVBlank();
} else if ((arm9_errorCode != ERR_NONE) && debugMode > 0) {
if (!consoleInit) {
BG_PALETTE_SUB[0] = RGB15(31,31,31);
BG_PALETTE_SUB[255] = RGB15(0,0,0);
@ -285,13 +287,12 @@ void arm9_main (void) {
miniconsoleSetWindow(5, 11, 24, 1); // Set console position for debug text if/when needed.
consoleInit = true;
}
while(REG_VCOUNT!=191); // Add vblank delay. Arm7 can somtimes go through the status codes pretty quick.
while(REG_VCOUNT==191);
waitForVBlank();
arm9_errorOutput (arm9_errorCode);
arm9_errorCode = ERR_NONE;
}
}
VRAM_C_CR = 0x80;
// BG_PALETTE_SUB[0] = 0xFFFF;
dmaFill((void*)&arm9_BLANK_RAM, BG_PALETTE+1, (2*1024)-2);
@ -306,14 +307,16 @@ void arm9_main (void) {
videoSetModeSub(0);
REG_POWERCNT = 0x820F;
if (!twlCLK)REG_SCFG_CLK = 0x80;
if (twlMode) {
REG_SCFG_EXT = 0x82073100;
REG_SCFG_RST = 1;
/*if ((twlRAM > 0) && ((twlMode == 0) || (isTWLSRL == 0))) {
*((u32*)0x027FF800) = arm9_cachedChipID;
*((u32*)0x027FFC00) = arm9_cachedChipID;
}
if (!TWLVRAM)REG_SCFG_EXT &= ~(1UL << 13);
if (!scfgUnlock)REG_SCFG_EXT &= ~(1UL << 31);
*((u32*)0x02FFF800) = arm9_cachedChipID;
*((u32*)0x02FFFC00) = arm9_cachedChipID;*/
if (twlCLK == 0) { REG_SCFG_CLK = 0x80; } else { REG_SCFG_CLK = 0x87; };
if (scfgUnlock == 0)REG_SCFG_EXT &= ~(1UL << 31);
arm9_reset();
}

View File

@ -7,27 +7,18 @@
#include <nds/memory.h>
#include <nds/arm9/background.h>
static int windowX = 0;
static int windowY = 0;
static int windowWidth = 32;
static int windowHeight = 24;
static int consoleWidth = 32;
static int tabSize = 3;
static int cursorX = 0;
static int cursorY = 0;
static u16 fontCurPal = 1;
static u16* fontBgMap = BG_MAP_RAM_SUB(4);
int windowX = 0;
int windowY = 0;
int windowWidth = 32;
int windowHeight = 24;
int consoleWidth = 32;
int tabSize = 3;
int cursorX = 0;
int cursorY = 0;
u16 fontCurPal = 1;
u16* fontBgMap = BG_MAP_RAM_SUB(4);
static void miniconsoleSetWindow(int x, int y, int width, int height) {
windowX = x;
windowY = y;
windowWidth = width;
windowHeight = height;
cursorX = 0;
cursorY = 0;
}
void miniNewRow() {
static void miniNewRow() {
cursorY ++;
if(cursorY >= windowHeight) {
int rowCount;
@ -44,7 +35,7 @@ void miniNewRow() {
}
}
void miniconsolePrintChar(char c) {
static void miniconsolePrintChar(char c) {
if (c==0) return;
if(fontBgMap == 0) return;
if(cursorX >= windowWidth) { cursorX = 0; miniNewRow(); }
@ -76,7 +67,7 @@ void miniconsolePrintChar(char c) {
}
}
void miniconsoleCls(char mode) {
/*static void miniconsoleCls(char mode) {
int i = 0;
int colTemp,rowTemp;
@ -122,13 +113,22 @@ void miniconsoleCls(char mode) {
break;
}
}
}*/
void miniconsoleSetWindow(int x, int y, int width, int height) {
windowX = x;
windowY = y;
windowWidth = width;
windowHeight = height;
cursorX = 0;
cursorY = 0;
}
static void Print(char *str) {
void Print(char *str) {
if (str == 0)return;
while(*str)miniconsolePrintChar(*(str++));
}
#endif // MINICONSOLE_ARM9_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
/**
* \file aes.h
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_AES_H
#define POLARSSL_AES_H
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0800
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0810
/**
* \brief AES context structure
*/
typedef struct
{
int nr; /*!< number of rounds */
unsigned long *rk; /*!< AES round keys */
unsigned long buf[68]; /*!< unaligned data */
}
aes_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keysize must be 128, 192 or 256
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/
int aes_setkey_enc( aes_context *ctx, const unsigned char *key, int keysize );
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keysize must be 128, 192 or 256
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
*/
int aes_setkey_dec( aes_context *ctx, const unsigned char *key, int keysize );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int aes_crypt_ecb( aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
*/
int aes_crypt_cbc( aes_context *ctx,
int mode,
int length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int aes_crypt_cfb128( aes_context *ctx,
int mode,
int length,
int *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int aes_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* aes.h */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,761 @@
/**
* \file bignum.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_BIGNUM_H
#define MBEDTLS_BIGNUM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#include <stdint.h>
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
#endif
#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */
#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */
#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */
#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */
#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */
#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */
#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */
#define MBEDTLS_MPI_CHK(f) do { if ( ( ret = f ) != 0 ) goto cleanup; } while ( 0 )
/*
* Maximum size MPIs are allowed to grow to in number of limbs.
*/
#define MBEDTLS_MPI_MAX_LIMBS 10000
#if !defined(MBEDTLS_MPI_WINDOW_SIZE)
/*
* Maximum window size used for modular exponentiation. Default: 6
* Minimum value: 1. Maximum value: 6.
*
* Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
* for the sliding window calculation. (So 64 by default)
*
* Reduction in size, reduces speed.
*/
#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */
#endif /* !MBEDTLS_MPI_WINDOW_SIZE */
#if !defined(MBEDTLS_MPI_MAX_SIZE)
/*
* Maximum size of MPIs allowed in bits and bytes for user-MPIs.
* ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits )
*
* Note: Calculations can results temporarily in larger MPIs. So the number
* of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher.
*/
#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */
#endif /* !MBEDTLS_MPI_MAX_SIZE */
#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */
/*
* When reading from files with mbedtls_mpi_read_file() and writing to files with
* mbedtls_mpi_write_file() the buffer should have space
* for a (short) label, the MPI (in the provided radix), the newline
* characters and the '\0'.
*
* By default we assume at least a 10 char label, a minimum radix of 10
* (decimal) and a maximum of 4096 bit numbers (1234 decimal chars).
* Autosized at compile time for at least a 10 char label, a minimum radix
* of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size.
*
* This used to be statically sized to 1250 for a maximum of 4096 bit
* numbers (1234 decimal chars).
*
* Calculate using the formula:
* MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) +
* LabelSize + 6
*/
#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS )
#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332
#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 )
/*
* Define the base integer type, architecture-wise.
*
* 32 or 64-bit integer types can be forced regardless of the underlying
* architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64
* respectively and undefining MBEDTLS_HAVE_ASM.
*
* Double-width integers (e.g. 128-bit in 64-bit architectures) can be
* disabled by defining MBEDTLS_NO_UDBL_DIVISION.
*/
#if !defined(MBEDTLS_HAVE_INT32)
#if defined(_MSC_VER) && defined(_M_AMD64)
/* Always choose 64-bit when using MSC */
#if !defined(MBEDTLS_HAVE_INT64)
#define MBEDTLS_HAVE_INT64
#endif /* !MBEDTLS_HAVE_INT64 */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#elif defined(__GNUC__) && ( \
defined(__amd64__) || defined(__x86_64__) || \
defined(__ppc64__) || defined(__powerpc64__) || \
defined(__ia64__) || defined(__alpha__) || \
( defined(__sparc__) && defined(__arch64__) ) || \
defined(__s390x__) || defined(__mips64) )
#if !defined(MBEDTLS_HAVE_INT64)
#define MBEDTLS_HAVE_INT64
#endif /* MBEDTLS_HAVE_INT64 */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#if !defined(MBEDTLS_NO_UDBL_DIVISION)
/* mbedtls_t_udbl defined as 128-bit unsigned int */
typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
#define MBEDTLS_HAVE_UDBL
#endif /* !MBEDTLS_NO_UDBL_DIVISION */
#elif defined(__ARMCC_VERSION) && defined(__aarch64__)
/*
* __ARMCC_VERSION is defined for both armcc and armclang and
* __aarch64__ is only defined by armclang when compiling 64-bit code
*/
#if !defined(MBEDTLS_HAVE_INT64)
#define MBEDTLS_HAVE_INT64
#endif /* !MBEDTLS_HAVE_INT64 */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#if !defined(MBEDTLS_NO_UDBL_DIVISION)
/* mbedtls_t_udbl defined as 128-bit unsigned int */
typedef __uint128_t mbedtls_t_udbl;
#define MBEDTLS_HAVE_UDBL
#endif /* !MBEDTLS_NO_UDBL_DIVISION */
#elif defined(MBEDTLS_HAVE_INT64)
/* Force 64-bit integers with unknown compiler */
typedef int64_t mbedtls_mpi_sint;
typedef uint64_t mbedtls_mpi_uint;
#endif
#endif /* !MBEDTLS_HAVE_INT32 */
#if !defined(MBEDTLS_HAVE_INT64)
/* Default to 32-bit compilation */
#if !defined(MBEDTLS_HAVE_INT32)
#define MBEDTLS_HAVE_INT32
#endif /* !MBEDTLS_HAVE_INT32 */
typedef int32_t mbedtls_mpi_sint;
typedef uint32_t mbedtls_mpi_uint;
#if !defined(MBEDTLS_NO_UDBL_DIVISION)
typedef uint64_t mbedtls_t_udbl;
#define MBEDTLS_HAVE_UDBL
#endif /* !MBEDTLS_NO_UDBL_DIVISION */
#endif /* !MBEDTLS_HAVE_INT64 */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MPI structure
*/
typedef struct
{
int s; /*!< integer sign */
size_t n; /*!< total # of limbs */
mbedtls_mpi_uint *p; /*!< pointer to limbs */
}
mbedtls_mpi;
/**
* \brief Initialize one MPI (make internal references valid)
* This just makes it ready to be set or freed,
* but does not define a value for the MPI.
*
* \param X One MPI to initialize.
*/
void mbedtls_mpi_init( mbedtls_mpi *X );
/**
* \brief Unallocate one MPI
*
* \param X One MPI to unallocate.
*/
void mbedtls_mpi_free( mbedtls_mpi *X );
/**
* \brief Enlarge to the specified number of limbs
*
* \param X MPI to grow
* \param nblimbs The target number of limbs
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs );
/**
* \brief Resize down, keeping at least the specified number of limbs
*
* \param X MPI to shrink
* \param nblimbs The minimum number of limbs to keep
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs );
/**
* \brief Copy the contents of Y into X
*
* \param X Destination MPI
* \param Y Source MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
* \brief Swap the contents of X and Y
*
* \param X First MPI value
* \param Y Second MPI value
*/
void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y );
/**
* \brief Safe conditional assignement X = Y if assign is 1
*
* \param X MPI to conditionally assign to
* \param Y Value to be assigned
* \param assign 1: perform the assignment, 0: keep X's original value
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
*
* \note This function is equivalent to
* if ( assign ) mbedtls_mpi_copy( X, Y );
* except that it avoids leaking any information about whether
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
*/
int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign );
/**
* \brief Safe conditional swap X <-> Y if swap is 1
*
* \param X First mbedtls_mpi value
* \param Y Second mbedtls_mpi value
* \param assign 1: perform the swap, 0: keep X and Y's original values
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
*
* \note This function is equivalent to
* if ( assign ) mbedtls_mpi_swap( X, Y );
* except that it avoids leaking any information about whether
* the assignment was done or not (the above code may leak
* information through branch prediction and/or memory access
* patterns analysis).
*/
int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign );
/**
* \brief Set value from integer
*
* \param X MPI to set
* \param z Value to use
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z );
/**
* \brief Get a specific bit from X
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
*
* \return Either a 0 or a 1
*/
int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos );
/**
* \brief Set a bit of X to a specific value of 0 or 1
*
* \note Will grow X if necessary to set a bit to 1 in a not yet
* existing limb. Will not grow if bit should be set to 0
*
* \param X MPI to use
* \param pos Zero-based index of the bit in X
* \param val The value to set the bit to (0 or 1)
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1
*/
int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val );
/**
* \brief Return the number of zero-bits before the least significant
* '1' bit
*
* Note: Thus also the zero-based index of the least significant '1' bit
*
* \param X MPI to use
*/
size_t mbedtls_mpi_lsb( const mbedtls_mpi *X );
/**
* \brief Return the number of bits up to and including the most
* significant '1' bit'
*
* Note: Thus also the one-based index of the most significant '1' bit
*
* \param X MPI to use
*/
size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X );
/**
* \brief Return the total size in bytes
*
* \param X MPI to use
*/
size_t mbedtls_mpi_size( const mbedtls_mpi *X );
/**
* \brief Import from an ASCII string
*
* \param X Destination MPI
* \param radix Input numeric base
* \param s Null-terminated string buffer
*
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
*/
int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s );
/**
* \brief Export into an ASCII string
*
* \param X Source MPI
* \param radix Output numeric base
* \param buf Buffer to write the string to
* \param buflen Length of buf
* \param olen Length of the string written, including final NUL byte
*
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code.
* *olen is always updated to reflect the amount
* of data that has (or would have) been written.
*
* \note Call this function with buflen = 0 to obtain the
* minimum required buffer size in *olen.
*/
int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
char *buf, size_t buflen, size_t *olen );
#if defined(MBEDTLS_FS_IO)
/**
* \brief Read MPI from a line in an opened file
*
* \param X Destination MPI
* \param radix Input numeric base
* \param fin Input file handle
*
* \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if
* the file read buffer is too small or a
* MBEDTLS_ERR_MPI_XXX error code
*
* \note On success, this function advances the file stream
* to the end of the current line or to EOF.
*
* The function returns 0 on an empty line.
*
* Leading whitespaces are ignored, as is a
* '0x' prefix for radix 16.
*
*/
int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin );
/**
* \brief Write X into an opened file, or stdout if fout is NULL
*
* \param p Prefix, can be NULL
* \param X Source MPI
* \param radix Output numeric base
* \param fout Output file handle (can be NULL)
*
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
*
* \note Set fout == NULL to print X on the console.
*/
int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout );
#endif /* MBEDTLS_FS_IO */
/**
* \brief Import X from unsigned binary data, big endian
*
* \param X Destination MPI
* \param buf Input buffer
* \param buflen Input buffer size
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen );
/**
* \brief Export X into unsigned binary data, big endian.
* Always fills the whole buffer, which will start with zeros
* if the number is smaller.
*
* \param X Source MPI
* \param buf Output buffer
* \param buflen Output buffer size
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
*/
int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen );
/**
* \brief Left-shift: X <<= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count );
/**
* \brief Right-shift: X >>= count
*
* \param X MPI to shift
* \param count Amount to shift
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count );
/**
* \brief Compare unsigned values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if |X| is greater than |Y|,
* -1 if |X| is lesser than |Y| or
* 0 if |X| is equal to |Y|
*/
int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param Y Right-hand MPI
*
* \return 1 if X is greater than Y,
* -1 if X is lesser than Y or
* 0 if X is equal to Y
*/
int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y );
/**
* \brief Compare signed values
*
* \param X Left-hand MPI
* \param z The integer value to compare to
*
* \return 1 if X is greater than z,
* -1 if X is lesser than z or
* 0 if X is equal to z
*/
int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z );
/**
* \brief Unsigned addition: X = |A| + |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Unsigned subtraction: X = |A| - |B|
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A
*/
int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Signed addition: X = A + B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Signed subtraction: X = A - B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Signed addition: X = A + b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to add
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Signed subtraction: X = A - b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The integer value to subtract
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Baseline multiplication: X = A * B
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Baseline multiplication: X = A * b
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param b The unsigned integer value to multiply with
*
* \note b is unsigned
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b );
/**
* \brief Division by mbedtls_mpi: A = Q * B + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0
*
* \note Either Q or R can be NULL.
*/
int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Division by int: A = Q * b + R
*
* \param Q Destination MPI for the quotient
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0
*
* \note Either Q or R can be NULL.
*/
int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Modulo: R = A mod B
*
* \param R Destination MPI for the rest value
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0,
* MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0
*/
int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Modulo: r = A mod b
*
* \param r Destination mbedtls_mpi_uint
* \param A Left-hand MPI
* \param b Integer to divide by
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0,
* MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0
*/
int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b );
/**
* \brief Sliding-window exponentiation: X = A^E mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param E Exponent MPI
* \param N Modular MPI
* \param _RR Speed-up MPI used for recalculations
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or
* if E is negative
*
* \note _RR is used to avoid re-computing R*R mod N across
* multiple calls, which speeds up things a bit. It can
* be set to NULL if the extra performance is unneeded.
*/
int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR );
/**
* \brief Fill an MPI X with size bytes of random
*
* \param X Destination MPI
* \param size Size in bytes
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Greatest common divisor: G = gcd(A, B)
*
* \param G Destination MPI
* \param A Left-hand MPI
* \param B Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
*/
int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B );
/**
* \brief Modular inverse: X = A^-1 mod N
*
* \param X Destination MPI
* \param A Left-hand MPI
* \param N Right-hand MPI
*
* \return 0 if successful,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1,
MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N.
*/
int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N );
/**
* \brief Miller-Rabin primality test
*
* \param X MPI to check
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime
*/
int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Prime number generation
*
* \param X Destination MPI
* \param nbits Required size of X in bits
* ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS )
* \param dh_flag If 1, then (X-1)/2 will be prime too
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
*/
int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mbedtls_mpi_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* bignum.h */

View File

@ -0,0 +1,887 @@
/**
* \file bn_mul.h
*
* \brief Multi-precision integer library
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* Multiply source vector [s] with b, add result
* to destination vector [d] and set carry c.
*
* Currently supports:
*
* . IA-32 (386+) . AMD64 / EM64T
* . IA-32 (SSE2) . Motorola 68000
* . PowerPC, 32-bit . MicroBlaze
* . PowerPC, 64-bit . TriCore
* . SPARC v8 . ARM v3+
* . Alpha . MIPS32
* . C, longlong . C, generic
*/
#ifndef MBEDTLS_BN_MUL_H
#define MBEDTLS_BN_MUL_H
#include "bignum.h"
#if defined(MBEDTLS_HAVE_ASM)
#ifndef asm
#define asm __asm
#endif
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
#if defined(__GNUC__) && \
( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
#if defined(__i386__)
#define MULADDC_INIT \
asm( \
"movl %%ebx, %0 \n\t" \
"movl %5, %%esi \n\t" \
"movl %6, %%edi \n\t" \
"movl %7, %%ecx \n\t" \
"movl %8, %%ebx \n\t"
#define MULADDC_CORE \
"lodsl \n\t" \
"mull %%ebx \n\t" \
"addl %%ecx, %%eax \n\t" \
"adcl $0, %%edx \n\t" \
"addl (%%edi), %%eax \n\t" \
"adcl $0, %%edx \n\t" \
"movl %%edx, %%ecx \n\t" \
"stosl \n\t"
#if defined(MBEDTLS_HAVE_SSE2)
#define MULADDC_HUIT \
"movd %%ecx, %%mm1 \n\t" \
"movd %%ebx, %%mm0 \n\t" \
"movd (%%edi), %%mm3 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd (%%esi), %%mm2 \n\t" \
"pmuludq %%mm0, %%mm2 \n\t" \
"movd 4(%%esi), %%mm4 \n\t" \
"pmuludq %%mm0, %%mm4 \n\t" \
"movd 8(%%esi), %%mm6 \n\t" \
"pmuludq %%mm0, %%mm6 \n\t" \
"movd 12(%%esi), %%mm7 \n\t" \
"pmuludq %%mm0, %%mm7 \n\t" \
"paddq %%mm2, %%mm1 \n\t" \
"movd 4(%%edi), %%mm3 \n\t" \
"paddq %%mm4, %%mm3 \n\t" \
"movd 8(%%edi), %%mm5 \n\t" \
"paddq %%mm6, %%mm5 \n\t" \
"movd 12(%%edi), %%mm4 \n\t" \
"paddq %%mm4, %%mm7 \n\t" \
"movd %%mm1, (%%edi) \n\t" \
"movd 16(%%esi), %%mm2 \n\t" \
"pmuludq %%mm0, %%mm2 \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd 20(%%esi), %%mm4 \n\t" \
"pmuludq %%mm0, %%mm4 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd 24(%%esi), %%mm6 \n\t" \
"pmuludq %%mm0, %%mm6 \n\t" \
"movd %%mm1, 4(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd 28(%%esi), %%mm3 \n\t" \
"pmuludq %%mm0, %%mm3 \n\t" \
"paddq %%mm5, %%mm1 \n\t" \
"movd 16(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm2 \n\t" \
"movd %%mm1, 8(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm7, %%mm1 \n\t" \
"movd 20(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm4 \n\t" \
"movd %%mm1, 12(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm2, %%mm1 \n\t" \
"movd 24(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm6 \n\t" \
"movd %%mm1, 16(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm4, %%mm1 \n\t" \
"movd 28(%%edi), %%mm5 \n\t" \
"paddq %%mm5, %%mm3 \n\t" \
"movd %%mm1, 20(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm6, %%mm1 \n\t" \
"movd %%mm1, 24(%%edi) \n\t" \
"psrlq $32, %%mm1 \n\t" \
"paddq %%mm3, %%mm1 \n\t" \
"movd %%mm1, 28(%%edi) \n\t" \
"addl $32, %%edi \n\t" \
"addl $32, %%esi \n\t" \
"psrlq $32, %%mm1 \n\t" \
"movd %%mm1, %%ecx \n\t"
#define MULADDC_STOP \
"emms \n\t" \
"movl %4, %%ebx \n\t" \
"movl %%ecx, %1 \n\t" \
"movl %%edi, %2 \n\t" \
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
);
#else
#define MULADDC_STOP \
"movl %4, %%ebx \n\t" \
"movl %%ecx, %1 \n\t" \
"movl %%edi, %2 \n\t" \
"movl %%esi, %3 \n\t" \
: "=m" (t), "=m" (c), "=m" (d), "=m" (s) \
: "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \
: "eax", "ecx", "edx", "esi", "edi" \
);
#endif /* SSE2 */
#endif /* i386 */
#if defined(__amd64__) || defined (__x86_64__)
#define MULADDC_INIT \
asm( \
"xorq %%r8, %%r8 \n\t"
#define MULADDC_CORE \
"movq (%%rsi), %%rax \n\t" \
"mulq %%rbx \n\t" \
"addq $8, %%rsi \n\t" \
"addq %%rcx, %%rax \n\t" \
"movq %%r8, %%rcx \n\t" \
"adcq $0, %%rdx \n\t" \
"nop \n\t" \
"addq %%rax, (%%rdi) \n\t" \
"adcq %%rdx, %%rcx \n\t" \
"addq $8, %%rdi \n\t"
#define MULADDC_STOP \
: "+c" (c), "+D" (d), "+S" (s) \
: "b" (b) \
: "rax", "rdx", "r8" \
);
#endif /* AMD64 */
#if defined(__mc68020__) || defined(__mcpu32__)
#define MULADDC_INIT \
asm( \
"movl %3, %%a2 \n\t" \
"movl %4, %%a3 \n\t" \
"movl %5, %%d3 \n\t" \
"movl %6, %%d2 \n\t" \
"moveq #0, %%d0 \n\t"
#define MULADDC_CORE \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"moveq #0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"addxl %%d4, %%d3 \n\t"
#define MULADDC_STOP \
"movl %%d3, %0 \n\t" \
"movl %%a3, %1 \n\t" \
"movl %%a2, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "d0", "d1", "d2", "d3", "d4", "a2", "a3" \
);
#define MULADDC_HUIT \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d4:%%d1 \n\t" \
"addxl %%d3, %%d1 \n\t" \
"addxl %%d0, %%d4 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"movel %%a2@+, %%d1 \n\t" \
"mulul %%d2, %%d3:%%d1 \n\t" \
"addxl %%d4, %%d1 \n\t" \
"addxl %%d0, %%d3 \n\t" \
"addl %%d1, %%a3@+ \n\t" \
"addxl %%d0, %%d3 \n\t"
#endif /* MC68000 */
#if defined(__powerpc64__) || defined(__ppc64__)
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( \
"ld r3, %3 \n\t" \
"ld r4, %4 \n\t" \
"ld r5, %5 \n\t" \
"ld r6, %6 \n\t" \
"addi r3, r3, -8 \n\t" \
"addi r4, r4, -8 \n\t" \
"addic r5, r5, 0 \n\t"
#define MULADDC_CORE \
"ldu r7, 8(r3) \n\t" \
"mulld r8, r7, r6 \n\t" \
"mulhdu r9, r7, r6 \n\t" \
"adde r8, r8, r5 \n\t" \
"ld r7, 8(r4) \n\t" \
"addze r5, r9 \n\t" \
"addc r8, r8, r7 \n\t" \
"stdu r8, 8(r4) \n\t"
#define MULADDC_STOP \
"addze r5, r5 \n\t" \
"addi r4, r4, 8 \n\t" \
"addi r3, r3, 8 \n\t" \
"std r5, %0 \n\t" \
"std r4, %1 \n\t" \
"std r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#else /* __MACH__ && __APPLE__ */
#define MULADDC_INIT \
asm( \
"ld %%r3, %3 \n\t" \
"ld %%r4, %4 \n\t" \
"ld %%r5, %5 \n\t" \
"ld %%r6, %6 \n\t" \
"addi %%r3, %%r3, -8 \n\t" \
"addi %%r4, %%r4, -8 \n\t" \
"addic %%r5, %%r5, 0 \n\t"
#define MULADDC_CORE \
"ldu %%r7, 8(%%r3) \n\t" \
"mulld %%r8, %%r7, %%r6 \n\t" \
"mulhdu %%r9, %%r7, %%r6 \n\t" \
"adde %%r8, %%r8, %%r5 \n\t" \
"ld %%r7, 8(%%r4) \n\t" \
"addze %%r5, %%r9 \n\t" \
"addc %%r8, %%r8, %%r7 \n\t" \
"stdu %%r8, 8(%%r4) \n\t"
#define MULADDC_STOP \
"addze %%r5, %%r5 \n\t" \
"addi %%r4, %%r4, 8 \n\t" \
"addi %%r3, %%r3, 8 \n\t" \
"std %%r5, %0 \n\t" \
"std %%r4, %1 \n\t" \
"std %%r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#endif /* __MACH__ && __APPLE__ */
#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */
#if defined(__MACH__) && defined(__APPLE__)
#define MULADDC_INIT \
asm( \
"lwz r3, %3 \n\t" \
"lwz r4, %4 \n\t" \
"lwz r5, %5 \n\t" \
"lwz r6, %6 \n\t" \
"addi r3, r3, -4 \n\t" \
"addi r4, r4, -4 \n\t" \
"addic r5, r5, 0 \n\t"
#define MULADDC_CORE \
"lwzu r7, 4(r3) \n\t" \
"mullw r8, r7, r6 \n\t" \
"mulhwu r9, r7, r6 \n\t" \
"adde r8, r8, r5 \n\t" \
"lwz r7, 4(r4) \n\t" \
"addze r5, r9 \n\t" \
"addc r8, r8, r7 \n\t" \
"stwu r8, 4(r4) \n\t"
#define MULADDC_STOP \
"addze r5, r5 \n\t" \
"addi r4, r4, 4 \n\t" \
"addi r3, r3, 4 \n\t" \
"stw r5, %0 \n\t" \
"stw r4, %1 \n\t" \
"stw r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#else /* __MACH__ && __APPLE__ */
#define MULADDC_INIT \
asm( \
"lwz %%r3, %3 \n\t" \
"lwz %%r4, %4 \n\t" \
"lwz %%r5, %5 \n\t" \
"lwz %%r6, %6 \n\t" \
"addi %%r3, %%r3, -4 \n\t" \
"addi %%r4, %%r4, -4 \n\t" \
"addic %%r5, %%r5, 0 \n\t"
#define MULADDC_CORE \
"lwzu %%r7, 4(%%r3) \n\t" \
"mullw %%r8, %%r7, %%r6 \n\t" \
"mulhwu %%r9, %%r7, %%r6 \n\t" \
"adde %%r8, %%r8, %%r5 \n\t" \
"lwz %%r7, 4(%%r4) \n\t" \
"addze %%r5, %%r9 \n\t" \
"addc %%r8, %%r8, %%r7 \n\t" \
"stwu %%r8, 4(%%r4) \n\t"
#define MULADDC_STOP \
"addze %%r5, %%r5 \n\t" \
"addi %%r4, %%r4, 4 \n\t" \
"addi %%r3, %%r3, 4 \n\t" \
"stw %%r5, %0 \n\t" \
"stw %%r4, %1 \n\t" \
"stw %%r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4", "r5", "r6", "r7", "r8", "r9" \
);
#endif /* __MACH__ && __APPLE__ */
#endif /* PPC32 */
/*
* The Sparc(64) assembly is reported to be broken.
* Disable it for now, until we're able to fix it.
*/
#if 0 && defined(__sparc__)
#if defined(__sparc64__)
#define MULADDC_INIT \
asm( \
"ldx %3, %%o0 \n\t" \
"ldx %4, %%o1 \n\t" \
"ld %5, %%o2 \n\t" \
"ld %6, %%o3 \n\t"
#define MULADDC_CORE \
"ld [%%o0], %%o4 \n\t" \
"inc 4, %%o0 \n\t" \
"ld [%%o1], %%o5 \n\t" \
"umul %%o3, %%o4, %%o4 \n\t" \
"addcc %%o4, %%o2, %%o4 \n\t" \
"rd %%y, %%g1 \n\t" \
"addx %%g1, 0, %%g1 \n\t" \
"addcc %%o4, %%o5, %%o4 \n\t" \
"st %%o4, [%%o1] \n\t" \
"addx %%g1, 0, %%o2 \n\t" \
"inc 4, %%o1 \n\t"
#define MULADDC_STOP \
"st %%o2, %0 \n\t" \
"stx %%o1, %1 \n\t" \
"stx %%o0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#else /* __sparc64__ */
#define MULADDC_INIT \
asm( \
"ld %3, %%o0 \n\t" \
"ld %4, %%o1 \n\t" \
"ld %5, %%o2 \n\t" \
"ld %6, %%o3 \n\t"
#define MULADDC_CORE \
"ld [%%o0], %%o4 \n\t" \
"inc 4, %%o0 \n\t" \
"ld [%%o1], %%o5 \n\t" \
"umul %%o3, %%o4, %%o4 \n\t" \
"addcc %%o4, %%o2, %%o4 \n\t" \
"rd %%y, %%g1 \n\t" \
"addx %%g1, 0, %%g1 \n\t" \
"addcc %%o4, %%o5, %%o4 \n\t" \
"st %%o4, [%%o1] \n\t" \
"addx %%g1, 0, %%o2 \n\t" \
"inc 4, %%o1 \n\t"
#define MULADDC_STOP \
"st %%o2, %0 \n\t" \
"st %%o1, %1 \n\t" \
"st %%o0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "g1", "o0", "o1", "o2", "o3", "o4", \
"o5" \
);
#endif /* __sparc64__ */
#endif /* __sparc__ */
#if defined(__microblaze__) || defined(microblaze)
#define MULADDC_INIT \
asm( \
"lwi r3, %3 \n\t" \
"lwi r4, %4 \n\t" \
"lwi r5, %5 \n\t" \
"lwi r6, %6 \n\t" \
"andi r7, r6, 0xffff \n\t" \
"bsrli r6, r6, 16 \n\t"
#define MULADDC_CORE \
"lhui r8, r3, 0 \n\t" \
"addi r3, r3, 2 \n\t" \
"lhui r9, r3, 0 \n\t" \
"addi r3, r3, 2 \n\t" \
"mul r10, r9, r6 \n\t" \
"mul r11, r8, r7 \n\t" \
"mul r12, r9, r7 \n\t" \
"mul r13, r8, r6 \n\t" \
"bsrli r8, r10, 16 \n\t" \
"bsrli r9, r11, 16 \n\t" \
"add r13, r13, r8 \n\t" \
"add r13, r13, r9 \n\t" \
"bslli r10, r10, 16 \n\t" \
"bslli r11, r11, 16 \n\t" \
"add r12, r12, r10 \n\t" \
"addc r13, r13, r0 \n\t" \
"add r12, r12, r11 \n\t" \
"addc r13, r13, r0 \n\t" \
"lwi r10, r4, 0 \n\t" \
"add r12, r12, r10 \n\t" \
"addc r13, r13, r0 \n\t" \
"add r12, r12, r5 \n\t" \
"addc r5, r13, r0 \n\t" \
"swi r12, r4, 0 \n\t" \
"addi r4, r4, 4 \n\t"
#define MULADDC_STOP \
"swi r5, %0 \n\t" \
"swi r4, %1 \n\t" \
"swi r3, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r3", "r4" "r5", "r6", "r7", "r8", \
"r9", "r10", "r11", "r12", "r13" \
);
#endif /* MicroBlaze */
#if defined(__tricore__)
#define MULADDC_INIT \
asm( \
"ld.a %%a2, %3 \n\t" \
"ld.a %%a3, %4 \n\t" \
"ld.w %%d4, %5 \n\t" \
"ld.w %%d1, %6 \n\t" \
"xor %%d5, %%d5 \n\t"
#define MULADDC_CORE \
"ld.w %%d0, [%%a2+] \n\t" \
"madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \
"ld.w %%d0, [%%a3] \n\t" \
"addx %%d2, %%d2, %%d0 \n\t" \
"addc %%d3, %%d3, 0 \n\t" \
"mov %%d4, %%d3 \n\t" \
"st.w [%%a3+], %%d2 \n\t"
#define MULADDC_STOP \
"st.w %0, %%d4 \n\t" \
"st.a %1, %%a3 \n\t" \
"st.a %2, %%a2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "d0", "d1", "e2", "d4", "a2", "a3" \
);
#endif /* TriCore */
/*
* gcc -O0 by default uses r7 for the frame pointer, so it complains about our
* use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately,
* passing that option is not easy when building with yotta.
*
* On the other hand, -fomit-frame-pointer is implied by any -Ox options with
* x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
* clang and armcc5 under the same conditions).
*
* So, only use the optimized assembly below for optimized build, which avoids
* the build error and is pretty reasonable anyway.
*/
#if defined(__GNUC__) && !defined(__OPTIMIZE__)
#define MULADDC_CANNOT_USE_R7
#endif
#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7)
#if defined(__thumb__) && !defined(__thumb2__)
#pragma message "using ARM THUMB MULADDC"
#define MULADDC_INIT \
asm( \
"ldr r0, %3 \n\t" \
"ldr r1, %4 \n\t" \
"ldr r2, %5 \n\t" \
"ldr r3, %6 \n\t" \
"lsr r7, r3, #16 \n\t" \
"mov r9, r7 \n\t" \
"lsl r7, r3, #16 \n\t" \
"lsr r7, r7, #16 \n\t" \
"mov r8, r7 \n\t"
#define MULADDC_CORE \
"ldmia r0!, {r6} \n\t" \
"lsr r7, r6, #16 \n\t" \
"lsl r6, r6, #16 \n\t" \
"lsr r6, r6, #16 \n\t" \
"mov r4, r8 \n\t" \
"mul r4, r6 \n\t" \
"mov r3, r9 \n\t" \
"mul r6, r3 \n\t" \
"mov r5, r9 \n\t" \
"mul r5, r7 \n\t" \
"mov r3, r8 \n\t" \
"mul r7, r3 \n\t" \
"lsr r3, r6, #16 \n\t" \
"add r5, r5, r3 \n\t" \
"lsr r3, r7, #16 \n\t" \
"add r5, r5, r3 \n\t" \
"add r4, r4, r2 \n\t" \
"mov r2, #0 \n\t" \
"adc r5, r2 \n\t" \
"lsl r3, r6, #16 \n\t" \
"add r4, r4, r3 \n\t" \
"adc r5, r2 \n\t" \
"lsl r3, r7, #16 \n\t" \
"add r4, r4, r3 \n\t" \
"adc r5, r2 \n\t" \
"ldr r3, [r1] \n\t" \
"add r4, r4, r3 \n\t" \
"adc r2, r5 \n\t" \
"stmia r1!, {r4} \n\t"
#define MULADDC_STOP \
"str r2, %0 \n\t" \
"str r1, %1 \n\t" \
"str r0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "r8", "r9", "cc" \
);
#else
#define MULADDC_INIT \
asm( \
"ldr r0, %3 \n\t" \
"ldr r1, %4 \n\t" \
"ldr r2, %5 \n\t" \
"ldr r3, %6 \n\t"
#define MULADDC_CORE \
"ldr r4, [r0], #4 \n\t" \
"mov r5, #0 \n\t" \
"ldr r6, [r1] \n\t" \
"umlal r2, r5, r3, r4 \n\t" \
"adds r7, r6, r2 \n\t" \
"adc r2, r5, #0 \n\t" \
"str r7, [r1], #4 \n\t"
#define MULADDC_STOP \
"str r2, %0 \n\t" \
"str r1, %1 \n\t" \
"str r0, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "r0", "r1", "r2", "r3", "r4", "r5", \
"r6", "r7", "cc" \
);
#endif /* Thumb */
#endif /* ARMv3 */
#if defined(__alpha__)
#define MULADDC_INIT \
asm( \
"ldq $1, %3 \n\t" \
"ldq $2, %4 \n\t" \
"ldq $3, %5 \n\t" \
"ldq $4, %6 \n\t"
#define MULADDC_CORE \
"ldq $6, 0($1) \n\t" \
"addq $1, 8, $1 \n\t" \
"mulq $6, $4, $7 \n\t" \
"umulh $6, $4, $6 \n\t" \
"addq $7, $3, $7 \n\t" \
"cmpult $7, $3, $3 \n\t" \
"ldq $5, 0($2) \n\t" \
"addq $7, $5, $7 \n\t" \
"cmpult $7, $5, $5 \n\t" \
"stq $7, 0($2) \n\t" \
"addq $2, 8, $2 \n\t" \
"addq $6, $3, $3 \n\t" \
"addq $5, $3, $3 \n\t"
#define MULADDC_STOP \
"stq $3, %0 \n\t" \
"stq $2, %1 \n\t" \
"stq $1, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "$1", "$2", "$3", "$4", "$5", "$6", "$7" \
);
#endif /* Alpha */
#if defined(__mips__) && !defined(__mips64)
#define MULADDC_INIT \
asm( \
"lw $10, %3 \n\t" \
"lw $11, %4 \n\t" \
"lw $12, %5 \n\t" \
"lw $13, %6 \n\t"
#define MULADDC_CORE \
"lw $14, 0($10) \n\t" \
"multu $13, $14 \n\t" \
"addi $10, $10, 4 \n\t" \
"mflo $14 \n\t" \
"mfhi $9 \n\t" \
"addu $14, $12, $14 \n\t" \
"lw $15, 0($11) \n\t" \
"sltu $12, $14, $12 \n\t" \
"addu $15, $14, $15 \n\t" \
"sltu $14, $15, $14 \n\t" \
"addu $12, $12, $9 \n\t" \
"sw $15, 0($11) \n\t" \
"addu $12, $12, $14 \n\t" \
"addi $11, $11, 4 \n\t"
#define MULADDC_STOP \
"sw $12, %0 \n\t" \
"sw $11, %1 \n\t" \
"sw $10, %2 \n\t" \
: "=m" (c), "=m" (d), "=m" (s) \
: "m" (s), "m" (d), "m" (c), "m" (b) \
: "$9", "$10", "$11", "$12", "$13", "$14", "$15" \
);
#endif /* MIPS */
#endif /* GNUC */
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
#define MULADDC_INIT \
__asm mov esi, s \
__asm mov edi, d \
__asm mov ecx, c \
__asm mov ebx, b
#define MULADDC_CORE \
__asm lodsd \
__asm mul ebx \
__asm add eax, ecx \
__asm adc edx, 0 \
__asm add eax, [edi] \
__asm adc edx, 0 \
__asm mov ecx, edx \
__asm stosd
#if defined(MBEDTLS_HAVE_SSE2)
#define EMIT __asm _emit
#define MULADDC_HUIT \
EMIT 0x0F EMIT 0x6E EMIT 0xC9 \
EMIT 0x0F EMIT 0x6E EMIT 0xC3 \
EMIT 0x0F EMIT 0x6E EMIT 0x1F \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x16 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \
EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \
EMIT 0x0F EMIT 0xD4 EMIT 0xDC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \
EMIT 0x0F EMIT 0xD4 EMIT 0xEE \
EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \
EMIT 0x0F EMIT 0xD4 EMIT 0xFC \
EMIT 0x0F EMIT 0x7E EMIT 0x0F \
EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \
EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \
EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \
EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \
EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCD \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \
EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCF \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \
EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCA \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \
EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCC \
EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \
EMIT 0x0F EMIT 0xD4 EMIT 0xDD \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCE \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0xD4 EMIT 0xCB \
EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \
EMIT 0x83 EMIT 0xC7 EMIT 0x20 \
EMIT 0x83 EMIT 0xC6 EMIT 0x20 \
EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \
EMIT 0x0F EMIT 0x7E EMIT 0xC9
#define MULADDC_STOP \
EMIT 0x0F EMIT 0x77 \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#else
#define MULADDC_STOP \
__asm mov c, ecx \
__asm mov d, edi \
__asm mov s, esi \
#endif /* SSE2 */
#endif /* MSVC */
#endif /* MBEDTLS_HAVE_ASM */
#if !defined(MULADDC_CORE)
#if defined(MBEDTLS_HAVE_UDBL)
#define MULADDC_INIT \
{ \
mbedtls_t_udbl r; \
mbedtls_mpi_uint r0, r1;
#define MULADDC_CORE \
r = *(s++) * (mbedtls_t_udbl) b; \
r0 = (mbedtls_mpi_uint) r; \
r1 = (mbedtls_mpi_uint)( r >> biL ); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#else
#define MULADDC_INIT \
{ \
mbedtls_mpi_uint s0, s1, b0, b1; \
mbedtls_mpi_uint r0, r1, rx, ry; \
b0 = ( b << biH ) >> biH; \
b1 = ( b >> biH );
#define MULADDC_CORE \
s0 = ( *s << biH ) >> biH; \
s1 = ( *s >> biH ); s++; \
rx = s0 * b1; r0 = s0 * b0; \
ry = s1 * b0; r1 = s1 * b1; \
r1 += ( rx >> biH ); \
r1 += ( ry >> biH ); \
rx <<= biH; ry <<= biH; \
r0 += rx; r1 += (r0 < rx); \
r0 += ry; r1 += (r0 < ry); \
r0 += c; r1 += (r0 < c); \
r0 += *d; r1 += (r0 < *d); \
c = r1; *(d++) = r0;
#define MULADDC_STOP \
}
#endif /* C (generic) */
#endif /* C (longlong) */
#endif /* bn_mul.h */

View File

@ -0,0 +1,5 @@
#define MBEDTLS_BIGNUM_C
#define POLARSSL_AES_C
#define MBEDTLS_HAVE_ASM

View File

@ -0,0 +1,125 @@
#include <stdint.h>
#include <string.h>
#include "crypto.h"
#include "u128_math.h"
#include "f_xy.h"
#include "dsi.h"
// more info:
// https://github.com/Jimmy-Z/TWLbf/blob/master/dsi.c
// https://github.com/Jimmy-Z/bfCL/blob/master/dsi.h
// ported back to 32 bit for ARM9
static dsi_context nand_ctx ;
static dsi_context boot2_ctx ;
static dsi_context es_ctx ;
static uint8_t nand_ctr_iv[16];
static uint8_t boot2_ctr[16];
static void generate_key(uint8_t *generated_key, const uint32_t *console_id, const key_mode_t mode)
{
uint32_t key[4];
switch (mode)
{
case NAND:
key[0] = console_id[0];
key[1] = console_id[0] ^ KEYSEED_DSI_NAND_0;
key[2] = console_id[1] ^ KEYSEED_DSI_NAND_1;
key[3] = console_id[1];
break;
case NAND_3DS:
key[0] = (console_id[0] ^ KEYSEED_3DS_NAND_0) | 0x80000000;
key[1] = KEYSEED_3DS_NAND_1;
key[2] = KEYSEED_3DS_NAND_2;
key[3] = console_id[1] ^ KEYSEED_3DS_NAND_3;
break;
case ES:
key[0] = KEYSEED_ES_0;
key[1] = KEYSEED_ES_1;
key[2] = console_id[1] ^ KEYSEED_ES_2;
key[3] = console_id[0];
break;
default:
break;
}
u128_xor((uint8_t *)key, mode == ES ? DSi_ES_KEY_Y : DSi_NAND_KEY_Y);
u128_add((uint8_t *)key, DSi_KEY_MAGIC);
u128_lrot((uint8_t *)key, 42) ;
memcpy(generated_key, key, 16) ;
}
int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len)
{
uint8_t digest[SHA1_LEN];
swiSHA1Calc(digest, data, len);
return memcmp(digest, digest_verify, SHA1_LEN);
}
void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS)
{
uint32_t console_id[2];
GET_UINT32_BE(console_id[0], console_id_be, 4);
GET_UINT32_BE(console_id[1], console_id_be, 0);
uint8_t key[16];
generate_key(key, console_id, is3DS ? NAND_3DS : NAND);
dsi_set_key(&nand_ctx, key) ;
generate_key(key, console_id, ES);
dsi_set_key(&es_ctx, key) ;
dsi_set_key(&boot2_ctx, DSi_BOOT2_KEY) ;
swiSHA1Calc(nand_ctr_iv, emmc_cid, 16);
}
// crypt one block, in/out must be aligned to 32 bit(restriction induced by xor_128)
// offset as block offset, block as AES block
void dsi_nand_crypt_1(uint8_t* out, const uint8_t* in, uint32_t offset)
{
uint8_t ctr[16] ;
memcpy(ctr, nand_ctr_iv, sizeof(nand_ctr_iv)) ;
u128_add32(ctr, offset);
dsi_set_ctr(&nand_ctx, ctr) ;
dsi_crypt_ctr(&nand_ctx, in, out, 16) ;
}
void dsi_nand_crypt(uint8_t* out, const uint8_t* in, uint32_t offset, unsigned count)
{
uint8_t ctr[16] ;
memcpy(ctr, nand_ctr_iv, sizeof(nand_ctr_iv)) ;
u128_add32(ctr, offset);
for (unsigned i = 0; i < count; ++i)
{
dsi_set_ctr(&nand_ctx, ctr) ;
dsi_crypt_ctr(&nand_ctx, in, out, 16) ;
out += AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
u128_add32(ctr, 1);
}
}
void dsi_boot2_crypt_set_ctr(uint32_t size_r)
{
for (int i=0;i<4;i++)
{
boot2_ctr[i] = (size_r) >> (8*i) ;
boot2_ctr[i+4] = (-size_r) >> (8*i) ;
boot2_ctr[i+8] = (~size_r) >> (8*i) ;
boot2_ctr[i+12] = 0 ;
}
}
void dsi_boot2_crypt(uint8_t* out, const uint8_t* in, unsigned count)
{
for (unsigned i = 0; i < count; ++i)
{
dsi_set_ctr(&boot2_ctx, boot2_ctr) ;
dsi_crypt_ctr(&boot2_ctx, in, out, 16) ;
out += AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
u128_add32(boot2_ctr, 1);
}
}

View File

@ -0,0 +1,70 @@
#pragma once
#include <nds.h>
#ifdef __cplusplus
extern "C" {
#endif
/************************ Constants / Defines *********************************/
#define AES_BLOCK_SIZE 16
#define SHA1_LEN 20
#define KEYSEED_DSI_NAND_0 0x24ee6906
#define KEYSEED_DSI_NAND_1 0xe65b601d
#define KEYSEED_3DS_NAND_0 0xb358a6af
#define KEYSEED_3DS_NAND_1 0x544e494e
#define KEYSEED_3DS_NAND_2 0x4f444e45
#define KEYSEED_3DS_NAND_3 0x08c267b7
#define KEYSEED_ES_0 0x4e00004a
#define KEYSEED_ES_1 0x4a00004e
#define KEYSEED_ES_2 0xc80c4b72
#define GET_UINT32_BE(n, b, i) \
((uint8_t*)&(n))[0] = (b)[i + 3]; \
((uint8_t*)&(n))[1] = (b)[i + 2]; \
((uint8_t*)&(n))[2] = (b)[i + 1]; \
((uint8_t*)&(n))[3] = (b)[i + 0]
#define PUT_UINT32_BE(n, b, i) \
(b)[i + 0] = ((uint8_t*)&(n))[3]; \
(b)[i + 1] = ((uint8_t*)&(n))[2]; \
(b)[i + 2] = ((uint8_t*)&(n))[1]; \
(b)[i + 3] = ((uint8_t*)&(n))[0]
typedef enum {
ENCRYPT,
DECRYPT
} crypt_mode_t;
typedef enum {
NAND,
NAND_3DS,
ES
} key_mode_t;
// don't want to include nds.h just for this
void swiSHA1Calc(void *digest, const void *buf, size_t len);
int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len);
void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS);
void dsi_nand_crypt_1(uint8_t *out, const uint8_t* in, u32 offset);
void dsi_nand_crypt(uint8_t *out, const uint8_t* in, u32 offset, unsigned count);
int dsi_es_block_crypt(uint8_t *buf, unsigned buf_len, crypt_mode_t mode);
void dsi_boot2_crypt_set_ctr(uint32_t size_r);
void dsi_boot2_crypt(uint8_t* out, const uint8_t* in, unsigned count);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,346 @@
#include "dsi.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "u128_math.h"
void dsi_set_key( dsi_context* ctx,
const unsigned char key[16] )
{
unsigned char keyswap[16];
u128_swap(keyswap, key) ;
aes_setkey_enc(&ctx->aes, keyswap, 128);
}
void dsi_add_ctr( dsi_context* ctx,
unsigned int carry)
{
unsigned int counter[4];
unsigned char *outctr = (unsigned char*)ctx->ctr;
unsigned int sum;
signed int i;
for (i = 0; i < 4; i++)
counter[i] = (outctr[i * 4 + 0] << 24) | (outctr[i * 4 + 1] << 16) |
(outctr[i * 4 + 2] << 8) | (outctr[i * 4 + 3] << 0);
for (i = 3; i >= 0; i--) {
sum = counter[i] + carry;
carry = (uint)(sum < counter[i]);
counter[i] = sum;
}
for (i = 0; i < 4; i++) {
outctr[i * 4 + 0] = counter[i] >> 24;
outctr[i * 4 + 1] = counter[i] >> 16;
outctr[i * 4 + 2] = counter[i] >> 8;
outctr[i * 4 + 3] = counter[i] >> 0;
}
}
void dsi_set_ctr( dsi_context* ctx, const unsigned char ctr[16] ) {
for (int i = 0; i < 16; i++)ctx->ctr[i] = ctr[15-i];
}
void dsi_init_ctr( dsi_context* ctx, const unsigned char key[16], const unsigned char ctr[16]) {
// void dsi_init_ctr( dsi_context* ctx, const unsigned char key[16], const unsigned char ctr[12]) {
dsi_set_key(ctx, key);
dsi_set_ctr(ctx, ctr);
}
void dsi_crypt_ctr( dsi_context* ctx,
const void* in,
void* out,
unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i += 0x10) {
dsi_crypt_ctr_block(ctx, in+i, out+i);
}
}
void dsi_crypt_ctr_block( dsi_context* ctx,
const unsigned char input[16],
unsigned char output[16] )
{
int i;
unsigned char stream[16];
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->ctr, stream);
if (input) {
for (i=0; i<16; i++) {
output[i] = stream[15-i] ^ input[i];
}
} else {
for (i=0; i<16; i++)
output[i] = stream[15-i];
}
dsi_add_ctr(ctx, 1);
}
void dsi_init_ccm( dsi_context* ctx,
unsigned char key[16],
unsigned int maclength,
unsigned int payloadlength,
unsigned int assoclength,
unsigned char nonce[12] )
{
int i;
dsi_set_key(ctx, key);
ctx->maclen = maclength;
maclength = (maclength-2)/2;
payloadlength = (payloadlength+15) & ~15;
// CCM B0 block:
// [1-byte flags] [12-byte nonce] [3-byte size]
ctx->mac[0] = (maclength<<3) | 2;
if (assoclength)
ctx->mac[0] |= (1<<6);
for (i=0; i<12; i++)
ctx->mac[1+i] = nonce[11-i];
ctx->mac[13] = payloadlength>>16;
ctx->mac[14] = payloadlength>>8;
ctx->mac[15] = payloadlength>>0;
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
// CCM CTR:
// [1-byte flags] [12-byte nonce] [3-byte ctr]
ctx->ctr[0] = 2;
for (i=0; i<12; i++)
ctx->ctr[1+i] = nonce[11-i];
ctx->ctr[13] = 0;
ctx->ctr[14] = 0;
ctx->ctr[15] = 0;
dsi_crypt_ctr_block(ctx, 0, ctx->S0);
}
void dsi_encrypt_ccm_block( dsi_context* ctx,
unsigned char input[16],
unsigned char output[16],
unsigned char* mac )
{
int i;
for (i=0; i<16; i++)
ctx->mac[i] ^= input[15-i];
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
if (mac) {
for (i=0; i<16; i++)
mac[i] = ctx->mac[15-i] ^ ctx->S0[i];
}
if (output)
dsi_crypt_ctr_block(ctx, input, output);
}
void dsi_decrypt_ccm_block( dsi_context* ctx,
unsigned char input[16],
unsigned char output[16],
unsigned char* mac )
{
int i;
if (output) {
dsi_crypt_ctr_block(ctx, input, output);
for (i=0; i<16; i++)
ctx->mac[i] ^= output[15-i];
} else {
for (i=0; i<16; i++)
ctx->mac[i] ^= input[15-i];
}
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
if (mac) {
for (i=0; i<16; i++)
mac[i] = ctx->mac[15-i] ^ ctx->S0[i];
}
}
void dsi_decrypt_ccm( dsi_context* ctx,
unsigned char* input,
unsigned char* output,
unsigned int size,
unsigned char* mac )
{
unsigned char block[16];
unsigned char ctr[16];
while (size > 16) {
dsi_decrypt_ccm_block(ctx, input, output, mac);
if (input)
input += 16;
if (output)
output += 16;
size -= 16;
}
memcpy(ctr, ctx->ctr, 16);
memset(block, 0, 16);
dsi_crypt_ctr_block(ctx, block, block);
memcpy(ctx->ctr, ctr, 16);
memcpy(block, input, size);
dsi_decrypt_ccm_block(ctx, block, block, mac);
memcpy(output, block, size);
}
void dsi_encrypt_ccm( dsi_context* ctx,
unsigned char* input,
unsigned char* output,
unsigned int size,
unsigned char* mac )
{
unsigned char block[16];
while (size > 16) {
dsi_encrypt_ccm_block(ctx, input, output, mac);
if (input)
input += 16;
if (output)
output += 16;
size -= 16;
}
memset(block, 0, 16);
memcpy(block, input, size);
dsi_encrypt_ccm_block(ctx, block, block, mac);
memcpy(output, block, size);
}
void dsi_es_init( dsi_es_context* ctx,
unsigned char key[16] )
{
memcpy(ctx->key, key, 16);
ctx->randomnonce = 1;
}
void dsi_es_set_nonce( dsi_es_context* ctx,
unsigned char nonce[12] )
{
memcpy(ctx->nonce, nonce, 12);
ctx->randomnonce = 0;
}
void dsi_es_set_random_nonce( dsi_es_context* ctx )
{
ctx->randomnonce = 1;
}
int dsi_es_decrypt( dsi_es_context* ctx,
unsigned char* buffer,
unsigned char metablock[32],
unsigned int size )
{
unsigned char ctr[16];
unsigned char nonce[12];
unsigned char scratchpad[16];
unsigned char chkmac[16];
unsigned char genmac[16];
dsi_context cryptoctx;
unsigned int chksize;
memcpy(chkmac, metablock, 16);
memcpy(ctr, metablock + 16, 16);
ctr[0] = 0;
ctr[13] = 0;
ctr[14] = 0;
ctr[15] = 0;
dsi_init_ctr(&cryptoctx, ctx->key, ctr);
dsi_crypt_ctr_block(&cryptoctx, metablock+16, scratchpad);
chksize = (scratchpad[13]<<16) | (scratchpad[14]<<8) | (scratchpad[15]<<0);
if (scratchpad[0] != 0x3A) {
return -1;
}
if (chksize != size) {
return -2;
}
memcpy(nonce, metablock + 17, 12);
dsi_init_ccm(&cryptoctx, ctx->key, 16, size, 0, nonce);
dsi_decrypt_ccm(&cryptoctx, buffer, buffer, size, genmac);
if (memcmp(genmac, chkmac, 16) != 0) {
return -3;
}
return 0;
}
void dsi_es_encrypt( dsi_es_context* ctx,
unsigned char* buffer,
unsigned char metablock[32],
unsigned int size )
{
int i;
unsigned char nonce[12];
unsigned char mac[16];
unsigned char ctr[16];
unsigned char scratchpad[16];
dsi_context cryptoctx;
if (ctx->randomnonce) {
srand( (unsigned int)time(0) );
for (i=0; i<12; i++)
nonce[i] = rand();
} else {
memcpy(nonce, ctx->nonce, 12);
}
dsi_init_ccm(&cryptoctx, ctx->key, 16, size, 0, nonce);
dsi_encrypt_ccm(&cryptoctx, buffer, buffer, size, mac);
memset(scratchpad, 0, 16);
scratchpad[0] = 0x3A;
scratchpad[13] = size >> 16;
scratchpad[14] = size >> 8;
scratchpad[15] = size >> 0;
memset(ctr, 0, 16);
memcpy(ctr+1, nonce, 12);
dsi_init_ctr(&cryptoctx, ctx->key, ctr);
dsi_crypt_ctr_block(&cryptoctx, scratchpad, metablock+16);
memcpy(metablock+17, nonce, 12);
memcpy(metablock, mac, 16);
}

View File

@ -0,0 +1,105 @@
#ifndef _DSI_H_
#define _DSI_H_
#include "aes.h"
typedef struct
{
unsigned char ctr[16];
unsigned char mac[16];
unsigned char S0[16];
unsigned int maclen;
aes_context aes;
}
dsi_context;
typedef struct
{
unsigned char key[16];
unsigned char nonce[12];
int randomnonce;
} dsi_es_context;
#ifdef __cplusplus
extern "C" {
#endif
void dsi_set_key( dsi_context* ctx,
const unsigned char key[16] );
void dsi_add_ctr( dsi_context* ctx,
unsigned int carry );
void dsi_set_ctr( dsi_context* ctx,
const unsigned char ctr[16] );
void dsi_init_ctr( dsi_context* ctx,
const unsigned char key[16],
const unsigned char ctr[16]);
void dsi_crypt_ctr( dsi_context* ctx,
const void* in,
void* out,
unsigned int len);
void dsi_crypt_ctr_block( dsi_context* ctx,
const unsigned char input[16],
unsigned char output[16] );
void dsi_init_ccm( dsi_context* ctx,
unsigned char key[16],
unsigned int maclength,
unsigned int payloadlength,
unsigned int assoclength,
unsigned char nonce[12] );
void dsi_encrypt_ccm_block( dsi_context* ctx,
unsigned char input[16],
unsigned char output[16],
unsigned char* mac );
void dsi_decrypt_ccm_block( dsi_context* ctx,
unsigned char input[16],
unsigned char output[16],
unsigned char* mac );
void dsi_decrypt_ccm( dsi_context* ctx,
unsigned char* input,
unsigned char* output,
unsigned int size,
unsigned char* mac );
void dsi_encrypt_ccm( dsi_context* ctx,
unsigned char* input,
unsigned char* output,
unsigned int size,
unsigned char* mac );
void dsi_es_init( dsi_es_context* ctx,
unsigned char key[16] );
void dsi_es_set_nonce( dsi_es_context* ctx,
unsigned char nonce[12] );
void dsi_es_set_random_nonce( dsi_es_context* ctx );
int dsi_es_decrypt( dsi_es_context* ctx,
unsigned char* buffer,
unsigned char metablock[32],
unsigned int size );
void dsi_es_encrypt( dsi_es_context* ctx,
unsigned char* buffer,
unsigned char metablock[32],
unsigned int size );
#ifdef __cplusplus
}
#endif
#endif // _DSI_H_

View File

@ -0,0 +1,50 @@
/* f_xy.c
*
* This file was imported from godmode9i, but it is liely not the
* original source. twltool uses the same file.
*
* If you happen to know whom to credit I'd love to add the name
*
* Refactored to reduce the pointer casts and remove the dependency
* from tonccpy.
*/
#include <string.h>
#include <stdint.h>
#include "u128_math.h"
/************************ Constants / Defines *********************************/
const uint8_t DSi_KEY_MAGIC[16] = { 0x79, 0x3e, 0x4f, 0x1a, 0x5f, 0x0f, 0x68, 0x2a,
0x58, 0x02, 0x59, 0x29, 0x4e, 0xfb, 0xfe, 0xff };
const uint8_t DSi_NAND_KEY_Y[16] = { 0x76, 0xdc, 0xb9, 0x0a, 0xd3, 0xc4, 0x4d, 0xbd,
0x1d, 0xdd, 0x2d, 0x20, 0x05, 0x00, 0xa0, 0xe1 };
const uint8_t DSi_ES_KEY_Y[16] = { 0xe5, 0xcc, 0x5a, 0x8b, 0x56, 0xd0, 0xc9,0x72,
0x9c, 0x17, 0xe8, 0xdc, 0x39, 0x12, 0x36, 0xa9 };
const uint8_t DSi_BOOT2_KEY[16] = { 0x98, 0xee, 0x80, 0x80, 0x00, 0x6c, 0xb4, 0xf6,
0x3a, 0xc2, 0x6e, 0x62, 0xf9, 0xec, 0x34, 0xad };
/************************ Functions *******************************************/
void F_XY(uint8_t *key, const uint8_t *key_x, const uint8_t *key_y)
{
uint8_t key_xy[16];
for (int i=0; i<16; i++)
key_xy[i] = key_x[i] ^ key_y[i];
memcpy(key, DSi_KEY_MAGIC, sizeof(DSi_KEY_MAGIC));
u128_add(key, key_xy);
u128_lrot(key, 42);
}
//F_XY_reverse does the reverse of F(X^Y): takes (normal)key, and does F in reverse to generate the original X^Y key_xy.
void F_XY_reverse(const uint8_t *key, uint8_t *key_xy)
{
memcpy(key_xy, key, 16);
u128_rrot(key_xy, 42);
u128_sub(key_xy, DSi_KEY_MAGIC);
}

View File

@ -0,0 +1,36 @@
/* f_xy.h
*
* This file was imported from godmode9i, but it is liely not the
* original source. twltool uses the same file.
*
* If you happen to know whom to credit I'd love to add the name
*
* Refactored to reduce the pointer casts and remove the dependency
* from tonccpy.
*/
#ifndef _H_F_XY
#define _H_F_XY
#ifdef __cplusplus
extern "C" {
#endif
/************************ Constants / Defines *********************************/
extern const uint8_t DSi_KEY_MAGIC[16] ;
extern const uint8_t DSi_NAND_KEY_Y[16] ;
extern const uint8_t DSi_ES_KEY_Y[16] ;
extern const uint8_t DSi_BOOT2_KEY[16] ;
/************************ Function Protoypes **********************************/
void F_XY(uint8_t *key, const uint8_t *key_x, const uint8_t *key_y);
void F_XY_reverse(const uint8_t *key, uint8_t *key_xy);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,98 @@
/**
* \file padlock.h
*
* Copyright (C) 2006-2010, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_PADLOCK_H
#define POLARSSL_PADLOCK_H
#include "aes.h"
#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__)
#ifndef POLARSSL_HAVE_X86
#define POLARSSL_HAVE_X86
#endif
#define PADLOCK_RNG 0x000C
#define PADLOCK_ACE 0x00C0
#define PADLOCK_PHE 0x0C00
#define PADLOCK_PMM 0x3000
#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15))
#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x08E0
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief PadLock detection routine
*
* \param The feature to detect
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
int padlock_supports( int feature );
/**
* \brief PadLock AES-ECB block en(de)cryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if success, 1 if operation failed
*/
int padlock_xcryptecb( aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief PadLock AES-CBC buffer en(de)cryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if success, 1 if operation failed
*/
int padlock_xcryptcbc( aes_context *ctx,
int mode,
int length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#ifdef __cplusplus
}
#endif
#endif /* HAVE_X86 */
#endif /* padlock.h */

View File

@ -0,0 +1,106 @@
// u128_math
#include "u128_math.h"
#include <string.h>
// rotate a 128bit, little endian by shift bits in direction of increasing significance.
void u128_lrot(uint8_t *num, uint32_t shift)
{
uint8_t tmp[16];
for (int i=0;i<16;i++)
{
// rot: rotate to more significant.
// LSB is tmp[0], MSB is tmp[15]
const uint32_t byteshift = shift / 8 ;
const uint32_t bitshift = shift % 8;
tmp[(i+byteshift) % 16] = (num[i] << bitshift)
| ((num[(i+16-1) % 16] >> (8-bitshift)) & 0xff);
}
memcpy(num, tmp, 16) ;
}
// rotate a 128bit, little endian by shift bits in direction of decreasing significance.
void u128_rrot(uint8_t *num, uint32_t shift)
{
uint8_t tmp[16];
for (int i=0;i<16;i++)
{
// rot: rotate to less significant.
// LSB is tmp[0], MSB is tmp[15]
const uint32_t byteshift = shift / 8 ;
const uint32_t bitshift = shift % 8;
tmp[i] = (num[(i+byteshift) % 16] >> bitshift)
| ((num[(i+byteshift+1) % 16] << (8-bitshift)) & 0xff);
}
memcpy(num, tmp, 16) ;
}
// xor two 128bit, little endian values and store the result into the first
void u128_xor(uint8_t *a, const uint8_t *b)
{
for (int i=0;i<16;i++)
{
a[i] = a[i] ^ b[i] ;
}
}
// or two 128bit, little endian values and store the result into the first
void u128_or(uint8_t *a, const uint8_t *b)
{
for (int i=0;i<16;i++)
{
a[i] = a[i] | b[i] ;
}
}
// and two 128bit, little endian values and store the result into the first
void u128_and(uint8_t *a, const uint8_t *b)
{
for (int i=0;i<16;i++)
{
a[i] = a[i] & b[i] ;
}
}
// add two 128bit, little endian values and store the result into the first
void u128_add(uint8_t *a, const uint8_t *b)
{
uint8_t carry = 0 ;
for (int i=0;i<16;i++)
{
uint16_t sum = a[i] + b[i] + carry ;
a[i] = sum & 0xff ;
carry = sum >> 8 ;
}
}
// add two 128bit, little endian values and store the result into the first
void u128_add32(uint8_t *a, const uint32_t b)
{
uint8_t _b[16];
memset(_b, 0, sizeof(_b)) ;
for (int i=0;i<4;i++)
_b[i] = b >> (i*8) ;
u128_add(a, _b);
}
// sub two 128bit, little endian values and store the result into the first
void u128_sub(uint8_t *a, const uint8_t *b)
{
uint8_t carry = 0 ;
for (int i=0;i<16;i++)
{
uint16_t sub = a[i] - b[i] - (carry & 1);
a[i] = sub & 0xff ;
carry = sub >> 8 ;
}
}
void u128_swap(uint8_t *out, const uint8_t *in)
{
for (int i=0;i<16;i++)
{
out[15-i] = in[i];
}
}

View File

@ -0,0 +1,38 @@
// u128_math
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// left rotate by (shift % 128) bits
void u128_lrot(uint8_t *num, uint32_t shift) ;
// right rotate by (shift % 128) bits
void u128_rrot(uint8_t *num, uint32_t shift) ;
// bitwise xor strored to a
void u128_xor(uint8_t *a, const uint8_t *b) ;
// bitwise or strored to a
void u128_or(uint8_t *a, const uint8_t *b) ;
// bitwise and strored to a
void u128_and(uint8_t *a, const uint8_t *b) ;
// add b to a and store in a
void u128_add(uint8_t *a, const uint8_t *b) ;
// add 32 bit value b to a and store in a
void u128_add32(uint8_t *a, const uint32_t b) ;
// substract b from a and store in a
void u128_sub(uint8_t *a, const uint8_t *b) ;
// swap byte order
void u128_swap(uint8_t *out, const uint8_t *in) ;
#ifdef __cplusplus
}
#endif

View File

@ -1,21 +0,0 @@
/*
NitroHax -- Cheat tool for the Nintendo DS
Copyright (C) 2008 Michael "Chishm" Chisholm
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <nds/ndstypes.h>
void readBios (u8* dest, u32 src, u32 size);

View File

@ -1,54 +0,0 @@
#include <nds/asminc.h>
@This code comes from a post by CaitSith2 at gbadev.org - THANKS!!
@
@Code to dump the complete Nintendo DS ARM7 bios, including the
@first 0x1204 bytes residing in the secure area.
@
@The ARM7 bios has read protection where 0x(Word)[FFFF(Half word)[FF(Byte)[FF]]]
@is returned, if any reads are attempted while PC is outside the arm7 bios range.
@
@Additionally, if the PC is outside the 0x0000 - 0x1204 range, that range of the bios
@is completely locked out from reading.
@ void readBios (u8* dest, u32 src, u32 size)
.arm
BEGIN_ASM_FUNC readBios
adr r3,bios_dump+1
bx r3
.thumb
bios_dump:
push {r4-r7,lr} @Even though we don't use R7, the code we are jumping to is going
@trash R7, therefore, we must save it.
mov r5, r1 @ src
sub r1, r2, #1 @ size
mov r2, r0 @ dest
ldr r0,=0x5ED @The code that will be made to read the full bios resides here.
loop:
mov r6,#0x12 @We Subtract 12 from the location we wish to read
sub r3,r1,r6 @because the code at 0x5EC is LDRB R3, [R3,#0x12]
add r3, r3, r5
adr r6,ret
push {r2-r6} @The line of code at 0x5EE is POP {R2,R4,R6,R7,PC}
bx r0
.align
ret:
strb r3,[r2,r1] @Store the read byte contained in r3, to SRAM.
sub r1,#1 @Subtract 1
bpl loop @And branch as long as R1 doesn't roll into -1 (0xFFFFFFFF).
pop {r4-r7} @Restore the saved registers
pop {r3} @and return.
bx r3
.END
@The exact code that resides at 0x5EC (secure area range) of the arm7 bios.
@ROM:000005EC 9B 7C LDRB R3, [R3,#0x12]
@ROM:000005EE D4 BD POP {R2,R4,R6,R7,PC}

View File

@ -20,9 +20,6 @@
#include <assert.h>
#include <nds.h>
#include <nds/arm9/cache.h>
#include <nds/dma.h>
#include <nds/card.h>
#include <string.h>
#include <stdlib.h>
@ -30,25 +27,72 @@
#include "common.h"
#include "tonccpy.h"
#define BASE_DELAY (100)
/*#define ARM7OWNSCARD BIT(11)
#define ARM7OWNSROM BIT(7)*/
typedef union { char title[4]; u32 key; } GameCode;
/*void SetCardOwner(bool arm9) {
REG_EXMEMSTAT = (REG_EXMEMSTAT & ~ARM7OWNSCARD) | (arm9 ? 0 : ARM7OWNSCARD);
}*/
static u32 twlBlowfish = 0;
static u32 normalChip = 0;
static u32 portFlags = 0;
static u32 secureAreaData[CARD_SECURE_AREA_SIZE/sizeof(u32)];
static ALIGN(4) u32 twlSecureAreaData[CARD_SECURE_AREA_SIZE/sizeof(u32)];
// static bool shortInit = false;
// static u32 iCardId;
// u32 cardGetId() { return iCardId; }
static const u8 cardSeedBytes[] = { 0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5 };
void EnableSlot1() {
int oldIME = enterCriticalSection();
while((REG_SCFG_MC & 0x0c) == 0x0c) swiDelay(1 * BASE_DELAY);
if(!(REG_SCFG_MC & 0x0c)) {
REG_SCFG_MC = (REG_SCFG_MC & ~0x0c) | 4;
swiDelay(20 * BASE_DELAY);
REG_SCFG_MC = (REG_SCFG_MC & ~0x0c) | 8;
swiDelay(20 * BASE_DELAY);
}
/*REG_ROMCTRL = 0x20000000; // wait 27ms, then set ROMCTRL=20000000h
while((REG_ROMCTRL & 0x8000000))swiDelay(1 * BASE_DELAY);*/
leaveCriticalSection(oldIME);
}
void DisableSlot1() {
int oldIME = enterCriticalSection();
while((REG_SCFG_MC & 0x0c) == 0x0c) swiDelay(1 * BASE_DELAY);
if((REG_SCFG_MC & 0x0c) == 8) {
REG_SCFG_MC = (REG_SCFG_MC & ~0x0c) | 0x0c;
while((REG_SCFG_MC & 0x0c) != 0) swiDelay(1 * BASE_DELAY);
}
leaveCriticalSection(oldIME);
}
static const u8 cardSeedBytes[] = {0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5};
// chosen by fair dice roll.
// guaranteed to be random.
// static u32 getRandomNumber(void) { return 4; }
static u32 getRandomNumber(void) { return rand(); } // make this actually random lol. :P
// static u32 getRandomNumber(void) { return rand(); } // make this actually random lol. :P
static u32 getRandomNumber(void) { return 0xDDAC86F5; }
static void decryptSecureArea (u32 gameCode, u32* secureArea) {
int i;
init_keycode (gameCode, 2, 8);
static void decryptSecureArea (u32 gameCode, u32* secureArea, int iCardDevice) {
init_keycode (gameCode, 2, 8, iCardDevice);
crypt_64bit_down (secureArea);
init_keycode (gameCode, 3, 8);
for (i = 0; i < 0x200; i+= 2) { crypt_64bit_down (secureArea + i); }
init_keycode (gameCode, 3, 8, iCardDevice);
for (int i = 0; i < 0x200; i+= 2)crypt_64bit_down (secureArea + i);
}
static struct {
@ -61,7 +105,7 @@ static struct {
} key1data;
static void initKey1Encryption (u8* cmdData) {
static void initKey1Encryption (u8* cmdData, int iCardDevice) {
key1data.iii = getRandomNumber() & 0x00000fff;
key1data.jjj = getRandomNumber() & 0x00000fff;
key1data.kkkkk = getRandomNumber() & 0x000fffff;
@ -69,7 +113,11 @@ static void initKey1Encryption (u8* cmdData) {
key1data.mmm = getRandomNumber() & 0x00000fff;
key1data.nnn = getRandomNumber() & 0x00000fff;
cmdData[7] = CARD_CMD_ACTIVATE_BF;
if (iCardDevice) //DSi
cmdData[7]=0x3D; // CARD_CMD_ACTIVATE_BF2
else
cmdData[7]=CARD_CMD_ACTIVATE_BF;
cmdData[6] = (u8) (key1data.iii >> 4);
cmdData[5] = (u8) ((key1data.iii << 4) | (key1data.jjj >> 8));
cmdData[4] = (u8) key1data.jjj;
@ -122,10 +170,118 @@ static void cardDelay (u16 readTimeout) {
TIMER_DATA(0) = 0;
}
static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) {
if ((twlBlowfish == 0) || ndsHeader->unitCode == 0) return;
// Used for dumping the DSi arm9i/7i binaries
u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
u32 portFlagsKey1, portFlagsSecRead;
bool normalChip; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000
int secureBlockNumber;
int i;
u8 cmdData[8] __attribute__ ((aligned));
GameCode* gameCode;
if (REG_SCFG_EXT & BIT(31)) {
// int oldIME = 0;
// Reset card slot
DisableSlot1();
// oldIME = enterCriticalSection();
swiDelay(40 * BASE_DELAY);
// leaveCriticalSection(oldIME);
EnableSlot1();
// oldIME = enterCriticalSection();
swiDelay(30 * BASE_DELAY);
// leaveCriticalSection(oldIME);
}
// Dummy command sent after card reset
cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0);
//int iCardDevice = 1;
// Initialise blowfish encryption for KEY1 commands and decrypting the secure area
gameCode = (GameCode*)ndsHeader->gameCode;
init_keycode (gameCode->key, 1, 8, 1);
// Port 40001A4h setting for normal reads (command B7)
portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7);
// Port 40001A4h setting for KEY1 commands (usually 001808F8h)
portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) |
((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16));
// Adjust card transfer method depending on the most significant bit of the chip ID
if (normalChip == 0)portFlagsKey1 |= CARD_SEC_LARGE;
// 3Ciiijjj xkkkkkxx - Activate KEY1 Encryption Mode
initKey1Encryption(cmdData, 1);
cardPolledTransfer((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE, NULL, 0, cmdData);
// 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode
createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0);
if (normalChip > 0) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
// Set the KEY2 encryption registers
REG_ROMCTRL = 0;
REG_CARD_1B0 = cardSeedBytes[ndsHeader->deviceType & 0x07] | (key1data.nnn << 15) | (key1data.mmm << 27) | 0x6000;
REG_CARD_1B4 = 0x879b9b05;
REG_CARD_1B8 = key1data.mmm >> 5;
REG_CARD_1BA = 0x5c;
REG_ROMCTRL = CARD_nRESET | CARD_SEC_SEED | CARD_SEC_EN | CARD_SEC_DAT;
// Update the DS card flags to suit KEY2 encryption
portFlagsKey1 |= CARD_SEC_EN | CARD_SEC_DAT;
// 1lllliii jjjkkkkk - 2nd Get ROM Chip ID / Get KEY2 Stream
createEncryptedCommand (CARD_CMD_SECURE_CHIPID, cmdData, 0);
if (normalChip > 0) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1 | CARD_BLK_SIZE(7), NULL, 0, cmdData);
// 2bbbbiii jjjkkkkk - Get Secure Area Block
portFlagsSecRead = (ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F)))
| CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT;
int secureAreaOffset = 0;
for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) {
createEncryptedCommand (CARD_CMD_SECURE_READ, cmdData, secureBlockNumber);
if (normalChip > 0) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(1), twlSecureAreaData + secureAreaOffset, 0x200, cmdData);
secureAreaOffset += 0x200/sizeof(u32);
}
} else {
cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(4) | CARD_SEC_LARGE, twlSecureAreaData + secureAreaOffset, 0x1000, cmdData);
secureAreaOffset += 0x1000/sizeof(u32);
}
}
// Alllliii jjjkkkkk - Enter Main Data Mode
createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0);
if (normalChip > 0) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
twlBlowfish = 0x01;
}
u16 cardInit (sNDSHeaderExt* ndsHeader, u32 *chipID) {
u32 portFlagsKey1, portFlagsSecRead;
normalChip = 0; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000
u32* secureArea;
int secureBlockNumber;
int i;
@ -133,6 +289,8 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
GameCode* gameCode;
// shortInit = false;
// SetCardOwner(false);
// Dummy command sent after card reset
cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0);
@ -140,36 +298,43 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
static_assert(sizeof(tNDSHeader) == 0x160, "tNDSHeader not packed properly");
// Read the header
cardParamCommand (CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), (u32*)ndsHeader, sizeof(tNDSHeader));
cardReadHeader((u8*)ndsHeader);
// cardParamCommand (CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), (u32*)ndsHeader, sizeof(tNDSHeader));
// while (REG_ROMCTRL & CARD_BUSY);
// Check header CRC
if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E))return ERR_HEAD_CRC;
// 1st Get ROM Chip ID
cardParamCommand (CARD_CMD_HEADER_CHIPID, 0, (ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7), chipID, sizeof(u32));
// iCardId = cardReadID((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7));
// iCardId = cardReadID(CARD_CLK_SLOW);
// chipID = cardReadID(CARD_CLK_SLOW);
while (REG_ROMCTRL & CARD_BUSY);
// *chipID = iCardId;
// Initialise blowfish encryption for KEY1 commands and decrypting the secure area
gameCode = (GameCode*)ndsHeader->gameCode;
init_keycode (gameCode->key, 2, 8);
init_keycode (gameCode->key, 2, 8, 0);
// Port 40001A4h setting for normal reads (command B7)
portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7);
// Port 40001A4h setting for KEY1 commands (usually 001808F8h)
portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16));
// 1st Get ROM Chip ID
cardParamCommand (CARD_CMD_HEADER_CHIPID, 0, (ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7), chipID, sizeof(u32));
while (REG_ROMCTRL & CARD_BUSY);
// Adjust card transfer method depending on the most significant bit of the chip ID
normalChip = ((*chipID) & 0x80000000) != 0; // ROM chip ID MSB
if (!normalChip)portFlagsKey1 |= CARD_SEC_LARGE;
if(((*chipID) & 0x80000000) != 0)normalChip = 0xFFFF; // ROM chip ID MSB
if (normalChip == 0)portFlagsKey1 |= CARD_SEC_LARGE;
// 3Ciiijjj xkkkkkxx - Activate KEY1 Encryption Mode
initKey1Encryption (cmdData);
initKey1Encryption (cmdData, 0);
cardPolledTransfer((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE, NULL, 0, cmdData);
// 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode
createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0);
if (normalChip) {
if (normalChip > 0) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
@ -191,7 +356,7 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
// 1lllliii jjjkkkkk - 2nd Get ROM Chip ID / Get KEY2 Stream
createEncryptedCommand (CARD_CMD_SECURE_CHIPID, cmdData, 0);
if (normalChip) {
if (normalChip > 0) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
cardPolledTransfer(portFlagsKey1 | CARD_BLK_SIZE(7), NULL, 0, cmdData);
@ -205,7 +370,7 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) {
createEncryptedCommand (CARD_CMD_SECURE_READ, cmdData, secureBlockNumber);
if (normalChip) {
if (normalChip > 0) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
@ -221,7 +386,7 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
// Alllliii jjjkkkkk - Enter Main Data Mode
createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0);
if (normalChip) {
if (normalChip > 0) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
@ -230,47 +395,52 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
}
// Now deal with secure area decryption and verification
decryptSecureArea (gameCode->key, secureAreaData);
decryptSecureArea (gameCode->key, secureAreaData, 0);
secureArea = secureAreaData;
if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) {
// Secure area exists, so just clear the tag
secureArea[0] = 0xe7ffdeff;
secureArea[1] = 0xe7ffdeff;
}/* else {
// Secure area tag is not there, so destroy the entire secure area
for (i = 0; i < 0x200; i ++) {
*secureArea++ = 0xe7ffdeff;
}
return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR;
}*/
}
return ERR_NONE;
}
void cardRead (u32 src, u32* dest, size_t size) {
void cardRead(sNDSHeaderExt* ndsHeader, u32 src, u32* dest, size_t size) {
size_t readSize;
if ((src < CARD_SECURE_AREA_OFFSET) /*&& !shortInit*/) {
if ((twlBlowfish == 0) && (ndsHeader->unitCode & BIT(1)) && (src > ndsHeader->romSize))switchToTwlBlowfish(ndsHeader);
if (src < CARD_SECURE_AREA_OFFSET) {
return;
} else if (src < CARD_DATA_OFFSET) {
// Read data from secure area
readSize = src + size < CARD_DATA_OFFSET ? size : CARD_DATA_OFFSET - src;
memcpy (dest, (u8*)secureAreaData + src - CARD_SECURE_AREA_OFFSET, readSize);
tonccpy (dest, (u8*)secureAreaData + src - CARD_SECURE_AREA_OFFSET, readSize);
src += readSize;
dest += readSize/sizeof(*dest);
size -= readSize;
} else if ((ndsHeader->unitCode & BIT(1)) && (twlBlowfish > 0) && (src >= ndsHeader->arm9iromOffset) && (src < ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE)) {
// Read data from secure area
readSize = src + size < (ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE) ? size : (ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE) - src;
tonccpy (dest, (u8*)twlSecureAreaData + src - ndsHeader->arm9iromOffset, readSize);
src += readSize;
dest += readSize/sizeof(*dest);
size -= readSize;
if (size <= 0)return;
}
while (size > 0) {
readSize = size < CARD_DATA_BLOCK_SIZE ? size : CARD_DATA_BLOCK_SIZE;
cardParamCommand (CARD_CMD_DATA_READ, src, (portFlags &~CARD_BLK_SIZE(7)) | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), dest, readSize);
cardParamCommand (CARD_CMD_DATA_READ, src, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), dest, readSize);
src += readSize;
dest += readSize/sizeof(*dest);
size -= readSize;
}
}
// If booted from DSi System Menu short cart init with no card reads or pokes to rom ctrl registers can be done.
// System Menu is nice enough to do this for you. :P
// (also is the case for booting from DS Download Play. ;) )
@ -291,7 +461,7 @@ void cardRead (u32 src, u32* dest, size_t size) {
// Initialise blowfish encryption for KEY1 commands and decrypting the secure area
gameCode = (GameCode*)ndsHeader->gameCode;
init_keycode (gameCode->key, 2, 8);
init_keycode (gameCode->key, 2, 8, 0);
// Port 40001A4h setting for normal reads (command B7)
portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7);
@ -314,7 +484,7 @@ void cardRead (u32 src, u32* dest, size_t size) {
cardRead (ndsHeader->arm9romOffset, secureArea, secureBlockSize);
// Now deal with secure area decryption and verification
decryptSecureArea (gameCode->key, secureAreaData);
decryptSecureArea (gameCode->key, secureAreaData, 0);
secureArea = secureAreaData;
if (secureArea[0] == 0x72636e65 && secureArea[1] == 0x6a624f79) {

View File

@ -20,7 +20,6 @@
#define READ_CARD_H
#include <nds/ndstypes.h>
#include <nds/memory.h>
#include <stdlib.h>
#define CARD_NDS_HEADER_SIZE (0x200)
@ -121,8 +120,9 @@ typedef struct {
u8 dsi3[0x174];
} sNDSHeaderExt;
u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID);
void cardRead (u32 src, u32* dest, size_t size);
// u32 cardGetId();
u16 cardInit (sNDSHeaderExt* ndsHeader, u32 *chipID);
void cardRead (sNDSHeaderExt* ndsHeader, u32 src, u32* dest, size_t size);
// u32 cardInitShort (sNDSHeaderExt* ndsHeader, u32* chipID);
#endif // READ_CARD_H

View File

@ -64,7 +64,7 @@ arm7_reset:
@ ipcSendState(ARM7_BOOT)
strh r0, [r12]
ldr r0,=0x27FFE34
ldr r0,=0x2FFFE34
ldr r0,[r0]
bx r0

View File

@ -100,7 +100,7 @@ arm9_reset:
@ while (ipcRecvState() != ARM7_BOOT);
bl waitsync
ldr r10, =0x27FFE24
ldr r10, =0x2FFFE24
ldr r2, [r10]
@ Switch MPU to startup default
@ -130,6 +130,6 @@ mpu_initial_data:
.word 0x08000035 @ p15,0,c6,c3,0,r6 ;PU Protection Unit Data/Unified Region 3
.word 0x0300001b @ p15,0,c6,c4,0,r7 ;PU Protection Unit Data/Unified Region 4
.word 0xffff001d @ p15,0,c6,c6,0,r8 ;PU Protection Unit Data/Unified Region 6
.word 0x027ff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB
.word 0x02fff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB
.word 0x0300000a @ p15,0,c9,c1,0,r10 ;TCM Data TCM Base and Virtual Size
itcm_reset_code_end:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,8 @@
[NTRLAUNCHER]
TWLCLOCK = 0
TWLVRAM = 0
TWLMODE = 0
TWLRAM = 0
TWLVRAM = 0
TWLCLOCK = 0
SCFGUNLOCK = 0
ANIMATEDSPLASH = 0
NTRSPLASH = 0

View File

@ -13,7 +13,7 @@ export TARGET := NTR_Launcher
export TOPDIR := $(CURDIR)
export VERSION_MAJOR := 3
export VERSION_MINOR := 1
export VERSION_MINOR := 2
export VERSTRING := $(VERSION_MAJOR).$(VERSION_MINOR)
# specify a directory which contains the nitro filesystem
@ -24,6 +24,7 @@ NITRO_FILES := CartFiles
#---------------------------------------------------------------------------------
# main targets
# -g KKGP 01 "NTR Launcher" -z 80040000 -u 00030004 -a 00000138 -p 0001 \
#---------------------------------------------------------------------------------
all: bootloader ndsbootloader $(TARGET).nds
@ -34,8 +35,8 @@ dist: all
$(TARGET).nds: $(TARGET).arm7 $(TARGET).arm9
ndstool -c $(TARGET).nds -7 $(TARGET).arm7.elf -9 $(TARGET).arm9.elf \
-b $(CURDIR)/icon.bmp "NTR Launcher;Slot-1 Launcher;Apache Thunder & RocketRobz" \
-g KKGP 01 "NTR Launcher" -z 80040000 -u 00030004 -a 00000138 -p 0001 \
-b $(CURDIR)/icon.bmp "NTR Launcher v$(VERSTRING);Slot-1 Launcher;Apache Thunder & RocketRobz" \
-g KKGP 01 "NTR Launcher" -z 80040407 -u 00030004 -a 00000138 -p 0001 \
-d $(NITRO_FILES)
@cp $(TARGET).nds 00000000.app

View File

@ -24,8 +24,8 @@ DATA :=
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi
CFLAGS := -g -Wall -O2\
-fomit-frame-pointer\
CFLAGS := -g -Wall -O2 \
-fomit-frame-pointer \
-ffast-math \
$(ARCH)

View File

@ -218,7 +218,7 @@ int main(void) {
irqSet(IRQ_VCOUNT, VcountHandler);
irqSet(IRQ_VBLANK, VblankHandler);
irqEnable( IRQ_VBLANK | IRQ_VCOUNT);
irqEnable(IRQ_VBLANK | IRQ_VCOUNT);
i2cWriteRegister(0x4A, 0x12, 0x00); // Press power-button for auto-reset
i2cWriteRegister(0x4A, 0x70, 0x01); // Bootflag = Warmboot/SkipHealthSafety

View File

@ -27,7 +27,7 @@ MUSIC := audio
ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork
CFLAGS := -g -Wall -O2 \
-fomit-frame-pointer\
-fomit-frame-pointer \
-ffast-math \
$(ARCH)

View File

@ -1,6 +1,7 @@
.arm
.global dsCardDefault_bin, hbNoIcon_bin
.global dsCardDefault_bin, dsCardInvalid_bin, hbNoIcon_bin
dsCardDefault_bin: .incbin "../include/dsCardDefault.bin"
dsCardInvalid_bin: .incbin "../include/dsCardInvalid.bin"
hbNoIcon_bin: .incbin "../include/hbNoIcon.bin"

View File

@ -1,21 +1,3 @@
/*
NitroHax -- Cheat tool for the Nintendo DS
Copyright (C) 2008 Michael "Chishm" Chisholm
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LAUNCHERDATA_H
#define LAUNCHERDATA_H
@ -23,13 +5,12 @@
extern "C" {
#endif
#define LAUNCH_DATA 0x020007F0
#define CartHeaderCopy 0x02000000
#define CartChipIDCopy 0x02000180
#define CartBannerBuffer 0x02500000
// #define InitialCartBannerOffset 0x02FFC068
#define LAUNCH_DATA 0x020007F0
// #define InitialCartBannerOffset 0x02FFC068
#define InitialCartHeaderTWL 0x02FFC000 // System Menu keeps cart's header here (if cart is present) on initial boot of any DSiWare!
#define InitialCartHeader 0x02FFFA80 // System Menu keeps cart's header here (if cart is present) on initial boot of any DSiWare!
#define InitialCartChipID 0x02FFFC00 // System Menu keeps cart's chip id here (if cart is present) on initial boot of any DSiWare!
@ -40,10 +21,11 @@ typedef struct sLauncherSettings {
u8 scfgUnlock;
u8 twlMode;
u8 twlCLK;
u8 twlRAM;
u8 twlVRAM;
u8 debugMode;
u8 fastBoot;
u8 unused2;
u8 isTWLSRL;
u32 cachedChipID;
} tLauncherSettings;

View File

@ -19,16 +19,18 @@
#include <stddef.h>
#include <nds.h>
#include "nds_card.h"
#include "read_card.h"
void CardReset(bool properReset) {
int i;
sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart
if (isDSiMode()) {
// Reset card slot
disableSlot1();
/*disableSlot1();
for (i = 0; i < 25; i++) { swiWaitForVBlank(); }
enableSlot1();
for (i = 0; i < 15; i++) { swiWaitForVBlank(); }
for (i = 0; i < 15; i++) { swiWaitForVBlank(); }*/
ResetSlot();
if (!properReset) {
// Dummy command sent after card reset
@ -43,9 +45,9 @@ void CardReset(bool properReset) {
for (i = 0; i < 10; i++) { swiWaitForVBlank(); }
REG_AUXSPICNT=CARD_CR1_ENABLE|CARD_CR1_IRQ;
REG_ROMCTRL=CARD_nRESET|CARD_SEC_SEED;
while (REG_ROMCTRL&CARD_BUSY);
while (REG_ROMCTRL&CARD_BUSY)swiWaitForVBlank();
cardReset();
while (REG_ROMCTRL&CARD_BUSY);
while (REG_ROMCTRL&CARD_BUSY)swiWaitForVBlank();
}
}

View File

@ -139,3 +139,4 @@ typedef struct {
//static_assert(sizeof(sNDSHeaderExt) == 0x3B4, "sizeof(sNDSHeaderExt) is not 0x3B4 bytes");
#endif // NDS_HEADER2

View File

@ -39,8 +39,10 @@ extern "C" {
extern u32 cardNandRomEnd;
extern u32 cardNandRwStart;
int cardInit (sNDSHeaderExt* ndsHeader);
int cardInitShort(sNDSHeaderExt* ndsHeader);
void ResetSlot();
u32 cardInit (sNDSHeaderExt* ndsHeader);
u32 cardInitShort(sNDSHeaderExt* ndsHeader);
void cardRead (u32 src, void* dest, bool nandSave);
void cardReadAlt (u32 src, void* dest, size_t size);

View File

@ -72,7 +72,18 @@ u32 cardNandRwStart = 0;
static const u8 cardSeedBytes[] = { 0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5 };
static u32 getRandomNumber(void) { return rand(); }
static u32 getRandomNumber() { return 0xDDAC86F5; }
void ResetSlot() {
// Reset card slot
if((REG_SCFG_MC != 0x11) && (REG_SCFG_MC != 0x10)) {
disableSlot1();
for(int i = 0; i < 15; i++)swiWaitForVBlank();
}
enableSlot1();
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();
for(int i = 0; i < 15; i++)swiWaitForVBlank();
}
//---------------------------------------------------------------------------------
// https://github.com/devkitPro/libnds/blob/105d4943dbac8f2bd99a47b22cd3ed48f96af083/source/common/card.c#L47-L62
@ -302,8 +313,7 @@ static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) {
twlBlowfish = true;
}
int cardInit (sNDSHeaderExt* ndsHeader) {
u32 cardInit (sNDSHeaderExt* ndsHeader) {
u32 portFlagsKey1, portFlagsSecRead;
normalChip = false; // As defined by GBAtek, normal chip secure area and header are accessed in blocks of 0x200, other chip in blocks of 0x1000
nandChip = false;
@ -316,41 +326,37 @@ int cardInit (sNDSHeaderExt* ndsHeader) {
twlBlowfish = false;
sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart
if (isDSiMode()) {
// Reset card slot
if(REG_SCFG_MC != 0x11){
disableSlot1();
for(i = 0; i < 15; i++)swiWaitForVBlank();
}
enableSlot1();
for(i = 0; i < 10; i++)swiWaitForVBlank();
ResetSlot();
// Dummy command sent after card reset
cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0);
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();
}
REG_ROMCTRL=0;
REG_AUXSPICNT=0;
/*REG_ROMCTRL = 0;
REG_AUXSPICNT = 0;
//ioDelay2(167550);
for(i = 0; i < 25; i++) { swiWaitForVBlank(); }
REG_AUXSPICNT=CARD_CR1_ENABLE|CARD_CR1_IRQ;
REG_ROMCTRL=CARD_nRESET|CARD_SEC_SEED;
while(REG_ROMCTRL&CARD_BUSY) ;
REG_AUXSPICNT = (CARD_CR1_ENABLE | CARD_CR1_IRQ);
REG_ROMCTRL = (CARD_nRESET | CARD_SEC_SEED);
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();
cardReset();
while(REG_ROMCTRL&CARD_BUSY) ;
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();*/
toncset(headerData, 0, 0x1000);
// Read the header
cardParamCommand (CARD_CMD_HEADER_READ, 0,
CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
(void*)headerData, 0x200/sizeof(u32));
while(REG_ROMCTRL&CARD_BUSY);
cardReadHeader((u8*)headerData);
/*cardParamCommand (CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), (void*)headerData, 0x200/sizeof(u32));
while(REG_ROMCTRL & CARD_BUSY);*/
tonccpy(ndsHeader, headerData, 0x200);
iCardId=cardReadID(CARD_CLK_SLOW);
while(REG_ROMCTRL & CARD_BUSY);
iCardId = cardReadID(CARD_CLK_SLOW);
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();
*(u32*)InitialCartChipID = iCardId;
normalChip = (iCardId & BIT(31)) != 0; // ROM chip ID MSB
nandChip = (iCardId & BIT(27)) != 0; // Card has a NAND chip
@ -377,35 +383,23 @@ int cardInit (sNDSHeaderExt* ndsHeader) {
}
// Check header CRC
if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E)) {
return ERR_HEAD_CRC;
}
/*
// Check logo CRC
if (ndsHeader->logoCRC16 != 0xCF56) {
return ERR_LOGO_CRC;
}
*/
if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E))return ERR_HEAD_CRC;
// Initialise blowfish encryption for KEY1 commands and decrypting the secure area
gameCode = (GameCode*)ndsHeader->gameCode;
init_keycode (gameCode->key, 2, 8, 0);
// Port 40001A4h setting for normal reads (command B7)
portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7);
portFlags = (ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7));
// Port 40001A4h setting for KEY1 commands (usually 001808F8h)
portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) |
((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16));
portFlagsKey1 = (CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16)));
// Adjust card transfer method depending on the most significant bit of the chip ID
if (!normalChip) {
portFlagsKey1 |= CARD_SEC_LARGE;
}
if (!normalChip)portFlagsKey1 |= CARD_SEC_LARGE;
// 3Ciiijjj xkkkkkxx - Activate KEY1 Encryption Mode
initKey1Encryption (cmdData, 0);
cardPolledTransfer((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE, NULL, 0, cmdData);
cardPolledTransfer (((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE), NULL, 0, cmdData);
// 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode
createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0);
@ -418,11 +412,11 @@ int cardInit (sNDSHeaderExt* ndsHeader) {
// Set the KEY2 encryption registers
REG_ROMCTRL = 0;
REG_CARD_1B0 = cardSeedBytes[ndsHeader->deviceType & 0x07] | (key1data.nnn << 15) | (key1data.mmm << 27) | 0x6000;
REG_CARD_1B4 = 0x879b9b05;
REG_CARD_1B8 = key1data.mmm >> 5;
REG_CARD_1B0 = (cardSeedBytes[ndsHeader->deviceType & 0x07] | (key1data.nnn << 15) | (key1data.mmm << 27) | 0x6000);
REG_CARD_1B4 = 0x879B9B05;
REG_CARD_1B8 = (key1data.mmm >> 5);
REG_CARD_1BA = 0x5c;
REG_ROMCTRL = CARD_nRESET | CARD_SEC_SEED | CARD_SEC_EN | CARD_SEC_DAT;
REG_ROMCTRL = (CARD_nRESET | CARD_SEC_SEED | CARD_SEC_EN | CARD_SEC_DAT);
// Update the DS card flags to suit KEY2 encryption
portFlagsKey1 |= CARD_SEC_EN | CARD_SEC_DAT;
@ -434,11 +428,10 @@ int cardInit (sNDSHeaderExt* ndsHeader) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1 | CARD_BLK_SIZE(7), NULL, 0, cmdData);
cardPolledTransfer((portFlagsKey1 | CARD_BLK_SIZE(7)), NULL, 0, cmdData);
// 2bbbbiii jjjkkkkk - Get Secure Area Block
portFlagsSecRead = (ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F)))
| CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT;
portFlagsSecRead = ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F))) | CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT);
int secureAreaOffset = 0;
for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) {
@ -448,11 +441,11 @@ int cardInit (sNDSHeaderExt* ndsHeader) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(1), secureArea + secureAreaOffset, 0x200, cmdData);
cardPolledTransfer((portFlagsSecRead | CARD_BLK_SIZE(1)), (secureArea + secureAreaOffset), 0x200, cmdData);
secureAreaOffset += 0x200/sizeof(u32);
}
} else {
cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(4) | CARD_SEC_LARGE, secureArea + secureAreaOffset, 0x1000, cmdData);
cardPolledTransfer((portFlagsSecRead | CARD_BLK_SIZE(4) | CARD_SEC_LARGE), (secureArea + secureAreaOffset), 0x1000, cmdData);
secureAreaOffset += 0x1000/sizeof(u32);
}
}
@ -469,12 +462,10 @@ int cardInit (sNDSHeaderExt* ndsHeader) {
//CycloDS doesn't like the dsi secure area being decrypted
if((ndsHeader->arm9romOffset != 0x4000) || secureArea[0] || secureArea[1])decryptSecureArea (gameCode->key, secureArea, 0);
if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) {
if (secureArea[0] == 0x72636E65 /*'encr'*/ && secureArea[1] == 0x6A624F79 /*'yObj'*/) {
// Secure area exists, so just clear the tag
secureArea[0] = 0xe7ffdeff;
secureArea[1] = 0xe7ffdeff;
} else {
//return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR;
secureArea[0] = 0xE7FFDEFF;
secureArea[1] = 0xE7FFDEFF;
}
// Set NAND card section location variables
@ -496,7 +487,7 @@ int cardInit (sNDSHeaderExt* ndsHeader) {
// If booted from DSi System Menu short cart init with no card reads or pokes to rom ctrl registers can be done.
// System Menu is nice enough to do this for you. :P
// (also is the case for booting from DS Download Play. ;) )
int cardInitShort(sNDSHeaderExt* ndsHeader) {
u32 cardInitShort(sNDSHeaderExt* ndsHeader) {
normalChip = false; // As defined by GBAtek, normal chip secure area and header are accessed in blocks of 0x200, other chip in blocks of 0x1000
nandChip = false;
nandSection = -1;
@ -515,8 +506,8 @@ int cardInitShort(sNDSHeaderExt* ndsHeader) {
iCardId = *(u32*)CartChipIDCopy; // This location contains cart's chipID when booting DSiWare that has Slot-1 access.
// iCardId = *(u32*)0x027FF800; // This location contains cart's chipID for DS Download Play users
normalChip = (iCardId & BIT(31)) != 0; // ROM chip ID MSB
nandChip = (iCardId & BIT(27)) != 0; // Card has a NAND chip
normalChip = ((iCardId & BIT(31)) != 0); // ROM chip ID MSB
nandChip = ((iCardId & BIT(27)) != 0); // Card has a NAND chip
tonccpy(ndsHeader, headerData, 0x200);
@ -528,20 +519,20 @@ int cardInitShort(sNDSHeaderExt* ndsHeader) {
init_keycode (gameCode->key, 2, 8, 0);
// Port 40001A4h setting for normal reads (command B7)
portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7);
portFlags = (ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7));
if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) {
if (secureArea[0] == 0x72636E65 /*'encr'*/ && secureArea[1] == 0x6A624F79 /*'yObj'*/) {
// Secure area exists, so just clear the tag
secureArea[0] = 0xe7ffdeff;
secureArea[1] = 0xe7ffdeff;
secureArea[0] = 0xE7FFDEFF;
secureArea[1] = 0xE7FFDEFF;
}
// Set NAND card section location variables
if (nandChip) {
if(ndsHeader->nandRomEnd != 0) {
// TWL cards (Face Training) multiply by 0x80000 instead of 0x20000
cardNandRomEnd = ndsHeader->nandRomEnd * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000);
cardNandRwStart = ndsHeader->nandRwStart * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000);
cardNandRomEnd = (ndsHeader->nandRomEnd * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000));
cardNandRwStart = (ndsHeader->nandRwStart * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000));
} else {
// Jam with the Band (J) (大合奏!バンドブラザーズ) doesn't have the RW section in the header
cardNandRomEnd = 0x7200000;

126
arm9/common/tonccpy.itcm.c Normal file
View File

@ -0,0 +1,126 @@
#include <stddef.h>
#include "tonccpy.h"
//# tonccpy.c
//! VRAM-safe cpy.
/*! This version mimics memcpy in functionality, with
the benefit of working for VRAM as well. It is also
slightly faster than the original memcpy, but faster
implementations can be made.
\param dst Destination pointer.
\param src Source pointer.
\param size Fill-length in bytes.
\note The pointers and size need not be word-aligned.
*/
void tonccpy(void *dst, const void *src, uint size) {
if(size==0 || dst==NULL || src==NULL) { return; }
uint count;
u16 *dst16; // hword destination
u8 *src8; // byte source
// Ideal case: copy by 4x words. Leaves tail for later.
if( ((u32)src|(u32)dst)%4==0 && size>=4) {
u32 *src32= (u32*)src, *dst32= (u32*)dst;
count= size/4;
uint tmp= count&3;
count /= 4;
// Duff's Device, good friend!
// Added fall through attribute to silance the compiler about this. ;)
switch(tmp) {
do { *dst32++ = *src32++; // fallthrough
case 3: *dst32++ = *src32++; // fallthrough
case 2: *dst32++ = *src32++; // fallthrough
case 1: *dst32++ = *src32++; // fallthrough
case 0: ;} while(count--); // fallthrough
}
// Check for tail
size &= 3;
if(size == 0) { return; }
src8= (u8*)src32;
dst16= (u16*)dst32;
} else {
// Unaligned.
uint dstOfs= (u32)dst&1;
src8= (u8*)src;
dst16= (u16*)(dst-dstOfs);
// Head: 1 byte.
if(dstOfs != 0) {
*dst16= (*dst16 & 0xFF) | *src8++<<8;
dst16++;
if(--size==0) { return; }
}
}
// Unaligned main: copy by 2x byte.
count= size/2;
while(count--) {
*dst16++ = src8[0] | src8[1]<<8;
src8 += 2;
}
// Tail: 1 byte.
if(size&1) { *dst16= (*dst16 &~ 0xFF) | *src8; }
}
//# toncset.c
//! VRAM-safe memset, internal routine.
/*! This version mimics memset in functionality, with
the benefit of working for VRAM as well. It is also
slightly faster than the original memset.
\param dst Destination pointer.
\param fill Word to fill with.
\param size Fill-length in bytes.
\note The \a dst pointer and \a size need not be
word-aligned. In the case of unaligned fills, \a fill
will be masked off to match the situation.
*/
void __toncset(void *dst, u32 fill, uint size) {
if(size==0 || dst==NULL) { return; }
uint left= (u32)dst&3;
u32 *dst32= (u32*)(dst-left);
u32 count, mask;
// Unaligned head.
if(left != 0) {
// Adjust for very small stint.
if(left+size<4) {
mask= BIT_MASK(size*8)<<(left*8);
*dst32= (*dst32 &~ mask) | (fill & mask);
return;
}
mask= BIT_MASK(left*8);
*dst32= (*dst32 & mask) | (fill&~mask);
dst32++;
size -= 4-left;
}
// Main stint.
count= size/4;
uint tmp= count&3;
count /= 4;
// Added fall through attribute to silance the compiler about this. ;)
switch(tmp) {
do { *dst32++ = fill; // fallthrough
case 3: *dst32++ = fill; // fallthrough
case 2: *dst32++ = fill; // fallthrough
case 1: *dst32++ = fill; // fallthrough
case 0: ;} while(count--); // fallthrough
}
// Tail
size &= 3;
if(size) {
mask= BIT_MASK(size*8);
*dst32= (*dst32 &~ mask) | (fill & mask);
}
}

View File

@ -25,12 +25,13 @@
#include <string>
#include <vector>
#include "read_card.h"
#include "launcherData.h"
extern bool cartInsertedOnBoot;
extern sNDSHeaderExt ntrHeader;
std::string browseForFile (const std::vector<std::string>& extensionList);
std::string browseForFile (const std::vector<std::string>& extensionList, tLauncherSettings launchdata);
#endif //FILE_BROWSE_H

View File

@ -35,6 +35,8 @@
#include "iconTitle.h"
#include "read_card.h"
#include "audio.h"
#include "tonccpy.h"
#include "launcherData.h"
#define SCREEN_COLS 30
#define ENTRIES_PER_SCREEN 20
@ -60,18 +62,24 @@ extern bool cartSelected;
bool cartInsertedOnBoot = false;
static void cartCheck() {
static void cartCheck(tLauncherSettings launchdata) {
switch (REG_SCFG_MC) {
case 0x10: {
if (!cardInserted)cardInserted = true;
initialLoad = false;
if (cartInsertedOnBoot)cartInsertedOnBoot = false;
if (cartInsertedOnBoot) {
cartInsertedOnBoot = false;
launchdata.cachedChipID = 0x00000000;
}
}break;
case 0x11: {
cardInserted = false;
initialLoad = false;
if (cartSelected)cartSelected = false;
if (cartInsertedOnBoot)cartInsertedOnBoot = false;
if (cartInsertedOnBoot) {
cartInsertedOnBoot = false;
launchdata.cachedChipID = 0x00000000;
}
}break;
case 0x18: {
cardInserted = true;
@ -85,10 +93,12 @@ static void cartCheck() {
}
if (cartInsertedOnBoot)cartInsertedOnBoot = false;
if (cartSelected)cartSelected = false;
launchdata.cachedChipID = 0x00000000;
ToggleBackground(true);
return;
}
if (cardInserted && initialLoad) {
launchdata.cachedChipID = *(u32*)0x02FFFC00;
cardInitShort(&ntrHeader);
cartIconUpdate(0, initialLoad);
initialLoad = false;
@ -97,7 +107,9 @@ static void cartCheck() {
ToggleBackground(false);
} else if (cardInserted && !cardLoaded){
cardInit(&ntrHeader);
for (int i = 0; i < 25; i++)swiWaitForVBlank();
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();
launchdata.cachedChipID = cardGetId();
for (int i = 0; i < 30; i++)swiWaitForVBlank();
cartIconUpdate(ntrHeader.bannerOffset, false);
ToggleBackground(false);
cardLoaded = true;
@ -202,7 +214,7 @@ void showDirectoryContents (const vector<DirEntry>& dirContents, int startRow) {
}
}
string browseForFile (const vector<string>& extensionList) {
string browseForFile (const vector<string>& extensionList, tLauncherSettings launchdata) {
int pressed = 0;
int screenOffset = 0;
int fileOffset = 0;
@ -223,7 +235,7 @@ string browseForFile (const vector<string>& extensionList) {
// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
do {
cartCheck();
cartCheck(launchdata);
scanKeys();
pressed = keysDownRepeat();
swiWaitForVBlank();

View File

@ -42,53 +42,61 @@
using namespace std;
// ALIGN(4) sNDSHeaderExt NTRHeader;
static char gameTitle[13] = {0};
// static char gameCode[5] = {0};
static u8* fileBuffer;
static ALIGN(4) u8* fileBuffer;
static const int FileListSize = 13;
static const u32 FileMaxSize = 0x500000;
static const char* NitroSourceFileList[9] = {
"nitro:/NTR_Launcher/Acekard2i.nds",
"nitro:/NTR_Launcher/ActionReplayDS.nds",
"nitro:/NTR_Launcher/DSTwo.nds",
"nitro:/NTR_Launcher/EZFlashV.nds",
"nitro:/NTR_Launcher/R4DS_Ultra.nds",
"nitro:/NTR_Launcher/R4i_SDHC_AVRJ.nds",
"nitro:/NTR_Launcher/R4iGold_Launcher.nds",
"nitro:/NTR_Launcher/R4iSDHC_Demon.nds",
"nitro:/NTR_Launcher/TTDS.nds"
static const char* NitroSourceFileList[FileListSize] = {
"nitro:/NTR_Launcher/Acekard2i.nds", // 0
"nitro:/NTR_Launcher/ActionReplayDS.nds", // 1
"nitro:/NTR_Launcher/CycloDS.nds", // 2
"nitro:/NTR_Launcher/DSONEi.nds", // 3
"nitro:/NTR_Launcher/DSTwo.nds", // 4
"nitro:/NTR_Launcher/EZFlashV.nds", // 5
"nitro:/NTR_Launcher/NCARD.nds", // 6
"nitro:/NTR_Launcher/R4DS.nds", // 7
"nitro:/NTR_Launcher/R4DS_Ultra.nds", // 8
"nitro:/NTR_Launcher/R4i_SDHC_AVRJ.nds", // 9
"nitro:/NTR_Launcher/R4iGold_Launcher.nds", // 10
"nitro:/NTR_Launcher/R4iSDHC_Demon.nds", // 11
"nitro:/NTR_Launcher/TTDS.nds" // 12
};
static const char* NitroDestFileList[9] = {
"sd:/NTR_Launcher/Acekard2i.nds",
"sd:/NTR_Launcher/ActionReplayDS.nds",
"sd:/NTR_Launcher/DSTwo.nds",
"sd:/NTR_Launcher/EZFlashV.nds",
"sd:/NTR_Launcher/R4DS_Ultra.nds",
"sd:/NTR_Launcher/R4i_SDHC_AVRJ.nds",
"sd:/NTR_Launcher/R4iGold_Launcher.nds",
"sd:/NTR_Launcher/R4iSDHC_Demon.nds",
"sd:/NTR_Launcher/TTDS.nds"
static const char* NitroDestFileList[FileListSize] = {
"sd:/NTR_Launcher/Acekard2i.nds", // 0
"sd:/NTR_Launcher/ActionReplayDS.nds", // 1
"sd:/NTR_Launcher/CycloDS.nds", // 2
"sd:/NTR_Launcher/DSONEi.nds", // 3
"sd:/NTR_Launcher/DSTwo.nds", // 4
"sd:/NTR_Launcher/EZFlashV.nds", // 5
"sd:/NTR_Launcher/NCARD.nds", // 6
"sd:/NTR_Launcher/R4DS.nds", // 7
"sd:/NTR_Launcher/R4DS_Ultra.nds", // 8
"sd:/NTR_Launcher/R4i_SDHC_AVRJ.nds", // 9
"sd:/NTR_Launcher/R4iGold_Launcher.nds", // 10
"sd:/NTR_Launcher/R4iSDHC_Demon.nds", // 11
"sd:/NTR_Launcher/TTDS.nds" // 12
};
static void DoWait(int waitTime = 30) { for (int i = 0; i < waitTime; i++)swiWaitForVBlank(); };
static void DoCardInit() {
sysSetCardOwner(BUS_OWNER_ARM9);
switch (REG_SCFG_MC) {
case 0x10: { enableSlot1(); DoWait(15); }break;
case 0x11: { enableSlot1(); DoWait(15); }break;
}
// Do cart init stuff to wake cart up. DLDI init may fail otherwise!
CardReset(true);
cardReadHeader((u8*)&ntrHeader);
cardInit(&ntrHeader);
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();
// CardReset(true);
// cardReadHeader((u8*)&ntrHeader);
CardReset(false);
// cardInit(&ntrHeader);
tonccpy(gameTitle, ntrHeader.gameTitle, 12);
// tonccpy(gameCode, ntrHeader.gameCode, 4);
// DoWait(25);
while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();
}
@ -121,30 +129,28 @@ static int stop(void) {
}
static void CheckFolder() {
// if (sizeof(NitroSourceFileList) != sizeof(NitroDestFileList))return;
bool copyNeeded = false;
int listSize = 8;
for (int i = 0; i < listSize; i++) {
int i = 0;
for (i = 0; i < FileListSize; i++) {
if (access(NitroDestFileList[i], F_OK) != 0) {
copyNeeded = true;
break;
}
}
if (!copyNeeded)return;
printf("\n\n\n\n\n\n\n\n\n Setting up Stage2 folder");
printf("\n\n Please Wait...\n");
u32 BufferSize = 0x40000;
fileBuffer = (u8*)malloc(BufferSize);
for (int i = 0; i < listSize; i++) {
fileBuffer = (u8*)malloc(FileMaxSize);
for (i = 0; i < FileListSize; i++) {
if (access(NitroDestFileList[i], F_OK) != 0) {
FILE *src = fopen(NitroSourceFileList[i], "rb");
if (src) {
fseek(src, 0, SEEK_END);
u32 fSize = ftell(src);
// toncset((u8*)fileBuffer, 0xFF, fSize);
fseek(src, 0, SEEK_SET);
if (fSize <= BufferSize) {
if (fSize <= FileMaxSize) {
FILE *dest = fopen(NitroDestFileList[i], "wb");
if (dest) {
fread((u8*)fileBuffer, 1, fSize, src);
@ -164,7 +170,7 @@ static int BrowserUI(tLauncherSettings launchdata) {
vector<string> extensionList = argsGetExtensionList();
chdir("sd:/NTR_Launcher");
while(1) {
string filename = browseForFile(extensionList);
string filename = browseForFile(extensionList, launchdata);
if (cartSelected)break;
// Construct a command line
vector<string> argarray;
@ -176,6 +182,16 @@ static int BrowserUI(tLauncherSettings launchdata) {
vector<const char*> c_args;
for (const auto& arg: argarray) { c_args.push_back(arg.c_str()); }
// Try to run the NDS file with the given arguments
if (access(c_args[0], F_OK) == 0) {
FILE *src = fopen(c_args[0], "rb");
if (src) {
fread((u8*)0x02FFE000, 1, 0x200, src);
if (((tNDSHeader*)0x02FFE000)->unitCode & BIT(1))launchdata.isTWLSRL = 0xFF;
fclose(src);
}
}
// tonccpy((void*)0x02FFDFF0, (void*)LAUNCH_DATA, 0x10);
launchdata.cachedChipID = *(u32*)InitialCartChipID;
int err = runNdsFile(c_args[0], c_args.size(), &c_args[0], launchdata);
iprintf("Start failed. Error %i\n", err);
break;
@ -185,17 +201,22 @@ static int BrowserUI(tLauncherSettings launchdata) {
if (cartSelected) {
// DS-Xtreme does not like running in TWL clock speeds.
// (write function likely goes too fast and semi-bricks hidden sector region randomly when using official launcher)
if (!memcmp(gameTitle, "D!S!XTREME", 9)) {
if (!memcmp(gameTitle, "D!S!XTREME", 10)) {
launchdata.scfgUnlock = 0x00;
launchdata.twlMode = 0x00;
launchdata.twlCLK = 0x00;
launchdata.twlVRAM = 0x00;
cardInit(&ntrHeader);
} else {
if (cartInsertedOnBoot)DoCardInit(); // Currently required for bootlaoder to succeed with card init.
// Give launch soundfx time to finish if card Init already occured.
if (!cartInsertedOnBoot)DoWait(29);
launchdata.twlRAM = 0x00;
launchdata.isTWLSRL = 0x00;
// cardInit(&ntrHeader);
}
if (cartInsertedOnBoot) {
DoCardInit(); // Currently required for bootlaoder to succeed with card init.
} else {
DoWait(29); // Give launch soundfx time to finish if card Init already occured.
}
if (ntrHeader.unitCode & BIT(1))launchdata.isTWLSRL = 0x01;
launchdata.cachedChipID = *(u32*)InitialCartChipID;
runLaunchEngine(launchdata);
}
return stop();

View File

@ -31,6 +31,7 @@
#include "hbmenu_banner_cartSelected.h"
#include "hbmenu_banner_noCart.h"
#include "font6x8.h"
#include "tonccpy.h"
#include "read_card.h"
#include "launcherData.h"
@ -45,19 +46,29 @@
#define ICON2_POS_X 26
#define ICON2_POS_Y 132
#define TEXT_WIDTH ((22-4)*8/6)
typedef struct sNDSBannerTest {
u16 version; //!< version of the banner.
u16 crc; //!< 16 bit crc/checksum of the banner.
u8 reserved[28];
u8 iconData[2080];
} tNDSBannerTest;
static int bg2, bg3;
static u16 *sprite;
static u16 *sprite2;
extern tNDSBanner dsCardDefault_bin;
extern tNDSBanner dsCardInvalid_bin;
extern tNDSBanner hbNoIcon_bin;
static tNDSBanner banner;
static tNDSBanner* cartBanner;
static u32 CartBannerBuffer[2304];
bool cartSelected = false;
static inline void writecharRS (int row, int col, u16 car) {
@ -115,6 +126,10 @@ void clearCartIcon(bool clearBannerText) {
dmaFillHalfWords(0, sprite2, sizeof(banner.icon));
}
static bool checkBannerCRC(u8* banner) {
return (((tNDSBannerTest*)banner)->crc == swiCRC16(0xFFFF, ((tNDSBannerTest*)banner)->iconData, 0x820));
}
void iconTitleInit (void) {
// initialize video mode
@ -162,6 +177,8 @@ void iconTitleInit (void) {
// oam can only be updated during vblank
swiWaitForVBlank();
oamUpdate(&oamMain);
toncset32(CartBannerBuffer, 0, 0x900);
cartBanner = (tNDSBanner*)CartBannerBuffer;
@ -253,6 +270,18 @@ void iconTitleUpdate (int isdir, const std::string& name) {
return;
}
if (!checkBannerCRC((u8*)&banner)) {
// text
writeRow (2,"(invalid icon/title!)", false);
// icon
clearIcon();
DC_FlushAll();
dmaCopy(hbNoIcon_bin.icon, sprite, sizeof(hbNoIcon_bin.icon));
dmaCopy(hbNoIcon_bin.palette, SPRITE_PALETTE, sizeof(hbNoIcon_bin.palette));
fclose (fp);
return;
}
// close file!
fclose (fp);
@ -287,28 +316,37 @@ void iconTitleUpdate (int isdir, const std::string& name) {
void cartIconUpdate (u32 BannerOffset, bool readExistingBanner) {
toncset32(CartBannerBuffer, 0, 0x900);
if(readExistingBanner) {
cardReadAlt(*(u32*)InitialCartBannerOffset, (u32*)CartBannerBuffer, 0x1000);
cardReadAlt(*(u32*)InitialCartBannerOffset, (u32*)CartBannerBuffer, 0x2400);
} else {
cardReadAlt(BannerOffset, (u32*)CartBannerBuffer, 0x1000);
cardReadAlt(BannerOffset, (u32*)CartBannerBuffer, 0x2400);
}
switch (cartBanner->crc) {
case 0x0000: {
clearCartIcon(false);
writeRow (1,"(invalid icon/title!)", true);
DC_FlushAll();
dmaCopy(dsCardDefault_bin.icon, sprite2, 512);
dmaCopy(dsCardDefault_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20);
dmaCopy(dsCardInvalid_bin.icon, sprite2, 512);
dmaCopy(dsCardInvalid_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20);
return;
}break;
} break;
case 0xFFFF: {
clearCartIcon(false);
dmaCopy(dsCardDefault_bin.icon, sprite2, 512);
dmaCopy(dsCardDefault_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20);
dmaCopy(dsCardInvalid_bin.icon, sprite2, 512);
dmaCopy(dsCardInvalid_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20);
writeRow (1,"(invalid icon/title!)", true);
return;
}break;
default: {
if (!checkBannerCRC((u8*)cartBanner)) {
clearCartIcon(false);
dmaCopy(dsCardInvalid_bin.icon, sprite2, 512);
dmaCopy(dsCardInvalid_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20);
writeRow (1,"(invalid icon/title!)", true);
return;
}
clearCartIcon(false);
// turn unicode into ascii (kind of)
// and convert 0x0A into 0x00
@ -326,11 +364,7 @@ void cartIconUpdate (u32 BannerOffset, bool readExistingBanner) {
// Recenter text to center row if less then 2 rows of text.
// Default offset 0 instead of 1 since no NDS file name for this to account for.
if (lineReturns < 2 && lineReturns != 1) {
rowOffset = 1;
} else if (lineReturns == 1) {
rowOffset = 0;
}
if (lineReturns < 2 && lineReturns != 1) { rowOffset = 1; } else if (lineReturns == 1) { rowOffset = 0; }
// text
for (size_t i = 0; i < 3; ++i) {

View File

@ -214,9 +214,8 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) {
return true;
}*/
ITCM_CODE static void SetSCFG(u8 scfgUnlock, u8 twlMode, u8 twlCLK, u8 twlVRAM) {
if (twlMode > 0) {
ITCM_CODE static void SetSCFG(tLauncherSettings launchData) {
/*if (launchData->twlMode > 0) {
*((vu32*)REG_MBK1)=0x8D898581;
*((vu32*)REG_MBK2)=0x8C888480;
*((vu32*)REG_MBK3)=0x9C989490;
@ -225,7 +224,7 @@ ITCM_CODE static void SetSCFG(u8 scfgUnlock, u8 twlMode, u8 twlCLK, u8 twlVRAM)
REG_MBK6=0x00000000;
REG_MBK7=0x07C03740;
REG_MBK8=0x07403700;
} else {
} else if ((launchData->twlMode == 0) && (launchData->twlRAM == 0)) {
// MBK settings for NTR mode games
*((vu32*)REG_MBK1)=0x8D898581;
*((vu32*)REG_MBK2)=0x91898581;
@ -235,18 +234,47 @@ ITCM_CODE static void SetSCFG(u8 scfgUnlock, u8 twlMode, u8 twlCLK, u8 twlVRAM)
REG_MBK6 = 0x00003000;
REG_MBK7 = 0x00003000;
REG_MBK8 = 0x00003000;
}
}*/
if (launchData.twlCLK == 0) { REG_SCFG_CLK = 0x80; } else { REG_SCFG_CLK = 0x87; };
if (twlCLK == 0)REG_SCFG_CLK = 0x80;
if (twlMode > 0) {
REG_SCFG_EXT = 0x82073100;
if (launchData.twlMode > 0) {
REG_SCFG_EXT = 0x8307F100;
REG_SCFG_RST = 1;
} else {
REG_SCFG_EXT=0x83002000;
REG_SCFG_EXT = 0x8300E000;
}
if (twlVRAM == 0)REG_SCFG_EXT &= ~(1UL << 13);
if (scfgUnlock == 0x00)REG_SCFG_EXT &= ~(1UL << 31);
for (int i = 0; i < 10; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); }
if (launchData.twlVRAM == 0)REG_SCFG_EXT &= ~(1UL << 13);
if (launchData.twlRAM == 0) {
REG_SCFG_EXT &= ~(1UL << 14);
REG_SCFG_EXT &= ~(1UL << 15);
}
if ((launchData.isTWLSRL > 0) && (launchData.twlRAM > 0) && (launchData.twlMode > 0)) {
*(vu32*)REG_MBK1 = *(u32*)0x02FFE180;
*(vu32*)REG_MBK2 = *(u32*)0x02FFE184;
*(vu32*)REG_MBK3 = *(u32*)0x02FFE188;
*(vu32*)REG_MBK4 = *(u32*)0x02FFE18C;
*(vu32*)REG_MBK5 = *(u32*)0x02FFE190;
REG_MBK6 = *(u32*)0x02FFE194;
REG_MBK7 = *(u32*)0x02FFE198;
REG_MBK8 = *(u32*)0x02FFE19C;
REG_MBK9 = *(u32*)0x02FFE1AC;
WRAM_CR = *(u8*)0x02FFE1AF;
} else {
*((vu32*)REG_MBK1)=0x8D898581;
*((vu32*)REG_MBK2)=0x91898581;
*((vu32*)REG_MBK3)=0x91999591;
*((vu32*)REG_MBK4)=0x91898581;
*((vu32*)REG_MBK5)=0x91999591;
REG_MBK6 = 0x00003000;
REG_MBK7 = 0x00003000;
REG_MBK8 = 0x00003000;
if (launchData.scfgUnlock == 0)REG_SCFG_EXT &= ~(1UL << 31);
}
for (int i = 0; i < 10; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); }
}
@ -256,28 +284,18 @@ eRunNdsRetCode runNds (const void* loader, u32 loaderSize, u32 cluster, bool ini
u16 argTempVal = 0;
int argSize;
const char* argChar;
bool scfgUnlock = false;
bool twlMode = false;
bool twlCLK = false;
bool twlVRAM = false;
if (launchdata.scfgUnlock > 0x00)scfgUnlock = true;
if (launchdata.twlMode > 0x00)twlMode = true;
if (launchdata.twlCLK > 0x00)twlCLK = true;
if (launchdata.twlVRAM > 0x00)twlVRAM = true;
if (!twlMode) {
if (launchdata.twlMode == 0) {
fifoSendValue32(FIFO_USER_01, 1);
fifoWaitValue32(FIFO_USER_02);
}
irqDisable(IRQ_ALL);
SetSCFG(scfgUnlock, twlMode, twlCLK, twlVRAM);
SetSCFG(launchdata);
// Direct CPU access to VRAM bank C
VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD;
VRAM_D_CR = (VRAM_ENABLE | VRAM_D_LCD);
// Load the loader/patcher into the correct address
vramcpy (LCDC_BANK_D, loader, loaderSize);
@ -332,9 +350,9 @@ eRunNdsRetCode runNds (const void* loader, u32 loaderSize, u32 cluster, bool ini
*(tLauncherSettings*)LAUNCH_DATA = launchdata;
// Give the VRAM to the ARM7
VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000;
VRAM_D_CR = (VRAM_ENABLE | VRAM_D_ARM7_0x06020000);
// Reset into a passme loop
REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD;
REG_EXMEMCNT |= (ARM7_OWNS_ROM | ARM7_OWNS_CARD);
*((vu32*)0x02FFFFFC) = 0;
*((vu32*)0x02FFFE04) = (u32)0xE59FF018;
*((vu32*)0x02FFFE24) = (u32)0x02FFFE04;

Binary file not shown.

View File

@ -39,23 +39,34 @@ extern void InitConsole();
extern bool ConsoleInit;
ITCM_CODE static void SETSCFG() {
REG_SCFG_EXT=0x83002000;
ITCM_CODE static void SETSCFG(u8 twlMode, u8 twlVRAM, u8 twlRAM) {
if (twlMode > 0) {
// if (twlRAM > 0) { REG_SCFG_EXT = 0x82076100; } else { REG_SCFG_EXT = 0x82073100; }
// if (twlRAM > 0) { REG_SCFG_EXT = 0x8207611F; } else { REG_SCFG_EXT = 0x8207311F; }
// if (twlRAM > 0) { REG_SCFG_EXT = 0x8207711F; } else { REG_SCFG_EXT = 0x8207311F; }
// REG_SCFG_EXT = 0x8207711F;
REG_SCFG_EXT = 0x8307F100;
REG_SCFG_RST = 1;
} else {
// if (twlRAM == 0) { REG_SCFG_EXT = 0x83002000; } else { REG_SCFG_EXT = 0x83006000; }
// REG_SCFG_EXT = 0x83006000;
REG_SCFG_EXT = 0x8300E000;
}
if (twlVRAM == 0)REG_SCFG_EXT &= ~(1UL << 13);
if (twlRAM == 0)REG_SCFG_EXT &= ~(1UL << 14);
if (twlRAM == 0)REG_SCFG_EXT &= ~(1UL << 15);
for(int i = 0; i < 8; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); }
}
void runLaunchEngine (tLauncherSettings launchdata) {
// Always init console so bootloader's new console can display error codes if needed.
if (!launchdata.debugMode || !ConsoleInit) { InitConsole(); } else { consoleClear(); }
if (!launchdata.debugMode || !ConsoleInit) { InitConsole(); } else { consoleClear(); }
irqDisable(IRQ_ALL);
// Direct CPU access to VRAM bank D
VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD;
// Clear VRAM
// memset (LCDC_BANK_D, 0x00, 128 * 1024);
VRAM_D_CR = (VRAM_ENABLE | VRAM_D_LCD);
// Load the loader/patcher into the correct address
vramcpy (LCDC_BANK_D, load_bin, load_bin_size);
@ -64,17 +75,17 @@ void runLaunchEngine (tLauncherSettings launchdata) {
VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000;
// Reset into a passme loop
nocashMessage("Reset into a passme loop");
// nocashMessage("Reset into a passme loop");
REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD;
*(tLauncherSettings*)LAUNCH_DATA = launchdata;
SETSCFG();
SETSCFG(launchdata.twlMode, launchdata.twlVRAM, launchdata.twlRAM);
// Return to passme loop
*(vu32*)0x027FFFFC = 0;
*(vu32*)0x027FFE04 = (u32)0xE59FF018; // ldr pc, 0x02FFFE24
*(vu32*)0x027FFE24 = (u32)0x02FFFE04; // Set ARM9 Loop address --> resetARM9(0x027FFE04);
*(vu32*)0x02FFFFFC = 0;
*(vu32*)0x02FFFE04 = (u32)0xE59FF018; // ldr pc, 0x02FFFE24
*(vu32*)0x02FFFE24 = (u32)0x02FFFE04; // Set ARM9 Loop address --> resetARM9(0x02FFFE04);
// Reset ARM7
// nocashMessage("resetARM7");
resetARM7(0x06020000);

View File

@ -49,7 +49,7 @@ static char gameTitle[13] = {0};
// static char gameCode[7] = {0};
static char gameCode[5] = {0};
static bool nitroFSMounted = false;
static ALIGN(4) sNDSHeaderExt ntrHeader;
// static ALIGN(4) sNDSHeaderExt ntrHeader;
const char* PROGVERSION = "3.1";
@ -75,7 +75,7 @@ void DisplayText(const char* text, bool clear = false, bool noText = false){
if (clear)consoleClear();
printf("--------------------------------\n");
printf("----[NTR Launcher Debug Mode]---\n");
printf("----------[Version: 3.1]--------\n");
printf("----------[Version: 3.2]--------\n");
printf("--------------------------------\n\n");
if (!noText)printf(text);
}
@ -110,8 +110,8 @@ bool DoCardInit(bool DebugMode, bool fastBoot) {
DisplayText("Loading Cart details.\nPlease Wait...\n", true);
}
switch (REG_SCFG_MC) {
case 0x10: { enableSlot1(); DoWait(10); FastBoot = false; }break;
case 0x11: { enableSlot1(); DoWait(10); FastBoot = false; }break;
case 0x10: { enableSlot1(); DoWait(15); FastBoot = false; }break;
case 0x11: { enableSlot1(); DoWait(15); FastBoot = false; }break;
}
// Do cart init stuff to wake cart up. DLDI init may fail otherwise!
/*if (FastBoot) {
@ -121,10 +121,14 @@ bool DoCardInit(bool DebugMode, bool fastBoot) {
} else {*/
CardReset(true);
cardReadHeader((u8*)&ndsHeader);
while(REG_ROMCTRL & CARD_BUSY);
CardReset(false);
tonccpy(gameTitle, ndsHeader.header.gameTitle, 12);
tonccpy(gameCode, ndsHeader.header.gameCode, 4);
// cardInit(&ntrHeader);
/*cardInit((sNDSHeaderExt*)&ndsHeader.header);
tonccpy(gameTitle, ndsHeader.header.gameTitle, 12);
tonccpy(gameCode, ndsHeader.header.gameCode, 4);
CardReset(false);*/
// }
if (DebugMode) {
DisplayText("CLR", true, true);
@ -170,8 +174,19 @@ int main() {
defaultExceptionHandler();
sysSetCardOwner(BUS_OWNER_ARM9);
if (!isDSiMode()) {
InitConsole();
printf("--------------------------------\n");
printf("----------[NTR Launcher]--------\n");
printf("----------[Version: 3.2]--------\n");
printf("--------------------------------\n\n");
printf("\nError has occured.!\nDSi Mode not detected.\nDS/DS Lite Unsupported!");
do { swiWaitForVBlank(); scanKeys(); } while (!keysDown());
return 0;
}
tLauncherSettings LaunchData = { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF };
tLauncherSettings LaunchData = { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFFFFFF };
// Create backup of Cart header (if present) saved by DSi System Menu.
// It will not survive memory reallocation after dropping to NTR ram spec during bootloader.
@ -181,6 +196,7 @@ int main() {
bool scfgunlock = true;
bool twlmode = false;
bool twlclk = false;
bool twlram = false;
bool twlvram = false;
bool debugmode = false;
// bool fastBoot = false;
@ -220,6 +236,7 @@ int main() {
twlclk = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLCLOCK",0);
twlvram = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLVRAM",0);
twlram = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLRAM",0);
twlmode = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLMODE",0);
scfgunlock = ntrlauncher_config.GetInt("NTRLAUNCHER","SCFGUNLOCK",0);
useAnimatedSplash = ntrlauncher_config.GetInt("NTRLAUNCHER","ANIMATEDSPLASH",0);
@ -236,10 +253,19 @@ int main() {
scanKeys();
swiWaitForVBlank();
/*scfgunlock = true;
twlmode = true;
twlclk = true;
twlram = true;
twlvram = true;
debugmode = true;*/
if (scfgunlock)LaunchData.scfgUnlock = 0x01;
if (twlmode)LaunchData.twlMode = 0x01;
if (twlclk)LaunchData.twlCLK = 0x01;
if (twlvram)LaunchData.twlVRAM = 0x01;
if (twlram)LaunchData.twlRAM = 0x01;
if (!autoBoot)stage2Menu = true;
// if (fastBoot)LaunchData.fastBoot = 0x01;
@ -251,6 +277,8 @@ int main() {
if ((REG_SCFG_MC == 0x10) && !stage2Menu) { sysSetCardOwner (BUS_OWNER_ARM9); DoCardInit(false, false); }
if (!fatInit)stage2Menu = false;
if (!stage2Menu) {
if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) {
debugmode = true;
@ -261,7 +289,6 @@ int main() {
}
}
if (!fatInit)stage2Menu = false;
ConsoleInit = debugmode;
if (stage2Menu) { ConsoleInit = false; debugmode = false; }
@ -307,7 +334,9 @@ int main() {
LaunchData.twlVRAM = 0x00;
LaunchData.twlMode = 0x00;
if (!useAnimatedSplash)SimpleSplashInit();
cardInit(&ntrHeader);
// cardInit(&ntrHeader);
} else {
if (ndsHeader.header.unitCode & BIT(1))LaunchData.isTWLSRL = 0x01;
}
while(1) {
// If SCFG_MC is returning as zero/null, this means SCFG_EXT registers are locked on arm9 or user attempted to run this while in NTR mode.
@ -320,6 +349,7 @@ int main() {
}
break;
} else {
LaunchData.cachedChipID = *(u32*)InitialCartChipID;
runLaunchEngine(LaunchData);
break;
}

View File

@ -1,13 +0,0 @@
.text
.align 4
.thumb
@---------------------------------------------------------------------------------
.global swiDelay
.thumb_func
@---------------------------------------------------------------------------------
swiDelay:
@---------------------------------------------------------------------------------
swi 0x03
bx lr

View File

@ -0,0 +1,233 @@
/*---------------------------------------------------------------------------------
Copyright (C) 2005
Michael Noland (joat)
Jason Rogers (dovoto)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/
#include <nds/asminc.h>
.text
.align 4
.thumb
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDelay
@---------------------------------------------------------------------------------
swi 0x03
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiSleep
@---------------------------------------------------------------------------------
swi 0x07
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiChangeSoundBias
@---------------------------------------------------------------------------------
swi 0x08
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDivide
@---------------------------------------------------------------------------------
swi 0x09
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiRemainder
@---------------------------------------------------------------------------------
swi 0x09
mov r0, r1
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDivMod
@---------------------------------------------------------------------------------
push {r2, r3}
swi 0x09
pop {r2, r3}
str r0, [r2]
str r1, [r3]
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiCopy
@---------------------------------------------------------------------------------
swi 0x0B
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiFastCopy
@---------------------------------------------------------------------------------
swi 0x0C
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiSqrt
@---------------------------------------------------------------------------------
swi 0x0D
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiCRC16
@---------------------------------------------------------------------------------
swi 0x0E
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiIsDebugger
@---------------------------------------------------------------------------------
swi 0x0F
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiUnpackBits
@---------------------------------------------------------------------------------
swi 0x10
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecompressLZSSWram
@---------------------------------------------------------------------------------
swi 0x11
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecompressLZSSVramNTR
@---------------------------------------------------------------------------------
swi 0x12
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecompressLZSSVramTWL
@---------------------------------------------------------------------------------
swi 0x02
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecompressHuffman
@---------------------------------------------------------------------------------
swi 0x13
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecompressRLEWram
@---------------------------------------------------------------------------------
swi 0x14
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecompressRLEVram
@---------------------------------------------------------------------------------
swi 0x15
bx lr
@---------------------------------------------------------------------------------
@ ARM7 only bios calls
@---------------------------------------------------------------------------------
#ifdef ARM7
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiHalt
@---------------------------------------------------------------------------------
swi 0x06
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiGetSineTable
@---------------------------------------------------------------------------------
swi 0x1A
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiGetPitchTable
@---------------------------------------------------------------------------------
swi 0x1B
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiGetVolumeTable
@---------------------------------------------------------------------------------
swi 0x1C
bx lr
@ ARM7 function, but no real point in exposing it, at least not
@ without adding a way to get the 3 arguments back into C
@ .global swiGetFptrs
@ .thumb_func
@swiGetFptrs:
@ swi 0x1D
@ bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiSwitchToGBAMode
@---------------------------------------------------------------------------------
mov r0, #0x40
swi 0x1F
@ does not return, of course
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiSetHaltCR
@---------------------------------------------------------------------------------
mov r2, r0
swi 0x1F
bx lr
#endif // ARM7
@---------------------------------------------------------------------------------
@ ARM9 only bios calls
@---------------------------------------------------------------------------------
#ifdef ARM9
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiWaitForIRQ
@---------------------------------------------------------------------------------
swi 0x06
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecodeDelta8
@---------------------------------------------------------------------------------
swi 0x16
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiDecodeDelta16
@---------------------------------------------------------------------------------
swi 0x18
bx lr
@---------------------------------------------------------------------------------
BEGIN_ASM_FUNC swiSetHaltCR
@---------------------------------------------------------------------------------
swi 0x1F
bx lr
#endif // ARM9

View File

@ -40,19 +40,29 @@ Helpful information:
#include <nds/timers.h>
#include <nds/memory.h>
#include <nds/arm7/audio.h>
#include <nds/ipc.h>
#include <string.h>
#include "fat.h"
#include "card.h"
#include "boot.h"
#include "sdmmc.h"
#include "tonccpy.h"
#include "../../arm9/common/launcherData.h"
void arm7clearRAM();
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Important things
#define TEMP_MEM 0x02FFD000
#define TWL_HEAD 0x02FFE000
#define NDS_HEAD 0x02FFFE00
#define TEMP_MEM 0x02FFD000
#define TEMP_LAUNCHMEM 0x02FFDFF0
#define TWL_HEAD 0x02FFE000
#define NDS_HEAD 0x02FFFE00
#define NDS_HEAD_POKEMON 0x02FFF000
#define TEMP_ARM9_START_ADDRESS (*(vu32*)0x02FFFFF4)
tTWLHeader* ntrHeader;
tTWLHeader* twlHeader;
const char* bootName = "BOOT.NDS";
@ -65,61 +75,39 @@ extern unsigned long argSize;
extern unsigned long dsiSD;
extern unsigned long dsiMode;
static bool scfgunlock = false;
static bool twlmode = false;
static bool twlclk = false;
static bool twlvram = false;
volatile u16 scfgunlock = 0;
volatile u16 twlmode = 0;
volatile u16 twlclk = 0;
volatile u16 twlvram = 0;
volatile u16 twlram = 0;
volatile u32 chipID = 0;
#define LAUNCH_DATA 0x020007F0
static volatile u32 ROM_TID = 0;
typedef struct sLauncherSettings {
u8 language;
u8 scfgUnlock;
u8 twlMode;
u8 twlCLK;
u8 twlVRAM;
u8 debugMode;
u8 fastBoot;
u8 unused2;
} tLauncherSettings;
static void setTWLMBK() {
*(vu32*)REG_MBK1 = *(u32*)0x02FFE180;
*(vu32*)REG_MBK2 = *(u32*)0x02FFE184;
*(vu32*)REG_MBK3 = *(u32*)0x02FFE188;
*(vu32*)REG_MBK4 = *(u32*)0x02FFE18C;
*(vu32*)REG_MBK5 = *(u32*)0x02FFE190;
REG_MBK6 = *(u32*)0x02FFE1A0;
REG_MBK7 = *(u32*)0x02FFE1A4;
REG_MBK8 = *(u32*)0x02FFE1A8;
REG_MBK9 = *(u32*)0x02FFE1AC;
}
const char* getRomTid(const tNDSHeader* ndsHeader) {
static char romTid[5];
strncpy(romTid, ndsHeader->gameCode, 4);
romTid[4] = '\0';
return romTid;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Firmware stuff
#define FW_READ 0x03
void boot_readFirmware (uint32 address, uint8 * buffer, uint32 size) {
uint32 index;
// Read command
while (REG_SPICNT & SPI_BUSY);
REG_SPICNT = SPI_ENABLE | SPI_CONTINUOUS | SPI_DEVICE_NVRAM;
REG_SPIDATA = FW_READ;
while (REG_SPICNT & SPI_BUSY);
// Set the address
REG_SPIDATA = (address>>16) & 0xFF;
while (REG_SPICNT & SPI_BUSY);
REG_SPIDATA = (address>>8) & 0xFF;
while (REG_SPICNT & SPI_BUSY);
REG_SPIDATA = (address) & 0xFF;
while (REG_SPICNT & SPI_BUSY);
for (index = 0; index < size; index++) {
REG_SPIDATA = 0;
while (REG_SPICNT & SPI_BUSY);
buffer[index] = REG_SPIDATA & 0xFF;
}
REG_SPICNT = 0;
}
static inline void copyLoop (u32* dest, const u32* src, u32 size) {
size = (size +3) & ~3;
do { *dest++ = *src++; } while (size -= 4);
}
//#define resetCpu() __asm volatile("\tswi 0x000000\n");
void mpu_reset();
void mpu_reset_end();
@ -173,17 +161,17 @@ void passArgs_ARM7 (void) {
argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned
/* if (dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) {
if ((twlmode > 0) && dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) {
u32 ARM9i_DST = *((u32*)(TWL_HEAD + 0x1C8));
u32 ARM9i_LEN = *((u32*)(TWL_HEAD + 0x1CC));
if (ARM9i_LEN) {
u32* argDst2 = (u32*)((ARM9i_DST + ARM9i_LEN + 3) & ~3); // Word aligned
if (argDst2 > argDst)
argDst = argDst2;
if (argDst2 > argDst)argDst = argDst2;
}
}*/
}
copyLoop(argDst, argSrc, argSize);
// copyLoop(argDst, argSrc, argSize);
tonccpy(argDst, argSrc, argSize);
__system_argv->argvMagic = ARGV_MAGIC;
__system_argv->commandLine = (char*)argDst;
@ -197,10 +185,8 @@ Written by Darkain.
Modified by Chishm:
* Added STMIA clear mem loop
--------------------------------------------------------------------------*/
void resetMemory_ARM7 (void) {
int i;
u8 settings1, settings2;
u32 settingsOffset = 0;
void resetMemory_ARM7(void) {
int i, reg;
REG_IME = 0;
@ -212,82 +198,281 @@ void resetMemory_ARM7 (void) {
}
REG_SOUNDCNT = 0;
REG_SNDCAP0CNT = 0;
REG_SNDCAP1CNT = 0;
//clear out ARM7 DMA channels and timers
REG_SNDCAP0DAD = 0;
REG_SNDCAP0LEN = 0;
REG_SNDCAP1DAD = 0;
REG_SNDCAP1LEN = 0;
// Clear out ARM7 DMA channels and timers
for (i=0; i<4; i++) {
DMA_CR(i) = 0;
DMA_SRC(i) = 0;
DMA_DEST(i) = 0;
TIMER_CR(i) = 0;
TIMER_DATA(i) = 0;
if ((twlmode > 0) || dsiMode) {
for (reg=0; reg<0x1c; reg+=4)*((u32*)(0x04004104 + ((i*0x1c)+reg))) = 0; //Reset NDMA.
}
}
REG_RCNT = 0;
// Clear out FIFO
REG_IPC_SYNC = 0;
REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR;
REG_IPC_FIFO_CR = 0;
arm7clearRAM();
// clear most of EXRAM
toncset((u8*)0x02000000, 0, 0x3FC000); // clear more of EXRAM, skipping the arm9 temp area used by bootloader
REG_IE = 0;
REG_IF = ~0;
REG_AUXIE = 0;
REG_AUXIF = ~0;
(*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version
(*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version
REG_POWERCNT = 1; //turn off power to stuff
REG_POWERCNT = 1; //turn off power to stuffs
}
// Get settings location
boot_readFirmware((u32)0x00020, (u8*)&settingsOffset, 0x2);
settingsOffset *= 8;
static void XMenuFix() {
*((vu8*)0x02FFFF70) = 0x91;
if (twlmode > 0)*((vu8*)0x027FFF70) = 0x91;
}
// Reload DS Firmware settings
boot_readFirmware(settingsOffset + 0x070, &settings1, 0x1);
boot_readFirmware(settingsOffset + 0x170, &settings2, 0x1);
static void setMemoryAddressTWL(const tNDSHeader* ndsHeader) {
if (ndsHeader->unitCode > 0) {
// copyLoop((u32*)0x027FFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header
tonccpy((u32*)0x027FFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header
if ((settings1 & 0x7F) == ((settings2+1) & 0x7F)) {
boot_readFirmware(settingsOffset + 0x000, (u8*)0x02FFFC80, 0x70);
} else {
boot_readFirmware(settingsOffset + 0x100, (u8*)0x02FFFC80, 0x70);
*(u32*)(0x027FA680) = 0x02FD4D80;
*(u32*)(0x027FA684) = 0x00000000;
*(u32*)(0x027FA688) = 0x00001980;
*(u32*)(0x027FF00C) = 0x0000007F;
*(u32*)(0x027FF010) = 0x550E25B8;
*(u32*)(0x027FF014) = 0x02FF4000;
// Set region flag
if (strncmp(getRomTid(ndsHeader)+3, "J", 1) == 0) {
*(u8*)(0x027FFD70) = 0;
} else if (strncmp(getRomTid(ndsHeader)+3, "E", 1) == 0) {
*(u8*)(0x027FFD70) = 1;
} else if (strncmp(getRomTid(ndsHeader)+3, "P", 1) == 0) {
*(u8*)(0x027FFD70) = 2;
} else if (strncmp(getRomTid(ndsHeader)+3, "U", 1) == 0) {
*(u8*)(0x027FFD70) = 3;
} else if (strncmp(getRomTid(ndsHeader)+3, "C", 1) == 0) {
*(u8*)(0x027FFD70) = 4;
} else if (strncmp(getRomTid(ndsHeader)+3, "K", 1) == 0) {
*(u8*)(0x027FFD70) = 5;
}
}
// Set memory values expected by loaded NDS
// from NitroHax, thanks to Chism
*((u32*)0x027FF800) = *(u32*)0x02FFFC00; // CurrentCardID
// *((u32*)0x027FF804) = *(u32*)0x02FFFC00; // Command10CardID
*((u16*)0x027FF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x027FF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x027FF850) = 0x5835;
// Copies of above
*((u32*)0x027FFC00) = *(u32*)0x02FFFC00; // CurrentCardID
// *((u32*)0x027FFC04) = *(u32*)0x02FFFC00; // Command10CardID
*((u16*)0x027FFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x027FFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x027FFC10) = 0x5835;
*((u16*)0x027FFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr
tonccpy((u32*)0x027FC000, (u32*)0x02FFC000, 0x1000);
tonccpy((u32*)0x027FF000, (u32*)NDS_HEAD_POKEMON, 0x170);
tonccpy((u32*)0x027FFE00, (u32*)NDS_HEAD, 0x160);
tonccpy((u32*)0x027FE000, (u32*)TWL_HEAD, 0x1000);
tonccpy((u32*)0x027FF830, (u32*)0x02FFF830, 0x20);
tonccpy((u32*)0x027FFC80, (u32*)0x02FFFC80, 0x70);
tonccpy((u32*)0x027FFD80, (u32*)0x02FFFD80, 0x70);
}
static void setMemoryAddress(const tNDSHeader* ndsHeader) {
if (ndsHeader->unitCode > 0) {
// copyLoop((u32*)0x02FFFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header
tonccpy((u32*)0x02FFFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header
*(u32*)(0x02FFA680) = 0x02FD4D80;
*(u32*)(0x02FFA684) = 0x00000000;
*(u32*)(0x02FFA688) = 0x00001980;
*(u32*)(0x02FFF00C) = 0x0000007F;
*(u32*)(0x02FFF010) = 0x550E25B8;
*(u32*)(0x02FFF014) = 0x02FF4000;
// Set region flag
if (strncmp(getRomTid(ndsHeader)+3, "J", 1) == 0) {
*(u8*)(0x02FFFD70) = 0;
} else if (strncmp(getRomTid(ndsHeader)+3, "E", 1) == 0) {
*(u8*)(0x02FFFD70) = 1;
} else if (strncmp(getRomTid(ndsHeader)+3, "P", 1) == 0) {
*(u8*)(0x02FFFD70) = 2;
} else if (strncmp(getRomTid(ndsHeader)+3, "U", 1) == 0) {
*(u8*)(0x02FFFD70) = 3;
} else if (strncmp(getRomTid(ndsHeader)+3, "C", 1) == 0) {
*(u8*)(0x02FFFD70) = 4;
} else if (strncmp(getRomTid(ndsHeader)+3, "K", 1) == 0) {
*(u8*)(0x02FFFD70) = 5;
}
}
// Fix Pokemon games needing header data.
// copyLoop((u32*)NDS_HEAD_POKEMON, (u32*)NDS_HEAD, 0x170);
tonccpy((u32*)NDS_HEAD_POKEMON, (u32*)NDS_HEAD, 0x170);
// Set memory values expected by loaded NDS
// from NitroHax, thanks to Chism
*((u32*)0x02FFF800) = chipID; // CurrentCardID
// *((u32*)0x02FFF804) = chipID; // Command10CardID
*((u16*)0x02FFF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x02FFF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x02FFF850) = 0x5835;
// Copies of above
*((u32*)0x02FFFC00) = chipID; // CurrentCardID
// *((u32*)0x02FFFC04) = chipID; // Command10CardID
*((u16*)0x02FFFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)0x02FFFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)0x02FFFC10) = 0x5835;
*((u16*)0x02FFFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr
if ((twlram > 0) && (ndsHeader->unitCode == 0))setMemoryAddressTWL(ndsHeader);
switch (*((vu16*)0x02FFFF5E)) {
case 0xF63D: XMenuFix(); break;
case 0x0695: XMenuFix(); break;
case 0xE4C4: XMenuFix(); break;
case 0x918C: XMenuFix(); break;
}
}
static u8 readwriteSPI(u8 data) {
REG_SPIDATA = data;
SerialWaitBusy();
return REG_SPIDATA;
}
//---------------------------------------------------------------------------------
void readFirmware(u32 address, void * destination, u32 size) {
//---------------------------------------------------------------------------------
int oldIME=enterCriticalSection();
u8 *buffer = destination;
// Read command
REG_SPICNT = SPI_ENABLE | SPI_BYTE_MODE | SPI_CONTINUOUS | SPI_DEVICE_FIRMWARE;
readwriteSPI(FIRMWARE_READ);
// Set the address
readwriteSPI((address>>16) & 0xFF);
readwriteSPI((address>> 8) & 0xFF);
readwriteSPI((address) & 0xFF);
u32 i;
// Read the data
for(i=0;i<size;i++) {
buffer[i] = readwriteSPI(0);
}
((vu32*)0x040044f0)[2] = 0x202DDD1D;
((vu32*)0x040044f0)[3] = 0xE1A00005;
while((*(vu32*)0x04004400) & 0x2000000);
REG_SPICNT = 0;
leaveCriticalSection(oldIME);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Firmware stuff
static void my_readUserSettings(tNDSHeader* ndsHeader) {
PERSONAL_DATA slot1;
PERSONAL_DATA slot2;
short slot1count, slot2count; //u8
short slot1CRC, slot2CRC;
u32 userSettingsBase;
// Get settings location
readFirmware(0x20, &userSettingsBase, 2);
u32 slot1Address = userSettingsBase * 8;
u32 slot2Address = userSettingsBase * 8 + 0x100;
// Reload DS Firmware settings
readFirmware(slot1Address, &slot1, sizeof(PERSONAL_DATA)); //readFirmware(slot1Address, personalData, 0x70);
readFirmware(slot2Address, &slot2, sizeof(PERSONAL_DATA)); //readFirmware(slot2Address, personalData, 0x70);
readFirmware(slot1Address + 0x70, &slot1count, 2); //readFirmware(slot1Address + 0x70, &slot1count, 1);
readFirmware(slot2Address + 0x70, &slot2count, 2); //readFirmware(slot1Address + 0x70, &slot2count, 1);
readFirmware(slot1Address + 0x72, &slot1CRC, 2);
readFirmware(slot2Address + 0x72, &slot2CRC, 2);
// Default to slot 1 user settings
void *currentSettings = &slot1;
short calc1CRC = swiCRC16(0xFFFF, &slot1, sizeof(PERSONAL_DATA));
short calc2CRC = swiCRC16(0xFFFF, &slot2, sizeof(PERSONAL_DATA));
// Bail out if neither slot is valid
if (calc1CRC != slot1CRC && calc2CRC != slot2CRC)return;
// If both slots are valid pick the most recent
if (calc1CRC == slot1CRC && calc2CRC == slot2CRC) {
currentSettings = (slot2count == ((slot1count + 1) & 0x7f) ? &slot2 : &slot1); //if ((slot1count & 0x7F) == ((slot2count + 1) & 0x7F)) {
} else {
if (calc2CRC == slot2CRC)currentSettings = &slot2;
}
PERSONAL_DATA* personalData = (PERSONAL_DATA*)((u32)__NDSHeader - (u32)ndsHeader + (u32)PersonalData); //(u8*)((u32)ndsHeader - 0x180)
tonccpy(PersonalData, currentSettings, sizeof(PERSONAL_DATA));
if (personalData->language != 6 && ndsHeader->reserved1[8] == 0x80) {
ndsHeader->reserved1[8] = 0; // Patch iQue game to be region-free
ndsHeader->headerCRC16 = swiCRC16(0xFFFF, ndsHeader, 0x15E); // Fix CRC
}
}
void loadBinary_ARM7 (u32 fileCluster) {
u32 ndsHeader[0x170>>2];
// read NDS header
fileRead ((char*)ndsHeader, fileCluster, 0, 0x170);
// read ARM9 info from NDS header
u32 ARM9_SRC = ndsHeader[0x020>>2];
char* ARM9_DST = (char*)ndsHeader[0x028>>2];
u32 ARM9_LEN = ndsHeader[0x02C>>2];
// read ARM7 info from NDS header
u32 ARM7_SRC = ndsHeader[0x030>>2];
char* ARM7_DST = (char*)ndsHeader[0x038>>2];
u32 ARM7_LEN = ndsHeader[0x03C>>2];
fileRead ((char*)NDS_HEAD, fileCluster, 0, 0x170);
// Load binaries into memory
fileRead(ARM9_DST, fileCluster, ARM9_SRC, ARM9_LEN);
fileRead(ARM7_DST, fileCluster, ARM7_SRC, ARM7_LEN);
fileRead((char*)ntrHeader->arm9destination, fileCluster, ntrHeader->arm9romOffset, ntrHeader->arm9binarySize);
fileRead((char*)ntrHeader->arm7destination, fileCluster, ntrHeader->arm7romOffset, ntrHeader->arm7binarySize);
// first copy the header to its proper location, excluding
// the ARM9 start address, so as not to start it
TEMP_ARM9_START_ADDRESS = ndsHeader[0x024>>2]; // Store for later
ndsHeader[0x024>>2] = 0;
dmaCopyWords(3, (void*)ndsHeader, (void*)NDS_HEAD, 0x170);
/*if (dsiMode && (ndsHeader[0x10>>2]&BIT(16+1))) {
TEMP_ARM9_START_ADDRESS = ntrHeader->arm9executeAddress; // Store for later
*(u32*)ntrHeader->arm9executeAddress = 0;
dmaCopyWords(3, (void*)ntrHeader, (void*)NDS_HEAD, 0x170);
ROM_TID = *(u32*)0x02FFFE0C;
setMemoryAddress((tNDSHeader*)ntrHeader);
if ((twlram > 0) && (ntrHeader->unitCode & BIT(1))) {
// Read full TWL header
fileRead((char*)TWL_HEAD, fileCluster, 0, 0x1000);
tonccpy((void*)0x02FFC000, (void*)TWL_HEAD, 0x1000);
if (twlHeader->arm9ibinarySize > 0)fileRead((char*)twlHeader->arm9idestination, fileCluster, twlHeader->arm9iromOffset, twlHeader->arm9ibinarySize);
if (twlHeader->arm7ibinarySize > 0)fileRead((char*)twlHeader->arm7idestination, fileCluster, twlHeader->arm7iromOffset, twlHeader->arm7ibinarySize);
if (twlmode > 0) {
setTWLMBK();
if (twlHeader->unitCode == 0x02)scfgunlock = 0;
}
}
u32 ARM9i_SRC = *(u32*)(TWL_HEAD+0x1C0);
char* ARM9i_DST = (char*)*(u32*)(TWL_HEAD+0x1C8);
u32 ARM9i_LEN = *(u32*)(TWL_HEAD+0x1CC);
u32 ARM7i_SRC = *(u32*)(TWL_HEAD+0x1D0);
char* ARM7i_DST = (char*)*(u32*)(TWL_HEAD+0x1D8);
u32 ARM7i_LEN = *(u32*)(TWL_HEAD+0x1DC);
if (ARM9i_LEN)fileRead(ARM9i_DST, fileCluster, ARM9i_SRC, ARM9i_LEN);
if (ARM7i_LEN)fileRead(ARM7i_DST, fileCluster, ARM7i_SRC, ARM7i_LEN);
}*/
my_readUserSettings((tNDSHeader*)ntrHeader);
}
/*-------------------------------------------------------------------------
@ -310,20 +495,19 @@ void startBinary_ARM7 (void) {
}
int main (void) {
ntrHeader = (tTWLHeader*)NDS_HEAD;
twlHeader = (tTWLHeader*)TWL_HEAD;
tLauncherSettings* tmpData = (tLauncherSettings*)LAUNCH_DATA;
if (tmpData->scfgUnlock > 0x00)scfgunlock = true;
if (tmpData->twlMode > 0x00)twlmode = true;
if (tmpData->twlCLK > 0x00)twlclk = true;
if (tmpData->twlVRAM > 0x00)twlvram = true;
if (tmpData->scfgUnlock > 0x00)scfgunlock = 0xFFFF;
if (tmpData->twlMode > 0x00)twlmode = 0xFFFF;
if (tmpData->twlCLK > 0x00)twlclk = 0xFFFF;
if (tmpData->twlRAM > 0x00)twlram = 0xFFFF;
if (tmpData->twlVRAM > 0x00)twlvram = 0xFFFF;
if (tmpData->cachedChipID > 0x00)chipID = tmpData->cachedChipID;
if (twlmode) {
REG_MBK9=0x0300000F;
REG_MBK6=0x080037C0;
REG_MBK7=0x07C03740;
REG_MBK8=0x07403700;
} else {
if ((twlmode == 0) && (twlram == 0)) {
REG_MBK9=0xFCFFFF0F;
REG_MBK6=0x09403900;
REG_MBK7=0x09803940;
@ -350,14 +534,14 @@ int main (void) {
// ARM9 clears its memory part 2
// copy ARM9 function to RAM, and make the ARM9 jump to it
copyLoop((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size);
tonccpy((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size);
(*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function
// Wait until the ARM9 has completed its task
while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM);
// ARM9 sets up mpu
// copy ARM9 function to RAM, and make the ARM9 jump to it
copyLoop((void*)TEMP_MEM, (void*)mpu_reset, mpu_reset_end - mpu_reset);
tonccpy((void*)TEMP_MEM, (void*)mpu_reset, mpu_reset_end - mpu_reset);
(*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function
// Wait until the ARM9 has completed its task
@ -365,15 +549,22 @@ int main (void) {
// Get ARM7 to clear RAM
resetMemory_ARM7();
// ARM9 enters a wait loop
// copy ARM9 function to RAM, and make the ARM9 jump to it
copyLoop((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size);
tonccpy((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size);
(*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function
// Load the NDS file
loadBinary_ARM7(fileCluster);
// Fix for Pictochat and DLP
if (ROM_TID == 0x41444E48 || ROM_TID == 0x41454E48
|| ROM_TID == 0x43444E48 || ROM_TID == 0x43454E48
|| ROM_TID == 0x4B444E48 || ROM_TID == 0x4B454E48) {
(*(vu16*)0x02FFFCFA) = 0x1041; // NoCash: channel ch1+7+13
}
#ifndef NO_SDMMC
if (dsiSD && dsiMode) {
sdmmc_controller_init(true);
@ -385,17 +576,18 @@ int main (void) {
// Pass command line arguments to loaded program
passArgs_ARM7();
if (twlclk) { REG_SCFG_CLK = 0x0187; } else { REG_SCFG_CLK = 0x0101; }
if (twlmode) {
REG_SCFG_EXT = 0x92FBFB06;
if (twlmode > 0) {
// REG_SCFG_EXT = 0x92FBFB06;
// REG_SCFG_EXT = 0x8307F100;
REG_SCFG_EXT = 0x93FFFB06;
} else {
REG_SCFG_EXT = 0x92A00000;
REG_SCFG_EXT = 0x92A40000; // REG_SCFG_EXT |= BIT(18);
REG_SCFG_ROM = 0x703;
}
if (scfgunlock) { REG_SCFG_EXT |= BIT(18); } else { REG_SCFG_EXT &= ~(1UL << 31); }
if (twlclk > 0) { REG_SCFG_CLK = 0x187; } else { REG_SCFG_CLK = 0x107; }
if (scfgunlock == 0)REG_SCFG_EXT &= ~(1UL << 31);
startBinary_ARM7();
return 0;
}

View File

@ -1,11 +1,140 @@
#ifndef _BOOT_H_
#define _BOOT_H_
typedef struct sTWLHeader {
char gameTitle[12]; //!< 12 characters for the game title.
char gameCode[4]; //!< 4 characters for the game code.
char makercode[2]; //!< identifies the (commercial) developer.
u8 unitCode; //!< identifies the required hardware.
u8 deviceType; //!< type of device in the game card
u8 deviceSize; //!< capacity of the device (1 << n Mbit)
u8 reserved1[9];
u8 romversion; //!< version of the ROM.
u8 flags; //!< bit 2: auto-boot flag.
u32 arm9romOffset; //!< offset of the arm9 binary in the nds file.
u32 arm9executeAddress; //!< adress that should be executed after the binary has been copied.
u32 arm9destination; //!< destination address to where the arm9 binary should be copied.
u32 arm9binarySize; //!< size of the arm9 binary.
u32 arm7romOffset; //!< offset of the arm7 binary in the nds file.
u32 arm7executeAddress; //!< adress that should be executed after the binary has been copied.
u32 arm7destination; //!< destination address to where the arm7 binary should be copied.
u32 arm7binarySize; //!< size of the arm7 binary.
u32 filenameOffset; //!< File Name Table (FNT) offset.
u32 filenameSize; //!< File Name Table (FNT) size.
u32 fatOffset; //!< File Allocation Table (FAT) offset.
u32 fatSize; //!< File Allocation Table (FAT) size.
u32 arm9overlaySource; //!< File arm9 overlay offset.
u32 arm9overlaySize; //!< File arm9 overlay size.
u32 arm7overlaySource; //!< File arm7 overlay offset.
u32 arm7overlaySize; //!< File arm7 overlay size.
u32 cardControl13; //!< Port 40001A4h setting for normal commands (used in modes 1 and 3)
u32 cardControlBF; //!< Port 40001A4h setting for KEY1 commands (used in mode 2)
u32 bannerOffset; //!< offset to the banner with icon and titles etc.
u16 secureCRC16; //!< Secure Area Checksum, CRC-16.
u16 readTimeout; //!< Secure Area Loading Timeout.
u32 unknownRAM1; //!< ARM9 Auto Load List RAM Address (?)
u32 unknownRAM2; //!< ARM7 Auto Load List RAM Address (?)
u32 bfPrime1; //!< Secure Area Disable part 1.
u32 bfPrime2; //!< Secure Area Disable part 2.
u32 romSize; //!< total size of the ROM.
u32 headerSize; //!< ROM header size.
u32 zeros88[14];
u8 gbaLogo[156]; //!< Nintendo logo needed for booting the game.
u16 logoCRC16; //!< Nintendo Logo Checksum, CRC-16.
u16 headerCRC16; //!< header checksum, CRC-16.
u32 debugRomSource; //!< debug ROM offset.
u32 debugRomSize; //!< debug size.
u32 debugRomDestination; //!< debug RAM destination.
u32 offset_0x16C; //reserved?
u8 zero[0x10];
u32 arm9MBK1;
u32 arm9MBK2;
u32 arm9MBK3;
u32 arm9MBK4;
u32 arm9MBK5;
u32 arm9MBK6;
u32 arm9MBK7;
u32 arm9MBK8;
u32 arm7MBK6;
u32 arm7MBK7;
u32 arm7MBK8;
u32 arm9MBKMaster;
u32 region;
u32 accessControl;
u32 arm7SCFGSettings;
u16 dsi_unk1;
u8 dsi_unk2;
u8 dsi_flags;
u32 arm9iromOffset; //!< offset of the arm9 binary in the nds file.
u32 arm9iexecuteAddress;
u32 arm9idestination; //!< destination address to where the arm9 binary should be copied.
u32 arm9ibinarySize; //!< size of the arm9 binary.
u32 arm7iromOffset; //!< offset of the arm7 binary in the nds file.
u32 deviceListDestination;
u32 arm7idestination; //!< destination address to where the arm7 binary should be copied.
u32 arm7ibinarySize; //!< size of the arm7 binary.
u8 zero2[0x20];
// 0x200
// TODO: More DSi-specific fields.
u32 dsi1[0x10/4];
u32 twlRomSize;
u32 dsi_unk3;
u32 dsi_unk4;
u32 dsi_unk5;
u32 modCrypt1Offset;
u32 modcrypt1Size;
u32 modcrypt2Offset;
u32 modcrypt2Size;
u32 dsi_tid;
u32 dsi_tid2;
u32 pubSavSize;
u32 prvSavSize;
u8 reserved3[176];
u8 age_ratings[0x10];
unsigned char hmac_arm9[16];
unsigned char hmac_arm7[16];
u8 hmac_digest_master[0x14];
u8 hmac_icon_title[0x14];
u8 hmac_arm9i[0x14];
u8 hmac_arm7i[0x14];
u8 reserved4[0x28];
u8 hmac_arm9_no_secure[0x14];
u8 reserved5[0xA4C];
u8 debug_args[0x180];
u8 rsa_signature[0x80];
} tTWLHeader;
#define resetMemory2_ARM9_size 0x400
void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9();
#define startBinary_ARM9_size 0x100
void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9();
// #define setSCFG_ARM9_size 0x400
#define ARM9_START_FLAG (*(vu8*)0x02FFFDFB)
void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9();
// void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) setSCFG_ARM9();
void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9();
#endif // _BOOT_H_

View File

@ -1,3 +1,4 @@
#include <stddef.h>
#include "tonccpy.h"
//# tonccpy.c
@ -11,18 +12,16 @@
\param size Fill-length in bytes.
\note The pointers and size need not be word-aligned.
*/
void tonccpy(void *dst, const void *src, uint size)
{
if(size==0 || dst==0 || src==0)
return;
void tonccpy(void *dst, const void *src, uint size) {
if(size==0 || dst==NULL || src==NULL) { return; }
uint count;
u16 *dst16; // hword destination
u8 *src8; // byte source
// Ideal case: copy by 4x words. Leaves tail for later.
if( ((u32)src|(u32)dst)%4==0 && size>=4)
{
if( ((u32)src|(u32)dst)%4==0 && size>=4) {
u32 *src32= (u32*)src, *dst32= (u32*)dst;
count= size/4;
@ -30,49 +29,43 @@ void tonccpy(void *dst, const void *src, uint size)
count /= 4;
// Duff's Device, good friend!
// Added fall through attribute to silance the compiler about this. ;)
switch(tmp) {
do { *dst32++ = *src32++;
case 3: *dst32++ = *src32++;
case 2: *dst32++ = *src32++;
case 1: *dst32++ = *src32++;
case 0: ; } while(count--);
do { *dst32++ = *src32++; // fallthrough
case 3: *dst32++ = *src32++; // fallthrough
case 2: *dst32++ = *src32++; // fallthrough
case 1: *dst32++ = *src32++; // fallthrough
case 0: ;} while(count--); // fallthrough
}
// Check for tail
size &= 3;
if(size == 0)
return;
if(size == 0) { return; }
src8= (u8*)src32;
dst16= (u16*)dst32;
}
else // Unaligned.
{
} else {
// Unaligned.
uint dstOfs= (u32)dst&1;
src8= (u8*)src;
dst16= (u16*)(dst-dstOfs);
// Head: 1 byte.
if(dstOfs != 0)
{
if(dstOfs != 0) {
*dst16= (*dst16 & 0xFF) | *src8++<<8;
dst16++;
if(--size==0)
return;
if(--size==0) { return; }
}
}
// Unaligned main: copy by 2x byte.
count= size/2;
while(count--)
{
while(count--) {
*dst16++ = src8[0] | src8[1]<<8;
src8 += 2;
}
// Tail: 1 byte.
if(size&1)
*dst16= (*dst16 &~ 0xFF) | *src8;
if(size&1) { *dst16= (*dst16 &~ 0xFF) | *src8; }
}
//# toncset.c
@ -87,21 +80,17 @@ void tonccpy(void *dst, const void *src, uint size)
word-aligned. In the case of unaligned fills, \a fill
will be masked off to match the situation.
*/
void __toncset(void *dst, u32 fill, uint size)
{
if(size==0 || dst==0)
return;
void __toncset(void *dst, u32 fill, uint size) {
if(size==0 || dst==NULL) { return; }
uint left= (u32)dst&3;
u32 *dst32= (u32*)(dst-left);
u32 count, mask;
// Unaligned head.
if(left != 0)
{
if(left != 0) {
// Adjust for very small stint.
if(left+size<4)
{
if(left+size<4) {
mask= BIT_MASK(size*8)<<(left*8);
*dst32= (*dst32 &~ mask) | (fill & mask);
return;
@ -117,20 +106,21 @@ void __toncset(void *dst, u32 fill, uint size)
count= size/4;
uint tmp= count&3;
count /= 4;
// Added fall through attribute to silance the compiler about this. ;)
switch(tmp) {
do { *dst32++ = fill;
case 3: *dst32++ = fill;
case 2: *dst32++ = fill;
case 1: *dst32++ = fill;
case 0: ; } while(count--);
do { *dst32++ = fill; // fallthrough
case 3: *dst32++ = fill; // fallthrough
case 2: *dst32++ = fill; // fallthrough
case 1: *dst32++ = fill; // fallthrough
case 0: ;} while(count--); // fallthrough
}
// Tail
size &= 3;
if(size)
{
if(size) {
mask= BIT_MASK(size*8);
*dst32= (*dst32 &~ mask) | (fill & mask);
}
}

View File

@ -0,0 +1,43 @@
//# Stuff you may not have yet.
#ifndef TONCCPY_H
#define TONCCPY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nds/ndstypes.h>
typedef unsigned int uint;
#define BIT_MASK(len) ( (1<<(len))-1 )
static inline u32 quad8(u16 x) { x |= x<<8; return x | x<<16; }
//# Declarations and inlines.
void tonccpy(void *dst, const void *src, uint size);
void __toncset(void *dst, u32 fill, uint size);
static inline void toncset(void *dst, u8 src, uint size);
static inline void toncset16(void *dst, u16 src, uint size);
static inline void toncset32(void *dst, u32 src, uint size);
//! VRAM-safe memset, byte version. Size in bytes.
static inline void toncset(void *dst, u8 src, uint size)
{ __toncset(dst, quad8(src), size); }
//! VRAM-safe memset, halfword version. Size in hwords.
static inline void toncset16(void *dst, u16 src, uint size)
{ __toncset(dst, src|src<<16, size*2); }
//! VRAM-safe memset, word version. Size in words.
static inline void toncset32(void *dst, u32 src, uint size)
{ __toncset(dst, src, size*4); }
#ifdef __cplusplus
}
#endif
#endif