mirror of
https://github.com/suloku/savegame-manager.git
synced 2026-04-24 23:16:54 -05:00
Source code for the 0.2.2 release (2-12-2011).
This commit is contained in:
parent
97bdcc76ad
commit
fb9eb21cf4
|
|
@ -41,6 +41,7 @@ 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 := -L../../../../libfat-src-1.0.9/lib -lfatx -ldswifi9 -lnds9x
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@
|
|||
|
||||
using std::max;
|
||||
|
||||
extern u8 data[0x8000];
|
||||
extern u8 *data;
|
||||
extern u32 size_buf;
|
||||
|
||||
|
||||
// ========================================================
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include <nds.h>
|
||||
|
||||
extern int ir_delay;
|
||||
|
||||
inline void auxspi_wait_busy()
|
||||
{
|
||||
while (REG_AUXSPICNT & 0x80);
|
||||
|
|
@ -78,8 +80,8 @@ inline uint16 auxspi_read_16()
|
|||
inline void auxspi_disable_infrared_core()
|
||||
{
|
||||
auxspi_open(0);
|
||||
swiDelay(1000);
|
||||
swiDelay(ir_delay);
|
||||
auxspi_open(2);
|
||||
auxspi_write(0);
|
||||
swiDelay(1000);
|
||||
swiDelay(ir_delay);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#include "auxspi_core.cpp"
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
PrintConsole upperScreen;
|
||||
PrintConsole lowerScreen;
|
||||
|
||||
|
|
@ -55,7 +57,7 @@ void displayInit()
|
|||
consoleInit(&lowerScreen, 3,BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true);
|
||||
|
||||
consoleSelect(&upperScreen);
|
||||
iprintf("\n\n\n\n\nDS savegame manager\nVersion 0.2.1 Beta\nBy Pokedoc");
|
||||
iprintf("\n\n\n\n\nDS savegame manager\nVersion 0.2.2 Beta\nBy Pokedoc");
|
||||
|
||||
displayPrintState("Press (B) to continue");
|
||||
while (!(keysCurrent() & KEY_B));
|
||||
|
|
@ -80,7 +82,7 @@ void displayPrintUpper()
|
|||
iprintf("Special :\n");
|
||||
iprintf("--- SLOT 2 ---------------------");
|
||||
if (dstype > 0)
|
||||
iprintf("This device has no Slot-2");
|
||||
iprintf("This device has no Slot-2\n");
|
||||
else {
|
||||
iprintf("Game ID :\n");
|
||||
iprintf("Game name:\n");
|
||||
|
|
@ -100,6 +102,24 @@ void displayPrintUpper()
|
|||
sNDSHeader nds;
|
||||
if (!flash_card)
|
||||
cardReadHeader((uint8*)&nds);
|
||||
// search for the correct header
|
||||
/*
|
||||
for (int i = 0; i < 0x1000000; i++)
|
||||
{
|
||||
char *test = (char*)0x02000000;
|
||||
if ((test[0]=='C')&&(test[1]=='P')&&(test[2]=='U')&&(test[3]=='D')) {
|
||||
iprintf("found!");
|
||||
while(1);
|
||||
}
|
||||
test++;
|
||||
}
|
||||
*/
|
||||
//nds = NDS_HEADER;
|
||||
/*
|
||||
if (nds.gameTitle[0] == 0xff)
|
||||
// DSi
|
||||
nds = NDS_HEADER;
|
||||
*/
|
||||
|
||||
char name[MAXPATHLEN];
|
||||
// 0) print the mode
|
||||
|
|
@ -194,8 +214,12 @@ void displayPrintUpper()
|
|||
if (ezflash) {
|
||||
if (ezflash == 0x89168916)
|
||||
sprintf(name, "3in1 (512M)");
|
||||
else if (ezflash == 0x227E2218)
|
||||
sprintf(name, "3in1 (256M V2)");
|
||||
else if (ezflash == 0x227E2202)
|
||||
sprintf(name, "3in1 (256M V1)");
|
||||
else
|
||||
sprintf(name, "3in1 (256M)");
|
||||
sprintf(name, "3in1 (unknown type)");
|
||||
} else if (gba)
|
||||
sprintf(name, "%.4s", (char*)0x080000ac);
|
||||
else if (slot2)
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ void SetSerialMode()
|
|||
}
|
||||
uint32 ReadNorFlashID()
|
||||
{
|
||||
// This function was damaged on the origonal sample, "ID mode" was never left. It is fixed now.
|
||||
vuint16 id1,id2,id3,id4;
|
||||
ID=0;
|
||||
//check intel 512M 3in1 card
|
||||
|
|
@ -134,29 +135,66 @@ uint32 ReadNorFlashID()
|
|||
|
||||
id1 = *((vuint16 *)(FlashBase+0x2)) ;
|
||||
id2 = *((vuint16 *)(FlashBase+0x2002)) ;
|
||||
if( (id1!=0x227E)|| (id2!=0x227E))
|
||||
if( (id1!=0x227E)|| (id2!=0x227E)) {
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ;
|
||||
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
id1 = *((vuint16 *)(FlashBase+0xE*2)) ;
|
||||
id2 = *((vuint16 *)(FlashBase+0x100e*2)) ;
|
||||
if(id1==0x2218 && id2==0x2218) //H6H6
|
||||
{
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ;
|
||||
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ;
|
||||
ID = 0x227E2218;
|
||||
return 0x227E2218;
|
||||
}
|
||||
|
||||
if(id1==0x2202 && id2==0x2202) //VZ064
|
||||
{
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ;
|
||||
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ;
|
||||
ID = 0x227E2202;
|
||||
return 0x227E2202;
|
||||
}
|
||||
if(id1==0x2202 && id2==0x2220) //VZ064
|
||||
{
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ;
|
||||
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ;
|
||||
ID = 0x227E2202;
|
||||
return 0x227E2202;
|
||||
}
|
||||
if(id1==0x2202 && id2==0x2215) //VZ064
|
||||
{
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x2AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x555*2)) = 0xf0 ;
|
||||
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xAA ;
|
||||
*((vuint16 *)(FlashBase+0x12AA*2)) = 0x55 ;
|
||||
*((vuint16 *)(FlashBase+0x1555*2)) = 0xf0 ;
|
||||
ID = 0x227E2202;
|
||||
return 0x227E2202;
|
||||
}
|
||||
|
|
@ -196,6 +234,12 @@ void Block_EraseIntel(u32 blockAdd)
|
|||
OpenNorWrite();
|
||||
b512=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseNorWrite();
|
||||
SetRompage(0);
|
||||
OpenNorWrite();
|
||||
}
|
||||
if(blockAdd==0)
|
||||
{
|
||||
for(loop=0;loop<0x40000;loop+=0x10000)
|
||||
|
|
@ -397,6 +441,11 @@ void ReadNorFlash(u8* pBuf,u32 address,u16 len)
|
|||
address-=0x2000000;
|
||||
b512=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseNorWrite();
|
||||
SetRompage(0);
|
||||
}
|
||||
Enable_Arm7DS();
|
||||
OpenNorWrite();
|
||||
if(ID==0x89168916)
|
||||
|
|
@ -520,6 +569,9 @@ void WriteNorFlash(u32 address,u8 *buffer,u32 size)
|
|||
WriteNorFlashINTEL(address,buffer,size);
|
||||
return;
|
||||
}
|
||||
CloseNorWrite();
|
||||
SetRompage(0);
|
||||
OpenNorWrite();
|
||||
vu16 v1,v2;
|
||||
register u32 loopwrite ;
|
||||
vu16* buf = (vu16*)buffer ;
|
||||
|
|
|
|||
|
|
@ -23,29 +23,47 @@
|
|||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <nds.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "dsi.h"
|
||||
|
||||
bool isDsi()
|
||||
{
|
||||
#if 0
|
||||
// This code attempts to identify an application running in DSi mode. We
|
||||
// make use of the fact that the DSi has 16 MB of memory, while the DS
|
||||
// only has 4 MB. Since the Chinese iQue DS has 8 MB, we will read above
|
||||
// this boundary.
|
||||
u32 test = *(u32*)0x02800000; // this is 8 MB into the main memory
|
||||
/*
|
||||
u32 test2 = *(u32*)0x02000000; // this is 8 MB into the main memory
|
||||
|
||||
char txt[128];
|
||||
sprintf(txt, "%x %x", test, test2);
|
||||
displayMessage(txt);
|
||||
while(1);
|
||||
|
||||
if (test == 0x00000000)
|
||||
return false;
|
||||
if (test == test2)
|
||||
return false;
|
||||
*/
|
||||
|
||||
// Try writing to this address. If the value is accepted, we are on a DSi in DSi mode.
|
||||
*(u32*)0x02800000 = 0x12345678;
|
||||
if (*(u32*)0x02800000 == 0x12345678)
|
||||
if (*(u32*)0x02800000 == 0x12345678) {
|
||||
*(u32*)0x02800000 == test;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The memory address does not exist, so we are on a DS (or a DSi in DS mode)
|
||||
return false;
|
||||
#endif
|
||||
#define SCFG_MODE (*(vu8*)0x4004000)
|
||||
if(SCFG_MODE)
|
||||
return (REG_DSIMODE != 0) ? true : false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,14 +40,15 @@
|
|||
#include "fileselect.h"
|
||||
|
||||
|
||||
extern u8 data[0x8000];
|
||||
extern u8 *data;
|
||||
extern u32 size_buf;
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
void ftpGetFileList(const char *dir, netbuf *ctrl, uint32 &num)
|
||||
{
|
||||
char *buf = (char*)data;
|
||||
memset(buf, 0, 0x8000);
|
||||
FtpDirBuf((char*)data, 0x8000, "/", ctrl);
|
||||
memset(buf, 0, size_buf);
|
||||
FtpDirBuf((char*)data, size_buf, "/", ctrl);
|
||||
//FtpDir("/dir.txt", "/", ctrl);
|
||||
char *ptr = buf; // scan pointer
|
||||
char *ptr2 = buf; // write pointer
|
||||
|
|
|
|||
35
trunk/arm9/source/globals.h
Normal file
35
trunk/arm9/source/globals.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* savegame_manager: a tool to backup and restore savegames from Nintendo
|
||||
* DS cartridges. Nintendo DS and all derivative names are trademarks
|
||||
* by Nintendo. EZFlash 3-in-1 is a trademark by EZFlash.
|
||||
*
|
||||
* globals.h: global varibles, defines etc.
|
||||
*
|
||||
* Copyright (C) Pokedoc (2011)
|
||||
*/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef GLOBALS_H
|
||||
#define GLOBALS_H
|
||||
|
||||
// TODO
|
||||
//#define NDS_HEADER *(sNDSHeader*) 0x023ffe00
|
||||
|
||||
extern u8 *data;
|
||||
extern u32 size_buf;
|
||||
|
||||
#endif // GLOBALS_H
|
||||
|
|
@ -38,6 +38,7 @@
|
|||
#include "dsCard.h"
|
||||
#include "ftplib.h"
|
||||
#include "gba.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
|
|
@ -49,6 +50,8 @@ using namespace std;
|
|||
|
||||
uint32 boot;
|
||||
|
||||
static u32 pitch = 0x40000;
|
||||
|
||||
bool flash_card = true; // the homebrew will always start with a FC inserted
|
||||
bool with_infrared = false; // ... which does not have an IR device
|
||||
|
||||
|
|
@ -57,7 +60,6 @@ extern char ftp_user[64];
|
|||
extern char ftp_pass[64];
|
||||
extern int ftp_port;
|
||||
|
||||
u8 data[0x8000];
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
bool swap_cart()
|
||||
|
|
@ -114,51 +116,90 @@ bool is_flash_card()
|
|||
return flash_card;
|
||||
}
|
||||
|
||||
bool swap_card_game(uint32 size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
void hwFormatNor(uint32 page, uint32 count)
|
||||
{
|
||||
chip_reset();
|
||||
OpenNorWrite();
|
||||
uint32 ime = hwGrab3in1();
|
||||
SetSerialMode();
|
||||
displayPrintState("Formating NOR memory");
|
||||
displayProgressBar(0, count);
|
||||
for (int i = page; i < page+count; i++) {
|
||||
for (uint32 i = page; i < page+count; i++) {
|
||||
Block_Erase(i << 18);
|
||||
displayProgressBar(i+1, count);
|
||||
displayProgressBar(i+1-page, count);
|
||||
}
|
||||
CloseNorWrite();
|
||||
hwRelease3in1(ime);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
void hwBackupDSi()
|
||||
{
|
||||
hwBackupFTP();
|
||||
}
|
||||
|
||||
void hwRestoreDSi()
|
||||
{
|
||||
// TODO: test!
|
||||
char path[256];
|
||||
char fname[256] = "";
|
||||
fileSelect("sd:/", path, fname, 0, true, false);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
void hwBackup3in1()
|
||||
{
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
|
||||
uint8 size = auxspi_save_size_log_2();
|
||||
int size_blocks = 1 << max(0, (int8(size) - 18)); // ... in units of 0x40000 bytes - that's 256 kB
|
||||
uint8 type = auxspi_save_type();
|
||||
|
||||
// EZFlash Vi needs this line
|
||||
sysSetBusOwners(true, true);
|
||||
displayPrintState("Format NOR");
|
||||
hwFormatNor(0, size_blocks);
|
||||
|
||||
// Dump save and write it to NOR
|
||||
chip_reset();
|
||||
OpenNorWrite();
|
||||
SetSerialMode();
|
||||
displayPrintState("Writing save to NOR");
|
||||
// TODO: test smaller write size!
|
||||
if (size < 15)
|
||||
size_blocks = 1;
|
||||
else
|
||||
size_blocks = 1 << (uint8(size) - 15);
|
||||
u8 *test = (u8*)malloc(0x8000);
|
||||
u32 LEN = min(1 << size, 0x8000);
|
||||
|
||||
for (int i = 0; i < size_blocks; i++) {
|
||||
displayProgressBar(i+1, size_blocks);
|
||||
auxspi_read_data(i << 15, data, 0x8000, type);
|
||||
WriteNorFlash(i << 15, data, 0x8000);
|
||||
auxspi_read_data(i << 15, data, LEN, type);
|
||||
// TODO: pull out "setserialmode"
|
||||
uint32 ime = hwGrab3in1();
|
||||
SetSerialMode();
|
||||
WriteNorFlash((i << 15) + pitch, data, LEN);
|
||||
hwRelease3in1(ime);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
uint32 ime = hwGrab3in1();
|
||||
ReadNorFlash(test, (i << 15) + pitch, LEN);
|
||||
hwRelease3in1(ime);
|
||||
}
|
||||
if (*((vuint16 *)(FlashBase+0x2002)) == 0x227E) {
|
||||
displayMessage("ERROR: ID mode active!");
|
||||
while(1);
|
||||
}
|
||||
if (memcmp(test, data, LEN)) {
|
||||
displayMessage("ERROR: verifying NOR failed");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
CloseNorWrite();
|
||||
free(test);
|
||||
|
||||
// Write a flag to tell the app what happens on restart
|
||||
// Write a flag to tell the app what happens on restart.
|
||||
// This is necessary, since some DLDI drivers cease working after swapping a card.
|
||||
sNDSHeader nds;
|
||||
cardReadHeader((u8*)&nds);
|
||||
cardReadHeader((u8*)&nds); // on a Cyclops Evolution, this call *will* mess up your DLDI driver!
|
||||
dsCardData data2;
|
||||
memset(&data2, 0, sizeof(data2));
|
||||
data2.data[0] = RS_BACKUP;
|
||||
|
|
@ -169,7 +210,7 @@ void hwBackup3in1()
|
|||
WriteSram(0x0a000000, (u8*)&data2, sizeof(data2));
|
||||
char txt[128];
|
||||
sprintf(txt, "%.12s", &nds.gameTitle[0]);
|
||||
|
||||
|
||||
displayMessage("Save has been written to 3in1.\nPlease power off and restart\nthis tool.");
|
||||
|
||||
while(1) {};
|
||||
|
|
@ -177,8 +218,6 @@ void hwBackup3in1()
|
|||
|
||||
void hwDump3in1(uint32 size, const char *gamename)
|
||||
{
|
||||
displayPrintState("Writing file to flash card");
|
||||
|
||||
u32 size_blocks = 1 << max(0, (uint8(size) - 18));
|
||||
|
||||
char path[256];
|
||||
|
|
@ -201,6 +240,7 @@ void hwDump3in1(uint32 size, const char *gamename)
|
|||
sprintf(fullpath, "%s/%s", path, fname);
|
||||
displayMessage(fname);
|
||||
|
||||
displayPrintState("Writing save to flash card");
|
||||
FILE *file = fopen(fullpath, "wb");
|
||||
if (size < 15)
|
||||
size_blocks = 1;
|
||||
|
|
@ -208,10 +248,10 @@ void hwDump3in1(uint32 size, const char *gamename)
|
|||
size_blocks = 1 << (uint8(size) - 15);
|
||||
for (u32 i = 0; i < size_blocks; i++) {
|
||||
displayProgressBar(i+1, size_blocks);
|
||||
u32 LEN = 0x8000;
|
||||
// EZFlash Vi needs this line
|
||||
sysSetBusOwners(true, true);
|
||||
ReadNorFlash(data, i << 15, LEN);
|
||||
u32 LEN = min((u32)0x8000, (u32)1 << size);
|
||||
uint32 ime = hwGrab3in1();
|
||||
ReadNorFlash(data, (i << 15) + pitch, LEN);
|
||||
hwRelease3in1(ime);
|
||||
fwrite(data, 1, LEN, file);
|
||||
}
|
||||
fclose(file);
|
||||
|
|
@ -239,47 +279,40 @@ void hwRestore3in1()
|
|||
}
|
||||
int size_blocks = 1 << max(0, int8(size) - 18); // ... in units of 0x40000 bytes - that's 256 kB
|
||||
|
||||
// EZFlash Vi needs this line
|
||||
sysSetBusOwners(true, true);
|
||||
hwFormatNor(0, size_blocks);
|
||||
hwFormatNor(1, size_blocks);
|
||||
displayPrintState("Writing save to NOR");
|
||||
|
||||
// Read save and write it to NOR
|
||||
chip_reset();
|
||||
OpenNorWrite();
|
||||
SetSerialMode();
|
||||
displayPrintState("Writing save to NOR");
|
||||
if (size < 15)
|
||||
size_blocks = 1;
|
||||
else
|
||||
size_blocks = 1 << (uint8(size) - 15);
|
||||
u8 *test = (u8*)malloc(0x8000);
|
||||
uint32 LEN = min(1 << size, 0x8000);
|
||||
|
||||
for (int i = 0; i < size_blocks; i++) {
|
||||
displayProgressBar(i+1, size_blocks);
|
||||
fread(data, 1, 0x8000, file);
|
||||
// EZFlash Vi needs this line
|
||||
sysSetBusOwners(true, true);
|
||||
WriteNorFlash(i << 15, data, 0x8000);
|
||||
displayProgressBar(i, size_blocks);
|
||||
fread(data, 1, LEN, file);
|
||||
uint32 ime = hwGrab3in1();
|
||||
SetSerialMode();
|
||||
WriteNorFlash((i << 15) + pitch, data, LEN);
|
||||
ReadNorFlash(test, (i << 15) + pitch, LEN);
|
||||
hwRelease3in1(ime);
|
||||
if (*((vuint16 *)(FlashBase+0x2002)) == 0x227E) {
|
||||
displayMessage("ERROR: ID mode active!");
|
||||
while(1);
|
||||
}
|
||||
if (int err = memcmp(test, data, LEN)) {
|
||||
char txt[128];
|
||||
sprintf(txt, "ERROR: NOR %x/%x: %x -> %x", abs(err), LEN, data[err], test[err]);
|
||||
displayMessage(txt);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
CloseNorWrite();
|
||||
fclose(file);
|
||||
free(test);
|
||||
|
||||
// FIXME: for some weird reason, reading the save written to NOR right now managed to mangle
|
||||
// precisely 2 bytes in my HG save, but not in my Platinum one. Therefore, we need to
|
||||
// make this a two-stage process as well, to prevent this weitd glitch.
|
||||
// (It appears in two different hardware revisions of the 3in1!)
|
||||
|
||||
// Write a flag to tell the app what happens on restart
|
||||
sNDSHeader nds;
|
||||
cardReadHeader((u8*)&nds);
|
||||
dsCardData data2;
|
||||
memset(&data2, 0, sizeof(data2));
|
||||
data2.data[0] = RS_BACKUP;
|
||||
data2.data[1] = 0;
|
||||
data2.data[2] = size;
|
||||
data2.data[3] = 0xbad00bad;
|
||||
WriteSram(0x0a000000, (u8*)&data2, sizeof(data2));
|
||||
|
||||
displayMessage("Thanks to some crazy bug,\nyou will need to restart your\nDS and this app. Sorry.");
|
||||
while(0);
|
||||
hwRestore3in1_b(size);
|
||||
}
|
||||
|
||||
void hwRestore3in1_b(uint32 size_file)
|
||||
|
|
@ -287,9 +320,6 @@ void hwRestore3in1_b(uint32 size_file)
|
|||
// Third, swap in a new game
|
||||
uint32 size = auxspi_save_size_log_2();
|
||||
while ((size_file < size) || flash_card) {
|
||||
//char txt[33];
|
||||
//sprintf(txt, "%i, %i (%i)", size_file, size, flash_card);
|
||||
//displayPrintState(txt);
|
||||
displayPrintState("File too small or no save chip!");
|
||||
swap_cart();
|
||||
size = auxspi_save_size_log_2();
|
||||
|
|
@ -321,17 +351,14 @@ void hwRestore3in1_b(uint32 size_file)
|
|||
LEN = 1 << shift;
|
||||
num_blocks = 1 << (size - shift);
|
||||
|
||||
chip_reset();
|
||||
OpenNorWrite();
|
||||
for (unsigned int i = 0; i < num_blocks; i++) {
|
||||
if (i % (num_blocks >> 6) == 0)
|
||||
displayProgressBar(i+1, num_blocks);
|
||||
// EZFlash Vi needs this line
|
||||
//sysSetBusOwners(true, true);
|
||||
ReadNorFlash(data, i << shift, LEN);
|
||||
uint32 ime = hwGrab3in1();
|
||||
ReadNorFlash(data, (i << shift) + pitch, LEN);
|
||||
hwRelease3in1(ime);
|
||||
auxspi_write_data(i << shift, data, LEN, type);
|
||||
}
|
||||
CloseNorWrite();
|
||||
displayProgressBar(1, 1);
|
||||
|
||||
|
||||
|
|
@ -502,9 +529,6 @@ void hwRestoreFTP()
|
|||
displayMessage("Please select a file name to\nrestore.");
|
||||
displayPrintState("FTP: dir");
|
||||
fileSelect("/", fdir, fname, buf, true, false);
|
||||
/*char fn[512];
|
||||
displayMessage(fname);
|
||||
while(1);*/
|
||||
|
||||
// Third: swap card
|
||||
swap_cart();
|
||||
|
|
@ -512,16 +536,12 @@ void hwRestoreFTP()
|
|||
uint8 size = auxspi_save_size_log_2();
|
||||
int size_blocks = 1 << (size - 9); // ... in units of 512 bytes
|
||||
uint8 type = auxspi_save_type();
|
||||
if (type == 3) {
|
||||
displayPrintState("Formating Flash chip");
|
||||
auxspi_erase();
|
||||
}
|
||||
|
||||
// Fourth: read file
|
||||
displayPrintState("");
|
||||
FtpChdir(fdir, buf);
|
||||
sprintf(fullname, "Reading file:\n%s%s", fdir, fname);
|
||||
displayMessage(fullname);
|
||||
FtpAccess(fname, FTPLIB_FILE_READ, FTPLIB_IMAGE, buf, &ndata);
|
||||
u32 LEN = 0, num_blocks = 0, shift = 0;
|
||||
switch (type) {
|
||||
case 1:
|
||||
|
|
@ -539,16 +559,55 @@ void hwRestoreFTP()
|
|||
LEN = 1 << shift;
|
||||
int num_blocks_ftp = 1 << (size - 9);
|
||||
num_blocks = 1 << (size - shift);
|
||||
|
||||
// if our save is small enough to fit in memory, use secure mode (i.e. read full file before erasing anything
|
||||
bool insecure = ((1 << size) > size_buf);
|
||||
if (insecure) {
|
||||
#if 0
|
||||
displayMessage("Save larger than available RAM.\nRestoring will be dangerous!\n\nPress Start + Select to proceed");
|
||||
while (!(keysCurrent() & (KEY_START | KEY_SELECT)));
|
||||
#else
|
||||
displayMessage("Save larger than available RAM.\nRestoring is buggy, so\nI will stop here.\n(Try Rudolphs tools.)");
|
||||
while (1);
|
||||
#endif
|
||||
}
|
||||
if ((type == 3) && (insecure)) {
|
||||
displayPrintState("Formating Flash chip");
|
||||
auxspi_erase();
|
||||
}
|
||||
FtpAccess(fname, FTPLIB_FILE_READ, FTPLIB_IMAGE, buf, &ndata);
|
||||
u8 *pdata = data;
|
||||
for (int i = 0; i < num_blocks_ftp; i++) {
|
||||
displayProgressBar(i+1, num_blocks_ftp);
|
||||
int out;
|
||||
if ((out = FtpRead((u8*)data, 512, ndata)) < 512) {
|
||||
if ((out = FtpRead((u8*)pdata, 512, ndata)) < 512) {
|
||||
char dings[512];
|
||||
sprintf(dings, "Error: requested 512, got %i", out);
|
||||
displayPrintState(dings);
|
||||
while(1);
|
||||
}
|
||||
for (int j = 0; j < 1 << (9-shift); j++) {
|
||||
auxspi_write_data((i << 9)+(j << shift), ((u8*)data)+(j<<shift), LEN, type);
|
||||
// does not fit into memory: insecure mode
|
||||
if (insecure) {
|
||||
//char bums[512];
|
||||
//sprintf(bums, "addr = %x", (i << 9)+(j << shift));
|
||||
displayPrintState("Writing save (insecure!)");
|
||||
//displayPrintState(bums);
|
||||
for (int j = 0; j < 1 << (9-shift); j++) {
|
||||
auxspi_write_data((i << 9)+(j << shift), ((u8*)pdata)+(j<<shift), LEN, type);
|
||||
}
|
||||
}
|
||||
pdata += 512;
|
||||
}
|
||||
if (!insecure) {
|
||||
displayMessage("Got file, now writing to game");
|
||||
if (type == 3) {
|
||||
displayPrintState("Formating Flash chip");
|
||||
auxspi_erase();
|
||||
}
|
||||
for (int i = 0; i < (1 << (size - shift)); i++) {
|
||||
displayPrintState("Writing save");
|
||||
displayProgressBar(i+1, 1 << (size - shift));
|
||||
auxspi_write_data(i << shift, ((u8*)data)+(i<<shift), LEN, type);
|
||||
}
|
||||
}
|
||||
FtpClose(ndata);
|
||||
|
|
@ -664,3 +723,19 @@ void hwEraseGBA()
|
|||
{
|
||||
// TODO: implement chip erase!
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
uint32 hwGrab3in1()
|
||||
{
|
||||
uint32 ime = enterCriticalSection();
|
||||
sysSetBusOwners(true, true);
|
||||
chip_reset();
|
||||
OpenNorWrite();
|
||||
return ime;
|
||||
}
|
||||
|
||||
void hwRelease3in1(uint32 ime)
|
||||
{
|
||||
CloseNorWrite();
|
||||
leaveCriticalSection(ime);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ void hwRestore3in1();
|
|||
void hwRestore3in1_b(uint32 size_file);
|
||||
void hwErase();
|
||||
|
||||
void hwBackupDSi();
|
||||
void hwRestoreDSi();
|
||||
|
||||
void hwBackupFTP();
|
||||
void hwRestoreFTP();
|
||||
|
||||
|
|
@ -63,4 +66,7 @@ void hwEraseGBA();
|
|||
|
||||
void hwFormatNor(uint32 page, uint32 count);
|
||||
|
||||
uint32 hwGrab3in1();
|
||||
void hwRelease3in1(uint32 ime);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#include <dirent.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "gba.h"
|
||||
#include "dsi.h"
|
||||
#include "display.h"
|
||||
|
|
@ -45,6 +47,10 @@
|
|||
|
||||
#include "libini.h"
|
||||
|
||||
u8 *data;
|
||||
u32 size_buf;
|
||||
|
||||
using std::max;
|
||||
|
||||
|
||||
uint32 ezflash = 0;
|
||||
|
|
@ -57,6 +63,7 @@ char ftp_ip[16] = "ftp_ip";
|
|||
char ftp_user[64] = "ftp_user";
|
||||
char ftp_pass[64] = "ftp_pass";
|
||||
int ftp_port = 0;
|
||||
int ir_delay = 1000;
|
||||
|
||||
char bootdir[256] = "/";
|
||||
|
||||
|
|
@ -64,6 +71,36 @@ char bootdir[256] = "/";
|
|||
// ============================================================================
|
||||
void mode_dsi()
|
||||
{
|
||||
// TODO: test is SD card is present!
|
||||
|
||||
// use 3in1 to buffer data
|
||||
displayPrintState("");
|
||||
displayPrintUpper();
|
||||
displayPrintLower();
|
||||
|
||||
touchPosition touchXY;
|
||||
while(1) {
|
||||
swiWaitForVBlank();
|
||||
touchRead(&touchXY);
|
||||
|
||||
// backup
|
||||
if ((touchXY.py > 8*0) && (touchXY.py < 8*8)) {
|
||||
hwBackupDSi();
|
||||
}
|
||||
|
||||
// restore
|
||||
if ((touchXY.py > 8*8) && (touchXY.py < 8*16)) {
|
||||
hwRestoreDSi();
|
||||
}
|
||||
|
||||
// erase
|
||||
if ((touchXY.py > 8*16) && (touchXY.py < 8*24)) {
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
hwErase();
|
||||
}
|
||||
}
|
||||
|
||||
// DSi mode, does nothing at the moment
|
||||
displayPrintState("DSi mode - still unsupported!");
|
||||
while (1);
|
||||
|
|
@ -136,8 +173,6 @@ void mode_3in1()
|
|||
|
||||
// backup
|
||||
if ((touchXY.py > 8*0) && (touchXY.py < 8*8)) {
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
hwBackup3in1();
|
||||
}
|
||||
|
||||
|
|
@ -192,8 +227,6 @@ void mode_gba()
|
|||
|
||||
void mode_wifi()
|
||||
{
|
||||
displayPrintUpper();
|
||||
|
||||
// use 3in1 to buffer data
|
||||
displayPrintState("");
|
||||
displayPrintUpper();
|
||||
|
|
@ -268,39 +301,44 @@ int main(int argc, char* argv[])
|
|||
ini_readString(ini, ftp_pass, 64);
|
||||
ini_locateKey(ini, "ftp_port");
|
||||
ini_readInt(ini, &ftp_port);
|
||||
ini_locateKey(ini, "ir_delay");
|
||||
ini_readInt(ini, &ir_delay);
|
||||
ir_delay = max(ir_delay, 1000);
|
||||
ini_close(ini);
|
||||
//displayPrintState(ftp_user);
|
||||
//while (1);
|
||||
|
||||
// Identify hardware and branch to corresponding mode
|
||||
displayPrintState("Identifying hardware...");
|
||||
// EZFlash Vi needs this line
|
||||
sysSetBusOwners(true, true);
|
||||
OpenNorWrite();
|
||||
ezflash = ReadNorFlashID();
|
||||
CloseNorWrite();
|
||||
// First attempt to identify the DSi. Read address > 8 MB
|
||||
dstype = isDsi() ? 1 : 0; // DS/DSL, no idea how to identify DSi etc.
|
||||
gba = gbaIsGame();
|
||||
|
||||
// Identify DSi (i.e. memory capacity)
|
||||
if (isDsi()) {
|
||||
dstype = 1;
|
||||
size_buf = 1 << 23; // 8 MB
|
||||
} else {
|
||||
dstype = 0;
|
||||
size_buf = 1 << 21; // 2 MB
|
||||
//size_buf = 1 << 14; // 32 kB - TESTING ONLY!
|
||||
}
|
||||
data = (u8*)malloc(size_buf);
|
||||
|
||||
// don't try to identify Slot-2 in DSi mode.
|
||||
if (dstype == 0) {
|
||||
uint32 ime = enterCriticalSection();
|
||||
sysSetBusOwners(true, true);
|
||||
OpenNorWrite();
|
||||
ezflash = ReadNorFlashID();
|
||||
CloseNorWrite();
|
||||
leaveCriticalSection(ime);
|
||||
chip_reset();
|
||||
|
||||
gba = gbaIsGame();
|
||||
}
|
||||
|
||||
// Try to identify slot-2 device. Try opening slot-2 root directory
|
||||
// Nope, does not work: CyclopsDS mounts itself on fat1, fat2, fat3,... (didn't test more)
|
||||
/*
|
||||
DIR* pdir = opendir("fat2:/");
|
||||
struct dirent *pent;
|
||||
if (pdir) {
|
||||
pent=readdir(pdir);
|
||||
if (pent)
|
||||
//char fullname[256];
|
||||
displayMessage(pent->d_name);
|
||||
//slot2=true;
|
||||
}
|
||||
*/
|
||||
if (argv[0][3] == '2')
|
||||
slot2 = true;
|
||||
|
||||
if (dstype == 1) {
|
||||
// DSi/DSiXL, will branch to SD-card mode when cracked.
|
||||
// DSi/DSiXL, branch to SD-card mode when cracked.
|
||||
mode = 3;
|
||||
mode_dsi();
|
||||
} else if (slot2) {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<Project name="Savegame Manager"><MagicFolder excludeFolders="CVS;.svn" filter="*" name="arm9" path="arm9\"><MagicFolder excludeFolders="CVS;.svn" filter="*" name="build" path="build\"><File path=".map"></File><File path="auxspi.d"></File><File path="auxspi.o"></File><File path="auxspi_core.d"></File><File path="auxspi_core.o"></File><File path="display.d"></File><File path="display.o"></File><File path="dsCard.d"></File><File path="dsCard.o"></File><File path="dsi.d"></File><File path="dsi.o"></File><File path="fileselect.d"></File><File path="fileselect.o"></File><File path="ftplib.d"></File><File path="ftplib.o"></File><File path="gba.d"></File><File path="gba.o"></File><File path="hardware.d"></File><File path="hardware.o"></File><File path="ini.d"></File><File path="ini.o"></File><File path="main.d"></File><File path="main.o"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn" filter="*" name="source" path="source\"><File path="auxspi.cpp"></File><File path="auxspi.h"></File><File path="auxspi_core.cpp"></File><File path="display.cpp"></File><File path="display.h"></File><File path="dsCard.cpp"></File><File path="dsCard.h"></File><File path="dsi.cpp"></File><File path="dsi.h"></File><File path="fileselect.cpp"></File><File path="fileselect.h"></File><File path="ftplib.c"></File><File path="ftplib.h"></File><File path="gba.cpp"></File><File path="gba.h"></File><File path="hardware.cpp"></File><File path="hardware.h"></File><File path="headings.i"></File><File path="ini.cpp"></File><File path="ini.h"></File><File path="iniconfig.h"></File><File path="iniheadings.h"></File><File path="inikeys.h"></File><File path="inilist.h"></File><File path="keys.i"></File><File path="libini.h"></File><File path="list.i"></File><File path="main.cpp"></File><File path="types.i"></File></MagicFolder><File path="Makefile"></File><File path="savegame_manager.arm9.elf"></File></MagicFolder><File path="Makefile"></File></Project>
|
||||
<Project name="Savegame Manager"><MagicFolder excludeFolders="CVS;.svn" filter="*" name="arm9" path="arm9\"><MagicFolder excludeFolders="CVS;.svn" filter="*" name="build" path="build\"><File path=".map"></File><File path="auxspi.d"></File><File path="auxspi.o"></File><File path="auxspi_core.d"></File><File path="auxspi_core.o"></File><File path="display.d"></File><File path="display.o"></File><File path="dsCard.d"></File><File path="dsCard.o"></File><File path="dsi.d"></File><File path="dsi.o"></File><File path="fileselect.d"></File><File path="fileselect.o"></File><File path="ftplib.d"></File><File path="ftplib.o"></File><File path="gba.d"></File><File path="gba.o"></File><File path="hardware.d"></File><File path="hardware.o"></File><File path="ini.d"></File><File path="ini.o"></File><File path="main.d"></File><File path="main.o"></File></MagicFolder><MagicFolder excludeFolders="CVS;.svn" filter="*" name="source" path="source\"><File path="auxspi.cpp"></File><File path="auxspi.h"></File><File path="auxspi_core.cpp"></File><File path="display.cpp"></File><File path="display.h"></File><File path="dsCard.cpp"></File><File path="dsCard.h"></File><File path="dsi.cpp"></File><File path="dsi.h"></File><File path="fileselect.cpp"></File><File path="fileselect.h"></File><File path="ftplib.c"></File><File path="ftplib.h"></File><File path="gba.cpp"></File><File path="gba.h"></File><File path="globals.h"></File><File path="hardware.cpp"></File><File path="hardware.h"></File><File path="headings.i"></File><File path="ini.cpp"></File><File path="ini.h"></File><File path="iniconfig.h"></File><File path="iniheadings.h"></File><File path="inikeys.h"></File><File path="inilist.h"></File><File path="keys.i"></File><File path="libini.h"></File><File path="list.i"></File><File path="main.cpp"></File><File path="types.i"></File></MagicFolder><File path="Makefile"></File><File path="savegame_manager.arm9.elf"></File></MagicFolder><File path="Makefile"></File></Project>
|
||||
Loading…
Reference in New Issue
Block a user