Skip to content

Commit

Permalink
Add support for TWL carts.
Browse files Browse the repository at this point in the history
Overhaul of old cart loading code courtasy of Robz8.

There is however a small regression. This build currently can't boot
DS-Xtreme.

If you have issues with flashcarts not booting games/homebrew correctly,
disable the extended ram option in the ini file. Currently off by
default. But it must be on for TWL carts to boot correctly.
  • Loading branch information
ApacheThunder committed Apr 4, 2020
1 parent 9f27ebd commit 33b0918
Show file tree
Hide file tree
Showing 35 changed files with 2,789 additions and 755 deletions.
6 changes: 3 additions & 3 deletions BootLoader/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ SPECS := specs
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi
ARCH := -mthumb-interwork -march=armv4t

CFLAGS := -g -Wall -O2\
-fomit-frame-pointer\
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
-ffast-math \
$(ARCH)

CFLAGS += $(INCLUDE) -DARM7
CFLAGS += $(INCLUDE) -DARM7 -std=gnu99

ASFLAGS := -g $(ARCH) $(INCLUDE)
LDFLAGS := -nostartfiles -T$(CURDIR)/../load.ld -g $(ARCH) -Wl,-Map,$(TARGET).map
Expand Down
6 changes: 4 additions & 2 deletions BootLoader/load.ld
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ ENTRY(_start)

MEMORY {

vram : ORIGIN = 0x06000000, LENGTH = 64K /* Reserve last 64K for cheats */
arm9ram : ORIGIN = 0x027FD800, LENGTH = 2K /* Used for the ARM9's functions */
vram : ORIGIN = 0x06020000, LENGTH = 128K
arm9ram : ORIGIN = 0x023FE000, LENGTH = 8K /* Used for the ARM9's functions */
}

__vram_start = ORIGIN(vram);
Expand All @@ -15,6 +15,7 @@ __sp_svc = __sp_irq - 0x100;
__sp_usr = __sp_svc - 0x100;

__irq_flags = __vram_top - 8;
__irq_flagsaux = __vram_top - 0x40; /*__irq_flagsaux = 0x04000000 - 0x40;*/
__irq_vector = __vram_top - 4;


Expand Down Expand Up @@ -222,3 +223,4 @@ SECTIONS
.stack 0x80000 : { _stack = .; *(.stack) }
/* These must appear regardless of . */
}

167 changes: 167 additions & 0 deletions BootLoader/source/card.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*---------------------------------------------------------------------------------
Copyright (C) 2005
Michael Noland (joat)
Jason Rogers (dovoto)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/

#ifndef NDS_CARD_INCLUDE
#define NDS_CARD_INCLUDE


#include "ndstypes.h"

// Card bus
#define REG_CARD_DATA_RD (*(vu32*)0x04100010)

#define REG_AUXSPICNT (*(vu16*)0x040001A0)
#define REG_AUXSPICNTH (*(vu8*)0x040001A1)
#define REG_AUXSPIDATA (*(vu8*)0x040001A2)
#define REG_ROMCTRL (*(vu32*)0x040001A4)

#define REG_CARD_COMMAND ((vu8*)0x040001A8)

#define REG_CARD_1B0 (*(vu32*)0x040001B0)
#define REG_CARD_1B4 (*(vu32*)0x040001B4)
#define REG_CARD_1B8 (*(vu16*)0x040001B8)
#define REG_CARD_1BA (*(vu16*)0x040001BA)

#define CARD_CR1_ENABLE 0x80 // in byte 1, i.e. 0x8000
#define CARD_CR1_IRQ 0x40 // in byte 1, i.e. 0x4000

// SPI EEPROM COMMANDS
#define SPI_EEPROM_WRSR 0x01
#define SPI_EEPROM_PP 0x02 // Page Program
#define SPI_EEPROM_READ 0x03
#define SPI_EEPROM_WRDI 0x04 // Write disable
#define SPI_EEPROM_RDSR 0x05 // Read status register
#define SPI_EEPROM_WREN 0x06 // Write enable
#define SPI_EEPROM_PW 0x0a // Page Write
#define SPI_EEPROM_FAST 0x0b // Fast Read
#define SPI_EEPROM_RDID 0x9f
#define SPI_EEPROM_RDP 0xab // Release from deep power down
#define SPI_EEPROM_DPD 0xb9 // Deep power down

