mirror of
https://github.com/LNH-team/pico-loader.git
synced 2026-06-02 01:06:50 +02:00
Initial commit
This commit is contained in:
83
common/ApList.cpp
Normal file
83
common/ApList.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "common.h"
|
||||
#include <algorithm>
|
||||
#include "ApList.h"
|
||||
|
||||
const ApListEntry* ApList::FindEntry(u32 gameCode, u8 gameVersion)
|
||||
{
|
||||
if (_count != 0)
|
||||
{
|
||||
const auto gameEntry = std::lower_bound(_entries.get(), _entries.get() + _count, gameCode,
|
||||
[gameVersion] (const ApListEntry& entry, u32 value)
|
||||
{
|
||||
if (entry.GetGameCode() == value)
|
||||
return entry.GetGameVersion() < gameVersion;
|
||||
return entry.GetGameCode() < value;
|
||||
});
|
||||
|
||||
if (gameEntry != _entries.get() + _count &&
|
||||
gameEntry->GetGameCode() == gameCode &&
|
||||
gameEntry->GetGameVersion() == gameVersion)
|
||||
{
|
||||
return gameEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ApListEntry::Dump() const
|
||||
{
|
||||
const char* dsProtectVersionString;
|
||||
switch (GetDSProtectVersion())
|
||||
{
|
||||
case DSProtectVersion::v1_05: dsProtectVersionString = "v1.05"; break;
|
||||
case DSProtectVersion::v1_06: dsProtectVersionString = "v1.06"; break;
|
||||
case DSProtectVersion::v1_08: dsProtectVersionString = "v1.08"; break;
|
||||
case DSProtectVersion::v1_10: dsProtectVersionString = "v1.10"; break;
|
||||
case DSProtectVersion::v1_20: dsProtectVersionString = "v1.20"; break;
|
||||
case DSProtectVersion::v1_22: dsProtectVersionString = "v1.22"; break;
|
||||
case DSProtectVersion::v1_23: dsProtectVersionString = "v1.23"; break;
|
||||
case DSProtectVersion::v1_23Z: dsProtectVersionString = "v1.23Z"; break;
|
||||
case DSProtectVersion::v1_25: dsProtectVersionString = "v1.25"; break;
|
||||
case DSProtectVersion::v1_26: dsProtectVersionString = "v1.26"; break;
|
||||
case DSProtectVersion::v1_27: dsProtectVersionString = "v1.27"; break;
|
||||
case DSProtectVersion::v1_28: dsProtectVersionString = "v1.28"; break;
|
||||
case DSProtectVersion::v2_00: dsProtectVersionString = "v2.00"; break;
|
||||
case DSProtectVersion::v2_01: dsProtectVersionString = "v2.01"; break;
|
||||
case DSProtectVersion::v2_03: dsProtectVersionString = "v2.03"; break;
|
||||
case DSProtectVersion::v2_05: dsProtectVersionString = "v2.05"; break;
|
||||
case DSProtectVersion::v2_00s: dsProtectVersionString = "v2.00s"; break;
|
||||
case DSProtectVersion::v2_01s: dsProtectVersionString = "v2.01s"; break;
|
||||
case DSProtectVersion::v2_03s: dsProtectVersionString = "v2.03s"; break;
|
||||
case DSProtectVersion::v2_05s: dsProtectVersionString = "v2.05s"; break;
|
||||
default:
|
||||
dsProtectVersionString = "unknown";
|
||||
break;
|
||||
}
|
||||
LOG_DEBUG("%c%c%c%c - %d - DSProtect %s\n",
|
||||
gameCode & 0xFF, (gameCode >> 8) & 0xFF, (gameCode >> 16) & 0xFF, gameCode >> 24,
|
||||
gameVersion,
|
||||
dsProtectVersionString);
|
||||
if (regularOverlayId != AP_LIST_OVERLAY_ID_INVALID)
|
||||
{
|
||||
if (regularOverlayId == AP_LIST_OVERLAY_ID_STATIC_ARM9)
|
||||
{
|
||||
LOG_DEBUG("regular: main memory offset 0x%x\n", GetRegularOffset());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("regular: overlay %d offset 0x%x\n", regularOverlayId, GetRegularOffset());
|
||||
}
|
||||
}
|
||||
if (sOverlayId != AP_LIST_OVERLAY_ID_INVALID)
|
||||
{
|
||||
if (sOverlayId == AP_LIST_OVERLAY_ID_STATIC_ARM9)
|
||||
{
|
||||
LOG_DEBUG("s: main memory offset 0x%x\n", GetSOffset());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("s: overlay %d offset 0x%x\n", sOverlayId, GetSOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
48
common/ApList.h
Normal file
48
common/ApList.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "common.h"
|
||||
#include "DSProtectVersion.h"
|
||||
|
||||
#define AP_LIST_OVERLAY_ID_STATIC_ARM9 0xFFFE
|
||||
#define AP_LIST_OVERLAY_ID_INVALID 0xFFFF
|
||||
|
||||
/// @brief Class representing an AP list entry.
|
||||
class ApListEntry
|
||||
{
|
||||
u32 gameCode;
|
||||
u16 gameVersion : 5;
|
||||
u16 dsProtectVersion : 5; // see DSProtectVersion
|
||||
u16 dsProtectFunctionMask : 6; // for versions < 1.23
|
||||
u16 regularOverlayId; // 0xFFFE = static ARM9, 0xFFFF = invalid
|
||||
u16 sOverlayId; // 0xFFFE = static ARM9, 0xFFFF = invalid
|
||||
u8 regularOffset[3]; // 24 bit
|
||||
u8 sOffset[3]; // 24 bit
|
||||
|
||||
public:
|
||||
u32 GetGameCode() const { return gameCode; }
|
||||
u8 GetGameVersion() const { return gameVersion; }
|
||||
DSProtectVersion GetDSProtectVersion() const { return static_cast<DSProtectVersion>(dsProtectVersion); }
|
||||
u8 GetDSProtectFunctionMask() const { return dsProtectFunctionMask; }
|
||||
u16 GetRegularOverlayId() const { return regularOverlayId; }
|
||||
u16 GetSOverlayId() const { return sOverlayId; }
|
||||
u32 GetRegularOffset() const { return regularOffset[0] | (regularOffset[1] << 8) | (regularOffset[2] << 16); }
|
||||
u32 GetSOffset() const { return sOffset[0] | (sOffset[1] << 8) | (sOffset[2] << 16); }
|
||||
|
||||
void Dump() const;
|
||||
};
|
||||
|
||||
static_assert(sizeof(ApListEntry) == 0x10, "Invalid sizeof(ApListEntry)");
|
||||
|
||||
/// @brief Class representing an AP list.
|
||||
class ApList
|
||||
{
|
||||
public:
|
||||
ApList(std::unique_ptr<const ApListEntry[]> entries, u32 count)
|
||||
: _entries(std::move(entries)), _count(count) { }
|
||||
|
||||
const ApListEntry* FindEntry(u32 gameCode, u8 gameVersion);
|
||||
|
||||
private:
|
||||
std::unique_ptr<const ApListEntry[]> _entries;
|
||||
u32 _count;
|
||||
};
|
||||
17
common/CardSaveType.h
Normal file
17
common/CardSaveType.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
/// @brief Enum representing the save type.
|
||||
enum class CardSaveType
|
||||
{
|
||||
/// @brief The game has no save.
|
||||
None = 0,
|
||||
|
||||
/// @brief EEPROM save.
|
||||
Eeprom = 1,
|
||||
|
||||
/// @brief Flash save.
|
||||
Flash = 2,
|
||||
|
||||
/// @brief NAND save.
|
||||
Nand = 3
|
||||
};
|
||||
26
common/DSProtectVersion.h
Normal file
26
common/DSProtectVersion.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
/// @brief Enum representing a DS Protect version.
|
||||
enum class DSProtectVersion : u32
|
||||
{
|
||||
v1_06,
|
||||
v1_05,
|
||||
v1_08,
|
||||
v1_10,
|
||||
v1_20,
|
||||
v1_22,
|
||||
v1_23,
|
||||
v1_23Z,
|
||||
v1_25,
|
||||
v1_26,
|
||||
v1_27,
|
||||
v1_28,
|
||||
v2_00,
|
||||
v2_01,
|
||||
v2_03,
|
||||
v2_05,
|
||||
v2_00s,
|
||||
v2_01s,
|
||||
v2_03s,
|
||||
v2_05s
|
||||
};
|
||||
10
common/LoaderInfo.h
Normal file
10
common/LoaderInfo.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
struct loader_info_t
|
||||
{
|
||||
u16 clusterShift;
|
||||
u16 picoLoaderBootDrive;
|
||||
u32 database;
|
||||
u32 clusterMap9[10];
|
||||
u32 clusterMap7[16];
|
||||
};
|
||||
41
common/SdkVersion.h
Normal file
41
common/SdkVersion.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#define SDK_VERSION_MAJOR_SHIFT 24
|
||||
#define SDK_VERSION_MINOR_SHIFT 16
|
||||
#define SDK_VERSION_RELEASE_STEP_SHIFT 0
|
||||
|
||||
#define SDK_VERSION_MAJOR_MASK 0x00FF
|
||||
#define SDK_VERSION_MINOR_MASK 0x00FF
|
||||
#define SDK_VERSION_RELEASE_STEP_MASK 0xFFFF
|
||||
|
||||
#define SDK_VERSION_MAJOR_NITRO_2 2
|
||||
#define SDK_VERSION_MAJOR_NITRO_3 3
|
||||
#define SDK_VERSION_MAJOR_NITRO_4 4
|
||||
#define SDK_VERSION_MAJOR_TWL 5
|
||||
|
||||
#define SDK_VERSION_RELEASE_STEP_PREVIEW 10000
|
||||
#define SDK_VERSION_RELEASE_STEP_RELEASE_CANDIDATE 20000
|
||||
#define SDK_VERSION_RELEASE_STEP_RELEASE 30000
|
||||
|
||||
/// @brief Class representing an exact SDK version.
|
||||
class SdkVersion
|
||||
{
|
||||
u32 _version;
|
||||
public:
|
||||
constexpr SdkVersion(u32 version)
|
||||
: _version(version) { }
|
||||
|
||||
constexpr SdkVersion(u32 major, u32 minor, u32 releaseStep)
|
||||
: _version((major << SDK_VERSION_MAJOR_SHIFT) | (minor << SDK_VERSION_MINOR_SHIFT) | releaseStep) { }
|
||||
|
||||
constexpr u32 GetMajor() const { return _version >> SDK_VERSION_MAJOR_SHIFT; }
|
||||
constexpr u32 GetMinor() const { return (_version >> SDK_VERSION_MINOR_SHIFT) & SDK_VERSION_MINOR_MASK; }
|
||||
constexpr u32 GetReleaseClass() const { return GetReleaseStep() / 10000; }
|
||||
constexpr u32 GetReleaseMajor() const { return (GetReleaseStep() % 10000) / 100; }
|
||||
constexpr u32 GetReleaseMinor() const { return (GetReleaseStep() % 10000) % 100; }
|
||||
constexpr u32 GetReleaseStep() const { return _version & SDK_VERSION_RELEASE_STEP_MASK; }
|
||||
|
||||
constexpr bool IsTwlSdk() const { return GetMajor() == SDK_VERSION_MAJOR_TWL; }
|
||||
|
||||
constexpr friend auto operator<=>(const SdkVersion&, const SdkVersion&) = default;
|
||||
};
|
||||
52
common/TwlConfig.h
Normal file
52
common/TwlConfig.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include <nds/ndstypes.h>
|
||||
|
||||
struct twl_config_t
|
||||
{
|
||||
u32 configFlags;
|
||||
u8 field4;
|
||||
u8 country;
|
||||
u8 language;
|
||||
u8 rtcYear;
|
||||
s64 rtcOffset;
|
||||
u8 eulaAgreeVersion[8];
|
||||
u8 field18[2];
|
||||
u8 alarmHour;
|
||||
u8 alarmMinute;
|
||||
u8 field1C[2];
|
||||
u8 alarmEnable;
|
||||
u8 field1F[2];
|
||||
u8 systemMenuUsedTitleSlots;
|
||||
u8 systemMenuFreeTitleSlots;
|
||||
u8 field23;
|
||||
u8 field24;
|
||||
u8 field25[3];
|
||||
u64 systemMenuLastSelectedTitleId;
|
||||
u16 touchCalibrationX1Adc;
|
||||
u16 touchCalibrationY1Adc;
|
||||
u8 touchCalibrationX1Pixel;
|
||||
u8 touchCalibrationY1Pixel;
|
||||
u16 touchCalibrationX2Adc;
|
||||
u16 touchCalibrationY2Adc;
|
||||
u8 touchCalibrationX2Pixel;
|
||||
u8 touchCalibrationY2Pixel;
|
||||
u32 field3C;
|
||||
u8 field40[4];
|
||||
u8 favoriteColor;
|
||||
u8 field45;
|
||||
u8 birthdayMonth;
|
||||
u8 birthdayDay;
|
||||
u16 nickname[11];
|
||||
u16 message[27];
|
||||
u8 parentalControlsFlags;
|
||||
u8 field95[6];
|
||||
u8 parentalControlsRegion;
|
||||
u8 parentalControlsAge;
|
||||
u8 parentalControlsSecretQuestion;
|
||||
u8 parentalControlsUnknown;
|
||||
u8 field9F[2];
|
||||
u8 parentalControlsPin[5];
|
||||
u16 parentalControlsSecretAnswer[65];
|
||||
};
|
||||
|
||||
static_assert(sizeof(twl_config_t) == 0x128);
|
||||
17
common/argv.h
Normal file
17
common/argv.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#define HOMEBREW_ARGV_MAGIC 0x5f617267
|
||||
|
||||
//structure used to set up argc/argv on the DS
|
||||
struct homebrew_argv_t
|
||||
{
|
||||
int magic; // argv magic number, set to 0x5f617267 ('_arg') if valid
|
||||
char* commandLine; // base address of command line, set of null terminated strings
|
||||
int length; // total length of command line
|
||||
int argc; // internal use, number of arguments
|
||||
char** argv; // internal use, argv pointer
|
||||
int dummy; // internal use
|
||||
u32 host; // internal use, host ip for dslink
|
||||
};
|
||||
|
||||
#define HOMEBREW_ARGV ((homebrew_argv_t*)0x02FFFE70)
|
||||
1272
common/core/heap/tlsf.arm.c
Normal file
1272
common/core/heap/tlsf.arm.c
Normal file
File diff suppressed because it is too large
Load Diff
90
common/core/heap/tlsf.h
Normal file
90
common/core/heap/tlsf.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef INCLUDED_tlsf
|
||||
#define INCLUDED_tlsf
|
||||
|
||||
/*
|
||||
** Two Level Segregated Fit memory allocator, version 3.1.
|
||||
** Written by Matthew Conte
|
||||
** http://tlsf.baisoku.org
|
||||
**
|
||||
** Based on the original documentation by Miguel Masmano:
|
||||
** http://www.gii.upv.es/tlsf/main/docs
|
||||
**
|
||||
** This implementation was written to the specification
|
||||
** of the document, therefore no GPL restrictions apply.
|
||||
**
|
||||
** Copyright (c) 2006-2016, Matthew Conte
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the copyright holder nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */
|
||||
/* pool_t: a block of memory that TLSF can manage. */
|
||||
typedef void* tlsf_t;
|
||||
typedef void* pool_t;
|
||||
|
||||
/* Create/destroy a memory pool. */
|
||||
tlsf_t tlsf_create(void* mem);
|
||||
tlsf_t tlsf_create_with_pool(void* mem, size_t bytes);
|
||||
void tlsf_destroy(tlsf_t tlsf);
|
||||
pool_t tlsf_get_pool(tlsf_t tlsf);
|
||||
|
||||
/* Add/remove memory pools. */
|
||||
pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes);
|
||||
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
|
||||
|
||||
/* malloc/memalign/realloc/free replacements. */
|
||||
void* tlsf_malloc(tlsf_t tlsf, size_t bytes);
|
||||
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t bytes);
|
||||
void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
|
||||
void tlsf_free(tlsf_t tlsf, void* ptr);
|
||||
|
||||
/* Returns internal block size, not original request size */
|
||||
size_t tlsf_block_size(void* ptr);
|
||||
|
||||
/* Overheads/limits of internal structures. */
|
||||
size_t tlsf_size(void);
|
||||
size_t tlsf_align_size(void);
|
||||
size_t tlsf_block_size_min(void);
|
||||
size_t tlsf_block_size_max(void);
|
||||
size_t tlsf_pool_overhead(void);
|
||||
size_t tlsf_alloc_overhead(void);
|
||||
|
||||
/* Debugging. */
|
||||
typedef void (*tlsf_walker)(void* ptr, size_t size, int used, void* user);
|
||||
void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user);
|
||||
/* Returns nonzero if any internal consistency check fails. */
|
||||
int tlsf_check(tlsf_t tlsf);
|
||||
int tlsf_check_pool(pool_t pool);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
312
common/core/mini-printf.c
Normal file
312
common/core/mini-printf.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* The Minimal snprintf() implementation
|
||||
*
|
||||
* Copyright (c) 2013,2014 Michal Ludvig <michal@logix.cz>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the auhor nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ----
|
||||
*
|
||||
* This is a minimal snprintf() implementation optimised
|
||||
* for embedded systems with a very limited program memory.
|
||||
* mini_snprintf() doesn't support _all_ the formatting
|
||||
* the glibc does but on the other hand is a lot smaller.
|
||||
* Here are some numbers from my STM32 project (.bin file size):
|
||||
* no snprintf(): 10768 bytes
|
||||
* mini snprintf(): 11420 bytes (+ 652 bytes)
|
||||
* glibc snprintf(): 34860 bytes (+24092 bytes)
|
||||
* Wasting nearly 24kB of memory just for snprintf() on
|
||||
* a chip with 32kB flash is crazy. Use mini_snprintf() instead.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mini-printf.h"
|
||||
|
||||
static int
|
||||
mini_strlen(const char *s)
|
||||
{
|
||||
int len = 0;
|
||||
while (s[len] != '\0') len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
mini_itoa(long value, unsigned int radix, int uppercase, int unsig,
|
||||
char *buffer)
|
||||
{
|
||||
char *pbuffer = buffer;
|
||||
int negative = 0;
|
||||
int i, len;
|
||||
|
||||
/* No support for unusual radixes. */
|
||||
if (radix > 16)
|
||||
return 0;
|
||||
|
||||
if (value < 0 && !unsig) {
|
||||
negative = 1;
|
||||
value = -value;
|
||||
}
|
||||
|
||||
/* This builds the string back to front ... */
|
||||
do {
|
||||
int digit = value % radix;
|
||||
*(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10);
|
||||
value /= radix;
|
||||
} while (value > 0);
|
||||
|
||||
if (negative)
|
||||
*(pbuffer++) = '-';
|
||||
|
||||
*(pbuffer) = '\0';
|
||||
|
||||
/* ... now we reverse it (could do it recursively but will
|
||||
* conserve the stack space) */
|
||||
len = (pbuffer - buffer);
|
||||
for (i = 0; i < len / 2; i++) {
|
||||
char j = buffer[i];
|
||||
buffer[i] = buffer[len-i-1];
|
||||
buffer[len-i-1] = j;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
mini_pad(char* ptr, int len, char pad_char, int pad_to, char *buffer)
|
||||
{
|
||||
int i;
|
||||
int overflow = 0;
|
||||
char * pbuffer = buffer;
|
||||
if(pad_to == 0) pad_to = len;
|
||||
if(len > pad_to) {
|
||||
len = pad_to;
|
||||
overflow = 1;
|
||||
}
|
||||
for(i = pad_to - len; i > 0; i --) {
|
||||
*(pbuffer++) = pad_char;
|
||||
}
|
||||
for(i = len; i > 0; i --) {
|
||||
*(pbuffer++) = *(ptr++);
|
||||
}
|
||||
len = pbuffer - buffer;
|
||||
if(overflow) {
|
||||
for (i = 0; i < 3 && pbuffer > buffer; i ++) {
|
||||
*(pbuffer-- - 1) = '*';
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
struct mini_buff {
|
||||
char *buffer, *pbuffer;
|
||||
unsigned int buffer_len;
|
||||
};
|
||||
|
||||
static int
|
||||
_puts(char *s, int len, void *buf)
|
||||
{
|
||||
if(!buf) return len;
|
||||
struct mini_buff *b = buf;
|
||||
char * p0 = b->buffer;
|
||||
int i;
|
||||
/* Copy to buffer */
|
||||
for (i = 0; i < len; i++) {
|
||||
if(b->pbuffer == b->buffer + b->buffer_len - 1) {
|
||||
break;
|
||||
}
|
||||
*(b->pbuffer ++) = s[i];
|
||||
}
|
||||
*(b->pbuffer) = 0;
|
||||
return b->pbuffer - p0;
|
||||
}
|
||||
|
||||
#ifdef MINI_PRINTF_ENABLE_OBJECTS
|
||||
static int (*mini_handler) (void* data, void* obj, int ch, int lhint, char** bf) = 0;
|
||||
static void (*mini_handler_freeor)(void* data, void*) = 0;
|
||||
static void * mini_handler_data = 0;
|
||||
|
||||
void mini_printf_set_handler(
|
||||
void* data,
|
||||
int (*handler)(void* data, void* obj, int ch, int len_hint, char** buf),
|
||||
void (*freeor)(void* data, void* buf))
|
||||
{
|
||||
mini_handler = handler;
|
||||
mini_handler_freeor = freeor;
|
||||
mini_handler_data = data;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va)
|
||||
{
|
||||
struct mini_buff b;
|
||||
b.buffer = buffer;
|
||||
b.pbuffer = buffer;
|
||||
b.buffer_len = buffer_len;
|
||||
if(buffer_len == 0) buffer = (void*) 0;
|
||||
int n = mini_vpprintf(_puts, (buffer != (void*)0)?&b:(void*)0, fmt, va);
|
||||
if(buffer == (void*) 0) {
|
||||
return n;
|
||||
}
|
||||
return b.pbuffer - b.buffer;
|
||||
}
|
||||
|
||||
int
|
||||
mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va)
|
||||
{
|
||||
char bf[24];
|
||||
char bf2[24];
|
||||
char ch;
|
||||
#ifdef MINI_PRINTF_ENABLE_OBJECTS
|
||||
void* obj;
|
||||
#endif
|
||||
if(puts == (void*)0) {
|
||||
/* run puts in counting mode. */
|
||||
puts = _puts; buf = (void*)0;
|
||||
}
|
||||
int n = 0;
|
||||
while ((ch=*(fmt++))) {
|
||||
int len;
|
||||
if (ch!='%') {
|
||||
len = 1;
|
||||
len = puts(&ch, len, buf);
|
||||
} else {
|
||||
char pad_char = ' ';
|
||||
int pad_to = 0;
|
||||
char l = 0;
|
||||
char *ptr;
|
||||
|
||||
ch=*(fmt++);
|
||||
|
||||
/* Zero padding requested */
|
||||
if (ch == '0') pad_char = '0';
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
pad_to = pad_to * 10 + (ch - '0');
|
||||
ch=*(fmt++);
|
||||
}
|
||||
if(pad_to > (signed int) sizeof(bf)) {
|
||||
pad_to = sizeof(bf);
|
||||
}
|
||||
if (ch == 'l') {
|
||||
l = 1;
|
||||
ch=*(fmt++);
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case 0:
|
||||
goto end;
|
||||
case 'u':
|
||||
case 'd':
|
||||
if(l) {
|
||||
len = mini_itoa(va_arg(va, unsigned long), 10, 0, (ch=='u'), bf2);
|
||||
} else {
|
||||
if(ch == 'u') {
|
||||
len = mini_itoa((unsigned long) va_arg(va, unsigned int), 10, 0, 1, bf2);
|
||||
} else {
|
||||
len = mini_itoa((long) va_arg(va, int), 10, 0, 0, bf2);
|
||||
}
|
||||
}
|
||||
len = mini_pad(bf2, len, pad_char, pad_to, bf);
|
||||
len = puts(bf, len, buf);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
case 'x':
|
||||
case 'X':
|
||||
if(l) {
|
||||
len = mini_itoa(va_arg(va, unsigned long), 16, (ch=='X'), 1, bf2);
|
||||
} else {
|
||||
len = mini_itoa((unsigned long) va_arg(va, unsigned int), 16, (ch=='X'), 1, bf2);
|
||||
}
|
||||
len = mini_pad(bf2, len, pad_char, pad_to, bf);
|
||||
len = puts(bf, len, buf);
|
||||
break;
|
||||
|
||||
case 'c' :
|
||||
ch = (char)(va_arg(va, int));
|
||||
len = mini_pad(&ch, 1, pad_char, pad_to, bf);
|
||||
len = puts(bf, len, buf);
|
||||
break;
|
||||
|
||||
case 's' :
|
||||
ptr = va_arg(va, char*);
|
||||
len = mini_strlen(ptr);
|
||||
if (pad_to > 0) {
|
||||
len = mini_pad(ptr, len, pad_char, pad_to, bf);
|
||||
len = puts(bf, len, buf);
|
||||
} else {
|
||||
len = puts(ptr, len, buf);
|
||||
}
|
||||
break;
|
||||
#ifdef MINI_PRINTF_ENABLE_OBJECTS
|
||||
case 'O' : /* Object by content (e.g. str) */
|
||||
case 'R' : /* Object by representation (e.g. repr)*/
|
||||
obj = va_arg(va, void*);
|
||||
len = mini_handler(mini_handler_data, obj, ch, pad_to, &ptr);
|
||||
if (pad_to > 0) {
|
||||
len = mini_pad(ptr, len, pad_char, pad_to, bf);
|
||||
len = puts(bf, len, buf);
|
||||
} else {
|
||||
len = puts(ptr, len, buf);
|
||||
}
|
||||
mini_handler_freeor(mini_handler_data, ptr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
len = 1;
|
||||
len = puts(&ch, len, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
n = n + len;
|
||||
}
|
||||
end:
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
ret = mini_vsnprintf(buffer, buffer_len, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
ret = mini_vpprintf(puts, buf, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
73
common/core/mini-printf.h
Normal file
73
common/core/mini-printf.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* The Minimal snprintf() implementation
|
||||
*
|
||||
* Copyright (c) 2013 Michal Ludvig <michal@logix.cz>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the auhor nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MINI_PRINTF__
|
||||
#define __MINI_PRINTF__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef MINI_PRINTF_ENABLE_OBJECTS
|
||||
/* If enabled, callback for object types (O and R).
|
||||
* void* arguments matching %O and %R are sent to handler as obj.
|
||||
* the result string created by handler at *buf is freed by freeor.
|
||||
* */
|
||||
void mini_printf_set_handler(
|
||||
void * data,
|
||||
/* handler returns number of chars in *buf; *buf is not NUL-terminated. */
|
||||
int (*handler)(void* data, void* obj, int ch, int len_hint, char** buf),
|
||||
void (*freeor)(void* data, void* buf));
|
||||
#endif
|
||||
|
||||
/* String IO interface; returns number of bytes written, not including the ending NUL.
|
||||
* Always appends a NUL at the end, therefore buffer_len shall be at least 1 in normal operation.
|
||||
* If buffer is NULL or buffer_len is 0, returns number of bytes to be written, not including the ending NUL.
|
||||
*/
|
||||
int mini_vsnprintf(char* buffer, unsigned int buffer_len, const char *fmt, va_list va);
|
||||
int mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...);
|
||||
|
||||
/* Stream IO interface; returns number of bytes written.
|
||||
* If puts is NULL, number of bytes to be written.
|
||||
* puts shall return number of bytes written.
|
||||
*/
|
||||
int mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va);
|
||||
int mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define vsnprintf mini_vsnprintf
|
||||
#define snprintf mini_snprintf
|
||||
|
||||
#endif
|
||||
22
common/fileInfo.h
Normal file
22
common/fileInfo.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "sharedMemory.h"
|
||||
|
||||
struct rom_file_info_t
|
||||
{
|
||||
u32 clusterShift;
|
||||
u32 database;
|
||||
u32 clusterMask;
|
||||
u32 clusterMap[124];
|
||||
u32 fileSize;
|
||||
};
|
||||
|
||||
struct save_file_info_t
|
||||
{
|
||||
u32 clusterShift;
|
||||
u32 database;
|
||||
u32 clusterMask;
|
||||
u32 clusterMap[29];
|
||||
};
|
||||
|
||||
#define SHARED_ROM_FILE_INFO ((rom_file_info_t*)TWL_SHARED_MEMORY->ntrSharedMem.gap0)
|
||||
#define SHARED_SAVE_FILE_INFO ((save_file_info_t*)TWL_SHARED_MEMORY->ntrSharedMem.gap200)
|
||||
11
common/gameCode.h
Normal file
11
common/gameCode.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
static inline consteval u32 GAMECODE(const char code[4])
|
||||
{
|
||||
return code[0] | (code[1] << 8) | (code[2] << 16) | (code[3] << 24);
|
||||
}
|
||||
|
||||
static inline consteval u32 GAMECODE_NO_REGION(const char code[3])
|
||||
{
|
||||
return code[0] | (code[1] << 8) | (code[2] << 16);
|
||||
}
|
||||
14
common/ipcCommands.h
Normal file
14
common/ipcCommands.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#define IPC_COMMAND_ARM9_WRAM_CONFIG 1
|
||||
#define IPC_COMMAND_ARM9_CLEAR_MAIN_MEM 2
|
||||
#define IPC_COMMAND_ARM9_APPLY_PATCHES 3
|
||||
#define IPC_COMMAND_ARM9_APPLY_ARM7_PATCHES 4
|
||||
#define IPC_COMMAND_ARM9_SET_AP_INFO 5
|
||||
#define IPC_COMMAND_ARM9_SET_ROM_FILE_INFO 6
|
||||
#define IPC_COMMAND_ARM9_INITIALIZE_SD_CARD 8
|
||||
#define IPC_COMMAND_ARM9_INITIALIZE_LOADER_INFO 9
|
||||
#define IPC_COMMAND_ARM9_GET_SD_FUNCTIONS 0xA
|
||||
#define IPC_COMMAND_ARM9_DISPLAY_ERROR 0xB
|
||||
#define IPC_COMMAND_ARM9_SWITCH_TO_DS_MODE 0xD
|
||||
#define IPC_COMMAND_ARM9_BOOT 0xF
|
||||
32
common/logger/ILogger.h
Normal file
32
common/logger/ILogger.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include <stdarg.h>
|
||||
|
||||
enum class LogLevel
|
||||
{
|
||||
Off,
|
||||
|
||||
Fatal,
|
||||
Error,
|
||||
Warning,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
|
||||
All
|
||||
};
|
||||
|
||||
class ILogger
|
||||
{
|
||||
public:
|
||||
virtual ~ILogger() { }
|
||||
|
||||
void Log(LogLevel level, const char* fmt, ...)
|
||||
{
|
||||
va_list vlist;
|
||||
va_start(vlist, fmt);
|
||||
LogV(level, fmt, vlist);
|
||||
va_end(vlist);
|
||||
}
|
||||
|
||||
virtual void LogV(LogLevel level, const char* fmt, va_list vlist) = 0;
|
||||
};
|
||||
10
common/logger/IOutputStream.h
Normal file
10
common/logger/IOutputStream.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
class IOutputStream
|
||||
{
|
||||
public:
|
||||
virtual ~IOutputStream() { }
|
||||
|
||||
virtual void Write(const char* str) = 0;
|
||||
virtual void Flush() = 0;
|
||||
};
|
||||
8
common/logger/NullLogger.h
Normal file
8
common/logger/NullLogger.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "ILogger.h"
|
||||
|
||||
class NullLogger : public ILogger
|
||||
{
|
||||
public:
|
||||
void LogV(LogLevel level, const char* fmt, va_list vlist) override { }
|
||||
};
|
||||
9
common/logger/NullOutputStream.h
Normal file
9
common/logger/NullOutputStream.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "IOutputStream.h"
|
||||
|
||||
class NullOutputStream : public IOutputStream
|
||||
{
|
||||
public:
|
||||
void Write(const char* str) { }
|
||||
void Flush() { }
|
||||
};
|
||||
26
common/logger/PicoAgbAdapterOutputStream.cpp
Normal file
26
common/logger/PicoAgbAdapterOutputStream.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <nds.h>
|
||||
#include "picoAgbAdapter.h"
|
||||
#include "PicoAgbAdapterOutputStream.h"
|
||||
|
||||
void PicoAgbAdapterOutputStream::Write(const char* str)
|
||||
{
|
||||
char c;
|
||||
vu16* ring = PICO_AGB_PRINT_ARM9_RING;
|
||||
u32 writePtr = PICO_AGB_PRINT_ARM9_WRITE_PTR;
|
||||
u32 readPtr = PICO_AGB_PRINT_ARM9_READ_PTR;
|
||||
while ((c = *str++) != 0)
|
||||
{
|
||||
u32 newWritePtr = (writePtr + 1) & (PICO_AGB_PRINT_RING_LENGTH - 1);
|
||||
while (newWritePtr == readPtr)
|
||||
{
|
||||
PICO_AGB_PRINT_ARM9_WRITE_PTR = writePtr;
|
||||
readPtr = PICO_AGB_PRINT_ARM9_READ_PTR;
|
||||
}
|
||||
if (writePtr & 1)
|
||||
ring[writePtr >> 1] = (ring[writePtr >> 1] & 0xFF) | (c << 8);
|
||||
else
|
||||
ring[writePtr >> 1] = (ring[writePtr >> 1] & 0xFF00) | c;
|
||||
writePtr = newWritePtr;
|
||||
}
|
||||
PICO_AGB_PRINT_ARM9_WRITE_PTR = writePtr;
|
||||
}
|
||||
11
common/logger/PicoAgbAdapterOutputStream.h
Normal file
11
common/logger/PicoAgbAdapterOutputStream.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "IOutputStream.h"
|
||||
|
||||
class PicoAgbAdapterOutputStream : public IOutputStream
|
||||
{
|
||||
public:
|
||||
PicoAgbAdapterOutputStream() { }
|
||||
|
||||
void Write(const char* str) override;
|
||||
void Flush() override { }
|
||||
};
|
||||
44
common/moduleParams.h
Normal file
44
common/moduleParams.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#define MODULE_PARAMS_NTR_MAGIC_LE 0x2106C0DE
|
||||
#define MODULE_PARAMS_NTR_MAGIC_BE 0xDEC00621
|
||||
|
||||
#define MODULE_PARAMS_TWL_MAGIC_LE 0x6314C0DE
|
||||
#define MODULE_PARAMS_TWL_MAGIC_BE 0xDEC01463
|
||||
|
||||
struct module_params_ntr_t
|
||||
{
|
||||
u32 autoloadListStart;
|
||||
u32 autoloadListEnd;
|
||||
u32 autoloadStart;
|
||||
u32 bssStart;
|
||||
u32 bssEnd;
|
||||
u32 compressedEnd;
|
||||
u32 sdkVersion;
|
||||
u32 magicBigEndian; //0xDEC00621
|
||||
u32 magicLittleEndian; //0x2106C0DE
|
||||
};
|
||||
|
||||
// for the twl binaries of a hybrid or limited rom
|
||||
struct module_params_twl_t
|
||||
{
|
||||
u32 autoloadListStart;
|
||||
u32 autoloadListEnd;
|
||||
u32 autoloadStart;
|
||||
u32 compressedEnd;
|
||||
u32 magicBigEndian; //0xDEC01463
|
||||
u32 magicLittleEndian; //0x6314C0DE
|
||||
};
|
||||
|
||||
// only on sdk 5
|
||||
struct build_params_t
|
||||
{
|
||||
u32 reserved0[4];
|
||||
u8 buildCode;
|
||||
u8 sdkTarget;
|
||||
u8 reserved1[2];
|
||||
u8 version;
|
||||
u8 reserved2[3];
|
||||
u32 magicBigEndian; //0xDEC08133
|
||||
u32 magicLittleEndian; //0x3381C0DE
|
||||
};
|
||||
144
common/ndsHeader.h
Normal file
144
common/ndsHeader.h
Normal file
@@ -0,0 +1,144 @@
|
||||
#pragma once
|
||||
#include <nds/ndstypes.h>
|
||||
|
||||
struct nds_header_ntr_t
|
||||
{
|
||||
u8 gameTitle[12];
|
||||
u32 gameCode;
|
||||
u8 makerCode[2];
|
||||
u8 unitCode;
|
||||
u8 encryptionSeedSelect;
|
||||
u8 deviceCapacity;
|
||||
u8 gap15[7];
|
||||
u8 twlFlags;
|
||||
u8 flags;
|
||||
u8 softwareVersion;
|
||||
u8 flags2;
|
||||
u32 arm9RomOffset;
|
||||
u32 arm9EntryAddress;
|
||||
u32 arm9LoadAddress;
|
||||
u32 arm9Size;
|
||||
u32 arm7RomOffset;
|
||||
u32 arm7EntryAddress;
|
||||
u32 arm7LoadAddress;
|
||||
u32 arm7Size;
|
||||
u32 fntOffset;
|
||||
u32 fntSize;
|
||||
u32 fatOffset;
|
||||
u32 fatSize;
|
||||
u32 arm9OverlayTableOffset;
|
||||
u32 arm9OverlayTableSize;
|
||||
u32 arm7OverlayTableOffset;
|
||||
u32 arm7OverlayTableSize;
|
||||
u32 normalModeRomControl;
|
||||
u32 secureModeRomControl;
|
||||
u32 bannerOffset;
|
||||
u16 secureAreaCrc;
|
||||
u16 secureDelay;
|
||||
u32 arm9AutoLoadDoneHookAddress;
|
||||
u32 arm7AutoLoadDoneHookAddress;
|
||||
u8 secureAreaDisable[8];
|
||||
u32 ntrRomSize;
|
||||
u32 romHeaderSize;
|
||||
u32 arm9ModuleParamsAddress;
|
||||
u32 arm7ModuleParamsAddress;
|
||||
u16 ntrRegionEnd;
|
||||
u16 twlRegionStart;
|
||||
u16 nandRomRegionEnd;
|
||||
u16 nandBackupRegionStart;
|
||||
u8 gap98[0x28];
|
||||
u8 nintendoLogo[0x9C];
|
||||
u16 nintendoLogoCrc;
|
||||
u16 headerCrc;
|
||||
u32 debugRomOffset;
|
||||
u32 debugRomSize;
|
||||
u32 debugRomLoadAddress; // and arm9 entry
|
||||
u32 debugRomArm7EntryAddress;
|
||||
|
||||
constexpr bool IsTwlRom() const
|
||||
{
|
||||
return unitCode & 2;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(nds_header_ntr_t) == 0x170, "Invalid size for nds_header_ntr_t");
|
||||
|
||||
struct nds_header_twl_t
|
||||
{
|
||||
nds_header_ntr_t ntrHeader;
|
||||
u8 gap170[0x10];
|
||||
u32 globalMbkSettings[5]; // slot mapping
|
||||
u32 arm9MbkSettings[3]; // wram mapping
|
||||
u32 arm7MbkSettings[3]; // wram mapping
|
||||
u8 mbk9Setting[3];
|
||||
u8 wramCntSetting;
|
||||
u32 regionFlags;
|
||||
u32 accessControl;
|
||||
u32 arm7ScfgExt7;
|
||||
u8 gap1B8[3];
|
||||
u8 twlFlags2;
|
||||
u32 arm9iRomOffset;
|
||||
u8 gap1C4[4];
|
||||
u32 arm9iLoadAddress;
|
||||
u32 arm9iSize;
|
||||
u32 arm7iRomOffset;
|
||||
u32 arm7DeviceListAddress;
|
||||
u32 arm7iLoadAddress;
|
||||
u32 arm7iSize;
|
||||
u32 ntrDigestRegionOffset;
|
||||
u32 ntrDigestRegionSize;
|
||||
u32 twlDigestRegionOffset;
|
||||
u32 twlDigestRegionSize;
|
||||
u32 digestSectorHashtableOffset;
|
||||
u32 digestSectorHashtableSize;
|
||||
u32 digestBlockHashtableOffset;
|
||||
u32 digestBlockHashtableSize;
|
||||
u32 digestSectorSize;
|
||||
u32 digestSectorsPerBlock;
|
||||
u32 bannerSize;
|
||||
u8 shared2File0Size;
|
||||
u8 shared2File1Size;
|
||||
u8 eulaVersion;
|
||||
u8 twlManagementFlags;
|
||||
u32 totalTwlRomSize; // can be 0
|
||||
u8 shared2File2Size;
|
||||
u8 shared2File3Size;
|
||||
u8 shared2File4Size;
|
||||
u8 shared2File5Size;
|
||||
u32 arm9iModuleParamsAddress;
|
||||
u32 arm7iModuleParamsAddress;
|
||||
u32 modcryptArea1Offset;
|
||||
u32 modcryptArea1Size;
|
||||
u32 modcryptArea2Offset;
|
||||
u32 modcryptArea2Size;
|
||||
u64 titleId;
|
||||
u32 twlPublicSavSize;
|
||||
u32 twlPrivateSavSize;
|
||||
u8 gap240[0xB0];
|
||||
u8 parentalControlRatings[0x10];
|
||||
u8 arm9Sha1Hmac[0x14];
|
||||
u8 arm7Sha1Hmac[0x14];
|
||||
u8 digestMasterSha1Hmac[0x14];
|
||||
u8 bannerSha1Hmac[0x14];
|
||||
u8 arm9iSha1Hmac[0x14];
|
||||
u8 arm7iSha1Hmac[0x14];
|
||||
u8 ntrHeaderArm9Arm7Sha1Hmac[0x14]; // whitelist phase 1
|
||||
u8 ntrArm9OvtOverlaysFatSha1Hmac[0x14]; // whitelist phase 2
|
||||
u8 arm9WithoutSecureAreaSha1Hmac[0x14];
|
||||
u8 gap3B4[0xA4C];
|
||||
u8 debugArguments[0x100];
|
||||
u8 gapF00[0x80];
|
||||
u8 headerRsaSha1Signature[0x80];
|
||||
|
||||
constexpr bool IsTwlRom() const
|
||||
{
|
||||
return ntrHeader.IsTwlRom();
|
||||
}
|
||||
|
||||
constexpr bool IsDsiWare() const
|
||||
{
|
||||
return IsTwlRom() && ((titleId >> 32) & 0xFF) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(nds_header_twl_t) == 0x1000, "Invalid size for nds_header_twl_t");
|
||||
39
common/ndsabi/macros.inc
Normal file
39
common/ndsabi/macros.inc
Normal file
@@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: Zlib
|
||||
// SPDX-FileNotice: Modified from the original version by the BlocksDS project.
|
||||
//
|
||||
// Copyright (C) 2021-2023 agbabi contributors
|
||||
//
|
||||
// ARM assembly support macros
|
||||
|
||||
@ Shift and test upper two bits, clobbering \reg
|
||||
@ Use mi for first bit, cs for second bit
|
||||
.macro joaobapt_test_lsl reg shift = #0
|
||||
movs \reg, \reg, lsl \shift
|
||||
.endm
|
||||
|
||||
@ Test lowest two bits, clobbering \reg
|
||||
@ Use mi for low bit, cs for high bit
|
||||
.macro joaobapt_test reg
|
||||
joaobapt_test_lsl \reg, #31
|
||||
.endm
|
||||
|
||||
@ Test lowest two bits of \src, result stored in \dst
|
||||
@ Use mi for low bit, cs for high bit
|
||||
.macro joaobapt_test_into dst, src
|
||||
movs \dst, \src, lsl #31
|
||||
.endm
|
||||
|
||||
@ Branches depending on lowest two bits, clobbering \reg
|
||||
@ b_mi = low bit case, b_cs = high bit case
|
||||
.macro joaobapt_switch reg, b_mi, b_cs
|
||||
joaobapt_test \reg
|
||||
bmi \b_mi
|
||||
bcs \b_cs
|
||||
.endm
|
||||
|
||||
@ Branches depending on alignment of \a and \b, clobbering \scratch
|
||||
@ b_byte = off-by-byte case, b_half = off-by-half case
|
||||
.macro align_switch a, b, scratch, b_byte, b_half
|
||||
eor \scratch, \a, \b
|
||||
joaobapt_switch \scratch, \b_byte, \b_half
|
||||
.endm
|
||||
126
common/ndsabi/memcpy.s
Normal file
126
common/ndsabi/memcpy.s
Normal file
@@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: Zlib
|
||||
// SPDX-FileNotice: Modified from the original version by the BlocksDS project.
|
||||
//
|
||||
// Copyright (C) 2021-2023 agbabi contributors
|
||||
//
|
||||
// ABI:
|
||||
// __aeabi_memcpy, __aeabi_memcpy4, __aeabi_memcpy8
|
||||
// Standard:
|
||||
// memcpy
|
||||
// Support:
|
||||
// __ndsabi_memcpy2, __ndsabi_memcpy1
|
||||
|
||||
#include <nds/asminc.h>
|
||||
|
||||
#include "macros.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.arm
|
||||
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __aeabi_memcpy
|
||||
|
||||
@ >6-bytes is roughly the threshold when byte-by-byte copy is slower
|
||||
cmp r2, #6
|
||||
ble __ndsabi_memcpy1
|
||||
|
||||
align_switch r0, r1, r3, __ndsabi_memcpy1, .Lcopy_halves
|
||||
|
||||
@ Check if r0 (or r1) needs word aligning
|
||||
rsbs r3, r0, #4
|
||||
joaobapt_test r3
|
||||
|
||||
@ Copy byte head to align
|
||||
ldrbmi r3, [r1], #1
|
||||
strbmi r3, [r0], #1
|
||||
submi r2, r2, #1
|
||||
@ r0, r1 are now half aligned
|
||||
|
||||
@ Copy half head to align
|
||||
ldrhcs r3, [r1], #2
|
||||
strhcs r3, [r0], #2
|
||||
subcs r2, r2, #2
|
||||
@ r0, r1 are now word aligned
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC_NO_SECTION __aeabi_memcpy8
|
||||
BEGIN_ASM_FUNC_NO_SECTION __aeabi_memcpy4
|
||||
|
||||
cmp r2, #32
|
||||
blt .Lcopy_words
|
||||
|
||||
@ Word aligned, 32-byte copy
|
||||
push {r4-r10}
|
||||
.Lloop_32:
|
||||
subs r2, r2, #32
|
||||
ldmiage r1!, {r3-r10}
|
||||
stmiage r0!, {r3-r10}
|
||||
bgt .Lloop_32
|
||||
pop {r4-r10}
|
||||
bxeq lr
|
||||
|
||||
@ < 32 bytes remaining to be copied
|
||||
add r2, r2, #32
|
||||
|
||||
.Lcopy_words:
|
||||
cmp r2, #4
|
||||
blt .Lcopy_halves
|
||||
.Lloop_4:
|
||||
subs r2, r2, #4
|
||||
ldrge r3, [r1], #4
|
||||
strge r3, [r0], #4
|
||||
bgt .Lloop_4
|
||||
bxeq lr
|
||||
|
||||
@ Copy byte & half tail
|
||||
@ This test still works when r2 is negative
|
||||
joaobapt_test r2
|
||||
@ Copy half
|
||||
ldrhcs r3, [r1], #2
|
||||
strhcs r3, [r0], #2
|
||||
@ Copy byte
|
||||
ldrbmi r3, [r1]
|
||||
strbmi r3, [r0]
|
||||
bx lr
|
||||
|
||||
.Lcopy_halves:
|
||||
@ Copy byte head to align
|
||||
tst r0, #1
|
||||
ldrbne r3, [r1], #1
|
||||
strbne r3, [r0], #1
|
||||
subne r2, r2, #1
|
||||
@ r0, r1 are now half aligned
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC_NO_SECTION __ndsabi_memcpy2
|
||||
|
||||
subs r2, r2, #2
|
||||
ldrhge r3, [r1], #2
|
||||
strhge r3, [r0], #2
|
||||
bgt __ndsabi_memcpy2
|
||||
bxeq lr
|
||||
|
||||
@ Copy byte tail
|
||||
adds r2, r2, #2
|
||||
ldrbne r3, [r1]
|
||||
strbne r3, [r0]
|
||||
bx lr
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __ndsabi_memcpy1
|
||||
|
||||
subs r2, r2, #1
|
||||
ldrbge r3, [r1], #1
|
||||
strbge r3, [r0], #1
|
||||
bgt __ndsabi_memcpy1
|
||||
bx lr
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC memcpy
|
||||
|
||||
push {r0, lr}
|
||||
bl __aeabi_memcpy
|
||||
pop {r0, lr}
|
||||
bx lr
|
||||
45
common/ndsabi/memmove.s
Normal file
45
common/ndsabi/memmove.s
Normal file
@@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: Zlib
|
||||
// SPDX-FileNotice: Modified from the original version by the BlocksDS project.
|
||||
//
|
||||
// Copyright (C) 2021-2023 agbabi contributors
|
||||
//
|
||||
// ABI:
|
||||
// __aeabi_memmove, __aeabi_memmove4, __aeabi_memmove8
|
||||
// Standard:
|
||||
// memmove
|
||||
|
||||
#include <nds/asminc.h>
|
||||
|
||||
.syntax unified
|
||||
|
||||
.arm
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __aeabi_memmove
|
||||
|
||||
cmp r0, r1
|
||||
bgt __ndsabi_rmemcpy
|
||||
b __aeabi_memcpy
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __aeabi_memmove8
|
||||
BEGIN_ASM_FUNC_NO_SECTION __aeabi_memmove4
|
||||
|
||||
cmp r0, r1
|
||||
bgt __ndsabi_rmemcpy
|
||||
b __aeabi_memcpy4
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __ndsabi_memmove1
|
||||
|
||||
cmp r0, r1
|
||||
bgt __ndsabi_rmemcpy1
|
||||
b __ndsabi_memcpy1
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC memmove
|
||||
|
||||
push {r0, lr}
|
||||
bl __aeabi_memmove
|
||||
pop {r0, lr}
|
||||
bx lr
|
||||
120
common/ndsabi/memset.s
Normal file
120
common/ndsabi/memset.s
Normal file
@@ -0,0 +1,120 @@
|
||||
// SPDX-License-Identifier: Zlib
|
||||
// SPDX-FileNotice: Modified from the original version by the BlocksDS project.
|
||||
//
|
||||
// Copyright (C) 2021-2023 agbabi contributors
|
||||
//
|
||||
// ABI:
|
||||
// __aeabi_memclr, __aeabi_memclr4, __aeabi_memclr8,
|
||||
// __aeabi_memset, __aeabi_memset4, __aeabi_memset8
|
||||
// Standard:
|
||||
// memset
|
||||
// Support:
|
||||
// __ndsabi_wordset4, __ndsabi_lwordset4, __ndsabi_memset1
|
||||
|
||||
#include <nds/asminc.h>
|
||||
|
||||
#include "macros.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.arm
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __aeabi_memclr
|
||||
|
||||
mov r2, #0
|
||||
b __aeabi_memset
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __aeabi_memclr8
|
||||
BEGIN_ASM_FUNC_NO_SECTION __aeabi_memclr4
|
||||
|
||||
mov r2, #0
|
||||
b __ndsabi_wordset4
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __aeabi_memset
|
||||
|
||||
@ < 8 bytes probably won't be aligned: go byte-by-byte
|
||||
cmp r1, #8
|
||||
blt __ndsabi_memset1
|
||||
|
||||
@ Copy head to align to next word
|
||||
rsb r3, r0, #4
|
||||
joaobapt_test r3
|
||||
strbmi r2, [r0], #1
|
||||
submi r1, r1, #1
|
||||
strbcs r2, [r0], #1
|
||||
strbcs r2, [r0], #1
|
||||
subcs r1, r1, #2
|
||||
|
||||
BEGIN_ASM_FUNC_NO_SECTION __aeabi_memset8
|
||||
BEGIN_ASM_FUNC_NO_SECTION __aeabi_memset4
|
||||
|
||||
lsl r2, r2, #24
|
||||
orr r2, r2, r2, lsr #8
|
||||
orr r2, r2, r2, lsr #16
|
||||
|
||||
BEGIN_ASM_FUNC_NO_SECTION __ndsabi_wordset4
|
||||
|
||||
mov r3, r2
|
||||
|
||||
BEGIN_ASM_FUNC_NO_SECTION __ndsabi_lwordset4
|
||||
|
||||
@ 16 words is roughly the threshold when lwordset is slower
|
||||
cmp r1, #64
|
||||
blt .Lset_2_words
|
||||
|
||||
@ 8 word set
|
||||
push {r4-r9}
|
||||
mov r4, r2
|
||||
mov r5, r3
|
||||
mov r6, r2
|
||||
mov r7, r3
|
||||
mov r8, r2
|
||||
mov r9, r3
|
||||
|
||||
.Lset_8_words:
|
||||
subs r1, r1, #32
|
||||
stmiage r0!, {r2-r9}
|
||||
bgt .Lset_8_words
|
||||
pop {r4-r9}
|
||||
bxeq lr
|
||||
|
||||
@ Fixup remaining
|
||||
add r1, r1, #32
|
||||
.Lset_2_words:
|
||||
subs r1, r1, #8
|
||||
stmiage r0!, {r2-r3}
|
||||
bgt .Lset_2_words
|
||||
bxeq lr
|
||||
|
||||
@ Test for remaining word
|
||||
adds r1, r1, #4
|
||||
strge r2, [r0], #4
|
||||
bxeq lr
|
||||
|
||||
@ Set tail
|
||||
joaobapt_test r1
|
||||
strhcs r2, [r0], #2
|
||||
strbmi r2, [r0], #1
|
||||
bx lr
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __ndsabi_memset1
|
||||
|
||||
subs r1, r1, #1
|
||||
strbge r2, [r0], #1
|
||||
bgt __ndsabi_memset1
|
||||
bx lr
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC memset
|
||||
|
||||
mov r3, r1
|
||||
mov r1, r2
|
||||
mov r2, r3
|
||||
push {r0, lr}
|
||||
bl __aeabi_memset
|
||||
pop {r0, lr}
|
||||
bx lr
|
||||
106
common/ndsabi/rmemcpy.s
Normal file
106
common/ndsabi/rmemcpy.s
Normal file
@@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: Zlib
|
||||
// SPDX-FileNotice: Modified from the original version by the BlocksDS project.
|
||||
//
|
||||
// Copyright (C) 2021-2023 agbabi contributors
|
||||
//
|
||||
// Support:
|
||||
// __ndsabi_rmemcpy, __ndsabi_rmemcpy1
|
||||
|
||||
#include <nds/asminc.h>
|
||||
|
||||
#include "macros.inc"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.arm
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC __ndsabi_rmemcpy
|
||||
|
||||
@ >6-bytes is roughly the threshold when byte-by-byte copy is slower
|
||||
cmp r2, #6
|
||||
ble __ndsabi_rmemcpy1
|
||||
|
||||
align_switch r0, r1, r3, __ndsabi_rmemcpy1, .Lcopy_halves
|
||||
|
||||
@ Check if end needs word aligning
|
||||
add r3, r0, r2
|
||||
joaobapt_test r3
|
||||
|
||||
@ Copy byte tail to align
|
||||
submi r2, r2, #1
|
||||
ldrbmi r3, [r1, r2]
|
||||
strbmi r3, [r0, r2]
|
||||
@ r2 is now half aligned
|
||||
|
||||
@ Copy half tail to align
|
||||
subcs r2, r2, #2
|
||||
ldrhcs r3, [r1, r2]
|
||||
strhcs r3, [r0, r2]
|
||||
@ r2 is now word aligned
|
||||
|
||||
cmp r2, #32
|
||||
blt .Lcopy_words
|
||||
|
||||
@ Word aligned, 32-byte copy
|
||||
push {r0-r1, r4-r10}
|
||||
add r0, r0, r2
|
||||
add r1, r1, r2
|
||||
.Lloop_32:
|
||||
subs r2, r2, #32
|
||||
ldmdbge r1!, {r3-r10}
|
||||
stmdbge r0!, {r3-r10}
|
||||
bgt .Lloop_32
|
||||
pop {r0-r1, r4-r10}
|
||||
bxeq lr
|
||||
|
||||
@ < 32 bytes remaining to be copied
|
||||
add r2, r2, #32
|
||||
|
||||
.Lcopy_words:
|
||||
subs r2, r2, #4
|
||||
ldrge r3, [r1, r2]
|
||||
strge r3, [r0, r2]
|
||||
bgt .Lcopy_words
|
||||
bxeq lr
|
||||
|
||||
@ Copy byte & half head
|
||||
joaobapt_test_into r3, r2
|
||||
@ Copy half
|
||||
addcs r2, r2, #2
|
||||
ldrhcs r3, [r1, r2]
|
||||
strhcs r3, [r0, r2]
|
||||
@ Copy byte
|
||||
ldrbmi r3, [r1]
|
||||
strbmi r3, [r0]
|
||||
bx lr
|
||||
|
||||
.Lcopy_halves:
|
||||
@ Copy byte tail to align
|
||||
add r3, r0, r2
|
||||
tst r3, #1
|
||||
subne r2, r2, #1
|
||||
ldrbne r3, [r1, r2]
|
||||
strbne r3, [r0, r2]
|
||||
@ r2 is now half aligned
|
||||
|
||||
.Lloop_2:
|
||||
subs r2, r2, #2
|
||||
ldrhge r3, [r1, r2]
|
||||
strhge r3, [r0, r2]
|
||||
bgt .Lloop_2
|
||||
bxeq lr
|
||||
|
||||
@ Copy byte head
|
||||
ldrb r3, [r1]
|
||||
strb r3, [r0]
|
||||
bx lr
|
||||
|
||||
|
||||
BEGIN_ASM_FUNC_NO_SECTION __ndsabi_rmemcpy1
|
||||
|
||||
subs r2, r2, #1
|
||||
ldrbge r3, [r1, r2]
|
||||
strbge r3, [r0, r2]
|
||||
bgt __ndsabi_rmemcpy1
|
||||
bx lr
|
||||
9
common/picoAgbAdapter.h
Normal file
9
common/picoAgbAdapter.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define PICO_AGB_PRINT_ARM9_RING ((vu16*)0x08000000)
|
||||
#define PICO_AGB_PRINT_ARM9_READ_PTR (*(vu16*)0x08010000)
|
||||
#define PICO_AGB_PRINT_ARM9_WRITE_PTR (*(vu16*)0x08010002)
|
||||
#define PICO_AGB_PRINT_RING_LENGTH 0x8000
|
||||
|
||||
#define PICO_AGB_IDENTIFIER (*(vu32*)0x08010008)
|
||||
#define PICO_AGB_IDENTIFIER_VALUE 0x4F434950
|
||||
9
common/sections.h
Normal file
9
common/sections.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define DEFINE_SECTION_SYMBOLS(sectionName) \
|
||||
extern u8 __start_##sectionName[]; \
|
||||
extern u8 __stop_##sectionName[]
|
||||
|
||||
#define SECTION_START(sectionName) ((void*)__start_##sectionName)
|
||||
#define SECTION_END(sectionName) ((void*)__stop_##sectionName)
|
||||
#define SECTION_SIZE(sectionName) ((u32)__stop_##sectionName - (u32)__start_##sectionName)
|
||||
98
common/sharedMemory.h
Normal file
98
common/sharedMemory.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
#include <nds/ndstypes.h>
|
||||
|
||||
#define BOOT_TYPE_INVALID 0
|
||||
#define BOOT_TYPE_CARD 1
|
||||
#define BOOT_TYPE_MULTIBOOT 2
|
||||
#define BOOT_TYPE_NAND 3
|
||||
#define BOOT_TYPE_MEMORY 4
|
||||
|
||||
struct shared_memory_multi_boot_info_t
|
||||
{
|
||||
u16 bootType;
|
||||
u8 multibootInfo[0x40 - 2];
|
||||
};
|
||||
|
||||
//0x02FFF800: 2KB
|
||||
struct shared_memory_ntr_t
|
||||
{
|
||||
u8 gap0[0x200];
|
||||
u8 gap200[0x80];
|
||||
u8 cardRomHeader[0x160]; // without debug footer
|
||||
u8 downloadParams[0x20];
|
||||
u8 bootCheckInfo[0x20];
|
||||
u32 resetParam;
|
||||
u8 gap424[8];
|
||||
u32 romOffset;
|
||||
u8 slot2Info[0xC];
|
||||
u32 vblankCounter;
|
||||
shared_memory_multi_boot_info_t multibootInfo;
|
||||
u8 firmwareUserData[0x100];
|
||||
u8 arm9ExceptionStack[0x1C];
|
||||
u32 arm9ExceptionVector;
|
||||
u8 arenaInfo[0x48];
|
||||
u8 rtcData[8];
|
||||
u8 systemConfig[6];
|
||||
u8 arm9Print;
|
||||
u8 arm7Print;
|
||||
u8 arm9ErrorPrint;
|
||||
u8 arm7ErrorPrint;
|
||||
u8 gap1FA[6];
|
||||
u8 romHeader[0x160];
|
||||
u8 isDebuggerData[0x20];
|
||||
u32 arm9IpcSignalParam;
|
||||
u32 arm7IpcSignalParam;
|
||||
u32 arm9IpcHandleChecker;
|
||||
u32 arm7IpcHandleChecker;
|
||||
u32 lastMicrophoneAddress;
|
||||
u16 microphoneSampleData;
|
||||
u16 wifiCallbackControl;
|
||||
u16 wifiRssiPool;
|
||||
u8 setSlot2InfoOnce;
|
||||
u8 slot2Inserted;
|
||||
u32 arm7Param;
|
||||
u32 arm9ThreadInfo;
|
||||
u32 arm7ThreadInfo;
|
||||
u16 padXYBuffer;
|
||||
u8 touchData[4];
|
||||
u16 autoloadSync;
|
||||
u8 arm9LockId[8];
|
||||
u8 arm7LockId[8];
|
||||
u8 vramCLock[8];
|
||||
u8 vramDLock[8];
|
||||
u8 wram0Lock[8];
|
||||
u8 wram1Lock[8];
|
||||
u8 slot1Lock[8];
|
||||
u8 slot2Lock[8];
|
||||
u8 initLock[8];
|
||||
u16 arm9MainMemoryCheck;
|
||||
u16 arm7MainMemoryCheck;
|
||||
u16 mainMemoryCmd;
|
||||
};
|
||||
|
||||
static_assert(sizeof(shared_memory_ntr_t) == 0x800);
|
||||
|
||||
#define NTR_SHARED_MEMORY ((shared_memory_ntr_t*)0x027FF800)
|
||||
#define NTR_SHARED_MEMORY_SDK5 ((shared_memory_ntr_t*)0x02FFF800)
|
||||
|
||||
//0x02FFC000: 16KB
|
||||
struct shared_memory_twl_t
|
||||
{
|
||||
u8 twlCardRomHeader[0x1000];
|
||||
u8 gap1000[0x7B0];
|
||||
char sysMenuVersionInfoContentId[9];
|
||||
char sysMenuVersionInfoContentLastInitialCode;
|
||||
u16 sysMenuDisableSetHotboot;
|
||||
u8 sdNandContext[0x44];
|
||||
u8 titleIdList[0x400];
|
||||
u8 mountInfo[0x3C0];
|
||||
u8 bootSrlPath[0x40];
|
||||
u8 twlRomHeader[0x1000];
|
||||
u8 sharedArena[0x680];
|
||||
u8 gap3680[0x180];
|
||||
shared_memory_ntr_t ntrSharedMem;
|
||||
};
|
||||
|
||||
static_assert(sizeof(shared_memory_twl_t) == 0x4000);
|
||||
|
||||
#define TWL_SHARED_MEMORY ((shared_memory_twl_t*)0x02FFC000)
|
||||
35
common/thumbInstructions.h
Normal file
35
common/thumbInstructions.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#define THUMB_R0 0
|
||||
#define THUMB_R1 1
|
||||
#define THUMB_R2 2
|
||||
#define THUMB_R3 3
|
||||
#define THUMB_R4 4
|
||||
#define THUMB_R5 5
|
||||
#define THUMB_R6 6
|
||||
#define THUMB_R7 7
|
||||
|
||||
#define THUMB_HI_R8 8
|
||||
#define THUMB_HI_R9 9
|
||||
#define THUMB_HI_R10 10
|
||||
#define THUMB_HI_R11 11
|
||||
#define THUMB_HI_R12 12
|
||||
#define THUMB_HI_SP 13
|
||||
#define THUMB_HI_LR 14
|
||||
#define THUMB_HI_PC 15
|
||||
|
||||
#define THUMB_LSLS_IMM(rd, rs, imm) (0x0000 | ((imm) << 6) | ((rs) << 3) | (rd))
|
||||
#define THUMB_ADDS_IMM(rd, rs, imm) (0x1C00 | ((imm) << 6) | ((rs) << 3) | (rd))
|
||||
#define THUMB_SUBS_IMM(rd, rs, imm) (0x1E00 | ((imm) << 6) | ((rs) << 3) | (rd))
|
||||
#define THUMB_MOVS_IMM(rd, imm) (0x2000 | ((rd) << 8) | (imm))
|
||||
#define THUMB_MOVS_REG(rd, rs) THUMB_ADDS_IMM((rd), (rs), 0)
|
||||
#define THUMB_MOV_HIREG(rd, rs) (0x4600 | ((((rd) >> 3) & 1) << 7) | ((rs) << 3) | ((rd) & 7))
|
||||
#define THUMB_NOP THUMB_MOV_HIREG(8, 8)
|
||||
#define THUMB_BX(rs) (0x4700 | ((rs) << 3))
|
||||
#define THUMB_BLX(rs) (0x4780 | ((rs) << 3))
|
||||
#define THUMB_BX_LR THUMB_BX(THUMB_HI_LR)
|
||||
#define THUMB_LDR_PC_IMM(rd, imm) (0x4800 | ((rd) << 8) | (((imm) >> 2) & 0xFF))
|
||||
#define THUMB_STR_IMM(rd, rb, imm) (0x6000 | (((imm) >> 2) << 6) | ((rb) << 3) | (rd))
|
||||
#define THUMB_STR_SP_IMM(rd, imm) (0x9000 | ((rd) << 8) | (((imm) >> 2) & 0xFF))
|
||||
#define THUMB_LDR_SP_IMM(rd, imm) (0x9800 | ((rd) << 8) | (((imm) >> 2) & 0xFF))
|
||||
#define THUMB_SVC(x) (0xDF00 | (x))
|
||||
Reference in New Issue
Block a user