mirror of
https://github.com/suloku/savegame-manager.git
synced 2026-04-24 23:16:54 -05:00
- split slot 1 detection from swap_cart (current version is slightly buggy)
- introduce a new hardware detection routine - introduce a new "argv" test, hoping to weed out more bad implementations - convert more strings to upcoming translation interface - some bugfixes
This commit is contained in:
parent
19ccec7d3f
commit
9002997030
|
|
@ -248,10 +248,10 @@ bool auxspi_has_infrared()
|
|||
|
||||
void auxspi_erase(bool ir)
|
||||
{
|
||||
uint8 type = auxspi_save_type();
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
if (type == 3) {
|
||||
uint8 size;
|
||||
size = 1 << (auxspi_save_size_log_2() - 16);
|
||||
size = 1 << (auxspi_save_size_log_2(ir) - 16);
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (ir)
|
||||
auxspi_disable_infrared();
|
||||
|
|
@ -280,10 +280,10 @@ void auxspi_erase(bool ir)
|
|||
auxspi_close();
|
||||
}
|
||||
} else {
|
||||
int8 size = 1 << max(0, (auxspi_save_size_log_2() - 15));
|
||||
int8 size = 1 << max(0, (auxspi_save_size_log_2(ir) - 15));
|
||||
memset(data, 0, 0x8000);
|
||||
for (int i = 0; i < size; i++) {
|
||||
auxspi_write_data(i << 15, data, 0x8000, type);
|
||||
auxspi_write_data(i << 15, data, 0x8000, type, ir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,16 +37,11 @@
|
|||
#include "globals.h"
|
||||
#include "strings.h"
|
||||
|
||||
#include "auxspi_core.inc"
|
||||
|
||||
|
||||
PrintConsole upperScreen;
|
||||
PrintConsole lowerScreen;
|
||||
|
||||
|
||||
extern uint32 mode;
|
||||
extern u8 gbatype;
|
||||
|
||||
|
||||
//===========================================================
|
||||
void displayInit()
|
||||
|
|
@ -68,10 +63,15 @@ void displayInit()
|
|||
|
||||
void displayPrintUpper()
|
||||
{
|
||||
extern uint32 ezflash;
|
||||
/*
|
||||
//extern uint32 ezflash;
|
||||
extern bool gba;
|
||||
extern uint32 dstype;
|
||||
extern bool slot2;
|
||||
*/
|
||||
bool gba = (mode == 1);
|
||||
u32 dstype = (mode == 3) ? 1 : 0;
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
|
||||
// print upper screen (background)
|
||||
consoleSelect(&upperScreen);
|
||||
|
|
@ -100,29 +100,9 @@ void displayPrintUpper()
|
|||
consoleClear();
|
||||
|
||||
// fetch cartridge header (maybe, calling "cardReadHeader" on a FC messes with libfat!)
|
||||
//bool flash_card = is_flash_card();
|
||||
//bool ir = auxspi_has_infrared();
|
||||
sNDSHeader nds;
|
||||
if (slot_1_type != 2)
|
||||
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
|
||||
|
|
@ -158,7 +138,7 @@ void displayPrintUpper()
|
|||
sprintf(&name[0], "----");
|
||||
if (slot_1_type == 2) {
|
||||
sprintf(&name[0], "Flash Card");
|
||||
} else /*if (nds.gameCode[0])*/ {
|
||||
} else {
|
||||
memcpy(&name[0], &nds.gameCode[0], 4);
|
||||
name[4] = 0x00;
|
||||
}
|
||||
|
|
@ -170,7 +150,7 @@ void displayPrintUpper()
|
|||
sprintf(&name[0], "----");
|
||||
if (slot_1_type == 2) {
|
||||
sprintf(&name[0], "Flash Card");
|
||||
} else /*if (nds.gameTitle[0])*/ {
|
||||
} else {
|
||||
memcpy(&name[0], &nds.gameTitle[0], 12);
|
||||
name[12] = 0x00;
|
||||
}
|
||||
|
|
@ -183,17 +163,17 @@ void displayPrintUpper()
|
|||
if (slot_1_type == 2) {
|
||||
sprintf(&name[0], "Flash Card");
|
||||
} else {
|
||||
uint8 type = auxspi_save_type();
|
||||
uint32 size = auxspi_save_size();
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
switch (type) {
|
||||
case 1:
|
||||
sprintf(&name[0], "Eeprom (%i Bytes)", size);
|
||||
break;
|
||||
case 2:
|
||||
sprintf(&name[0], "FRAM (%i kB)", size >> 10);
|
||||
sprintf(&name[0], "FRAM (%i kB)", 1 << (size - 10));
|
||||
break;
|
||||
case 3:
|
||||
sprintf(&name[0], "Flash (%i kB)", size >> 10);
|
||||
sprintf(&name[0], "Flash (%i kB)", 1 << (size - 10));
|
||||
break;
|
||||
default:
|
||||
sprintf(&name[0], "unknown");
|
||||
|
|
@ -207,7 +187,6 @@ void displayPrintUpper()
|
|||
consoleSetWindow(&upperScreen, 10, 5, 22, 1);
|
||||
consoleClear();
|
||||
memset(&name[0], 0, MAXPATHLEN);
|
||||
//if (auxspi_has_infrared()) {
|
||||
if (slot_1_type == 1) {
|
||||
sprintf(&name[0], "Infrared");
|
||||
} else {
|
||||
|
|
@ -260,18 +239,18 @@ void displayPrintUpper()
|
|||
if (ezflash)
|
||||
sprintf(name, "SRAM");
|
||||
else if (gba) {
|
||||
u8 type = gbatype;
|
||||
saveTypeGBA type = GetSlot2SaveType(CART_GBA_GAME);
|
||||
u8 size = gbaGetSaveSizeLog2(type);
|
||||
switch (type) {
|
||||
case 1:
|
||||
case 2:
|
||||
case SAVE_GBA_EEPROM_05:
|
||||
case SAVE_GBA_EEPROM_8:
|
||||
sprintf(name, "EEPROM (%i bytes)", 1 << size);
|
||||
break;
|
||||
case 3:
|
||||
case SAVE_GBA_SRAM_32:
|
||||
sprintf(name, "SRAM (%i kB)", 1 << (size - 10));
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case SAVE_GBA_FLASH_64:
|
||||
case SAVE_GBA_FLASH_128:
|
||||
sprintf(name, "Flash (%i kB)", 1 << (size - 10));
|
||||
break;
|
||||
default:
|
||||
|
|
@ -292,7 +271,8 @@ void displayPrintUpper()
|
|||
if (ezflash)
|
||||
sprintf(name, "NOR + PSRAM");
|
||||
else if (gba)
|
||||
sprintf(name, "(unsupported)");
|
||||
// TODO: test for RTC, add function for syncing RTC?
|
||||
sprintf(name, "???");
|
||||
else if (slot2)
|
||||
sprintf(name, "----");
|
||||
else if (dstype == 0)
|
||||
|
|
@ -416,6 +396,9 @@ void displayProgressBar(int cur, int max0)
|
|||
}
|
||||
buffer[31] = ']';
|
||||
buffer[32] = 0;
|
||||
|
||||
if (max0 == 0)
|
||||
buffer[0] = 0;
|
||||
|
||||
iprintf("%s", buffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,7 @@
|
|||
|
||||
bool isDsi()
|
||||
{
|
||||
#define SCFG_MODE (*(vu8*)0x4004000)
|
||||
if(SCFG_MODE)
|
||||
return (REG_DSIMODE != 0) ? true : false;
|
||||
|
||||
return false;
|
||||
return (REG_DSIMODE != 0) ? true : false;
|
||||
}
|
||||
|
||||
bool dsiUnlockSlot1()
|
||||
|
|
|
|||
|
|
@ -78,11 +78,11 @@ void ftpGetFileList(const char *dir, netbuf *ctrl, int &num)
|
|||
}
|
||||
}
|
||||
|
||||
void fileGetFileList(const char *dir, int num)
|
||||
void fileGetFileList(const char *dir, int &num)
|
||||
{
|
||||
char *buf = (char*)data;
|
||||
int idx = 0;
|
||||
memset(buf, 0, 0x8000);
|
||||
memset(buf, 0, size_buf);
|
||||
|
||||
DIR *pdir;
|
||||
struct dirent *pent;
|
||||
|
|
@ -96,7 +96,7 @@ void fileGetFileList(const char *dir, int num)
|
|||
stat(fullname, &statbuf);
|
||||
|
||||
// TODO: check for buffer overflow!
|
||||
if (idx + strlen(pent->d_name) < 0x8000-2) {
|
||||
if (idx + strlen(pent->d_name) < size_buf-2) {
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
int len = sprintf(buf, "d%s\n", pent->d_name);
|
||||
buf += len;
|
||||
|
|
@ -178,6 +178,10 @@ void fileSelect(const char *startdir, char *out_dir, char *out_fname, netbuf *bu
|
|||
ftpGetFileList("/", buf, num_files);
|
||||
else
|
||||
fileGetFileList(startdir, num_files);
|
||||
if (num_files == 0) {
|
||||
displayMessage("ERROR");
|
||||
while(1);
|
||||
}
|
||||
filePrintFileList(startdir, first_file, sel_file, num_files, allow_cancel);
|
||||
|
||||
while (!select) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "dsCard.h"
|
||||
|
||||
#include "display.h"
|
||||
#include "globals.h"
|
||||
|
||||
inline u32 min(u32 i, u32 j) { return (i < j) ? i : j;}
|
||||
inline u32 max(u32 i, u32 j) { return (i > j) ? i : j;}
|
||||
|
|
@ -158,7 +159,7 @@ uint8 gbaGetSaveType()
|
|||
for (int i = 0; i < (0x02000000 >> 2); i++, data++) {
|
||||
if (*data == MAGIC_EEPR) {
|
||||
// 2 versions: 512 bytes / 8 kB
|
||||
return 1; // TODO: Try to figure out how to ID the 512 bytes version... hard way? write/restore!
|
||||
return 2; // TODO: Try to figure out how to ID the 512 bytes version... hard way? write/restore!
|
||||
}
|
||||
if (*data == MAGIC_SRAM) {
|
||||
// *always* 32 kB
|
||||
|
|
@ -205,21 +206,24 @@ uint32 gbaGetSaveSize(uint8 type)
|
|||
}
|
||||
|
||||
// local function
|
||||
//#define E_DEBUG
|
||||
void gbaEepromRead8Bytes(u8 *out, u32 addr, bool short_addr = false)
|
||||
{
|
||||
// waitstates
|
||||
//*(volatile unsigned short *)0x04000204 = 0x4317;
|
||||
#ifdef E_DEBUG
|
||||
char txt[64];
|
||||
#endif
|
||||
// TODO: this still does not work... figure out somehow how to do it right!
|
||||
|
||||
// waitstates - this is what Rudolph uses...
|
||||
*(volatile unsigned short *)0x04000204 = 0x4317;
|
||||
|
||||
// maximal length of the buffer
|
||||
u16 buf[68];
|
||||
// "read" command
|
||||
|
||||
// Prepare a "read" command.
|
||||
u16 length;
|
||||
// raw command
|
||||
buf[0] = 1;
|
||||
buf[1] = 1;
|
||||
// write address
|
||||
// address
|
||||
if (short_addr) {
|
||||
length = 9;
|
||||
buf[2] = addr >> 5;
|
||||
buf[3] = addr >> 4;
|
||||
buf[4] = addr >> 3;
|
||||
|
|
@ -227,49 +231,8 @@ void gbaEepromRead8Bytes(u8 *out, u32 addr, bool short_addr = false)
|
|||
buf[6] = addr >> 1;
|
||||
buf[7] = addr;
|
||||
buf[8] = 0;
|
||||
#if 1
|
||||
// does not work
|
||||
char txt[512];
|
||||
sprintf(txt, "EXMEMCNT = %x", REG_EXMEMCNT);
|
||||
sysSetBusOwners(true, true);
|
||||
displayMessage(txt);
|
||||
//u32 ime = enterCriticalSection();
|
||||
// EXMEMCNT: 0..1: long sram wait state (18/8) - set to "2", i.e. not the slowest
|
||||
// EXMEMCNT: 2..3: long ROM wait state (18/8)
|
||||
REG_EXMEMCNT |= 15;
|
||||
REG_EXMEMCNT &= ~(1 << 4);
|
||||
// EXMEMCNT: ~4: 6 waitstates on 2nd access (should be 18 as well, but that's no option!)
|
||||
dmaCopy((u16*)&buf[0], (u32*)0x09ffff00, 9<<1);
|
||||
while (*(u16*)0x040000dc != 0);
|
||||
dmaCopy((u32*)0x09ffff00, (u16*)&buf[0], 68<<1);
|
||||
while (*(u16*)0x040000dc != 0);
|
||||
//leaveCriticalSection(ime);
|
||||
#endif
|
||||
#if 0
|
||||
// TEST
|
||||
//u32 ime = enterCriticalSection();
|
||||
REG_EXMEMCNT |= 3;
|
||||
u32 ie = REG_IE;
|
||||
REG_IE = 1 << 11; // DMA3 only
|
||||
dmaCopy((u16*)&buf[0], (u32*)0x09ffff00, 9 << 1);
|
||||
REG_EXMEMCNT |= 3;
|
||||
dmaCopy((u32*)0x09ffff00, (u16*)&buf[0], 68 << 1);
|
||||
REG_IE = ie;
|
||||
//leaveCriticalSection(ime);
|
||||
#endif
|
||||
#if 0
|
||||
#define EEPROM *(u16*)0x0dffff00
|
||||
for (int i = 0; i < 9; i++) {
|
||||
EEPROM = buf[i];
|
||||
swiDelay(10);
|
||||
}
|
||||
swiDelay(100);
|
||||
for (int i = 0; i < 68; i++) {
|
||||
buf[i] = EEPROM;
|
||||
swiDelay(10);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
length = 17;
|
||||
buf[2] = addr >> 13;
|
||||
buf[3] = addr >> 12;
|
||||
buf[4] = addr >> 11;
|
||||
|
|
@ -285,54 +248,159 @@ void gbaEepromRead8Bytes(u8 *out, u32 addr, bool short_addr = false)
|
|||
buf[14] = addr >> 1;
|
||||
buf[15] = addr;
|
||||
buf[16] = 0;
|
||||
dmaCopy((u16*)&buf[0], (u32*)0x09000000, 17);
|
||||
dmaCopy((u32*)0x09000000, (u16*)&buf[0], 68);
|
||||
}
|
||||
|
||||
// Extract data (there is only one *bit* per halfword!)
|
||||
u16 *in_pos = &buf[4];
|
||||
u8 *out_pos = out;
|
||||
u8 out_byte;
|
||||
for(s8 byte = 7; byte >= 0; --byte )
|
||||
{
|
||||
out_byte = 0;
|
||||
for(s8 bit = 7; bit >= 0; --bit )
|
||||
{
|
||||
#ifdef E_DEBUG
|
||||
static u32 eeprom = 0x09ffff00;
|
||||
|
||||
// send command to eeprom
|
||||
displayPrintState("Sending command");
|
||||
// commenting this out or not does not have any impact on the EEPROM device. Therefore,
|
||||
// the following command does not "make" it to the hardware!
|
||||
DC_FlushRange(&buf[0], sizeof(buf));
|
||||
DMA_SRC(3) = (uint32)&buf[0];
|
||||
DMA_DEST(3) = (uint32)eeprom;
|
||||
// there is a bit for eeprom access, but it only seems to freeze the transfer!?
|
||||
//DMA_CR(3) = DMA_COPY_HALFWORDS | DMA_START_CARD | length; // this bit is expanding to "3 bits"
|
||||
//DMA_CR(3) = DMA_COPY_HALFWORDS | length;
|
||||
DMA_CR(3) = DMA_COPY_HALFWORDS | (6 << 27) | length;
|
||||
while(DMA_CR(3) & DMA_BUSY);
|
||||
//while ((*(u16*)0x09ffff00 & 1) == 0);
|
||||
|
||||
// get answer from eeprom
|
||||
displayPrintState("listening");
|
||||
DC_FlushRange(&buf[0], sizeof(buf));
|
||||
DMA_SRC(3) = (uint32)eeprom;
|
||||
DMA_DEST(3) = (uint32)&buf[0];
|
||||
// there is a bit for eeprom access, but it only seems to freeze the transfer!?
|
||||
//DMA_CR(3) = DMA_COPY_HALFWORDS | DMA_START_CARD | 68; // this bit is expanding to "3 bits"
|
||||
//DMA_CR(3) = DMA_COPY_HALFWORDS | 68;
|
||||
DMA_CR(3) = DMA_COPY_HALFWORDS | (6 << 27) | 68;
|
||||
while(DMA_CR(3) & DMA_BUSY);
|
||||
//while ((*(u16*)0x09ffff00 & 1) == 0);
|
||||
|
||||
/*
|
||||
sprintf(txt, "byte: %i, Bit: %i, Val: %x", byte, bit, *in_pos);
|
||||
displayPrintState(txt);
|
||||
*/
|
||||
// Extract data (there is only one *bit* per halfword!)
|
||||
u16 *in_pos = &buf[4];
|
||||
u8 *out_pos = out;
|
||||
u8 out_byte;
|
||||
for(s8 byte = 7; byte >= 0; --byte )
|
||||
{
|
||||
out_byte = 0;
|
||||
for(s8 bit = 7; bit >= 0; --bit )
|
||||
{
|
||||
out_byte += ((*in_pos++)&1)<<bit;
|
||||
}
|
||||
*out_pos++ = out_byte;
|
||||
}
|
||||
*/
|
||||
// let us study what the hardware *does* give us!
|
||||
for (u8 i = 0; i < 8; i++)
|
||||
*out++ = buf[i+4];
|
||||
}
|
||||
|
||||
// local function
|
||||
void gbaEepromWrite8Bytes(u8 *out, u32 addr, bool short_addr = false)
|
||||
{
|
||||
// TODO: this still does not work... figure out somehow how to do it right!
|
||||
|
||||
// don't do anything unless we know what we are doing!
|
||||
#if 0
|
||||
// waitstates - this is what Rudolph uses...
|
||||
*(volatile unsigned short *)0x04000204 = 0x4317;
|
||||
|
||||
// maximal length of the buffer
|
||||
u16 buf[68];
|
||||
|
||||
// Prepare a "read" command.
|
||||
u16 length;
|
||||
// raw command
|
||||
buf[0] = 1;
|
||||
buf[1] = 1;
|
||||
// address
|
||||
if (short_addr) {
|
||||
length = 9;
|
||||
buf[2] = addr >> 5;
|
||||
buf[3] = addr >> 4;
|
||||
buf[4] = addr >> 3;
|
||||
buf[5] = addr >> 2;
|
||||
buf[6] = addr >> 1;
|
||||
buf[7] = addr;
|
||||
buf[8] = 0;
|
||||
} else {
|
||||
length = 17;
|
||||
buf[2] = addr >> 13;
|
||||
buf[3] = addr >> 12;
|
||||
buf[4] = addr >> 11;
|
||||
buf[5] = addr >> 10;
|
||||
buf[6] = addr >> 9;
|
||||
buf[7] = addr >> 8;
|
||||
buf[8] = addr >> 7;
|
||||
buf[9] = addr >> 6;
|
||||
buf[10] = addr >> 5;
|
||||
buf[11] = addr >> 4;
|
||||
buf[12] = addr >> 3;
|
||||
buf[13] = addr >> 2;
|
||||
buf[14] = addr >> 1;
|
||||
buf[15] = addr;
|
||||
buf[16] = 0;
|
||||
}
|
||||
|
||||
// send command to eeprom
|
||||
displayPrintState("Sending command");
|
||||
static u32 eeprom = 0x09ffff00;
|
||||
DMA_SRC(3) = (uint32)&buf[0];
|
||||
DMA_DEST(3) = (uint32)eeprom;
|
||||
// there is a bit for eeprom access, but it only seems to freeze the transfer!?
|
||||
//DMA_CR(3) = DMA_COPY_HALFWORDS | DMA_START_CARD | length;
|
||||
DMA_CR(3) = DMA_COPY_HALFWORDS | length;
|
||||
while(DMA_CR(3) & DMA_BUSY);
|
||||
|
||||
// get answer from eeprom
|
||||
displayPrintState("listening");
|
||||
DMA_SRC(3) = (uint32)eeprom;
|
||||
DMA_DEST(3) = (uint32)&buf[0];
|
||||
// there is a bit for eeprom access, but it only seems to freeze the transfer!?
|
||||
DMA_CR(3) = DMA_COPY_HALFWORDS | DMA_START_CARD | 68;
|
||||
//DMA_CR(3) = DMA_COPY_HALFWORDS | 68;
|
||||
while(DMA_CR(3) & DMA_BUSY);
|
||||
|
||||
// Extract data (there is only one *bit* per halfword!)
|
||||
// TODO: convert this to write format
|
||||
u16 *in_pos = &buf[4];
|
||||
u8 *out_pos = out;
|
||||
u8 out_byte;
|
||||
for(s8 byte = 7; byte >= 0; --byte )
|
||||
{
|
||||
out_byte = 0;
|
||||
for(s8 bit = 7; bit >= 0; --bit )
|
||||
{
|
||||
out_byte += ((*in_pos++)&1)<<bit;
|
||||
}
|
||||
*out_pos++ = out_byte;
|
||||
}
|
||||
#endif
|
||||
out_byte += ((*in_pos++)&1)<<bit;
|
||||
}
|
||||
*out_pos++ = out_byte ;
|
||||
}
|
||||
displayPrintState("Exit!");
|
||||
}
|
||||
|
||||
bool gbaReadSave(u8 *dst, u8 src, u32 len, u8 type)
|
||||
{
|
||||
int nbanks = 2; // for type 4,5
|
||||
bool eeprom_long = true;
|
||||
|
||||
switch (type) {
|
||||
case 1: {
|
||||
// FIXME: this does not work yet...
|
||||
eeprom_long = false;
|
||||
}
|
||||
case 2: {
|
||||
int start, end;
|
||||
start = src >> 3;
|
||||
end = (src + len - 1) >> 3;
|
||||
u8 *tmp = (u8*)malloc((end-start+1) << 3);
|
||||
u8 *ptr = tmp;
|
||||
displayPrintState("Reading from Eeprom...");
|
||||
for (int j = start; j <= end; j++, ptr+=8) {
|
||||
gbaEepromRead8Bytes(ptr, j, true);
|
||||
gbaEepromRead8Bytes(ptr, j, eeprom_long);
|
||||
}
|
||||
memcpy(dst, tmp, len);
|
||||
free(tmp);
|
||||
displayPrintState("Done!");
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
|
|
@ -345,10 +413,9 @@ bool gbaReadSave(u8 *dst, u8 src, u32 len, u8 type)
|
|||
break;
|
||||
}
|
||||
case 4:
|
||||
// FLASH - must be opend by register magic, then blind copy
|
||||
nbanks = 1;
|
||||
case 5:
|
||||
// FLASH - must be opend by register magic, then blind copy
|
||||
nbanks = 2;
|
||||
for (int j = 0; j < nbanks; j++) {
|
||||
// we need to wait a few cycles before the hardware reacts!
|
||||
*(u8*)0x0a005555 = 0xaa;
|
||||
|
|
@ -396,7 +463,7 @@ bool gbaIsAtmel()
|
|||
*(u8*)0x0a005555 = 0xf0; // leave ID mode
|
||||
swiDelay(10);
|
||||
//
|
||||
char txt[128];
|
||||
//char txt[128];
|
||||
sprintf(txt, "Man: %x, Dev: %x", man, dev);
|
||||
displayPrintState(txt);
|
||||
if ((man == 0x3d) && (dev == 0x1f))
|
||||
|
|
@ -408,12 +475,25 @@ bool gbaIsAtmel()
|
|||
bool gbaWriteSave(u8 *dst, u8 src, u32 len, u8 type)
|
||||
{
|
||||
int nbanks = 2; // for type 4,5
|
||||
bool eeprom_long = true;
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
case 2:
|
||||
// TODO: how does eeprom work?
|
||||
case 1: {
|
||||
eeprom_long = false;
|
||||
}
|
||||
case 2: {
|
||||
int start, end;
|
||||
start = src >> 3;
|
||||
end = (src + len - 1) >> 3;
|
||||
u8 *tmp = (u8*)malloc((end-start+1) << 3);
|
||||
u8 *ptr = tmp;
|
||||
for (int j = start; j <= end; j++, ptr+=8) {
|
||||
gbaEepromWrite8Bytes(ptr, j, eeprom_long);
|
||||
}
|
||||
memcpy(dst, tmp, len);
|
||||
free(tmp);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// SRAM: blind write
|
||||
u32 start = 0x0a000000 + src;
|
||||
|
|
@ -521,4 +601,5 @@ bool gbaFormatSave(u8 type)
|
|||
swiDelay(10);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ enum cartTypeGBA {
|
|||
|
||||
enum saveTypeGBA {
|
||||
SAVE_GBA_NONE = 0,
|
||||
SAVE_GBA_EEPROM_05 = 0x00010001, // 512 bytes
|
||||
SAVE_GBA_EEPROM_8 = 0x00010002, // 8k
|
||||
SAVE_GBA_SRAM_32 = 0x00020001, // 32k
|
||||
SAVE_GBA_FLASH_64 = 0x00040001, // 64k
|
||||
SAVE_GBA_FLASH_128 = 0x00040002 // 128k
|
||||
SAVE_GBA_EEPROM_05, // 512 bytes
|
||||
SAVE_GBA_EEPROM_8, // 8k
|
||||
SAVE_GBA_SRAM_32, // 32k
|
||||
SAVE_GBA_FLASH_64, // 64k
|
||||
SAVE_GBA_FLASH_128 // 128k
|
||||
};
|
||||
|
||||
struct dataSlot2 {
|
||||
|
|
|
|||
|
|
@ -35,4 +35,13 @@ char ftp_user[64] = "ftp_user";
|
|||
char ftp_pass[64] = "ftp_pass";
|
||||
int ftp_port = 0;
|
||||
|
||||
int ir_delay = 1000;
|
||||
int ir_delay = 1200;
|
||||
|
||||
char device[16] = "/";
|
||||
|
||||
char txt[256] = "";
|
||||
|
||||
u32 mode = 0;
|
||||
u32 ezflash = 0;
|
||||
|
||||
int slot2 = 0;
|
||||
|
|
|
|||
|
|
@ -40,4 +40,15 @@ extern int ftp_port;
|
|||
|
||||
extern int ir_delay;
|
||||
|
||||
// all libfat access will be using this device. default value = "/", i.e. "default" DLDI device
|
||||
extern char device[16];
|
||||
|
||||
// text buffer for composing various messages
|
||||
extern char txt[256];
|
||||
|
||||
extern u32 mode;
|
||||
extern u32 ezflash;
|
||||
|
||||
extern int slot2;
|
||||
|
||||
#endif // GLOBALS_H
|
||||
|
|
@ -25,6 +25,8 @@
|
|||
*/
|
||||
|
||||
#include <nds.h>
|
||||
#include <fat.h>
|
||||
|
||||
#include <nds/interrupts.h>
|
||||
#include <nds/arm9/console.h>
|
||||
#include <sys/dir.h>
|
||||
|
|
@ -47,6 +49,7 @@
|
|||
|
||||
#include "auxspi.h"
|
||||
#include "strings.h"
|
||||
#include "dsi.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -54,6 +57,7 @@ static u32 pitch = 0x40000;
|
|||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// FIXME: after the slot 1 detection was factored out, swap_cart no longer has perfect accuracy!
|
||||
bool swap_cart()
|
||||
{
|
||||
sNDSHeader nds;
|
||||
|
|
@ -67,9 +71,12 @@ bool swap_cart()
|
|||
if (keysCurrent() & KEY_A) {
|
||||
// identify hardware
|
||||
slot_1_type = get_slot1_type();
|
||||
// don't try to dump a flash card
|
||||
if (slot_1_type == 2)
|
||||
continue;
|
||||
sysSetBusOwners(true, true);
|
||||
// this will break DLDI on the Cyclops Evolution, but we need it anyway.
|
||||
cardReadHeader((u8*)&nds);
|
||||
//flash_card = false;
|
||||
displayPrintUpper();
|
||||
if (!nds.gameTitle[0])
|
||||
continue;
|
||||
|
|
@ -84,16 +91,21 @@ bool swap_cart()
|
|||
|
||||
u32 get_slot1_type()
|
||||
{
|
||||
u8 size1 = auxspi_save_size_log_2(false);
|
||||
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;
|
||||
|
||||
if (size1 == size2)
|
||||
return 2; // flash card
|
||||
// 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;
|
||||
|
||||
if ((size1 == 0) && (size2 != 0))
|
||||
return 1; // ir device
|
||||
|
||||
return 0; // regular game
|
||||
// No save size test returned a save chip, so it must be a flash card.
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool swap_card_game(uint32 size)
|
||||
|
|
@ -101,12 +113,74 @@ bool swap_card_game(uint32 size)
|
|||
return false;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// First, look for a DSi running in DSi mode.
|
||||
if (isDsi()) {
|
||||
size_buf = 1 << 23; // 8 MB memory buffer
|
||||
return 3;
|
||||
}
|
||||
size_buf = 1 << 21; // 2 MB memory buffer
|
||||
|
||||
// Identify Slot 2 device.
|
||||
// First, look for an EZFlash 3in1
|
||||
uint32 ime = enterCriticalSection();
|
||||
sysSetBusOwners(true, true);
|
||||
OpenNorWrite();
|
||||
ezflash = ReadNorFlashID();
|
||||
CloseNorWrite();
|
||||
leaveCriticalSection(ime);
|
||||
chip_reset();
|
||||
if (ezflash)
|
||||
return 2;
|
||||
|
||||
// Okay, maybe it is a regular GBA game instead
|
||||
if (gbaIsGame())
|
||||
return 1;
|
||||
|
||||
// Maybe it is a Slot 2 flash card.
|
||||
|
||||
// Detecting slot 2 flash cards is very evil:
|
||||
// - They don't usually support argv, so we can't simply test that we are
|
||||
// running from "fat2".
|
||||
// - We need a passme compatible slot 1 device, i.e. we can't verify that
|
||||
// there is a flash card in slot 1 (which usually is).
|
||||
// - There is only a limited number of Slot 2 flash cards on the market, so
|
||||
// we could test for this (I think there is a library for this). But if we
|
||||
// boot from Slot 1, a positive Slot 2 test does not mean that we did boot
|
||||
// from there - the card may be sitting there unused!
|
||||
//
|
||||
// --> So we select slot 2 mode the "dumb" way - with an ini parameter. Unless you swap
|
||||
// the same microSD card between Slot 1 and Slot 2, this should be the safest mode.
|
||||
// (If you know a smarter way of doing this, feel free to commit a patch!)
|
||||
//
|
||||
if (slot2)
|
||||
return 4;
|
||||
|
||||
// Try to identify download play mode. This also introduces various complications:
|
||||
// - The latest libnds versions include code for the SD-slot on the DSi. It does not work
|
||||
// from flash cards or download play, but it may still result in a positive DLDI driver
|
||||
// initialisation. So we can't simply run "fatInitDefault" and test return values.
|
||||
// - Currently, download play mode aims to "insert game first, then run dlp", i.e.
|
||||
// it does not support hotswapping the game. So we select this mode if there is *no*
|
||||
// flash card inserted in Slot 1.
|
||||
//
|
||||
if (slot_1_type != 2)
|
||||
return 5;
|
||||
|
||||
// Nothing unique found, so enter WiFi mode
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
void hwFormatNor(uint32 page, uint32 count)
|
||||
{
|
||||
uint32 ime = hwGrab3in1();
|
||||
SetSerialMode();
|
||||
//displayPrintState("Formating NOR memory");
|
||||
displayProgressBar(0, count);
|
||||
for (uint32 i = page; i < page+count; i++) {
|
||||
Block_Erase(i << 18);
|
||||
|
|
@ -139,9 +213,10 @@ void hwBackup3in1()
|
|||
swap_cart();
|
||||
displayPrintUpper();
|
||||
|
||||
uint8 size = auxspi_save_size_log_2();
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
int size_blocks = 1 << max(0, (int8(size) - 18)); // ... in units of 0x40000 bytes - that's 256 kB
|
||||
uint8 type = auxspi_save_type();
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
|
||||
displayMessage2A(STR_HW_3IN1_FORMAT_NOR, false);
|
||||
hwFormatNor(0, size_blocks+1);
|
||||
|
|
@ -152,26 +227,27 @@ void hwBackup3in1()
|
|||
else
|
||||
size_blocks = 1 << (uint8(size) - 15);
|
||||
u8 *test = (u8*)malloc(0x8000);
|
||||
if (test == NULL)
|
||||
while(1);
|
||||
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, LEN, type);
|
||||
auxspi_read_data(i << 15, data, LEN, type, ir);
|
||||
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);
|
||||
}
|
||||
// test if NOR memory is sane, i.e. if we can read what we just wrote
|
||||
ime = hwGrab3in1();
|
||||
ReadNorFlash(test, (i << 15) + pitch, LEN);
|
||||
hwRelease3in1(ime);
|
||||
if (*((vuint16 *)(FlashBase+0x2002)) == 0x227E) {
|
||||
displayMessage("ERROR: ID mode active!");
|
||||
displayMessage2A(STR_HW_3IN1_ERR_IDMODE, false);
|
||||
while(1);
|
||||
}
|
||||
if (memcmp(test, data, LEN)) {
|
||||
displayMessage("ERROR: verifying NOR failed");
|
||||
displayMessage2A(STR_HW_3IN1_ERR_NOR, false);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -201,13 +277,6 @@ void hwBackup3in1()
|
|||
|
||||
displayMessage2A(STR_HW_3IN1_PLEASE_REBOOT, false);
|
||||
|
||||
ime = hwGrab3in1();
|
||||
ReadNorFlash((u8*)&data2, 0x1000, sizeof(data2)); // this should work - but it does not!
|
||||
hwRelease3in1(ime);
|
||||
char txt[128];
|
||||
sprintf(txt, "%.12s", &data2.name[0]);
|
||||
displayMessage(txt);
|
||||
|
||||
while(1) {};
|
||||
}
|
||||
|
||||
|
|
@ -220,10 +289,12 @@ void hwDump3in1(uint32 size, const char *gamename)
|
|||
char path[256];
|
||||
char fname[256] = "";
|
||||
fileSelect("/", path, fname, 0, true, false);
|
||||
|
||||
// look for an unused filename
|
||||
if (!fname[0]) {
|
||||
uint32 cnt = 0;
|
||||
sprintf(fname, "/%s.%i.sav", gamename, cnt);
|
||||
char txt[256];
|
||||
//char txt[256];
|
||||
sprintf(txt, stringsGetMessageString(STR_HW_SEEK_UNUSED_FNAME), fname);
|
||||
displayMessage2(txt, false);
|
||||
while (fileExists(fname)) {
|
||||
|
|
@ -238,7 +309,6 @@ void hwDump3in1(uint32 size, const char *gamename)
|
|||
}
|
||||
char fullpath[256];
|
||||
sprintf(fullpath, "%s/%s", path, fname);
|
||||
char txt[512];
|
||||
sprintf(txt, stringsGetMessageString(STR_HW_3IN1_DUMP), fullpath);
|
||||
displayMessage2(txt, false);
|
||||
|
||||
|
|
@ -259,7 +329,7 @@ void hwDump3in1(uint32 size, const char *gamename)
|
|||
|
||||
sprintf(txt, stringsGetMessageString(STR_HW_3IN1_DONE_DUMP), fullpath);
|
||||
displayMessage2(txt, false);
|
||||
while (1);
|
||||
while (!(keysCurrent() & KEY_B)) {};
|
||||
}
|
||||
|
||||
void hwRestore3in1()
|
||||
|
|
@ -270,6 +340,7 @@ void hwRestore3in1()
|
|||
displayMessageA(STR_HW_SELECT_FILE); // lower screen is used for file browser
|
||||
fileSelect("/", path, fname, 0, false, false);
|
||||
char msg[256];
|
||||
// This does not have to be translated.
|
||||
sprintf(msg, "%s/%s", path, fname);
|
||||
displayMessage(msg);
|
||||
|
||||
|
|
@ -303,13 +374,11 @@ void hwRestore3in1()
|
|||
ReadNorFlash(test, (i << 15) + pitch, LEN);
|
||||
hwRelease3in1(ime);
|
||||
if (*((vuint16 *)(FlashBase+0x2002)) == 0x227E) {
|
||||
displayMessage("ERROR: ID mode active!");
|
||||
displayMessage2A(STR_HW_3IN1_ERR_IDMODE, false);
|
||||
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);
|
||||
if (memcmp(test, data, LEN)) {
|
||||
displayMessage2A(STR_HW_3IN1_ERR_NOR, false);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -317,25 +386,30 @@ void hwRestore3in1()
|
|||
fclose(file);
|
||||
free(test);
|
||||
|
||||
hwRestore3in1_b(size);
|
||||
hwRestore3in1_b(1 << size);
|
||||
}
|
||||
|
||||
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();
|
||||
uint32 size = auxspi_save_size_log_2(ir);
|
||||
while ((size_file < size) || (slot_1_type == 2)) {
|
||||
// TODO: make THIS error message more meaningful!
|
||||
displayPrintState("File too small or no save chip!");
|
||||
if (slot_1_type == 2)
|
||||
displayMessage2A(STR_HW_SWAP_CARD, false);
|
||||
else if (size_file < size)
|
||||
displayMessage2A(STR_HW_WRONG_GAME, false);
|
||||
swap_cart();
|
||||
size = auxspi_save_size_log_2();
|
||||
ir = (slot_1_type == 1) ? true : false;
|
||||
size = auxspi_save_size_log_2(ir);
|
||||
}
|
||||
displayPrintUpper();
|
||||
|
||||
uint8 type = auxspi_save_type();
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
if (type == 3) {
|
||||
displayMessage2A(STR_HW_FORMAT_GAME, false);
|
||||
auxspi_erase();
|
||||
auxspi_erase(ir);
|
||||
}
|
||||
|
||||
// And finally, write the save!
|
||||
|
|
@ -363,7 +437,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);
|
||||
auxspi_write_data(i << shift, data, LEN, type, ir);
|
||||
}
|
||||
displayProgressBar(1, 1);
|
||||
|
||||
|
|
@ -375,11 +449,10 @@ void hwRestore3in1_b(uint32 size_file)
|
|||
// ------------------------------------------------------------
|
||||
void hwErase()
|
||||
{
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
displayMessage2A(STR_HW_WARN_DELETE, true);
|
||||
while (!(keysCurrent() & (KEY_UP | KEY_R | KEY_Y))) {};
|
||||
auxspi_erase();
|
||||
displayMessage2A(STR_HW_DID_DELETE, true);
|
||||
while(1);
|
||||
auxspi_erase(ir);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
|
@ -388,44 +461,45 @@ void hwBackupFTP(bool dlp)
|
|||
netbuf *buf, *ndata;
|
||||
int j;
|
||||
static int jmax = 10;
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
|
||||
// Dump save and write it to FTP server
|
||||
// First: swap card
|
||||
if (!dlp)
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
uint8 size = auxspi_save_size_log_2();
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
int size_blocks = 1 << max(0, (int8(size) - 18)); // ... in units of 0x40000 bytes - that's 256 kB
|
||||
uint8 type = auxspi_save_type();
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
if (size < 15)
|
||||
size_blocks = 1;
|
||||
else
|
||||
size_blocks = 1 << (uint8(size) - 15);
|
||||
|
||||
// Second: connect to FTP server
|
||||
displayPrintState("FTP: connecting to AP");
|
||||
displayMessage2A(STR_HW_FTP_SEEK_AP, false);
|
||||
if (!Wifi_InitDefault(true)) {
|
||||
displayPrintState("FTP: ERROR: AP not found");
|
||||
displayMessage2A(STR_HW_FTP_ERR_AP, true);
|
||||
while(1);
|
||||
}
|
||||
displayPrintState("FTP: connecting to FTP server");
|
||||
displayMessage2A(STR_HW_FTP_SEEK_FTP, false);
|
||||
char fullname[512];
|
||||
sprintf(fullname, "%s:%i", ftp_ip, ftp_port);
|
||||
j = 0;
|
||||
while (!FtpConnect(fullname, &buf)) {
|
||||
j++;
|
||||
if (j >= jmax) {
|
||||
displayPrintState("FTP: ERROR: FTP server missing");
|
||||
displayMessage2A(STR_HW_FTP_ERR_FTP, true);
|
||||
while(1);
|
||||
}
|
||||
swiDelay(10000);
|
||||
}
|
||||
displayPrintState("FTP: login");
|
||||
displayMessage2A(STR_HW_FTP_LOGIN, false);
|
||||
j = 0;
|
||||
while (!FtpLogin(ftp_user, ftp_pass, buf)) {
|
||||
j++;
|
||||
if (j >= jmax) {
|
||||
displayPrintState("FTP: ERROR: login failed");
|
||||
displayMessage2A(STR_HW_FTP_ERR_LOGIN, true);
|
||||
while(1);
|
||||
}
|
||||
swiDelay(10000);
|
||||
|
|
@ -435,7 +509,7 @@ void hwBackupFTP(bool dlp)
|
|||
char fname[256] ="";
|
||||
memset(fname, 0, 256);
|
||||
displayMessageA(STR_HW_SELECT_FILE_OW);
|
||||
displayPrintState("FTP: dir");
|
||||
displayPrintState("FTP: dir"); // TODO: translate me!
|
||||
fileSelect("/", fdir, fname, buf, true, false);
|
||||
bool newfile;
|
||||
if (!fname[0])
|
||||
|
|
@ -452,7 +526,6 @@ void hwBackupFTP(bool dlp)
|
|||
int tsize = 0;
|
||||
sprintf(fname, "%.12s.%i.sav", nds.gameTitle, cnt);
|
||||
while (FtpSize(fname, &tsize, FTPLIB_IMAGE, buf) != 0) {
|
||||
char txt[256];
|
||||
sprintf(txt, stringsGetMessageString(STR_HW_SEEK_UNUSED_FNAME), fname);
|
||||
displayMessage2(txt, false);
|
||||
if (cnt < 65536)
|
||||
|
|
@ -462,13 +535,13 @@ void hwBackupFTP(bool dlp)
|
|||
while(1);
|
||||
}
|
||||
sprintf(fname, "%.12s.%i.sav", nds.gameTitle, cnt);
|
||||
displayPrintState(fname);
|
||||
}
|
||||
}
|
||||
|
||||
// Fourth: dump save
|
||||
displayPrintState("");
|
||||
sprintf(fullname, "Writing file:\n%s%s", fdir, fname);
|
||||
// This may not have to be translated.
|
||||
sprintf(fullname, "%s%s", fdir, fname);
|
||||
displayMessage(fullname);
|
||||
FtpAccess(fname, FTPLIB_FILE_WRITE, FTPLIB_IMAGE, buf, &ndata);
|
||||
u32 length = 0x200;
|
||||
|
|
@ -476,19 +549,18 @@ void hwBackupFTP(bool dlp)
|
|||
length = 1 << size;
|
||||
for (int i = 0; i < (1 << (size - 9)); i++) {
|
||||
displayProgressBar(i+1, (size_blocks << 6));
|
||||
auxspi_read_data(i << 9, (u8*)&data[0], length, type);
|
||||
int out = 0;
|
||||
while (out < 512) {
|
||||
out += FtpWrite((u8*)&data[out], 512-out, ndata);
|
||||
if (out < 512) {
|
||||
auxspi_read_data(i << 9, (u8*)&data[0], length, type, ir);
|
||||
u32 out = 0;
|
||||
while (out < length) {
|
||||
u32 delta = FtpWrite((u8*)&data[out], length-out, ndata);
|
||||
out += delta;
|
||||
if (delta == 0) {
|
||||
displayMessage2A(STR_HW_FTP_READ_ONLY, false);
|
||||
} else {
|
||||
displayMessage2("", false);
|
||||
}
|
||||
if (delta < length) {
|
||||
displayPrintState(stringsGetMessageString(STR_HW_FTP_SLOW));
|
||||
/*
|
||||
debug++;
|
||||
if (debug >= 2048) {
|
||||
debug = 0;
|
||||
displayMessage2("Unable to reach FTP server. Make sure that you have WRITE ACCESS!"
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
displayPrintState("");
|
||||
}
|
||||
|
|
@ -500,7 +572,7 @@ void hwBackupFTP(bool dlp)
|
|||
Wifi_DisconnectAP();
|
||||
|
||||
if (dlp) {
|
||||
displayMessage("Done! Please turn off your DS.");
|
||||
displayMessage2A(STR_HW_PLEASE_REBOOT, false);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -510,32 +582,33 @@ void hwRestoreFTP(bool dlp)
|
|||
netbuf *buf, *ndata;
|
||||
int j;
|
||||
static int jmax = 10;
|
||||
bool ir = (slot_1_type == 1) ? true : false;
|
||||
|
||||
// Dump save and write it to FTP server
|
||||
// First: connect to FTP server
|
||||
displayPrintState("FTP: connecting to AP");
|
||||
displayMessage2A(STR_HW_FTP_SEEK_AP, false);
|
||||
if (!Wifi_InitDefault(true)) {
|
||||
displayPrintState("FTP: ERROR: AP not found");
|
||||
displayMessage2A(STR_HW_FTP_ERR_AP, true);
|
||||
while(1);
|
||||
}
|
||||
displayPrintState("FTP: connecting to FTP server");
|
||||
displayMessage2A(STR_HW_FTP_SEEK_FTP, false);
|
||||
char fullname[512];
|
||||
sprintf(fullname, "%s:%i", ftp_ip, ftp_port);
|
||||
j = 0;
|
||||
while (!FtpConnect(fullname, &buf)) {
|
||||
j++;
|
||||
if (j >= jmax) {
|
||||
displayPrintState("FTP: ERROR: FTP server missing");
|
||||
displayMessage2A(STR_HW_FTP_ERR_FTP, true);
|
||||
while(1);
|
||||
}
|
||||
swiDelay(10000);
|
||||
}
|
||||
displayPrintState("FTP: login");
|
||||
displayMessage2A(STR_HW_FTP_LOGIN, false);
|
||||
j = 0;
|
||||
while (!FtpLogin(ftp_user, ftp_pass, buf)) {
|
||||
j++;
|
||||
if (j >= jmax) {
|
||||
displayPrintState("FTP: ERROR: login failed");
|
||||
displayMessage2A(STR_HW_FTP_ERR_LOGIN, false);
|
||||
while(1);
|
||||
}
|
||||
swiDelay(10000);
|
||||
|
|
@ -545,21 +618,21 @@ void hwRestoreFTP(bool dlp)
|
|||
char fdir[256] = "";
|
||||
char fname[256] ="";
|
||||
memset(fname, 0, 256);
|
||||
displayMessage("Please select a file name to\nrestore.");
|
||||
displayMessageA(STR_HW_SELECT_FILE);
|
||||
displayPrintState("FTP: dir");
|
||||
fileSelect("/", fdir, fname, buf, true, false);
|
||||
fileSelect("/", fdir, fname, buf, false, false);
|
||||
|
||||
// Third: swap card
|
||||
if (!dlp)
|
||||
swap_cart();
|
||||
displayPrintUpper();
|
||||
uint8 size = auxspi_save_size_log_2();
|
||||
uint8 type = auxspi_save_type();
|
||||
uint8 size = auxspi_save_size_log_2(ir);
|
||||
uint8 type = auxspi_save_type(ir);
|
||||
|
||||
// Fourth: read file
|
||||
displayPrintState("");
|
||||
FtpChdir(fdir, buf);
|
||||
sprintf(fullname, "Reading file:\n%s%s", fdir, fname);
|
||||
sprintf(fullname, "%s%s", fdir, fname);
|
||||
displayMessage(fullname);
|
||||
u32 LEN = 0, num_blocks = 0, shift = 0;
|
||||
switch (type) {
|
||||
|
|
@ -591,8 +664,9 @@ void hwRestoreFTP(bool dlp)
|
|||
#endif
|
||||
}
|
||||
if ((type == 3) && (insecure)) {
|
||||
displayPrintState("Formating Flash chip");
|
||||
auxspi_erase();
|
||||
displayMessage2A(STR_HW_FORMAT_GAME, false);
|
||||
//displayPrintState("Formating Flash chip");
|
||||
auxspi_erase(ir);
|
||||
}
|
||||
FtpAccess(fname, FTPLIB_FILE_READ, FTPLIB_IMAGE, buf, &ndata);
|
||||
u8 *pdata = data;
|
||||
|
|
@ -606,36 +680,26 @@ void hwRestoreFTP(bool dlp)
|
|||
else
|
||||
displayPrintState("");
|
||||
}
|
||||
/*
|
||||
int out;
|
||||
if ((out = FtpRead((u8*)pdata, 512, ndata)) < 512) {
|
||||
char dings[512];
|
||||
sprintf(dings, "Error: requested 512, got %i", out);
|
||||
displayPrintState(dings);
|
||||
while(1);
|
||||
}
|
||||
*/
|
||||
// does not fit into memory: insecure mode
|
||||
// does not fit into memory: unsafe mode
|
||||
// TODO: reactivate this!
|
||||
if (insecure) {
|
||||
//char bums[512];
|
||||
//sprintf(bums, "addr = %x", (i << 9)+(j << shift));
|
||||
displayPrintState("Writing save (insecure!)");
|
||||
for (int j = 0; j < 1 << (9-shift); j++) {
|
||||
auxspi_write_data((i << 9)+(j << shift), ((u8*)pdata)+(j<<shift), LEN, type);
|
||||
auxspi_write_data((i << 9)+(j << shift), ((u8*)pdata)+(j<<shift), LEN, type, ir);
|
||||
}
|
||||
}
|
||||
pdata += 512;
|
||||
}
|
||||
// Write to game (safe mode)
|
||||
if (!insecure) {
|
||||
displayMessage("Got file, now writing to game");
|
||||
if (type == 3) {
|
||||
displayPrintState("Formating Flash chip");
|
||||
auxspi_erase();
|
||||
displayMessage2A(STR_HW_FORMAT_GAME, false);
|
||||
auxspi_erase(ir);
|
||||
}
|
||||
for (int i = 0; i < (1 << (size - shift)); i++) {
|
||||
displayPrintState("Writing save");
|
||||
displayMessage2A(STR_HW_WRITE_GAME, false);
|
||||
displayProgressBar(i+1, 1 << (size - shift));
|
||||
auxspi_write_data(i << shift, ((u8*)data)+(i<<shift), LEN, type);
|
||||
auxspi_write_data(i << shift, ((u8*)data)+(i<<shift), LEN, type, ir);
|
||||
}
|
||||
}
|
||||
FtpClose(ndata);
|
||||
|
|
@ -644,7 +708,7 @@ void hwRestoreFTP(bool dlp)
|
|||
Wifi_DisconnectAP();
|
||||
|
||||
if (dlp) {
|
||||
displayMessage("Done! Please turn off your DS.");
|
||||
displayMessage2A(STR_HW_PLEASE_REBOOT, false);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -656,22 +720,26 @@ void hwBackupGBA(u8 type)
|
|||
return;
|
||||
|
||||
if ((type == 1) || (type == 2)) {
|
||||
// This is not to be translated, it will be removed at some point.
|
||||
displayMessage("I can't read this save type\nyet. Please use Rudolphs tool\ninstead.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char path[256];
|
||||
char fname[256] = "";
|
||||
char *gamename = (char*)0x080000a0;
|
||||
fileSelect("/", path, fname, 0, true, false);
|
||||
// look for an unused filename
|
||||
if (!fname[0]) {
|
||||
uint32 cnt = 0;
|
||||
sprintf(fname, "/%.12s.%i.sav", gamename, cnt);
|
||||
sprintf(txt, stringsGetMessageString(STR_HW_SEEK_UNUSED_FNAME), fname);
|
||||
displayMessage2(txt, false);
|
||||
while (fileExists(fname)) {
|
||||
if (cnt < 65536)
|
||||
cnt++;
|
||||
else {
|
||||
displayMessage("Unable to get a filename!\nThis means that you have more\nthan 65536 saves! (wow!)\nOops!");
|
||||
displayMessage2A(STR_ERR_NO_FNAME, true);
|
||||
while(1);
|
||||
}
|
||||
sprintf(fname, "/%.12s.%i.sav", gamename, cnt);
|
||||
|
|
@ -681,11 +749,11 @@ void hwBackupGBA(u8 type)
|
|||
sprintf(fullpath, "%s/%s", path, fname);
|
||||
displayMessage(fname);
|
||||
|
||||
displayPrintState("Reading save from game");
|
||||
displayMessage2A(STR_HW_GBA_READ, false);
|
||||
uint32 size = gbaGetSaveSize(type);
|
||||
gbaReadSave(data, 0, size, type);
|
||||
|
||||
displayPrintState("Writing save to flash card");
|
||||
displayMessage2A(STR_HW_GBA_DUMP, false);
|
||||
FILE *file = fopen(fullpath, "wb");
|
||||
fwrite(data, 1, size, file);
|
||||
fclose(file);
|
||||
|
|
@ -701,6 +769,7 @@ void hwRestoreGBA()
|
|||
return;
|
||||
|
||||
if ((type == 1) || (type == 2)) {
|
||||
// This is not to be translated, it will be removed at some point.
|
||||
displayMessage("I can't write this save type\nyet. Please use Rudolphs tool\ninstead.");
|
||||
return;
|
||||
}
|
||||
|
|
@ -712,22 +781,23 @@ void hwRestoreGBA()
|
|||
fileSelect("/", path, fname, 0);
|
||||
char fullpath[512];
|
||||
sprintf(fullpath, "%s/%s", path, fname);
|
||||
displayMessage(fname);
|
||||
//displayMessage(fname);
|
||||
|
||||
displayPrintState("Reading save from flash card");
|
||||
sprintf(txt, stringsGetMessageString(STR_HW_GBA_LOAD), fname);
|
||||
displayMessage2A(STR_HW_GBA_LOAD, false);
|
||||
FILE *file = fopen(fullpath, "rb");
|
||||
fread(data, 1, size, file);
|
||||
fclose(file);
|
||||
|
||||
if ((type == 4) || (type == 5)) {
|
||||
displayPrintState("Deleting old save.");
|
||||
displayMessage2A(STR_HW_FORMAT_GAME, false);
|
||||
gbaFormatSave(type);
|
||||
}
|
||||
|
||||
displayPrintState("Writing save to game");
|
||||
displayMessage2A(STR_HW_WRITE_GAME, false);
|
||||
gbaWriteSave(data, 0, size, type);
|
||||
|
||||
displayPrintState("Done!");
|
||||
displayMessage2A(STR_HW_PLEASE_REBOOT, false);
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,17 @@ void do_restore_nds_save();
|
|||
|
||||
bool swap_cart();
|
||||
u32 get_slot1_type();
|
||||
//bool is_flash_card();
|
||||
|
||||
// This function was previously found in the main function.
|
||||
// Return values:
|
||||
// 0 - no special configuration, WiFi mode
|
||||
// 1 - GBA game in Slot 2
|
||||
// 2 - EZFlash 3in1 in Slot 2
|
||||
// 3 - running in DSi mode
|
||||
// 4 - running from Slot 2 flash card
|
||||
// 5 - running from download play or another exploit that does not need a flash card in Slot 1
|
||||
//
|
||||
u32 hwDetect();
|
||||
|
||||
void hwBackup3in1();
|
||||
void hwDump3in1(uint32 size, const char *gamename);
|
||||
|
|
|
|||
|
|
@ -53,13 +53,6 @@
|
|||
using std::max;
|
||||
|
||||
|
||||
uint32 ezflash = 0;
|
||||
uint32 dstype = 0;
|
||||
bool gba = 0;
|
||||
uint32 mode = 0;
|
||||
bool slot2 = false;
|
||||
u8 gbatype = 0;
|
||||
|
||||
char bootdir[256] = "/";
|
||||
|
||||
|
||||
|
|
@ -73,10 +66,9 @@ void mode_dsi()
|
|||
displayPrintUpper();
|
||||
displayPrintLower();
|
||||
|
||||
|
||||
// DSi mode, does nothing at the moment
|
||||
displayPrintState("DSi mode - still unsupported!");
|
||||
while (1);
|
||||
displayMessage2A(STR_BOOT_MODE_UNSUPPORTED,true);
|
||||
while(1);
|
||||
|
||||
touchPosition touchXY;
|
||||
while(1) {
|
||||
|
|
@ -109,7 +101,7 @@ void mode_slot2()
|
|||
displayPrintUpper();
|
||||
displayPrintLower();
|
||||
|
||||
displayMessage("This mode is DISABLED.\nPlease remove Slot-2 module\nand restart this tool.");
|
||||
displayMessage2A(STR_BOOT_MODE_UNSUPPORTED,true);
|
||||
while(1);
|
||||
|
||||
touchPosition touchXY;
|
||||
|
|
@ -140,7 +132,6 @@ void mode_slot2()
|
|||
void mode_3in1()
|
||||
{
|
||||
displayPrintUpper();
|
||||
displayPrintLower();
|
||||
|
||||
dsCardData data2;
|
||||
uint32 ime = hwGrab3in1();
|
||||
|
|
@ -156,6 +147,9 @@ void mode_3in1()
|
|||
hwFormatNor(0, 1); // clear reboot flag
|
||||
hwDump3in1(size, name);
|
||||
}
|
||||
displayMessage("");
|
||||
displayProgressBar(0,0);
|
||||
displayPrintLower();
|
||||
|
||||
touchPosition touchXY;
|
||||
while(1) {
|
||||
|
|
@ -184,6 +178,10 @@ void mode_3in1()
|
|||
|
||||
void mode_gba()
|
||||
{
|
||||
// This function takes some time, since it needs to parse the entire GBA module
|
||||
// for a magic string. It is only called when truly necessary. (i.e. once for now)
|
||||
u8 gbatype = gbaGetSaveType();
|
||||
|
||||
// use 3in1 to buffer data
|
||||
displayPrintState("");
|
||||
gbatype = gbaGetSaveType();
|
||||
|
|
@ -251,7 +249,7 @@ void mode_wifi()
|
|||
|
||||
void mode_dlp()
|
||||
{
|
||||
// use 3in1 to buffer data
|
||||
// use non-flash card based exploits (download play or Sudoku?). untested, and does not work yet!
|
||||
displayPrintState("");
|
||||
displayPrintUpper();
|
||||
displayPrintLower();
|
||||
|
|
@ -275,45 +273,30 @@ void mode_dlp()
|
|||
if ((touchXY.py > 8*16) && (touchXY.py < 8*24)) {
|
||||
displayPrintUpper();
|
||||
hwErase();
|
||||
displayMessage("Done! Please turn off your DS.");
|
||||
displayMessage2A(STR_HW_DID_DELETE, true);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
bool loadIniFile(char* path)
|
||||
{
|
||||
sysSetBusOwners(true, true);
|
||||
|
||||
// Init the screens
|
||||
displayInit();
|
||||
|
||||
// Init DLDI (file system driver)
|
||||
// TODO: find some way to skip this when loading from a different exploit/download play/not a flash card
|
||||
int fat = fatInitDefault();
|
||||
if (fat == 0) {
|
||||
displayPrintState("DLDI error\n");
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
// test if our flash card supports argv at all. some R4 clones seem to be very picky!
|
||||
// (untested due to lack of an R4 myself, but I hope it works)
|
||||
bool has_argv = false;
|
||||
if (argc)
|
||||
has_argv = true;
|
||||
// Don't try to load ini file in DLP mode, we need to get our options from a different source.
|
||||
// Still trying to figure something out...
|
||||
if (mode == 5)
|
||||
return true;
|
||||
|
||||
ini_fd_t ini = 0;
|
||||
|
||||
// load ini file...
|
||||
ini_fd_t ini = 0;
|
||||
char inipath[256];
|
||||
if (has_argv) {
|
||||
if (argv[0]) {
|
||||
char *last = strrchr(argv[0], '/');
|
||||
int len = (last - argv[0])+1;
|
||||
strncpy(bootdir, argv[0], len);
|
||||
sprintf(inipath, "%s/savegame_manager.ini", bootdir);
|
||||
if (fileExists(inipath))
|
||||
ini = ini_open(inipath, "r", "");
|
||||
}
|
||||
if (path) {
|
||||
char *last = strrchr(path, '/');
|
||||
int len = (last - path)+1;
|
||||
strncpy(bootdir, path, len);
|
||||
sprintf(inipath, "%s/savegame_manager.ini", bootdir);
|
||||
if (fileExists(inipath))
|
||||
ini = ini_open(inipath, "r", "");
|
||||
}
|
||||
if (!ini) {
|
||||
sprintf(inipath, "/savegame_manager.ini");
|
||||
|
|
@ -321,8 +304,8 @@ int main(int argc, char* argv[])
|
|||
ini = ini_open(inipath, "r", "");
|
||||
}
|
||||
if (!ini) {
|
||||
displayMessage("Unable to open ini file!\nPlease make sure that it is\n1. in this apps folder, or"
|
||||
"\n2. in the root folder\nIf 1. does not work, use 2.");
|
||||
// FIXME
|
||||
displayMessage2A(STR_BOOT_NO_INI,true);
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
|
@ -335,77 +318,116 @@ 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_locateKey(ini, "ir_delay");
|
||||
ini_readInt(ini, &ir_delay);
|
||||
ir_delay = max(ir_delay, 1000);
|
||||
|
||||
ini_locateKey(ini, "slot2");
|
||||
ini_readInt(ini, &slot2);
|
||||
|
||||
ini_close(ini);
|
||||
|
||||
// delete temp file (which is a remnant of inilib)
|
||||
remove("/tmpfile");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is a new attempt to reliably identify if the flash card has argv support or not,
|
||||
// including R4 clones which may have *bad* argv support.
|
||||
bool has_argv(int argc, char* argv[])
|
||||
{
|
||||
// no argv support
|
||||
if (argc == 0)
|
||||
return false;
|
||||
|
||||
// bad argv support: if argc is larger than unity, your flash card can't even do
|
||||
// a proper negative indicator. let us test for 2 argv arguments, just to be safe.
|
||||
if (argc > 2)
|
||||
return false;
|
||||
|
||||
/*
|
||||
// test if argv[0] pointer is valid (scan main memory and WRAM)
|
||||
if ((argv[0] < 0x02000000) || (argv[0] >= 0x04000000))
|
||||
return false;
|
||||
*/
|
||||
|
||||
// test if argv[0] contains a valid string
|
||||
char *arg0 = argv[0];
|
||||
// test for possible "/path", "fat*:/path" and "sd:/*".
|
||||
if (*arg0 == 'f')
|
||||
if (strncasecmp(argv[0], "fat:/", 5) || strncasecmp(argv[0], "fat1:/", 6)
|
||||
|| strncasecmp(argv[0], "fat2:/", 6))
|
||||
return true;
|
||||
|
||||
if (*arg0 == 's')
|
||||
if (strncasecmp(argv[0], "sd:/", 4))
|
||||
return true;
|
||||
|
||||
if (*arg0 == '/')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
sysSetBusOwners(true, true);
|
||||
|
||||
// Init the screens
|
||||
displayInit();
|
||||
|
||||
// detect hardware
|
||||
mode = hwDetect();
|
||||
|
||||
// Init DLDI (file system driver), skip for mode == 4,5 which already calls this during
|
||||
// hardware initialisation
|
||||
if (mode < 4) {
|
||||
int fat = fatInitDefault();
|
||||
if (fat == 0) {
|
||||
displayMessage2A(STR_BOOT_DLDI_ERROR,true);
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the ini file with the FTP settings and more options
|
||||
if (has_argv(argc, argv))
|
||||
loadIniFile(argv[0]);
|
||||
else
|
||||
loadIniFile(0);
|
||||
|
||||
// prepare the global data buffer
|
||||
data = (u8*)malloc(size_buf);
|
||||
// This should not be required, but better safe than sorry. On the DS, it *might* be
|
||||
// possible that no continuous 2 MB are available.
|
||||
if (data == NULL) {
|
||||
size_buf >>= 1;
|
||||
data = (u8*)malloc(size_buf);
|
||||
}
|
||||
|
||||
// load strings
|
||||
stringsLoadFile(0);
|
||||
|
||||
// Identify hardware and branch to corresponding mode
|
||||
//displayMessage("Identifying hardware...");
|
||||
|
||||
// 1) Identify DSi (i.e. memory capacity)
|
||||
//displayPrintState("ID: DS model");
|
||||
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);
|
||||
|
||||
// is there a game card in slot-1? if so, we have been starten with download-play or a new exploit
|
||||
slot_1_type = get_slot1_type();
|
||||
|
||||
// don't try to identify Slot-2 in DSi mode.
|
||||
if (dstype == 0) {
|
||||
//displayPrintState("ID: Slot 2");
|
||||
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
|
||||
if (argv[0][3] == '2')
|
||||
slot2 = true;
|
||||
|
||||
// okay, we got our HW identified; now branch to the corresponding main function/event handler
|
||||
if (slot_1_type != 2) {
|
||||
// running from download play, NOR, or a different exploit. enter dlp mode.
|
||||
mode = 5;
|
||||
mode_dlp();
|
||||
} else if (dstype == 1) {
|
||||
// DSi/DSiXL, branch to SD-card mode when cracked.
|
||||
mode = 3;
|
||||
mode_dsi();
|
||||
} else if (slot2) {
|
||||
mode = 4;
|
||||
mode_slot2();
|
||||
} else if (ezflash != 0) {
|
||||
// DS with EZFlash found -> branch to 3in1 mode
|
||||
mode = 2;
|
||||
mode_3in1();
|
||||
} else if (gba) {
|
||||
// GBA game in slot 2 -> branch to GBA mode
|
||||
mode = 1;
|
||||
mode_gba();
|
||||
} else {
|
||||
// failsafe: enter WiFi mode
|
||||
mode = 0;
|
||||
mode_wifi();
|
||||
switch (mode) {
|
||||
case 1:
|
||||
mode_gba();
|
||||
break;
|
||||
case 2:
|
||||
mode_3in1();
|
||||
break;
|
||||
case 3:
|
||||
mode_dsi();
|
||||
break;
|
||||
case 4:
|
||||
mode_slot2();
|
||||
break;
|
||||
case 5:
|
||||
mode_dlp();
|
||||
break;
|
||||
default:
|
||||
mode_wifi();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -31,12 +31,13 @@
|
|||
#include "libini.h"
|
||||
#include <nds.h>
|
||||
#include "fileselect.h"
|
||||
#include "globals.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// a global string array
|
||||
char **message_strings;
|
||||
char txt[512];
|
||||
//char txt[512];
|
||||
|
||||
#define ADD_STRING(id,text) strcpy(txt,text);\
|
||||
message_strings[id] = new char[strlen(txt)+1];\
|
||||
|
|
@ -59,7 +60,7 @@ bool stringsLoadFile(const char *fname)
|
|||
message_strings = new char*[STR_LAST];
|
||||
#ifndef NOT_FINISHED
|
||||
ini_locateHeading(ini, "");
|
||||
char txt[512];
|
||||
//char txt[512];
|
||||
for (int i = 0; i < STR_LAST; i++) {
|
||||
sprintf(txt, "%i", i);
|
||||
ini_locateKey(ini, txt);
|
||||
|
|
@ -71,7 +72,14 @@ bool stringsLoadFile(const char *fname)
|
|||
// delete temp file (which is a remnant of inilib)
|
||||
remove("/tmpfile");
|
||||
#else
|
||||
ADD_STRING(STR_BOOT_NO_INI,"Unable to open ini file!\nPlease make sure that it is\n1. in this apps folder, or"
|
||||
"\n2. in the root folder\nIf 1. does not work, use 2.");
|
||||
ADD_STRING(STR_BOOT_MODE_UNSUPPORTED,"This mode is DISABLED.\nPlease restart the system.");
|
||||
ADD_STRING(STR_BOOT_DLDI_ERROR,"DLDI initialisation error!");
|
||||
//
|
||||
ADD_STRING(STR_HW_SWAP_CARD,"Please take out Slot 1\nflash card and insert a game\n\nPress A when done.");
|
||||
ADD_STRING(STR_HW_WRONG_GAME,"This game has a save chip\nthat is smaller than the\nsave you are going to\nwrite. Please insert a\ndifferent game.\n\nPress A when done.");
|
||||
ADD_STRING(STR_HW_PLEASE_REBOOT,"Done! Please power off\n(and restart if you want\nto do more).");
|
||||
//
|
||||
ADD_STRING(STR_HW_SELECT_FILE,"Please select a .sav file.");
|
||||
ADD_STRING(STR_HW_SELECT_FILE_OW,"Please select a file to\noverwrite, or press L+R in afolder to create a new file.");
|
||||
|
|
@ -87,10 +95,25 @@ bool stringsLoadFile(const char *fname)
|
|||
ADD_STRING(STR_HW_3IN1_PLEASE_REBOOT,"Save has been written to\nthe 3in1. Please power off\nand restart this tool.");
|
||||
ADD_STRING(STR_HW_3IN1_CLEAR_FLAG,"Preparing to dump your\nsave... Please wait...");
|
||||
ADD_STRING(STR_HW_3IN1_DUMP,"Dumping the save from the\n3in1 to your flash card.\nFilename:\n%s");
|
||||
ADD_STRING(STR_HW_3IN1_DONE_DUMP,"Done. Your game save has\nbeen dumped using your\n3in1. Filename:\n%s\n\nPlease restart your DS.");
|
||||
ADD_STRING(STR_HW_3IN1_DONE_DUMP,"Done. Your game save has\nbeen dumped using your\n3in1. Filename:\n%s\n\nPress (B) to continue.");
|
||||
ADD_STRING(STR_HW_3IN1_RESTORE,"Done. Your game save has\nbeen restored using your\n3in1.\n\nPlease restart your DS.");
|
||||
ADD_STRING(STR_HW_3IN1_ERR_IDMODE,"ERROR!\nID mode still active!");
|
||||
ADD_STRING(STR_HW_3IN1_ERR_NOR,"ERROR!\nNOR memory seems to be\ndamaged!");
|
||||
//
|
||||
ADD_STRING(STR_HW_FTP_SEEK_AP,"Connecting to an access\npoint...\n\nplease wait...");
|
||||
ADD_STRING(STR_HW_FTP_ERR_AP,"ERROR!\nCould not find a compatible\nAccess Point. Please config\nyour WiFi Connection from\na WiFi-enabled game!");
|
||||
ADD_STRING(STR_HW_FTP_SEEK_FTP,"Connecting to an FTP\nserver...\n\nplease wait...");
|
||||
ADD_STRING(STR_HW_FTP_ERR_FTP,"ERROR!\nCould not find an FTP\nserver. Please refer to\nthe documentation.");
|
||||
ADD_STRING(STR_HW_FTP_LOGIN,"Logging in...");
|
||||
ADD_STRING(STR_HW_FTP_ERR_LOGIN,"ERROR!\nCould not log in to the\nFTP server. Please verify\nyour username and password\nare correct in your\nini file.");
|
||||
ADD_STRING(STR_HW_FTP_DIR,"Reading FTP directory...");
|
||||
ADD_STRING(STR_HW_FTP_SLOW,"FTP is slow, please wait...");
|
||||
ADD_STRING(STR_HW_FTP_READ_ONLY,"WARNING: could not write to\nyour FTP server! Maybe you\nforgot to enable write\naccess?");
|
||||
//
|
||||
ADD_STRING(STR_HW_GBA_READ,"Reading save from your game.Please wait...");
|
||||
ADD_STRING(STR_HW_GBA_DUMP,"Writing save to flash card.\nPlease wait...");
|
||||
ADD_STRING(STR_HW_GBA_LOAD,"Reading save from your\nflash card. Filename:\n%s\n\nPlease wait...");
|
||||
ADD_STRING(STR_HW_GBA_RESTORE,"Restoring save to your game\n\nPlease wait...");
|
||||
//
|
||||
ADD_STRING(STR_HW_WARN_DELETE,"This will WIPE OUT your\nentire save! ARE YOU SURE?\n\nPress R+up+Y to confim!");
|
||||
ADD_STRING(STR_HW_DID_DELETE,"Done. Your game save has\nbeen PERMANENTLY deleted.\n\nPlease restart your DS.");
|
||||
|
|
|
|||
|
|
@ -32,8 +32,13 @@
|
|||
|
||||
enum {
|
||||
STR_TITLE_MSG,
|
||||
STR_BOOT_NO_INI,
|
||||
STR_BOOT_MODE_UNSUPPORTED,
|
||||
STR_BOOT_DLDI_ERROR,
|
||||
//
|
||||
STR_HW_SWAP_CARD,
|
||||
STR_HW_WRONG_GAME,
|
||||
STR_HW_PLEASE_REBOOT,
|
||||
//
|
||||
STR_HW_SELECT_FILE,
|
||||
STR_HW_SELECT_FILE_OW,
|
||||
|
|
@ -51,8 +56,23 @@ enum {
|
|||
STR_HW_3IN1_DUMP,
|
||||
STR_HW_3IN1_DONE_DUMP,
|
||||
STR_HW_3IN1_RESTORE,
|
||||
STR_HW_3IN1_ERR_IDMODE,
|
||||
STR_HW_3IN1_ERR_NOR,
|
||||
//
|
||||
STR_HW_FTP_SEEK_AP,
|
||||
STR_HW_FTP_ERR_AP,
|
||||
STR_HW_FTP_SEEK_FTP,
|
||||
STR_HW_FTP_ERR_FTP,
|
||||
STR_HW_FTP_LOGIN,
|
||||
STR_HW_FTP_ERR_LOGIN,
|
||||
STR_HW_FTP_DIR,
|
||||
STR_HW_FTP_SLOW,
|
||||
STR_HW_FTP_READ_ONLY,
|
||||
//
|
||||
STR_HW_GBA_READ,
|
||||
STR_HW_GBA_DUMP,
|
||||
STR_HW_GBA_LOAD,
|
||||
STR_HW_GBA_RESTORE,
|
||||
//
|
||||
STR_HW_WARN_DELETE,
|
||||
STR_HW_DID_DELETE,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<pd><ViewState><e p="Savegame Manager\arm7" x="true"></e><e p="Savegame Manager\arm9" x="true"></e><e p="Savegame Manager" x="true"></e><e p="Savegame Manager\arm7\build" x="false"></e><e p="Savegame Manager\arm7\source" x="true"></e><e p="Savegame Manager\arm9\build" x="false"></e><e p="Savegame Manager\arm9\source" x="true"></e></ViewState></pd>
|
||||
<pd><ViewState><e p="Savegame Manager\arm7" x="false"></e><e p="Savegame Manager\arm9" x="true"></e><e p="Savegame Manager" x="true"></e><e p="Savegame Manager\arm9\build" x="false"></e><e p="Savegame Manager\arm9\source" x="true"></e></ViewState></pd>
|
||||
Loading…
Reference in New Issue
Block a user