#define CARD_ACTIVATE (1<<31) // when writing, get the ball rolling
#define CARD_WR (1<<30) // Card write enable
#define CARD_nRESET (1<<29) // value on the /reset pin (1 = high out, not a reset state, 0 = low out = in reset)
#define CARD_SEC_LARGE (1<<28) // Use "other" secure area mode, which tranfers blocks of 0x1000 bytes at a time
#define CARD_CLK_SLOW (1<<27) // Transfer clock rate (0 = 6.7MHz, 1 = 4.2MHz)
#define CARD_BLK_SIZE(n) (((n)&0x7)<<24) // Transfer block size, (0 = None, 1..6 = (0x100 << n) bytes, 7 = 4 bytes)
#define CARD_SEC_CMD (1<<22) // The command transfer will be hardware encrypted (KEY2)
#define CARD_DELAY2(n) (((n)&0x3F)<<16) // Transfer delay length part 2
#define CARD_SEC_SEED (1<<15) // Apply encryption (KEY2) seed to hardware registers
#define CARD_SEC_EN (1<<14) // Security enable
#define CARD_SEC_DAT (1<<13) // The data transfer will be hardware encrypted (KEY2)
#define CARD_DELAY1(n) ((n)&0x1FFF) // Transfer delay length part 1

// 3 bits in b10..b8 indicate something
// read bits
#define CARD_BUSY (1<<31) // when reading, still expecting incomming data?
#define CARD_DATA_READY (1<<23) // when reading, CARD_DATA_RD or CARD_DATA has another word of data and is good to go

// Card commands
#define CARD_CMD_DUMMY 0x9F
#define CARD_CMD_HEADER_READ 0x00
#define CARD_CMD_HEADER_CHIPID 0x90
#define CARD_CMD_ACTIVATE_BF 0x3C // Go into blowfish (KEY1) encryption mode
#define CARD_CMD_ACTIVATE_SEC 0x40 // Go into hardware (KEY2) encryption mode
#define CARD_CMD_SECURE_CHIPID 0x10
#define CARD_CMD_SECURE_READ 0x20
#define CARD_CMD_DISABLE_SEC 0x60 // Leave hardware (KEY2) encryption mode
#define CARD_CMD_DATA_MODE 0xA0
#define CARD_CMD_DATA_READ 0xB7
#define CARD_CMD_DATA_CHIPID 0xB8

//REG_AUXSPICNT
#define CARD_ENABLE (1<<15)
#define CARD_SPI_ENABLE (1<<13)
#define CARD_SPI_BUSY (1<<7)
#define CARD_SPI_HOLD (1<<6)

#define CARD_SPICNTH_ENABLE (1<<7) // in byte 1, i.e. 0x8000
#define CARD_SPICNTH_IRQ (1<<6) // in byte 1, i.e. 0x4000

#ifdef __cplusplus
extern "C" {
#endif


void enableSlot1();
void disableSlot1();

void cardWriteCommand(const u8 *command);
void cardPolledTransfer(u32 flags, u32 *destination, u32 length, const u8 *command);
void cardStartTransfer(const u8 *command, u32 *destination, int channel, u32 flags);
uint32 cardWriteAndRead(const u8 *command, u32 flags);
void cardParamCommand (u8 command, u32 parameter, u32 flags, u32 *destination, u32 length);

// These commands require the cart to not be initialized yet, which may mean the user
// needs to eject and reinsert the cart or they will return random data.
void cardReadHeader(u8 *header);
u32 cardReadID(u32 flags);
void cardReset();

//---------------------------------------------------------------------------------
static inline void eepromWaitBusy() {
//---------------------------------------------------------------------------------
while (REG_AUXSPICNT & CARD_SPI_BUSY);
}

// Reads from the EEPROM
void cardReadEeprom(u32 address, u8 *data, u32 length, u32 addrtype);

// Writes to the EEPROM. TYPE 3 EEPROM must be erased first (I think?)
void cardWriteEeprom(u32 address, u8 *data, u32 length, u32 addrtype);

// Returns the ID of the EEPROM chip? Doesn't work well, most chips give ff,ff
// i = 0 or 1
u32 cardEepromReadID();

// Sends a command to the EEPROM
u8 cardEepromCommand(u8 command);

/*
* -1:no card or no EEPROM
* 0:unknown PassMe?
* 1:TYPE 1 4Kbit(512Byte) EEPROM
* 2:TYPE 2 64Kbit(8KByte)or 512kbit(64Kbyte) EEPROM
* 3:TYPE 3 2Mbit(256KByte) FLASH MEMORY (some rare 4Mbit and 8Mbit chips also)
*/
int cardEepromGetType(void);

// Returns the size in bytes of EEPROM
u32 cardEepromGetSize();

// Erases the entire chip. TYPE 3 chips MUST be erased before writing to them. (I think?)
void cardEepromChipErase(void);

// Erases a single sector of the TYPE 3 chip
void cardEepromSectorErase(u32 address);

#ifdef __cplusplus
}
#endif


#endif

23 changes: 23 additions & 0 deletions BootLoader/source/clear_cache.arm9.s
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,28 @@ BEGIN_ASM_FUNC arm9_clearCache
mcr p15, 0, r3, c7, c6, 0 @ Flush DCache
mcr p15, 0, r3, c7, c10, 4 @ empty write buffer

