From b03c727fb9525b90163472962bb59713ed535da5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 13 Jun 2019 13:59:11 +0200 Subject: blarg --- src/DSi.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/DSi.h (limited to 'src/DSi.h') diff --git a/src/DSi.h b/src/DSi.h new file mode 100644 index 0000000..6a524dd --- /dev/null +++ b/src/DSi.h @@ -0,0 +1,17 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS 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. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ -- cgit v1.2.3 From 0e421ccebd3ebabfbbabcae96acc262b76198ad2 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 13 Jun 2019 14:41:54 +0200 Subject: add all sorts of shit --- melonDS.cbp | 9 + src/DSi.cpp | 16 ++ src/DSi.h | 14 ++ src/DSiCrypto.h | 7 + src/NDS.cpp | 36 +-- src/NDS.h | 4 +- src/sha1/sha1.c | 276 +++++++++++++++++++++ src/sha1/sha1.h | 17 ++ src/tiny-AES-c/README.md | 80 ++++++ src/tiny-AES-c/aes.c | 572 +++++++++++++++++++++++++++++++++++++++++++ src/tiny-AES-c/aes.h | 90 +++++++ src/tiny-AES-c/aes.hpp | 12 + src/tiny-AES-c/unlicense.txt | 24 ++ 13 files changed, 1141 insertions(+), 16 deletions(-) create mode 100644 src/sha1/sha1.c create mode 100644 src/sha1/sha1.h create mode 100644 src/tiny-AES-c/README.md create mode 100644 src/tiny-AES-c/aes.c create mode 100644 src/tiny-AES-c/aes.h create mode 100644 src/tiny-AES-c/aes.hpp create mode 100644 src/tiny-AES-c/unlicense.txt (limited to 'src/DSi.h') diff --git a/melonDS.cbp b/melonDS.cbp index 59df311..97958f5 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -254,6 +254,15 @@ + + + + + + + diff --git a/src/DSi.cpp b/src/DSi.cpp index 6a524dd..376e6a0 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -15,3 +15,19 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include "DSi.h" +#include "tiny-AES-c/aes.hpp" +#include "sha1/sha1.h" + +namespace DSi +{ + +bool LoadNAND() +{ + // + + return true; +} + +} diff --git a/src/DSi.h b/src/DSi.h index 6a524dd..2c71ad9 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -15,3 +15,17 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#ifndef DSI_H +#define DSI_H + +#include "types.h" + +namespace DSi +{ + +bool LoadNAND(); + +} + +#endif // DSI_H diff --git a/src/DSiCrypto.h b/src/DSiCrypto.h index 6a524dd..dc9bfe6 100644 --- a/src/DSiCrypto.h +++ b/src/DSiCrypto.h @@ -15,3 +15,10 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#ifndef DSICRYPTO_H +#define DSICRYPTO_H + +// + +#endif // DSICRYPTO_H diff --git a/src/NDS.cpp b/src/NDS.cpp index ea34103..f00665e 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -31,6 +31,8 @@ #include "Wifi.h" #include "Platform.h" +#include "DSi.h" + namespace NDS { @@ -83,8 +85,8 @@ u32 SchedListMask; u32 CPUStop; -u8 ARM9BIOS[0x1000]; -u8 ARM7BIOS[0x4000]; +u8 ARM9BIOS[0x10000]; +u8 ARM7BIOS[0x10000]; u8 MainRAM[MAIN_RAM_SIZE]; @@ -387,6 +389,9 @@ void Reset() LastSysClockCycles = 0; + memset(ARM9BIOS, 0, 0x10000); + memset(ARM7BIOS, 0, 0x10000); + f = Platform::OpenLocalFile("bios9.bin", "rb"); if (!f) { @@ -421,6 +426,8 @@ void Reset() fclose(f); } + DSi::LoadNAND(); + // TODO for later: configure this when emulating a DSi ARM9ClockShift = 1; @@ -1566,9 +1573,9 @@ void debug(u32 param) u8 ARM9Read8(u32 addr) { - if ((addr & 0xFFFFF000) == 0xFFFF0000) + if ((addr & 0xFFFF0000) == 0xFFFF0000) { - return *(u8*)&ARM9BIOS[addr & 0xFFF]; + return *(u8*)&ARM9BIOS[addr & 0xFFFF]; } switch (addr & 0xFF000000) @@ -1627,9 +1634,9 @@ u8 ARM9Read8(u32 addr) u16 ARM9Read16(u32 addr) { - if ((addr & 0xFFFFF000) == 0xFFFF0000) + if ((addr & 0xFFFF0000) == 0xFFFF0000) { - return *(u16*)&ARM9BIOS[addr & 0xFFF]; + return *(u16*)&ARM9BIOS[addr & 0xFFFF]; } switch (addr & 0xFF000000) @@ -1688,9 +1695,9 @@ u16 ARM9Read16(u32 addr) u32 ARM9Read32(u32 addr) { - if ((addr & 0xFFFFF000) == 0xFFFF0000) + if ((addr & 0xFFFF0000) == 0xFFFF0000) { - return *(u32*)&ARM9BIOS[addr & 0xFFF]; + return *(u32*)&ARM9BIOS[addr & 0xFFFF]; } switch (addr & 0xFF000000) @@ -1896,9 +1903,10 @@ bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region) u8 ARM7Read8(u32 addr) { - if (addr < 0x00004000) + if (addr < 0x00010000) { - if (ARM7->R[15] >= 0x4000) + // TODO: check the boundary? is it 4000 or higher on regular DS? + if (ARM7->R[15] >= 0x00010000) return 0xFF; if (addr < ARM7BIOSProt && ARM7->R[15] >= ARM7BIOSProt) return 0xFF; @@ -1952,9 +1960,9 @@ u8 ARM7Read8(u32 addr) u16 ARM7Read16(u32 addr) { - if (addr < 0x00004000) + if (addr < 0x00010000) { - if (ARM7->R[15] >= 0x4000) + if (ARM7->R[15] >= 0x00010000) return 0xFFFF; if (addr < ARM7BIOSProt && ARM7->R[15] >= ARM7BIOSProt) return 0xFFFF; @@ -2015,9 +2023,9 @@ u16 ARM7Read16(u32 addr) u32 ARM7Read32(u32 addr) { - if (addr < 0x00004000) + if (addr < 0x00010000) { - if (ARM7->R[15] >= 0x4000) + if (ARM7->R[15] >= 0x00010000) return 0xFFFFFFFF; if (addr < ARM7BIOSProt && ARM7->R[15] >= ARM7BIOSProt) return 0xFFFFFFFF; diff --git a/src/NDS.h b/src/NDS.h index 9b7a10a..e8bb44d 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -117,8 +117,8 @@ extern u16 ExMemCnt[2]; extern u8 ROMSeed0[2*8]; extern u8 ROMSeed1[2*8]; -extern u8 ARM9BIOS[0x1000]; -extern u8 ARM7BIOS[0x4000]; +extern u8 ARM9BIOS[0x10000]; +extern u8 ARM7BIOS[0x10000]; //#define MAIN_RAM_SIZE 0x400000 #define MAIN_RAM_SIZE 0x1000000 diff --git a/src/sha1/sha1.c b/src/sha1/sha1.c new file mode 100644 index 0000000..2c50433 --- /dev/null +++ b/src/sha1/sha1.c @@ -0,0 +1,276 @@ + +/* from valgrind tests */ + +/* ================ sha1.c ================ */ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include +#include /* for u_int*_t */ +#if defined(__sun) +#include "solarisfixes.h" +#endif +#include "sha1.h" + +#ifndef BYTE_ORDER +#if (BSD >= 199103) +# include +#else +#if defined(linux) || defined(__linux__) +# include +#else +#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ +#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ + +#if defined(vax) || defined(ns32000) || defined(sun386) || defined(__i386__) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || \ + defined (BIT_ZERO_ON_LEFT) || defined(m68k) || defined(__sparc) +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif /* linux */ +#endif /* BSD */ +#endif /* BYTE_ORDER */ + +#if defined(__BYTE_ORDER) && !defined(BYTE_ORDER) +#if (__BYTE_ORDER == __LITTLE_ENDIAN) +#define BYTE_ORDER LITTLE_ENDIAN +#else +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif + +#if !defined(BYTE_ORDER) || \ + (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ + BYTE_ORDER != PDP_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ +#error "Undefined or invalid BYTE_ORDER" +#endif + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]) +{ +u_int32_t a, b, c, d, e; +typedef union { + unsigned char c[64]; + u_int32_t l[16]; +} CHAR64LONG16; +#ifdef SHA1HANDSOFF +CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ +CHAR64LONG16* block = (const CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len) +{ +u_int32_t i; +u_int32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len>>29); + j = (j >> 3) & 63; + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +unsigned i; +unsigned char finalcount[8]; +unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + u_int32_t t = context->count[i]; + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t + } +#else + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } +#endif + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) { + c = 0000; + SHA1Update(context, &c, 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} +/* ================ end of sha1.c ================ */ + +#if 0 +#define BUFSIZE 4096 + +int +main(int argc, char **argv) +{ + SHA1_CTX ctx; + unsigned char hash[20], buf[BUFSIZE]; + int i; + + for(i=0;i +100% Public Domain +*/ + +typedef struct { + u_int32_t state[5]; + u_int32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); diff --git a/src/tiny-AES-c/README.md b/src/tiny-AES-c/README.md new file mode 100644 index 0000000..e32e25e --- /dev/null +++ b/src/tiny-AES-c/README.md @@ -0,0 +1,80 @@ +### Tiny AES in C + +This is a small and portable implementation of the AES [ECB](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29), [CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29) and [CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29) encryption algorithms written in C. + +You can override the default key-size of 128 bit with 192 or 256 bit by defining the symbols AES192 or AES256 in `aes.h`. + +The API is very simple and looks like this (I am using C99 ``-style annotated types): + +```C +/* Initialize context calling one of: */ +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); + +/* ... or reset IV at random point: */ +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); + +/* Then start encrypting and decrypting with the functions below: */ +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); + +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); + +/* Same function for encrypting as for decrypting in CTR mode */ +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); +``` + +Note: + * No padding is provided so for CBC and ECB all buffers should be multiples of 16 bytes. For padding [PKCS7](https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7) is recommendable. + * ECB mode is considered unsafe for most uses and is not implemented in streaming mode. If you need this mode, call the function for every block of 16 bytes you need encrypted. See [wikipedia's article on ECB](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_(ECB)) for more details. + +You can choose to use any or all of the modes-of-operations, by defining the symbols CBC, CTR or ECB. See the header file for clarification. + +C++ users should `#include` [aes.hpp](https://github.com/kokke/tiny-AES-c/blob/master/aes.hpp) instead of [aes.h](https://github.com/kokke/tiny-AES-c/blob/master/aes.h) + +There is no built-in error checking or protection from out-of-bounds memory access errors as a result of malicious input. + +The module uses less than 200 bytes of RAM and 1-2K ROM when compiled for ARM, but YMMV depending on which modes are enabled. + +It is one of the smallest implementations in C I've seen yet, but do contact me if you know of something smaller (or have improvements to the code here). + +I've successfully used the code on 64bit x86, 32bit ARM and 8 bit AVR platforms. + + +GCC size output when only CTR mode is compiled for ARM: + + $ arm-none-eabi-gcc -Os -DCBC=0 -DECB=0 -DCTR=1 -c aes.c + $ size aes.o + text data bss dec hex filename + 1343 0 0 1343 53f aes.o + +.. and when compiling for the THUMB instruction set, we end up just below 1K in code size. + + $ arm-none-eabi-gcc -Os -mthumb -DCBC=0 -DECB=0 -DCTR=1 -c aes.c + $ size aes.o + text data bss dec hex filename + 979 0 0 979 3d3 aes.o + + +I am using the Free Software Foundation, ARM GCC compiler: + + $ arm-none-eabi-gcc --version + arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 8-2018-q4-major) 8.2.1 20181213 (release) + Copyright (C) 2018 Free Software Foundation, Inc. + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + + +This implementation is verified against the data in: + +[National Institute of Standards and Technology Special Publication 800-38A 2001 ED](http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf) Appendix F: Example Vectors for Modes of Operation of the AES. + +The other appendices in the document are valuable for implementation details on e.g. padding, generation of IVs and nonces in CTR-mode etc. + + +A heartfelt thank-you to all the nice people out there who have contributed to this project. + + +All material in this repository is in the public domain. diff --git a/src/tiny-AES-c/aes.c b/src/tiny-AES-c/aes.c new file mode 100644 index 0000000..313ff71 --- /dev/null +++ b/src/tiny-AES-c/aes.c @@ -0,0 +1,572 @@ +/* + +This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. +Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. + +The implementation is verified against the test vectors in: + National Institute of Standards and Technology Special Publication 800-38A 2001 ED + +ECB-AES128 +---------- + + plain-text: + 6bc1bee22e409f96e93d7e117393172a + ae2d8a571e03ac9c9eb76fac45af8e51 + 30c81c46a35ce411e5fbc1191a0a52ef + f69f2445df4f9b17ad2b417be66c3710 + + key: + 2b7e151628aed2a6abf7158809cf4f3c + + resulting cipher + 3ad77bb40d7a3660a89ecaf32466ef97 + f5d3d58503b9699de785895a96fdbaaf + 43b1cd7f598ece23881b00e3ed030688 + 7b0c785e27e8ad3f8223207104725dd4 + + +NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) + You should pad the end of the string with zeros if this is not the case. + For AES192/256 the key size is proportionally larger. + +*/ + + +/*****************************************************************************/ +/* Includes: */ +/*****************************************************************************/ +#include +#include // CBC mode, for memset +#include "aes.h" + +/*****************************************************************************/ +/* Defines: */ +/*****************************************************************************/ +// The number of columns comprising a state in AES. This is a constant in AES. Value=4 +#define Nb 4 + +#if defined(AES256) && (AES256 == 1) + #define Nk 8 + #define Nr 14 +#elif defined(AES192) && (AES192 == 1) + #define Nk 6 + #define Nr 12 +#else + #define Nk 4 // The number of 32 bit words in a key. + #define Nr 10 // The number of rounds in AES Cipher. +#endif + +// jcallan@github points out that declaring Multiply as a function +// reduces code size considerably with the Keil ARM compiler. +// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 +#ifndef MULTIPLY_AS_A_FUNCTION + #define MULTIPLY_AS_A_FUNCTION 0 +#endif + + + + +/*****************************************************************************/ +/* Private variables: */ +/*****************************************************************************/ +// state - array holding the intermediate results during decryption. +typedef uint8_t state_t[4][4]; + + + +// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM +// The numbers below can be computed dynamically trading ROM for RAM - +// This can be useful in (embedded) bootloader applications, where ROM is often limited. +static const uint8_t sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + +static const uint8_t rsbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; + +// The round constant word array, Rcon[i], contains the values given by +// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; + +/* + * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), + * that you can remove most of the elements in the Rcon array, because they are unused. + * + * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon + * + * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), + * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." + */ + + +/*****************************************************************************/ +/* Private functions: */ +/*****************************************************************************/ +/* +static uint8_t getSBoxValue(uint8_t num) +{ + return sbox[num]; +} +*/ +#define getSBoxValue(num) (sbox[(num)]) +/* +static uint8_t getSBoxInvert(uint8_t num) +{ + return rsbox[num]; +} +*/ +#define getSBoxInvert(num) (rsbox[(num)]) + +// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. +static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +{ + unsigned i, j, k; + uint8_t tempa[4]; // Used for the column/row operations + + // The first round key is the key itself. + for (i = 0; i < Nk; ++i) + { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + // All other round keys are found from the previous round keys. + for (i = Nk; i < Nb * (Nr + 1); ++i) + { + { + k = (i - 1) * 4; + tempa[0]=RoundKey[k + 0]; + tempa[1]=RoundKey[k + 1]; + tempa[2]=RoundKey[k + 2]; + tempa[3]=RoundKey[k + 3]; + + } + + if (i % Nk == 0) + { + // This function shifts the 4 bytes in a word to the left once. + // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] + + // Function RotWord() + { + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + } + + // SubWord() is a function that takes a four-byte input word and + // applies the S-box to each of the four bytes to produce an output word. + + // Function Subword() + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + + tempa[0] = tempa[0] ^ Rcon[i/Nk]; + } +#if defined(AES256) && (AES256 == 1) + if (i % Nk == 4) + { + // Function Subword() + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + } +#endif + j = i * 4; k=(i - Nk) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) +{ + KeyExpansion(ctx->RoundKey, key); +} +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) +{ + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} +#endif + +// This function adds the round key to state. +// The round key is added to the state by an XOR function. +static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) +{ + uint8_t i,j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; + } + } +} + +// The SubBytes Function Substitutes the values in the +// state matrix with values in an S-box. +static void SubBytes(state_t* state) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxValue((*state)[j][i]); + } + } +} + +// The ShiftRows() function shifts the rows in the state to the left. +// Each row is shifted with different offset. +// Offset = Row number. So the first row is not shifted. +static void ShiftRows(state_t* state) +{ + uint8_t temp; + + // Rotate first row 1 columns to left + temp = (*state)[0][1]; + (*state)[0][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[3][1]; + (*state)[3][1] = temp; + + // Rotate second row 2 columns to left + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to left + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[3][3]; + (*state)[3][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[1][3]; + (*state)[1][3] = temp; +} + +static uint8_t xtime(uint8_t x) +{ + return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); +} + +// MixColumns function mixes the columns of the state matrix +static void MixColumns(state_t* state) +{ + uint8_t i; + uint8_t Tmp, Tm, t; + for (i = 0; i < 4; ++i) + { + t = (*state)[i][0]; + Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; + Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; + Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; + Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; + Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; + } +} + +// Multiply is used to multiply numbers in the field GF(2^8) +// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary +// The compiler seems to be able to vectorize the operation better this way. +// See https://github.com/kokke/tiny-AES-c/pull/34 +#if MULTIPLY_AS_A_FUNCTION +static uint8_t Multiply(uint8_t x, uint8_t y) +{ + return (((y & 1) * x) ^ + ((y>>1 & 1) * xtime(x)) ^ + ((y>>2 & 1) * xtime(xtime(x))) ^ + ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ + ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ + } +#else +#define Multiply(x, y) \ + ( ((y & 1) * x) ^ \ + ((y>>1 & 1) * xtime(x)) ^ \ + ((y>>2 & 1) * xtime(xtime(x))) ^ \ + ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ + ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ + +#endif + +#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) +// MixColumns function mixes the columns of the state matrix. +// The method used to multiply may be difficult to understand for the inexperienced. +// Please use the references to gain more information. +static void InvMixColumns(state_t* state) +{ + int i; + uint8_t a, b, c, d; + for (i = 0; i < 4; ++i) + { + a = (*state)[i][0]; + b = (*state)[i][1]; + c = (*state)[i][2]; + d = (*state)[i][3]; + + (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); + (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); + (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); + (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); + } +} + + +// The SubBytes Function Substitutes the values in the +// state matrix with values in an S-box. +static void InvSubBytes(state_t* state) +{ + uint8_t i, j; + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxInvert((*state)[j][i]); + } + } +} + +static void InvShiftRows(state_t* state) +{ + uint8_t temp; + + // Rotate first row 1 columns to right + temp = (*state)[3][1]; + (*state)[3][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[0][1]; + (*state)[0][1] = temp; + + // Rotate second row 2 columns to right + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to right + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[1][3]; + (*state)[1][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[3][3]; + (*state)[3][3] = temp; +} +#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) + +// Cipher is the main function that encrypts the PlainText. +static void Cipher(state_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // Add the First round key to the state before starting the rounds. + AddRoundKey(0, state, RoundKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr-1 rounds are executed in the loop below. + for (round = 1; round < Nr; ++round) + { + SubBytes(state); + ShiftRows(state); + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + + // The last round is given below. + // The MixColumns function is not here in the last round. + SubBytes(state); + ShiftRows(state); + AddRoundKey(Nr, state, RoundKey); +} + +#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) +static void InvCipher(state_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + // Add the First round key to the state before starting the rounds. + AddRoundKey(Nr, state, RoundKey); + + // There will be Nr rounds. + // The first Nr-1 rounds are identical. + // These Nr-1 rounds are executed in the loop below. + for (round = (Nr - 1); round > 0; --round) + { + InvShiftRows(state); + InvSubBytes(state); + AddRoundKey(round, state, RoundKey); + InvMixColumns(state); + } + + // The last round is given below. + // The MixColumns function is not here in the last round. + InvShiftRows(state); + InvSubBytes(state); + AddRoundKey(0, state, RoundKey); +} +#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) + +/*****************************************************************************/ +/* Public functions: */ +/*****************************************************************************/ +#if defined(ECB) && (ECB == 1) + + +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + // The next function call encrypts the PlainText with the Key using AES algorithm. + Cipher((state_t*)buf, ctx->RoundKey); +} + +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) +{ + // The next function call decrypts the PlainText with the Key using AES algorithm. + InvCipher((state_t*)buf, ctx->RoundKey); +} + + +#endif // #if defined(ECB) && (ECB == 1) + + + + + +#if defined(CBC) && (CBC == 1) + + +static void XorWithIv(uint8_t* buf, const uint8_t* Iv) +{ + uint8_t i; + for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size + { + buf[i] ^= Iv[i]; + } +} + +void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length) +{ + uintptr_t i; + uint8_t *Iv = ctx->Iv; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + XorWithIv(buf, Iv); + Cipher((state_t*)buf, ctx->RoundKey); + Iv = buf; + buf += AES_BLOCKLEN; + //printf("Step %d - %d", i/16, i); + } + /* store Iv in ctx for next call */ + memcpy(ctx->Iv, Iv, AES_BLOCKLEN); +} + +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) +{ + uintptr_t i; + uint8_t storeNextIv[AES_BLOCKLEN]; + for (i = 0; i < length; i += AES_BLOCKLEN) + { + memcpy(storeNextIv, buf, AES_BLOCKLEN); + InvCipher((state_t*)buf, ctx->RoundKey); + XorWithIv(buf, ctx->Iv); + memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); + buf += AES_BLOCKLEN; + } + +} + +#endif // #if defined(CBC) && (CBC == 1) + + + +#if defined(CTR) && (CTR == 1) + +/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) +{ + uint8_t buffer[AES_BLOCKLEN]; + + unsigned i; + int bi; + for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) + { + if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ + { + + memcpy(buffer, ctx->Iv, AES_BLOCKLEN); + Cipher((state_t*)buffer,ctx->RoundKey); + + /* Increment Iv and handle overflow */ + for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) + { + /* inc will overflow */ + if (ctx->Iv[bi] == 255) + { + ctx->Iv[bi] = 0; + continue; + } + ctx->Iv[bi] += 1; + break; + } + bi = 0; + } + + buf[i] = (buf[i] ^ buffer[bi]); + } +} + +#endif // #if defined(CTR) && (CTR == 1) + diff --git a/src/tiny-AES-c/aes.h b/src/tiny-AES-c/aes.h new file mode 100644 index 0000000..87f1471 --- /dev/null +++ b/src/tiny-AES-c/aes.h @@ -0,0 +1,90 @@ +#ifndef _AES_H_ +#define _AES_H_ + +#include + +// #define the macros below to 1/0 to enable/disable the mode of operation. +// +// CBC enables AES encryption in CBC-mode of operation. +// CTR enables encryption in counter-mode. +// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. + +// The #ifndef-guard allows it to be configured before #include'ing or at compile time. +#ifndef CBC + #define CBC 1 +#endif + +#ifndef ECB + #define ECB 1 +#endif + +#ifndef CTR + #define CTR 1 +#endif + + +#define AES128 1 +//#define AES192 1 +//#define AES256 1 + +#define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only + +#if defined(AES256) && (AES256 == 1) + #define AES_KEYLEN 32 + #define AES_keyExpSize 240 +#elif defined(AES192) && (AES192 == 1) + #define AES_KEYLEN 24 + #define AES_keyExpSize 208 +#else + #define AES_KEYLEN 16 // Key length in bytes + #define AES_keyExpSize 176 +#endif + +struct AES_ctx +{ + uint8_t RoundKey[AES_keyExpSize]; +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) + uint8_t Iv[AES_BLOCKLEN]; +#endif +}; + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); +#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); +#endif + +#if defined(ECB) && (ECB == 1) +// buffer size is exactly AES_BLOCKLEN bytes; +// you need only AES_init_ctx as IV is not used in ECB +// NB: ECB is considered insecure for most uses +void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); +void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); + +#endif // #if defined(ECB) && (ECB == !) + + +#if defined(CBC) && (CBC == 1) +// buffer size MUST be mutile of AES_BLOCKLEN; +// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme +// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() +// no IV should ever be reused with the same key +void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); +void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); + +#endif // #if defined(CBC) && (CBC == 1) + + +#if defined(CTR) && (CTR == 1) + +// Same function for encrypting as for decrypting. +// IV is incremented for every block, and used after encryption as XOR-compliment for output +// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme +// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() +// no IV should ever be reused with the same key +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); + +#endif // #if defined(CTR) && (CTR == 1) + + +#endif //_AES_H_ diff --git a/src/tiny-AES-c/aes.hpp b/src/tiny-AES-c/aes.hpp new file mode 100644 index 0000000..ade1642 --- /dev/null +++ b/src/tiny-AES-c/aes.hpp @@ -0,0 +1,12 @@ +#ifndef _AES_HPP_ +#define _AES_HPP_ + +#ifndef __cplusplus +#error Do not include the hpp header in a c project! +#endif //__cplusplus + +extern "C" { +#include "aes.h" +} + +#endif //_AES_HPP_ diff --git a/src/tiny-AES-c/unlicense.txt b/src/tiny-AES-c/unlicense.txt new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/src/tiny-AES-c/unlicense.txt @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to -- cgit v1.2.3 From 83d23939db58a3d59d97e26c7dc3cfd9ea7927d9 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Jun 2019 13:09:11 +0200 Subject: melonDSi: skeleton in place --- src/ARM.h | 31 +++-- src/CP15.cpp | 31 +++-- src/DSi.cpp | 393 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/DSi.h | 33 +++++ src/NDS.cpp | 65 +++++----- src/sha1/sha1.c | 17 +-- src/sha1/sha1.h | 10 +- 7 files changed, 518 insertions(+), 62 deletions(-) (limited to 'src/DSi.h') diff --git a/src/ARM.h b/src/ARM.h index d13d535..6b6e330 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -23,6 +23,7 @@ #include "types.h" #include "NDS.h" +#include "DSi.h" #define ROR(x, n) (((x) >> (n)) | ((x) << (32-(n)))) @@ -271,17 +272,20 @@ public: u16 CodeRead16(u32 addr) { - return NDS::ARM7Read16(addr); + //return NDS::ARM7Read16(addr); + return DSi::ARM7Read16(addr); } u32 CodeRead32(u32 addr) { - return NDS::ARM7Read32(addr); + //return NDS::ARM7Read32(addr); + return DSi::ARM7Read32(addr); } void DataRead8(u32 addr, u32* val) { - *val = NDS::ARM7Read8(addr); + *val = DSi::ARM7Read8(addr); + //*val = NDS::ARM7Read8(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -290,7 +294,8 @@ public: { addr &= ~1; - *val = NDS::ARM7Read16(addr); + *val = DSi::ARM7Read16(addr); + //*val = NDS::ARM7Read16(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -299,7 +304,8 @@ public: { addr &= ~3; - *val = NDS::ARM7Read32(addr); + *val = DSi::ARM7Read32(addr); + //*val = NDS::ARM7Read32(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][2]; } @@ -308,13 +314,15 @@ public: { addr &= ~3; - *val = NDS::ARM7Read32(addr); + *val = DSi::ARM7Read32(addr); + //*val = NDS::ARM7Read32(addr); DataCycles += NDS::ARM7MemTimings[DataRegion][3]; } void DataWrite8(u32 addr, u8 val) { - NDS::ARM7Write8(addr, val); + DSi::ARM7Write8(addr, val); + //NDS::ARM7Write8(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -323,7 +331,8 @@ public: { addr &= ~1; - NDS::ARM7Write16(addr, val); + DSi::ARM7Write16(addr, val); + //NDS::ARM7Write16(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -332,7 +341,8 @@ public: { addr &= ~3; - NDS::ARM7Write32(addr, val); + DSi::ARM7Write32(addr, val); + //NDS::ARM7Write32(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][2]; } @@ -341,7 +351,8 @@ public: { addr &= ~3; - NDS::ARM7Write32(addr, val); + DSi::ARM7Write32(addr, val); + //NDS::ARM7Write32(addr, val); DataCycles += NDS::ARM7MemTimings[DataRegion][3]; } diff --git a/src/CP15.cpp b/src/CP15.cpp index a4db5f3..4654a2a 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -19,6 +19,7 @@ #include #include #include "NDS.h" +#include "DSi.h" #include "ARM.h" @@ -680,7 +681,8 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch) if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask]; - return NDS::ARM9Read32(addr); + //return NDS::ARM9Read32(addr); + return DSi::ARM9Read32(addr); } @@ -699,7 +701,8 @@ void ARMv5::DataRead8(u32 addr, u32* val) return; } - *val = NDS::ARM9Read8(addr); + *val = DSi::ARM9Read8(addr); + //*val = NDS::ARM9Read8(addr); DataCycles = MemTimings[addr >> 12][1]; } @@ -720,7 +723,8 @@ void ARMv5::DataRead16(u32 addr, u32* val) return; } - *val = NDS::ARM9Read16(addr); + *val = DSi::ARM9Read16(addr); + //*val = NDS::ARM9Read16(addr); DataCycles = MemTimings[addr >> 12][1]; } @@ -741,7 +745,8 @@ void ARMv5::DataRead32(u32 addr, u32* val) return; } - *val = NDS::ARM9Read32(addr); + *val = DSi::ARM9Read32(addr); + //*val = NDS::ARM9Read32(addr); DataCycles = MemTimings[addr >> 12][2]; } @@ -762,7 +767,8 @@ void ARMv5::DataRead32S(u32 addr, u32* val) return; } - *val = NDS::ARM9Read32(addr); + *val = DSi::ARM9Read32(addr); + //*val = NDS::ARM9Read32(addr); DataCycles += MemTimings[addr >> 12][3]; } @@ -781,7 +787,8 @@ void ARMv5::DataWrite8(u32 addr, u8 val) return; } - NDS::ARM9Write8(addr, val); + DSi::ARM9Write8(addr, val); + //NDS::ARM9Write8(addr, val); DataCycles = MemTimings[addr >> 12][1]; } @@ -802,7 +809,8 @@ void ARMv5::DataWrite16(u32 addr, u16 val) return; } - NDS::ARM9Write16(addr, val); + DSi::ARM9Write16(addr, val); + //NDS::ARM9Write16(addr, val); DataCycles = MemTimings[addr >> 12][1]; } @@ -823,7 +831,8 @@ void ARMv5::DataWrite32(u32 addr, u32 val) return; } - NDS::ARM9Write32(addr, val); + DSi::ARM9Write32(addr, val); + //NDS::ARM9Write32(addr, val); DataCycles = MemTimings[addr >> 12][2]; } @@ -844,7 +853,8 @@ void ARMv5::DataWrite32S(u32 addr, u32 val) return; } - NDS::ARM9Write32(addr, val); + DSi::ARM9Write32(addr, val); + //NDS::ARM9Write32(addr, val); DataCycles += MemTimings[addr >> 12][3]; } @@ -857,6 +867,7 @@ void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region) return; }*/ - NDS::ARM9GetMemRegion(addr, false, &CodeMem); + DSi::ARM9GetMemRegion(addr, false, &CodeMem); + //NDS::ARM9GetMemRegion(addr, false, &CodeMem); } diff --git a/src/DSi.cpp b/src/DSi.cpp index 376e6a0..8026e49 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -16,18 +16,409 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ +#include "NDS.h" #include "DSi.h" #include "tiny-AES-c/aes.hpp" #include "sha1/sha1.h" +#include "Platform.h" + namespace DSi { +// + + +bool LoadBIOS() +{ + FILE* f; + u32 i; + + f = Platform::OpenLocalFile("bios9i.bin", "rb"); + if (!f) + { + printf("ARM9i BIOS not found\n"); + + for (i = 0; i < 16; i++) + ((u32*)NDS::ARM9BIOS)[i] = 0xE7FFDEFF; + } + else + { + fseek(f, 0, SEEK_SET); + fread(NDS::ARM9BIOS, 0x10000, 1, f); + + printf("ARM9i BIOS loaded\n"); + fclose(f); + } + + f = Platform::OpenLocalFile("bios7i.bin", "rb"); + if (!f) + { + printf("ARM7i BIOS not found\n"); + + for (i = 0; i < 16; i++) + ((u32*)NDS::ARM7BIOS)[i] = 0xE7FFDEFF; + } + else + { + // TODO: check if the first 32 bytes are crapoed + + fseek(f, 0, SEEK_SET); + fread(NDS::ARM7BIOS, 0x10000, 1, f); + + printf("ARM7i BIOS loaded\n"); + fclose(f); + } + + // herp + *(u32*)&NDS::ARM9BIOS[0] = 0xEAFFFFFE; + *(u32*)&NDS::ARM7BIOS[0] = 0xEAFFFFFE; + + return true; +} + bool LoadNAND() { - // + printf("Loading DSi NAND\n"); + + FILE* f = Platform::OpenLocalFile("nand.bin", "rb"); + if (f) + { + u32 bootparams[8]; + fseek(f, 0x220, SEEK_SET); + fread(bootparams, 4, 8, f); + + printf("ARM9: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n", + bootparams[0], bootparams[1], bootparams[2], bootparams[3]); + printf("ARM7: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n", + bootparams[4], bootparams[5], bootparams[6], bootparams[7]); + +#define printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } +#define printhex_rev(str, size) { for (int z = (size)-1; z >= 0; z--) printf("%02X", (str)[z]); printf("\n"); } + + u8 emmc_cid[16]; + u8 consoleid[8]; + fseek(f, 0xF000010, SEEK_SET); + fread(emmc_cid, 1, 16, f); + fread(consoleid, 1, 8, f); + + printf("eMMC CID: "); printhex(emmc_cid, 16); + printf("Console ID: "); printhex_rev(consoleid, 8); + + fclose(f); + } return true; } + +u8 ARM9Read8(u32 addr) +{ + switch (addr & 0xFF000000) + { + case 0x04000000: + return ARM9IORead8(addr); + } + + return NDS::ARM9Read8(addr); +} + +u16 ARM9Read16(u32 addr) +{ + switch (addr & 0xFF000000) + { + case 0x04000000: + return ARM9IORead16(addr); + } + + return NDS::ARM9Read16(addr); +} + +u32 ARM9Read32(u32 addr) +{ + switch (addr & 0xFF000000) + { + case 0x04000000: + return ARM9IORead32(addr); + } + + return NDS::ARM9Read32(addr); +} + +void ARM9Write8(u32 addr, u8 val) +{ + switch (addr & 0xFF000000) + { + case 0x04000000: + ARM9IOWrite8(addr, val); + return; + } + + return NDS::ARM9Write8(addr, val); +} + +void ARM9Write16(u32 addr, u16 val) +{ + switch (addr & 0xFF000000) + { + case 0x04000000: + ARM9IOWrite16(addr, val); + return; + } + + return NDS::ARM9Write16(addr, val); +} + +void ARM9Write32(u32 addr, u32 val) +{ + switch (addr & 0xFF000000) + { + case 0x04000000: + ARM9IOWrite32(addr, val); + return; + } + + return NDS::ARM9Write32(addr, val); +} + +bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) +{ + switch (addr & 0xFF000000) + { + case 0x02000000: + region->Mem = NDS::MainRAM; + region->Mask = MAIN_RAM_SIZE-1; + return true; + } + + if ((addr & 0xFFFF0000) == 0xFFFF0000 && !write) + { + region->Mem = NDS::ARM9BIOS; + region->Mask = 0xFFFF; + return true; + } + + region->Mem = NULL; + return false; +} + + + +u8 ARM7Read8(u32 addr) +{ + switch (addr & 0xFF800000) + { + case 0x04000000: + return ARM7IORead8(addr); + } + + return NDS::ARM7Read8(addr); +} + +u16 ARM7Read16(u32 addr) +{ + switch (addr & 0xFF800000) + { + case 0x04000000: + return ARM7IORead16(addr); + } + + return NDS::ARM7Read16(addr); +} + +u32 ARM7Read32(u32 addr) +{ + switch (addr & 0xFF800000) + { + case 0x04000000: + return ARM7IORead32(addr); + } + + return NDS::ARM7Read32(addr); +} + +void ARM7Write8(u32 addr, u8 val) +{ + switch (addr & 0xFF800000) + { + case 0x04000000: + ARM7IOWrite8(addr, val); + return; + } + + return NDS::ARM7Write8(addr, val); +} + +void ARM7Write16(u32 addr, u16 val) +{ + switch (addr & 0xFF800000) + { + case 0x04000000: + ARM7IOWrite16(addr, val); + return; + } + + return NDS::ARM7Write16(addr, val); +} + +void ARM7Write32(u32 addr, u32 val) +{ + switch (addr & 0xFF800000) + { + case 0x04000000: + ARM7IOWrite32(addr, val); + return; + } + + return NDS::ARM7Write32(addr, val); +} + +bool ARM7GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) +{ + switch (addr & 0xFF800000) + { + case 0x02000000: + case 0x02800000: + region->Mem = NDS::MainRAM; + region->Mask = MAIN_RAM_SIZE-1; + return true; + } + + // BIOS. ARM7 PC has to be within range. + /*if (addr < 0x00010000 && !write) + { + if (NDS::ARM7->R[15] < 0x00010000 && (addr >= NDS::ARM7BIOSProt || NDS::ARM7->R[15] < NDS::ARM7BIOSProt)) + { + region->Mem = NDS::ARM7BIOS; + region->Mask = 0xFFFF; + return true; + } + }*/ + + region->Mem = NULL; + return false; +} + + + + +#define CASE_READ8_16BIT(addr, val) \ + case (addr): return (val) & 0xFF; \ + case (addr+1): return (val) >> 8; + +#define CASE_READ8_32BIT(addr, val) \ + case (addr): return (val) & 0xFF; \ + case (addr+1): return ((val) >> 8) & 0xFF; \ + case (addr+2): return ((val) >> 16) & 0xFF; \ + case (addr+3): return (val) >> 24; + +u8 ARM9IORead8(u32 addr) +{ + switch (addr) + { + } + + return NDS::ARM9IORead8(addr); +} + +u16 ARM9IORead16(u32 addr) +{ + switch (addr) + { + } + + return NDS::ARM9IORead16(addr); +} + +u32 ARM9IORead32(u32 addr) +{ + switch (addr) + { + } + + return NDS::ARM9IORead32(addr); +} + +void ARM9IOWrite8(u32 addr, u8 val) +{ + switch (addr) + { + } + + return NDS::ARM9IOWrite8(addr, val); +} + +void ARM9IOWrite16(u32 addr, u16 val) +{ + switch (addr) + { + } + + return NDS::ARM9IOWrite16(addr, val); +} + +void ARM9IOWrite32(u32 addr, u32 val) +{ + switch (addr) + { + } + + return NDS::ARM9IOWrite32(addr, val); +} + + +u8 ARM7IORead8(u32 addr) +{ + switch (addr) + { + } + + return NDS::ARM7IORead8(addr); +} + +u16 ARM7IORead16(u32 addr) +{ + switch (addr) + { + } + + return NDS::ARM7IORead16(addr); +} + +u32 ARM7IORead32(u32 addr) +{ + switch (addr) + { + } + + return NDS::ARM7IORead32(addr); +} + +void ARM7IOWrite8(u32 addr, u8 val) +{ + switch (addr) + { + } + + return NDS::ARM7IOWrite8(addr, val); +} + +void ARM7IOWrite16(u32 addr, u16 val) +{ + switch (addr) + { + } + + return NDS::ARM7IOWrite16(addr, val); +} + +void ARM7IOWrite32(u32 addr, u32 val) +{ + switch (addr) + { + } + + return NDS::ARM7IOWrite32(addr, val); +} + } diff --git a/src/DSi.h b/src/DSi.h index 2c71ad9..2a3ee21 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -24,8 +24,41 @@ namespace DSi { +bool LoadBIOS(); bool LoadNAND(); +u8 ARM9Read8(u32 addr); +u16 ARM9Read16(u32 addr); +u32 ARM9Read32(u32 addr); +void ARM9Write8(u32 addr, u8 val); +void ARM9Write16(u32 addr, u16 val); +void ARM9Write32(u32 addr, u32 val); + +bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region); + +u8 ARM7Read8(u32 addr); +u16 ARM7Read16(u32 addr); +u32 ARM7Read32(u32 addr); +void ARM7Write8(u32 addr, u8 val); +void ARM7Write16(u32 addr, u16 val); +void ARM7Write32(u32 addr, u32 val); + +bool ARM7GetMemRegion(u32 addr, bool write, NDS::MemRegion* region); + +u8 ARM9IORead8(u32 addr); +u16 ARM9IORead16(u32 addr); +u32 ARM9IORead32(u32 addr); +void ARM9IOWrite8(u32 addr, u8 val); +void ARM9IOWrite16(u32 addr, u16 val); +void ARM9IOWrite32(u32 addr, u32 val); + +u8 ARM7IORead8(u32 addr); +u16 ARM7IORead16(u32 addr); +u32 ARM7IORead32(u32 addr); +void ARM7IOWrite8(u32 addr, u8 val); +void ARM7IOWrite16(u32 addr, u16 val); +void ARM7IOWrite32(u32 addr, u32 val); + } #endif // DSI_H diff --git a/src/NDS.cpp b/src/NDS.cpp index f00665e..5481f6f 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -392,44 +392,51 @@ void Reset() memset(ARM9BIOS, 0, 0x10000); memset(ARM7BIOS, 0, 0x10000); - f = Platform::OpenLocalFile("bios9.bin", "rb"); - if (!f) + if (true) { - printf("ARM9 BIOS not found\n"); + DSi::LoadBIOS(); + DSi::LoadNAND(); - for (i = 0; i < 16; i++) - ((u32*)ARM9BIOS)[i] = 0xE7FFDEFF; + ARM9ClockShift = 2; } else { - fseek(f, 0, SEEK_SET); - fread(ARM9BIOS, 0x1000, 1, f); + f = Platform::OpenLocalFile("bios9.bin", "rb"); + if (!f) + { + printf("ARM9 BIOS not found\n"); - printf("ARM9 BIOS loaded\n"); - fclose(f); - } + for (i = 0; i < 16; i++) + ((u32*)ARM9BIOS)[i] = 0xE7FFDEFF; + } + else + { + fseek(f, 0, SEEK_SET); + fread(ARM9BIOS, 0x1000, 1, f); - f = Platform::OpenLocalFile("bios7.bin", "rb"); - if (!f) - { - printf("ARM7 BIOS not found\n"); + printf("ARM9 BIOS loaded\n"); + fclose(f); + } - for (i = 0; i < 16; i++) - ((u32*)ARM7BIOS)[i] = 0xE7FFDEFF; - } - else - { - fseek(f, 0, SEEK_SET); - fread(ARM7BIOS, 0x4000, 1, f); + f = Platform::OpenLocalFile("bios7.bin", "rb"); + if (!f) + { + printf("ARM7 BIOS not found\n"); - printf("ARM7 BIOS loaded\n"); - fclose(f); - } + for (i = 0; i < 16; i++) + ((u32*)ARM7BIOS)[i] = 0xE7FFDEFF; + } + else + { + fseek(f, 0, SEEK_SET); + fread(ARM7BIOS, 0x4000, 1, f); - DSi::LoadNAND(); + printf("ARM7 BIOS loaded\n"); + fclose(f); + } - // TODO for later: configure this when emulating a DSi - ARM9ClockShift = 1; + ARM9ClockShift = 1; + } ARM9Timestamp = 0; ARM9Target = 0; ARM7Timestamp = 0; ARM7Target = 0; @@ -443,8 +450,8 @@ void Reset() MapSharedWRAM(0); - ExMemCnt[0] = 0; - ExMemCnt[1] = 0; + ExMemCnt[0] = 0x4000; + ExMemCnt[1] = 0x4000; memset(ROMSeed0, 0, 2*8); memset(ROMSeed1, 0, 2*8); SetGBASlotTimings(); diff --git a/src/sha1/sha1.c b/src/sha1/sha1.c index 2c50433..3729550 100644 --- a/src/sha1/sha1.c +++ b/src/sha1/sha1.c @@ -42,7 +42,8 @@ A million repetitions of "a" #if defined(vax) || defined(ns32000) || defined(sun386) || defined(__i386__) || \ defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ - defined(__alpha__) || defined(__alpha) + defined(__alpha__) || defined(__alpha) || \ + defined(__WIN32__) #define BYTE_ORDER LITTLE_ENDIAN #endif @@ -103,12 +104,12 @@ A million repetitions of "a" /* Hash a single 512-bit block. This is the core of the algorithm. */ -void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]) +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) { -u_int32_t a, b, c, d, e; +uint32_t a, b, c, d, e; typedef union { unsigned char c[64]; - u_int32_t l[16]; + uint32_t l[16]; } CHAR64LONG16; #ifdef SHA1HANDSOFF CHAR64LONG16 block[1]; /* use array to appear as a pointer */ @@ -178,10 +179,10 @@ void SHA1Init(SHA1_CTX* context) /* Run your data through this. */ -void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len) +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len) { -u_int32_t i; -u_int32_t j; +uint32_t i; +uint32_t j; j = context->count[0]; if ((context->count[0] += len << 3) < j) @@ -219,7 +220,7 @@ unsigned char c; for (i = 0; i < 2; i++) { - u_int32_t t = context->count[i]; + uint32_t t = context->count[i]; int j; for (j = 0; j < 4; t >>= 8, j++) diff --git a/src/sha1/sha1.h b/src/sha1/sha1.h index 9d6f129..56ffa56 100644 --- a/src/sha1/sha1.h +++ b/src/sha1/sha1.h @@ -5,13 +5,15 @@ By Steve Reid 100% Public Domain */ +#include + typedef struct { - u_int32_t state[5]; - u_int32_t count[2]; + uint32_t state[5]; + uint32_t count[2]; unsigned char buffer[64]; } SHA1_CTX; -void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]); +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]); void SHA1Init(SHA1_CTX* context); -void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len); +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len); void SHA1Final(unsigned char digest[20], SHA1_CTX* context); -- cgit v1.2.3 From ebd1a359cc72c4dadf2741bf3f4bb96dfcc5b505 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Jun 2019 13:46:20 +0200 Subject: setup new-WRAM mapping. hark hark hark --- src/DSi.cpp | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/DSi.h | 5 ++ 2 files changed, 206 insertions(+), 1 deletion(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index 8026e49..920981d 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -16,6 +16,8 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ +#include +#include #include "NDS.h" #include "DSi.h" #include "tiny-AES-c/aes.hpp" @@ -26,7 +28,19 @@ namespace DSi { -// +u32 MBK[2][9]; + +u8 NWRAM_A[0x40000]; +u8 NWRAM_B[0x40000]; +u8 NWRAM_C[0x40000]; + +u8* NWRAMMap_A[2][4]; +u8* NWRAMMap_B[3][4]; +u8* NWRAMMap_C[3][4]; + +u32 NWRAMStart[2][3]; +u32 NWRAMEnd[2][3]; +u32 NWRAMMask[2][3]; bool LoadBIOS() @@ -81,6 +95,18 @@ bool LoadNAND() { printf("Loading DSi NAND\n"); + memset(NWRAM_A, 0, 0x40000); + memset(NWRAM_B, 0, 0x40000); + memset(NWRAM_C, 0, 0x40000); + + memset(MBK, 0, sizeof(MBK)); + memset(NWRAMMap_A, 0, sizeof(NWRAMMap_A)); + memset(NWRAMMap_B, 0, sizeof(NWRAMMap_B)); + memset(NWRAMMap_C, 0, sizeof(NWRAMMap_C)); + memset(NWRAMStart, 0, sizeof(NWRAMStart)); + memset(NWRAMEnd, 0, sizeof(NWRAMEnd)); + memset(NWRAMMask, 0, sizeof(NWRAMMask)); + FILE* f = Platform::OpenLocalFile("nand.bin", "rb"); if (f) { @@ -93,6 +119,45 @@ bool LoadNAND() printf("ARM7: offset=%08X size=%08X RAM=%08X size_aligned=%08X\n", bootparams[4], bootparams[5], bootparams[6], bootparams[7]); + // read and apply new-WRAM settings + + u32 mbk[12]; + fseek(f, 0x380, SEEK_SET); + fread(mbk, 4, 12, f); + + MapNWRAM_A(0, mbk[0] & 0xFF); + MapNWRAM_A(1, (mbk[0] >> 8) & 0xFF); + MapNWRAM_A(2, (mbk[0] >> 16) & 0xFF); + MapNWRAM_A(3, mbk[0] >> 24); + + MapNWRAM_B(0, mbk[1] & 0xFF); + MapNWRAM_B(1, (mbk[1] >> 8) & 0xFF); + MapNWRAM_B(2, (mbk[1] >> 16) & 0xFF); + MapNWRAM_B(3, mbk[1] >> 24); + MapNWRAM_B(4, mbk[2] & 0xFF); + MapNWRAM_B(5, (mbk[2] >> 8) & 0xFF); + MapNWRAM_B(6, (mbk[2] >> 16) & 0xFF); + MapNWRAM_B(7, mbk[2] >> 24); + + MapNWRAM_C(0, mbk[3] & 0xFF); + MapNWRAM_C(1, (mbk[3] >> 8) & 0xFF); + MapNWRAM_C(2, (mbk[3] >> 16) & 0xFF); + MapNWRAM_C(3, mbk[3] >> 24); + MapNWRAM_C(4, mbk[4] & 0xFF); + MapNWRAM_C(5, (mbk[4] >> 8) & 0xFF); + MapNWRAM_C(6, (mbk[4] >> 16) & 0xFF); + MapNWRAM_C(7, mbk[4] >> 24); + + MapNWRAMRange(0, 0, mbk[5]); + MapNWRAMRange(0, 1, mbk[6]); + MapNWRAMRange(0, 2, mbk[7]); + + MapNWRAMRange(1, 0, mbk[8]); + MapNWRAMRange(1, 1, mbk[9]); + MapNWRAMRange(1, 2, mbk[10]); + + // TODO: MBK9 protect thing + #define printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } #define printhex_rev(str, size) { for (int z = (size)-1; z >= 0; z--) printf("%02X", (str)[z]); printf("\n"); } @@ -112,6 +177,141 @@ bool LoadNAND() } +// new WRAM mapping +// TODO: find out what happens upon overlapping slots!! + +void MapNWRAM_A(u32 num, u8 val) +{ + int mbkn = 0, mbks = 8*num; + + u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF; + if (oldval == val) return; + + MBK[0][mbkn] &= ~(0xFF << mbks); + MBK[0][mbkn] |= (val << mbks); + MBK[1][mbkn] = MBK[0][mbkn]; + + u8* ptr = &NWRAM_A[num << 16]; + + if (oldval & 0x80) + { + if (NWRAMMap_A[oldval & 0x01][(oldval >> 2) & 0x3] == ptr) + NWRAMMap_A[oldval & 0x01][(oldval >> 2) & 0x3] = NULL; + } + + if (val & 0x80) + { + NWRAMMap_A[val & 0x01][(val >> 2) & 0x3] = ptr; + } +} + +void MapNWRAM_B(u32 num, u8 val) +{ + int mbkn = 1+(num>>2), mbks = 8*(num&3); + + u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF; + if (oldval == val) return; + + MBK[0][mbkn] &= ~(0xFF << mbks); + MBK[0][mbkn] |= (val << mbks); + MBK[1][mbkn] = MBK[0][mbkn]; + + u8* ptr = &NWRAM_B[num << 15]; + + if (oldval & 0x80) + { + if (oldval & 0x02) oldval &= 0xFE; + + if (NWRAMMap_B[oldval & 0x03][(oldval >> 2) & 0x7] == ptr) + NWRAMMap_B[oldval & 0x03][(oldval >> 2) & 0x7] = NULL; + } + + if (val & 0x80) + { + if (val & 0x02) val &= 0xFE; + + NWRAMMap_B[val & 0x03][(val >> 2) & 0x7] = ptr; + } +} + +void MapNWRAM_C(u32 num, u8 val) +{ + int mbkn = 3+(num>>2), mbks = 8*(num&3); + + u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF; + if (oldval == val) return; + + MBK[0][mbkn] &= ~(0xFF << mbks); + MBK[0][mbkn] |= (val << mbks); + MBK[1][mbkn] = MBK[0][mbkn]; + + u8* ptr = &NWRAM_C[num << 15]; + + if (oldval & 0x80) + { + if (oldval & 0x02) oldval &= 0xFE; + + if (NWRAMMap_C[oldval & 0x03][(oldval >> 2) & 0x7] == ptr) + NWRAMMap_C[oldval & 0x03][(oldval >> 2) & 0x7] = NULL; + } + + if (val & 0x80) + { + if (val & 0x02) val &= 0xFE; + + NWRAMMap_C[val & 0x03][(val >> 2) & 0x7] = ptr; + } +} + +void MapNWRAMRange(u32 cpu, u32 num, u32 val) +{ + u32 oldval = MBK[cpu][5+num]; + if (oldval == val) return; + + MBK[cpu][5+num] = val; + + // TODO: what happens when the ranges are 'out of range'???? + if (num == 0) + { + u32 start = 0x03000000 + (((val >> 4) & 0xFF) << 16); + u32 end = 0x03000000 + (((val >> 20) & 0x1FF) << 16); + u32 size = (val >> 12) & 0x3; + + printf("NWRAM-A: ARM%d range %08X-%08X, size %d\n", cpu?7:9, start, end, size); + + NWRAMStart[cpu][num] = start; + NWRAMEnd[cpu][num] = end; + + switch (size) + { + case 0: + case 1: NWRAMMask[cpu][num] = 0x0; break; + case 2: NWRAMMask[cpu][num] = 0x1; break; // CHECKME + case 3: NWRAMMask[cpu][num] = 0x3; break; + } + } + else + { + u32 start = 0x03000000 + (((val >> 3) & 0x1FF) << 15); + u32 end = 0x03000000 + (((val >> 19) & 0x3FF) << 15); + u32 size = (val >> 12) & 0x3; + + printf("NWRAM-%c: ARM%d range %08X-%08X, size %d\n", 'A'+num, cpu?7:9, start, end, size); + + NWRAMStart[cpu][num] = start; + NWRAMEnd[cpu][num] = end; + + switch (size) + { + case 0: NWRAMMask[cpu][num] = 0x0; break; + case 1: NWRAMMask[cpu][num] = 0x1; break; + case 2: NWRAMMask[cpu][num] = 0x3; break; + case 3: NWRAMMask[cpu][num] = 0x7; break; + } + } +} + + u8 ARM9Read8(u32 addr) { switch (addr & 0xFF000000) diff --git a/src/DSi.h b/src/DSi.h index 2a3ee21..040c39b 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -27,6 +27,11 @@ namespace DSi bool LoadBIOS(); bool LoadNAND(); +void MapNWRAM_A(u32 num, u8 val); +void MapNWRAM_B(u32 num, u8 val); +void MapNWRAM_C(u32 num, u8 val); +void MapNWRAMRange(u32 cpu, u32 num, u32 val); + u8 ARM9Read8(u32 addr); u16 ARM9Read16(u32 addr); u32 ARM9Read32(u32 addr); -- cgit v1.2.3 From 7aa5131ec719f6dc4577a660ce94d793aa4a8617 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Jun 2019 14:05:31 +0200 Subject: run teh binary. BAHAHAHAHAHAHAHAAHHHH it doesn't do much for now tho --- src/DSi.cpp | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DSi.h | 2 + src/NDS.cpp | 2 + 3 files changed, 288 insertions(+) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index 920981d..22741aa 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -20,14 +20,26 @@ #include #include "NDS.h" #include "DSi.h" +#include "ARM.h" #include "tiny-AES-c/aes.hpp" #include "sha1/sha1.h" #include "Platform.h" +namespace NDS +{ + +extern ARMv5* ARM9; +extern ARMv4* ARM7; + +} + + namespace DSi { +u32 BootAddr[2]; + u32 MBK[2][9]; u8 NWRAM_A[0x40000]; @@ -43,6 +55,12 @@ u32 NWRAMEnd[2][3]; u32 NWRAMMask[2][3]; +void Reset() +{ + NDS::ARM9->JumpTo(BootAddr[0]); + NDS::ARM7->JumpTo(BootAddr[1]); +} + bool LoadBIOS() { FILE* f; @@ -158,6 +176,56 @@ bool LoadNAND() // TODO: MBK9 protect thing + // load binaries + // TODO: optionally support loading from actual NAND? + // currently decrypted binaries have to be provided + // they can be decrypted with twltool + + FILE* bin; + + bin = Platform::OpenLocalFile("boot2_9.bin", "rb"); + if (bin) + { + u32 dstaddr = bootparams[2]; + for (u32 i = 0; i < bootparams[1]; i += 4) + { + u32 _tmp; + fread(&_tmp, 4, 1, bin); + ARM9Write32(dstaddr, _tmp); + dstaddr += 4; + } + + fclose(bin); + } + else + { + printf("ARM9 boot2 not found\n"); + } + + bin = Platform::OpenLocalFile("boot2_7.bin", "rb"); + if (bin) + { + u32 dstaddr = bootparams[6]; + for (u32 i = 0; i < bootparams[5]; i += 4) + { + u32 _tmp; + fread(&_tmp, 4, 1, bin); + ARM7Write32(dstaddr, _tmp); + dstaddr += 4; + } + + fclose(bin); + } + else + { + printf("ARM7 boot2 not found\n"); + } + + // repoint CPUs to the boot2 binaries + + BootAddr[0] = bootparams[2]; + BootAddr[1] = bootparams[6]; + #define printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } #define printhex_rev(str, size) { for (int z = (size)-1; z >= 0; z--) printf("%02X", (str)[z]); printf("\n"); } @@ -316,6 +384,24 @@ u8 ARM9Read8(u32 addr) { switch (addr & 0xFF000000) { + case 0x03000000: + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + return ptr ? *(u8*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } + return NDS::ARM9Read8(addr); + case 0x04000000: return ARM9IORead8(addr); } @@ -327,6 +413,24 @@ u16 ARM9Read16(u32 addr) { switch (addr & 0xFF000000) { + case 0x03000000: + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + return ptr ? *(u16*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } + return NDS::ARM9Read16(addr); + case 0x04000000: return ARM9IORead16(addr); } @@ -338,6 +442,24 @@ u32 ARM9Read32(u32 addr) { switch (addr & 0xFF000000) { + case 0x03000000: + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + return ptr ? *(u32*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } + return NDS::ARM9Read32(addr); + case 0x04000000: return ARM9IORead32(addr); } @@ -349,6 +471,24 @@ void ARM9Write8(u32 addr, u8 val) { switch (addr & 0xFF000000) { + case 0x03000000: + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + if (ptr) *(u8*)&ptr[addr & 0xFFFF] = val; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val; + } + return NDS::ARM9Write8(addr, val); + case 0x04000000: ARM9IOWrite8(addr, val); return; @@ -361,6 +501,24 @@ void ARM9Write16(u32 addr, u16 val) { switch (addr & 0xFF000000) { + case 0x03000000: + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + if (ptr) *(u16*)&ptr[addr & 0xFFFF] = val; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val; + } + return NDS::ARM9Write16(addr, val); + case 0x04000000: ARM9IOWrite16(addr, val); return; @@ -373,6 +531,24 @@ void ARM9Write32(u32 addr, u32 val) { switch (addr & 0xFF000000) { + case 0x03000000: + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + if (ptr) *(u32*)&ptr[addr & 0xFFFF] = val; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val; + } + return NDS::ARM9Write32(addr, val); + case 0x04000000: ARM9IOWrite32(addr, val); return; @@ -408,6 +584,24 @@ u8 ARM7Read8(u32 addr) { switch (addr & 0xFF800000) { + case 0x03000000: + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + return ptr ? *(u8*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } + return NDS::ARM7Read8(addr); + case 0x04000000: return ARM7IORead8(addr); } @@ -419,6 +613,24 @@ u16 ARM7Read16(u32 addr) { switch (addr & 0xFF800000) { + case 0x03000000: + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + return ptr ? *(u16*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } + return NDS::ARM7Read16(addr); + case 0x04000000: return ARM7IORead16(addr); } @@ -430,6 +642,24 @@ u32 ARM7Read32(u32 addr) { switch (addr & 0xFF800000) { + case 0x03000000: + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + return ptr ? *(u32*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } + return NDS::ARM7Read32(addr); + case 0x04000000: return ARM7IORead32(addr); } @@ -441,6 +671,24 @@ void ARM7Write8(u32 addr, u8 val) { switch (addr & 0xFF800000) { + case 0x03000000: + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + if (ptr) *(u8*)&ptr[addr & 0xFFFF] = val; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val; + } + return NDS::ARM7Write8(addr, val); + case 0x04000000: ARM7IOWrite8(addr, val); return; @@ -453,6 +701,24 @@ void ARM7Write16(u32 addr, u16 val) { switch (addr & 0xFF800000) { + case 0x03000000: + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + if (ptr) *(u16*)&ptr[addr & 0xFFFF] = val; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val; + } + return NDS::ARM7Write16(addr, val); + case 0x04000000: ARM7IOWrite16(addr, val); return; @@ -465,6 +731,24 @@ void ARM7Write32(u32 addr, u32 val) { switch (addr & 0xFF800000) { + case 0x03000000: + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + if (ptr) *(u32*)&ptr[addr & 0xFFFF] = val; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val; + } + return NDS::ARM7Write32(addr, val); + case 0x04000000: ARM7IOWrite32(addr, val); return; diff --git a/src/DSi.h b/src/DSi.h index 040c39b..b1b4abf 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -24,6 +24,8 @@ namespace DSi { +void Reset(); + bool LoadBIOS(); bool LoadNAND(); diff --git a/src/NDS.cpp b/src/NDS.cpp index 5481f6f..c285910 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -510,6 +510,8 @@ void Reset() SPI::Reset(); RTC::Reset(); Wifi::Reset(); + + DSi::Reset(); } void Stop() -- cgit v1.2.3 From 58e3ff61ac31a6ac20e12d03c518a6c16715e83c Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 15 Jun 2019 16:58:02 +0200 Subject: add I2C shito --- melonDS.cbp | 2 + src/ARM.cpp | 1 + src/DSi.cpp | 8 +++ src/DSi.h | 2 +- src/DSi_I2C.cpp | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DSi_I2C.h | 41 +++++++++++++ src/SPI.cpp | 2 +- src/SPI.h | 1 - 8 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 src/DSi_I2C.cpp create mode 100644 src/DSi_I2C.h (limited to 'src/DSi.h') diff --git a/melonDS.cbp b/melonDS.cbp index 97958f5..bbe07dd 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -104,6 +104,8 @@ + + diff --git a/src/ARM.cpp b/src/ARM.cpp index f50af25..870c455 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -175,6 +175,7 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) // aging cart debug crap //if (addr == 0x0201764C) printf("capture test %d: R1=%08X\n", R[6], R[1]); //if (addr == 0x020175D8) printf("capture test %d: res=%08X\n", R[6], R[0]); + if (addr==0x037CA0D0) printf("VLORP %08X\n", R[15]); u32 oldregion = R[15] >> 24; u32 newregion = addr >> 24; diff --git a/src/DSi.cpp b/src/DSi.cpp index 22741aa..057d229 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -25,6 +25,8 @@ #include "sha1/sha1.h" #include "Platform.h" +#include "DSi_I2C.h" + namespace NDS { @@ -59,6 +61,8 @@ void Reset() { NDS::ARM9->JumpTo(BootAddr[0]); NDS::ARM7->JumpTo(BootAddr[1]); + + DSi_I2C::Reset(); } bool LoadBIOS() @@ -855,6 +859,8 @@ u8 ARM7IORead8(u32 addr) { switch (addr) { + case 0x04004500: return DSi_I2C::ReadData(); + case 0x04004501: return DSi_I2C::Cnt; } return NDS::ARM7IORead8(addr); @@ -882,6 +888,8 @@ void ARM7IOWrite8(u32 addr, u8 val) { switch (addr) { + case 0x04004500: DSi_I2C::WriteData(val); return; + case 0x04004501: DSi_I2C::WriteCnt(val); return; } return NDS::ARM7IOWrite8(addr, val); diff --git a/src/DSi.h b/src/DSi.h index b1b4abf..02f84da 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -19,7 +19,7 @@ #ifndef DSI_H #define DSI_H -#include "types.h" +#include "NDS.h" namespace DSi { diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp new file mode 100644 index 0000000..1836c31 --- /dev/null +++ b/src/DSi_I2C.cpp @@ -0,0 +1,185 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS 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. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "DSi.h" +#include "DSi_I2C.h" + + +namespace DSi_BPTWL +{ + +u8 Registers[0x100]; +u32 CurPos; + +bool Init() +{ + return true; +} + +void DeInit() +{ +} + +void Reset() +{ + CurPos = 0; + memset(Registers, 0x5A, 0x100); + + Registers[0x00] = 0x33; // TODO: support others?? + Registers[0x01] = 0x00; + Registers[0x02] = 0x50; + Registers[0x10] = 0x00; // power btn + Registers[0x11] = 0x00; // reset + Registers[0x12] = 0x00; // power btn tap + Registers[0x20] = 0x83; // battery + Registers[0x21] = 0x07; + Registers[0x30] = 0x13; + Registers[0x31] = 0x00; // camera power + Registers[0x40] = 0x1F; // volume + Registers[0x41] = 0x04; // backlight + Registers[0x60] = 0x00; + Registers[0x61] = 0x01; + Registers[0x62] = 0x50; + Registers[0x63] = 0x00; + Registers[0x70] = 0x00; // boot flag + Registers[0x71] = 0x00; + Registers[0x72] = 0x00; + Registers[0x73] = 0x00; + Registers[0x74] = 0x00; + Registers[0x75] = 0x00; + Registers[0x76] = 0x00; + Registers[0x77] = 0x00; + Registers[0x80] = 0x10; + Registers[0x81] = 0x64; +} + +void Start() +{ + CurPos = 0; +} + +u8 Read(bool last) +{ + return Registers[CurPos++]; +} + +void Write(u8 val, bool last) +{ + if (CurPos == 0x11 || CurPos == 0x12 || + CurPos == 0x21 || + CurPos == 0x30 || CurPos == 0x31 || + CurPos == 0x40 || CurPos == 0x31 || + CurPos == 0x60 || CurPos == 0x63 || + (CurPos >= 0x70 && CurPos <= 0x77) || + CurPos == 0x80 || CurPos == 0x81) + { + Registers[CurPos] = val; + } + + CurPos++; +} + +} + + +namespace DSi_I2C +{ + +u8 Cnt; +u32 Device; + +bool Init() +{ + if (!DSi_BPTWL::Init()) return false; + + return true; +} + +void DeInit() +{ + DSi_BPTWL::DeInit(); +} + +void Reset() +{ + Device = -1; + + DSi_BPTWL::Reset(); +} + +void WriteCnt(u8 val) +{ + val &= 0xF7; + // TODO: check ACK flag + // TODO: transfer delay + + if (val & (1<<7)) + { + if (val & (1<<2)) + { + Device = -1; + printf("I2C: start\n"); + } + } + + Cnt = val; +} + +u8 ReadData() +{ + switch (Device) + { + case 0x4A: return DSi_BPTWL::Read(Cnt & (1<<0)); + + default: + printf("I2C: read from unknown device %02X\n", Device); + break; + } + + return 0; +} + +void WriteData(u8 val) +{ + if (Device == -1) + { + Device = val; + switch (Device) + { + case 0x4A: DSi_BPTWL::Start(); return; + + default: + printf("I2C: start on unknown device %02X\n", Device); + break; + } + return; + } + + switch (Device) + { + case 0x4A: DSi_BPTWL::Write(val, Cnt & (1<<0)); return; + + default: + printf("I2C: write to unknown device %02X\n", Device); + break; + } +} + +} diff --git a/src/DSi_I2C.h b/src/DSi_I2C.h new file mode 100644 index 0000000..d058be1 --- /dev/null +++ b/src/DSi_I2C.h @@ -0,0 +1,41 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS 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. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef DSI_I2C_H +#define DSI_I2C_H + +namespace DSi_I2C +{ + +extern u8 Cnt; + +bool Init(); +void DeInit(); +void Reset(); +//void DoSavestate(Savestate* file); + +void WriteCnt(u8 val); + +u8 ReadData(); +void WriteData(u8 val); + +//void TransferDone(u32 param); + +} + +#endif // DSI_I2C_H diff --git a/src/SPI.cpp b/src/SPI.cpp index 759bbd9..8bee66f 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -581,7 +581,7 @@ namespace SPI u16 Cnt; -u32 CurDevice; +u32 CurDevice; // remove me bool Init() diff --git a/src/SPI.h b/src/SPI.h index 9b987ca..21ad9a6 100644 --- a/src/SPI.h +++ b/src/SPI.h @@ -50,7 +50,6 @@ void DeInit(); void Reset(); void DoSavestate(Savestate* file); -u16 ReadCnt(); void WriteCnt(u16 val); u8 ReadData(); -- cgit v1.2.3 From d4dd97638d1615f51bcadd256d390a895519d565 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 16 Jun 2019 17:01:49 +0200 Subject: lay base for SD shit --- melonDS.cbp | 2 ++ src/DSi.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DSi.h | 2 ++ src/DSi_SD.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DSi_SD.h | 41 +++++++++++++++++++++++++++++++++ src/NDS.cpp | 4 ++++ src/version.h | 2 +- 7 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 src/DSi_SD.cpp create mode 100644 src/DSi_SD.h (limited to 'src/DSi.h') diff --git a/melonDS.cbp b/melonDS.cbp index bbe07dd..e75e02c 100644 --- a/melonDS.cbp +++ b/melonDS.cbp @@ -106,6 +106,8 @@ + + diff --git a/src/DSi.cpp b/src/DSi.cpp index 206c253..e30e3e1 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -26,6 +26,7 @@ #include "Platform.h" #include "DSi_I2C.h" +#include "DSi_SD.h" namespace NDS @@ -56,6 +57,27 @@ u32 NWRAMStart[2][3]; u32 NWRAMEnd[2][3]; u32 NWRAMMask[2][3]; +DSi_SD* SDMMC; +DSi_SD* SDIO; + + +bool Init() +{ + if (!DSi_I2C::Init()) return false; + + SDMMC = new DSi_SD(0); + SDIO = new DSi_SD(1); + + return true; +} + +void DeInit() +{ + DSi_I2C::DeInit(); + + delete SDMMC; + delete SDIO; +} void Reset() { @@ -67,6 +89,9 @@ void Reset() NDS::ARM7->JumpTo(BootAddr[1]); DSi_I2C::Reset(); + + SDMMC->Reset(); + SDIO->Reset(); } bool LoadBIOS() @@ -904,6 +929,15 @@ u16 ARM7IORead16(u32 addr) case 0x04004006: return 0; // JTAG register } + if (addr >= 0x04004800 && addr < 0x04004A00) + { + return SDMMC->Read(addr); + } + if (addr >= 0x04004A00 && addr < 0x04004C00) + { + return SDIO->Read(addr); + } + return NDS::ARM7IORead16(addr); } @@ -917,6 +951,15 @@ u32 ARM7IORead32(u32 addr) case 0x04004008: return 0x80000000; // HAX } + if (addr >= 0x04004800 && addr < 0x04004A00) + { + return SDMMC->Read(addr) | (SDMMC->Read(addr+2) << 16); + } + if (addr >= 0x04004A00 && addr < 0x04004C00) + { + return SDIO->Read(addr) | (SDIO->Read(addr+2) << 16); + } + return NDS::ARM7IORead32(addr); } @@ -939,6 +982,17 @@ void ARM7IOWrite16(u32 addr, u16 val) case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; } + if (addr >= 0x04004800 && addr < 0x04004A00) + { + SDMMC->Write(addr, val); + return; + } + if (addr >= 0x04004A00 && addr < 0x04004C00) + { + SDIO->Write(addr, val); + return; + } + return NDS::ARM7IOWrite16(addr, val); } @@ -950,6 +1004,19 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; } + if (addr >= 0x04004800 && addr < 0x04004A00) + { + SDMMC->Write(addr, val & 0xFFFF); + SDMMC->Write(addr+2, val >> 16); + return; + } + if (addr >= 0x04004A00 && addr < 0x04004C00) + { + SDIO->Write(addr, val & 0xFFFF); + SDIO->Write(addr+2, val >> 16); + return; + } + return NDS::ARM7IOWrite32(addr, val); } diff --git a/src/DSi.h b/src/DSi.h index 02f84da..6d45a10 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -24,6 +24,8 @@ namespace DSi { +bool Init(); +void DeInit(); void Reset(); bool LoadBIOS(); diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp new file mode 100644 index 0000000..58b733c --- /dev/null +++ b/src/DSi_SD.cpp @@ -0,0 +1,72 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS 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. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include +#include +#include "DSi.h" +#include "DSi_SD.h" + + +DSi_SD::DSi_SD(u32 num) +{ + Num = num; +} + +DSi_SD::~DSi_SD() +{ + // +} + +void DSi_SD::Reset() +{ + if (Num == 0) + { + PortSelect = 0x0200; // CHECKME + } + else + { + PortSelect = 0x0100; // CHECKME + } +} + +void DSi_SD::DoSavestate(Savestate* file) +{ + // TODO! +} + + +u16 DSi_SD::Read(u32 addr) +{ + switch (addr & 0x1FF) + { + case 0x002: return PortSelect & 0x030F; + } + + printf("unknown %s read %08X\n", Num?"SDIO":"SD/MMC", addr); + return 0; +} + +void DSi_SD::Write(u32 addr, u16 val) +{ + switch (addr & 0x1FF) + { + case 0x002: PortSelect = val; return; + } + + printf("unknown %s write %08X %04X\n", Num?"SDIO":"SD/MMC", addr, val); +} diff --git a/src/DSi_SD.h b/src/DSi_SD.h new file mode 100644 index 0000000..ce3eb84 --- /dev/null +++ b/src/DSi_SD.h @@ -0,0 +1,41 @@ +/* + Copyright 2016-2019 Arisotura + + This file is part of melonDS. + + melonDS 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. + + melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef DSI_SD_H +#define DSI_SD_H + +class DSi_SD +{ +public: + DSi_SD(u32 num); + ~DSi_SD(); + + void Reset(); + + void DoSavestate(Savestate* file); + + u16 Read(u32 addr); + void Write(u32 addr, u16 val); + +private: + u32 Num; + + u16 PortSelect; +}; + +#endif // DSI_SD_H diff --git a/src/NDS.cpp b/src/NDS.cpp index 5ca55f3..414f87c 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -178,6 +178,8 @@ bool Init() if (!RTC::Init()) return false; if (!Wifi::Init()) return false; + if (!DSi::Init()) return false; + return true; } @@ -198,6 +200,8 @@ void DeInit() SPI::DeInit(); RTC::DeInit(); Wifi::DeInit(); + + DSi::DeInit(); } diff --git a/src/version.h b/src/version.h index cc15c89..bb97c3c 100644 --- a/src/version.h +++ b/src/version.h @@ -19,7 +19,7 @@ #ifndef VERSION_H #define VERSION_H -#define MELONDS_VERSION "0.8.1" +#define MELONDS_VERSION "0.8.1-DSi" #define MELONDS_URL "http://melonds.kuribo64.net/" -- cgit v1.2.3 From 6c75275593c854ab6324f9c38155930ed1ca9328 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 17 Jun 2019 18:40:45 +0200 Subject: moar SD/MMC commands --- src/DSi.cpp | 13 +++++---- src/DSi.h | 2 ++ src/DSi_SD.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/DSi_SD.h | 13 +++++++-- 4 files changed, 100 insertions(+), 14 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index 8315fb8..abd3bd6 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -60,6 +60,9 @@ u32 NWRAMMask[2][3]; DSi_SDHost* SDMMC; DSi_SDHost* SDIO; +u64 ConsoleID; +u8 eMMC_CID[16]; + bool Init() { @@ -262,14 +265,12 @@ bool LoadNAND() #define printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } #define printhex_rev(str, size) { for (int z = (size)-1; z >= 0; z--) printf("%02X", (str)[z]); printf("\n"); } - u8 emmc_cid[16]; - u8 consoleid[8]; fseek(f, 0xF000010, SEEK_SET); - fread(emmc_cid, 1, 16, f); - fread(consoleid, 1, 8, f); + fread(eMMC_CID, 1, 16, f); + fread(&ConsoleID, 1, 8, f); - printf("eMMC CID: "); printhex(emmc_cid, 16); - printf("Console ID: "); printhex_rev(consoleid, 8); + printf("eMMC CID: "); printhex(eMMC_CID, 16); + printf("Console ID: %llx\n", ConsoleID); fclose(f); } diff --git a/src/DSi.h b/src/DSi.h index 6d45a10..3ebee37 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -24,6 +24,8 @@ namespace DSi { +extern u8 eMMC_CID[16]; + bool Init(); void DeInit(); void Reset(); diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index a821fe5..35859cc 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -52,6 +52,7 @@ void DSi_SDHost::Reset() } SoftReset = 0x0007; // CHECKME + SDClock = 0; Command = 0; Param = 0; @@ -67,8 +68,11 @@ void DSi_SDHost::Reset() if (Num == 0) { + DSi_MMCStorage* mmc = new DSi_MMCStorage(this, true, "nand.bin"); + mmc->SetCID(DSi::eMMC_CID); + // TODO: port 0 (SD) - Ports[1] = new DSi_MMCStorage(this, true, "nand.bin"); + Ports[1] = mmc; } else { @@ -129,6 +133,8 @@ u16 DSi_SDHost::Read(u32 addr) case 0x020: return IRQMask & 0x031D; case 0x022: return (IRQMask >> 16) & 0x8B7F; + case 0x024: return SDClock; + case 0x0E0: return SoftReset; } @@ -150,10 +156,13 @@ void DSi_SDHost::Write(u32 addr, u16 val) DSi_SDDevice* dev = Ports[PortSelect & 0x1]; if (dev) { + // CHECKME + // "Setting Command Type to "ACMD" is automatically sending an APP_CMD prefix prior to the command number" + // except DSi boot2 manually sends an APP_CMD prefix AND sets the next command to be ACMD switch ((Command >> 6) & 0x3) { case 0: dev->SendCMD(cmd, Param); break; - case 1: dev->SendACMD(cmd, Param); break; + case 1: /*dev->SendCMD(55, 0);*/ dev->SendCMD(cmd, Param); break; default: printf("%s: unknown command type %d, %02X %08X\n", SD_DESC, (Command>>6)&0x3, cmd, Param); break; @@ -171,6 +180,8 @@ void DSi_SDHost::Write(u32 addr, u16 val) case 0x020: IRQMask = (IRQMask & 0x8B7F0000) | (val & 0x031D); return; case 0x022: IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); return; + case 0x024: SDClock = val & 0x03FF; return; + case 0x0E0: if ((SoftReset & 0x0001) && !(val & 0x0001)) { @@ -200,6 +211,14 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path File = Platform::OpenLocalFile(path, "r+b"); CSR = 0x00; // checkme + + // TODO: busy bit + // TODO: SDHC/SDXC bit + OCR = 0x80FF8000; + + // TODO: customize based on card size etc + u8 csd_template[16] = {0x40, 0x40, 0x96, 0xE9, 0x7F, 0xDB, 0xF6, 0xDF, 0x01, 0x59, 0x0F, 0x2A, 0x01, 0x26, 0x90, 0x00}; + memcpy(CSD, csd_template, 16); } DSi_MMCStorage::~DSi_MMCStorage() @@ -209,21 +228,76 @@ DSi_MMCStorage::~DSi_MMCStorage() void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) { + if (CSR & (1<<5)) + { + CSR &= ~(1<<5); + return SendACMD(cmd, param); + } + switch (cmd) { - case 0x00: // reset/etc + case 0: // reset/etc Host->SendResponse(CSR, true); return; - case 0x08: // set voltage + case 2: + case 10: // get CID + Host->SendResponse(*(u32*)&CID[0], false); + Host->SendResponse(*(u32*)&CID[1], false); + Host->SendResponse(*(u32*)&CID[2], false); + Host->SendResponse(*(u32*)&CID[3], true); + //if (cmd == 2) SetState(0x02); + return; + + case 3: // get/set RCA + if (Internal) + { + RCA = param >> 16; + Host->SendResponse(CSR|0x10000, true); // huh?? + } + else + { + // TODO + printf("CMD3 on SD card: TODO\n"); + } + return; + + case 7: // select card (by RCA) + Host->SendResponse(CSR, true); + return; + + case 8: // set voltage Host->SendResponse(param, true); return; + + case 9: // get CSD + Host->SendResponse(*(u32*)&CSD[0], false); + Host->SendResponse(*(u32*)&CSD[1], false); + Host->SendResponse(*(u32*)&CSD[2], false); + Host->SendResponse(*(u32*)&CSD[3], true); + return; + + case 55: // ?? + printf("CMD55 %08X\n", param); + CSR |= (1<<5); + Host->SendResponse(CSR, true); + return; } - printf("MMC: unknown CMD %02X %08X\n", cmd, param); + printf("MMC: unknown CMD %d %08X\n", cmd, param); } void DSi_MMCStorage::SendACMD(u8 cmd, u32 param) { - printf("MMC: ACMD %02X %08X\n", cmd, param); + switch (cmd) + { + case 41: // set operating conditions + OCR &= 0xBF000000; + OCR |= (param & 0x40FFFFFF); + Host->SendResponse(OCR, true); + SetState(0x01); + return; + } + + printf("MMC: unknown ACMD %d %08X\n", cmd, param); } diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 248755d..d223fac 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -42,6 +42,7 @@ private: u16 PortSelect; u16 SoftReset; + u16 SDClock; u32 IRQStatus; // IF u32 IRQMask; // ~IE @@ -63,7 +64,6 @@ public: ~DSi_SDDevice() {} virtual void SendCMD(u8 cmd, u32 param) = 0; - virtual void SendACMD(u8 cmd, u32 param) = 0; protected: DSi_SDHost* Host; @@ -76,6 +76,8 @@ public: DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path); ~DSi_MMCStorage(); + void SetCID(u8* cid) { memcpy(CID, cid, 16); } + void SendCMD(u8 cmd, u32 param); void SendACMD(u8 cmd, u32 param); @@ -84,7 +86,14 @@ private: char FilePath[1024]; FILE* File; - u8 CSR; + u8 CID[16]; + u8 CSD[16]; + + u32 CSR; + u32 OCR; + u32 RCA; + + void SetState(u32 state) { CSR &= ~(0xF << 9); CSR |= (state << 9); } }; #endif // DSI_SD_H -- cgit v1.2.3 From dc3c9f5bf8d86dfa11ecf239a28ca50f7bfe3fe6 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 18 Jun 2019 14:12:37 +0200 Subject: take all the SDMMC shit further. now it's completing MMC init and trying to read shit. --- src/DSi.h | 5 ++ src/DSi_SD.cpp | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/DSi_SD.h | 25 ++++++++ src/NDS.h | 3 + 4 files changed, 218 insertions(+), 11 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.h b/src/DSi.h index 3ebee37..efd533a 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -20,12 +20,17 @@ #define DSI_H #include "NDS.h" +#include "DSi_SD.h" namespace DSi { extern u8 eMMC_CID[16]; +extern DSi_SDHost* SDMMC; +extern DSi_SDHost* SDIO; + + bool Init(); void DeInit(); void Reset(); diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 35859cc..76c2676 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -30,12 +30,18 @@ DSi_SDHost::DSi_SDHost(u32 num) { Num = num; + DataFIFO[0] = new FIFO(0x100); + DataFIFO[1] = new FIFO(0x100); + Ports[0] = NULL; Ports[1] = NULL; } DSi_SDHost::~DSi_SDHost() { + delete DataFIFO[0]; + delete DataFIFO[1]; + if (Ports[0]) delete Ports[0]; if (Ports[1]) delete Ports[1]; } @@ -53,14 +59,26 @@ void DSi_SDHost::Reset() SoftReset = 0x0007; // CHECKME SDClock = 0; + SDOption = 0; Command = 0; Param = 0; memset(ResponseBuffer, 0, sizeof(ResponseBuffer)); + DataFIFO[0]->Clear(); + DataFIFO[1]->Clear(); + CurFIFO = 0; + IRQStatus = 0; IRQMask = 0x8B7F031D; + DataCtl = 0; + Data32IRQ = 0; + DataMode = 0; + BlockCount16 = 0; BlockCount32 = 0; BlockCountInternal = 0; + BlockLen16 = 0; BlockLen32 = 0; + StopAction = 0; + if (Ports[0]) delete Ports[0]; if (Ports[1]) delete Ports[1]; Ports[0] = NULL; @@ -86,6 +104,11 @@ void DSi_SDHost::DoSavestate(Savestate* file) } +void DSi_SDHost::ClearIRQ(u32 irq) +{ + IRQStatus &= ~(1<CurFIFO ^= 1; + + host->ClearIRQ(25); + host->SetIRQ(24); + if (param & 0x2) host->SetIRQ(2); +} + +void DSi_SDHost::SendData(u8* data, u32 len, bool last) +{ + printf("%s: data RX, len=%d, blkcnt=%d blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockLen16, IRQMask); + if (len != BlockLen16) printf("!! BAD BLOCKLEN\n"); + + u32 f = CurFIFO ^ 1; + for (u32 i = 0; i < len; i += 2) + DataFIFO[f]->Write(*(u16*)&data[i]); + + //CurFIFO = f; + //SetIRQ(24); + // TODO: determine what the delay should be! + // for now, this is a placeholder + // we need a delay because DSi boot2 will send a command and then wait for IRQ0 + // but if IRQ24 is thrown instantly, the handler clears IRQ0 before the + // send-command function starts polling IRQ status + u32 param = Num | (last << 1); + NDS::ScheduleEvent(NDS::Event_DSi_SDTransfer, false, 512, FinishSend, param); +} + u16 DSi_SDHost::Read(u32 addr) { @@ -119,6 +173,9 @@ u16 DSi_SDHost::Read(u32 addr) case 0x004: return Param & 0xFFFF; case 0x006: return Param >> 16; + case 0x008: return StopAction; + case 0x00A: return BlockCount16; + case 0x00C: return ResponseBuffer[0]; case 0x00E: return ResponseBuffer[1]; case 0x010: return ResponseBuffer[2]; @@ -128,14 +185,70 @@ u16 DSi_SDHost::Read(u32 addr) case 0x018: return ResponseBuffer[6]; case 0x01A: return ResponseBuffer[7]; - case 0x01C: return IRQStatus & 0x031D; - case 0x01E: return (IRQStatus >> 16) & 0x8B7F; + case 0x01C: return (IRQStatus & 0x031D) | 0x0030; // TODO: adjust insert flags for SD card + case 0x01E: return ((IRQStatus >> 16) & 0x8B7F); case 0x020: return IRQMask & 0x031D; case 0x022: return (IRQMask >> 16) & 0x8B7F; case 0x024: return SDClock; + case 0x026: return BlockLen16; + case 0x028: return SDOption; + + case 0x030: // FIFO16 + { + // TODO: decrement BlockLen???? + + u32 f = CurFIFO; + if (DataFIFO[f]->IsEmpty()) + { + // TODO + return 0; + } + + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; + u16 ret = DataFIFO[f]->Read(); + + if (DataFIFO[f]->IsEmpty()) + { + ClearIRQ(24); + + if (BlockCountInternal == 0) + { + printf("%s: data RX complete", SD_DESC); + + if (StopAction & (1<<8)) + { + printf(", sending CMD12"); + if (dev) dev->SendCMD(12, 0); + } + + printf("\n"); + + // CHECKME: presumably IRQ2 should not trigger here, but rather + // when the data transfer is done + //SetIRQ(0); + //SetIRQ(2); + } + else + { + BlockCountInternal--; + + if (dev) dev->ContinueTransfer(); + } + + SetIRQ(25); + } + + return ret; + } + + case 0x0D8: return DataCtl; case 0x0E0: return SoftReset; + + case 0x100: return Data32IRQ; + case 0x104: return BlockLen32; + case 0x108: return BlockCount32; } printf("unknown %s read %08X\n", SD_DESC, addr); @@ -171,32 +284,55 @@ void DSi_SDHost::Write(u32 addr, u16 val) } return; - case 0x002: PortSelect = val; return; + case 0x002: PortSelect = val; printf("%s: PORT SELECT %04X\n", SD_DESC, val); return; case 0x004: Param = (Param & 0xFFFF0000) | val; return; case 0x006: Param = (Param & 0x0000FFFF) | (val << 16); return; - case 0x01C: IRQStatus &= ~(u32)val; return; - case 0x01E: IRQStatus &= ~((u32)val << 16); return; + case 0x008: StopAction = val & 0x0101; return; + case 0x00A: BlockCount16 = val; BlockCountInternal = val; return; + + case 0x01C: IRQStatus &= (val | 0xFFFF0000); return; + case 0x01E: IRQStatus &= ((val << 16) | 0xFFFF); return; case 0x020: IRQMask = (IRQMask & 0x8B7F0000) | (val & 0x031D); return; case 0x022: IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); return; case 0x024: SDClock = val & 0x03FF; return; + case 0x026: + BlockLen16 = val & 0x03FF; + if (BlockLen16 > 0x200) BlockLen16 = 0x200; + return; + case 0x028: SDOption = val & 0xC1FF; return; + + case 0x0D8: + DataCtl = (val & 0x0022); + DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); + printf("%s: data mode %d-bit\n", SD_DESC, DataMode?32:16); + return; case 0x0E0: if ((SoftReset & 0x0001) && !(val & 0x0001)) { printf("%s: RESET\n", SD_DESC); - // TODO: STOP_INTERNAL_ACTION - // TODO: SD_RESPONSE + StopAction = 0; + memset(ResponseBuffer, 0, sizeof(ResponseBuffer)); IRQStatus = 0; // TODO: ERROR_DETAIL_STATUS - // TODO: CARD_CLK_CTL - // TODO: CARD_OPTION + SDClock &= ~0x0500; + SDOption = 0x40EE; // TODO: CARD_IRQ_STAT // TODO: FIFO16 shit } SoftReset = 0x0006 | (val & 0x0001); return; + + case 0x100: + Data32IRQ = (val & 0x1802) | (Data32IRQ & 0x0300); + if (val & (1<<10)) printf("TODO: SD/MMC: CLEAR FIFO32\n"); + DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); + printf("%s: data mode %d-bit\n", SD_DESC, DataMode?32:16); + return; + case 0x104: BlockLen32 = val & 0x03FF; return; + case 0x108: BlockCount32 = val; return; } printf("unknown %s write %08X %04X\n", SD_DESC, addr, val); @@ -210,7 +346,7 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path File = Platform::OpenLocalFile(path, "r+b"); - CSR = 0x00; // checkme + CSR = 0x00000100; // checkme // TODO: busy bit // TODO: SDHC/SDXC bit @@ -219,6 +355,12 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path // TODO: customize based on card size etc u8 csd_template[16] = {0x40, 0x40, 0x96, 0xE9, 0x7F, 0xDB, 0xF6, 0xDF, 0x01, 0x59, 0x0F, 0x2A, 0x01, 0x26, 0x90, 0x00}; memcpy(CSD, csd_template, 16); + + // checkme + memset(SCR, 0, 8); + *(u32*)&SCR[0] = 0x012A0000; + + memset(SSR, 0, 64); } DSi_MMCStorage::~DSi_MMCStorage() @@ -277,8 +419,16 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) Host->SendResponse(*(u32*)&CSD[3], true); return; + case 12: // stop operation + Host->SendResponse(CSR, true); + return; + + case 16: // set block size + BlockSize = param; + Host->SendResponse(CSR, true); + return; + case 55: // ?? - printf("CMD55 %08X\n", param); CSR |= (1<<5); Host->SendResponse(CSR, true); return; @@ -291,13 +441,37 @@ void DSi_MMCStorage::SendACMD(u8 cmd, u32 param) { switch (cmd) { + case 6: // set bus width (TODO?) + printf("SET BUS WIDTH %08X\n", param); + Host->SendResponse(CSR, true); + return; + + case 13: // get SSR + Host->SendResponse(CSR, true); + Host->SendData(SSR, 64, true); + return; + case 41: // set operating conditions OCR &= 0xBF000000; OCR |= (param & 0x40FFFFFF); Host->SendResponse(OCR, true); SetState(0x01); return; + + case 42: // ??? + Host->SendResponse(CSR, true); + return; + + case 51: // get SCR + Host->SendResponse(CSR, true); + Host->SendData(SCR, 8, true); + return; } printf("MMC: unknown ACMD %d %08X\n", cmd, param); } + +void DSi_MMCStorage::ContinueTransfer() +{ + // +} diff --git a/src/DSi_SD.h b/src/DSi_SD.h index d223fac..ae8cd11 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -19,6 +19,10 @@ #ifndef DSI_SD_H #define DSI_SD_H +#include +#include "FIFO.h" + + class DSi_SDDevice; @@ -32,7 +36,9 @@ public: void DoSavestate(Savestate* file); + static void FinishSend(u32 param); void SendResponse(u32 val, bool last); + void SendData(u8* data, u32 len, bool last); u16 Read(u32 addr); void Write(u32 addr, u16 val); @@ -43,16 +49,28 @@ private: u16 PortSelect; u16 SoftReset; u16 SDClock; + u16 SDOption; u32 IRQStatus; // IF u32 IRQMask; // ~IE + u16 DataCtl; + u16 Data32IRQ; + u32 DataMode; // 0=16bit 1=32bit + u16 BlockCount16, BlockCount32, BlockCountInternal; + u16 BlockLen16, BlockLen32; + u16 StopAction; + u16 Command; u32 Param; u16 ResponseBuffer[8]; + FIFO* DataFIFO[2]; + u32 CurFIFO; // FIFO accessible for read/write + DSi_SDDevice* Ports[2]; + void ClearIRQ(u32 irq); void SetIRQ(u32 irq); }; @@ -64,6 +82,7 @@ public: ~DSi_SDDevice() {} virtual void SendCMD(u8 cmd, u32 param) = 0; + virtual void ContinueTransfer() = 0; protected: DSi_SDHost* Host; @@ -81,6 +100,8 @@ public: void SendCMD(u8 cmd, u32 param); void SendACMD(u8 cmd, u32 param); + void ContinueTransfer(); + private: bool Internal; char FilePath[1024]; @@ -92,6 +113,10 @@ private: u32 CSR; u32 OCR; u32 RCA; + u8 SCR[8]; + u8 SSR[64]; + + u32 BlockSize; void SetState(u32 state) { CSR &= ~(0xF << 9); CSR |= (state << 9); } }; diff --git a/src/NDS.h b/src/NDS.h index e6cd2ee..f87ffed 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -42,6 +42,9 @@ enum Event_Div, Event_Sqrt, + // DSi + Event_DSi_SDTransfer, + Event_MAX }; -- cgit v1.2.3 From d6bbc6f0f1ede57f0805137617ba670a49f7506f Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 18 Jun 2019 22:54:07 +0200 Subject: tremble upon the NDMA implementation that doesn't do much beyond getting stuck --- src/DMA.cpp | 6 -- src/DSi.cpp | 171 +++++++++++++++++++++++++++++++ src/DSi.h | 4 + src/DSi_NDMA.cpp | 301 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DSi_NDMA.h | 74 +++++++++++++- src/NDS.cpp | 4 + src/NDS.h | 5 +- 7 files changed, 556 insertions(+), 9 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DMA.cpp b/src/DMA.cpp index 2814264..0826d7a 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -20,15 +20,9 @@ #include "NDS.h" #include "DSi.h" #include "DMA.h" -#include "NDSCart.h" #include "GPU.h" -// NOTES ON DMA SHIT -// -// * could use optimized code paths for common types of DMA transfers. for example, VRAM -// have to profile it to see if it's actually worth doing - // DMA TIMINGS // diff --git a/src/DSi.cpp b/src/DSi.cpp index abd3bd6..0c9c26c 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -25,6 +25,7 @@ #include "sha1/sha1.h" #include "Platform.h" +#include "DSi_NDMA.h" #include "DSi_I2C.h" #include "DSi_SD.h" @@ -57,6 +58,9 @@ u32 NWRAMStart[2][3]; u32 NWRAMEnd[2][3]; u32 NWRAMMask[2][3]; +u32 NDMACnt[2]; +DSi_NDMA* NDMAs[8]; + DSi_SDHost* SDMMC; DSi_SDHost* SDIO; @@ -68,6 +72,15 @@ bool Init() { if (!DSi_I2C::Init()) return false; + NDMAs[0] = new DSi_NDMA(0, 0); + NDMAs[1] = new DSi_NDMA(0, 1); + NDMAs[2] = new DSi_NDMA(0, 2); + NDMAs[3] = new DSi_NDMA(0, 3); + NDMAs[4] = new DSi_NDMA(1, 0); + NDMAs[5] = new DSi_NDMA(1, 1); + NDMAs[6] = new DSi_NDMA(1, 2); + NDMAs[7] = new DSi_NDMA(1, 3); + SDMMC = new DSi_SDHost(0); SDIO = new DSi_SDHost(1); @@ -78,6 +91,8 @@ void DeInit() { DSi_I2C::DeInit(); + for (int i = 0; i < 8; i++) delete NDMAs[i]; + delete SDMMC; delete SDIO; } @@ -91,6 +106,9 @@ void Reset() NDS::ARM9->JumpTo(BootAddr[0]); NDS::ARM7->JumpTo(BootAddr[1]); + NDMACnt[0] = 0; NDMACnt[1] = 0; + for (int i = 0; i < 8; i++) NDMAs[i]->Reset(); + DSi_I2C::Reset(); SDMMC->Reset(); @@ -279,6 +297,40 @@ bool LoadNAND() } +void RunNDMAs(u32 cpu) +{ + // TODO: round-robin mode (requires DMA channels to have a subblock delay set) + + if (cpu == 0) + { + if (NDS::ARM9Timestamp >= NDS::ARM9Target) return; + + // + } + else + { + if (NDS::ARM7Timestamp >= NDS::ARM7Target) return; + + // + } +} + +void StallNDMAs() +{ + // TODO +} + +bool NDMAsRunning(u32 cpu) +{ + cpu <<= 2; + if (NDMAs[cpu+0]->IsRunning()) return true; + if (NDMAs[cpu+1]->IsRunning()) return true; + if (NDMAs[cpu+2]->IsRunning()) return true; + if (NDMAs[cpu+3]->IsRunning()) return true; + return false; +} + + // new WRAM mapping // TODO: find out what happens upon overlapping slots!! @@ -872,6 +924,36 @@ u32 ARM9IORead32(u32 addr) switch (addr) { case 0x04004010: return 1; // todo + + case 0x04004100: return NDMACnt[0]; + case 0x04004104: return NDMAs[0]->SrcAddr; + case 0x04004108: return NDMAs[0]->DstAddr; + case 0x0400410C: return NDMAs[0]->TotalLength; + case 0x04004110: return NDMAs[0]->BlockLength; + case 0x04004114: return NDMAs[0]->SubblockTimer; + case 0x04004118: return NDMAs[0]->FillData; + case 0x0400411C: return NDMAs[0]->Cnt; + case 0x04004120: return NDMAs[1]->SrcAddr; + case 0x04004124: return NDMAs[1]->DstAddr; + case 0x04004128: return NDMAs[1]->TotalLength; + case 0x0400412C: return NDMAs[1]->BlockLength; + case 0x04004130: return NDMAs[1]->SubblockTimer; + case 0x04004134: return NDMAs[1]->FillData; + case 0x04004138: return NDMAs[1]->Cnt; + case 0x0400413C: return NDMAs[2]->SrcAddr; + case 0x04004140: return NDMAs[2]->DstAddr; + case 0x04004144: return NDMAs[2]->TotalLength; + case 0x04004148: return NDMAs[2]->BlockLength; + case 0x0400414C: return NDMAs[2]->SubblockTimer; + case 0x04004150: return NDMAs[2]->FillData; + case 0x04004154: return NDMAs[2]->Cnt; + case 0x04004158: return NDMAs[3]->SrcAddr; + case 0x0400415C: return NDMAs[3]->DstAddr; + case 0x04004160: return NDMAs[3]->TotalLength; + case 0x04004164: return NDMAs[3]->BlockLength; + case 0x04004168: return NDMAs[3]->SubblockTimer; + case 0x0400416C: return NDMAs[3]->FillData; + case 0x04004170: return NDMAs[3]->Cnt; } return NDS::ARM9IORead32(addr); @@ -899,6 +981,35 @@ void ARM9IOWrite32(u32 addr, u32 val) { switch (addr) { + case 0x04004100: NDMACnt[0] = val & 0x800F0000; return; + case 0x04004104: NDMAs[0]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004108: NDMAs[0]->DstAddr = val & 0xFFFFFFFC; return; + case 0x0400410C: NDMAs[0]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004110: NDMAs[0]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004114: NDMAs[0]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004118: NDMAs[0]->FillData = val; return; + case 0x0400411C: NDMAs[0]->WriteCnt(val); return; + case 0x04004120: NDMAs[1]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004124: NDMAs[1]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004128: NDMAs[1]->TotalLength = val & 0x0FFFFFFF; return; + case 0x0400412C: NDMAs[1]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004130: NDMAs[1]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004134: NDMAs[1]->FillData = val; return; + case 0x04004138: NDMAs[1]->WriteCnt(val); return; + case 0x0400413C: NDMAs[2]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004140: NDMAs[2]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004144: NDMAs[2]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004148: NDMAs[2]->BlockLength = val & 0x00FFFFFF; return; + case 0x0400414C: NDMAs[2]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004150: NDMAs[2]->FillData = val; return; + case 0x04004154: NDMAs[2]->WriteCnt(val); return; + case 0x04004158: NDMAs[3]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x0400415C: NDMAs[3]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004160: NDMAs[3]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004164: NDMAs[3]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004168: NDMAs[3]->SubblockTimer = val & 0x0003FFFF; return; + case 0x0400416C: NDMAs[3]->FillData = val; return; + case 0x04004170: NDMAs[3]->WriteCnt(val); return; } return NDS::ARM9IOWrite32(addr, val); @@ -950,6 +1061,36 @@ u32 ARM7IORead32(u32 addr) case 0x0400021C: return NDS::IF2; case 0x04004008: return 0x80000000; // HAX + + case 0x04004100: return NDMACnt[1]; + case 0x04004104: return NDMAs[4]->SrcAddr; + case 0x04004108: return NDMAs[4]->DstAddr; + case 0x0400410C: return NDMAs[4]->TotalLength; + case 0x04004110: return NDMAs[4]->BlockLength; + case 0x04004114: return NDMAs[4]->SubblockTimer; + case 0x04004118: return NDMAs[4]->FillData; + case 0x0400411C: return NDMAs[4]->Cnt; + case 0x04004120: return NDMAs[5]->SrcAddr; + case 0x04004124: return NDMAs[5]->DstAddr; + case 0x04004128: return NDMAs[5]->TotalLength; + case 0x0400412C: return NDMAs[5]->BlockLength; + case 0x04004130: return NDMAs[5]->SubblockTimer; + case 0x04004134: return NDMAs[5]->FillData; + case 0x04004138: return NDMAs[5]->Cnt; + case 0x0400413C: return NDMAs[6]->SrcAddr; + case 0x04004140: return NDMAs[6]->DstAddr; + case 0x04004144: return NDMAs[6]->TotalLength; + case 0x04004148: return NDMAs[6]->BlockLength; + case 0x0400414C: return NDMAs[6]->SubblockTimer; + case 0x04004150: return NDMAs[6]->FillData; + case 0x04004154: return NDMAs[6]->Cnt; + case 0x04004158: return NDMAs[7]->SrcAddr; + case 0x0400415C: return NDMAs[7]->DstAddr; + case 0x04004160: return NDMAs[7]->TotalLength; + case 0x04004164: return NDMAs[7]->BlockLength; + case 0x04004168: return NDMAs[7]->SubblockTimer; + case 0x0400416C: return NDMAs[7]->FillData; + case 0x04004170: return NDMAs[7]->Cnt; } if (addr >= 0x04004800 && addr < 0x04004A00) @@ -1003,6 +1144,36 @@ void ARM7IOWrite32(u32 addr, u32 val) { case 0x04000218: NDS::IE2 = (val & 0x7FF7); NDS::UpdateIRQ(1); return; case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; + + case 0x04004100: NDMACnt[1] = val & 0x800F0000; return; + case 0x04004104: NDMAs[4]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004108: NDMAs[4]->DstAddr = val & 0xFFFFFFFC; return; + case 0x0400410C: NDMAs[4]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004110: NDMAs[4]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004114: NDMAs[4]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004118: NDMAs[4]->FillData = val; return; + case 0x0400411C: NDMAs[4]->WriteCnt(val); return; + case 0x04004120: NDMAs[5]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004124: NDMAs[5]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004128: NDMAs[5]->TotalLength = val & 0x0FFFFFFF; return; + case 0x0400412C: NDMAs[5]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004130: NDMAs[5]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004134: NDMAs[5]->FillData = val; return; + case 0x04004138: NDMAs[5]->WriteCnt(val); return; + case 0x0400413C: NDMAs[6]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004140: NDMAs[6]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004144: NDMAs[6]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004148: NDMAs[6]->BlockLength = val & 0x00FFFFFF; return; + case 0x0400414C: NDMAs[6]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004150: NDMAs[6]->FillData = val; return; + case 0x04004154: NDMAs[6]->WriteCnt(val); return; + case 0x04004158: NDMAs[7]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x0400415C: NDMAs[7]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004160: NDMAs[7]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004164: NDMAs[7]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004168: NDMAs[7]->SubblockTimer = val & 0x0003FFFF; return; + case 0x0400416C: NDMAs[7]->FillData = val; return; + case 0x04004170: NDMAs[7]->WriteCnt(val); return; } if (addr >= 0x04004800 && addr < 0x04004A00) diff --git a/src/DSi.h b/src/DSi.h index efd533a..32253a7 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -38,6 +38,10 @@ void Reset(); bool LoadBIOS(); bool LoadNAND(); +void RunNDMAs(u32 cpu); +void StallNDMAs(); +bool NDMAsRunning(u32 cpu); + void MapNWRAM_A(u32 num, u8 val); void MapNWRAM_B(u32 num, u8 val); void MapNWRAM_C(u32 num, u8 val); diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp index 6a524dd..a8055eb 100644 --- a/src/DSi_NDMA.cpp +++ b/src/DSi_NDMA.cpp @@ -15,3 +15,304 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include +#include "NDS.h" +#include "DSi.h" +#include "DSi_NDMA.h" +#include "GPU.h" + + + +DSi_NDMA::DSi_NDMA(u32 cpu, u32 num) +{ + CPU = cpu; + Num = num; + + Reset(); +} + +DSi_NDMA::~DSi_NDMA() +{ +} + +void DSi_NDMA::Reset() +{ + SrcAddr = 0; + DstAddr = 0; + TotalLength = 0; + BlockLength = 0; + SubblockTimer = 0; + FillData = 0; + Cnt = 0; + + StartMode = 0; + CurSrcAddr = 0; + CurDstAddr = 0; + SubblockLength = 0; + RemCount = 0; + IterCount = 0; + TotalRemCount = 0; + SrcAddrInc = 0; + DstAddrInc = 0; + + Running = false; + InProgress = false; +} + +void DSi_NDMA::DoSavestate(Savestate* file) +{ + // TODO! +} + +void DSi_NDMA::WriteCnt(u32 val) +{ + u32 oldcnt = Cnt; + Cnt = val; + + if ((!(oldcnt & 0x80000000)) && (val & 0x80000000)) // checkme + { + CurSrcAddr = SrcAddr; + CurDstAddr = DstAddr; + TotalRemCount = TotalLength; + + switch ((Cnt >> 10) & 0x3) + { + case 0: DstAddrInc = 1; break; + case 1: DstAddrInc = -1; break; + case 2: DstAddrInc = 0; break; + case 3: DstAddrInc = 1; printf("BAD NDMA DST INC MODE 3\n"); break; + } + + switch ((Cnt >> 13) & 0x3) + { + case 0: SrcAddrInc = 1; break; + case 1: SrcAddrInc = -1; break; + case 2: SrcAddrInc = 0; break; + case 3: SrcAddrInc = 0; break; // fill mode + } + + StartMode = (Cnt >> 24) & 0x1F; + if (StartMode > 0x10) StartMode = 0x10; + if (CPU == 1) StartMode |= 0x20; + + if ((StartMode & 0x1F) == 0x10) + Start(); + + if (StartMode != 0x10 && StartMode != 0x30) + printf("UNIMPLEMENTED ARM%d NDMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr); + } +} + +void DSi_NDMA::Start() +{ + if (Running) return; + + if (!InProgress) + { + RemCount = BlockLength; + if (!RemCount) + RemCount = 0x1000000; + } + + // TODO: how does GXFIFO DMA work with all the block shito? + IterCount = RemCount; + + if (IterCount > TotalRemCount) + IterCount = TotalRemCount; + + if (Cnt & (1<<12)) CurDstAddr = DstAddr; + if (Cnt & (1<<15)) CurSrcAddr = SrcAddr; + + printf("ARM%d NDMA%d %08X %02X %08X->%08X %d bytes\n", CPU?7:9, Num, Cnt, StartMode, CurSrcAddr, CurDstAddr, RemCount*4); + + //IsGXFIFODMA = (CPU == 0 && (CurSrcAddr>>24) == 0x02 && CurDstAddr == 0x04000400 && DstAddrInc == 0); + + // TODO eventually: not stop if we're running code in ITCM + + if (SubblockTimer & 0xFFFF) + printf("TODO! NDMA SUBBLOCK TIMER: %08X\n", SubblockTimer); + + if (NDS::DMAsRunning(CPU)) + Running = 1; + else + Running = 2; + + InProgress = true; + NDS::StopCPU(CPU, 1<<(Num+4)); +} + +void DSi_NDMA::Run() +{ + if (!Running) return; + if (CPU == 0) return Run9(); + else return Run7(); +} + +void DSi_NDMA::Run9() +{ + if (NDS::ARM9Timestamp >= NDS::ARM9Target) return; + + Executing = true; + + // add NS penalty for first accesses in burst + bool burststart = (Running == 2); + Running = 1; + + s32 unitcycles; + //s32 lastcycles = cycles; + + bool dofill = ((Cnt >> 13) & 0x3) == 3; + + if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02) + { + unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2]; + } + else + { + unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][3] + NDS::ARM9MemTimings[CurDstAddr >> 14][3]; + if ((CurSrcAddr >> 24) == (CurDstAddr >> 24)) + unitcycles++; + else if ((CurSrcAddr >> 24) == 0x02) + unitcycles--; + + /*if (burststart) + { + cycles -= 2; + cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2]); + cycles += unitcycles; + }*/ + } + + while (IterCount > 0 && !Stall) + { + NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); + + if (dofill) + DSi::ARM9Write32(CurDstAddr, FillData); + else + DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr)); + + CurSrcAddr += SrcAddrInc<<2; + CurDstAddr += DstAddrInc<<2; + IterCount--; + RemCount--; + TotalRemCount--; + + if (NDS::ARM9Timestamp >= NDS::ARM9Target) break; + } + + Executing = false; + Stall = false; + + if (RemCount) + { + if (IterCount == 0) + { + Running = 0; + NDS::ResumeCPU(0, 1<<(Num+4)); + + //if (StartMode == 0x07) + // GPU3D::CheckFIFODMA(); + } + + return; + } + + if ((StartMode & 0x1F) == 0x10) // CHECKME + Cnt &= ~(1<<31); + else if (!(Cnt & (1<<29))) + { + if (TotalRemCount == 0) + Cnt &= ~(1<<31); + } + + if (Cnt & (1<<30)) + NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); + + Running = 0; + InProgress = false; + NDS::ResumeCPU(0, 1<<(Num+4)); +} + +void DSi_NDMA::Run7() +{ + if (NDS::ARM7Timestamp >= NDS::ARM7Target) return; + + Executing = true; + + // add NS penalty for first accesses in burst + bool burststart = (Running == 2); + Running = 1; + + s32 unitcycles; + //s32 lastcycles = cycles; + + bool dofill = ((Cnt >> 13) & 0x3) == 3; + + if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02) + { + unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2]; + } + else + { + unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][3] + NDS::ARM7MemTimings[CurDstAddr >> 15][3]; + if ((CurSrcAddr >> 23) == (CurDstAddr >> 23)) + unitcycles++; + else if ((CurSrcAddr >> 24) == 0x02) + unitcycles--; + + /*if (burststart) + { + cycles -= 2; + cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2]); + cycles += unitcycles; + }*/ + } + + while (IterCount > 0 && !Stall) + { + NDS::ARM7Timestamp += unitcycles; + + if (dofill) + DSi::ARM7Write32(CurDstAddr, FillData); + else + DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr)); + + CurSrcAddr += SrcAddrInc<<2; + CurDstAddr += DstAddrInc<<2; + IterCount--; + RemCount--; + + if (NDS::ARM7Timestamp >= NDS::ARM7Target) break; + } + + Executing = false; + Stall = false; + + if (RemCount) + { + if (IterCount == 0) + { + Running = 0; + NDS::ResumeCPU(1, 1<<(Num+4)); + } + + return; + } + + if ((StartMode & 0x1F) == 0x10) // CHECKME + Cnt &= ~(1<<31); + else if (!(Cnt & (1<<29))) + { + if (TotalRemCount == 0) + Cnt &= ~(1<<31); + } + + if (Cnt & (1<<30)) + NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); + + Running = 0; + InProgress = false; + NDS::ResumeCPU(1, 1<<(Num+4)); +} diff --git a/src/DSi_NDMA.h b/src/DSi_NDMA.h index 6661652..d7b7483 100644 --- a/src/DSi_NDMA.h +++ b/src/DSi_NDMA.h @@ -19,6 +19,78 @@ #ifndef DSI_NDMA_H #define DSI_NDMA_H -// +#include "types.h" + +class DSi_NDMA +{ +public: + DSi_NDMA(u32 cpu, u32 num); + ~DSi_NDMA(); + + void Reset(); + + void DoSavestate(Savestate* file); + + void WriteCnt(u32 val); + void Start(); + + void Run(); + + void Run9(); + void Run7(); + + bool IsInMode(u32 mode) + { + return ((mode == StartMode) && (Cnt & 0x80000000)); + } + + bool IsRunning() { return Running!=0; } + + void StartIfNeeded(u32 mode) + { + if ((mode == StartMode) && (Cnt & 0x80000000)) + Start(); + } + + void StopIfNeeded(u32 mode) + { + if (mode == StartMode) + Cnt &= ~0x80000000; + } + + void StallIfRunning() + { + if (Executing) Stall = true; + } + + u32 SrcAddr; + u32 DstAddr; + u32 TotalLength; // total length, when transferring multiple blocks + u32 BlockLength; // length of one transfer + u32 SubblockTimer; // optional delay between subblocks (only in round-robin mode) + u32 FillData; + u32 Cnt; + +private: + u32 CPU, Num; + + u32 StartMode; + u32 CurSrcAddr; + u32 CurDstAddr; + u32 SubblockLength; // length transferred per run when delay is used + u32 RemCount; + u32 IterCount; + u32 TotalRemCount; + u32 SrcAddrInc; + u32 DstAddrInc; + + u32 Running; + bool InProgress; + + bool Executing; + bool Stall; + + bool IsGXFIFODMA; +}; #endif // DSI_NDMA_H diff --git a/src/NDS.cpp b/src/NDS.cpp index 414f87c..e20f62f 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -827,6 +827,7 @@ u32 RunFrame() if (!(CPUStop & 0x80000000)) DMAs[1]->Run(); if (!(CPUStop & 0x80000000)) DMAs[2]->Run(); if (!(CPUStop & 0x80000000)) DMAs[3]->Run(); + DSi::RunNDMAs(0); } else { @@ -849,6 +850,7 @@ u32 RunFrame() DMAs[5]->Run(); DMAs[6]->Run(); DMAs[7]->Run(); + DSi::RunNDMAs(1); } else { @@ -1153,6 +1155,7 @@ void GXFIFOStall() DMAs[1]->StallIfRunning(); DMAs[2]->StallIfRunning(); DMAs[3]->StallIfRunning(); + DSi::StallNDMAs(); } } @@ -1367,6 +1370,7 @@ bool DMAsRunning(u32 cpu) if (DMAs[cpu+1]->IsRunning()) return true; if (DMAs[cpu+2]->IsRunning()) return true; if (DMAs[cpu+3]->IsRunning()) return true; + if (DSi::NDMAsRunning(cpu>>2)) return true; return false; } diff --git a/src/NDS.h b/src/NDS.h index f87ffed..850e829 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -101,7 +101,7 @@ enum IRQ2_DSi_GPIO18_0 = 0, IRQ2_DSi_GPIO18_1, IRQ2_DSi_GPIO18_2, - IRQ2_DSi_Unused35, + IRQ2_DSi_Unused3, IRQ2_DSi_GPIO33_0, IRQ2_DSi_Headphone, IRQ2_DSi_PowerButton, @@ -138,7 +138,6 @@ extern u64 ARM9Timestamp, ARM9Target; extern u64 ARM7Timestamp, ARM7Target; extern u32 ARM9ClockShift; -// hax extern u32 IME[2]; extern u32 IE[2]; extern u32 IF[2]; @@ -146,6 +145,8 @@ extern u32 IE2; extern u32 IF2; extern Timer Timers[8]; +extern u32 CPUStop; + extern u16 PowerControl9; extern u16 ExMemCnt[2]; -- cgit v1.2.3 From 81dde71ebac19cf9a68dd7a2a41561cbcbfacc68 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 19 Jun 2019 14:24:49 +0200 Subject: add AES, fix a bunch of bugs we're getting an error screen! wee --- src/ARM.cpp | 37 ------- src/DSi.cpp | 55 ++++++++++ src/DSi.h | 3 + src/DSi_AES.cpp | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DSi_AES.h | 26 ++++- src/DSi_NDMA.cpp | 21 ++-- src/DSi_SD.cpp | 21 ++-- src/NDS.cpp | 6 +- 8 files changed, 416 insertions(+), 56 deletions(-) (limited to 'src/DSi.h') diff --git a/src/ARM.cpp b/src/ARM.cpp index 60dec9a..b7fe3c7 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -239,36 +239,6 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr) else addr &= ~0x1; } - /*if (addr==0x037D4668) printf("MYSTERY START\n"); - if (addr==0x037CA71C) printf("MYSTERY END\n"); - if (addr==0x037CCD68) printf("atomic_store %08X %08X, %08X\n", R[0], R[1], R[15]); - if (addr==0x037CDD00) printf("zog %08X\n", R[15]);*/ - /*if (addr==0x037CDC00) printf("sendcmd %08X %08X\n", R[0], R[15]); - if (addr==0x037CA700) printf("prepare CID, %08X\n", R[15]); - if(addr==0x037D4498) printf("READ SHITTY FIFO. %08X\n", R[15]); - if (addr==0x037CCD68) printf("atomic_store %08X %08X, %08X\n", R[0], R[1], R[15]); - if (addr>=0x037CEE00 && addr<=0x037CEE30) printf("shitty loop: %08X->%08X\n", R[15], addr); - if (R[15]==0x037CCD8C) printf("BERG!!! %08X\n", addr); - if (addr==0x037CD600) printf("XFER IRQ HANDLER\n"); - if (R[15]==0x037CD62C) printf("TERRIBLE HANDLER: %08X\n", addr); - if (addr==0x037CCE24) printf("SD IRQ HANDLER\n"); - if (addr==0x037CCD94) printf("atomic_load %08X %08X, %08X\n", R[0], R[1], R[15]); - if (addr==0x037CEB7C) printf("CHECK CSR RESULT. %08X %08X %08X, %08X\n", R[0], R[1], R[2], R[15]); - if (R[15]==0x037CEC6C) printf("RETURN FROM CSR CHECK: %08X %08X\n", R[0], R[3]+0x38); - if (addr==0x037CB2AC) printf("ZOG!\n"); - if (addr==0x037CB2A0) printf("GONP %08X %08X, %08X\n", R[1]+0x28, R[3]+0x34, R[15]); - if (addr==0x037CCFC0) printf("SDMMC TIMEOUT. %08X\n", R[15]); - if (addr==0x037D68A8) printf("BARKBARKBARK. %08X\n", R[15]); - if (addr==0x037CCF04) printf("BAKAAA\n"); - if (addr==0x037D6988) printf("MORPMORPMORPMORPMORPMORPMORPMORPMORP %08X\n", R[15]); - if (addr==0x37D6904) printf("TIMEOUT FARTORED! %08X, %08X %08X, %08X\n", R[4], R[3], R[12], R[15]); - // TIMEOUT FARTORED! 037E89B8, 00000000 00200BFB, 037D68FC - if (addr==0x037CD660) printf("BRAAAAAAAAAAAP %08X\n", R[15]); - if (addr==0x037CD798) printf("BRAAPP SHATORED. %08X, %08X %08X\n", R[0], R[1], R[2]); - if (addr==0x037CCD34) printf("atomic_and %08X %08X, %08X\n", R[0], R[1], R[15]);*/ - // atomic_and 0400481C 0000FFE7, 037CD850 - - u32 oldregion = R[15] >> 23; u32 newregion = addr >> 23; @@ -607,13 +577,6 @@ void ARMv4::Execute() } else AddCycles_C(); - - /*if (R[15]==0x037CEE18) printf("SHITTY POINTER = %08X\n", R[0]+0x34); - if (R[15]==0x037CEE1C) printf("SHITTY FLAG = %08X\n", R[0]); - if (R[15]==0x037D68F0) printf("TIMESTAMP THING = %08X:%08X, CUR=%08X:%08X, ptr=%08X\n", - R[3], R[12], R[1], R[0], R[4]); - //if (R[15]==0x037CB29C) printf("GLORG!!! %08X\n", R[3]+0x34); 037E8A8C - if (R[15]==0x037CD730) printf("COUNT OF SHITO. %08X %08X\n", R[0], R[2]);*/ } // TODO optimize this shit!!! diff --git a/src/DSi.cpp b/src/DSi.cpp index fc590e1..fd58872 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -28,6 +28,7 @@ #include "DSi_NDMA.h" #include "DSi_I2C.h" #include "DSi_SD.h" +#include "DSi_AES.h" namespace NDS @@ -71,6 +72,7 @@ u8 eMMC_CID[16]; bool Init() { if (!DSi_I2C::Init()) return false; + if (!DSi_AES::Init()) return false; NDMAs[0] = new DSi_NDMA(0, 0); NDMAs[1] = new DSi_NDMA(0, 1); @@ -90,6 +92,7 @@ bool Init() void DeInit() { DSi_I2C::DeInit(); + DSi_AES::DeInit(); for (int i = 0; i < 8; i++) delete NDMAs[i]; @@ -110,6 +113,7 @@ void Reset() for (int i = 0; i < 8; i++) NDMAs[i]->Reset(); DSi_I2C::Reset(); + DSi_AES::Reset(); SDMMC->Reset(); SDIO->Reset(); @@ -336,6 +340,24 @@ bool NDMAsRunning(u32 cpu) return false; } +void CheckNDMAs(u32 cpu, u32 mode) +{ + cpu <<= 2; + NDMAs[cpu+0]->StartIfNeeded(mode); + NDMAs[cpu+1]->StartIfNeeded(mode); + NDMAs[cpu+2]->StartIfNeeded(mode); + NDMAs[cpu+3]->StartIfNeeded(mode); +} + +void StopNDMAs(u32 cpu, u32 mode) +{ + cpu <<= 2; + NDMAs[cpu+0]->StopIfNeeded(mode); + NDMAs[cpu+1]->StopIfNeeded(mode); + NDMAs[cpu+2]->StopIfNeeded(mode); + NDMAs[cpu+3]->StopIfNeeded(mode); +} + // new WRAM mapping // TODO: find out what happens upon overlapping slots!! @@ -1097,6 +1119,9 @@ u32 ARM7IORead32(u32 addr) case 0x04004168: return NDMAs[7]->SubblockTimer; case 0x0400416C: return NDMAs[7]->FillData; case 0x04004170: return NDMAs[7]->Cnt; + + case 0x04004400: return DSi_AES::ReadCnt(); + case 0x0400440C: return DSi_AES::ReadOutputFIFO(); } if (addr >= 0x04004800 && addr < 0x04004A00) @@ -1182,6 +1207,36 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x04004168: NDMAs[7]->SubblockTimer = val & 0x0003FFFF; return; case 0x0400416C: NDMAs[7]->FillData = val; return; case 0x04004170: NDMAs[7]->WriteCnt(val); return; + + case 0x04004400: DSi_AES::WriteCnt(val); return; + case 0x04004404: DSi_AES::WriteBlkCnt(val); return; + case 0x04004408: DSi_AES::WriteInputFIFO(val); return; + } + + if (addr >= 0x04004420 && addr < 0x04004430) + { + addr -= 0x04004420; + DSi_AES::WriteIV(addr, val, 0xFFFFFFFF); + return; + } + if (addr >= 0x04004430 && addr < 0x04004440) + { + addr -= 0x04004430; + DSi_AES::WriteMAC(addr, val, 0xFFFFFFFF); + return; + } + if (addr >= 0x04004440 && addr < 0x04004500) + { + addr -= 0x04004440; + int n = 0; + while (addr > 0x30) { addr -= 0x30; n++; } + + switch (addr >> 4) + { + case 0: DSi_AES::WriteKeyNormal(n, addr&0xF, val, 0xFFFFFFFF); return; + case 1: DSi_AES::WriteKeyX(n, addr&0xF, val, 0xFFFFFFFF); return; + case 2: DSi_AES::WriteKeyY(n, addr&0xF, val, 0xFFFFFFFF); return; + } } if (addr >= 0x04004800 && addr < 0x04004A00) diff --git a/src/DSi.h b/src/DSi.h index 32253a7..642a56a 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -26,6 +26,7 @@ namespace DSi { extern u8 eMMC_CID[16]; +extern u64 ConsoleID; extern DSi_SDHost* SDMMC; extern DSi_SDHost* SDIO; @@ -41,6 +42,8 @@ bool LoadNAND(); void RunNDMAs(u32 cpu); void StallNDMAs(); bool NDMAsRunning(u32 cpu); +void CheckNDMAs(u32 cpu, u32 mode); +void StopNDMAs(u32 cpu, u32 mode); void MapNWRAM_A(u32 num, u8 val); void MapNWRAM_B(u32 num, u8 val); diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index 6a524dd..8271e3e 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -15,3 +15,306 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include +#include +#include "DSi.h" +#include "DSi_AES.h" +#include "FIFO.h" +#include "tiny-AES-c/aes.hpp" + + +namespace DSi_AES +{ + +u32 Cnt; + +u32 BlkCnt; +u32 RemBlocks; + +u32 InputDMASize, OutputDMASize; +u32 AESMode; + +FIFO* InputFIFO; +FIFO* OutputFIFO; + +u8 IV[16]; + +u8 KeyNormal[4][16]; +u8 KeyX[4][16]; +u8 KeyY[4][16]; + +u8 CurKey[16]; + +AES_ctx Ctx; + + +void Swap16(u8* dst, u8* src) +{ + for (int i = 0; i < 16; i++) + dst[i] = src[15-i]; +} + +void ROL16(u8* val, u32 n) +{ + u32 n_coarse = n >> 3; + u32 n_fine = n & 7; + u8 tmp[16]; + + for (u32 i = 0; i < 16; i++) + { + tmp[i] = val[(i - n_coarse) & 0xF]; + } + + for (u32 i = 0; i < 16; i++) + { + val[i] = (tmp[i] << n_fine) | (tmp[(i - 1) & 0xF] >> (8-n_fine)); + } +} + +#define _printhex(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[z]); printf("\n"); } + + +bool Init() +{ + InputFIFO = new FIFO(16); + OutputFIFO = new FIFO(16); + + const u8 zero[16] = {0}; + AES_init_ctx_iv(&Ctx, zero, zero); + + return true; +} + +void DeInit() +{ + delete InputFIFO; + delete OutputFIFO; +} + +void Reset() +{ + Cnt = 0; + + BlkCnt = 0; + RemBlocks = 0; + + InputDMASize = 0; + OutputDMASize = 0; + AESMode = 0; + + InputFIFO->Clear(); + OutputFIFO->Clear(); + + memset(KeyNormal, 0, sizeof(KeyNormal)); + memset(KeyX, 0, sizeof(KeyX)); + memset(KeyY, 0, sizeof(KeyY)); + + memset(CurKey, 0, sizeof(CurKey)); + + // initialize keys, as per GBAtek + + // slot 3: console-unique eMMC crypto + *(u32*)&KeyX[3][0] = (u32)DSi::ConsoleID; + *(u32*)&KeyX[3][4] = (u32)DSi::ConsoleID ^ 0x24EE6906; + *(u32*)&KeyX[3][8] = (u32)(DSi::ConsoleID >> 32) ^ 0xE65B601D; + *(u32*)&KeyX[3][12] = (u32)(DSi::ConsoleID >> 32); + *(u32*)&KeyY[3][0] = 0x0AB9DC76; + *(u32*)&KeyY[3][4] = 0xBD4DC4D3; + *(u32*)&KeyY[3][8] = 0x202DDD1D; +} + + +void ProcessBlock_CTR() +{ + u8 data[16]; + u8 data_rev[16]; + + *(u32*)&data[0] = InputFIFO->Read(); + *(u32*)&data[4] = InputFIFO->Read(); + *(u32*)&data[8] = InputFIFO->Read(); + *(u32*)&data[12] = InputFIFO->Read(); + + //printf("AES-CTR: INPUT: "); _printhex(data, 16); + + Swap16(data_rev, data); + AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16); + Swap16(data, data_rev); + + //printf("AES-CTR: OUTPUT: "); _printhex(data, 16); + + OutputFIFO->Write(*(u32*)&data[0]); + OutputFIFO->Write(*(u32*)&data[4]); + OutputFIFO->Write(*(u32*)&data[8]); + OutputFIFO->Write(*(u32*)&data[12]); +} + + +u32 ReadCnt() +{ + u32 ret = Cnt; + + ret |= InputFIFO->Level(); + ret |= (OutputFIFO->Level() << 5); + + return ret; +} + +void WriteCnt(u32 val) +{ + u32 oldcnt = Cnt; + Cnt = val & 0xFC1FF000; + + if (val & (1<<10)) InputFIFO->Clear(); + if (val & (1<<11)) OutputFIFO->Clear(); + + u32 dmasize[4] = {4, 8, 12, 16}; + InputDMASize = dmasize[3 - ((val >> 12) & 0x3)]; + OutputDMASize = dmasize[(val >> 14) & 0x3]; + + AESMode = (val >> 28) & 0x3; + if (AESMode < 2) printf("AES-CCM TODO\n"); + + if (val & (1<<24)) + { + u32 slot = (val >> 26) & 0x3; + memcpy(CurKey, KeyNormal[slot], 16); + + //printf("AES: key(%d): ", slot); _printhex(CurKey, 16); + + u8 tmp[16]; + Swap16(tmp, CurKey); + AES_init_ctx(&Ctx, tmp); + } + + if (!(oldcnt & (1<<31)) && (val & (1<<31))) + { + // transfer start (checkme) + RemBlocks = BlkCnt >> 16; + } + + printf("AES CNT: %08X / mode=%d inDMA=%d outDMA=%d blocks=%d\n", + val, AESMode, InputDMASize, OutputDMASize, RemBlocks); +} + +void WriteBlkCnt(u32 val) +{ + BlkCnt = val; +} + +u32 ReadOutputFIFO() +{ + return OutputFIFO->Read(); +} + +void WriteInputFIFO(u32 val) +{ + // TODO: add some delay to processing + + InputFIFO->Write(val); + + if (!(Cnt & (1<<31))) return; + + while (InputFIFO->Level() >= 4 && RemBlocks > 0) + { + switch (AESMode) + { + case 2: + case 3: ProcessBlock_CTR(); break; + default: + // dorp + OutputFIFO->Write(InputFIFO->Read()); + OutputFIFO->Write(InputFIFO->Read()); + OutputFIFO->Write(InputFIFO->Read()); + OutputFIFO->Write(InputFIFO->Read()); + } + + RemBlocks--; + } + + if (OutputFIFO->Level() >= OutputDMASize) + { + // trigger DMA + DSi::CheckNDMAs(1, 0x2B); + } + // TODO: DMA the other way around + + if (RemBlocks == 0) + { + Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ2(NDS::IRQ2_DSi_AES); + } +} + + +void WriteIV(u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&IV[offset]; + + *(u32*)&IV[offset] = (old & ~mask) | (val & mask); + + //printf("AES: IV: "); _printhex(IV, 16); + + u8 tmp[16]; + Swap16(tmp, IV); + AES_ctx_set_iv(&Ctx, tmp); +} + +void WriteMAC(u32 offset, u32 val, u32 mask) +{ + // +} + +void DeriveNormalKey(u32 slot) +{ + const u8 key_const[16] = {0xFF, 0xFE, 0xFB, 0x4E, 0x29, 0x59, 0x02, 0x58, 0x2A, 0x68, 0x0F, 0x5F, 0x1A, 0x4F, 0x3E, 0x79}; + u8 tmp[16]; + + //printf("keyX: "); _printhex(KeyX[slot], 16); + //printf("keyY: "); _printhex(KeyY[slot], 16); + + for (int i = 0; i < 16; i++) + tmp[i] = KeyX[slot][i] ^ KeyY[slot][i]; + + u32 carry = 0; + for (int i = 0; i < 16; i++) + { + u32 res = tmp[i] + key_const[15-i] + carry; + tmp[i] = res & 0xFF; + carry = res >> 8; + } + + ROL16(tmp, 42); + + //printf("derive normalkey %d\n", slot); _printhex(tmp, 16); + + memcpy(KeyNormal[slot], tmp, 16); +} + +void WriteKeyNormal(u32 slot, u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&KeyNormal[slot][offset]; + + *(u32*)&KeyNormal[slot][offset] = (old & ~mask) | (val & mask); +} + +void WriteKeyX(u32 slot, u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&KeyX[slot][offset]; + + *(u32*)&KeyX[slot][offset] = (old & ~mask) | (val & mask); +} + +void WriteKeyY(u32 slot, u32 offset, u32 val, u32 mask) +{ + u32 old = *(u32*)&KeyY[slot][offset]; + + *(u32*)&KeyY[slot][offset] = (old & ~mask) | (val & mask); + + if (offset >= 0xC) + { + DeriveNormalKey(slot); + } +} + +} diff --git a/src/DSi_AES.h b/src/DSi_AES.h index 028523a..7c388f5 100644 --- a/src/DSi_AES.h +++ b/src/DSi_AES.h @@ -19,6 +19,30 @@ #ifndef DSI_AES_H #define DSI_AES_H -// +#include "types.h" + +namespace DSi_AES +{ + +extern u32 Cnt; + +bool Init(); +void DeInit(); +void Reset(); + +u32 ReadCnt(); +void WriteCnt(u32 val); +void WriteBlkCnt(u32 val); + +u32 ReadOutputFIFO(); +void WriteInputFIFO(u32 val); + +void WriteIV(u32 offset, u32 val, u32 mask); +void WriteMAC(u32 offset, u32 val, u32 mask); +void WriteKeyNormal(u32 slot, u32 offset, u32 val, u32 mask); +void WriteKeyX(u32 slot, u32 offset, u32 val, u32 mask); +void WriteKeyY(u32 slot, u32 offset, u32 val, u32 mask); + +} #endif // DSI_AES_H diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp index 7c0b2a1..aed78af 100644 --- a/src/DSi_NDMA.cpp +++ b/src/DSi_NDMA.cpp @@ -99,7 +99,8 @@ void DSi_NDMA::WriteCnt(u32 val) if ((StartMode & 0x1F) == 0x10) Start(); - if (StartMode != 0x10 && StartMode != 0x30) + if (StartMode != 0x10 && StartMode != 0x30 && + StartMode != 0x2B) printf("UNIMPLEMENTED ARM%d NDMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr); } } @@ -223,16 +224,19 @@ void DSi_NDMA::Run9() } if ((StartMode & 0x1F) == 0x10) // CHECKME + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); + } else if (!(Cnt & (1<<29))) { if (TotalRemCount == 0) + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); + } } - if (Cnt & (1<<30)) - NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); - Running = 0; InProgress = false; NDS::ResumeCPU(0, 1<<(Num+4)); @@ -305,16 +309,19 @@ void DSi_NDMA::Run7() } if ((StartMode & 0x1F) == 0x10) // CHECKME + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); + } else if (!(Cnt & (1<<29))) { if (TotalRemCount == 0) + { Cnt &= ~(1<<31); + if (Cnt & (1<<30)) NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); + } } - if (Cnt & (1<<30)) - NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); - Running = 0; InProgress = false; NDS::ResumeCPU(1, 1<<(Num+4)); diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 42b515c..bb3c4a4 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -473,10 +473,10 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) case 2: case 10: // get CID - Host->SendResponse(*(u32*)&CID[0], false); - Host->SendResponse(*(u32*)&CID[1], false); - Host->SendResponse(*(u32*)&CID[2], false); - Host->SendResponse(*(u32*)&CID[3], true); + Host->SendResponse(*(u32*)&CID[12], false); + Host->SendResponse(*(u32*)&CID[8], false); + Host->SendResponse(*(u32*)&CID[4], false); + Host->SendResponse(*(u32*)&CID[0], true); //if (cmd == 2) SetState(0x02); return; @@ -502,13 +502,18 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) return; case 9: // get CSD - Host->SendResponse(*(u32*)&CSD[0], false); - Host->SendResponse(*(u32*)&CSD[1], false); - Host->SendResponse(*(u32*)&CSD[2], false); - Host->SendResponse(*(u32*)&CSD[3], true); + Host->SendResponse(*(u32*)&CSD[12], false); + Host->SendResponse(*(u32*)&CSD[8], false); + Host->SendResponse(*(u32*)&CSD[4], false); + Host->SendResponse(*(u32*)&CSD[0], true); return; case 12: // stop operation + // TODO + Host->SendResponse(CSR, true); + return; + + case 13: // get status Host->SendResponse(CSR, true); return; diff --git a/src/NDS.cpp b/src/NDS.cpp index e20f62f..7513d57 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1582,12 +1582,12 @@ void debug(u32 param) printf("ARM7 PC=%08X LR=%08X %08X\n", ARM7->R[15], ARM7->R[14], ARM7->R_IRQ[1]); printf("ARM9 IME=%08X IE=%08X IF=%08X\n", IME[0], IE[0], IF[0]); - printf("ARM7 IME=%08X IE=%08X IF=%08X\n", IME[1], IE[1], IF[1]); + printf("ARM7 IME=%08X IE=%08X IF=%08X IE2=%04X IF2=%04X\n", IME[1], IE[1], IF[1], IE2, IF2); //for (int i = 0; i < 9; i++) // printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]); - FILE* + /*FILE* shit = fopen("debug/card.bin", "wb"); for (u32 i = 0x02000000; i < 0x02400000; i+=4) { @@ -1599,7 +1599,7 @@ void debug(u32 param) u32 val = ARM7Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit); + fclose(shit);*/ } -- cgit v1.2.3 From c5e14074c3b999d09b8a8612cfa7f011423e83ab Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 3 Jul 2019 12:37:34 +0200 Subject: * add SCFG_EXT * quick hack to detect cartridges --- src/DSi.cpp | 24 +++++++++++++++++++++--- src/DSi.h | 2 ++ src/DSi_I2C.cpp | 8 ++++---- src/NDSCart.cpp | 8 +++++--- 4 files changed, 32 insertions(+), 10 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index e601da9..26a67f4 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -46,6 +46,7 @@ u32 BootAddr[2]; u16 SCFG_Clock9; u16 SCFG_Clock7; +u32 SCFG_EXT[2]; u32 SCFG_MC; u32 MBK[2][9]; @@ -127,7 +128,9 @@ void Reset() SCFG_Clock9 = 0x0187; // CHECKME SCFG_Clock7 = 0x0187; - SCFG_MC = 0x0011; + SCFG_EXT[0] = 0x8307F100; + SCFG_EXT[1] = 0x93FFFB06; + SCFG_MC = 0x0010;//0x0011; // LCD init flag GPU::DispStat[0] |= (1<<6); @@ -1038,7 +1041,7 @@ u32 ARM9IORead32(u32 addr) { switch (addr) { - case 0x04004008: return 0x8307F100; + case 0x04004008: return SCFG_EXT[0]; case 0x04004010: return SCFG_MC & 0xFFFF; case 0x04004040: return MBK[0][0]; @@ -1183,6 +1186,14 @@ void ARM9IOWrite32(u32 addr, u32 val) { switch (addr) { + case 0x04004008: + SCFG_EXT[0] &= ~0x8007F19F; + SCFG_EXT[0] |= (val & 0x8007F19F); + SCFG_EXT[1] &= ~0x0000F080; + SCFG_EXT[1] |= (val & 0x0000F080); + printf("SCFG_EXT = %08X / %08X (val9 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val); + return; + case 0x04004040: MapNWRAM_A(0, val & 0xFF); MapNWRAM_A(1, (val >> 8) & 0xFF); @@ -1333,7 +1344,7 @@ u32 ARM7IORead32(u32 addr) case 0x04000218: return NDS::IE2; case 0x0400021C: return NDS::IF2; - case 0x04004008: return 0x80000000; // HAX + case 0x04004008: return SCFG_EXT[1]; case 0x04004010: return SCFG_MC; case 0x04004040: return MBK[1][0]; @@ -1449,6 +1460,13 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x04000218: NDS::IE2 = (val & 0x7FF7); NDS::UpdateIRQ(1); return; case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; + case 0x04004008: + SCFG_EXT[0] &= ~0x03000000; + SCFG_EXT[0] |= (val & 0x03000000); + SCFG_EXT[1] &= ~0x93FF0F07; + SCFG_EXT[1] |= (val & 0x93FF0F07); + printf("SCFG_EXT = %08X / %08X (val7 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val); + return; case 0x04004010: val &= 0xFFFF800C; if ((val & 0xC) == 0xC) val &= ~0xC; // hax diff --git a/src/DSi.h b/src/DSi.h index 642a56a..db585b4 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -31,6 +31,8 @@ extern u64 ConsoleID; extern DSi_SDHost* SDMMC; extern DSi_SDHost* SDIO; +extern u8 ITCMInit[0x8000]; + bool Init(); void DeInit(); diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp index 845dd9d..e88858b 100644 --- a/src/DSi_I2C.cpp +++ b/src/DSi_I2C.cpp @@ -72,7 +72,7 @@ void Reset() void Start() { - printf("BPTWL: start\n"); + //printf("BPTWL: start\n"); } u8 Read(bool last) @@ -83,7 +83,7 @@ u8 Read(bool last) return 0; } - printf("BPTWL: read %02X -> %02X\n", CurPos, Registers[CurPos]); + //printf("BPTWL: read %02X -> %02X\n", CurPos, Registers[CurPos]); return Registers[CurPos++]; } @@ -98,7 +98,7 @@ void Write(u8 val, bool last) if (CurPos == -1) { CurPos = val; - printf("BPTWL: reg=%02X\n", val); + //printf("BPTWL: reg=%02X\n", val); return; } @@ -113,7 +113,7 @@ void Write(u8 val, bool last) Registers[CurPos] = val; } - printf("BPTWL: write %02X -> %02X\n", CurPos, val); + //printf("BPTWL: write %02X -> %02X\n", CurPos, val); CurPos++; // CHECKME } diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 0ecd304..0bb8b5c 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -19,6 +19,7 @@ #include #include #include "NDS.h" +#include "DSi.h" #include "NDSCart.h" #include "ARM.h" #include "CRC32.h" @@ -558,7 +559,8 @@ void Key1_ApplyKeycode(u32* keycode, u32 mod) void Key1_InitKeycode(u32 idcode, u32 level, u32 mod) { - memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax + //memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax + memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax u32 keycode[3] = {idcode, idcode>>1, idcode<<1}; if (level >= 1) Key1_ApplyKeycode(keycode, mod); @@ -1185,11 +1187,11 @@ void WriteROMCnt(u32 val) *(u32*)&cmd[4] = *(u32*)&ROMCommand[4]; } - /*printf("ROM COMMAND %04X %08X %02X%02X%02X%02X%02X%02X%02X%02X SIZE %04X\n", + printf("ROM COMMAND %04X %08X %02X%02X%02X%02X%02X%02X%02X%02X SIZE %04X\n", SPICnt, ROMCnt, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], - datasize);*/ + datasize); switch (cmd[0]) { -- cgit v1.2.3 From 36c741241a3efbfeb81a447c53917b1ab586fe73 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 4 Aug 2019 16:46:02 +0200 Subject: support DSi-mode carts except they need to have the DSi-mode shit encrypted --- src/DSi.cpp | 27 ++++++++++++------ src/DSi.h | 1 + src/DSi_SD.cpp | 4 +-- src/NDSCart.cpp | 87 ++++++++++++++++++++++++++++++++++++++++----------------- src/NDSCart.h | 2 ++ 5 files changed, 85 insertions(+), 36 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index 17d7f0d..771f67b 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -22,6 +22,7 @@ #include "DSi.h" #include "ARM.h" #include "GPU.h" +#include "NDSCart.h" #include "Platform.h" #include "DSi_NDMA.h" @@ -581,6 +582,22 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val) } +void Set_SCFG_MC(u32 val) +{ + u32 oldslotstatus = SCFG_MC & 0xC; + + val &= 0xFFFF800C; + if ((val & 0xC) == 0xC) val &= ~0xC; // hax + if (val & 0x8000) printf("SCFG_MC: weird NDS slot swap\n"); + SCFG_MC = (SCFG_MC & ~0xFFFF800C) | val; + + if ((oldslotstatus == 0x0) && ((SCFG_MC & 0xC) == 0x4)) + { + NDSCart::ResetCart(); + } +} + + u8 ARM9Read8(u32 addr) { switch (addr & 0xFF000000) @@ -1455,10 +1472,7 @@ void ARM7IOWrite16(u32 addr, u16 val) return; case 0x04004010: - val &= 0x800C; - if ((val & 0xC) == 0xC) val &= ~0xC; // hax - if (val & 0x8000) printf("SCFG_MC: weird NDS slot swap\n"); - SCFG_MC = (SCFG_MC & ~0x800C) | val; + Set_SCFG_MC((SCFG_MC & 0xFFFF0000) | val); return; } @@ -1491,10 +1505,7 @@ void ARM7IOWrite32(u32 addr, u32 val) printf("SCFG_EXT = %08X / %08X (val7 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val); return; case 0x04004010: - val &= 0xFFFF800C; - if ((val & 0xC) == 0xC) val &= ~0xC; // hax - if (val & 0x8000) printf("SCFG_MC: weird NDS slot swap\n"); - SCFG_MC = (SCFG_MC & ~0xFFFF800C) | val; + Set_SCFG_MC(val); return; case 0x04004054: MapNWRAMRange(1, 0, val); return; diff --git a/src/DSi.h b/src/DSi.h index db585b4..b29cdb5 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -32,6 +32,7 @@ extern DSi_SDHost* SDMMC; extern DSi_SDHost* SDIO; extern u8 ITCMInit[0x8000]; +extern u8 ARM7Init[0x3C00]; bool Init(); diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 07eca83..44d8d62 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -191,7 +191,7 @@ void DSi_SDHost::FinishSend(u32 param) u32 DSi_SDHost::SendData(u8* data, u32 len) { - printf("%s: data RX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask); + //printf("%s: data RX, len=%d, blkcnt=%d (%d) blklen=%d, irq=%08X\n", SD_DESC, len, BlockCount16, BlockCountInternal, BlockLen16, IRQMask); if (len != BlockLen16) { printf("!! BAD BLOCKLEN\n"); len = BlockLen16; } bool last = (BlockCountInternal == 0); @@ -796,7 +796,7 @@ void DSi_MMCStorage::ContinueTransfer() u32 DSi_MMCStorage::ReadBlock(u64 addr) { - printf("SD/MMC: reading block @ %08X, len=%08X\n", addr, BlockSize); + //printf("SD/MMC: reading block @ %08X, len=%08X\n", addr, BlockSize); u32 len = BlockSize; len = Host->GetTransferrableLen(len); diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 0bb8b5c..c3765d8 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -475,6 +475,7 @@ u32 CartROMSize; u32 CartCRC; u32 CartID; bool CartIsHomebrew; +bool CartIsDSi; u32 CmdEncMode; u32 DataEncMode; @@ -557,10 +558,13 @@ void Key1_ApplyKeycode(u32* keycode, u32 mod) } } -void Key1_InitKeycode(u32 idcode, u32 level, u32 mod) +void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod) { //memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax - memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax + if (dsi) + memcpy(Key1_KeyBuf, &DSi::ARM7Init[0x254], 0x1048); // hax + else + memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax u32 keycode[3] = {idcode, idcode>>1, idcode<<1}; if (level >= 1) Key1_ApplyKeycode(keycode, mod); @@ -613,32 +617,19 @@ void DeInit() void Reset() { - SPICnt = 0; - ROMCnt = 0; - - memset(ROMCommand, 0, 8); - ROMDataOut = 0; - - Key2_X = 0; - Key2_Y = 0; - - memset(DataOut, 0, 0x4000); - DataOutPos = 0; - DataOutLen = 0; - CartInserted = false; if (CartROM) delete[] CartROM; CartROM = NULL; CartROMSize = 0; CartID = 0; CartIsHomebrew = false; + CartIsDSi = false; ROMCommandHandler = NULL; - CmdEncMode = 0; - DataEncMode = 0; - NDSCart_SRAM::Reset(); + + ResetCart(); } void DoSavestate(Savestate* file) @@ -893,6 +884,11 @@ bool LoadROM(const char* path, const char* sram, bool direct) fread(&gamecode, 4, 1, f); printf("Game code: %c%c%c%c\n", gamecode&0xFF, (gamecode>>8)&0xFF, (gamecode>>16)&0xFF, gamecode>>24); + u8 unitcode; + fseek(f, 0x12, SEEK_SET); + fread(&unitcode, 1, 1, f); + CartIsDSi = (unitcode & 0x02) != 0; + CartROM = new u8[CartROMSize]; memset(CartROM, 0, CartROMSize); fseek(f, 0, SEEK_SET); @@ -934,6 +930,9 @@ bool LoadROM(const char* path, const char* sram, bool direct) if (romparams[1] == 8) CartID |= 0x08000000; // NAND flag + if (CartIsDSi) + CartID |= 0x40000000; + printf("Cart ID: %08X\n", CartID); if (*(u32*)&CartROM[0x20] < 0x4000) @@ -969,11 +968,11 @@ bool LoadROM(const char* path, const char* sram, bool direct) strncpy((char*)&CartROM[arm9base], "encryObj", 8); - Key1_InitKeycode(gamecode, 3, 2); + Key1_InitKeycode(false, gamecode, 3, 2); for (u32 i = 0; i < 0x800; i += 8) Key1_Encrypt((u32*)&CartROM[arm9base + i]); - Key1_InitKeycode(gamecode, 2, 2); + Key1_InitKeycode(false, gamecode, 2, 2); Key1_Encrypt((u32*)&CartROM[arm9base]); } } @@ -981,9 +980,6 @@ bool LoadROM(const char* path, const char* sram, bool direct) CartIsHomebrew = true; } - // encryption - Key1_InitKeycode(gamecode, 2, 2); - // save printf("Save file: %s\n", sram); @@ -998,6 +994,27 @@ void RelocateSave(const char* path, bool write) NDSCart_SRAM::RelocateSave(path, write); } +void ResetCart() +{ + // CHECKME: what if there is a transfer in progress? + + SPICnt = 0; + ROMCnt = 0; + + memset(ROMCommand, 0, 8); + ROMDataOut = 0; + + Key2_X = 0; + Key2_Y = 0; + + memset(DataOut, 0, 0x4000); + DataOutPos = 0; + DataOutLen = 0; + + CmdEncMode = 0; + DataEncMode = 0; +} + void ReadROM(u32 addr, u32 len, u32 offset) { if (!CartInserted) return; @@ -1172,7 +1189,7 @@ void WriteROMCnt(u32 val) // handle KEY1 encryption as needed. // KEY2 encryption is implemented in hardware and doesn't need to be handled. u8 cmd[8]; - if (CmdEncMode == 1) + if (CmdEncMode == 1 || CmdEncMode == 11) { *(u32*)&cmd[0] = ByteSwap(*(u32*)&ROMCommand[4]); *(u32*)&cmd[4] = ByteSwap(*(u32*)&ROMCommand[0]); @@ -1218,11 +1235,23 @@ void WriteROMCnt(u32 val) break; case 0x3C: - if (CartInserted) CmdEncMode = 1; + if (CartInserted) + { + CmdEncMode = 1; + Key1_InitKeycode(false, *(u32*)&CartROM[0xC], 2, 2); + } + break; + + case 0x3D: + if (CartInserted && CartIsDSi) + { + CmdEncMode = 11; + Key1_InitKeycode(true, *(u32*)&CartROM[0xC], 1, 2); + } break; default: - if (CmdEncMode == 1) + if (CmdEncMode == 1 || CmdEncMode == 11) { switch (cmd[0] & 0xF0) { @@ -1238,6 +1267,12 @@ void WriteROMCnt(u32 val) case 0x20: { u32 addr = (cmd[2] & 0xF0) << 8; + if (CmdEncMode == 11) + { + u32 arm9i_base = *(u32*)&CartROM[0x1C0]; + addr -= 0x4000; + addr += arm9i_base; + } ReadROM(addr, 0x1000, 0); } break; diff --git a/src/NDSCart.h b/src/NDSCart.h index 0dc4220..05516d7 100644 --- a/src/NDSCart.h +++ b/src/NDSCart.h @@ -47,6 +47,8 @@ void DoSavestate(Savestate* file); bool LoadROM(const char* path, const char* sram, bool direct); void RelocateSave(const char* path, bool write); +void ResetCart(); + void WriteROMCnt(u32 val); u32 ReadROMData(); -- cgit v1.2.3 From 4d3d8433cbfc7916a344c18c491da401f6e32bfb Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 5 Aug 2019 19:52:03 +0200 Subject: * add old DS BIOSes and 04004000 BIOS-switch fixes audio issues when running DS games * attempt adding other fun shit like dynamic RAM size, but that mostly went nowhere for now --- src/DSi.cpp | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- src/DSi.h | 3 + src/NDS.cpp | 154 ++++++++++++++++++++++++++---------------------- src/NDS.h | 11 ++-- 4 files changed, 251 insertions(+), 108 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index 771f67b..9f07fa1 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -45,11 +45,15 @@ namespace DSi u32 BootAddr[2]; +u16 SCFG_BIOS; u16 SCFG_Clock9; u16 SCFG_Clock7; u32 SCFG_EXT[2]; u32 SCFG_MC; +u8 ARM9iBIOS[0x10000]; +u8 ARM7iBIOS[0x10000]; + u32 MBK[2][9]; u8 NWRAM_A[0x40000]; @@ -131,6 +135,7 @@ void Reset() SDMMC->Reset(); SDIO->Reset(); + SCFG_BIOS = 0x0101; // TODO: should be zero when booting from BIOS SCFG_Clock9 = 0x0187; // CHECKME SCFG_Clock7 = 0x0187; SCFG_EXT[0] = 0x8307F100; @@ -160,18 +165,21 @@ bool LoadBIOS() FILE* f; u32 i; + memset(ARM9iBIOS, 0, 0x10000); + memset(ARM7iBIOS, 0, 0x10000); + f = Platform::OpenLocalFile("bios9i.bin", "rb"); if (!f) { printf("ARM9i BIOS not found\n"); for (i = 0; i < 16; i++) - ((u32*)NDS::ARM9BIOS)[i] = 0xE7FFDEFF; + ((u32*)ARM9iBIOS)[i] = 0xE7FFDEFF; } else { fseek(f, 0, SEEK_SET); - fread(NDS::ARM9BIOS, 0x10000, 1, f); + fread(ARM9iBIOS, 0x10000, 1, f); printf("ARM9i BIOS loaded\n"); fclose(f); @@ -183,22 +191,25 @@ bool LoadBIOS() printf("ARM7i BIOS not found\n"); for (i = 0; i < 16; i++) - ((u32*)NDS::ARM7BIOS)[i] = 0xE7FFDEFF; + ((u32*)ARM7iBIOS)[i] = 0xE7FFDEFF; } else { // TODO: check if the first 32 bytes are crapoed fseek(f, 0, SEEK_SET); - fread(NDS::ARM7BIOS, 0x10000, 1, f); + fread(ARM7iBIOS, 0x10000, 1, f); printf("ARM7i BIOS loaded\n"); fclose(f); } // herp - *(u32*)&NDS::ARM9BIOS[0] = 0xEAFFFFFE; - *(u32*)&NDS::ARM7BIOS[0] = 0xEAFFFFFE; + *(u32*)&ARM9iBIOS[0] = 0xEAFFFFFE; + *(u32*)&ARM7iBIOS[0] = 0xEAFFFFFE; + + // TODO!!!! + // hax the upper 32K out of the goddamn DSi return true; } @@ -582,6 +593,22 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val) } +void Set_SCFG_Clock9(u16 val) +{ + SCFG_Clock9 = val & 0x0187; + return; + + NDS::ARM9Timestamp >>= NDS::ARM9ClockShift; + + printf("CLOCK9=%04X\n", val); + SCFG_Clock9 = val & 0x0187; + + if (SCFG_Clock9 & (1<<0)) NDS::ARM9ClockShift = 2; + else NDS::ARM9ClockShift = 1; + NDS::ARM9Timestamp <<= NDS::ARM9ClockShift; + NDS::ARM9->UpdateRegionTimings(0x00000000, 0xFFFFFFFF); +} + void Set_SCFG_MC(u32 val) { u32 oldslotstatus = SCFG_MC & 0xC; @@ -600,6 +627,14 @@ void Set_SCFG_MC(u32 val) u8 ARM9Read8(u32 addr) { + if ((addr >= 0xFFFF0000) && (!(SCFG_BIOS & (1<<1)))) + { + if ((addr >= 0xFFFF8000) && (SCFG_BIOS & (1<<0))) + return 0xFF; + + return *(u8*)&ARM9iBIOS[addr & 0xFFFF]; + } + switch (addr & 0xFF000000) { case 0x03000000: @@ -629,6 +664,14 @@ u8 ARM9Read8(u32 addr) u16 ARM9Read16(u32 addr) { + if ((addr >= 0xFFFF0000) && (!(SCFG_BIOS & (1<<1)))) + { + if ((addr >= 0xFFFF8000) && (SCFG_BIOS & (1<<0))) + return 0xFFFF; + + return *(u16*)&ARM9iBIOS[addr & 0xFFFF]; + } + switch (addr & 0xFF000000) { case 0x03000000: @@ -658,6 +701,14 @@ u16 ARM9Read16(u32 addr) u32 ARM9Read32(u32 addr) { + if ((addr >= 0xFFFF0000) && (!(SCFG_BIOS & (1<<1)))) + { + if ((addr >= 0xFFFF8000) && (SCFG_BIOS & (1<<0))) + return 0xFFFFFFFF; + + return *(u32*)&ARM9iBIOS[addr & 0xFFFF]; + } + switch (addr & 0xFF000000) { case 0x03000000: @@ -790,14 +841,28 @@ bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) { case 0x02000000: region->Mem = NDS::MainRAM; - region->Mask = MAIN_RAM_SIZE-1; + region->Mask = NDS::MainRAMMask; return true; } if ((addr & 0xFFFF0000) == 0xFFFF0000 && !write) { - region->Mem = NDS::ARM9BIOS; - region->Mask = 0xFFFF; + if (SCFG_BIOS & (1<<1)) + { + if (addr >= 0xFFFF1000) + { + region->Mem = NULL; + return false; + } + + region->Mem = NDS::ARM9BIOS; + region->Mask = 0xFFF; + } + else + { + region->Mem = ARM9iBIOS; + region->Mask = 0xFFFF; + } return true; } @@ -809,6 +874,18 @@ bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) u8 ARM7Read8(u32 addr) { + if ((addr < 0x00010000) && (!(SCFG_BIOS & (1<<9)))) + { + if ((addr >= 0x00008000) && (SCFG_BIOS & (1<<8))) + return 0xFF; + if (NDS::ARM7->R[15] >= 0x00010000) + return 0xFF; + if (addr < NDS::ARM7BIOSProt && NDS::ARM7->R[15] >= NDS::ARM7BIOSProt) + return 0xFF; + + return *(u8*)&ARM7iBIOS[addr]; + } + switch (addr & 0xFF800000) { case 0x03000000: @@ -838,6 +915,18 @@ u8 ARM7Read8(u32 addr) u16 ARM7Read16(u32 addr) { + if ((addr < 0x00010000) && (!(SCFG_BIOS & (1<<9)))) + { + if ((addr >= 0x00008000) && (SCFG_BIOS & (1<<8))) + return 0xFFFF; + if (NDS::ARM7->R[15] >= 0x00010000) + return 0xFFFF; + if (addr < NDS::ARM7BIOSProt && NDS::ARM7->R[15] >= NDS::ARM7BIOSProt) + return 0xFFFF; + + return *(u16*)&ARM7iBIOS[addr]; + } + switch (addr & 0xFF800000) { case 0x03000000: @@ -867,6 +956,18 @@ u16 ARM7Read16(u32 addr) u32 ARM7Read32(u32 addr) { + if ((addr < 0x00010000) && (!(SCFG_BIOS & (1<<9)))) + { + if ((addr >= 0x00008000) && (SCFG_BIOS & (1<<8))) + return 0xFFFFFFFF; + if (NDS::ARM7->R[15] >= 0x00010000) + return 0xFFFFFFFF; + if (addr < NDS::ARM7BIOSProt && NDS::ARM7->R[15] >= NDS::ARM7BIOSProt) + return 0xFFFFFFFF; + + return *(u32*)&ARM7iBIOS[addr]; + } + switch (addr & 0xFF800000) { case 0x03000000: @@ -1000,7 +1101,7 @@ bool ARM7GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) case 0x02000000: case 0x02800000: region->Mem = NDS::MainRAM; - region->Mask = MAIN_RAM_SIZE-1; + region->Mask = NDS::MainRAMMask; return true; } @@ -1040,7 +1141,7 @@ u8 ARM9IORead8(u32 addr) { switch (addr) { - case 0x04004000: return 1; + case 0x04004000: return SCFG_BIOS & 0xFF; CASE_READ8_32BIT(0x04004040, MBK[0][0]) CASE_READ8_32BIT(0x04004044, MBK[0][1]) @@ -1060,6 +1161,7 @@ u16 ARM9IORead16(u32 addr) { switch (addr) { + case 0x04004000: return SCFG_BIOS & 0xFF; case 0x04004004: return SCFG_Clock9; case 0x04004010: return SCFG_MC & 0xFFFF; @@ -1081,6 +1183,7 @@ u32 ARM9IORead32(u32 addr) { switch (addr) { + case 0x04004000: return SCFG_BIOS & 0xFF; case 0x04004008: return SCFG_EXT[0]; case 0x04004010: return SCFG_MC & 0xFFFF; @@ -1172,9 +1275,7 @@ void ARM9IOWrite16(u32 addr, u16 val) switch (addr) { case 0x04004004: - // TODO: actually change clock! - printf("CLOCK9=%04X\n", val); - SCFG_Clock9 = val & 0x0187; + Set_SCFG_Clock9(val); return; case 0x04004040: @@ -1232,6 +1333,20 @@ void ARM9IOWrite32(u32 addr, u32 val) SCFG_EXT[1] &= ~0x0000F080; SCFG_EXT[1] |= (val & 0x0000F080); printf("SCFG_EXT = %08X / %08X (val9 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val); + /*switch ((SCFG_EXT[0] >> 14) & 0x3) + { + case 0: + case 1: + NDS::MainRAMMask = 0x3FFFFF; + printf("RAM: 4MB\n"); + break; + case 2: + case 3: // TODO: debug console w/ 32MB? + NDS::MainRAMMask = 0xFFFFFF; + printf("RAM: 16MB\n"); + break; + }*/ + printf("from %08X, ARM7 %08X, %08X\n", NDS::GetPC(0), NDS::GetPC(1), NDS::ARM7->R[1]); return; case 0x04004040: @@ -1307,8 +1422,8 @@ u8 ARM7IORead8(u32 addr) { switch (addr) { - case 0x04004000: return 0x01; - case 0x04004001: return 0x01; + case 0x04004000: return SCFG_BIOS & 0xFF; + case 0x04004001: return SCFG_BIOS >> 8; CASE_READ8_32BIT(0x04004040, MBK[1][0]) CASE_READ8_32BIT(0x04004044, MBK[1][1]) @@ -1323,14 +1438,14 @@ u8 ARM7IORead8(u32 addr) case 0x04004500: return DSi_I2C::ReadData(); case 0x04004501: return DSi_I2C::Cnt; - case 0x04004D00: return ConsoleID & 0xFF; - case 0x04004D01: return (ConsoleID >> 8) & 0xFF; - case 0x04004D02: return (ConsoleID >> 16) & 0xFF; - case 0x04004D03: return (ConsoleID >> 24) & 0xFF; - case 0x04004D04: return (ConsoleID >> 32) & 0xFF; - case 0x04004D05: return (ConsoleID >> 40) & 0xFF; - case 0x04004D06: return (ConsoleID >> 48) & 0xFF; - case 0x04004D07: return ConsoleID >> 56; + case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID & 0xFF; + case 0x04004D01: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 8) & 0xFF; + case 0x04004D02: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 16) & 0xFF; + case 0x04004D03: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 24) & 0xFF; + case 0x04004D04: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 32) & 0xFF; + case 0x04004D05: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 40) & 0xFF; + case 0x04004D06: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 48) & 0xFF; + case 0x04004D07: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID >> 56; case 0x04004D08: return 0; } @@ -1344,6 +1459,7 @@ u16 ARM7IORead16(u32 addr) case 0x04000218: return NDS::IE2; case 0x0400021C: return NDS::IF2; + case 0x04004000: return SCFG_BIOS; case 0x04004004: return SCFG_Clock7; case 0x04004006: return 0; // JTAG register case 0x04004010: return SCFG_MC & 0xFFFF; @@ -1358,10 +1474,10 @@ u16 ARM7IORead16(u32 addr) CASE_READ16_32BIT(0x0400405C, MBK[1][7]) CASE_READ16_32BIT(0x04004060, MBK[1][8]) - case 0x04004D00: return ConsoleID & 0xFFFF; - case 0x04004D02: return (ConsoleID >> 16) & 0xFFFF; - case 0x04004D04: return (ConsoleID >> 32) & 0xFFFF; - case 0x04004D06: return ConsoleID >> 48; + case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID & 0xFFFF; + case 0x04004D02: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 16) & 0xFFFF; + case 0x04004D04: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 32) & 0xFFFF; + case 0x04004D06: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID >> 48; case 0x04004D08: return 0; } @@ -1384,6 +1500,7 @@ u32 ARM7IORead32(u32 addr) case 0x04000218: return NDS::IE2; case 0x0400021C: return NDS::IF2; + case 0x04004000: return SCFG_BIOS; case 0x04004008: return SCFG_EXT[1]; case 0x04004010: return SCFG_MC; @@ -1430,8 +1547,8 @@ u32 ARM7IORead32(u32 addr) case 0x04004400: return DSi_AES::ReadCnt(); case 0x0400440C: return DSi_AES::ReadOutputFIFO(); - case 0x04004D00: return ConsoleID & 0xFFFFFFFF; - case 0x04004D04: return ConsoleID >> 32; + case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID & 0xFFFFFFFF; + case 0x04004D04: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID >> 32; case 0x04004D08: return 0; } @@ -1453,6 +1570,13 @@ void ARM7IOWrite8(u32 addr, u8 val) { switch (addr) { + case 0x04004000: + SCFG_BIOS |= (val & 0x03); + return; + case 0x04004001: + SCFG_BIOS |= ((val & 0x07) << 8); + return; + case 0x04004500: DSi_I2C::WriteData(val); return; case 0x04004501: DSi_I2C::WriteCnt(val); return; } @@ -1467,10 +1591,12 @@ void ARM7IOWrite16(u32 addr, u16 val) case 0x04000218: NDS::IE2 = (val & 0x7FF7); NDS::UpdateIRQ(1); return; case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; + case 0x04004000: + SCFG_BIOS |= (val & 0x0703); + return; case 0x04004004: SCFG_Clock7 = val & 0x0187; return; - case 0x04004010: Set_SCFG_MC((SCFG_MC & 0xFFFF0000) | val); return; @@ -1497,6 +1623,9 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x04000218: NDS::IE2 = (val & 0x7FF7); NDS::UpdateIRQ(1); return; case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; + case 0x04004000: + SCFG_BIOS |= (val & 0x0703); + return; case 0x04004008: SCFG_EXT[0] &= ~0x03000000; SCFG_EXT[0] |= (val & 0x03000000); diff --git a/src/DSi.h b/src/DSi.h index b29cdb5..bd37550 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -25,6 +25,9 @@ namespace DSi { +extern u8 ARM9iBIOS[0x10000]; +extern u8 ARM7iBIOS[0x10000]; + extern u8 eMMC_CID[16]; extern u64 ConsoleID; diff --git a/src/NDS.cpp b/src/NDS.cpp index 42b5d9f..95265cf 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -86,10 +86,11 @@ u32 SchedListMask; u32 CPUStop; -u8 ARM9BIOS[0x10000]; -u8 ARM7BIOS[0x10000]; +u8 ARM9BIOS[0x1000]; +u8 ARM7BIOS[0x4000]; -u8 MainRAM[MAIN_RAM_SIZE]; +u8 MainRAM[0x1000000]; +u32 MainRAMMask; u8 SharedWRAM[0x8000]; u8 WRAMCnt; @@ -235,7 +236,11 @@ void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, ARM9MemTimings[i][3] = S32; } - ARM9->UpdateRegionTimings(addrstart<<14, addrend<<14); + addrstart <<= 14; + addrend <<= 14; + if (!addrend) addrend = 0xFFFFFFFF; + + ARM9->UpdateRegionTimings(addrstart, addrend); } void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq) @@ -395,53 +400,58 @@ void Reset() LastSysClockCycles = 0; - memset(ARM9BIOS, 0, 0x10000); - memset(ARM7BIOS, 0, 0x10000); + memset(ARM9BIOS, 0, 0x1000); + memset(ARM7BIOS, 0, 0x4000); - if (true) + // DS BIOSes are always loaded, even in DSi mode + // we need them for DS-compatible mode + + f = Platform::OpenLocalFile("bios9.bin", "rb"); + if (!f) { - DSi::LoadBIOS(); - DSi::LoadNAND(); + printf("ARM9 BIOS not found\n"); - ARM9ClockShift = 2; + for (i = 0; i < 16; i++) + ((u32*)ARM9BIOS)[i] = 0xE7FFDEFF; } else { - f = Platform::OpenLocalFile("bios9.bin", "rb"); - if (!f) - { - printf("ARM9 BIOS not found\n"); + fseek(f, 0, SEEK_SET); + fread(ARM9BIOS, 0x1000, 1, f); - for (i = 0; i < 16; i++) - ((u32*)ARM9BIOS)[i] = 0xE7FFDEFF; - } - else - { - fseek(f, 0, SEEK_SET); - fread(ARM9BIOS, 0x1000, 1, f); + printf("ARM9 BIOS loaded\n"); + fclose(f); + } - printf("ARM9 BIOS loaded\n"); - fclose(f); - } + f = Platform::OpenLocalFile("bios7.bin", "rb"); + if (!f) + { + printf("ARM7 BIOS not found\n"); - f = Platform::OpenLocalFile("bios7.bin", "rb"); - if (!f) - { - printf("ARM7 BIOS not found\n"); + for (i = 0; i < 16; i++) + ((u32*)ARM7BIOS)[i] = 0xE7FFDEFF; + } + else + { + fseek(f, 0, SEEK_SET); + fread(ARM7BIOS, 0x4000, 1, f); - for (i = 0; i < 16; i++) - ((u32*)ARM7BIOS)[i] = 0xE7FFDEFF; - } - else - { - fseek(f, 0, SEEK_SET); - fread(ARM7BIOS, 0x4000, 1, f); + printf("ARM7 BIOS loaded\n"); + fclose(f); + } - printf("ARM7 BIOS loaded\n"); - fclose(f); - } + if (true) + { + DSi::LoadBIOS(); + DSi::LoadNAND(); + ARM9ClockShift = 2; + MainRAMMask = 0xFFFFFF; + } + else + { ARM9ClockShift = 1; + MainRAMMask = 0x3FFFFF; } ARM9Timestamp = 0; ARM9Target = 0; @@ -450,7 +460,7 @@ void Reset() InitTimings(); - memset(MainRAM, 0, MAIN_RAM_SIZE); + memset(MainRAM, 0, 0x1000000); memset(SharedWRAM, 0, 0x8000); memset(ARM7WRAM, 0, 0x10000); @@ -1608,36 +1618,36 @@ void debug(u32 param) fwrite(&val, 4, 1, shit); } fclose(shit);*/ - /*FILE* - shit = fopen("debug/dump9.bin", "wb"); + FILE* + /*shit = fopen("debug/dump9.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { u32 val = DSi::ARM9Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit); - shit = fopen("debug/dump7.bin", "wb"); + fclose(shit);*/ + shit = fopen("debug/dump7_2.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { u32 val = DSi::ARM7Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit);*/ + fclose(shit); } u8 ARM9Read8(u32 addr) { - if ((addr & 0xFFFF0000) == 0xFFFF0000) + if ((addr & 0xFFFFF000) == 0xFFFF0000) { - return *(u8*)&ARM9BIOS[addr & 0xFFFF]; + return *(u8*)&ARM9BIOS[addr & 0xFFF]; } switch (addr & 0xFF000000) { case 0x02000000: - return *(u8*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)]; + return *(u8*)&MainRAM[addr & MainRAMMask]; case 0x03000000: if (SWRAM_ARM9) @@ -1690,15 +1700,15 @@ u8 ARM9Read8(u32 addr) u16 ARM9Read16(u32 addr) { - if ((addr & 0xFFFF0000) == 0xFFFF0000) + if ((addr & 0xFFFFF000) == 0xFFFF0000) { - return *(u16*)&ARM9BIOS[addr & 0xFFFF]; + return *(u16*)&ARM9BIOS[addr & 0xFFF]; } switch (addr & 0xFF000000) { case 0x02000000: - return *(u16*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)]; + return *(u16*)&MainRAM[addr & MainRAMMask]; case 0x03000000: if (SWRAM_ARM9) @@ -1751,15 +1761,15 @@ u16 ARM9Read16(u32 addr) u32 ARM9Read32(u32 addr) { - if ((addr & 0xFFFF0000) == 0xFFFF0000) + if ((addr & 0xFFFFF000) == 0xFFFF0000) { - return *(u32*)&ARM9BIOS[addr & 0xFFFF]; + return *(u32*)&ARM9BIOS[addr & 0xFFF]; } switch (addr & 0xFF000000) { case 0x02000000: - return *(u32*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)]; + return *(u32*)&MainRAM[addr & MainRAMMask]; case 0x03000000: if (SWRAM_ARM9) @@ -1815,7 +1825,7 @@ void ARM9Write8(u32 addr, u8 val) switch (addr & 0xFF000000) { case 0x02000000: - *(u8*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)] = val; + *(u8*)&MainRAM[addr & MainRAMMask] = val; return; case 0x03000000: @@ -1844,7 +1854,7 @@ void ARM9Write16(u32 addr, u16 val) switch (addr & 0xFF000000) { case 0x02000000: - *(u16*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)] = val; + *(u16*)&MainRAM[addr & MainRAMMask] = val; return; case 0x03000000: @@ -1887,7 +1897,7 @@ void ARM9Write32(u32 addr, u32 val) switch (addr & 0xFF000000) { case 0x02000000: - *(u32*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)] = val; + *(u32*)&MainRAM[addr & MainRAMMask] = val; return ; case 0x03000000: @@ -1931,7 +1941,7 @@ bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region) { case 0x02000000: region->Mem = MainRAM; - region->Mask = MAIN_RAM_SIZE-1; + region->Mask = MainRAMMask; return true; case 0x03000000: @@ -1959,10 +1969,10 @@ bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region) u8 ARM7Read8(u32 addr) { - if (addr < 0x00010000) + if (addr < 0x00004000) { // TODO: check the boundary? is it 4000 or higher on regular DS? - if (ARM7->R[15] >= 0x00010000) + if (ARM7->R[15] >= 0x00004000) return 0xFF; if (addr < ARM7BIOSProt && ARM7->R[15] >= ARM7BIOSProt) return 0xFF; @@ -1974,7 +1984,7 @@ u8 ARM7Read8(u32 addr) { case 0x02000000: case 0x02800000: - return *(u8*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)]; + return *(u8*)&MainRAM[addr & MainRAMMask]; case 0x03000000: if (SWRAM_ARM7) @@ -2016,9 +2026,9 @@ u8 ARM7Read8(u32 addr) u16 ARM7Read16(u32 addr) { - if (addr < 0x00010000) + if (addr < 0x00004000) { - if (ARM7->R[15] >= 0x00010000) + if (ARM7->R[15] >= 0x00004000) return 0xFFFF; if (addr < ARM7BIOSProt && ARM7->R[15] >= ARM7BIOSProt) return 0xFFFF; @@ -2030,7 +2040,7 @@ u16 ARM7Read16(u32 addr) { case 0x02000000: case 0x02800000: - return *(u16*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)]; + return *(u16*)&MainRAM[addr & MainRAMMask]; case 0x03000000: if (SWRAM_ARM7) @@ -2079,9 +2089,9 @@ u16 ARM7Read16(u32 addr) u32 ARM7Read32(u32 addr) { - if (addr < 0x00010000) + if (addr < 0x00004000) { - if (ARM7->R[15] >= 0x00010000) + if (ARM7->R[15] >= 0x00004000) return 0xFFFFFFFF; if (addr < ARM7BIOSProt && ARM7->R[15] >= ARM7BIOSProt) return 0xFFFFFFFF; @@ -2093,7 +2103,7 @@ u32 ARM7Read32(u32 addr) { case 0x02000000: case 0x02800000: - return *(u32*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)]; + return *(u32*)&MainRAM[addr & MainRAMMask]; case 0x03000000: if (SWRAM_ARM7) @@ -2146,7 +2156,7 @@ void ARM7Write8(u32 addr, u8 val) { case 0x02000000: case 0x02800000: - *(u8*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)] = val; + *(u8*)&MainRAM[addr & MainRAMMask] = val; return; case 0x03000000: @@ -2184,7 +2194,7 @@ void ARM7Write16(u32 addr, u16 val) { case 0x02000000: case 0x02800000: - *(u16*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)] = val; + *(u16*)&MainRAM[addr & MainRAMMask] = val; return; case 0x03000000: @@ -2230,7 +2240,7 @@ void ARM7Write32(u32 addr, u32 val) { case 0x02000000: case 0x02800000: - *(u32*)&MainRAM[addr & (MAIN_RAM_SIZE - 1)] = val; + *(u32*)&MainRAM[addr & MainRAMMask] = val; return; case 0x03000000: @@ -2278,7 +2288,7 @@ bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region) case 0x02000000: case 0x02800000: region->Mem = MainRAM; - region->Mask = MAIN_RAM_SIZE-1; + region->Mask = MainRAMMask; return true; case 0x03000000: @@ -2555,7 +2565,7 @@ u32 ARM9IORead32(u32 addr) case 0x04000130: return (KeyInput & 0xFFFF) | (KeyCnt << 16); - case 0x04000180: return IPCSync9; + case 0x04000180: /*printf("ARM9 read IPCSYNC: %04X\n", IPCSync9);*/ return IPCSync9; case 0x040001A0: return NDSCart::SPICnt | (NDSCart::ReadSPIData() << 16); case 0x040001A4: return NDSCart::ROMCnt; @@ -2764,6 +2774,7 @@ void ARM9IOWrite16(u32 addr, u16 val) return; case 0x04000180: + printf("ARM9 IPCSYNC = %04X\n", val); IPCSync7 &= 0xFFF0; IPCSync7 |= ((val & 0x0F00) >> 8); IPCSync9 &= 0xB0FF; @@ -3348,6 +3359,7 @@ void ARM7IOWrite16(u32 addr, u16 val) case 0x04000138: RTC::Write(val, false); return; case 0x04000180: + printf("ARM7 IPCSYNC = %04X\n", val); IPCSync9 &= 0xFFF0; IPCSync9 |= ((val & 0x0F00) >> 8); IPCSync7 &= 0xB0FF; diff --git a/src/NDS.h b/src/NDS.h index 309b16a..1b572ea 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -155,13 +155,12 @@ extern u16 ExMemCnt[2]; extern u8 ROMSeed0[2*8]; extern u8 ROMSeed1[2*8]; -extern u8 ARM9BIOS[0x10000]; -extern u8 ARM7BIOS[0x10000]; +extern u8 ARM9BIOS[0x1000]; +extern u8 ARM7BIOS[0x4000]; +extern u16 ARM7BIOSProt; -//#define MAIN_RAM_SIZE 0x400000 -#define MAIN_RAM_SIZE 0x1000000 - -extern u8 MainRAM[MAIN_RAM_SIZE]; +extern u8 MainRAM[0x1000000]; +extern u32 MainRAMMask; extern u32 KeyInput; -- cgit v1.2.3 From e82364f010f6ad4e4883c241a05a4aac10cd75d6 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 19 Oct 2019 16:03:59 +0200 Subject: * some fixes to SD controller support, make it clear that there is no SD inserted, makes Flipnote work somewhat better * immediately clear AES busy flag when the block count is zero (occurs when loading DSi cart games) * implement NDMA start modes that have an old-DMA equivalent (except for GXFIFO mode) now it boots DSi carts! --- src/DSi.cpp | 16 +++++++++- src/DSi.h | 1 + src/DSi_AES.cpp | 90 +++++++++++++++++++++++++------------------------------- src/DSi_NDMA.cpp | 6 ++-- src/DSi_SD.cpp | 62 +++++++++++++++++++++++++++++++++----- src/NDS.cpp | 42 ++++++++++++++++++++++++++ src/NDSCart.cpp | 4 +-- 7 files changed, 159 insertions(+), 62 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index 9f07fa1..ef4e6da 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -411,6 +411,16 @@ void StallNDMAs() // TODO } +bool NDMAsInMode(u32 cpu, u32 mode) +{ + cpu <<= 2; + if (NDMAs[cpu+0]->IsInMode(mode)) return true; + if (NDMAs[cpu+1]->IsInMode(mode)) return true; + if (NDMAs[cpu+2]->IsInMode(mode)) return true; + if (NDMAs[cpu+3]->IsInMode(mode)) return true; + return false; +} + bool NDMAsRunning(u32 cpu) { cpu <<= 2; @@ -1156,7 +1166,7 @@ u8 ARM9IORead8(u32 addr) return NDS::ARM9IORead8(addr); } - +//u16 dicks = 0; u16 ARM9IORead16(u32 addr) { switch (addr) @@ -1174,6 +1184,8 @@ u16 ARM9IORead16(u32 addr) CASE_READ16_32BIT(0x04004058, MBK[0][6]) CASE_READ16_32BIT(0x0400405C, MBK[0][7]) CASE_READ16_32BIT(0x04004060, MBK[0][8]) + + //case 0x04004202: return dicks & 0xEF1F; } return NDS::ARM9IORead16(addr); @@ -1318,6 +1330,8 @@ void ARM9IOWrite16(u32 addr, u16 val) MapNWRAM_C(6, val & 0xFF); MapNWRAM_C(7, val >> 8); return; + + //case 0x04004202: dicks = val & 0xEF3F; return; } return NDS::ARM9IOWrite16(addr, val); diff --git a/src/DSi.h b/src/DSi.h index bd37550..5697237 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -47,6 +47,7 @@ bool LoadNAND(); void RunNDMAs(u32 cpu); void StallNDMAs(); +bool NDMAsInMode(u32 cpu, u32 mode); bool NDMAsRunning(u32 cpu); void CheckNDMAs(u32 cpu, u32 mode); void StopNDMAs(u32 cpu, u32 mode); diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index e49ebf5..7aae8f3 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -129,28 +129,8 @@ void Reset() memset(CurKey, 0, sizeof(CurKey)); memset(CurMAC, 0, sizeof(CurMAC)); - // initialize keys, as per GBAtek - -#if 0 - // slot 0: modcrypt - *(u32*)&KeyX[0][0] = 0x746E694E; - *(u32*)&KeyX[0][4] = 0x6F646E65; - - // slot 1: 'Tad'/dev.kp - *(u32*)&KeyX[1][0] = 0x4E00004A; - *(u32*)&KeyX[1][4] = 0x4A00004E; - *(u32*)&KeyX[1][8] = (u32)(DSi::ConsoleID >> 32) ^ 0xC80C4B72; - *(u32*)&KeyX[1][12] = (u32)DSi::ConsoleID; - - // slot 3: console-unique eMMC crypto - *(u32*)&KeyX[3][0] = (u32)DSi::ConsoleID; - *(u32*)&KeyX[3][4] = (u32)DSi::ConsoleID ^ 0x24EE6906; - *(u32*)&KeyX[3][8] = (u32)(DSi::ConsoleID >> 32) ^ 0xE65B601D; - *(u32*)&KeyX[3][12] = (u32)(DSi::ConsoleID >> 32); - *(u32*)&KeyY[3][0] = 0x0AB9DC76; - *(u32*)&KeyY[3][4] = 0xBD4DC4D3; - *(u32*)&KeyY[3][8] = 0x202DDD1D; -#endif + // initialize keys + FILE* f = Platform::OpenLocalFile("aeskeys.bin", "rb"); if (f) { @@ -233,12 +213,12 @@ u32 ReadCnt() ret |= InputFIFO->Level(); ret |= (OutputFIFO->Level() << 5); - +//printf("READ AES CNT: %08X, LEVELS: IN=%d OUT=%d\n", ret, InputFIFO->Level(), OutputFIFO->Level()); return ret; } void WriteCnt(u32 val) -{ +{printf("AES CNT = %08X\n", val); u32 oldcnt = Cnt; Cnt = val & 0xFC1FF000; @@ -267,41 +247,51 @@ void WriteCnt(u32 val) // transfer start (checkme) RemBlocks = BlkCnt >> 16; - u8 key[16]; - u8 iv[16]; + if (RemBlocks > 0) + { + u8 key[16]; + u8 iv[16]; - Swap16(key, CurKey); - Swap16(iv, IV); + Swap16(key, CurKey); + Swap16(iv, IV); - if (AESMode < 2) - { - if (BlkCnt & 0xFFFF) printf("AES: CCM EXTRA LEN TODO\n"); + if (AESMode < 2) + { + if (BlkCnt & 0xFFFF) printf("AES: CCM EXTRA LEN TODO\n"); - u32 maclen = (val >> 16) & 0x7; - if (maclen < 1) maclen = 1; + u32 maclen = (val >> 16) & 0x7; + if (maclen < 1) maclen = 1; - iv[0] = 0x02; - for (int i = 0; i < 12; i++) iv[1+i] = iv[4+i]; - iv[13] = 0x00; - iv[14] = 0x00; - iv[15] = 0x01; + iv[0] = 0x02; + for (int i = 0; i < 12; i++) iv[1+i] = iv[4+i]; + iv[13] = 0x00; + iv[14] = 0x00; + iv[15] = 0x01; - AES_init_ctx_iv(&Ctx, key, iv); + AES_init_ctx_iv(&Ctx, key, iv); - iv[0] |= (maclen << 3) | ((BlkCnt & 0xFFFF) ? (1<<6) : 0); - iv[13] = RemBlocks >> 12; - iv[14] = RemBlocks >> 4; - iv[15] = RemBlocks << 4; + iv[0] |= (maclen << 3) | ((BlkCnt & 0xFFFF) ? (1<<6) : 0); + iv[13] = RemBlocks >> 12; + iv[14] = RemBlocks >> 4; + iv[15] = RemBlocks << 4; - memcpy(CurMAC, iv, 16); - AES_ECB_encrypt(&Ctx, CurMAC); + memcpy(CurMAC, iv, 16); + AES_ECB_encrypt(&Ctx, CurMAC); + } + else + { + AES_init_ctx_iv(&Ctx, key, iv); + } + + DSi::CheckNDMAs(1, 0x2A); } else { - AES_init_ctx_iv(&Ctx, key, iv); - } + // no blocks to process? oh well. mark it finished + // CHECKME: does this trigger any IRQ or shit? - DSi::CheckNDMAs(1, 0x2A); + Cnt &= ~(1<<31); + } } printf("AES CNT: %08X / mode=%d key=%d inDMA=%d outDMA=%d blocks=%d\n", @@ -309,7 +299,7 @@ void WriteCnt(u32 val) } void WriteBlkCnt(u32 val) -{ +{printf("AES BLOCK CNT %08X / %d\n", val, val>>16); BlkCnt = val; } @@ -415,7 +405,7 @@ void Update() // CHECKME Cnt &= ~(1<<21); } - +printf("AES: FINISHED\n"); Cnt &= ~(1<<31); if (Cnt & (1<<30)) NDS::SetIRQ2(NDS::IRQ2_DSi_AES); DSi::StopNDMAs(1, 0x2A); diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp index e7fc7ab..19c72b6 100644 --- a/src/DSi_NDMA.cpp +++ b/src/DSi_NDMA.cpp @@ -101,8 +101,10 @@ void DSi_NDMA::WriteCnt(u32 val) Start(); if (StartMode != 0x10 && StartMode != 0x30 && - StartMode != 0x2A && StartMode != 0x2B) - printf("UNIMPLEMENTED ARM%d NDMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr); + StartMode != 0x04 && StartMode != 0x06 && StartMode != 0x07 && StartMode != 0x08 && StartMode != 0x09 && + StartMode != 0x24 && StartMode != 0x26 && StartMode != 0x28 && StartMode != 0x29 && StartMode != 0x2A && StartMode != 0x2B) + printf("UNIMPLEMENTED ARM%d NDMA%d START MODE %02X, %08X->%08X LEN=%d BLK=%d CNT=%08X\n", + CPU?7:9, Num, StartMode, SrcAddr, DstAddr, TotalLength, BlockLength, Cnt); } } diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 796466d..a45a8ce 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -91,10 +91,16 @@ void DSi_SDHost::Reset() if (Num == 0) { + // TODO: eventually pull from host filesystem + /*DSi_MMCStorage* sd = new DSi_MMCStorage(this, false, "sd.bin"); + u8 sd_cid[16] = {0xBD, 0x12, 0x34, 0x56, 0x78, 0x03, 0x4D, 0x30, 0x30, 0x46, 0x50, 0x41, 0x00, 0x00, 0x15, 0x00}; + sd->SetCID(sd_cid);*/ + DSi_MMCStorage* sd = NULL; + DSi_MMCStorage* mmc = new DSi_MMCStorage(this, true, "nand.bin"); mmc->SetCID(DSi::eMMC_CID); - // TODO: port 0 (SD) + Ports[0] = sd; Ports[1] = mmc; } else @@ -196,6 +202,14 @@ void DSi_SDHost::FinishSend(u32 param) host->ClearIRQ(25); host->SetIRQ(24); //if (param & 0x2) host->SetIRQ(2); + + // TODO: this is an assumption and should eventually be confirmed + // Flipnote sets DMA blocklen to 128 words and totallen to 1024 words + // so, presumably, DMA should trigger when the FIFO is full + // 'full' being when it reaches whatever BlockLen16 is set to, or the + // other blocklen register, or when it is actually full (but that makes + // less sense) + DSi::CheckNDMAs(1, host->Num ? 0x29 : 0x28); } u32 DSi_SDHost::SendData(u8* data, u32 len) @@ -286,7 +300,7 @@ u32 DSi_SDHost::GetTransferrableLen(u32 len) u16 DSi_SDHost::Read(u32 addr) { - //if(Num)printf("SDIO READ %08X %08X\n", addr, NDS::GetPC(1)); + if(!Num)printf("SDMMC READ %08X %08X\n", addr, NDS::GetPC(1)); switch (addr & 0x1FF) { @@ -307,7 +321,24 @@ u16 DSi_SDHost::Read(u32 addr) case 0x018: return ResponseBuffer[6]; case 0x01A: return ResponseBuffer[7]; - case 0x01C: return (IRQStatus & 0x031D) | 0x0030; // TODO: adjust insert flags for SD card + case 0x01C: + { + u16 ret = (IRQStatus & 0x031D); + + if (!Num) + { + if (Ports[0]) // basic check of whether the SD card is inserted + ret |= 0x0030; + else + ret |= 0x0008; + } + else + { + // SDIO wifi is always inserted, I guess + ret |= 0x0030; + } + return ret; + } case 0x01E: return ((IRQStatus >> 16) & 0x8B7F); case 0x020: return IRQMask & 0x031D; case 0x022: return (IRQMask >> 16) & 0x8B7F; @@ -436,7 +467,7 @@ u32 DSi_SDHost::ReadFIFO32() void DSi_SDHost::Write(u32 addr, u16 val) { - //if(Num)printf("SDIO WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); + if(!Num)printf("SDMMC WRITE %08X %04X %08X\n", addr, val, NDS::GetPC(1)); switch (addr & 0x1FF) { @@ -464,7 +495,7 @@ void DSi_SDHost::Write(u32 addr, u16 val) } return; - case 0x002: PortSelect = val; printf("%s: PORT SELECT %04X\n", SD_DESC, val); return; + case 0x002: PortSelect = (val & 0x040F) | (PortSelect & 0x0300); printf("%s: PORT SELECT %04X (%04X)\n", SD_DESC, val, PortSelect); return; case 0x004: Param = (Param & 0xFFFF0000) | val; return; case 0x006: Param = (Param & 0x0000FFFF) | (val << 16); return; @@ -504,7 +535,7 @@ void DSi_SDHost::Write(u32 addr, u16 val) if (DataFIFO[f]->IsFull()) { // TODO - printf("!!!! %s FIFO FULL\n", SD_DESC); + printf("!!!! %s FIFO (16) FULL\n", SD_DESC); return; } @@ -582,12 +613,14 @@ void DSi_SDHost::WriteFIFO32(u32 val) { if (DataMode != 1) return; + printf("%s: WRITE FIFO32: LEVEL=%d/%d\n", SD_DESC, DataFIFO[CurFIFO]->Level(), (BlockLen16>>1)); + DSi_SDDevice* dev = Ports[PortSelect & 0x1]; u32 f = CurFIFO; if (DataFIFO[f]->IsFull()) { // TODO - printf("!!!! %s FIFO FULL\n", SD_DESC); + printf("!!!! %s FIFO (32) FULL\n", SD_DESC); return; } @@ -608,12 +641,26 @@ void DSi_SDHost::WriteFIFO32(u32 val) } +#define MMC_DESC (Internal?"NAND":"SDcard") + DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path) : DSi_SDDevice(host) { Internal = internal; strncpy(FilePath, path, 1023); FilePath[1023] = '\0'; File = Platform::OpenLocalFile(path, "r+b"); + if (!File) + { + if (internal) + { + // TODO: proper failure + printf("!! MMC file %s does not exist\n", path); + } + else + { + File = Platform::OpenLocalFile(path, "w+b"); + } + } CSR = 0x00000100; // checkme @@ -674,6 +721,7 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) { // TODO printf("CMD3 on SD card: TODO\n"); + Host->SendResponse((CSR & 0x1FFF) | ((CSR >> 6) & 0x2000) | ((CSR >> 8) & 0xC000) | (1 << 16), true); } return; diff --git a/src/NDS.cpp b/src/NDS.cpp index 95265cf..6933e95 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1371,6 +1371,29 @@ void RunTimers(u32 cpu) +// matching NDMA modes for DSi +const u32 NDMAModes[] = +{ + // ARM9 + + 0x10, // immediate + 0x06, // VBlank + 0x07, // HBlank + 0x08, // scanline start + 0x09, // mainmem FIFO + 0x04, // DS cart slot + 0xFF, // GBA cart slot + 0x0A, // GX FIFO + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // ARM7 + + 0x30, // immediate + 0x26, // VBlank + 0x24, // DS cart slot + 0xFF, // wifi / GBA cart slot (TODO) +}; + bool DMAsInMode(u32 cpu, u32 mode) { cpu <<= 2; @@ -1378,6 +1401,13 @@ bool DMAsInMode(u32 cpu, u32 mode) if (DMAs[cpu+1]->IsInMode(mode)) return true; if (DMAs[cpu+2]->IsInMode(mode)) return true; if (DMAs[cpu+3]->IsInMode(mode)) return true; + + if (true) + { + cpu >>= 2; + return DSi::NDMAsInMode(cpu, NDMAModes[mode]); + } + return false; } @@ -1399,6 +1429,12 @@ void CheckDMAs(u32 cpu, u32 mode) DMAs[cpu+1]->StartIfNeeded(mode); DMAs[cpu+2]->StartIfNeeded(mode); DMAs[cpu+3]->StartIfNeeded(mode); + + if (true) + { + cpu >>= 2; + DSi::CheckNDMAs(cpu, NDMAModes[mode]); + } } void StopDMAs(u32 cpu, u32 mode) @@ -1408,6 +1444,12 @@ void StopDMAs(u32 cpu, u32 mode) DMAs[cpu+1]->StopIfNeeded(mode); DMAs[cpu+2]->StopIfNeeded(mode); DMAs[cpu+3]->StopIfNeeded(mode); + + if (true) + { + cpu >>= 2; + DSi::StopNDMAs(cpu, NDMAModes[mode]); + } } diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 65cf8ae..b0e9837 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -1227,11 +1227,11 @@ void WriteROMCnt(u32 val) *(u32*)&cmd[4] = *(u32*)&ROMCommand[4]; } - printf("ROM COMMAND %04X %08X %02X%02X%02X%02X%02X%02X%02X%02X SIZE %04X\n", + /*printf("ROM COMMAND %04X %08X %02X%02X%02X%02X%02X%02X%02X%02X SIZE %04X\n", SPICnt, ROMCnt, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], - datasize); + datasize);*/ switch (cmd[0]) { -- cgit v1.2.3 From 1c72df43ab8a45c3d7253274d8b1cb6e286a41eb Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 20 Oct 2019 18:35:16 +0200 Subject: messing around --- src/DSi.cpp | 36 ++++++++++++++++++++++++++++++------ src/DSi.h | 2 ++ src/DSi_I2C.cpp | 7 +++++++ 3 files changed, 39 insertions(+), 6 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index ef4e6da..71ef6d3 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -160,6 +160,27 @@ void Reset() ARM7Write16(eaddr+0x42, 0x0001); } +void SoftReset() +{ + // TODO: check exactly what is reset + // presumably, main RAM isn't reset, since the DSi can be told + // to boot a specific title this way + // BPTWL state wouldn't be reset either since BPTWL[0x70] is + // the warmboot flag + + // also, BPTWL[0x70] could be abused to quickly boot specific titles + + NDS::ARM9->Reset(); + NDS::ARM7->Reset(); + + DSi_AES::Reset(); + + LoadNAND(); + + NDS::ARM9->JumpTo(BootAddr[0]); + NDS::ARM7->JumpTo(BootAddr[1]); +} + bool LoadBIOS() { FILE* f; @@ -636,7 +657,8 @@ void Set_SCFG_MC(u32 val) u8 ARM9Read8(u32 addr) -{ +{if(addr==0x02FFC1B0) printf("ARM9 READ8 ROM REGION %08X\n", NDS::GetPC(0)); +if(addr==0x02FFFD70) printf("ARM9 READ8 CONSOLE REGION %08X\n", NDS::GetPC(0)); if ((addr >= 0xFFFF0000) && (!(SCFG_BIOS & (1<<1)))) { if ((addr >= 0xFFFF8000) && (SCFG_BIOS & (1<<0))) @@ -673,7 +695,7 @@ u8 ARM9Read8(u32 addr) } u16 ARM9Read16(u32 addr) -{ +{if(addr==0x02FFC1B0) printf("ARM9 READ16 ROM REGION %08X\n", NDS::GetPC(0)); if ((addr >= 0xFFFF0000) && (!(SCFG_BIOS & (1<<1)))) { if ((addr >= 0xFFFF8000) && (SCFG_BIOS & (1<<0))) @@ -710,7 +732,8 @@ u16 ARM9Read16(u32 addr) } u32 ARM9Read32(u32 addr) -{ +{if(addr==0x02FFC1B0) printf("ARM9 READ32 ROM REGION %08X\n", NDS::GetPC(0)); +if(addr==0x2FE71B0) return 0xFFFFFFFF; // hax: bypass region lock if ((addr >= 0xFFFF0000) && (!(SCFG_BIOS & (1<<1)))) { if ((addr >= 0xFFFF8000) && (SCFG_BIOS & (1<<0))) @@ -883,7 +906,8 @@ bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region) u8 ARM7Read8(u32 addr) -{ +{if(addr==0x02FFC1B0) printf("ARM7 READ8 ROM REGION %08X\n", NDS::GetPC(1)); +if(addr==0x02FFFD70) printf("ARM7 READ8 CONSOLE REGION %08X\n", NDS::GetPC(1)); if ((addr < 0x00010000) && (!(SCFG_BIOS & (1<<9)))) { if ((addr >= 0x00008000) && (SCFG_BIOS & (1<<8))) @@ -924,7 +948,7 @@ u8 ARM7Read8(u32 addr) } u16 ARM7Read16(u32 addr) -{ +{if(addr==0x02FFC1B0) printf("ARM7 READ16 ROM REGION %08X\n", NDS::GetPC(1)); if ((addr < 0x00010000) && (!(SCFG_BIOS & (1<<9)))) { if ((addr >= 0x00008000) && (SCFG_BIOS & (1<<8))) @@ -965,7 +989,7 @@ u16 ARM7Read16(u32 addr) } u32 ARM7Read32(u32 addr) -{ +{if(addr==0x02FFC1B0) printf("ARM7 READ32 ROM REGION %08X\n", NDS::GetPC(1)); if ((addr < 0x00010000) && (!(SCFG_BIOS & (1<<9)))) { if ((addr >= 0x00008000) && (SCFG_BIOS & (1<<8))) diff --git a/src/DSi.h b/src/DSi.h index 5697237..08712de 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -42,6 +42,8 @@ bool Init(); void DeInit(); void Reset(); +void SoftReset(); + bool LoadBIOS(); bool LoadNAND(); diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp index 5ced51e..0ab7008 100644 --- a/src/DSi_I2C.cpp +++ b/src/DSi_I2C.cpp @@ -103,6 +103,13 @@ void Write(u8 val, bool last) return; } + if (CurPos == 0x11 && val == 0x01) + { + printf("BPTWL: soft-reset\n"); + val = 0; // checkme + DSi::SoftReset(); + } + if (CurPos == 0x11 || CurPos == 0x12 || CurPos == 0x21 || CurPos == 0x30 || CurPos == 0x31 || -- cgit v1.2.3 From d0af89924edf4e14a092e5352808f6a2ce44d53a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 2 Jun 2020 00:25:29 +0200 Subject: remove requirement for initmem7/9.bin (but this requires augmented BIOS dumps, we'll get there) --- src/DSi.cpp | 46 +++++++++++++++------------------------------- src/DSi.h | 3 --- src/NDSCart.cpp | 11 ++--------- 3 files changed, 17 insertions(+), 43 deletions(-) (limited to 'src/DSi.h') diff --git a/src/DSi.cpp b/src/DSi.cpp index 6a60f80..701387a 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -129,9 +129,6 @@ void Reset() memcpy(NDS::ARM9->ITCM, ITCMInit, 0x8000); - for (u32 i = 0; i < 0x3C00; i+=4) - ARM7Write32(0x03FFC400+i, *(u32*)&ARM7Init[i]); - DSi_I2C::Reset(); DSi_AES::Reset(); @@ -151,6 +148,9 @@ void Reset() NDS::MapSharedWRAM(3); + for (u32 i = 0; i < 0x3C00; i+=4) + ARM7Write32(0x03FFC400+i, *(u32*)&ARM7Init[i]); + u32 eaddr = 0x03FFE6E4; ARM7Write32(eaddr+0x00, *(u32*)&eMMC_CID[0]); ARM7Write32(eaddr+0x04, *(u32*)&eMMC_CID[4]); @@ -178,9 +178,6 @@ void SoftReset() memcpy(NDS::ARM9->ITCM, ITCMInit, 0x8000); - for (u32 i = 0; i < 0x3C00; i+=4) - ARM7Write32(0x03FFC400+i, *(u32*)&ARM7Init[i]); - DSi_AES::Reset(); LoadNAND(); @@ -204,6 +201,9 @@ void SoftReset() NDS::MapSharedWRAM(3); + for (u32 i = 0; i < 0x3C00; i+=4) + ARM7Write32(0x03FFC400+i, *(u32*)&ARM7Init[i]); + u32 eaddr = 0x03FFE6E4; ARM7Write32(eaddr+0x00, *(u32*)&eMMC_CID[0]); ARM7Write32(eaddr+0x04, *(u32*)&eMMC_CID[4]); @@ -433,32 +433,16 @@ bool LoadNAND() } memset(ITCMInit, 0, 0x8000); - memset(ARM7Init, 0, 0x3C00); - - f = fopen("initmem9.bin", "rb"); - if (f) - { - // first 0x2524 bytes are loaded to 0x01FFC400 - - u32 dstaddr = 0x01FFC400; - fread(&ITCMInit[dstaddr & 0x7FFF], /*0x2524*/0x3C00, 1, f); - fclose(f); - } - else - { - printf("DSi ARM9 meminit not found\n"); - } + memcpy(&ITCMInit[0x4400], &ARM9iBIOS[0x87F4], 0x400); + memcpy(&ITCMInit[0x4800], &ARM9iBIOS[0x9920], 0x80); + memcpy(&ITCMInit[0x4894], &ARM9iBIOS[0x99A0], 0x1048); + memcpy(&ITCMInit[0x58DC], &ARM9iBIOS[0xA9E8], 0x1048); - f = fopen("initmem7.bin", "rb"); - if (f) - { - fread(ARM7Init, 0x3C00, 1, f); - fclose(f); - } - else - { - printf("DSi ARM7 meminit not found\n"); - } + memset(ARM7Init, 0, 0x3C00); + memcpy(&ARM7Init[0x0000], &ARM7iBIOS[0x8188], 0x200); + memcpy(&ARM7Init[0x0200], &ARM7iBIOS[0xB5D8], 0x40); + memcpy(&ARM7Init[0x0254], &ARM7iBIOS[0xC6D0], 0x1048); + memcpy(&ARM7Init[0x129C], &ARM7iBIOS[0xD718], 0x1048); return true; } diff --git a/src/DSi.h b/src/DSi.h index 08712de..8cc8fd5 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -34,9 +34,6 @@ extern u64 ConsoleID; extern DSi_SDHost* SDMMC; extern DSi_SDHost* SDIO; -extern u8 ITCMInit[0x8000]; -extern u8 ARM7Init[0x3C00]; - bool Init(); void DeInit(); diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index b326dd6..a5e0f41 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -562,17 +562,10 @@ void Key1_ApplyKeycode(u32* keycode, u32 mod) void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod) { // TODO: source the key data from different possible places - if (NDS::ConsoleType == 1) - { - if (dsi) - memcpy(Key1_KeyBuf, &DSi::ARM7Init[0x254], 0x1048); // hax - else - memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax - } + if (dsi && NDS::ConsoleType==1) + memcpy(Key1_KeyBuf, &DSi::ARM7iBIOS[0xC6D0], 0x1048); // hax else - { memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax - } u32 keycode[3] = {idcode, idcode>>1, idcode<<1}; if (level >= 1) Key1_ApplyKeycode(keycode, mod); -- cgit v1.2.3