DSi/3DS Support, add second bootloader for TWL

* Original bootloader doesn't currently support TWL carts so a second
one is used in those cases. (still unknown if cheat engine will work for
them however)
* Main code and bootloader updated to account for DSi/3DS consoles.
This commit is contained in:
ApacheThunder 2023-09-26 23:31:33 -05:00
parent c5b68b31a8
commit 0872e70084
57 changed files with 6744 additions and 170 deletions

5
.gitignore vendored
View File

@ -1,8 +1,13 @@
BootLoader/build
BootLoader/load.bin
BootLoaderTWL/build
BootLoaderTWL/load.bin
title/
arm7/build
arm9/build/
arm9/data/
arm9/source/version.h
*.nds
*.dsi
*.app
*.elf

View File

@ -208,6 +208,23 @@ void arm7_main (void) {
// Get ARM7 to clear RAM
arm7_resetMemory();
if (REG_SNDEXTCNT != 0) {
if ((REG_SCFG_EXT & BIT(31))) {
*((vu32*)REG_MBK1)=0x8D898581;
*((vu32*)REG_MBK2)=0x8C888480;
*((vu32*)REG_MBK3)=0x9C989490;
*((vu32*)REG_MBK4)=0x8C888480;
*((vu32*)REG_MBK5)=0x9C989490;
REG_MBK6=0x09403900;
REG_MBK7=0x09803940;
REG_MBK8=0x09C03980;
REG_MBK9=0xFCFFFF0F;
REG_SCFG_ROM = 0x703;
REG_SCFG_CLK = 0x100;
REG_SCFG_EXT = 0x12A00000;
}
}
ipcSendState(ARM7_LOADBIN);
// Load the NDS file
@ -215,7 +232,7 @@ void arm7_main (void) {
if (errorCode) {
errorOutput(errorCode);
}
ipcSendState(ARM7_HOOKBIN);
// Load the cheat engine and hook it into the ARM7 binary
@ -223,7 +240,7 @@ void arm7_main (void) {
if (errorCode != ERR_NONE && errorCode != ERR_NOCHEAT) {
errorOutput(errorCode);
}
ipcSendState(ARM7_BOOTBIN);
arm7_reset();

View File

@ -28,11 +28,8 @@
#include "encryption.h"
#include "common.h"
typedef union
{
char title[4];
u32 key;
} GameCode;
typedef union { char title[4]; u32 key; } GameCode;
static u32 portFlags = 0;
static u32 secureAreaData[CARD_SECURE_AREA_SIZE/sizeof(u32)];
@ -44,18 +41,12 @@ static u32 getRandomNumber(void) {
// guaranteed to be random.
}
static void decryptSecureArea (u32 gameCode, u32* secureArea)
{
static void decryptSecureArea (u32 gameCode, u32* secureArea) {
int i;
init_keycode (gameCode, 2, 8);
crypt_64bit_down (secureArea);
init_keycode (gameCode, 3, 8);
for (i = 0; i < 0x200; i+= 2) {
crypt_64bit_down (secureArea + i);
}
for (i = 0; i < 0x200; i+= 2) { crypt_64bit_down (secureArea + i); }
}
static struct {
@ -87,14 +78,11 @@ static void initKey1Encryption (u8* cmdData) {
}
// Note: cmdData must be aligned on a word boundary
static void createEncryptedCommand (u8 command, u8* cmdData, u32 block)
{
static void createEncryptedCommand (u8 command, u8* cmdData, u32 block) {
unsigned long iii, jjj;
if (command != CARD_CMD_SECURE_READ) {
block = key1data.llll;
}
if (command != CARD_CMD_SECURE_READ)block = key1data.llll;
if (command == CARD_CMD_ACTIVATE_SEC) {
iii = key1data.mmm;
jjj = key1data.nnn;
@ -133,8 +121,7 @@ static void cardDelay (u16 readTimeout) {
}
int cardInit (tNDSHeader* ndsHeader, u32* chipID)
{
int cardInit (tNDSHeader* 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
u32* secureArea;
@ -142,11 +129,9 @@ int cardInit (tNDSHeader* ndsHeader, u32* chipID)
int i;
u8 cmdData[8] __attribute__ ((aligned));
GameCode* gameCode;
// 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);
cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0);
// Verify that the ndsHeader is packed correctly, now that it's no longer __packed__
static_assert(sizeof(tNDSHeader) == 0x160, "tNDSHeader not packed properly");

118
BootLoaderTWL/Makefile Normal file
View File

@ -0,0 +1,118 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
endif
-include $(DEVKITARM)/ds_rules
#---------------------------------------------------------------------------------
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
export TARGET := loadtwl
BUILD := build
SOURCES := source source/patches
INCLUDES := build
SPECS := specs
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi
CFLAGS := -g -Wall -O2\
-fomit-frame-pointer\
-ffast-math \
-Wall -Wextra \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM7 -std=gnu99
ASFLAGS := -g $(ARCH) $(INCLUDE)
LDFLAGS := -nostartfiles -T$(CURDIR)/../loadtwl.ld -g $(ARCH) -Wl,-Map,$(TARGET).map
LIBS := -lnds7
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(LIBNDS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export TARGETBIN := $(CURDIR)/$(TARGET).bin
export ARM7ELF := $(CURDIR)/$(BUILD)/$(TARGET).arm7.elf
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
export CC := $(PREFIX)gcc
export CXX := $(PREFIX)g++
export AR := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
#---------------------------------------------------------------------------------
# use CC for linking standard C
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) *.elf loadtwl.bin
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(TARGETBIN) : $(ARM7ELF)
@$(OBJCOPY) -O binary $< $@
@echo built ... $(notdir $@)
$(ARM7ELF) : $(OFILES)
@echo linking $(notdir $@)
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

226
BootLoaderTWL/loadtwl.ld Normal file
View File

@ -0,0 +1,226 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
MEMORY {
vram : ORIGIN = 0x06020000, LENGTH = 128K
arm9ram : ORIGIN = 0x023FE000, LENGTH = 8K /* Used for the ARM9's functions */
}
__vram_start = ORIGIN(vram);
__vram_top = ORIGIN(vram)+ LENGTH(vram);
__sp_irq = __vram_top - 0x60;
__sp_svc = __sp_irq - 0x100;
__sp_usr = __sp_svc - 0x100;
__irq_flags = __vram_top - 8;
__irq_flagsaux = __vram_top - 0x40; /*__irq_flagsaux = 0x04000000 - 0x40;*/
__irq_vector = __vram_top - 4;
__arm9ram_start = ORIGIN(arm9ram);
__arm9ram_top = ORIGIN(arm9ram)+ LENGTH(arm9ram);
__arm9_sp_irq = __arm9ram_top - 0x60;
__arm9_sp_svc = __arm9_sp_irq - 0x100;
__arm9_sp_usr = __arm9_sp_svc - 0x100;
SECTIONS
{
.init :
{
__text_start = . ;
KEEP (*(.init))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.plt :
{
*(.plt)
} >vram = 0xff
__arm9_source_start = . ;
.arm9 :
{
__arm9_start = . ;
*.arm9.*(.text*)
*.arm9.*(.data*)
__arm9_bss_start = ABSOLUTE(.);
*.arm9.*(.bss*)
__arm9_bss_end = ABSOLUTE(.);
__arm9_end = . ;
} >arm9ram AT>vram =0xff
__arm9_source_end = __arm9_source_start + SIZEOF(.arm9);
. = __arm9_source_end;
. = ALIGN(4);
.text ALIGN(4) : /* ALIGN (4): */
{
*(.text)
*(.stub)
*(.text.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.fini :
{
KEEP (*(.fini))
} >vram =0xff
__text_end = . ;
.rodata :
{
*(.rodata)
*all.rodata*(*)
*(.roda)
*(.rodata.*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >vram
__exidx_start = .;
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >vram
__exidx_end = .;
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(32 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { KEEP (*(.preinit_array)) } >vram = 0xff
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { KEEP (*(.init_array)) } >vram = 0xff
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { KEEP (*(.fini_array)) } >vram = 0xff
PROVIDE (__fini_array_end = .);
.ctors :
{
/* gcc uses crtbegin.o to find the start of the constructors, so
we make sure it is first. Because this is a wildcard, it
doesn't matter if the user does not actually link against
crtbegin.o; the linker won't look for a file to match a
wildcard. The wildcard also means that it doesn't matter which
directory crtbegin.o is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.eh_frame :
{
KEEP (*(.eh_frame))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.gcc_except_table :
{
*(.gcc_except_table)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.jcr : { KEEP (*(.jcr)) } >vram = 0
.got : { *(.got.plt) *(.got) } >vram = 0
.vram ALIGN(4) :
{
__vram_start = ABSOLUTE(.) ;
*(.vram)
*vram.*(.text)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
__vram_end = ABSOLUTE(.) ;
} >vram = 0xff
.data ALIGN(4) : {
__data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(4);
__data_end = ABSOLUTE(.) ;
} >vram = 0xff
.bss ALIGN(4) :
{
__bss_start = ABSOLUTE(.);
__bss_start__ = ABSOLUTE(.);
*(.dynbss)
*(.gnu.linkonce.b*)
*(.bss*)
*(COMMON)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram
__bss_end = . ;
__bss_end__ = . ;
_end = . ;
__end__ = . ;
PROVIDE (end = _end);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.stack 0x80000 : { _stack = .; *(.stack) }
/* These must appear regardless of . */
}

View File

@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------------
Copyright (C) 2009
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.
---------------------------------------------------------------------------------*/
.text
.align 4
.arm
@---------------------------------------------------------------------------------
.global swiSoftResetarm7
.type swiSoftResetarm7 STT_FUNC
@---------------------------------------------------------------------------------
swiSoftResetarm7:
@---------------------------------------------------------------------------------
REG_IME = 0;
ldr r0,=0x2FFFE34
ldr r0,[r0]
bx r0
.pool

View File

@ -0,0 +1,56 @@
/*---------------------------------------------------------------------------------
Copyright (C) 2009
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.
---------------------------------------------------------------------------------*/
.text
.align 4
.arm
@---------------------------------------------------------------------------------
.global swiSoftResetarm9
.type swiSoftResetarm9 STT_FUNC
@---------------------------------------------------------------------------------
swiSoftResetarm9:
@---------------------------------------------------------------------------------
REG_IME = 0;
.arch armv5te
.cpu arm946e-s
ldr r1, =0x00002078 @ disable TCM and protection unit
mcr p15, 0, r1, c1, c0
@ Disable cache
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ Instruction cache
mcr p15, 0, r0, c7, c6, 0 @ Data cache
@ Wait for write buffer to empty
mcr p15, 0, r0, c7, c10, 4
ldr r0,=0x2FFFE24
ldr r0,[r0]
bx r0
.pool

167
BootLoaderTWL/source/card.h Normal file
View File

@ -0,0 +1,167 @@
/*---------------------------------------------------------------------------------
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.
---------------------------------------------------------------------------------*/
#ifndef NDS_CARD_INCLUDE
#define NDS_CARD_INCLUDE
#include "ndstypes.h"
// Card bus
#define REG_CARD_DATA_RD (*(vu32*)0x04100010)
#define REG_AUXSPICNT (*(vu16*)0x040001A0)
#define REG_AUXSPICNTH (*(vu8*)0x040001A1)
#define REG_AUXSPIDATA (*(vu8*)0x040001A2)
#define REG_ROMCTRL (*(vu32*)0x040001A4)
#define REG_CARD_COMMAND ((vu8*)0x040001A8)
#define REG_CARD_1B0 (*(vu32*)0x040001B0)
#define REG_CARD_1B4 (*(vu32*)0x040001B4)
#define REG_CARD_1B8 (*(vu16*)0x040001B8)
#define REG_CARD_1BA (*(vu16*)0x040001BA)
#define CARD_CR1_ENABLE 0x80 // in byte 1, i.e. 0x8000
#define CARD_CR1_IRQ 0x40 // in byte 1, i.e. 0x4000
// SPI EEPROM COMMANDS
#define SPI_EEPROM_WRSR 0x01
#define SPI_EEPROM_PP 0x02 // Page Program
#define SPI_EEPROM_READ 0x03
#define SPI_EEPROM_WRDI 0x04 // Write disable
#define SPI_EEPROM_RDSR 0x05 // Read status register
#define SPI_EEPROM_WREN 0x06 // Write enable
#define SPI_EEPROM_PW 0x0a // Page Write
#define SPI_EEPROM_FAST 0x0b // Fast Read
#define SPI_EEPROM_RDID 0x9f
#define SPI_EEPROM_RDP 0xab // Release from deep power down
#define SPI_EEPROM_DPD 0xb9 // Deep power down
#define CARD_ACTIVATE (1<<31) // when writing, get the ball rolling
#define CARD_WR (1<<30) // Card write enable
#define CARD_nRESET (1<<29) // value on the /reset pin (1 = high out, not a reset state, 0 = low out = in reset)
#define CARD_SEC_LARGE (1<<28) // Use "other" secure area mode, which tranfers blocks of 0x1000 bytes at a time
#define CARD_CLK_SLOW (1<<27) // Transfer clock rate (0 = 6.7MHz, 1 = 4.2MHz)
#define CARD_BLK_SIZE(n) (((n)&0x7)<<24) // Transfer block size, (0 = None, 1..6 = (0x100 << n) bytes, 7 = 4 bytes)
#define CARD_SEC_CMD (1<<22) // The command transfer will be hardware encrypted (KEY2)
#define CARD_DELAY2(n) (((n)&0x3F)<<16) // Transfer delay length part 2
#define CARD_SEC_SEED (1<<15) // Apply encryption (KEY2) seed to hardware registers
#define CARD_SEC_EN (1<<14) // Security enable
#define CARD_SEC_DAT (1<<13) // The data transfer will be hardware encrypted (KEY2)
#define CARD_DELAY1(n) ((n)&0x1FFF) // Transfer delay length part 1
// 3 bits in b10..b8 indicate something
// read bits
#define CARD_BUSY (1<<31) // when reading, still expecting incomming data?
#define CARD_DATA_READY (1<<23) // when reading, CARD_DATA_RD or CARD_DATA has another word of data and is good to go
// Card commands
#define CARD_CMD_DUMMY 0x9F
#define CARD_CMD_HEADER_READ 0x00
#define CARD_CMD_HEADER_CHIPID 0x90
#define CARD_CMD_ACTIVATE_BF 0x3C // Go into blowfish (KEY1) encryption mode
#define CARD_CMD_ACTIVATE_SEC 0x40 // Go into hardware (KEY2) encryption mode
#define CARD_CMD_SECURE_CHIPID 0x10
#define CARD_CMD_SECURE_READ 0x20
#define CARD_CMD_DISABLE_SEC 0x60 // Leave hardware (KEY2) encryption mode
#define CARD_CMD_DATA_MODE 0xA0
#define CARD_CMD_DATA_READ 0xB7
#define CARD_CMD_DATA_CHIPID 0xB8
//REG_AUXSPICNT
#define CARD_ENABLE (1<<15)
#define CARD_SPI_ENABLE (1<<13)
#define CARD_SPI_BUSY (1<<7)
#define CARD_SPI_HOLD (1<<6)
#define CARD_SPICNTH_ENABLE (1<<7) // in byte 1, i.e. 0x8000
#define CARD_SPICNTH_IRQ (1<<6) // in byte 1, i.e. 0x4000
#ifdef __cplusplus
extern "C" {
#endif
void enableSlot1();
void disableSlot1();
void cardWriteCommand(const u8 *command);
void cardPolledTransfer(u32 flags, u32 *destination, u32 length, const u8 *command);
void cardStartTransfer(const u8 *command, u32 *destination, int channel, u32 flags);
uint32 cardWriteAndRead(const u8 *command, u32 flags);
void cardParamCommand (u8 command, u32 parameter, u32 flags, u32 *destination, u32 length);
// These commands require the cart to not be initialized yet, which may mean the user
// needs to eject and reinsert the cart or they will return random data.
void cardReadHeader(u8 *header);
u32 cardReadID(u32 flags);
void cardReset();
//---------------------------------------------------------------------------------
static inline void eepromWaitBusy() {
//---------------------------------------------------------------------------------
while (REG_AUXSPICNT & CARD_SPI_BUSY);
}
// Reads from the EEPROM
void cardReadEeprom(u32 address, u8 *data, u32 length, u32 addrtype);
// Writes to the EEPROM. TYPE 3 EEPROM must be erased first (I think?)
void cardWriteEeprom(u32 address, u8 *data, u32 length, u32 addrtype);
// Returns the ID of the EEPROM chip? Doesn't work well, most chips give ff,ff
// i = 0 or 1
u32 cardEepromReadID();
// Sends a command to the EEPROM
u8 cardEepromCommand(u8 command);
/*
* -1:no card or no EEPROM
* 0:unknown PassMe?
* 1:TYPE 1 4Kbit(512Byte) EEPROM
* 2:TYPE 2 64Kbit(8KByte)or 512kbit(64Kbyte) EEPROM
* 3:TYPE 3 2Mbit(256KByte) FLASH MEMORY (some rare 4Mbit and 8Mbit chips also)
*/
int cardEepromGetType(void);
// Returns the size in bytes of EEPROM
u32 cardEepromGetSize();
// Erases the entire chip. TYPE 3 chips MUST be erased before writing to them. (I think?)
void cardEepromChipErase(void);
// Erases a single sector of the TYPE 3 chip
void cardEepromSectorErase(u32 address);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,148 @@
/*
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 "cheat.h"
#include "common.h"
extern unsigned long cheat_engine_size;
extern unsigned long intr_orig_return_offset;
extern const u8 cheat_engine_start[];
#define CHEAT_CODE_END 0xCF000000
#define CHEAT_ENGINE_RELOCATE 0xCF000001
#define CHEAT_ENGINE_HOOK 0xCF000002
static const u32 handlerStartSig[5] = {
0xe92d4000, // push {lr}
0xe3a0c301, // mov ip, #0x4000000
0xe28cce21, // add ip, ip, #0x210
0xe51c1008, // ldr r1, [ip, #-8]
0xe3510000 // cmp r1, #0
};
static const u32 handlerEndSig[4] = {
0xe59f1008, // ldr r1, [pc, #8] (IRQ Vector table address)
0xe7910100, // ldr r0, [r1, r0, lsl #2]
0xe59fe004, // ldr lr, [pc, #4] (IRQ return address)
0xe12fff10 // bx r0
};
static const int MAX_HANDLER_SIZE = 50;
static u32* hookInterruptHandler (u32* addr, size_t size) {
u32* end = addr + size/sizeof(u32);
int i;
// Find the start of the handler
while (addr < end) {
if ((addr[0] == handlerStartSig[0]) &&
(addr[1] == handlerStartSig[1]) &&
(addr[2] == handlerStartSig[2]) &&
(addr[3] == handlerStartSig[3]) &&
(addr[4] == handlerStartSig[4]))
{
break;
}
addr++;
}
if (addr >= end) {
return NULL;
}
// Find the end of the handler
for (i = 0; i < MAX_HANDLER_SIZE; i++) {
if ((addr[i+0] == handlerEndSig[0]) &&
(addr[i+1] == handlerEndSig[1]) &&
(addr[i+2] == handlerEndSig[2]) &&
(addr[i+3] == handlerEndSig[3]))
{
break;
}
}
if (i >= MAX_HANDLER_SIZE) {
return NULL;
}
// Now find the IRQ vector table
// Make addr point to the vector table address pointer within the IRQ handler
addr = addr + i + sizeof(handlerEndSig)/sizeof(handlerEndSig[0]);
// Use relative and absolute addresses to find the location of the table in RAM
u32 tableAddr = addr[0];
u32 returnAddr = addr[1];
u32* actualReturnAddr = addr + 2;
u32* actualTableAddr = actualReturnAddr + (tableAddr - returnAddr)/sizeof(u32);
// The first entry in the table is for the Vblank handler, which is what we want
return actualTableAddr;
}
int arm7_hookGame (const tNDSHeader* ndsHeader, const u32* cheatData, u32* cheatEngineLocation) {
u32 oldReturn;
u32 cheatWord1, cheatWord2;
u32* cheatDest;
u32* hookLocation = NULL;
if (cheatData[0] == CHEAT_CODE_END) {
return ERR_NOCHEAT;
}
if (cheatData[0] == CHEAT_ENGINE_RELOCATE) {
cheatWord1 = *cheatData++;
cheatWord2 = *cheatData++;
cheatEngineLocation = (u32*)cheatWord2;
}
if (cheatData[0] == CHEAT_ENGINE_HOOK) {
cheatWord1 = *cheatData++;
cheatWord2 = *cheatData++;
hookLocation = (u32*)cheatWord2;
}
if (!hookLocation) {
hookLocation = hookInterruptHandler ((u32*)ndsHeader->arm7destination, ndsHeader->arm7binarySize);
}
if (!hookLocation) {
return ERR_HOOK;
}
oldReturn = *hookLocation;
*hookLocation = (u32)cheatEngineLocation;
copyLoop (cheatEngineLocation, (u32*)cheat_engine_start, cheat_engine_size);
cheatEngineLocation [intr_orig_return_offset/sizeof(u32)] = oldReturn;
cheatDest = cheatEngineLocation + (cheat_engine_size/sizeof(u32));
// Copy cheat data across
do {
cheatWord1 = *cheatData++;
cheatWord2 = *cheatData++;
*cheatDest++ = cheatWord1;
*cheatDest++ = cheatWord2;
} while (cheatWord1 != CHEAT_CODE_END);
return ERR_NONE;
}

View File

@ -0,0 +1,27 @@
/*
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/memory.h>
#include <nds/ndstypes.h>
/*-------------------------------------------------------------------------
arm7_hookGame
Adds a hook in the game's ARM7 binary to our own code
-------------------------------------------------------------------------*/
int arm7_hookGame (const tNDSHeader* ndsHeader, const u32* cheatData, u32* cheatEngineLocation);

View File

@ -0,0 +1,485 @@
@ 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/asminc.h>
.arm
.global cheat_engine_start
.global cheat_engine_end
.global intr_orig_return_offset
.global cheat_engine_size
cheat_engine_size:
.word cheat_engine_end - cheat_engine_start
intr_orig_return_offset:
.word intr_orig_return - cheat_engine_start
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
BEGIN_ASM_FUNC cheat_engine_start
@ Hook the return address, then go back to the original function
stmdb sp!, {lr}
adr lr, code_handler_start
ldr r0, intr_orig_return
bx r0
code_handler_start:
stmdb sp!, {r0-r12}
mov r9, #0x00000000 @ offset register
mov r8, #0x00000000 @ execution status. bit0: 1 = no exec, 0 = exec. allows nested ifs 32 deep
mov r7, #0x00000000 @ Dx loop start
mov r6, #0x00000000 @ Dx repeat ammount
mov r5, #0x00000000 @ DX data
mov r4, #0x00000000 @ Dx execution status
@ increment counter
ldrh r0, counter_value
add r0, r0, #1
strh r0, counter_value
@ r0-r3 are generic registers for the code processor to use
@ 0xCF000000 0x00000000 indicates the end of the code list
@ r12 points to the next code to load
adr r12, cheat_data
main_loop:
ldmia r12!, {r10, r11} @ load a code
cmp r10, #0xCF000000
beq exit
mov r0, r10, lsr #28
cmp r0, #0xE
beq patch_code
cmp r0, #0xD
beq dx_codes
cmp r0, #0xC
beq type_c
@ check execution status
tst r8, #0x00000001
bne main_loop
@ check code group
cmp r0, #0x3
blt raw_write
cmp r0, #0x6
ble if_32bit
cmp r0, #0xB
blt if_16bit_mask
beq offset_load
b mem_copy_code
counter_value:
.word 0x00000000
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type 0-2
raw_write:
cmp r0, #0x1
bic r10, r10, #0xf0000000
strlt r11, [r10, r9] @ type 0
streqh r11, [r10, r9] @ type 1
strgtb r11, [r10, r9] @ type 2
b main_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type 3-6
@ r0 still contains the code type
if_32bit:
bic r1, r10, #0xf0000001
tst r10, #0x00000001
addne r1, r1, r9 @ add offset to the address if the lowest bit is set
cmp r1, #0x00000000
moveq r1, r9 @ if address is 0, set address to offset
ldr r1, [r1] @ load word from [0XXXXXXX]
mov r8, r8, lsl #1 @ push execution status
cmp r0, #0x3
beq if_32bit_bhi
cmp r0, #0x5
blt if_32bit_bcc
beq if_32bit_beq
@ fall through to if_32bit_bne
@ type 6
if_32bit_bne:
cmp r11, r1
orreq r8, r8, #0x00000001
b main_loop
@ type 3
if_32bit_bhi:
cmp r11, r1
orrls r8, r8, #0x00000001
b main_loop
@ type 4
if_32bit_bcc:
cmp r11, r1
orrcs r8, r8, #0x00000001
b main_loop
@ type 5
if_32bit_beq:
cmp r11, r1
orrne r8, r8, #0x00000001
b main_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type 7-A
@ r0 still contains the code type
if_16bit_mask:
bic r1, r10, #0xf0000001
tst r10, #0x00000001
addne r1, r1, r9 @ add offset to the address if the lowest bit is set
cmp r1, #0x00000000
moveq r1, r9 @ if address is 0, set address to offset
ldrh r1, [r1] @ load halfword from [0XXXXXXX]
mov r2, r11, lsr #16 @ bit mask
mov r3, r11, lsl #16 @ compare data
mov r3, r3, lsr #16
bic r1, r1, r2 @ clear any bit that is set in the mask
mov r8, r8, lsl #1 @ push execution status
cmp r0, #0x7
beq if_16bit_bhi
cmp r0, #0x9
blt if_16bit_bcc
beq if_16bit_beq
@ fall through to if_16bit_bne
@ type A
if_16bit_bne:
cmp r3, r1
orreq r8, r8, #0x00000001
b main_loop
@ type 7
if_16bit_bhi:
cmp r3, r1
orrls r8, r8, #0x00000001
b main_loop
@ type 8
if_16bit_bcc:
cmp r3, r1
orrcs r8, r8, #0x00000001
b main_loop
@ type 9
if_16bit_beq:
cmp r3, r1
orrne r8, r8, #0x00000001
b main_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type B
offset_load:
bic r10, r10, #0xf0000000
ldr r9, [r10, r9]
b main_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type C
type_c:
mov r0, r10, lsr #24
cmp r0, #0xC1
beq exec_remote_function
cmp r0, #0xC2
beq exec_custom_function
tst r8, #0x00000001 @ make sure execution is enabled
bne main_loop
cmp r0, #0xC0
beq loop_start
cmp r0, #0xC5
beq execution_counter @ type C5
offset_data_store: @ type C4
sublt r9, r12, #0x08 @ Offset = Two words back from current code pointer (ie, word at C4000000 code)
save_offset: @ type C6
strgt r9, [r11] @ Save offset to [XXXXXXXX] in C6000000 XXXXXXXX
b main_loop
loop_start:
mov r4, r8 @ execution status
mov r6, r11 @ loop repeat amount
mov r7, r12 @ loop start
b main_loop
exec_remote_function:
ldmia r12, {r0, r1, r2, r3} @ load arguments
and r10, r10, #0x00000007
add r12, r12, r10 @ move code pointer to where it should be
tst r8, #0x00000001
bne align_cheat_list @ execution disabled
stmdb sp!, {r12}
adr lr, exec_function_return
bx r11
exec_custom_function:
and r0, r10, #0x00000001 @ thumb mode?
add r0, r0, r12 @ custom function location
add r12, r12, r11
tst r8, #0x00000001
bne align_cheat_list @ execution disabled
stmdb sp!, {r12}
adr lr, exec_function_return
bx r0
exec_function_return:
ldmia sp!, {r12}
b align_cheat_list
execution_counter:
ldr r0, counter_value @ we only need the low 16 bits but counter_value is out of immediate range for ldrh
mov r1, r11, lsl #16
and r0, r0, r1, lsr #16 @ mask off counter
mov r8, r8, lsl #1 @ push execution status
cmp r0, r11, lsr #16 @ Compare against compare value component of code
orrne r8, r8, #0x00000001 @ set execution to false
b main_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type D
dx_codes:
mov r0, r10, lsr #24
cmp r0, #0xD3
bcs dx_conditional_exec
cmp r0, #0xD1
bgt end_loop_clear
beq end_loop_no_clear
@ fall through to end_if
@ type D0
end_if:
mov r8, r8, lsr #1 @ pop exec status
b main_loop
@ type D2
end_loop_clear:
mov r8, r4 @ restore the old execution status
cmp r6, #0 @ end of a loop?
@ no
subgt r6, r6, #1
movgt r12, r7 @ load the Dx loop start
bgt main_loop
@ yes
mov r5, #0 @ clear Dx data register
mov r8, #0 @ clear execution status
mov r9, #0 @ clear offset
b main_loop
@ type D1
end_loop_no_clear:
mov r8, r4 @ restore the old execution status
cmp r6, #0 @ end of a loop?
@ no
subgt r6, r6, #1
movgt r12, r7 @ load the Dx loop start
@ yes
b main_loop
dx_conditional_exec:
tst r8, #0x00000001
bne main_loop
cmp r0, #0xD6
bcs dx_write
cmp r0, #0xD4
@ type D3 - Offset Set
movlt r9, r11
beq dx_data_op
@ type D5 - Dx Data set
movgt r5, r11
b main_loop
dx_write:
cmp r0, #0xD9
bcs dx_load
cmp r0, #0xD7
@ type D6 - Dx Data write 32 bits
strlt r5, [r11, r9]
addlt r9, r9, #4
@ type D7 - Dx Data write 16 bits
streqh r5, [r11, r9]
addeq r9, r9, #2
@ type D8 - Dx Data write 8 bits
strgtb r5, [r11, r9]
addgt r9, r9, #1
b main_loop
dx_load:
cmp r0, #0xDC
bcs dx_offset_add_addr
cmp r0, #0xDA
@ type D9 - Dx Data load 32 bits
ldrlt r5, [r11, r9]
@ type DA - Dx Data load 16 bits
ldreqh r5, [r11, r9]
@ type DB - Dx Data load 8 bits
ldrgtb r5, [r11, r9]
b main_loop
@ type DC
dx_offset_add_addr:
add r9, r9, r11
b main_loop
@ type D4
dx_data_op:
and r0, r10, #0x000000ff
cmp r0, #0x01
@ type D4000000 - add, use negative values for sub
addlt r5, r5, r11
@ type D4000001 - or
orreq r5, r5, r11
ble main_loop
cmp r0, #0x03
@ type D4000002 - and
andlt r5, r5, r11
@ type D4000003 - xor
eoreq r5, r5, r11
ble main_loop
cmp r0, #0x05
@ type D4000004 - lsl
movlt r5, r5, lsl r11
@ type D4000005 - lsr
moveq r5, r5, lsr r11
ble main_loop
cmp r0, #0x07
@ type D4000006 - ror
movlt r5, r5, ror r11
@ type D4000007 - asr
moveq r5, r5, asr r11
ble main_loop
cmp r0, #0x09
@ type D4000008 - mul
mullt r5, r11, r5
b main_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type E
patch_code:
@ check execution status
tst r8, #0x00000001
addne r12, r12, r11 @ skip the data section
bne align_cheat_list
bic r10, r10, #0xf0000000 @ destination address
add r10, r10, r9 @ add offset to dest
@ r11 is bytes remaining
@ r12 is source
patch_code_word_loop:
cmp r11, #4
blt patch_code_byte_loop
ldr r1, [r12], #4
str r1, [r10], #4
sub r11, r11, #4
b patch_code_word_loop
patch_code_byte_loop:
cmp r11, #1
blt align_cheat_list @ patch_code_end
ldrb r1, [r12], #1
strb r1, [r10], #1
sub r11, r11, #1
b patch_code_byte_loop
align_cheat_list:
add r12, r12, #0x7
bic r12, r12, #0x00000007 @ round up to nearest multiple of 8
b main_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ type F
mem_copy_code:
bic r10, r10, #0xf0000000 @ destination address
@ r11 is bytes remaining
mov r2, r9 @ source address
mem_copy_code_word_loop:
cmp r11, #4
blt mem_copy_code_byte_loop
ldr r1, [r2], #4
str r1, [r10], #4
sub r11, r11, #4
b mem_copy_code_word_loop
mem_copy_code_byte_loop:
cmp r11, #1
blt main_loop @ mem_copy_code_end
ldrb r1, [r2], #1
strb r1, [r10], #1
sub r11, r11, #1
b mem_copy_code_byte_loop
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
exit:
ldmia sp!, {r0-r12}
ldmia sp!, {lr}
bx lr
intr_orig_return:
.word 0x00000000
.pool
cheat_data:
cheat_engine_end:
@ Cheat data goes here
.word 0xCF000000, 0x00000000
.word 0x00000000, 0x00000000
.word 0x00000000, 0x00000000
.word 0x00000000, 0x00000000

View File

@ -0,0 +1,68 @@
@ 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/>.
@ Clears ICache and Dcache, and resets the protection units
@ Originally written by Darkain, modified by Chishm
#include <nds/asminc.h>
.arm
BEGIN_ASM_FUNC arm9_clearCache
@ Clean and flush cache
mov r1, #0
outer_loop:
mov r0, #0
inner_loop:
orr r2, r1, r0
mcr p15, 0, r2, c7, c14, 2
add r0, r0, #0x20
cmp r0, #0x400
bne inner_loop
add r1, r1, #0x40000000
cmp r1, #0x0
bne outer_loop
mov r3, #0
mcr p15, 0, r3, c7, c5, 0 @ Flush ICache
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

@ -0,0 +1,44 @@
@ 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/>.
@ void arm7_clearmem (void* loc, size_t len);
@ Clears memory using an stmia loop
#include <nds/asminc.h>
.arm
BEGIN_ASM_FUNC arm7_clearmem
add r1, r0, r1
stmfd sp!, {r4-r9}
mov r2, #0
mov r3, #0
mov r4, #0
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
mov r9, #0
clearmem_loop:
stmia r0!, {r2-r9}
cmp r0, r1
blt clearmem_loop
ldmfd sp!, {r4-r9}
bx lr

View File

@ -0,0 +1,63 @@
/*
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 _COMMON_H
#define _COMMON_H
#include <nds/dma.h>
#include <stdlib.h>
#define resetCpu() \
__asm volatile("swi 0x000000")
typedef enum { ERR_NONE=0x00, ERR_STS_CLR_MEM=0x01, ERR_STS_LOAD_BIN=0x02, ERR_STS_HOOK_BIN=0x03, ERR_STS_START=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,
// hookARM7Binary error codes:
ERR_NOCHEAT=0x21, ERR_HOOK=0x22,
} ERROR_CODES;
typedef enum {ARM9_BOOT, ARM9_START, ARM9_MEMCLR, ARM9_READY, ARM9_BOOTBIN, ARM9_DISPERR, ARM9_SETSCFG} ARM9_STATE;
extern tNDSHeader* ndsHeader;
extern bool arm9_dsiModeConfirmed;
extern bool arm9_ExtendRam;
extern bool arm9_boostVram;
extern bool arm9_scfgUnlock;
extern bool arm9_TWLClockSpeeds;
extern bool arm9_DebugMode;
extern volatile int arm9_stateFlag;
extern volatile u32 arm9_errorCode;
extern volatile bool arm9_errorClearBG;
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) {
do {
*dest++ = *src++;
} while (size -= 4);
}
#endif // _COMMON_H

View File

@ -0,0 +1,62 @@
@---------------------------------------------------------------------------------
.global _arm9_start
@---------------------------------------------------------------------------------
.align 4
.arm
@---------------------------------------------------------------------------------
_arm9_start:
@---------------------------------------------------------------------------------
mov r0, #0x04000000 @ IME = 0;
add r0, r0, #0x208
strh r0, [r0]
mov r0, #0x12 @ Switch to IRQ Mode
msr cpsr, r0
ldr sp, =__arm9_sp_irq @ Set IRQ stack
mov r0, #0x13 @ Switch to SVC Mode
msr cpsr, r0
ldr sp, =__arm9_sp_svc @ Set SVC stack
mov r0, #0x1F @ Switch to System Mode
msr cpsr, r0
ldr sp, =__arm9_sp_usr @ Set user stack
ldr r0, =__arm9_bss_start @ Clear BSS section to 0x00
ldr r1, =__arm9_bss_end
sub r1, r1, r0
bl ClearMem
mov r0, #0 @ int argc
mov r1, #0 @ char *argv[]
ldr r3, =arm9_main
bl _blx_r3_stub @ jump to user code
@ If the user ever returns, restart
b _arm9_start
@---------------------------------------------------------------------------------
_blx_r3_stub:
@---------------------------------------------------------------------------------
bx r3
@---------------------------------------------------------------------------------
@ Clear memory to 0x00 if length != 0
@ r0 = Start Address
@ r1 = Length
@---------------------------------------------------------------------------------
ClearMem:
@---------------------------------------------------------------------------------
mov r2, #3 @ Round down to nearest word boundary
add r1, r1, r2 @ Shouldn't be needed
bics r1, r1, r2 @ Clear 2 LSB (and set Z)
bxeq lr @ Quit if copy size is 0
mov r2, #0
ClrLoop:
stmia r0!, {r2}
subs r1, r1, #4
bne ClrLoop
bx lr

View File

@ -0,0 +1,151 @@
/*
Copyright (C) 2008 somebody
Copyright (C) 2009 yellow wood goblin
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>
#include <nds/memory.h> // tNDSHeader
#include <stddef.h>
#include "module_params.h"
/*static void decompressLZ77Backwards(u8* addr, u32 size) {
u32 len = *(u32*)(addr + size - 4) + size;
if(len == size) {
size -= 12;
}
len = *(u32*)(addr + size - 4) + size;
//byte[] Result = new byte[len];
//Array.Copy(Data, Result, Data.Length);
u32 end = *(u32*)(addr + size - 8) & 0xFFFFFF;
u8* result = addr;
int Offs = (int)(size - (*(u32*)(addr + size - 8) >> 24));
int dstoffs = (int)len;
while (true) {
u8 header = result[--Offs];
for (int i = 0; i < 8; i++) {
if ((header & 0x80) == 0) {
result[--dstoffs] = result[--Offs];
} else {
u8 a = result[--Offs];
u8 b = result[--Offs];
int offs = (((a & 0xF) << 8) | b) + 2;//+ 1;
int length = (a >> 4) + 2;
do {
result[dstoffs - 1] = result[dstoffs + offs];
dstoffs--;
length--;
} while (length >= 0);
}
if (Offs <= size - end) {
return;
}
header <<= 1;
}
}
}*/
//static u32 iUncompressedSize = 0;
static u32 iFixedAddr = 0;
static u32 iFixedData = 0;
static u32 decompressBinary(u8 *aMainMemory, u32 aCodeLength, u32 aMemOffset) {
u8 *ADDR1 = NULL;
u8 *ADDR1_END = NULL;
u8 *ADDR2 = NULL;
u8 *ADDR3 = NULL;
u8 *pBuffer32 = (u8 *)(aMainMemory);
u8 *pBuffer32End = (u8 *)(aMainMemory + aCodeLength);
while (pBuffer32 < pBuffer32End) {
if (0xDEC00621 == *(u32 *)pBuffer32 && 0x2106C0DE == *(u32 *)(pBuffer32 + 4)) {
ADDR1 = (u8 *)(*(u32 *)(pBuffer32 - 8));
iFixedAddr = (u32)(pBuffer32 - 8);
iFixedData = *(u32 *)(pBuffer32 - 8);
*(u32 *)(pBuffer32 - 8) = 0;
break;
}
pBuffer32 += 4;
}
if (0 == ADDR1) {
iFixedAddr = 0;
return 0;
}
u32 A = *(u32 *)(ADDR1 + aMemOffset - 4);
u32 B = *(u32 *)(ADDR1 + aMemOffset - 8);
ADDR1_END = ADDR1 + A;
ADDR2 = ADDR1 - (B >> 24);
B &= ~0xff000000;
ADDR3 = ADDR1 - B;
u32 uncompressEnd = ((u32)ADDR1_END) - ((u32)aMainMemory);
while (!(ADDR2 <= ADDR3)) {
u32 marku8 = *(--ADDR2 + aMemOffset);
//ADDR2-=1;
int count = 8;
while (true) {
count--;
if (count < 0)
break;
if (0 == (marku8 & 0x80)) {
*(--ADDR1_END + aMemOffset) = *(--ADDR2 + aMemOffset);
} else {
int u8_r12 = *(--ADDR2 + aMemOffset);
int u8_r7 = *(--ADDR2 + aMemOffset);
u8_r7 |= (u8_r12 << 8);
u8_r7 &= ~0xf000;
u8_r7 += 2;
u8_r12 += 0x20;
do
{
u8 realu8 = *(ADDR1_END + aMemOffset + u8_r7);
*(--ADDR1_END + aMemOffset) = realu8;
u8_r12 -= 0x10;
} while (u8_r12 >= 0);
}
marku8 <<= 1;
if (ADDR2 <= ADDR3) {
break;
}
}
}
return uncompressEnd;
}
void ensureBinaryDecompressed(const tNDSHeader* ndsHeader, module_params_t* moduleParams) {
//const char* romTid = getRomTid(ndsHeader);
if (
moduleParams->compressed_static_end
/*|| strcmp(romTid, "YQUJ") == 0 // Chrono Trigger (Japan)
|| strcmp(romTid, "YQUE") == 0 // Chrono Trigger (USA)
|| strcmp(romTid, "YQUP") == 0 // Chrono Trigger (Europe)*/
) {
// Compressed
//dbg_printf("This rom is compressed\n");
//decompressLZ77Backwards((u8*)ndsHeader->arm9destination, ndsHeader->arm9binarySize);
decompressBinary((u8*)ndsHeader->arm9destination, ndsHeader->arm9binarySize, 0);
moduleParams->compressed_static_end = 0;
}/* else {
// Not compressed
dbg_printf("This rom is not compressed\n");
}*/
}

View File

@ -0,0 +1,112 @@
/*
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 <string.h>
#include "encryption.h"
#include "key1.h"
#include "key2.h"
#include "tonccpy.h"
#define KEYSIZE 0x1048
static u32 keycode [3];
static u32 keybuf [KEYSIZE/sizeof(u32)];
void crypt_64bit_up (u32* ptr) {
u32 x = ptr[1];
u32 y = ptr[0];
u32 z;
int i;
for (i = 0; i < 0x10; i++) {
z = keybuf[i] ^ x;
x = keybuf[0x012 + ((z>>24)&0xff)];
x = keybuf[0x112 + ((z>>16)&0xff)] + x;
x = keybuf[0x212 + ((z>> 8)&0xff)] ^ x;
x = keybuf[0x312 + ((z>> 0)&0xff)] + x;
x = y ^ x;
y = z;
}
ptr[0] = x ^ keybuf[0x10];
ptr[1] = y ^ keybuf[0x11];
}
void crypt_64bit_down (u32* ptr) {
u32 x = ptr[1];
u32 y = ptr[0];
u32 z;
int i;
for (i = 0x11; i > 0x01; i--) {
z = keybuf[i] ^ x;
x = keybuf[0x012 + ((z>>24)&0xff)];
x = keybuf[0x112 + ((z>>16)&0xff)] + x;
x = keybuf[0x212 + ((z>> 8)&0xff)] ^ x;
x = keybuf[0x312 + ((z>> 0)&0xff)] + x;
x = y ^ x;
y = z;
}
ptr[0] = x ^ keybuf[0x01];
ptr[1] = y ^ keybuf[0x00];
}
static u32 bswap_32bit (u32 in) {
u8 a,b,c,d;
a = (u8)((in >> 0) & 0xff);
b = (u8)((in >> 8) & 0xff);
c = (u8)((in >> 16) & 0xff);
d = (u8)((in >> 24) & 0xff);
u32 out = (a << 24) | (b << 16) | (c << 8) | (d << 0);
return out;
}
void apply_keycode (u32 modulo) {
u32 scratch[2];
int i;
modulo = modulo / sizeof(*keycode);
crypt_64bit_up (&keycode[1]);
crypt_64bit_up (&keycode[0]);
toncset (scratch, 0, 8);
for (i = 0; i < 0x12; i+=1) {
keybuf[i] = keybuf[i] ^ bswap_32bit (keycode[i % modulo]);
}
for (i = 0; i < 0x412; i+=2) {
crypt_64bit_up (scratch);
keybuf[i] = scratch[1];
keybuf[i+1] = scratch[0];
}
}
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;
if (level >= 1) apply_keycode (modulo); // first apply (always)
if (level >= 2) apply_keycode (modulo); // second apply (optional)
keycode[1] = keycode[1] * 2;
keycode[2] = keycode[2] / 2;
if (level >= 3) apply_keycode (modulo); // third apply (optional)
}

View File

@ -0,0 +1,27 @@
/*
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 ENCRYPTION_H
#define ENCRYPTION_H
#include <nds/ndstypes.h>
void init_keycode (u32 idcode, u32 level, u32 modulo, int iCardDevice);
void crypt_64bit_down (u32* ptr);
void crypt_64bit_up (u32* ptr);
#endif

View File

@ -0,0 +1,32 @@
#ifndef FIND_H
#define FIND_H
#include <nds/ndstypes.h>
#include <nds/memory.h> // tNDSHeader
#include "module_params.h"
// COMMON
//u8* memsearch(const u8* start, u32 dataSize, const u8* find, u32 findSize);
u32* memsearch32(const u32* start, u32 dataSize, const u32* find, u32 findSize, bool forward);
u16* memsearch16(const u16* start, u32 dataSize, const u16* find, u32 findSize, bool forward);
inline u32* findOffset(const u32* start, u32 dataSize, const u32* find, u32 findLen) {
return memsearch32(start, dataSize, find, findLen*sizeof(u32), true);
}
inline u32* findOffsetBackwards(const u32* start, u32 dataSize, const u32* find, u32 findLen) {
return memsearch32(start, dataSize, find, findLen*sizeof(u32), false);
}
inline u16* findOffsetThumb(const u16* start, u32 dataSize, const u16* find, u32 findLen) {
return memsearch16(start, dataSize, find, findLen*sizeof(u16), true);
}
inline u16* findOffsetBackwardsThumb(const u16* start, u32 dataSize, const u16* find, u32 findLen) {
return memsearch16(start, dataSize, find, findLen*sizeof(u16), false);
}
const u32* getMpuInitRegionSignature(u32 patchMpuRegion);
u32* findMpuStartOffset(const tNDSHeader* ndsHeader, u32 patchMpuRegion);
u32* findMpuDataOffset(const module_params_t* moduleParams, u32 patchMpuRegion, const u32* mpuStartOffset);
u32* findMpuInitCacheOffset(const u32* mpuStartOffset);
#endif // FIND_H

View File

@ -0,0 +1,141 @@
#include <stddef.h> // NULL
#include "patch.h"
#include "find.h"
//#define memset __builtin_memset
//
// Subroutine function signatures ARM9
//
// Mpu cache
static const u32 mpuInitRegion0Signature[1] = {0xEE060F10};
static const u32 mpuInitRegion0Data[1] = {0x4000033};
static const u32 mpuInitRegion1Signature[1] = {0xEE060F11};
static const u32 mpuInitRegion1Data1[1] = {0x200002D}; // SDK <= 3
static const u32 mpuInitRegion1Data4[1] = {0x200002D}; // SDK >= 4
//static const u32 mpuInitRegion1DataAlt[1] = {0x200002B};
static const u32 mpuInitRegion2Signature[1] = {0xEE060F12};
static const u32 mpuInitRegion2Data1[1] = {0x27C0023}; // SDK != 3 (Previously: SDK <= 2)
static const u32 mpuInitRegion2Data3[1] = {0x27E0021}; // SDK 3 (Previously: SDK >= 3)
static const u32 mpuInitRegion3Signature[1] = {0xEE060F13};
static const u32 mpuInitRegion3Data[1] = {0x8000035};
// Mpu cache init
static const u32 mpuInitCache[1] = {0xE3A00042};
const u32* getMpuInitRegionSignature(u32 patchMpuRegion) {
switch (patchMpuRegion) {
case 0: return mpuInitRegion0Signature;
case 1: return mpuInitRegion1Signature;
case 2: return mpuInitRegion2Signature;
case 3: return mpuInitRegion3Signature;
}
return mpuInitRegion1Signature;
}
u32* findMpuStartOffset(const tNDSHeader* ndsHeader, u32 patchMpuRegion) {
// dbg_printf("findMpuStartOffset:\n");
const u32* mpuInitRegionSignature = getMpuInitRegionSignature(patchMpuRegion);
u32* mpuStartOffset = findOffset(
(u32*)ndsHeader->arm9destination, ndsHeader->arm9binarySize,
mpuInitRegionSignature, 1
);
if (mpuStartOffset) {
// dbg_printf("Mpu init found: ");
} else {
// dbg_printf("Mpu init not found\n");
}
if (mpuStartOffset) {
// dbg_hexa((u32)mpuStartOffset);
// dbg_printf("\n");
}
// dbg_printf("\n");
return mpuStartOffset;
}
u32* findMpuDataOffset(const module_params_t* moduleParams, u32 patchMpuRegion, const u32* mpuStartOffset) {
if (!mpuStartOffset) {
return NULL;
}
// dbg_printf("findMpuDataOffset:\n");
const u32* mpuInitRegion1Data = mpuInitRegion1Data1;
const u32* mpuInitRegion2Data = mpuInitRegion2Data1;
if (moduleParams->sdk_version > 0x3000000 && moduleParams->sdk_version < 0x4000000) {
mpuInitRegion2Data = mpuInitRegion2Data3;
} else if (moduleParams->sdk_version > 0x4000000) {
mpuInitRegion1Data = mpuInitRegion1Data4;
}
const u32* mpuInitRegionData = mpuInitRegion1Data;
switch (patchMpuRegion) {
case 0:
mpuInitRegionData = mpuInitRegion0Data;
break;
case 1:
mpuInitRegionData = mpuInitRegion1Data;
break;
case 2:
mpuInitRegionData = mpuInitRegion2Data;
break;
case 3:
mpuInitRegionData = mpuInitRegion3Data;
break;
}
u32* mpuDataOffset = findOffset(
mpuStartOffset, 0x100,
mpuInitRegionData, 1
);
if (!mpuDataOffset) {
// Try to find it
for (int i = 0; i < 0x100; i++) {
mpuDataOffset += i;
if ((*mpuDataOffset & 0xFFFFFF00) == 0x02000000) {
break;
}
}
}
if (mpuDataOffset) {
// dbg_printf("Mpu data found: ");
} else {
// dbg_printf("Mpu data not found\n");
}
if (mpuDataOffset) {
// dbg_hexa((u32)mpuDataOffset);
// dbg_printf("\n");
}
// dbg_printf("\n");
return mpuDataOffset;
}
u32* findMpuInitCacheOffset(const u32* mpuStartOffset) {
// dbg_printf("findMpuInitCacheOffset:\n");
u32* mpuInitCacheOffset = findOffset(
mpuStartOffset, 0x100,
mpuInitCache, 1
);
if (mpuInitCacheOffset) {
// dbg_printf("Mpu init cache found: ");
} else {
// dbg_printf("Mpu init cache not found\n");
}
if (mpuInitCacheOffset) {
// dbg_hexa((u32)mpuInitCacheOffset);
// dbg_printf("\n");
}
// dbg_printf("\n");
return mpuInitCacheOffset;
}

View File

@ -0,0 +1,117 @@
//#include <string.h> // memcmp
#include <stddef.h> // NULL
#include <nds/ndstypes.h>
//#include <limits.h>
#include "find.h"
// (memcmp is slower)
//#define memcmp __builtin_memcmp
//#define TABLE_SIZE (UCHAR_MAX + 1) // 256
extern inline u32* findOffset(const u32* start, u32 dataLen, const u32* find, u32 findLen);
extern inline u32* findOffsetBackwards(const u32* start, u32 dataLen, const u32* find, u32 findLen);
extern inline u16* findOffsetThumb(const u16* start, u32 dataLen, const u16* find, u32 findLen);
extern inline u16* findOffsetBackwardsThumb(const u16* start, u32 dataLen, const u16* find, u32 findLen);
/*
* Look for @find and return the position of it.
* Brute Force algorithm
*/
u32* memsearch32(const u32* start, u32 dataSize, const u32* find, u32 findSize, bool forward) {
u32 dataLen = dataSize/sizeof(u32);
u32 findLen = findSize/sizeof(u32);
const u32* end = forward ? (start + dataLen) : (start - dataLen);
for (u32* addr = (u32*)start; addr != end; forward ? ++addr : --addr) {
bool found = true;
for (u32 j = 0; j < findLen; ++j) {
if (addr[j] != find[j]) {
found = false;
break;
}
}
if (found) {
return (u32*)addr;
}
}
return NULL;
}
u16* memsearch16(const u16* start, u32 dataSize, const u16* find, u32 findSize, bool forward) {
u32 dataLen = dataSize/sizeof(u16);
u32 findLen = findSize/sizeof(u16);
const u16* end = forward ? (start + dataLen) : (start - dataLen);
for (u16* addr = (u16*)start; addr != end; forward ? ++addr : --addr) {
bool found = true;
for (u32 j = 0; j < findLen; ++j) {
if (addr[j] != find[j]) {
found = false;
break;
}
}
if (found) {
return (u16*)addr;
}
}
return NULL;
}
/*
* Boyer-Moore Horspool algorithm
*/
/*u8* memsearch(const u8* start, u32 dataSize, const u8* find, u32 findSize) {
u32 dataLen = dataSize/sizeof(u8);
u32 findLen = findSize/sizeof(u8);
u32 table[TABLE_SIZE];
// Preprocessing
for (u32 i = 0; i < TABLE_SIZE; ++i) {
table[i] = findLen;
}
for (u32 i = 0; i < findLen - 1; ++i) {
table[find[i]] = findLen - i - 1;
}
// Searching
u32 j = 0;
while (j <= dataLen - findLen) {
u8 c = start[j + findLen - 1];
if (find[findLen - 1] == c && memcmp(find, start + j, findLen - 1) == 0) {
return (u8*)start + j;
}
j += table[c];
}
return NULL;
}*/
/*
* Quick Search algorithm
*/
/*u8* memsearch(const u8* start, u32 dataSize, const u8* find, u32 findSize) {
u32 dataLen = dataSize/sizeof(u8);
u32 findLen = findSize/sizeof(u8);
u32 table[TABLE_SIZE];
// Preprocessing
for (u32 i = 0; i < TABLE_SIZE; ++i) {
table[i] = findLen + 1;
}
for (u32 i = 0; i < findLen; ++i) {
table[find[i]] = findLen - i;
}
// Searching
u32 j = 0;
while (j <= dataLen - findLen) {
if (memcmp(find, start + j, findLen) == 0) {
return (u8*)start + j;
}
j += table[start[j + findLen]];
}
return NULL;
}*/

264
BootLoaderTWL/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
BootLoaderTWL/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

@ -0,0 +1,111 @@
@---------------------------------------------------------------------------------
.section ".init"
.global _start
@---------------------------------------------------------------------------------
.align 4
.arm
@---------------------------------------------------------------------------------
_start:
@---------------------------------------------------------------------------------
b startUp
startUp:
mov r0, #0x04000000 @ IME = 0;
add r0, r0, #0x208
strh r0, [r0]
mov r0, #0x12 @ Switch to IRQ Mode
msr cpsr, r0
ldr sp, =__sp_irq @ Set IRQ stack
mov r0, #0x13 @ Switch to SVC Mode
msr cpsr, r0
ldr sp, =__sp_svc @ Set SVC stack
mov r0, #0x1F @ Switch to System Mode
msr cpsr, r0
ldr sp, =__sp_usr @ Set user stack
ldr r0, =__bss_start @ Clear BSS section to 0x00
ldr r1, =__bss_end
sub r1, r1, r0
bl ClearMem
@ Load ARM9 region into main RAM
ldr r1, =__arm9_source_start
ldr r2, =__arm9_start
ldr r3, =__arm9_source_end
sub r3, r3, r1
bl CopyMem
@ Start ARM9 binary
ldr r0, =0x02FFFE24
ldr r1, =_arm9_start
str r1, [r0]
mov r0, #0 @ int argc
mov r1, #0 @ char *argv[]
ldr r3, =arm7_main
bl _blx_r3_stub @ jump to user code
@ If the user ever returns, restart
b _start
@---------------------------------------------------------------------------------
_blx_r3_stub:
@---------------------------------------------------------------------------------
bx r3
@---------------------------------------------------------------------------------
@ Clear memory to 0x00 if length != 0
@ r0 = Start Address
@ r1 = Length
@---------------------------------------------------------------------------------
ClearMem:
@---------------------------------------------------------------------------------
mov r2, #3 @ Round down to nearest word boundary
add r1, r1, r2 @ Shouldn't be needed
bics r1, r1, r2 @ Clear 2 LSB (and set Z)
bxeq lr @ Quit if copy size is 0
mov r2, #0
ClrLoop:
stmia r0!, {r2}
subs r1, r1, #4
bne ClrLoop
bx lr
@---------------------------------------------------------------------------------
@ Copy memory if length != 0
@ r1 = Source Address
@ r2 = Dest Address
@ r4 = Dest Address + Length
@---------------------------------------------------------------------------------
CopyMemCheck:
@---------------------------------------------------------------------------------
sub r3, r4, r2 @ Is there any data to copy?
@---------------------------------------------------------------------------------
@ Copy memory
@ r1 = Source Address
@ r2 = Dest Address
@ r3 = Length
@---------------------------------------------------------------------------------
CopyMem:
@---------------------------------------------------------------------------------
mov r0, #3 @ These commands are used in cases where
add r3, r3, r0 @ the length is not a multiple of 4,
bics r3, r3, r0 @ even though it should be.
bxeq lr @ Length is zero, so exit
CIDLoop:
ldmia r1!, {r0}
stmia r2!, {r0}
subs r3, r3, #4
bne CIDLoop
bx lr
@---------------------------------------------------------------------------------
.align
.pool
.end
@---------------------------------------------------------------------------------

View File

@ -0,0 +1,367 @@
/*
main.arm7.c
By Michael Chisholm (Chishm)
All resetMemory and startBinary functions are based
on the MultiNDS loader by Darkain.
Original source available at:
http://cvs.sourceforge.net/viewcvs.py/ndslib/ndslib/examples/loader/boot/main.cpp
License:
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 ARM7
# define ARM7
#endif
#include <nds/ndstypes.h>
#include <nds/arm7/codec.h>
#include <nds/system.h>
#include <nds/interrupts.h>
#include <nds/timers.h>
#include <nds/dma.h>
#include <nds/arm7/audio.h>
#include <nds/ipc.h>
#include <string.h>
#ifndef NULL
#define NULL 0
#endif
#include "common.h"
#include "tonccpy.h"
#include "read_card.h"
#include "module_params.h"
#include "find.h"
#include "cheat.h"
void arm7_clearmem (void* loc, size_t len);
extern void ensureBinaryDecompressed(const tNDSHeader* ndsHeader, module_params_t* moduleParams);
// Module params
static const u32 moduleParamsSignature[2] = {0xDEC00621, 0x2106C0DE};
static u32 chipID;
static module_params_t* moduleParams;
u32* findModuleParamsOffset(const tNDSHeader* ndsHeader) {
u32* moduleParamsOffset = findOffset((u32*)ndsHeader->arm9destination, ndsHeader->arm9binarySize, moduleParamsSignature, 2);
return moduleParamsOffset;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Important things
#define NDS_HEADER 0x027FFE00
#define NDS_HEADER_SDK5 0x02FFFE00 // __NDSHeader
#define NDS_HEADER_POKEMON 0x027FF000
#define DSI_HEADER 0x027FE000
#define DSI_HEADER_SDK5 0x02FFE000 // __DSiHeader
// #define CHEAT_ENGINE_LOCATION 0x027FE000
#define CHEAT_ENGINE_LOCATION 0x023FE800
#define CHEAT_DATA_LOCATION 0x06030000
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Used for debugging purposes
static void debugOutput (u32 code) {
// Wait until the ARM9 is ready
while (arm9_stateFlag != ARM9_READY);
// Set the error code, then tell ARM9 to display it
arm9_errorCode = code;
arm9_stateFlag = ARM9_DISPERR;
// Wait for completion
while (arm9_stateFlag != ARM9_READY);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 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 memset_addrs_arm7(u32 start, u32 end) { toncset((u32*)start, 0, ((int)end - (int)start)); }
/*-------------------------------------------------------------------------
arm7_resetMemory
Clears all of the NDS's RAM that is visible to the ARM7
Written by Darkain.
Modified by Chishm:
* Added STMIA clear mem loop
--------------------------------------------------------------------------*/
void arm7_resetMemory (void) {
int i, reg;
REG_IME = 0;
for (i=0; i<16; i++) {
SCHANNEL_CR(i) = 0;
SCHANNEL_TIMER(i) = 0;
SCHANNEL_SOURCE(i) = 0;
SCHANNEL_LENGTH(i) = 0;
}
REG_SOUNDCNT = 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 ((REG_SCFG_EXT & BIT(31)))for(reg=0; reg<0x1c; reg+=4)*((u32*)(0x04004104 + ((i*0x1c)+reg))) = 0; //Reset NDMA.
}
// Clear out FIFO
REG_IPC_SYNC = 0;
REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR;
REG_IPC_FIFO_CR = 0;
// clear IWRAM - 037F:8000 to 0380:FFFF, total 96KiB
toncset ((void*)0x037F8000, 0, 96*1024);
memset_addrs_arm7(0x03000000, 0x0380FFC0);
memset_addrs_arm7(0x0380FFD0, 0x03800000 + 0x10000);
// clear most of EXRAM - except before 0x023F0000, which has the cheat data
toncset ((void*)0x02004000, 0, 0x3EC000);
// clear more of EXRAM, skipping the cheat data section
toncset ((void*)0x023F8000, 0, 0x6000);
// clear last part of EXRAM
toncset ((void*)0x02400000, 0, 0xC00000);
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 stuffs
}
// SDK 5
static bool ROMsupportsDSiMode(const tNDSHeader* ndsHeader) { return (ndsHeader->unitCode > 0); }
// SDK 5
static bool ROMisDSiEnhanced(const tNDSHeader* ndsHeader) { return (ndsHeader->unitCode == 0x02); }
// SDK 5
static bool ROMisDSiExclusive(const tNDSHeader* ndsHeader) { return (ndsHeader->unitCode == 0x03); }
int arm7_loadBinary (const tDSiHeader* dsiHeaderTemp) {
u32 errorCode;
// Init card
errorCode = cardInit((sNDSHeaderExt*)dsiHeaderTemp, &chipID);
if (errorCode)return errorCode;
// Fix Pokemon games needing header data.
tonccpy((u32*)NDS_HEADER_POKEMON, (u32*)NDS_HEADER, 0x170);
char* romTid = (char*)NDS_HEADER_POKEMON+0xC;
if (
memcmp(romTid, "ADA", 3) == 0 // Diamond
|| memcmp(romTid, "APA", 3) == 0 // Pearl
|| memcmp(romTid, "CPU", 3) == 0 // Platinum
|| memcmp(romTid, "IPK", 3) == 0 // HG
|| memcmp(romTid, "IPG", 3) == 0 // SS
) {
// Make the Pokemon game code ADAJ.
const char gameCodePokemon[] = { 'A', 'D', 'A', 'J' };
tonccpy((char*)NDS_HEADER_POKEMON+0xC, gameCodePokemon, 4);
}
cardRead(dsiHeaderTemp->ndshdr.arm9romOffset, (u32*)dsiHeaderTemp->ndshdr.arm9destination, dsiHeaderTemp->ndshdr.arm9binarySize);
cardRead(dsiHeaderTemp->ndshdr.arm7romOffset, (u32*)dsiHeaderTemp->ndshdr.arm7destination, dsiHeaderTemp->ndshdr.arm7binarySize);
moduleParams = (module_params_t*)findModuleParamsOffset(&dsiHeaderTemp->ndshdr);
return ERR_NONE;
}
static tNDSHeader* loadHeader(tDSiHeader* dsiHeaderTemp) {
tNDSHeader* ndsHeader = (tNDSHeader*)(isSdk5(moduleParams) ? NDS_HEADER_SDK5 : NDS_HEADER);
*ndsHeader = dsiHeaderTemp->ndshdr;
return ndsHeader;
}
/*-------------------------------------------------------------------------
arm7_startBinary
Jumps to the ARM7 NDS binary in sync with the display and ARM9
Written by Darkain, modified by Chishm.
--------------------------------------------------------------------------*/
void arm7_startBinary (void) {
REG_IME = 0;
// Get the ARM9 to boot
arm9_stateFlag = ARM9_BOOTBIN;
while(REG_VCOUNT!=191);
while(REG_VCOUNT==191);
// Start ARM7
VoidFn arm7code = (VoidFn)ndsHeader->arm7executeAddress;
arm7code();
}
static void setMemoryAddress(const tNDSHeader* ndsHeader) {
if (ROMsupportsDSiMode(ndsHeader)) {
tonccpy((u32*)0x02FFFA80, (u32*)NDS_HEADER_SDK5, 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 memory values expected by loaded NDS
// from NitroHax, thanks to Chism
*((u32*)(isSdk5(moduleParams) ? 0x02fff800 : 0x027ff800)) = chipID; // CurrentCardID
*((u32*)(isSdk5(moduleParams) ? 0x02fff804 : 0x027ff804)) = chipID; // Command10CardID
*((u16*)(isSdk5(moduleParams) ? 0x02fff808 : 0x027ff808)) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)(isSdk5(moduleParams) ? 0x02fff80a : 0x027ff80a)) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
// Copies of above
*((u32*)(isSdk5(moduleParams) ? 0x02fffc00 : 0x027ffc00)) = chipID; // CurrentCardID
*((u32*)(isSdk5(moduleParams) ? 0x02fffc04 : 0x027ffc04)) = chipID; // Command10CardID
*((u16*)(isSdk5(moduleParams) ? 0x02fffc08 : 0x027ffc08)) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh]
*((u16*)(isSdk5(moduleParams) ? 0x02fffc0a : 0x027ffc0a)) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh]
*((u16*)(isSdk5(moduleParams) ? 0x02fffc40 : 0x027ffc40)) = 0x1; // Boot Indicator (Booted from card for SDK5) -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Main function
void arm7_main (void) {
if (REG_SNDEXTCNT != 0) {
if ((REG_SCFG_EXT & BIT(31))) {
REG_MBK9=0xFCFFFF0F;
*((vu32*)REG_MBK1)=0x8D898581;
*((vu32*)REG_MBK2)=0x8C888480;
*((vu32*)REG_MBK3)=0x9C989490;
*((vu32*)REG_MBK4)=0x8C888480;
*((vu32*)REG_MBK5)=0x9C989490;
REG_MBK6=0x09403900;
REG_MBK7=0x09803940;
REG_MBK8=0x09C03980;
}
}
int errorCode;
// Wait for ARM9 to at least start
while (arm9_stateFlag < ARM9_START);
// debugOutput (ERR_STS_CLR_MEM);
// Get ARM7 to clear RAM
arm7_resetMemory();
// debugOutput (ERR_STS_LOAD_BIN);
if ((REG_SCFG_EXT & BIT(31)))REG_SCFG_ROM = 0x703;
tDSiHeader* dsiHeaderTemp = (tDSiHeader*)0x02FFC000;
// Load the NDS file
errorCode = arm7_loadBinary(dsiHeaderTemp);
if (errorCode)debugOutput(errorCode);
// Override some settings depending on if DSi Enhanced cart or DSi Exclusive cart is inserted
// if (ROMisDSiEnhanced(&dsiHeaderTemp->ndshdr)) { extendRam = true; } // Required for TWL carts to boot properly. Disabled by default for NTR carts to allow WoodR4 to operate correctly.
/*if (twlMode) {
if (dsiHeaderTemp->arm9ibinarySize > 0) {
cardRead((u32)dsiHeaderTemp->arm9iromOffset, (u32*)dsiHeaderTemp->arm9idestination, dsiHeaderTemp->arm9ibinarySize);
}
if (dsiHeaderTemp->arm7ibinarySize > 0) {
cardRead((u32)dsiHeaderTemp->arm7iromOffset, (u32*)dsiHeaderTemp->arm7idestination, dsiHeaderTemp->arm7ibinarySize);
}
}*/
ndsHeader = loadHeader(dsiHeaderTemp);
if (!ROMisDSiExclusive(&dsiHeaderTemp->ndshdr)) { tonccpy((u32*)0x023FF000, (u32*)(isSdk5(moduleParams) ? 0x02FFF000 : 0x027FF000), 0x1000); }
my_readUserSettings(ndsHeader); // Header has to be loaded first
toncset ((void*)0x023F0000, 0, 0x8000); // Clear cheat data from main memory
// debugOutput (ERR_STS_START);
if (ROMisDSiExclusive(&dsiHeaderTemp->ndshdr)) { REG_SCFG_CLK = 0x0184; } else { REG_SCFG_CLK = 0x0100; }
if (REG_SNDEXTCNT != 0) {
if ((REG_SCFG_EXT & BIT(31)))REG_SCFG_EXT = 0x12A00000;
//REG_SCFG_EXT &= ~(1UL << 31);
}
while (arm9_stateFlag != ARM9_READY);
arm9_stateFlag = ARM9_SETSCFG;
while (arm9_stateFlag != ARM9_READY);
setMemoryAddress(ndsHeader);
// Load the cheat engine and hook it into the ARM7 binary
errorCode = arm7_hookGame(ndsHeader, (const u32*)CHEAT_DATA_LOCATION, (u32*)CHEAT_ENGINE_LOCATION);
if (errorCode != ERR_NONE && errorCode != ERR_NOCHEAT)debugOutput(errorCode);
arm7_startBinary();
while (1);
}

View File

@ -0,0 +1,323 @@
/*
main.arm9.c
By Michael Chisholm (Chishm)
All resetMemory and startBinary functions are based
on the MultiNDS loader by Darkain.
Original source available at:
http://cvs.sourceforge.net/viewcvs.py/ndslib/ndslib/examples/loader/boot/main.cpp
License:
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/>.
*/
#define ARM9
#undef ARM7
#include <nds/memory.h>
#include <nds/arm9/video.h>
#include <nds/arm9/input.h>
#include <nds/interrupts.h>
#include <nds/dma.h>
#include <nds/timers.h>
#include <nds/system.h>
#include <nds/ipc.h>
#include <nds/dma.h>
#include <stddef.h> // NULL
#include <stdlib.h>
#include "common.h"
tNDSHeader* ndsHeader = NULL;
volatile int arm9_stateFlag = ARM9_BOOT;
volatile u32 arm9_errorCode = 0xFFFFFFFF;
volatile u32 arm9_BLANK_RAM = 0;
/*-------------------------------------------------------------------------
External functions
--------------------------------------------------------------------------*/
extern void arm9_clearCache (void);
void SetBrightness(u8 screen, s8 bright) {
u16 mode = 1 << 14;
if (bright < 0) {
mode = 2 << 14;
bright = -bright;
}
if (bright > 31) { bright = 31; }
*(u16*)(0x0400006C + (0x1000 * screen)) = bright + mode;
}
/*-------------------------------------------------------------------------
arm9_errorOutput
Displays an error code on screen.
Written by Chishm
--------------------------------------------------------------------------*/
static void arm9_errorOutput (u32 code) {
int i, j, k;
u16 colour;
vu16 *const vram_a = (vu16*)VRAM_A;
REG_POWERCNT = (u16)(POWER_LCD | POWER_2D_A);
REG_DISPCNT = MODE_FB0;
VRAM_A_CR = VRAM_ENABLE;
// Clear display
for (i = 0; i < 256*192; i++)vram_a[i] = 0x0000;
// Draw boxes of colour, signifying error codes
if ((code >> 16) != 0) {
// high 16 bits
for (i = 0; i < 8; i++) { // Pair of bits to use
if (((code>>(30-2*i))&3) == 0) {
colour = 0x001F; // Red
} else if (((code>>(30-2*i))&3) == 1) {
colour = 0x03FF; // Yellow
} else if (((code>>(30-2*i))&3) == 2) {
colour = 0x03E0; // Green
} else {
colour = 0x7C00; // Blue
}
for (j = 71; j < 87; j++) { // Row
for (k = 32*i+8; k < 32*i+24; k++) { // Column
vram_a[j*256+k] = colour;
}
}
}
}
// Low 16 bits
for (i = 0; i < 8; i++) { // Pair of bits to use
if (((code>>(14-2*i))&3) == 0) {
colour = 0x001F; // Red
} else if (((code>>(14-2*i))&3) == 1) {
colour = 0x03FF; // Yellow
} else if (((code>>(14-2*i))&3) == 2) {
colour = 0x03E0; // Green
} else {
colour = 0x7C00; // Blue
}
for (j = 103; j < 119; j++) { // Row
for (k = 32*i+8; k < 32*i+24; k++) { // Column
vram_a[j*256+k] = colour;
}
}
}
}
/*static void arm9_errorOutput (u32 code) {
int i, j, k;
u16 colour;
REG_POWERCNT = (u16)(POWER_LCD | POWER_2D_A);
REG_DISPCNT = MODE_FB0;
VRAM_A_CR = VRAM_ENABLE;
// Clear display
for (i = 0; i < 256*192; i++) { VRAM_A[i] = 0xFFFF; }
// Draw boxes of colour, signifying error codes
if ((code >> 16) != 0) {
// high 16 bits
for (i = 0; i < 8; i++) { // Pair of bits to use
if (((code>>(30-2*i))&3) == 0) {
colour = 0x001F; // Red
} else if (((code>>(30-2*i))&3) == 1) {
colour = 0x03FF; // Yellow
} else if (((code>>(30-2*i))&3) == 2) {
colour = 0x03E0; // Green
} else {
colour = 0x7C00; // Blue
}
for (j = 71; j < 87; j++) { // Row
for (k = 32*i+8; k < 32*i+24; k++) { // Column
VRAM_A[j*256+k] = colour;
}
}
}
}
if ((code >> 8) != 0) {
// Low 16 bits
for (i = 0; i < 8; i++) { // Pair of bits to use
if (((code>>(14-2*i))&3) == 0) {
colour = 0x001F; // Red
} else if (((code>>(14-2*i))&3) == 1) {
colour = 0x03FF; // Yellow
} else if (((code>>(14-2*i))&3) == 2) {
colour = 0x03E0; // Green
} else {
colour = 0x7C00; // Blue
}
for (j = 103; j < 119; j++) { // Row
for (k = 32*i+8; k < 32*i+24; k++) { // Column
VRAM_A[j*256+k] = colour;
}
}
}
} else {
// Low 8 bits
for (i = 0; i < 4; i++) { // Pair of bits to use
if (((code>>(6-2*i))&3) == 0) {
colour = 0x001F; // Red
} else if (((code>>(6-2*i))&3) == 1) {
colour = 0x03FF; // Yellow
} else if (((code>>(6-2*i))&3) == 2) {
colour = 0x03E0; // Green
} else {
colour = 0x7C00; // Blue
}
for (j = 87; j < 103; j++) { // Row
for (k = 32*i+72; k < 32*i+88; k++) { // Column
VRAM_A[j*256+k] = colour;
}
}
}
}
}*/
/*-------------------------------------------------------------------------
arm9_main
Clears the ARM9's icahce and dcache
Clears the ARM9's DMA channels and resets video memory
Jumps to the ARM9 NDS binary in sync with the display and ARM7
Written by Darkain, modified by Chishm
--------------------------------------------------------------------------*/
void __attribute__((target("arm"))) arm9_main (void) {
// MBK settings for NTR mode games
REG_MBK6=0x00003000;
REG_MBK7=0x00003000;
REG_MBK8=0x00003000;
REG_MBK9=0xFCFFFF0F;
register int i;
//set shared ram to ARM7
WRAM_CR = 0x03;
REG_EXMEMCNT = 0xE880;
arm9_stateFlag = ARM9_START;
REG_IME = 0;
REG_IE = 0;
REG_IF = ~0;
arm9_clearCache();
for (i=0; i<16*1024; i+=4) { //first 16KB
(*(vu32*)(i+0x00000000)) = 0x00000000; //clear ITCM
(*(vu32*)(i+0x00800000)) = 0x00000000; //clear DTCM
}
for (i=16*1024; i<32*1024; i+=4) { //second 16KB
(*(vu32*)(i+0x00000000)) = 0x00000000; //clear ITCM
}
arm9_stateFlag = ARM9_MEMCLR;
(*(vu32*)0x00803FFC) = 0; //IRQ_HANDLER ARM9 version
(*(vu32*)0x00803FF8) = ~0; //VBLANK_INTR_WAIT_FLAGS ARM9 version
//clear out ARM9 DMA channels
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;
}
// Clear out FIFO
REG_IPC_SYNC = 0;
REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR;
REG_IPC_FIFO_CR = 0;
VRAM_A_CR = 0x80;
VRAM_B_CR = 0x80;
VRAM_C_CR = 0x80;
// Don't mess with the VRAM used for execution
// VRAM_D_CR = 0x80;
VRAM_E_CR = 0x80;
VRAM_F_CR = 0x80;
VRAM_G_CR = 0x80;
VRAM_H_CR = 0x80;
VRAM_I_CR = 0x80;
BG_PALETTE[0] = 0xFFFF;
dmaFill((u16*)&arm9_BLANK_RAM, BG_PALETTE+1, (2*1024)-2);
dmaFill((u16*)&arm9_BLANK_RAM, OAM, 2*1024);
dmaFill((u16*)&arm9_BLANK_RAM, (u16*)0x04000000, 0x56); // Clear main display registers
dmaFill((u16*)&arm9_BLANK_RAM, (u16*)0x04001000, 0x56); // Clear sub display registers
dmaFill((u16*)&arm9_BLANK_RAM, VRAM_A, 0x20000*3); // Banks A, B, C
dmaFill((u16*)&arm9_BLANK_RAM, VRAM_D, 272*1024); // Banks D (excluded), E, F, G, H, I
REG_DISPSTAT = 0;
//videoSetMode(0);
//videoSetModeSub(0);
VRAM_A_CR = 0;
VRAM_B_CR = 0;
VRAM_C_CR = 0;
// Don't mess with the ARM7's VRAM
//VRAM_D_CR = 0;
VRAM_E_CR = 0;
VRAM_F_CR = 0;
VRAM_G_CR = 0;
VRAM_H_CR = 0;
VRAM_I_CR = 0;
REG_POWERCNT = 0x820F;
*(u16*)0x0400006C |= BIT(14);
*(u16*)0x0400006C &= BIT(15);
SetBrightness(0, 0);
SetBrightness(1, 0);
// set ARM9 state to ready and wait for it to change again
arm9_stateFlag = ARM9_READY;
while (arm9_stateFlag != ARM9_BOOTBIN) {
if (arm9_stateFlag == ARM9_DISPERR) {
// Re-enable for debugging
arm9_errorOutput(arm9_errorCode);
if (arm9_stateFlag == ARM9_DISPERR) { arm9_stateFlag = ARM9_READY; }
}
if (arm9_stateFlag == ARM9_SETSCFG) { arm9_stateFlag = ARM9_READY; }
}
VoidFn arm9code = (VoidFn)ndsHeader->arm9executeAddress;
while(REG_VCOUNT!=191);
while(REG_VCOUNT==191);
if ((REG_SCFG_EXT & BIT(31))) {
REG_SCFG_EXT = 0x8200E000;
REG_SCFG_CLK = 0x81;
}
// wait for vblank then boot
while(REG_VCOUNT!=191);
while(REG_VCOUNT==191);
arm9code();
}

View File

@ -0,0 +1,23 @@
#ifndef MODULE_PARAMS_H
#define MODULE_PARAMS_H
#include <nds/ndstypes.h>
typedef struct {
u32 auto_load_list_offset;
u32 auto_load_list_end;
u32 auto_load_start;
u32 static_bss_start;
u32 static_bss_end;
u32 compressed_static_end;
u32 sdk_version;
u32 nitro_code_be;
u32 nitro_code_le;
} module_params_t;
inline bool isSdk5(const module_params_t* moduleParams) {
return (moduleParams->sdk_version > 0x5000000);
}
#endif // MODULE_PARAMS_H

View File

@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------------
memory.h -- Declaration of memory regions
Copyright (C) 2005 Michael Noland (joat) and Jason Rogers (dovoto)
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.
---------------------------------------------------------------------------------*/
/*! \file ndsheaderbanner.h
\brief Defines the Nintendo DS file header and icon/title structs.
*/
#ifndef NDS_HEADER2
#define NDS_HEADER2
#include <nds.h>
/*!
\brief the NDS file header format
See gbatek for more info.
*/
typedef struct {
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[0x40];
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;
u8 dsi2[0x10];
u32 dsi_tid;
u32 dsi_tid2;
u32 pubSavSize;
u32 prvSavSize;
u8 dsi3[0x174];
} sNDSHeaderExt;
//#define __NDSHeader ((tNDSHeader *)0x02FFFE00)
// Make sure the header size is correct.
//static_assert(sizeof(sNDSHeaderExt) == 0x3B4, "sizeof(sNDSHeaderExt) is not 0x3B4 bytes");
#endif // NDS_HEADER2

View File

@ -0,0 +1,48 @@
/*
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 PATCH_H
#define PATCH_H
//#include <stddef.h>
#include <nds/ndstypes.h>
#include <nds/memory.h> // tNDSHeader
#define PAGE_4K (0b01011 << 1)
#define PAGE_8K (0b01100 << 1)
#define PAGE_16K (0b01101 << 1)
#define PAGE_32K (0b01110 << 1)
#define PAGE_64K (0b01111 << 1)
#define PAGE_128K (0b10000 << 1)
#define PAGE_256K (0b10001 << 1)
#define PAGE_512K (0b10010 << 1)
#define PAGE_1M (0b10011 << 1)
#define PAGE_2M (0b10100 << 1)
#define PAGE_4M (0b10101 << 1)
#define PAGE_8M (0b10110 << 1)
#define PAGE_16M (0b10111 << 1)
#define PAGE_32M (0b11000 << 1)
#define PAGE_64M (0b11001 << 1)
#define PAGE_128M (0b11010 << 1)
#define PAGE_256M (0b11011 << 1)
#define PAGE_512M (0b11100 << 1)
#define PAGE_1G (0b11101 << 1)
#define PAGE_2G (0b11110 << 1)
#define PAGE_4G (0b11111 << 1)
#endif // PATCH_H

View File

@ -0,0 +1,94 @@
#include <string.h>
#include <nds/system.h>
#include "module_params.h"
#include "patch.h"
#include "find.h"
#include "common.h"
//#define memcpy __builtin_memcpy // memcpy
void patchMpu(const tNDSHeader* ndsHeader, const module_params_t* moduleParams) {
u32 patchMpuRegion = 0;
u32 patchMpuSize = 0;
// Find the mpu init
u32* mpuStartOffset = findMpuStartOffset(ndsHeader, patchMpuRegion);
u32* mpuDataOffset = findMpuDataOffset(moduleParams, patchMpuRegion, mpuStartOffset);
if (mpuDataOffset) {
// Change the region 1 configuration
u32 mpuInitRegionNewData = PAGE_32M | 0x02000000 | 1;
u32 mpuNewDataAccess = 0;
u32 mpuNewInstrAccess = 0;
int mpuAccessOffset = 0;
switch (patchMpuRegion) {
case 0:
mpuInitRegionNewData = PAGE_128M | 0x00000000 | 1;
break;
case 2:
mpuNewDataAccess = 0x15111111;
mpuNewInstrAccess = 0x5111111;
mpuAccessOffset = 6;
break;
case 3:
mpuInitRegionNewData = PAGE_8M | 0x03000000 | 1;
mpuNewInstrAccess = 0x5111111;
mpuAccessOffset = 5;
break;
}
*mpuDataOffset = mpuInitRegionNewData;
if (mpuAccessOffset) {
if (mpuNewInstrAccess) {
mpuDataOffset[mpuAccessOffset] = mpuNewInstrAccess;
}
if (mpuNewDataAccess) {
mpuDataOffset[mpuAccessOffset + 1] = mpuNewDataAccess;
}
}
}
// Find the mpu cache init
u32* mpuInitCacheOffset = findMpuInitCacheOffset(mpuStartOffset);
if (mpuInitCacheOffset) {
*mpuInitCacheOffset = 0xE3A00046;
}
// Patch out all further mpu reconfiguration
// dbg_printf("patchMpuSize: ");
// dbg_hexa(patchMpuSize);
// dbg_printf("\n\n");
const u32* mpuInitRegionSignature = getMpuInitRegionSignature(patchMpuRegion);
u32* mpuInitOffset = mpuStartOffset;
while (mpuInitOffset && patchMpuSize) {
u32 patchSize = ndsHeader->arm9binarySize;
if (patchMpuSize > 1) {
patchSize = patchMpuSize;
}
mpuInitOffset = findOffset(
//(u32*)((u32)mpuStartOffset + 4), patchSize,
mpuInitOffset + 1, patchSize,
mpuInitRegionSignature, 1
);
if (mpuInitOffset) {
// dbg_printf("Mpu init: ");
// dbg_hexa((u32)mpuInitOffset);
// dbg_printf("\n\n");
*mpuInitOffset = 0xE1A00000; // nop
// Try to find it
/*for (int i = 0; i < 0x100; i++) {
mpuDataOffset += i;
if ((*mpuDataOffset & 0xFFFFFF00) == 0x02000000) {
*mpuDataOffset = PAGE_32M | 0x02000000 | 1;
break;
}
if (i == 100) {
*mpuStartOffset = 0xE1A00000;
}
}*/
}
}
}

View File

@ -0,0 +1,20 @@
/*
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

@ -0,0 +1,54 @@
#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

@ -0,0 +1,427 @@
/*
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 "read_card.h"
#include <nds.h>
#include <nds/arm9/cache.h>
#include <nds/dma.h>
#include <nds/card.h>
#include <string.h>
#include "tonccpy.h"
#include "encryption.h"
#include "common.h"
typedef union {
char title[4];
u32 key;
} GameCode;
static bool twlBlowfish = false;
static bool normalChip = false; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000
static u32 portFlags = 0;
static u32 headerData[0x1000/sizeof(u32)] = {0};
static u32 secureArea[CARD_SECURE_AREA_SIZE/sizeof(u32)];
static const u8 cardSeedBytes[] = {0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5};
static u32 getRandomNumber(void) {
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
static void decryptSecureArea (u32 gameCode, u32* secureArea, int iCardDevice) {
init_keycode (gameCode, 2, 8, iCardDevice);
crypt_64bit_down (secureArea);
init_keycode (gameCode, 3, 8, iCardDevice);
for (int i = 0; i < 0x200; i+= 2) { crypt_64bit_down (secureArea + i); }
}
static struct {
unsigned int iii;
unsigned int jjj;
unsigned int kkkkk;
unsigned int llll;
unsigned int mmm;
unsigned int nnn;
} key1data;
static void initKey1Encryption (u8* cmdData, int iCardDevice) {
key1data.iii = getRandomNumber() & 0x00000fff;
key1data.jjj = getRandomNumber() & 0x00000fff;
key1data.kkkkk = getRandomNumber() & 0x000fffff;
key1data.llll = getRandomNumber() & 0x0000ffff;
key1data.mmm = getRandomNumber() & 0x00000fff;
key1data.nnn = getRandomNumber() & 0x00000fff;
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;
cmdData[3] = (u8) (key1data.kkkkk >> 16);
cmdData[2] = (u8) (key1data.kkkkk >> 8);
cmdData[1] = (u8) key1data.kkkkk;
cmdData[0] = (u8) getRandomNumber();
}
// Note: cmdData must be aligned on a word boundary
static void createEncryptedCommand (u8 command, u8* cmdData, u32 block) {
unsigned long iii, jjj;
if (command != CARD_CMD_SECURE_READ) { block = key1data.llll; }
if (command == CARD_CMD_ACTIVATE_SEC) {
iii = key1data.mmm;
jjj = key1data.nnn;
} else {
iii = key1data.iii;
jjj = key1data.jjj;
}
cmdData[7] = (u8) (command | (block >> 12));
cmdData[6] = (u8) (block >> 4);
cmdData[5] = (u8) ((block << 4) | (iii >> 8));
cmdData[4] = (u8) iii;
cmdData[3] = (u8) (jjj >> 4);
cmdData[2] = (u8) ((jjj << 4) | (key1data.kkkkk >> 16));
cmdData[1] = (u8) (key1data.kkkkk >> 8);
cmdData[0] = (u8) key1data.kkkkk;
crypt_64bit_up ((u32*)cmdData);
key1data.kkkkk += 1;
}
static void cardDelay (u16 readTimeout) {
/* Using a while loop to check the timeout,
so we have to wait until one before overflow.
This also requires an extra 1 for the timer data.
See GBATek for the normal formula used for card timeout.
*/
TIMER_DATA(0) = 0 - (((readTimeout & 0x3FFF) + 3));
TIMER_CR(0) = TIMER_DIV_256 | TIMER_ENABLE;
while (TIMER_DATA(0) != 0xFFFF);
// Clear out the timer registers
TIMER_CR(0) = 0;
TIMER_DATA(0) = 0;
}
static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) {
if (twlBlowfish || ndsHeader->unitCode == 0) return;
// Used for dumping the DSi arm9i/7i binaries
u32 portFlagsKey1, portFlagsSecRead;
int secureBlockNumber;
int i;
u8 cmdData[8] __attribute__ ((aligned));
GameCode* gameCode;
// Reset card slot
disableSlot1();
for(int i = 0; i < 25; i++) {
while(REG_VCOUNT!=191);
while(REG_VCOUNT==191);
}
enableSlot1();
for(int i = 0; i < 15; i++) {
while(REG_VCOUNT!=191);
while(REG_VCOUNT==191);
}
// 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) { 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) {
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) {
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) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
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);
secureAreaOffset += 0x1000/sizeof(u32);
}
}
// Alllliii jjjkkkkk - Enter Main Data Mode
createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0);
if (normalChip) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
// The 0x800 bytes are modcrypted, so this function isn't ran
//decryptSecureArea (gameCode->key, secureArea, 1);
twlBlowfish = true;
}
int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) {
u32 portFlagsKey1, portFlagsSecRead;
normalChip = false; // 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;
// 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);
// 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));
tonccpy(ndsHeader, headerData, 0x200);
if ((ndsHeader->unitCode != 0) || (ndsHeader->dsi_flags != 0)) {
// Extended header found
cardParamCommand (CARD_CMD_HEADER_READ, 0,
CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(4) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
(void*)headerData, 0x1000/sizeof(u32));
if (ndsHeader->dsi1[0]==0xFFFFFFFF && ndsHeader->dsi1[1]==0xFFFFFFFF
&& ndsHeader->dsi1[2]==0xFFFFFFFF && ndsHeader->dsi1[3]==0xFFFFFFFF)
{
toncset((u8*)headerData+0x200, 0, 0xE00); // Clear out FFs
}
tonccpy(ndsHeader, headerData, 0x1000);
}
// 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;
}
*/
// 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);
// 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));
// 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; }
// 3Ciiijjj xkkkkkxx - Activate KEY1 Encryption Mode
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) {
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) {
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;
u32* secureAreaOffset = secureArea;
for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) {
createEncryptedCommand (CARD_CMD_SECURE_READ, cmdData, secureBlockNumber);
if (normalChip) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(1), secureAreaOffset, 0x200, cmdData);
secureAreaOffset += 0x200/sizeof(u32);
}
} else {
cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(4) | CARD_SEC_LARGE, secureAreaOffset, 0x1000, cmdData);
secureAreaOffset += 0x1000/sizeof(u32);
}
}
// Alllliii jjjkkkkk - Enter Main Data Mode
createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0);
if (normalChip) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
//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'*/) {
// 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[i] = 0xe7ffdeff; }
// Disabled error checks on secure area. This was able to boot a DS-Xtreme. May increase flashcart compatiblity drastically.
// return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR;
}
return ERR_NONE;
}
void cardRead (u32 src, u32* dest, size_t size) {
sNDSHeaderExt* ndsHeader = (sNDSHeaderExt*)headerData;
size_t readSize;
if (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;
tonccpy (dest, (u8*)secureArea + src - CARD_SECURE_AREA_OFFSET, readSize);
src += readSize;
dest += readSize/sizeof(*dest);
size -= readSize;
} else if ((ndsHeader->unitCode != 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*)secureArea + src - ndsHeader->arm9iromOffset, readSize);
src += readSize;
dest += readSize/sizeof(*dest);
size -= readSize;
}
while (size > 0) {
readSize = size < CARD_DATA_BLOCK_SIZE ? size : CARD_DATA_BLOCK_SIZE;
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;
}
}

