mirror of
https://github.com/Normmatt/ntrcardhax.git
synced 2025-06-18 21:15:32 -04:00
Initial Commit
This commit is contained in:
commit
d1225a56c7
BIN
auto_ntrcardhax/ak2i_flash81_ntrcardhax_template.bin
Normal file
BIN
auto_ntrcardhax/ak2i_flash81_ntrcardhax_template.bin
Normal file
Binary file not shown.
28
auto_ntrcardhax/auto_ntrcardhax.sln
Normal file
28
auto_ntrcardhax/auto_ntrcardhax.sln
Normal 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
|
219
auto_ntrcardhax/auto_ntrcardhax/ERTFS_types.h
Normal file
219
auto_ntrcardhax/auto_ntrcardhax/ERTFS_types.h
Normal 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;
|
245
auto_ntrcardhax/auto_ntrcardhax/auto_ntrcardhax.cpp
Normal file
245
auto_ntrcardhax/auto_ntrcardhax/auto_ntrcardhax.cpp
Normal 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;
|
||||
}
|
||||
|
160
auto_ntrcardhax/auto_ntrcardhax/auto_ntrcardhax.vcxproj
Normal file
160
auto_ntrcardhax/auto_ntrcardhax/auto_ntrcardhax.vcxproj
Normal 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>
|
@ -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>
|
48
auto_ntrcardhax/auto_ntrcardhax/crc.cpp
Normal file
48
auto_ntrcardhax/auto_ntrcardhax/crc.cpp
Normal 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;
|
||||
}
|
12
auto_ntrcardhax/auto_ntrcardhax/crc.h
Normal file
12
auto_ntrcardhax/auto_ntrcardhax/crc.h
Normal 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
|
44
auto_ntrcardhax/auto_ntrcardhax/firm.cpp
Normal file
44
auto_ntrcardhax/auto_ntrcardhax/firm.cpp
Normal 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;
|
||||
}
|
34
auto_ntrcardhax/auto_ntrcardhax/firm.h
Normal file
34
auto_ntrcardhax/auto_ntrcardhax/firm.h
Normal 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
174
ntrcardhax_arm11/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
3
ntrcardhax_arm11/build.bat
Normal file
3
ntrcardhax_arm11/build.bat
Normal file
@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
make
|
||||
pause
|
3
ntrcardhax_arm11/clean.bat
Normal file
3
ntrcardhax_arm11/clean.bat
Normal file
@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
make clean
|
||||
pause
|
17
ntrcardhax_arm11/source/csvc.s
Normal file
17
ntrcardhax_arm11/source/csvc.s
Normal 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
|
18
ntrcardhax_arm11/source/khax.h
Normal file
18
ntrcardhax_arm11/source/khax.h
Normal 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
|
1727
ntrcardhax_arm11/source/khaxinit.cpp
Normal file
1727
ntrcardhax_arm11/source/khaxinit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
361
ntrcardhax_arm11/source/khaxinternal.h
Normal file
361
ntrcardhax_arm11/source/khaxinternal.h
Normal 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
|
||||
}
|
503
ntrcardhax_arm11/source/main.c
Normal file
503
ntrcardhax_arm11/source/main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user