mirror of
https://github.com/suloku/savegame-manager.git
synced 2026-09-07 18:55:43 -05:00
- add basic framework to support new types of exotic hardware; there are now stubs for big saves (Band Bros DX/Wario Ware DIY)
- Wario Ware DIY is now officially *not* supported
This commit is contained in:
@@ -41,7 +41,6 @@ LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lfat -ldswifi9 -lnds9
|
||||
#LIBS := -lnds9
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
|
||||
@@ -68,7 +68,7 @@ uint8 jedec_table(uint32 id)
|
||||
};
|
||||
}
|
||||
|
||||
uint8 type2_size(bool ir = false)
|
||||
uint8 type2_size(auxspi_extra extra)
|
||||
{
|
||||
static const uint32 offset0 = (8*1024-1); // 8KB
|
||||
static const uint32 offset1 = (2*8*1024-1); // 16KB
|
||||
@@ -76,12 +76,12 @@ uint8 type2_size(bool ir = false)
|
||||
u8 buf2; // +8k data read -> read
|
||||
u8 buf3; // +0k ~data write
|
||||
u8 buf4; // +8k data new comp buf2
|
||||
auxspi_read_data(offset0, &buf1, 1, 2, ir);
|
||||
auxspi_read_data(offset1, &buf2, 1, 2, ir);
|
||||
auxspi_read_data(offset0, &buf1, 1, 2, extra);
|
||||
auxspi_read_data(offset1, &buf2, 1, 2, extra);
|
||||
buf3=~buf1;
|
||||
auxspi_write_data(offset0, &buf3, 1, 2, ir);
|
||||
auxspi_read_data (offset1, &buf4, 1, 2, ir);
|
||||
auxspi_write_data(offset0, &buf1, 1, 2, ir);
|
||||
auxspi_write_data(offset0, &buf3, 1, 2, extra);
|
||||
auxspi_read_data (offset1, &buf4, 1, 2, extra);
|
||||
auxspi_write_data(offset0, &buf1, 1, 2, extra);
|
||||
if(buf4!=buf2) // +8k
|
||||
return 0x0d; // 8KB(64kbit)
|
||||
else
|
||||
@@ -90,47 +90,46 @@ uint8 type2_size(bool ir = false)
|
||||
|
||||
// ========================================================
|
||||
|
||||
uint8 auxspi_save_type(bool ir)
|
||||
uint8 auxspi_save_type(auxspi_extra extra)
|
||||
{
|
||||
uint32 jedec = auxspi_save_jedec_id(ir); // 9f
|
||||
int8 sr = auxspi_save_status_register(ir); // 05
|
||||
uint32 jedec = auxspi_save_jedec_id(extra); // 9f
|
||||
int8 sr = auxspi_save_status_register(extra); // 05
|
||||
|
||||
if ((sr & 0xfd) == 0xF0 && (jedec == 0x00ffffff)) return 1;
|
||||
if ((sr & 0xfd) == 0x00 && (jedec == 0x00ffffff)) return 2;
|
||||
if ((sr & 0xfd) == 0x00 && (jedec != 0x00ffffff)) return 3;
|
||||
// TODO: add support for Band Brothers DX (as soon as I know how)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 auxspi_save_size(bool ir)
|
||||
uint32 auxspi_save_size(auxspi_extra extra)
|
||||
{
|
||||
return 1 << auxspi_save_size_log_2(ir);
|
||||
return 1 << auxspi_save_size_log_2(extra);
|
||||
}
|
||||
|
||||
uint8 auxspi_save_size_log_2(bool ir)
|
||||
uint8 auxspi_save_size_log_2(auxspi_extra extra)
|
||||
{
|
||||
uint8 type = auxspi_save_type(ir); // TESTME: "ir" was missing, should fix recent issues
|
||||
uint8 type = auxspi_save_type(extra);
|
||||
switch (type) {
|
||||
case 1:
|
||||
return 0x09; // 512 bytes
|
||||
break;
|
||||
case 2:
|
||||
return type2_size(ir);
|
||||
return type2_size(extra);
|
||||
break;
|
||||
case 3:
|
||||
return jedec_table(auxspi_save_jedec_id(ir));
|
||||
return jedec_table(auxspi_save_jedec_id(extra));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 auxspi_save_jedec_id(bool ir)
|
||||
uint32 auxspi_save_jedec_id(auxspi_extra extra)
|
||||
{
|
||||
uint32 id = 0;
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(0x9f);
|
||||
id |= auxspi_read() << 16;
|
||||
@@ -141,11 +140,11 @@ uint32 auxspi_save_jedec_id(bool ir)
|
||||
return id;
|
||||
}
|
||||
|
||||
uint8 auxspi_save_status_register(bool ir)
|
||||
uint8 auxspi_save_status_register(auxspi_extra extra)
|
||||
{
|
||||
uint8 sr = 0;
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(0x05);
|
||||
sr = auxspi_read();
|
||||
@@ -153,15 +152,15 @@ uint8 auxspi_save_status_register(bool ir)
|
||||
return sr;
|
||||
}
|
||||
|
||||
void auxspi_read_data(uint32 addr, uint8* buf, uint16 cnt, uint8 type, bool ir)
|
||||
void auxspi_read_data(uint32 addr, uint8* buf, uint16 cnt, uint8 type, auxspi_extra extra)
|
||||
{
|
||||
if (type == 0)
|
||||
type = auxspi_save_type(ir);
|
||||
type = auxspi_save_type(extra);
|
||||
if (type == 0)
|
||||
return;
|
||||
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(0x03 | ((type == 1) ? addr>>8<<3 : 0));
|
||||
|
||||
@@ -183,7 +182,7 @@ void auxspi_read_data(uint32 addr, uint8* buf, uint16 cnt, uint8 type, bool ir)
|
||||
auxspi_close();
|
||||
}
|
||||
|
||||
void auxspi_write_data(uint32 addr, uint8 *buf, uint16 cnt, uint8 type, bool ir)
|
||||
void auxspi_write_data(uint32 addr, uint8 *buf, uint16 cnt, uint8 type, auxspi_extra extra)
|
||||
{
|
||||
if (type == 0)
|
||||
type = auxspi_save_type();
|
||||
@@ -200,15 +199,15 @@ void auxspi_write_data(uint32 addr, uint8 *buf, uint16 cnt, uint8 type, bool ir)
|
||||
// we can only write a finite amount of data at once, so we need a separate loop
|
||||
// for multiple passes.
|
||||
while (addr < addr_end) {
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
// set WEL (Write Enable Latch)
|
||||
auxspi_write(0x06);
|
||||
auxspi_close_lite();
|
||||
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
// send initial "write" command
|
||||
if(type == 1) {
|
||||
@@ -233,42 +232,139 @@ void auxspi_write_data(uint32 addr, uint8 *buf, uint16 cnt, uint8 type, bool ir)
|
||||
auxspi_close_lite();
|
||||
|
||||
// wait programming to finish
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(5);
|
||||
do { REG_AUXSPIDATA = 0; auxspi_wait_busy(); } while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
|
||||
auxspi_wait_wip();
|
||||
auxspi_wait_busy();
|
||||
auxspi_close();
|
||||
}
|
||||
}
|
||||
|
||||
void auxspi_disable_extra(auxspi_extra extra)
|
||||
{
|
||||
switch (extra) {
|
||||
case AUXSPI_INFRARED:
|
||||
auxspi_disable_infrared_core();
|
||||
break;
|
||||
case AUXSPI_BBDX:
|
||||
// TODO:
|
||||
auxspi_disable_big_protection();
|
||||
break;
|
||||
case AUXSPI_BLUETOOTH:
|
||||
// TODO
|
||||
//auxspi_disable_bluetooth();
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
void auxspi_disable_infrared()
|
||||
{
|
||||
auxspi_disable_infrared_core();
|
||||
}
|
||||
|
||||
bool auxspi_has_infrared()
|
||||
void auxspi_disable_big_protection()
|
||||
{
|
||||
return (slot_1_type == 1);
|
||||
static bool doonce = false;
|
||||
if (doonce)
|
||||
return;
|
||||
doonce = true;
|
||||
sysSetBusOwners(true, true);
|
||||
|
||||
auxspi_open(3);
|
||||
auxspi_write(0xf1);
|
||||
auxspi_wait_busy();
|
||||
auxspi_close_lite();
|
||||
|
||||
auxspi_open(3);
|
||||
auxspi_write(0x6);
|
||||
auxspi_wait_busy();
|
||||
auxspi_close_lite();
|
||||
|
||||
auxspi_open(3);
|
||||
auxspi_write(0xfa);
|
||||
auxspi_wait_busy();
|
||||
auxspi_write(0x1);
|
||||
auxspi_wait_busy();
|
||||
auxspi_write(0x31);
|
||||
auxspi_wait_busy();
|
||||
auxspi_close();
|
||||
// --
|
||||
|
||||
auxspi_open(3);
|
||||
auxspi_write(0x14);
|
||||
auxspi_wait_busy();
|
||||
auxspi_close_lite();
|
||||
|
||||
auxspi_open(3);
|
||||
auxspi_write(0x6);
|
||||
auxspi_wait_busy();
|
||||
auxspi_close_lite();
|
||||
|
||||
auxspi_open(3);
|
||||
auxspi_write(0xf8);
|
||||
auxspi_wait_busy();
|
||||
auxspi_write(0x1);
|
||||
auxspi_wait_busy();
|
||||
auxspi_write(0x0);
|
||||
auxspi_wait_busy();
|
||||
auxspi_close();
|
||||
// --
|
||||
|
||||
auxspi_open(3);
|
||||
auxspi_write(0xe);
|
||||
auxspi_wait_busy();
|
||||
auxspi_close();
|
||||
|
||||
}
|
||||
|
||||
void auxspi_erase(bool ir)
|
||||
auxspi_extra auxspi_has_extra()
|
||||
{
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
sysSetBusOwners(true, true);
|
||||
|
||||
// Trying to read the save size in IR mode will fail on non-IR devices.
|
||||
// If we have success, it is an IR device.
|
||||
u8 size2 = auxspi_save_size_log_2(AUXSPI_INFRARED);
|
||||
if (size2 > 0)
|
||||
return AUXSPI_INFRARED;
|
||||
|
||||
// It is not an IR game, so maybe it is a regular game.
|
||||
u8 size1 = auxspi_save_size_log_2();
|
||||
if (size1 > 0)
|
||||
return AUXSPI_DEFAULT;
|
||||
|
||||
#if 0
|
||||
// EXPERIMENTAL: verify that flash cards do not answer with the same signature!
|
||||
// Look for BBDX (which always returns "ff" on every command)
|
||||
uint32 jedec = auxspi_save_jedec_id(); // 9f
|
||||
//int8 sr = auxspi_save_status_register(); // 05
|
||||
if (jedec == 0x00ffffff)
|
||||
return AUXSPI_BBDX;
|
||||
#endif
|
||||
|
||||
// TODO: add support for Pokemon Typing DS (as soon as we figure out how)
|
||||
|
||||
return AUXSPI_FLASH_CARD;
|
||||
}
|
||||
|
||||
void auxspi_erase(auxspi_extra extra)
|
||||
{
|
||||
uint8 type = auxspi_save_type(extra);
|
||||
if (type == 3) {
|
||||
uint8 size;
|
||||
size = 1 << (auxspi_save_size_log_2(ir) - 16);
|
||||
size = 1 << (auxspi_save_size_log_2(extra) - 16);
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
// set WEL (Write Enable Latch)
|
||||
auxspi_write(0x06);
|
||||
auxspi_close_lite();
|
||||
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(0xd8);
|
||||
auxspi_write(i);
|
||||
@@ -277,36 +373,36 @@ void auxspi_erase(bool ir)
|
||||
auxspi_close_lite();
|
||||
|
||||
// wait for programming to finish
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(5);
|
||||
do { REG_AUXSPIDATA = 0; auxspi_wait_busy(); } while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
|
||||
auxspi_wait_wip();
|
||||
auxspi_wait_busy();
|
||||
auxspi_close();
|
||||
}
|
||||
} else {
|
||||
int8 size = 1 << max(0, (auxspi_save_size_log_2(ir) - 15));
|
||||
int8 size = 1 << max(0, (auxspi_save_size_log_2(extra) - 15));
|
||||
memset(data, 0, 0x8000);
|
||||
for (int i = 0; i < size; i++) {
|
||||
auxspi_write_data(i << 15, data, 0x8000, type, ir);
|
||||
auxspi_write_data(i << 15, data, 0x8000, type, extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void auxspi_erase_sector(u32 sector, bool ir)
|
||||
void auxspi_erase_sector(u32 sector, auxspi_extra extra)
|
||||
{
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint8 type = auxspi_save_type(extra);
|
||||
if (type == 3) {
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
// set WEL (Write Enable Latch)
|
||||
auxspi_write(0x06);
|
||||
auxspi_close_lite();
|
||||
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(0xd8);
|
||||
auxspi_write(sector & 0xff);
|
||||
@@ -315,11 +411,11 @@ void auxspi_erase_sector(u32 sector, bool ir)
|
||||
auxspi_close_lite();
|
||||
|
||||
// wait for programming to finish
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
if (extra)
|
||||
auxspi_disable_extra(extra);
|
||||
auxspi_open(0);
|
||||
auxspi_write(5);
|
||||
do { REG_AUXSPIDATA = 0; auxspi_wait_busy(); } while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
|
||||
auxspi_wait_wip();
|
||||
auxspi_wait_busy();
|
||||
auxspi_close();
|
||||
}
|
||||
|
||||
@@ -31,22 +31,52 @@
|
||||
|
||||
#include <nds.h>
|
||||
|
||||
// This is a handy typedef for nonstandard SPI buses, i.e. games with some
|
||||
// extra hardware on the cartridge. The following values mean:
|
||||
// AUXSPI_DEFAULT: A regular game with no exotic hardware.
|
||||
// AUXSPI_INFRARED: A game with an infrared transceiver.
|
||||
// Games known to use this hardware:
|
||||
// - Personal Trainer: Walking (aka Laufrhytmus DS, Walk With Me, ...)
|
||||
// - Pokemon HeartGold/SoulSilver/Black/White
|
||||
// AUXSPI_BBDX: A game with what seems to be an extra protection against reading
|
||||
// out the chip. Exclusively found on Band Brothers DX.
|
||||
// AUXSPI_BLUETOOTH: A game with a Bluetooth transceiver. The only game using this
|
||||
// hardware is Pokemon Typing DS.
|
||||
//
|
||||
// NOTE: This library does *not* support BBDX (I do have the game, but did not find the
|
||||
// time to reverse engineer this; besides, a separate homebrew for this game already exists),
|
||||
// and also *not* BLUETOOTH (the game is Japan-only, and I am from Europe. Plus I can't
|
||||
// read Japanese. And it is unlikely that this game will ever make it here.)
|
||||
//
|
||||
typedef enum {
|
||||
AUXSPI_DEFAULT,
|
||||
AUXSPI_INFRARED,
|
||||
AUXSPI_BBDX,
|
||||
AUXSPI_BLUETOOTH,
|
||||
AUXSPI_FLASH_CARD = 999
|
||||
} auxspi_extra;
|
||||
|
||||
extern bool with_infrared;
|
||||
// These functions reimplement relevant parts of "card.cpp", in a way that is easier to modify.
|
||||
uint8 auxspi_save_type(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
uint32 auxspi_save_size(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
uint8 auxspi_save_size_log_2(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
uint32 auxspi_save_jedec_id(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
uint8 auxspi_save_status_register(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
void auxspi_read_data(uint32 addr, uint8* buf, uint16 cnt, uint8 type = 0,auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
void auxspi_write_data(uint32 addr, uint8 *buf, uint16 cnt, uint8 type = 0,auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
void auxspi_erase(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
void auxspi_erase_sector(u32 sector, auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
|
||||
uint8 auxspi_save_type(bool ir = false);
|
||||
uint32 auxspi_save_size(bool ir = false);
|
||||
uint8 auxspi_save_size_log_2(bool ir = false);
|
||||
uint32 auxspi_save_jedec_id(bool ir = false);
|
||||
uint8 auxspi_save_status_register(bool ir = false);
|
||||
void auxspi_read_data(uint32 addr, uint8* buf, uint16 cnt, uint8 type = 0, bool ir = false);
|
||||
void auxspi_write_data(uint32 addr, uint8 *buf, uint16 cnt, uint8 type = 0, bool ir = false);
|
||||
// These functions are used to identify exotic hardware.
|
||||
auxspi_extra auxspi_has_extra();
|
||||
//bool auxspi_has_infrared();
|
||||
|
||||
void auxspi_disable_extra(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
void auxspi_disable_infrared();
|
||||
void auxspi_erase(bool ir = false);
|
||||
void auxspi_erase_sector(u32 sector, bool ir = false);
|
||||
void auxspi_disable_big_protection();
|
||||
|
||||
bool auxspi_has_infrared();
|
||||
|
||||
bool auxspi_is_unknown_type3();
|
||||
// The following function returns true if this is a type 3 save (big saves, Flash memory), but
|
||||
// the JEDEC ID is not known.
|
||||
bool auxspi_is_unknown_type3(auxspi_extra extra = AUXSPI_DEFAULT);
|
||||
|
||||
#endif
|
||||
@@ -34,9 +34,14 @@ inline void auxspi_wait_busy()
|
||||
while (REG_AUXSPICNT & 0x80);
|
||||
}
|
||||
|
||||
inline void auxspi_wait_wip()
|
||||
{
|
||||
do { REG_AUXSPIDATA = 0; auxspi_wait_busy(); } while (REG_AUXSPIDATA & 0x01); // WIP (Write In Progress) ?
|
||||
}
|
||||
|
||||
inline void auxspi_open(uint8 device)
|
||||
{
|
||||
REG_AUXSPICNT = 0xa040 | (device & 3) | 3;
|
||||
REG_AUXSPICNT = 0xa040 | (device & 3);
|
||||
auxspi_wait_busy();
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ void displayPrintUpper()
|
||||
{
|
||||
bool gba = (mode == 1);
|
||||
u32 dstype = (mode == 3) ? 1 : 0;
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
|
||||
// print upper screen (background)
|
||||
consoleSelect(&upperScreen);
|
||||
@@ -98,7 +97,7 @@ void displayPrintUpper()
|
||||
|
||||
// fetch cartridge header (maybe, calling "cardReadHeader" on a FC messes with libfat!)
|
||||
sNDSHeader nds;
|
||||
if (slot_1_type != 2)
|
||||
if (slot_1_type != AUXSPI_FLASH_CARD)
|
||||
cardReadHeader((uint8*)&nds);
|
||||
|
||||
char name[MAXPATHLEN];
|
||||
@@ -136,7 +135,7 @@ void displayPrintUpper()
|
||||
// 1) The cart id.
|
||||
consoleSetWindow(&upperScreen, 10, 3, 22, 1);
|
||||
sprintf(&name[0], "----");
|
||||
if (slot_1_type == 2) {
|
||||
if (slot_1_type == AUXSPI_FLASH_CARD) {
|
||||
sprintf(&name[0], "Flash Card");
|
||||
} else {
|
||||
memcpy(&name[0], &nds.gameCode[0], 4);
|
||||
@@ -148,7 +147,7 @@ void displayPrintUpper()
|
||||
// 2) The cart name.
|
||||
consoleSetWindow(&upperScreen, 10, 4, 22, 1);
|
||||
sprintf(&name[0], "----");
|
||||
if (slot_1_type == 2) {
|
||||
if (slot_1_type == AUXSPI_FLASH_CARD) {
|
||||
sprintf(&name[0], "Flash Card");
|
||||
} else {
|
||||
memcpy(&name[0], &nds.gameTitle[0], 12);
|
||||
@@ -160,11 +159,11 @@ void displayPrintUpper()
|
||||
// 3) The save type
|
||||
consoleSetWindow(&upperScreen, 10, 5, 22, 1);
|
||||
sprintf(&name[0], "----");
|
||||
if (slot_1_type == 2) {
|
||||
if (slot_1_type == AUXSPI_FLASH_CARD) {
|
||||
sprintf(&name[0], "Flash Card");
|
||||
} else {
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
uint8 type = auxspi_save_type(slot_1_type);
|
||||
uint8 size = auxspi_save_size_log_2(slot_1_type);
|
||||
switch (type) {
|
||||
case 1:
|
||||
sprintf(&name[0], "Eeprom (%i Bytes)", size);
|
||||
@@ -174,7 +173,7 @@ void displayPrintUpper()
|
||||
break;
|
||||
case 3:
|
||||
if (size == 0)
|
||||
sprintf(&name[0], "Flash (ID:%x)", auxspi_save_jedec_id(ir));
|
||||
sprintf(&name[0], "Flash (ID:%x)", auxspi_save_jedec_id(slot_1_type));
|
||||
else
|
||||
sprintf(&name[0], "Flash (%i kB)", 1 << (size - 10));
|
||||
break;
|
||||
@@ -190,10 +189,18 @@ void displayPrintUpper()
|
||||
consoleSetWindow(&upperScreen, 10, 6, 22, 1);
|
||||
consoleClear();
|
||||
memset(&name[0], 0, MAXPATHLEN);
|
||||
if (slot_1_type == 1) {
|
||||
sprintf(&name[0], "Infrared");
|
||||
} else {
|
||||
sprintf(&name[0], "----");
|
||||
switch (slot_1_type) {
|
||||
case AUXSPI_INFRARED:
|
||||
sprintf(&name[0], "Infrared");
|
||||
break;
|
||||
case AUXSPI_BBDX:
|
||||
sprintf(name, "XXL");
|
||||
break;
|
||||
case AUXSPI_BLUETOOTH:
|
||||
sprintf(name, "Bluetooth");
|
||||
break;
|
||||
default:
|
||||
sprintf(&name[0], "----");
|
||||
}
|
||||
iprintf("%s", name);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
u8 *data;
|
||||
u32 size_buf;
|
||||
|
||||
u32 slot_1_type = ~0;
|
||||
auxspi_extra slot_1_type = AUXSPI_FLASH_CARD;
|
||||
|
||||
char ftp_ip[16] = "ftp_ip";
|
||||
char ftp_user[64] = "ftp_user";
|
||||
|
||||
@@ -27,11 +27,12 @@
|
||||
#define GLOBALS_H
|
||||
|
||||
#include <nds.h>
|
||||
#include "auxspi.h"
|
||||
|
||||
extern u8 *data;
|
||||
extern u32 size_buf;
|
||||
|
||||
extern u32 slot_1_type;
|
||||
extern auxspi_extra slot_1_type;
|
||||
|
||||
extern char ftp_ip[16];
|
||||
extern char ftp_user[64];
|
||||
|
||||
@@ -80,9 +80,9 @@ bool swap_cart()
|
||||
while (!swap) {
|
||||
if (keysCurrent() & KEY_A) {
|
||||
// identify hardware
|
||||
slot_1_type = get_slot1_type();
|
||||
slot_1_type = auxspi_has_extra();
|
||||
// don't try to dump a flash card
|
||||
if (slot_1_type == 2)
|
||||
if (slot_1_type == AUXSPI_FLASH_CARD)
|
||||
continue;
|
||||
|
||||
sysSetBusOwners(true, true);
|
||||
@@ -102,37 +102,6 @@ bool swap_cart()
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 get_slot1_type()
|
||||
{
|
||||
sysSetBusOwners(true, true);
|
||||
|
||||
// Trying to read the save size in IR mode will fail on non-IR devices.
|
||||
// If we have success, it is an IR device.
|
||||
u8 size2 = auxspi_save_size_log_2(true);
|
||||
if (size2 > 0)
|
||||
return 1;
|
||||
|
||||
// It is not an IR game, so maybe it is a regular game.
|
||||
u8 size1 = auxspi_save_size_log_2(false);
|
||||
if (size1 > 0)
|
||||
return 0;
|
||||
|
||||
// No save size test returned a save chip, so it must be a flash card,
|
||||
// or a type 3 save with an unknown JEDEC ID. Unfortunately, due to
|
||||
// different behaviour of flash cards, we can't test for this case,
|
||||
// or the flash card may be recognised as "type 3 game".
|
||||
/*
|
||||
u32 id2 = auxspi_save_jedec_id(true);
|
||||
u32 id1 = auxspi_save_jedec_id(false);
|
||||
if (id2 != 0x00ffffff)
|
||||
return 1;
|
||||
if (id1 != 0x00ffffff)
|
||||
return 0;
|
||||
*/
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool swap_card_game(uint32 size)
|
||||
{
|
||||
return false;
|
||||
@@ -195,8 +164,8 @@ bool hwDetectSlot2DLDI()
|
||||
// This function is called on boot; it detects the hardware configuration and selects the mode.
|
||||
u32 hwDetect()
|
||||
{
|
||||
// Identify Slot 1 devide. This is used by pretty much everything.
|
||||
slot_1_type = get_slot1_type();
|
||||
// Identify Slot 1 device. This is used by pretty much everything.
|
||||
slot_1_type = auxspi_has_extra();
|
||||
|
||||
// First, look for a DSi running in DSi mode.
|
||||
if (isDsi()) {
|
||||
@@ -294,10 +263,9 @@ void hwBackup3in1()
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
uint8 size = auxspi_save_size_log_2(slot_1_type);
|
||||
int size_blocks = 1 << max(0, (int8(size) - 18)); // ... in units of 0x40000 bytes - that's 256 kB
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint8 type = auxspi_save_type(slot_1_type);
|
||||
|
||||
displayMessage2F(STR_HW_3IN1_FORMAT_NOR);
|
||||
hwFormatNor(0, size_blocks+1);
|
||||
@@ -314,7 +282,7 @@ void hwBackup3in1()
|
||||
|
||||
for (int i = 0; i < size_blocks; i++) {
|
||||
displayProgressBar(i+1, size_blocks);
|
||||
auxspi_read_data(i << 15, data, LEN, type, ir);
|
||||
auxspi_read_data(i << 15, data, LEN, type, slot_1_type);
|
||||
uint32 ime = hwGrab3in1();
|
||||
SetSerialMode();
|
||||
WriteNorFlash((i << 15) + pitch, data, LEN);
|
||||
@@ -462,25 +430,22 @@ void hwRestore3in1()
|
||||
|
||||
void hwRestore3in1_b(uint32 size_file)
|
||||
{
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
|
||||
// Third, swap in a new game
|
||||
uint32 size = auxspi_save_size_log_2(ir);
|
||||
uint32 size = auxspi_save_size_log_2(slot_1_type);
|
||||
while ((size_file < size) || (slot_1_type == 2)) {
|
||||
if (slot_1_type == 2)
|
||||
displayMessage2F(STR_HW_SWAP_CARD);
|
||||
else if (size_file < size)
|
||||
displayMessage2F(STR_HW_WRONG_GAME);
|
||||
swap_cart();
|
||||
ir = (slot_1_type == 1) ? true : false;
|
||||
size = auxspi_save_size_log_2(ir);
|
||||
size = auxspi_save_size_log_2(slot_1_type);
|
||||
}
|
||||
displayPrintUpper();
|
||||
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint8 type = auxspi_save_type(slot_1_type);
|
||||
if (type == 3) {
|
||||
displayMessage2F(STR_HW_FORMAT_GAME);
|
||||
auxspi_erase(ir);
|
||||
auxspi_erase(slot_1_type);
|
||||
}
|
||||
|
||||
// And finally, write the save!
|
||||
@@ -508,7 +473,7 @@ void hwRestore3in1_b(uint32 size_file)
|
||||
uint32 ime = hwGrab3in1();
|
||||
ReadNorFlash(data, (i << shift) + pitch, LEN);
|
||||
hwRelease3in1(ime);
|
||||
auxspi_write_data(i << shift, data, LEN, type, ir);
|
||||
auxspi_write_data(i << shift, data, LEN, type, slot_1_type);
|
||||
}
|
||||
displayProgressBar(1, 1);
|
||||
|
||||
@@ -519,10 +484,9 @@ void hwRestore3in1_b(uint32 size_file)
|
||||
// ------------------------------------------------------------
|
||||
void hwErase()
|
||||
{
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
displayMessage2F(STR_HW_WARN_DELETE);
|
||||
while (!(keysCurrent() & (KEY_UP | KEY_R | KEY_Y))) {};
|
||||
auxspi_erase(ir);
|
||||
auxspi_erase(slot_1_type);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
@@ -533,9 +497,8 @@ void hwBackupSlot2()
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
uint32 size = auxspi_save_size_log_2(ir);
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint32 size = auxspi_save_size_log_2(slot_1_type);
|
||||
uint8 type = auxspi_save_type(slot_1_type);
|
||||
|
||||
// just select a filename, no extra work required!
|
||||
char path[256];
|
||||
@@ -572,7 +535,7 @@ void hwBackupSlot2()
|
||||
u32 LEN = min(1 << size, 0x100);
|
||||
for (u32 i = 0; i < size_blocks; i++) {
|
||||
displayProgressBar(i+1, size_blocks);
|
||||
auxspi_read_data(i << 8, data, LEN, type, ir);
|
||||
auxspi_read_data(i << 8, data, LEN, type, slot_1_type);
|
||||
fwrite(data, 1, LEN, file);
|
||||
}
|
||||
fclose(file);
|
||||
@@ -585,9 +548,8 @@ void hwRestoreSlot2()
|
||||
{
|
||||
// First, swap in a new game
|
||||
swap_cart();
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
uint32 size = auxspi_save_size_log_2(ir);
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint32 size = auxspi_save_size_log_2(slot_1_type);
|
||||
uint8 type = auxspi_save_type(slot_1_type);
|
||||
displayPrintUpper();
|
||||
|
||||
// second, select a save file
|
||||
@@ -610,7 +572,7 @@ void hwRestoreSlot2()
|
||||
// 2a, format game if required
|
||||
if (type == 3) {
|
||||
displayMessage2F(STR_HW_FORMAT_GAME);
|
||||
auxspi_erase(ir);
|
||||
auxspi_erase(slot_1_type);
|
||||
}
|
||||
|
||||
// and third, write save
|
||||
@@ -637,7 +599,7 @@ void hwRestoreSlot2()
|
||||
displayProgressBar(i+1, num_blocks);
|
||||
fread(data, 1, LEN, file);
|
||||
sysSetBusOwners(true, true);
|
||||
auxspi_write_data(i << shift, data, LEN, type, ir);
|
||||
auxspi_write_data(i << shift, data, LEN, type, slot_1_type);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
@@ -656,11 +618,10 @@ void hwBackupFTP(bool dlp)
|
||||
// First: swap card
|
||||
if (!dlp)
|
||||
swap_cart();
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
displayPrintUpper();
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
uint8 size = auxspi_save_size_log_2(slot_1_type);
|
||||
int size_blocks = 1 << max(0, (int8(size) - 18)); // ... in units of 0x40000 bytes - that's 256 kB
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint8 type = auxspi_save_type(slot_1_type);
|
||||
if (size < 15)
|
||||
size_blocks = 1;
|
||||
else
|
||||
@@ -735,7 +696,7 @@ void hwBackupFTP(bool dlp)
|
||||
int num_ftp_blocks = 1 << (size - 9);
|
||||
for (int i = 0; i < num_ftp_blocks; i++) {
|
||||
displayProgressBar(i+1, num_ftp_blocks);
|
||||
auxspi_read_data(i << 9, (u8*)&data[0], length, type, ir);
|
||||
auxspi_read_data(i << 9, (u8*)&data[0], length, type, slot_1_type);
|
||||
u32 out = 0;
|
||||
while (out < length) {
|
||||
u32 delta = FtpWrite((u8*)&data[out], length-out, ndata);
|
||||
@@ -767,7 +728,7 @@ void hwBackupFTP(bool dlp)
|
||||
}
|
||||
|
||||
// an internal function used to read big files from the FTP server
|
||||
bool hwRestoreFTPPartial(u32 ofs, u32 size, u32 type, netbuf *ndata, bool ir)
|
||||
bool hwRestoreFTPPartial(u32 ofs, u32 size, u32 type, netbuf *ndata)
|
||||
{
|
||||
int num_blocks_ftp = 1 << (size - 9);
|
||||
u8 *pdata = data;
|
||||
@@ -808,14 +769,14 @@ bool hwRestoreFTPPartial(u32 ofs, u32 size, u32 type, netbuf *ndata, bool ir)
|
||||
u32 num = max(u32(0), size-16);
|
||||
for (int i = 0; i < (1 << num); i++) {
|
||||
displayProgressBar(i+1, 1 << num);
|
||||
auxspi_erase_sector(sector+i, ir);
|
||||
auxspi_erase_sector(sector+i, slot_1_type);
|
||||
}
|
||||
displayProgressBar(0,0);
|
||||
}
|
||||
displayMessage2F(STR_HW_WRITE_GAME);
|
||||
for (int i = 0; i < (1 << (size - shift)); i++) {
|
||||
displayProgressBar(i+1, 1 << (size - shift));
|
||||
auxspi_write_data(ofs + (i << shift), ((u8*)data)+(i<<shift), LEN, type, ir);
|
||||
auxspi_write_data(ofs + (i << shift), ((u8*)data)+(i<<shift), LEN, type, slot_1_type);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -871,9 +832,8 @@ void hwRestoreFTP(bool dlp)
|
||||
if (!dlp)
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint8 size = auxspi_save_size_log_2(slot_1_type);
|
||||
uint8 type = auxspi_save_type(slot_1_type);
|
||||
|
||||
// Fourth: read file
|
||||
u8 data_log2 = log2trunc(size_buf);
|
||||
@@ -886,7 +846,7 @@ void hwRestoreFTP(bool dlp)
|
||||
sprintf(ctr, "%i/%i", i+1, num_read_blocks);
|
||||
displayMessage2F(STR_HW_READ_FILE, fname);
|
||||
displayMessageF(STR_STR, ctr);
|
||||
hwRestoreFTPPartial(i << len_block, len_block, type, ndata, ir);
|
||||
hwRestoreFTPPartial(i << len_block, len_block, type, ndata);
|
||||
}
|
||||
FtpClose(ndata);
|
||||
FtpQuit(buf);
|
||||
|
||||
@@ -47,7 +47,7 @@ void do_dump_nds_save_stage_2(int size);
|
||||
void do_restore_nds_save();
|
||||
|
||||
bool swap_cart();
|
||||
u32 get_slot1_type();
|
||||
//u32 get_slot1_type();
|
||||
|
||||
// This function was previously found in the main function.
|
||||
// Return values:
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user