mcr p15, 0, r3, c3, c0, 0 @ disable write buffer (def = 0)

mcr p15, 0, r3, c2, c0, 0 @ disable DTCM and protection unit

mcr p15, 0, r3, c6, c0, 0 @ disable protection unit 0 (def = 0)
mcr p15, 0, r3, c6, c1, 0 @ disable protection unit 1 (def = 0)
mcr p15, 0, r3, c6, c2, 0 @ disable protection unit 2 (def = 0)
mcr p15, 0, r3, c6, c3, 0 @ disable protection unit 3 (def = 0)
mcr p15, 0, r3, c6, c4, 0 @ disable protection unit 4 (def = ?)
mcr p15, 0, r3, c6, c5, 0 @ disable protection unit 5 (def = ?)
mcr p15, 0, r3, c6, c6, 0 @ disable protection unit 6 (def = ?)
mcr p15, 0, r3, c6, c7, 0 @ disable protection unit 7 (def = ?)

mcr p15, 0, r3, c5, c0, 3 @ IAccess
mcr p15, 0, r3, c5, c0, 2 @ DAccess

mov r3, #0x00800000
add r3, r3, #0x00A
mcr p15, 0, r3, c9, c1, 0 @ DTCM base (def = 0x0080000A) ???

mov r3, #0x0000000C
mcr p15, 0, r3, c9, c1, 1 @ ITCM base (def = 0x0000000C) ???

bx lr

39 changes: 10 additions & 29 deletions BootLoader/source/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#define _COMMON_H

#include <nds/dma.h>
#include <nds/ipc.h>
#include <stdlib.h>

#define resetCpu() \
Expand All @@ -33,28 +32,18 @@ enum { ERR_NONE=0x00, ERR_STS_CLR_MEM=0x01, ERR_STS_LOAD_BIN=0x02, ERR_STS_HOOK_
ERR_NOCHEAT=0x21, ERR_HOOK=0x22,
} ERROR_CODES;

// Values fixed so they can be shared with ASM code
enum {
ARM9_BOOT = 0,
ARM9_START = 1,
ARM9_RESET = 2,
ARM9_READY = 3,
ARM9_MEMCLR = 4
} ARM9_STATE;

enum {
ARM7_BOOT = 0,
ARM7_START = 1,
ARM7_RESET = 2,
ARM7_READY = 3,
ARM7_MEMCLR = 4,
ARM7_LOADBIN = 5,
ARM7_HOOKBIN = 6,
ARM7_BOOTBIN = 7,
ARM7_ERR = 8
} ARM7_STATE;
enum {ARM9_BOOT, ARM9_START, ARM9_MEMCLR, ARM9_READY, ARM9_BOOTBIN, ARM9_DISPERR, ARM9_SETSCFG} ARM9_STATE;
extern tNDSHeader* ndsHeader;
extern bool dsiModeConfirmed;
extern bool arm9_dsiModeConfirmed;
extern bool arm9_boostVram;
extern bool arm9_scfgUnlock;
extern bool arm9_TWLClockSpeeds;
extern bool arm9_ExtendRam;

extern volatile int arm9_stateFlag;
extern volatile u32 arm9_errorCode;
extern volatile bool arm9_errorClearBG;

static inline void dmaFill(const void* src, void* dest, uint32 size) {
DMA_SRC(3) = (uint32)src;
Expand All @@ -69,13 +58,5 @@ static inline void copyLoop (u32* dest, const u32* src, size_t size) {
} while (size -= 4);
}

static inline void ipcSendState(uint8_t state) {
REG_IPC_SYNC = (state & 0x0f) << 8;
}

static inline uint8_t ipcRecvState(void) {
return (uint8_t)(REG_IPC_SYNC & 0x0f);
}

#endif // _COMMON_H

9 changes: 4 additions & 5 deletions BootLoader/source/crt0.arm9.s
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
@---------------------------------------------------------------------------------
_arm9_start:
@---------------------------------------------------------------------------------
mov r0, #0x04000000
mov r1, #0
str r1, [r0,#0x208] @ REG_IME
str r1, [r0,#0x210] @ REG_IE
str r1, [r0,#0x218] @ REG_AUXIE
mov r0, #0x04000000 @ IME = 0;
add r0, r0, #0x208
strh r0, [r0]

mov r0, #0x12 @ Switch to IRQ Mode
msr cpsr, r0
Expand All @@ -36,6 +34,7 @@ _arm9_start:

@ If the user ever returns, restart
b _arm9_start

@---------------------------------------------------------------------------------
_blx_r3_stub:
@---------------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 33b0918

Please sign in to comment.