View File

@ -0,0 +1,39 @@
/*
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 READ_CARD_H
#define READ_CARD_H
#include <nds/ndstypes.h>
#include <nds/memory.h>
#include <stdlib.h>
#include "ndsheaderbanner.h"
#define CARD_NDS_HEADER_SIZE (0x200)
#define CARD_SECURE_AREA_OFFSET (0x4000)
#define CARD_SECURE_AREA_SIZE (0x4000)
#define CARD_DATA_OFFSET (0x8000)
#define CARD_DATA_BLOCK_SIZE (0x200)
int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID);
void cardRead (u32 src, u32* dest, size_t size);
#endif // READ_CARD_H

View File

@ -0,0 +1,124 @@
#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!
switch(tmp) {
do { *dst32++ = *src32++;
case 3: *dst32++ = *src32++;
case 2: *dst32++ = *src32++;
case 1: *dst32++ = *src32++;
case 0: ; } while(count--);
}
// 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;
switch(tmp) {
do { *dst32++ = fill;
case 3: *dst32++ = fill;
case 2: *dst32++ = fill;
case 1: *dst32++ = fill;
case 0: ; } while(count--);
}
// Tail
size &= 3;
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(u8 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

152
LICENSE
View File

@ -1,23 +1,21 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
@ -72,7 +60,7 @@ modification follow.
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
@ -618,4 +616,46 @@ an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

View File

@ -11,16 +11,16 @@ export TARGET := NitroHax
export TOPDIR := $(CURDIR)
export VERSION_MAJOR := 0
export VERSION_MINOR := 94
export VERSION_MINOR := 95
export VERSTRING := $(VERSION_MAJOR).$(VERSION_MINOR)
.PHONY: checkarm7 checkarm9
.PHONY: dsi checkarm7 checkarm9
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all: $(TARGET).nds checkarm7 checkarm9
all: $(TARGET).nds $(TARGET).dsi checkarm7 checkarm9
#---------------------------------------------------------------------------------
checkarm7:
@ -34,16 +34,31 @@ $(TARGET).nds : arm7/$(TARGET).elf arm9/$(TARGET).elf
ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \
-b $(CURDIR)/icon.bmp "Nitro Hax;DS Game Cheat Tool;Created by Chishm"
$(TARGET).dsi : arm7/$(TARGET).elf arm9/$(TARGET).elf
ndstool -c $(TARGET).dsi -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \
-b $(CURDIR)/icon.bmp "Nitro Hax for DSi;DS Game Cheat Tool;Created by Chishm" \
-g CHTE 01 "NITROHAXTWL" -z 80040000 -u 00030004 -a 00000038 -p 0000
#---------------------------------------------------------------------------------
# Create boot loader and link raw binary into ARM9 ELF
#---------------------------------------------------------------------------------
BootLoader/load.bin : BootLoader/source/*
$(MAKE) -C BootLoader
BootLoaderTWL/loadtwl.bin : BootLoaderTWL/source/*
$(MAKE) -C BootLoaderTWL
arm9/data/load.bin : BootLoader/load.bin
mkdir -p $(@D)
cp $< $@
arm9/data/loadtwl.bin : BootLoaderTWL/loadtwl.bin
mkdir -p $(@D)
cp $< $@
#---------------------------------------------------------------------------------
arm9/source/version.h : Makefile
@echo "#ifndef VERSION_H" > $@
@ -58,11 +73,11 @@ arm7/$(TARGET).elf:
$(MAKE) -C arm7
#---------------------------------------------------------------------------------
arm9/$(TARGET).elf : arm9/data/load.bin arm9/source/version.h
arm9/$(TARGET).elf : arm9/data/load.bin arm9/data/loadtwl.bin arm9/source/version.h
$(MAKE) -C arm9
#---------------------------------------------------------------------------------
dist-bin : $(TARGET).nds README.md LICENSE
dist-bin : $(TARGET).nds $(TARGET).dsi README.md LICENSE
zip -X -9 $(TARGET)_v$(VERSTRING).zip $^
dist-src :
@ -71,7 +86,8 @@ dist-src :
Makefile icon.bmp LICENSE README.md \
arm7/Makefile arm7/source \
arm9/Makefile arm9/source arm9/graphics \
BootLoader/Makefile BootLoader/load.ld BootLoader/source
BootLoader/Makefile BootLoader/load.ld BootLoader/source \
BootLoaderTWL/Makefile BootLoaderTWL/loadtwl.ld BootLoaderTWL/source
dist : dist-bin dist-src
@ -80,5 +96,7 @@ clean:
$(MAKE) -C arm9 clean
$(MAKE) -C arm7 clean
$(MAKE) -C BootLoader clean
$(MAKE) -C BootLoaderTWL clean
rm -f arm9/data/load.bin
rm -f $(TARGET).ds.gba $(TARGET).nds $(TARGET).arm7 $(TARGET).arm9
rm -f arm9/data/loadtwl.bin
rm -f $(TARGET).ds.gba $(TARGET).nds $(TARGET).dsi $(TARGET).arm7 $(TARGET).arm9

View File

@ -1,4 +1,4 @@
Nitro Hax
Nitro Hax (TWL Build by Apache Thunder)
=========
By Chishm
@ -13,6 +13,10 @@ The newest release is available to
Usage
=====
Note: For DSi users able to use Unlaunch to launch NitroHax from DSi SD, the step
of replacing the cart with the game during 5 and 6 are not required.
Cheats will be stored on DSi SD instead of flashcart.
1. Patch NitroHax.nds with a DLDI file if you need to.
2. Copy the NitroHax.nds file to your media device.
3. Place an Action Replay XML file on your media device.
@ -24,9 +28,10 @@ Usage
* "/data/NitroHax/cheats.xml"
* "/cheats.xml"
2. If no file is found, browse for and select a file to open.
5. Remove your media device if you want to.
6. Remove any card that is in Slot-1
5. Remove your media device if you want to. (Not applicable on DSi)
6. Remove any card that is in Slot-1 (Not applicable on DSi)
7. Insert the DS game into Slot-1
(Not applicable on DSi. Program will wait for user to insert game if booted up with slot empty)
8. Choose the cheats you want to enable.
1. Some cheats are enabled by default and others may be always on. This is
specified in the XML file.

View File

@ -22,13 +22,9 @@
#include "cheat_engine_arm7.h"
void VcountHandler() { inputGetAndSend(); }
void VcountHandler() {
inputGetAndSend();
}
void VblankHandler(void) {
}
void VblankHandler(void) { }
//---------------------------------------------------------------------------------
int main(void) {
@ -52,6 +48,11 @@ int main(void) {
irqEnable( IRQ_VBLANK | IRQ_VCOUNT);
if (REG_SNDEXTCNT != 0) {
i2cWriteRegister(0x4A, 0x12, 0x00); // Press power-button for auto-reset
i2cWriteRegister(0x4A, 0x70, 0x01); // Bootflag = Warmboot/SkipHealthSafety
}
// Keep the ARM7 mostly idle
while (1) {
runCheatEngineCheck();

View File

@ -28,7 +28,7 @@ ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork
CFLAGS := -g -Wall -O2\
-fomit-frame-pointer\
-ffast-math \
-Wall -Wextra -Werror \
-Wall -Wextra \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM9
@ -36,7 +36,7 @@ CXXFLAGS := $(CFLAGS)
ASFLAGS := -g $(ARCH) $(INCLUDE)
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LDFLAGS = -specs=dsi_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
@ -128,6 +128,12 @@ bgtop.s : ../$(IMAGES)/bgtop.bmp
bgsub.s : ../$(IMAGES)/bgsub.bmp
grit $< -gB4 -gzl -fts -o $@ -q
bgtopTWL.s : ../$(IMAGES)/bgtopTWL.bmp
grit $< -gB4 -gzl -fts -o $@ -q
bgsubTWL.s : ../$(IMAGES)/bgsubTWL.bmp
grit $< -gB4 -gzl -fts -o $@ -q
cursor.s : ../$(IMAGES)/cursor.bmp
grit $< -gB4 -fts -Mw8 -Mh4 -o $@ -q

BIN
arm9/graphics/bgsubTWL.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
arm9/graphics/bgtopTWL.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

View File

@ -20,10 +20,14 @@
#include <nds.h>
#include "load_bin.h"
#include "loadtwl_bin.h"
#include "cheat_engine.h"
#define LCDC_BANK_C (vu16*)0x06840000
#define LCDC_BANK_D (vu16*)0x06860000
#define CHEAT_DATA_LOCATION ((u32*)0x06850000)
#define CHEAT_DATA_LOCATIONTWL ((u32*)0x06870000)
#define CHEAT_CODE_END 0xCF000000
static void vramset (volatile void* dst, u16 val, int len)
@ -46,30 +50,56 @@ static void vramcpy (volatile void* dst, const void* src, int len)
}
}
void runCheatEngine (void* cheats, int cheatLength)
void runCheatEngine (void* cheats, int cheatLength, bool isTWLCart)
{
irqDisable(IRQ_ALL);
// Direct CPU access to VRAM bank C
VRAM_C_CR = VRAM_ENABLE | VRAM_C_LCD;
// Clear VRAM
vramset (LCDC_BANK_C, 0x0000, 128 * 1024);
// Load the loader/patcher into the correct address
vramcpy (LCDC_BANK_C, load_bin, load_bin_size);
// Put the codes 64KiB after the start of the loader
vramcpy (CHEAT_DATA_LOCATION, cheats, cheatLength);
// Mark the end of the code list
CHEAT_DATA_LOCATION[cheatLength/sizeof(u32)] = CHEAT_CODE_END;
CHEAT_DATA_LOCATION[cheatLength/sizeof(u32) + 1] = 0;
// Give the VRAM to the ARM7
VRAM_C_CR = VRAM_ENABLE | VRAM_C_ARM7_0x06000000;
// The original bootloader fails to boot TWL carts. Using an alternate for those for now.
// With new bootloader Arm9 SCFG settings occur there instead.
if (isTWLCart) {
VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD;
vramset (LCDC_BANK_D, 0x0000, 128 * 1024);
vramcpy (LCDC_BANK_D, loadtwl_bin, loadtwl_bin_size);
vramcpy (CHEAT_DATA_LOCATIONTWL, cheats, cheatLength);
CHEAT_DATA_LOCATIONTWL[cheatLength/sizeof(u32)] = CHEAT_CODE_END;
CHEAT_DATA_LOCATIONTWL[cheatLength/sizeof(u32) + 1] = 0;
VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000;
REG_EXMEMCNT = 0xffff;
*(vu32*)0x02FFFFFC = 0;
*(vu32*)0x02FFFE04 = (u32)0xE59FF018; // ldr pc, 0x02FFFE24
*(vu32*)0x02FFFE24 = (u32)0x02FFFE04; // Set ARM9 Loop address --> resetARM9(0x02FFFE04);
resetARM7(0x06020000);
} else {
// Direct CPU access to VRAM bank C
VRAM_C_CR = VRAM_ENABLE | VRAM_C_LCD;
// Clear VRAM
vramset (LCDC_BANK_C, 0x0000, 128 * 1024);
// Load the loader/patcher into the correct address
vramcpy (LCDC_BANK_C, load_bin, load_bin_size);
// Put the codes 64KiB after the start of the loader
vramcpy (CHEAT_DATA_LOCATION, cheats, cheatLength);
// Mark the end of the code list
CHEAT_DATA_LOCATION[cheatLength/sizeof(u32)] = CHEAT_CODE_END;
CHEAT_DATA_LOCATION[cheatLength/sizeof(u32) + 1] = 0;
// Reset into a passme loop
REG_EXMEMCNT = 0xffff;
*((vu32*)0x027FFFFC) = 0;
*((vu32*)0x027FFE04) = (u32)0xE59FF018;
*((vu32*)0x027FFE24) = (u32)0x027FFE04;
// Give the VRAM to the ARM7
VRAM_C_CR = VRAM_ENABLE | VRAM_C_ARM7_0x06000000;
// Set MBK and lock SCFG_EXT registers and if not a TWL enhanced cart. (must be locked later in bootloader if TWL cart)
// Set standard NTR configuration for SCFG and MBK registers. (MBK 1-5 set only on Arm7. Done in bootloader for now)
if (REG_SCFG_EXT & BIT(31)) {
REG_MBK6 = 0x00003000;
REG_MBK7 = 0x00003000;
REG_MBK8 = 0x00003000;
REG_SCFG_CLK = 0x80;
REG_SCFG_EXT = 0x03000000;
}
// Reset into a passme loop
REG_EXMEMCNT = 0xffff;
*((vu32*)0x027FFFFC) = 0;
*((vu32*)0x027FFE04) = (u32)0xE59FF018;
*((vu32*)0x027FFE24) = (u32)0x027FFE04;
}
swiSoftReset();
}

View File

@ -27,7 +27,7 @@ extern "C" {
#endif
void runCheatEngine (void* cheats, int cheatLength);
void runCheatEngine (void* cheats, int cheatLength, bool isTWLCart);
#ifdef __cplusplus

112
arm9/source/encryption.c Normal file
View File

@ -0,0 +1,112 @@
/*
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 <string.h>
#include "encryption.h"
#include "key1.h"
#include "key2.h"
#include "tonccpy.h"
#define KEYSIZE 0x1048
static u32 keycode [3];
static u32 keybuf [KEYSIZE/sizeof(u32)];
void crypt_64bit_up (u32* ptr) {
u32 x = ptr[1];
u32 y = ptr[0];
u32 z;
int i;
for (i = 0; i < 0x10; i++) {
z = keybuf[i] ^ x;
x = keybuf[0x012 + ((z>>24)&0xff)];
x = keybuf[0x112 + ((z>>16)&0xff)] + x;
x = keybuf[0x212 + ((z>> 8)&0xff)] ^ x;
x = keybuf[0x312 + ((z>> 0)&0xff)] + x;
x = y ^ x;
y = z;
}
ptr[0] = x ^ keybuf[0x10];
ptr[1] = y ^ keybuf[0x11];
}
void crypt_64bit_down (u32* ptr) {
u32 x = ptr[1];
u32 y = ptr[0];
u32 z;
int i;
for (i = 0x11; i > 0x01; i--) {
z = keybuf[i] ^ x;
x = keybuf[0x012 + ((z>>24)&0xff)];
x = keybuf[0x112 + ((z>>16)&0xff)] + x;
x = keybuf[0x212 + ((z>> 8)&0xff)] ^ x;
x = keybuf[0x312 + ((z>> 0)&0xff)] + x;
x = y ^ x;
y = z;
}
ptr[0] = x ^ keybuf[0x01];
ptr[1] = y ^ keybuf[0x00];
}
static u32 bswap_32bit (u32 in) {
u8 a,b,c,d;
a = (u8)((in >> 0) & 0xff);
b = (u8)((in >> 8) & 0xff);
c = (u8)((in >> 16) & 0xff);
d = (u8)((in >> 24) & 0xff);
u32 out = (a << 24) | (b << 16) | (c << 8) | (d << 0);
return out;
}
void apply_keycode (u32 modulo) {
u32 scratch[2];
int i;
modulo = modulo / sizeof(*keycode);
crypt_64bit_up (&keycode[1]);
crypt_64bit_up (&keycode[0]);
toncset (scratch, 0, 8);
for (i = 0; i < 0x12; i+=1) {
keybuf[i] = keybuf[i] ^ bswap_32bit (keycode[i % modulo]);
}
for (i = 0; i < 0x412; i+=2) {
crypt_64bit_up (scratch);
keybuf[i] = scratch[1];
keybuf[i+1] = scratch[0];
}
}
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;
if (level >= 1) apply_keycode (modulo); // first apply (always)
if (level >= 2) apply_keycode (modulo); // second apply (optional)
keycode[1] = keycode[1] * 2;
keycode[2] = keycode[2] / 2;
if (level >= 3) apply_keycode (modulo); // third apply (optional)
}

27
arm9/source/encryption.h Normal file
View File

@ -0,0 +1,27 @@
/*
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 ENCRYPTION_H
#define ENCRYPTION_H
#include <nds/ndstypes.h>
void init_keycode (u32 idcode, u32 level, u32 modulo, int iCardDevice);
void crypt_64bit_down (u32* ptr);
void crypt_64bit_up (u32* ptr);
#endif

264
arm9/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
arm9/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

@ -29,20 +29,49 @@
#include "cheat_engine.h"
#include "crc.h"
#include "version.h"
#include "read_card.h"
const char TITLE_STRING[] = "Nitro Hax " VERSION_STRING "\nWritten by Chishm";
const char* defaultFiles[] = {"cheats.xml", "/DS/NitroHax/cheats.xml", "/NitroHax/cheats.xml", "/data/NitroHax/cheats.xml", "/cheats.xml"};
const char* defaultFiles[] = {
"cheats.xml",
"/DS/NitroHax/cheats.xml",
"/NitroHax/cheats.xml",
"/NDS/NitroHax/cheats.xml",
"/data/NitroHax/cheats.xml",
"/_nds/NitroHax/cheats.xml",
"/cheats.xml"};
static bool ROMisDSiExclusive(const tNDSHeader* ndsHeader) { return (ndsHeader->unitCode == 0x03); }
static bool ROMisDSiEnhanced(const tNDSHeader* ndsHeader) { return (ndsHeader->unitCode == 0x02); }
static inline void ensure (bool condition, const char* errorMsg) {
if (false == condition) {
if (!condition) {
ui.showMessage (errorMsg);
while(1) swiWaitForVBlank();
while(1)swiWaitForVBlank();
}
return;
}
void DoWait(int waitTime = 30){
for (int i = 0; i < waitTime; i++) swiWaitForVBlank();
};
void ResetSlot1() {
if (REG_SCFG_MC == 0x11) return;
disableSlot1();
DoWait();
enableSlot1();
}
void DoCartCheck() {
if (REG_SCFG_MC == 0x11) {
do { swiWaitForVBlank(); } while (REG_SCFG_MC != 0x10);
enableSlot1();
DoWait(60);
}
}
//---------------------------------------------------------------------------------
int main(int argc, const char* argv[])
{
@ -57,7 +86,8 @@ int main(int argc, const char* argv[])
std::string filename;
int c;
FILE* cheatFile;
bool isTWLCart = false;
ui.showMessage (UserInterface::TEXT_TITLE, TITLE_STRING);
#ifdef DEMO
@ -68,15 +98,16 @@ int main(int argc, const char* argv[])
ensure (fatInitDefault(), "FAT init failed");
// Read cheat file
for (u32 i = 0; i < sizeof(defaultFiles)/sizeof(const char*); i++) {
cheatFile = fopen (defaultFiles[i], "rb");
if (NULL != cheatFile) break;
for (const char* FileName : defaultFiles) {
cheatFile = fopen(FileName, "rb");
if (cheatFile)break;
}
if (NULL == cheatFile) {
if (!cheatFile) {
filename = ui.fileBrowser (".xml");
ensure (filename.size() > 0, "No file specified");
cheatFile = fopen (filename.c_str(), "rb");
ensure (cheatFile != NULL, "Couldn't load cheats");
ensure (cheatFile, "Couldn't load cheats");
}
ui.showMessage (UserInterface::TEXT_TITLE, TITLE_STRING);
@ -93,24 +124,29 @@ int main(int argc, const char* argv[])
ui.showMessage (UserInterface::TEXT_TITLE, TITLE_STRING);
sysSetCardOwner (BUS_OWNER_ARM9);
ui.showMessage ("Loaded codes\nYou can remove your flash card\nRemove DS Card");
do {
swiWaitForVBlank();
getHeader (ndsHeader);
} while (ndsHeader[0] != 0xffffffff);
ui.showMessage ("Insert Game");
do {
swiWaitForVBlank();
getHeader (ndsHeader);
} while (ndsHeader[0] == 0xffffffff);
// Delay half a second for the DS card to stabilise
for (int i = 0; i < 30; i++) {
swiWaitForVBlank();
// Check if on DSi with unlocked SCFG, if not, then assume standard NTR precedure.
if ((REG_SCFG_EXT & BIT(31))) {
ui.showMessage ("Loaded codes\nChecking if a cart is inserted");
if (REG_SCFG_MC != 0x18)ui.showMessage ("Insert Game");
while (REG_SCFG_MC != 0x18)DoCartCheck();
CardInit();
} else {
ui.showMessage ("Loaded codes\nYou can remove your flash card\nRemove DS Card");
do {
swiWaitForVBlank();
getHeader (ndsHeader);
} while (ndsHeader[0] != 0xffffffff);
ui.showMessage ("Insert Game");
do {
swiWaitForVBlank();
getHeader (ndsHeader);
} while (ndsHeader[0] == 0xffffffff);
}
// Delay half a second for the DS card to stabilise
DoWait();
getHeader (ndsHeader);
ui.showMessage ("Finding game");
@ -119,13 +155,14 @@ int main(int argc, const char* argv[])
headerCRC = crc32((const char*)ndsHeader, sizeof(ndsHeader));
CheatFolder *gameCodes = codelist->getGame (gameid, headerCRC);
if (!gameCodes) {
gameCodes = codelist;
}
if (!gameCodes)gameCodes = codelist;
ensure(!ROMisDSiExclusive((const tNDSHeader*)ndsHeader), "TWL exclusive games are not supported!");
isTWLCart = ROMisDSiEnhanced((const tNDSHeader*)ndsHeader);
ui.cheatMenu (gameCodes, gameCodes);
cheatDest = (u32*) malloc(CHEAT_MAX_DATA_SIZE);
ensure (cheatDest != NULL, "Bad malloc\n");
@ -138,11 +175,10 @@ int main(int argc, const char* argv[])
ui.showMessage (UserInterface::TEXT_TITLE, TITLE_STRING);
ui.showMessage ("Running game");
runCheatEngine (cheatDest, curCheat * sizeof(u32));
runCheatEngine (cheatDest, curCheat * sizeof(u32), isTWLCart);
while(1) {
}
while(1)swiWaitForVBlank();
return 0;
}

View File

@ -21,12 +21,7 @@
#include "nds_card.h"
void getHeader (u32* ndsHeader) {
cardParamCommand (CARD_CMD_DUMMY, 0,
CARD_ACTIVATE | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
NULL, 0);
cardParamCommand(CARD_CMD_HEADER_READ, 0,
CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
ndsHeader, 512);
cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0);
cardParamCommand(CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), ndsHeader, 512);
}

View File

@ -0,0 +1,141 @@
/*---------------------------------------------------------------------------------
memory.h -- Declaration of memory regions
Copyright (C) 2005 Michael Noland (joat) and Jason Rogers (dovoto)
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.
---------------------------------------------------------------------------------*/
/*! \file ndsheaderbanner.h
\brief Defines the Nintendo DS file header and icon/title structs.
*/
#ifndef NDS_HEADER2
#define NDS_HEADER2
#include <nds.h>
/*!
\brief the NDS file header format
See gbatek for more info.
*/
typedef struct {
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[3];
u16 nandRomEnd; //!< ROM region end for NAND games.
u16 nandRwStart; //!< RW region start for NAND games.
u32 zeros98[10];
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[0x40];
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;
u8 dsi2[0x10];
u32 dsi_tid;
u32 dsi_tid2;
u32 pubSavSize;
u32 prvSavSize;
u8 dsi3[0x174];
} sNDSHeaderExt;
//#define __NDSHeader ((tNDSHeader *)0x02FFFE00)
// Make sure the header size is correct.
//static_assert(sizeof(sNDSHeaderExt) == 0x3B4, "sizeof(sNDSHeaderExt) is not 0x3B4 bytes");
#endif // NDS_HEADER2

