- more work on backup memory handler (not finished yet, i'll be finished this coming soon);
This commit is contained in:
mtabachenko 2013-10-25 18:58:48 +00:00
parent 4ce78d5e49
commit 3384b93c4a
3 changed files with 194 additions and 174 deletions

View File

@ -2458,8 +2458,9 @@ u32 DmaController::read32()
return ret; return ret;
} }
static INLINE void write_auxspicnt(const int proc, const int size, const int adr, const int val) static INLINE void write_auxspicnt(const int PROCNUM, const int size, const int adr, const int val)
{ {
//u16 oldCnt = MMU.AUX_SPI_CNT;
bool csOld = (MMU.AUX_SPI_CNT & (1 << 6))?true:false; bool csOld = (MMU.AUX_SPI_CNT & (1 << 6))?true:false;
switch(size) switch(size)
@ -2474,16 +2475,13 @@ static INLINE void write_auxspicnt(const int proc, const int size, const int adr
bool cs = (MMU.AUX_SPI_CNT & (1 << 6))?true:false; bool cs = (MMU.AUX_SPI_CNT & (1 << 6))?true:false;
//printf("MMU%c: cnt %04X, old %04X\n", proc?'7':'9', MMU.AUX_SPI_CNT, oldCnt);
if (MMU.AUX_SPI_CNT == 0)
MMU_new.backupDevice.reset_command(false);
if (!cs && csOld) if (!cs && csOld)
{ {
//printf("MMU%c: CS changed from HIGH to LOW *****\n", proc?'7':'9'); //printf("MMU%c: CS changed from HIGH to LOW *****\n", PROCNUM?'7':'9');
slot1_device->auxspi_reset(proc); slot1_device->auxspi_reset(PROCNUM);
} }
//printf("MMU%c: cnt %04X, old %04X\n", PROCNUM?'7':'9', MMU.AUX_SPI_CNT, oldCnt);
} }
template <u8 PROCNUM> template <u8 PROCNUM>

View File

@ -28,23 +28,31 @@
#include "NDSSystem.h" #include "NDSSystem.h"
#include "utils/advanscene.h" #include "utils/advanscene.h"
//#define _NO_LOAD_BACKUP
//#define _NO_SAVE_BACKUP
// TODO: motion device was broken
//#define _ENABLE_MOTION //#define _ENABLE_MOTION
#define BM_CMD_AUTODETECT 0xFF #define BM_CMD_NOP 0x00
#define BM_CMD_WRITESTATUS 0x01 #define BM_CMD_AUTODETECT 0xFF
#define BM_CMD_WRITELOW 0x02 #define BM_CMD_WRITESTATUS 0x01
#define BM_CMD_READLOW 0x03 #define BM_CMD_WRITELOW 0x02
#define BM_CMD_WRITEDISABLE 0x04 #define BM_CMD_READLOW 0x03
#define BM_CMD_READSTATUS 0x05 #define BM_CMD_WRITEDISABLE 0x04
#define BM_CMD_WRITEENABLE 0x06 #define BM_CMD_READSTATUS 0x05
#define BM_CMD_WRITEHIGH 0x0A #define BM_CMD_WRITEENABLE 0x06
#define BM_CMD_READHIGH 0x0B #define BM_CMD_WRITEHIGH 0x0A
#define BM_CMD_READHIGH 0x0B
// Pokemons IrDA
#define BM_CMD_IRDA 0x08
//FLASH //FLASH
#define COMM_PAGE_WRITE 0x0A #define COMM_PAGE_WRITE 0x0A
#define COMM_PAGE_ERASE 0xDB #define COMM_PAGE_ERASE 0xDB
#define COMM_SECTOR_ERASE 0xD8 #define COMM_SECTOR_ERASE 0xD8
#define COMM_CHIP_ERASE 0xC7 #define COMM_CHIP_ERASE 0xC7
#define CARDFLASH_READ_BYTES_FAST 0x0B /* Not used*/ #define CARDFLASH_READ_BYTES_FAST 0x0B /* Not used*/
#define CARDFLASH_DEEP_POWDOWN 0xB9 /* Not used*/ #define CARDFLASH_DEEP_POWDOWN 0xB9 /* Not used*/
#define CARDFLASH_WAKEUP 0xAB /* Not used*/ #define CARDFLASH_WAKEUP 0xAB /* Not used*/
@ -250,13 +258,7 @@ void BackupDevice::detect()
case 0: case 0:
case 1: case 1:
addr_size = 1; //choose 1 just to keep the busted savefile from growing too big addr_size = 1; //choose 1 just to keep the busted savefile from growing too big
msgbox->error("Catastrophic error while autodetecting save type.\nIt will need to be specified manually\n");
if(!memcmp(gameInfo.header.gameCode,"AL3", 3)) break; //spongebob atlantis squarepantis.
if(!memcmp(gameInfo.header.gameCode,"AVH", 3)) break; //over the hedge - Hammy Goes Nuts!
if(!memcmp(gameInfo.header.gameCode,"AQ3", 3)) break; //spider-man 3
printf("Catastrophic error while autodetecting save type.\nIt will need to be specified manually\n");
//msgbox->error("Catastrophic error while autodetecting save type.\nIt will need to be specified manually\n");
break; break;
case 2: case 2:
//the modern typical case for small eeproms //the modern typical case for small eeproms
@ -268,8 +270,13 @@ void BackupDevice::detect()
//(the archaic 1+2 case is: specifying one address byte, and then reading the first two bytes, instead of the first one byte, as most other games would do.) //(the archaic 1+2 case is: specifying one address byte, and then reading the first two bytes, instead of the first one byte, as most other games would do.)
//so, we're gonna hack in checks for the games that are doing this //so, we're gonna hack in checks for the games that are doing this
addr_size = 2; addr_size = 2;
if(!memcmp(gameInfo.header.gameCode,"AH5", 3)) addr_size = 1; //over the hedge
// TODO: will study a deep, why this happens (wrong detect size)
if(!memcmp(gameInfo.header.gameCode,"AL3", 3)) addr_size = 1; //spongebob atlantis squarepantis.
if(!memcmp(gameInfo.header.gameCode,"AH5", 3)) addr_size = 1; //over the hedge
if(!memcmp(gameInfo.header.gameCode,"AVH", 3)) addr_size = 1; //over the hedge - Hammy Goes Nuts!
if(!memcmp(gameInfo.header.gameCode,"AQ3", 3)) addr_size = 1; //spider-man 3
break; break;
case 4: case 4:
//a modern typical case //a modern typical case
@ -279,9 +286,11 @@ void BackupDevice::detect()
default: default:
//the archaic case: write the address and then some modulo-4 number of bytes //the archaic case: write the address and then some modulo-4 number of bytes
//why modulo 4? who knows. //why modulo 4? who knows.
if(!memcmp(gameInfo.header.gameCode,"BDE", 3)) { addr_size = 2; break; } // Dementium II
//SM64 (KOR) makes it here with autodetect_size=11 and nothing interesting in the buffer //SM64 (KOR) makes it here with autodetect_size=11 and nothing interesting in the buffer
addr_size = autodetect_size & 3; addr_size = autodetect_size & 3;
if(!memcmp(gameInfo.header.gameCode,"BDE", 3)) addr_size = 2; // Dementium II
break; break;
} }
@ -311,9 +320,9 @@ void BackupDevice::checkReset()
} }
} }
u8 BackupDevice::data_command(u8 val, int cpu) u8 BackupDevice::data_command(u8 val, u8 PROCNUM)
{ {
//printf("MC%c : cmd %02X, val %02X\n", cpu?'7':'9', com, val); //printf("MC%c : cmd %02X, val %02X\n", PROCNUM?'7':'9', com, val);
#ifdef _ENABLE_MOTION #ifdef _ENABLE_MOTION
//motion: some guessing here... hope it doesn't break anything //motion: some guessing here... hope it doesn't break anything
@ -332,172 +341,177 @@ u8 BackupDevice::data_command(u8 val, int cpu)
} }
#endif #endif
if(com == BM_CMD_READLOW || com == BM_CMD_WRITELOW) switch (com)
{ {
//handle data or address case BM_CMD_READLOW:
if(state == DETECTING) case BM_CMD_WRITELOW:
{ //handle data or address
if(com == BM_CMD_WRITELOW) if(state == DETECTING)
{ {
printf("Unexpected backup device initialization sequence using writes!\n"); if(com == BM_CMD_WRITELOW)
} printf("MC%c: Unexpected backup device initialization sequence using writes!\n", PROCNUM?'7':'9');
//just buffer the data until we're no longer detecting //just buffer the data until we're no longer detecting
data_autodetect.push_back(val); data_autodetect.push_back(val);
val = 0; detect();
detect(); val = 0xFF;
}
else
{
if(addr_counter<addr_size)
{
//continue building address
addr <<= 8;
addr |= val;
addr_counter++;
//if(addr_counter==addr_size) printf("ADR: %08X\n",addr);
} }
else else
{ {
//why does tomb raider underworld access 0x180 and go clear through to 0x280? if(addr_counter<addr_size)
//should this wrap around at 0 or at 0x100?
if(addr_size == 1) addr &= 0x1FF;
//address is complete
ensure(addr+1);
if(com == BM_CMD_READLOW)
{ {
//printf("READ ADR: %08X\n",addr); //continue building address
val = data[addr]; addr <<= 8;
//flushPending = true; //is this a good idea? it may slow stuff down, but it is helpful for debugging addr |= val;
lazyFlushPending = true; //lets do this instead addr_counter++;
//printf("read: %08X\n",addr); val = 0xFF;
} }
else else
{ {
if(write_enable) //why does tomb raider underworld access 0x180 and go clear through to 0x280?
//should this wrap around at 0 or at 0x100?
if(addr_size == 1) addr &= 0x1FF;
//address is complete
ensure(addr+1);
if(com == BM_CMD_READLOW)
{ {
//printf("WRITE ADR: %08X\n",addr); val = data[addr];
data[addr] = val; //flushPending = true; //is this a good idea? it may slow stuff down, but it is helpful for debugging
flushPending = true; lazyFlushPending = true; //lets do this instead
//printf("writ: %08X\n",addr); //printf("MC%c: read from %08X, value %02Xh\n", PROCNUM?'7':'9', addr, val);
} }
} else
addr++; if(write_enable)
{
data[addr] = val;
flushPending = true;
//printf("MC%c: write to %08X, value %02Xh\n", PROCNUM?'7':'9', addr, val);
}
checkReset(); addr++;
}
} }
} break;
}
else if(com == BM_CMD_READSTATUS) case BM_CMD_READSTATUS:
{ //handle request to read status
//handle request to read status //LOG("Backup Memory Read Status: %02X\n", write_enable << 1);
//LOG("Backup Memory Read Status: %02X\n", write_enable << 1); val = (write_enable << 1) | (3<<2);
checkReset(); break;
return (write_enable << 1) | (3<<2);
}
else
{
//there is no current command. receive one
switch(val)
{
case 0: break; //??
case BM_CMD_IRDA:
printf("MC%c: Unverified Backup Memory command: %02X FROM %08X\n", PROCNUM?'7':'9', com, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr);
val = 0xAA;
break;
default:
if (com != 0)
{
//printf("MC%c: Unhandled Backup Memory command %02X, value %02X (PC:%08X)\n", PROCNUM?'7':'9', com, val, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr);
break;
}
com = val;
//there is no current command. receive one
switch (com)
{
case BM_CMD_NOP: break;
#ifdef _ENABLE_MOTION #ifdef _ENABLE_MOTION
case 0xFE: case 0xFE:
if(motionInitState == MOTION_INIT_STATE_IDLE) { motionInitState = MOTION_INIT_STATE_FE; return 0; } if(motionInitState == MOTION_INIT_STATE_IDLE) { motionInitState = MOTION_INIT_STATE_FE; return 0; }
break; break;
case 0xFD: case 0xFD:
if(motionInitState == MOTION_INIT_STATE_FE) { motionInitState = MOTION_INIT_STATE_FD; return 0; } if(motionInitState == MOTION_INIT_STATE_FE) { motionInitState = MOTION_INIT_STATE_FD; return 0; }
break; break;
case 0xFB: case 0xFB:
if(motionInitState == MOTION_INIT_STATE_FD) { motionInitState = MOTION_INIT_STATE_FB; return 0; } if(motionInitState == MOTION_INIT_STATE_FD) { motionInitState = MOTION_INIT_STATE_FB; return 0; }
break; break;
case 0xF8: case 0xF8:
//enable sensor mode //enable sensor mode
if(motionInitState == MOTION_INIT_STATE_FD) if(motionInitState == MOTION_INIT_STATE_FD)
{ {
motionInitState = MOTION_INIT_STATE_IDLE; motionInitState = MOTION_INIT_STATE_IDLE;
motionFlag |= MOTION_FLAG_SENSORMODE; motionFlag |= MOTION_FLAG_SENSORMODE;
return 0; return 0;
} }
break; break;
case 0xF9: case 0xF9:
//disable sensor mode //disable sensor mode
if(motionInitState == MOTION_INIT_STATE_FD) if(motionInitState == MOTION_INIT_STATE_FD)
{ {
motionInitState = MOTION_INIT_STATE_IDLE; motionInitState = MOTION_INIT_STATE_IDLE;
motionFlag &= ~MOTION_FLAG_SENSORMODE; motionFlag &= ~MOTION_FLAG_SENSORMODE;
return 0; return 0;
} }
break; break;
#endif #endif
case 0x08: // IrDA - Pokemon HG/SS case BM_CMD_IRDA:
printf("COMMAND%c: Unverified Backup Memory command: %02X FROM %08X\n",(cpu==ARMCPU_ARM9)?'9':'7',val, (cpu==ARMCPU_ARM9)?NDS_ARM9.instruct_adr:NDS_ARM7.instruct_adr); printf("MC%c: Unverified Backup Memory command: %02X FROM %08X\n", PROCNUM?'7':'9', com, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr);
val = 0xAA;
val = 0xAA;
break;
checkReset(); case BM_CMD_WRITEDISABLE:
break;
case BM_CMD_WRITEDISABLE:
#ifdef _ENABLE_MOTION #ifdef _ENABLE_MOTION
switch(motionInitState) switch (motionInitState)
{ {
case MOTION_INIT_STATE_IDLE: motionInitState = MOTION_INIT_STATE_RECEIVED_4; break; case MOTION_INIT_STATE_IDLE: motionInitState = MOTION_INIT_STATE_RECEIVED_4; break;
case MOTION_INIT_STATE_RECEIVED_4: motionInitState = MOTION_INIT_STATE_RECEIVED_4_B; break; case MOTION_INIT_STATE_RECEIVED_4: motionInitState = MOTION_INIT_STATE_RECEIVED_4_B; break;
} }
#endif #endif
write_enable = FALSE; write_enable = FALSE;
checkReset(); break;
break;
case BM_CMD_READSTATUS:
case BM_CMD_READSTATUS: //val = (write_enable << 1) | (3<<2);
com = BM_CMD_READSTATUS; val = 0xFF;
val = (write_enable << 1) | (3<<2); break;
checkReset();
break;
case BM_CMD_WRITEENABLE: case BM_CMD_WRITEENABLE:
write_enable = TRUE; write_enable = TRUE;
checkReset(); break;
break;
case BM_CMD_WRITELOW: case BM_CMD_WRITELOW:
case BM_CMD_READLOW: case BM_CMD_READLOW:
//printf("XLO: %08X\n",addr); //printf("XLO: %08X\n",addr);
com = val; addr_counter = 0;
addr_counter = 0; addr = 0;
addr = 0; val = 0xFF;
break; break;
case BM_CMD_WRITEHIGH: case BM_CMD_WRITEHIGH:
case BM_CMD_READHIGH: case BM_CMD_READHIGH:
//printf("XHI: %08X\n",addr); //printf("XHI: %08X\n",addr);
if(val == BM_CMD_WRITEHIGH) val = BM_CMD_WRITELOW; if(val == BM_CMD_WRITEHIGH) com = BM_CMD_WRITELOW;
if(val == BM_CMD_READHIGH) val = BM_CMD_READLOW; if(val == BM_CMD_READHIGH) com = BM_CMD_READLOW;
com = val; addr_counter = 0;
addr_counter = 0; addr = 0;
addr = 0; if(addr_size==1)
if(addr_size==1) { {
//"write command that's only available on ST M95040-W that I know of" //"write command that's only available on ST M95040-W that I know of"
//this makes sense, since this device would only have a 256 bytes address space with writelow //this makes sense, since this device would only have a 256 bytes address space with writelow
//and writehigh would allow access to the upper 256 bytes //and writehigh would allow access to the upper 256 bytes
//but it was detected in pokemon diamond also during the main save process //but it was detected in pokemon diamond also during the main save process
addr = 0x1; addr = 0x1;
} }
break; break;
default: default:
printf("COMMAND%c: Unhandled Backup Memory command: %02X FROM %08X\n",(cpu==ARMCPU_ARM9)?'9':'7',val, (cpu==ARMCPU_ARM9)?NDS_ARM9.instruct_adr:NDS_ARM7.instruct_adr); printf("MC%c: Unhandled Backup Memory command: %02X FROM %08X\n", PROCNUM?'7':'9', val, PROCNUM?NDS_ARM7.instruct_adr:NDS_ARM9.instruct_adr);
break; break;
} //switch(val) } //switch(val)
break;
} //switch (com)
#ifdef _ENABLE_MOTION #ifdef _ENABLE_MOTION
//motion control state machine broke, return to ground //motion control state machine broke, return to ground
motionInitState = MOTION_INIT_STATE_IDLE; motionInitState = MOTION_INIT_STATE_IDLE;
#endif #endif
}
checkReset();
return val; return val;
} }
@ -812,6 +826,10 @@ void BackupDevice::loadfile()
if(isMovieMode) return; if(isMovieMode) return;
if(filename.length() ==0) return; //No sense crashing if no filename supplied if(filename.length() ==0) return; //No sense crashing if no filename supplied
#ifdef _NO_LOAD_BACKUP
return;
#endif
EMUFILE_FILE* inf = new EMUFILE_FILE(filename.c_str(),"rb"); EMUFILE_FILE* inf = new EMUFILE_FILE(filename.c_str(),"rb");
if(inf->fail()) if(inf->fail())
{ {
@ -963,6 +981,10 @@ void BackupDevice::flush()
//never use save files if we are in movie mode //never use save files if we are in movie mode
if(isMovieMode) return; if(isMovieMode) return;
#ifdef _NO_SAVE_BACKUP
return;
#endif
if (filename.length() == 0) return; if (filename.length() == 0) return;
EMUFILE* outf = new EMUFILE_FILE(filename.c_str(),"wb"); EMUFILE* outf = new EMUFILE_FILE(filename.c_str(),"wb");

View File

@ -76,8 +76,8 @@ public:
bool load_state(EMUFILE* is); bool load_state(EMUFILE* is);
//commands from mmu //commands from mmu
void reset_command(bool state = true) { reset_command_state = state; }; void reset_command() { reset_command_state = true; };
u8 data_command(u8,int); u8 data_command(u8, u8);
std::vector<u8> data; std::vector<u8> data;
//this info was saved before the last reset (used for savestate compatibility) //this info was saved before the last reset (used for savestate compatibility)