785
arm9/source/read_card.c Normal file
View File

@ -0,0 +1,785 @@
/*
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 "read_card.h"
#include <nds.h>
#include <nds/arm9/cache.h>
#include <nds/dma.h>
#include <nds/card.h>
#include <string.h>
#include "encryption.h"
#include "tonccpy.h"
enum {
ERR_NONE = 0x00,
ERR_STS_CLR_MEM = 0x01,
ERR_STS_LOAD_BIN = 0x02,
ERR_STS_HOOK_BIN = 0x03,
ERR_STS_START = 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,
} ERROR_CODES;
// NAND Card commands
// https://problemkaputt.de/gbatek-ds-cartridge-nand.htm
#define CARD_CMD_NAND_WRITE_BUFFER 0x81
#define CARD_CMD_NAND_COMMIT_BUFFER 0x82
#define CARD_CMD_NAND_DISCARD_BUFFER 0x84
#define CARD_CMD_NAND_WRITE_ENABLE 0x85
#define CARD_CMD_NAND_ROM_MODE 0x8B
#define CARD_CMD_NAND_RW_MODE 0xB2
#define CARD_CMD_NAND_READ_STATUS 0xD6
#define CARD_CMD_NAND_UNKNOWN 0xBB
#define CARD_CMD_NAND_READ_ID 0x94
typedef union
{
char title[4];
u32 key;
} GameCode;
static bool twlBlowfish = false;
static bool normalChip = false; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000
static u32 portFlags = 0;
static u32 headerData[0x1000/sizeof(u32)] = {0};
static u32 secureArea[CARD_SECURE_AREA_SIZE/sizeof(u32)] = {0};
static u32 iCardId;
static bool nandChip = false;
static int nandSection = -1; // -1 = ROM, above that is the current 128 KiB section in RW
u32 cardNandRomEnd = 0;
u32 cardNandRwStart = 0;
static const u8 cardSeedBytes[] = {0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5};
static u32 getRandomNumber(void) {
return rand();
}
//---------------------------------------------------------------------------------
// https://github.com/devkitPro/libnds/blob/105d4943dbac8f2bd99a47b22cd3ed48f96af083/source/common/card.c#L47-L62
// but modified to write if CARD_WR is set.
static void cardPolledTransferWrite(u32 flags, u32 *buffer, u32 length, const u8 *command) {
//---------------------------------------------------------------------------------
cardWriteCommand(command);
REG_ROMCTRL = flags | CARD_BUSY;
u32 * target = buffer + length;
do {
// Read/write data if available
if (REG_ROMCTRL & CARD_DATA_READY) {
if (flags & CARD_WR) { // Write
if (NULL != buffer && buffer < target)
REG_CARD_DATA_RD = *buffer++;
else
REG_CARD_DATA_RD = 0;
} else { // Read
u32 data = REG_CARD_DATA_RD;
if (NULL != buffer && buffer < target)
*buffer++ = REG_CARD_DATA_RD;
else
(void)data;
}
}
} while (REG_ROMCTRL & CARD_BUSY);
}
static void decryptSecureArea (u32 gameCode, u32* secureArea, int iCardDevice)
{
init_keycode (gameCode, 2, 8, iCardDevice);
crypt_64bit_down (secureArea);
init_keycode (gameCode, 3, 8, iCardDevice);
for (int i = 0; i < 0x200; i+= 2) {
crypt_64bit_down (secureArea + i);
}
}
static struct {
unsigned int iii;
unsigned int jjj;
unsigned int kkkkk;
unsigned int llll;
unsigned int mmm;
unsigned int nnn;
} key1data;
static void initKey1Encryption (u8* cmdData, int iCardDevice) {
key1data.iii = getRandomNumber() & 0x00000fff;
key1data.jjj = getRandomNumber() & 0x00000fff;
key1data.kkkkk = getRandomNumber() & 0x000fffff;
key1data.llll = getRandomNumber() & 0x0000ffff;
key1data.mmm = getRandomNumber() & 0x00000fff;
key1data.nnn = getRandomNumber() & 0x00000fff;
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;
cmdData[3] = (u8) (key1data.kkkkk >> 16);
cmdData[2] = (u8) (key1data.kkkkk >> 8);
cmdData[1] = (u8) key1data.kkkkk;
cmdData[0] = (u8) getRandomNumber();
}
// Note: cmdData must be aligned on a word boundary
static void createEncryptedCommand (u8 command, u8* cmdData, u32 block)
{
unsigned long iii, jjj;
if (command != CARD_CMD_SECURE_READ) {
block = key1data.llll;
}
if (command == CARD_CMD_ACTIVATE_SEC) {
iii = key1data.mmm;
jjj = key1data.nnn;
} else {
iii = key1data.iii;
jjj = key1data.jjj;
}
cmdData[7] = (u8) (command | (block >> 12));
cmdData[6] = (u8) (block >> 4);
cmdData[5] = (u8) ((block << 4) | (iii >> 8));
cmdData[4] = (u8) iii;
cmdData[3] = (u8) (jjj >> 4);
cmdData[2] = (u8) ((jjj << 4) | (key1data.kkkkk >> 16));
cmdData[1] = (u8) (key1data.kkkkk >> 8);
cmdData[0] = (u8) key1data.kkkkk;
crypt_64bit_up ((u32*)cmdData);
key1data.kkkkk += 1;
}
static void cardDelay (u16 readTimeout) {
/* Using a while loop to check the timeout,
so we have to wait until one before overflow.
This also requires an extra 1 for the timer data.
See GBATek for the normal formula used for card timeout.
*/
TIMER_DATA(0) = 0 - (((readTimeout & 0x3FFF) + 3));
TIMER_CR(0) = TIMER_DIV_256 | TIMER_ENABLE;
while (TIMER_DATA(0) != 0xFFFF);
// Clear out the timer registers
TIMER_CR(0) = 0;
TIMER_DATA(0) = 0;
}
static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) {
if (twlBlowfish || ndsHeader->unitCode == 0) return;
// Used for dumping the DSi arm9i/7i binaries
u32 portFlagsKey1, portFlagsSecRead;
int secureBlockNumber;
int i;
u8 cmdData[8] __attribute__ ((aligned));
GameCode* gameCode;
if (isDSiMode()) {
// Reset card slot
disableSlot1();
for(int i = 0; i < 25; i++) { swiWaitForVBlank(); }
enableSlot1();
for(int i = 0; i < 15; i++) { swiWaitForVBlank(); }
// 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);
} else {
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) ;
cardReset();
while(REG_ROMCTRL&CARD_BUSY) ;
}
//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) {
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) {
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) {
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) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
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);
secureAreaOffset += 0x1000/sizeof(u32);
}
}
// Alllliii jjjkkkkk - Enter Main Data Mode
createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0);
if (normalChip) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
// The 0x800 bytes are modcrypted, so this function isn't ran
//decryptSecureArea (gameCode->key, secureArea, 1);
twlBlowfish = true;
}
int 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;
nandSection = -1;
int secureBlockNumber;
int i;
u8 cmdData[8] __attribute__ ((aligned));
GameCode* gameCode;
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 < 30; i++) { swiWaitForVBlank(); }
}
enableSlot1();
for(i = 0; i < 15; i++) { swiWaitForVBlank(); }
// 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);
}
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) ;
cardReset();
while(REG_ROMCTRL&CARD_BUSY) ;
toncset(headerData, 0, 0x1000);
iCardId=cardReadID(CARD_CLK_SLOW);
while(REG_ROMCTRL & CARD_BUSY);
normalChip = (iCardId & BIT(31)) != 0; // ROM chip ID MSB
nandChip = (iCardId & BIT(27)) != 0; // Card has a NAND chip
// 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));
tonccpy(ndsHeader, headerData, 0x200);
if ((ndsHeader->unitCode != 0) || (ndsHeader->dsi_flags != 0))
{
// Extended header found
if(normalChip) {
for(int i = 0; i < 8; i++) {
cardParamCommand (CARD_CMD_HEADER_READ, i * 0x200,
CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
headerData + i * 0x200 / sizeof(u32), 0x200/sizeof(u32));
}
} else {
cardParamCommand (CARD_CMD_HEADER_READ, 0,
CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(4) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
(void*)headerData, 0x1000/sizeof(u32));
}
if (ndsHeader->dsi1[0]==0xFFFFFFFF && ndsHeader->dsi1[1]==0xFFFFFFFF
&& ndsHeader->dsi1[2]==0xFFFFFFFF && ndsHeader->dsi1[3]==0xFFFFFFFF)
{
toncset((u8*)headerData+0x200, 0, 0xE00); // Clear out FFs
}
tonccpy(ndsHeader, headerData, sizeof(sNDSHeaderExt));
}
// 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;
}
*/
// 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);
// 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) {
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);
// 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode
createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0);
if (normalChip) {
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) {
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) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
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);
secureAreaOffset += 0x1000/sizeof(u32);
}
}
// Alllliii jjjkkkkk - Enter Main Data Mode
createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0);
if (normalChip) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
//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'*/) {
// Secure area exists, so just clear the tag
secureArea[0] = 0xe7ffdeff;
secureArea[1] = 0xe7ffdeff;
} else {
//return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR;
}
// 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);
} else {
// Jam with the Band (J) (大合奏!バンドブラザーズ) doesn't have the RW section in the header
cardNandRomEnd = 0x7200000;
cardNandRwStart = 0x7200000;
}
}
return ERR_NONE;
}
int CardInit ()
{
if (!isDSiMode())return ERR_NONE;
if (!(REG_SCFG_EXT & BIT(31)))return ERR_NONE;
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;
nandSection = -1;
int secureBlockNumber;
int i;
u8 cmdData[8] __attribute__ ((aligned));
GameCode* gameCode;
twlBlowfish = false;
sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart
// Reset card slot
if(REG_SCFG_MC != 0x11){
disableSlot1();
for(i = 0; i < 30; i++) { swiWaitForVBlank(); }
}
enableSlot1();
for(i = 0; i < 15; i++) { swiWaitForVBlank(); }
// 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);
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) ;
cardReset();
while(REG_ROMCTRL&CARD_BUSY) ;
toncset(headerData, 0, 0x1000);
iCardId=cardReadID(CARD_CLK_SLOW);
while(REG_ROMCTRL & CARD_BUSY);
normalChip = (iCardId & BIT(31)) != 0; // ROM chip ID MSB
nandChip = (iCardId & BIT(27)) != 0; // Card has a NAND chip
// 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));
tonccpy(ndsHeader, headerData, 0x200);
if ((ndsHeader->unitCode != 0) || (ndsHeader->dsi_flags != 0))
{
// Extended header found
if(normalChip) {
for(int i = 0; i < 8; i++) {
cardParamCommand (CARD_CMD_HEADER_READ, i * 0x200,
CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
headerData + i * 0x200 / sizeof(u32), 0x200/sizeof(u32));
}
} else {
cardParamCommand (CARD_CMD_HEADER_READ, 0,
CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(4) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F),
(void*)headerData, 0x1000/sizeof(u32));
}
if (ndsHeader->dsi1[0]==0xFFFFFFFF && ndsHeader->dsi1[1]==0xFFFFFFFF
&& ndsHeader->dsi1[2]==0xFFFFFFFF && ndsHeader->dsi1[3]==0xFFFFFFFF)
{
toncset((u8*)headerData+0x200, 0, 0xE00); // Clear out FFs
}
tonccpy(ndsHeader, headerData, sizeof(sNDSHeaderExt));
}
// 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;
}
*/
// 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);
// 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) {
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);
// 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode
createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0);
if (normalChip) {
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) {
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) {
cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
for (i = 8; i > 0; i--) {
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);
secureAreaOffset += 0x1000/sizeof(u32);
}
}
// Alllliii jjjkkkkk - Enter Main Data Mode
createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0);
if (normalChip) {
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
cardDelay(ndsHeader->readTimeout);
}
cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData);
//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'*/) {
// Secure area exists, so just clear the tag
secureArea[0] = 0xe7ffdeff;
secureArea[1] = 0xe7ffdeff;
} else {
//return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR;
}
// 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);
} else {
// Jam with the Band (J) (大合奏!バンドブラザーズ) doesn't have the RW section in the header
cardNandRomEnd = 0x7200000;
cardNandRwStart = 0x7200000;
}
}
return ERR_NONE;
}
u32 cardGetId() {
return iCardId;
}
void cardRead (u32 src, void* dest, bool nandSave)
{
sNDSHeaderExt* ndsHeader = (sNDSHeaderExt*)headerData;
if (src >= 0 && src < 0x1000) {
// Read header
tonccpy (dest, (u8*)headerData + src, 0x200);
return;
} else if (src < CARD_SECURE_AREA_OFFSET) {
toncset (dest, 0, 0x200);
return;
} else if (src < CARD_DATA_OFFSET) {
// Read data from secure area
tonccpy (dest, (u8*)secureArea + src - CARD_SECURE_AREA_OFFSET, 0x200);
return;
} else if ((ndsHeader->unitCode != 0) && (src >= ndsHeader->arm9iromOffset) && (src < ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE)) {
// Read data from secure area
tonccpy (dest, (u8*)secureArea + src - ndsHeader->arm9iromOffset, 0x200);
return;
}
if (nandChip) {
if ((src < cardNandRomEnd || !nandSave) && nandSection != -1) {
cardParamCommand(CARD_CMD_NAND_ROM_MODE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
nandSection = -1;
} else if (src >= cardNandRwStart && nandSection != (src - cardNandRwStart) / (128 << 10) && nandSave) {
if(nandSection != -1) // Need to switch back to ROM mode before switching to another RW section
cardParamCommand(CARD_CMD_NAND_ROM_MODE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
cardParamCommand(CARD_CMD_NAND_RW_MODE, src, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
nandSection = (src - cardNandRwStart) / (128 << 10);
}
}
cardParamCommand (CARD_CMD_DATA_READ, src,
portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1),
dest, 0x200/sizeof(u32));
if (src > ndsHeader->romSize && !(nandSave && src >= cardNandRwStart)) {
switchToTwlBlowfish(ndsHeader);
}
}
// src must be a 0x800 byte array
void cardWriteNand (void* src, u32 dest)
{
if (dest < cardNandRwStart || !nandChip)
return;
if (nandSection != (dest - cardNandRwStart) / (128 << 10)) {
if(nandSection != -1) // Need to switch back to ROM mode before switching to another RW section
cardParamCommand(CARD_CMD_NAND_ROM_MODE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
cardParamCommand(CARD_CMD_NAND_RW_MODE, dest, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
nandSection = (dest - cardNandRwStart) / (128 << 10);
}
cardParamCommand(CARD_CMD_NAND_WRITE_ENABLE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
const u8 cmdData[8] = {0, 0, 0, dest, dest >> 8, dest >> 16, dest >> 24, CARD_CMD_NAND_WRITE_BUFFER};
for (int i = 0; i < 4; i++) {
cardPolledTransferWrite(portFlags | CARD_ACTIVATE | CARD_WR | CARD_nRESET | CARD_BLK_SIZE(1), src + (i * 0x200), 0x200 / sizeof(u32), cmdData);
}
cardParamCommand(CARD_CMD_NAND_COMMIT_BUFFER, 0, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
u32 status;
do {
cardParamCommand(CARD_CMD_NAND_READ_STATUS, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(7), &status, 1);
} while((status & BIT(5)) == 0);
cardParamCommand(CARD_CMD_NAND_DISCARD_BUFFER, 0, portFlags | CARD_ACTIVATE | CARD_nRESET, NULL, 0);
}

56
arm9/source/read_card.h Normal file
View File

@ -0,0 +1,56 @@
/*
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 READ_CARD_H
#define READ_CARD_H
#include <nds/ndstypes.h>
#include <nds/memory.h>
#include <stdlib.h>
#include "ndsheaderbanner.h"
#define CARD_NDS_HEADER_SIZE (0x200)
#define CARD_SECURE_AREA_OFFSET (0x4000)
#define CARD_SECURE_AREA_SIZE (0x4000)
#define CARD_DATA_OFFSET (0x8000)
#define CARD_DATA_BLOCK_SIZE (0x200)
#define MODC_AREA_SIZE 0x4000
#ifdef __cplusplus
extern "C" {
#endif
extern u32 cardNandRomEnd;
extern u32 cardNandRwStart;
int cardInit (sNDSHeaderExt* ndsHeader);
int CardInit (void);
void cardRead (u32 src, void* dest, bool nandSave);
u32 cardGetId (void);
void cardWriteNand (void* src, u32 dest);
#ifdef __cplusplus
}
#endif
#endif // READ_CARD_H

136
arm9/source/tonccpy.c Normal file
View File

@ -0,0 +1,136 @@
#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==0 || src==0)
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!
switch(tmp) {
do { *dst32++ = *src32++;
case 3: *dst32++ = *src32++;
case 2: *dst32++ = *src32++;
case 1: *dst32++ = *src32++;
case 0: ; } while(count--);
}
// 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==0)
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;
switch(tmp) {
do { *dst32++ = fill;
case 3: *dst32++ = fill;
case 2: *dst32++ = fill;
case 1: *dst32++ = fill;
case 0: ; } while(count--);
}
// Tail
size &= 3;
if(size)
{
mask= BIT_MASK(size*8);
*dst32= (*dst32 &~ mask) | (fill & mask);
}
}

43
arm9/source/tonccpy.h Normal file
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

View File

@ -31,6 +31,8 @@
#include "font.h"
#include "bgtop.h"
#include "bgsub.h"
#include "bgtopTWL.h"
#include "bgsubTWL.h"
#include "scrollbar.h"
#include "cursor.h"
#include "textbox.h"
@ -135,10 +137,17 @@ UserInterface::UserInterface (void)
REG_BG2CNT_SUB = BG_MAP_BASE(4) | BG_COLOR_16 | BG_TILE_BASE(6) | BG_PRIORITY(0);
// Set up background image
swiDecompressLZSSVram ((void*)bgtopTiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback);
swiDecompressLZSSVram ((void*)bgsubTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback);
vramcpy (&BG_PALETTE[0], bgtopPal, bgtopPalLen);
vramcpy (&BG_PALETTE_SUB[0], bgsubPal, bgsubPalLen);
if ((REG_SCFG_EXT & BIT(31))) {
swiDecompressLZSSVram ((void*)bgtopTWLTiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback);
swiDecompressLZSSVram ((void*)bgsubTWLTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback);
vramcpy (&BG_PALETTE[0], bgtopTWLPal, bgtopTWLPalLen);
vramcpy (&BG_PALETTE_SUB[0], bgsubTWLPal, bgsubTWLPalLen);
} else {
swiDecompressLZSSVram ((void*)bgtopTiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback);
swiDecompressLZSSVram ((void*)bgsubTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback);
vramcpy (&BG_PALETTE[0], bgtopPal, bgtopPalLen);
vramcpy (&BG_PALETTE_SUB[0], bgsubPal, bgsubPalLen);
}
u16* bgMapTop = (u16*)SCREEN_BASE_BLOCK(0);
u16* bgMapSub = (u16*)SCREEN_BASE_BLOCK_SUB(0);
for (int i = 0; i < CONSOLE_SCREEN_WIDTH*CONSOLE_SCREEN_HEIGHT; i++) {