- more accurate emulation of backup chips (add emulation aux HOLD bit);
This commit is contained in:
mtabachenko 2013-10-20 12:20:44 +00:00
parent 22f814672d
commit 3dc14e59da
4 changed files with 77 additions and 38 deletions

View File

@ -2460,30 +2460,27 @@ u32 DmaController::read32()
static INLINE void write_auxspicnt(const int proc, const int size, const int adr, const int val) static INLINE void write_auxspicnt(const int proc, const int size, const int adr, const int val)
{ {
//why val==0 to reset? is it a particular bit? its not bit 6... //u16 oldCnt = MMU.AUX_SPI_CNT;
bool csOld = (MMU.AUX_SPI_CNT & (1 << 6))?true:false;
switch(size) switch(size)
{ {
case 16: case 16:
MMU.AUX_SPI_CNT = val; MMU.AUX_SPI_CNT = val;
if (val == 0)
{
//you know.. its strange. according to gbatek, this should get cleared before the last transfer.
//we've got it coded in such a way that it sort of terminates the transfer (is it getting reset immediately before a new transfer?)
slot1_device->auxspi_reset(proc);
}
break; break;
case 8: case 8:
switch(adr) T1WriteByte((u8*)&MMU.AUX_SPI_CNT, adr, val);
{ break;
case 0: }
T1WriteByte((u8*)&MMU.AUX_SPI_CNT, 0, val);
if (val == 0) slot1_device->auxspi_reset(proc); bool cs = (MMU.AUX_SPI_CNT & (1 << 6))?true:false;
break;
case 1: //printf("MMU%c: cnt %04X, old %04X\n", proc?'7':'9', MMU.AUX_SPI_CNT, oldCnt);
T1WriteByte((u8*)&MMU.AUX_SPI_CNT, 1, val);
break; if (!cs && csOld)
} {
//printf("MMU%c: CS changed from HIGH to LOW *****\n", proc?'7':'9');
slot1_device->auxspi_reset(proc);
} }
} }
@ -3115,7 +3112,7 @@ bool validateIORegsRead(u32 addr, u8 size)
return true; return true;
default: default:
//printf("MMU9 read%02d from undefined register %08Xh = %08Xh (PC:%08X)\n", size, addr, T1ReadLong(MMU.ARM9_REG, addr & 0x00FFFFFF), ARMPROC.instruct_adr); printf("MMU9 read%02d from undefined register %08Xh = %08Xh (PC:%08X)\n", size, addr, T1ReadLong(MMU.ARM9_REG, addr & 0x00FFFFFF), ARMPROC.instruct_adr);
return false; return false;
} }
} }
@ -3788,7 +3785,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
} }
case REG_AUXSPICNT: case REG_AUXSPICNT:
write_auxspicnt(9, 16, 0, val); write_auxspicnt(ARMCPU_ARM9, 16, 0, val);
return; return;
case REG_AUXSPIDATA: case REG_AUXSPIDATA:
@ -4835,7 +4832,7 @@ void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val)
case REG_AUXSPICNT: case REG_AUXSPICNT:
case REG_AUXSPICNT+1: case REG_AUXSPICNT+1:
write_auxspicnt(7, 8, adr & 1, val); write_auxspicnt(ARMCPU_ARM7, 8, adr & 1, val);
return; return;
case REG_AUXSPIDATA: case REG_AUXSPIDATA:
@ -4946,7 +4943,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
case REG_AUXSPICNT: case REG_AUXSPICNT:
write_auxspicnt(7, 16, 0, val); write_auxspicnt(ARMCPU_ARM7, 16, 0, val);
return; return;
case REG_AUXSPIDATA: case REG_AUXSPIDATA:

View File

@ -26,7 +26,7 @@ Slot1Comp_MC g_Slot1Comp_MC;
u8 Slot1Comp_MC::auxspi_transaction(int PROCNUM, u8 value) u8 Slot1Comp_MC::auxspi_transaction(int PROCNUM, u8 value)
{ {
return MMU_new.backupDevice.data_command((u8)value,ARMCPU_ARM9); return MMU_new.backupDevice.data_command(value, PROCNUM);
} }
void Slot1Comp_MC::auxspi_reset(int PROCNUM) void Slot1Comp_MC::auxspi_reset(int PROCNUM)
{ {

View File

@ -28,6 +28,7 @@
#include "NDSSystem.h" #include "NDSSystem.h"
#include "utils/advanscene.h" #include "utils/advanscene.h"
//#define _ENABLE_MOTION
#define BM_CMD_AUTODETECT 0xFF #define BM_CMD_AUTODETECT 0xFF
#define BM_CMD_WRITESTATUS 0x01 #define BM_CMD_WRITESTATUS 0x01
@ -106,7 +107,7 @@ void backup_setManualBackupType(int type)
bool BackupDevice::save_state(EMUFILE* os) bool BackupDevice::save_state(EMUFILE* os)
{ {
u32 version = 2; u32 version = 3;
//v0 //v0
write32le(version,os); write32le(version,os);
write32le(write_enable,os); write32le(write_enable,os);
@ -121,6 +122,8 @@ bool BackupDevice::save_state(EMUFILE* os)
//v2 //v2
write8le(motionInitState,os); write8le(motionInitState,os);
write8le(motionFlag,os); write8le(motionFlag,os);
//v3
writebool(reset_command_state,os);
return true; return true;
} }
@ -142,12 +145,18 @@ bool BackupDevice::load_state(EMUFILE* is)
} }
if(version>=1) if(version>=1)
read32le(&addr,is); read32le(&addr,is);
if(version>=2) if(version>=2)
{ {
read8le(&motionInitState,is); read8le(&motionInitState,is);
read8le(&motionFlag,is); read8le(&motionFlag,is);
} }
if(version>=3)
{
readbool(&reset_command_state,is);
}
return true; return true;
} }
@ -182,6 +191,7 @@ void BackupDevice::reset_hardware()
motionInitState = MOTION_INIT_STATE_IDLE; motionInitState = MOTION_INIT_STATE_IDLE;
motionFlag = MOTION_FLAG_NONE; motionFlag = MOTION_FLAG_NONE;
state = DETECTING; state = DETECTING;
reset_command_state = false;
flushPending = false; flushPending = false;
lazyFlushPending = false; lazyFlushPending = false;
} }
@ -223,17 +233,9 @@ u8 BackupDevice::searchFileSaveType(u32 size)
return 0xFF; return 0xFF;
} }
void BackupDevice::reset_command() void BackupDevice::detect()
{ {
//printf("MC RESET\n"); if (!reset_command_state) return;
//for a performance hack, save files are only flushed after each reset command
//(hopefully, after each page)
if(flushPending)
{
flush();
flushPending = false;
lazyFlushPending = false;
}
if(state == DETECTING && data_autodetect.size()>0) if(state == DETECTING && data_autodetect.size()>0)
{ {
@ -285,13 +287,33 @@ void BackupDevice::reset_command()
data_autodetect.resize(0); data_autodetect.resize(0);
flush(); flush();
} }
com = 0;
} }
void BackupDevice::checkReset()
{
if (reset_command_state)
{
//printf("MC : reset command\n");
//for a performance hack, save files are only flushed after each reset command
//(hopefully, after each page)
if(flushPending)
{
flush();
flushPending = false;
lazyFlushPending = false;
}
com = 0;
reset_command_state = false;
}
}
u8 BackupDevice::data_command(u8 val, int cpu) u8 BackupDevice::data_command(u8 val, int cpu)
{ {
//printf("MC CMD: (%02X) %02X\n",com,val); //printf("MC%c : cmd %02X, val %02X\n", cpu?'7':'9', com, val);
#ifdef _ENABLE_MOTION
//motion: some guessing here... hope it doesn't break anything //motion: some guessing here... hope it doesn't break anything
if(com == BM_CMD_READLOW && motionInitState == MOTION_INIT_STATE_RECEIVED_4_B && val == 0) if(com == BM_CMD_READLOW && motionInitState == MOTION_INIT_STATE_RECEIVED_4_B && val == 0)
{ {
@ -306,6 +328,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
{ {
return 0; return 0;
} }
#endif
if(com == BM_CMD_READLOW || com == BM_CMD_WRITELOW) if(com == BM_CMD_READLOW || com == BM_CMD_WRITELOW)
{ {
@ -320,6 +343,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
//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; val = 0;
detect();
} }
else else
{ {
@ -359,6 +383,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
} }
addr++; addr++;
checkReset();
} }
} }
} }
@ -366,6 +391,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
{ {
//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);
checkReset();
return (write_enable << 1) | (3<<2); return (write_enable << 1) | (3<<2);
} }
else else
@ -375,6 +401,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
{ {
case 0: break; //?? case 0: break; //??
#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;
@ -402,28 +429,36 @@ u8 BackupDevice::data_command(u8 val, int cpu)
return 0; return 0;
} }
break; break;
#endif
case 8: case 0x08: // IrDA - Pokemon HG/SS
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("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);
val = 0xAA; val = 0xAA;
checkReset();
break; break;
case BM_CMD_WRITEDISABLE: case BM_CMD_WRITEDISABLE:
#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
write_enable = FALSE; write_enable = FALSE;
checkReset();
break; break;
case BM_CMD_READSTATUS: case BM_CMD_READSTATUS:
com = BM_CMD_READSTATUS; com = BM_CMD_READSTATUS;
val = (write_enable << 1) | (3<<2); val = (write_enable << 1) | (3<<2);
checkReset();
break; 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:
@ -456,8 +491,10 @@ u8 BackupDevice::data_command(u8 val, int cpu)
break; break;
} //switch(val) } //switch(val)
#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
} }
return val; return val;
} }

View File

@ -76,7 +76,7 @@ public:
bool load_state(EMUFILE* is); bool load_state(EMUFILE* is);
//commands from mmu //commands from mmu
void reset_command(); void reset_command() { reset_command_state = true; };
u8 data_command(u8,int); u8 data_command(u8,int);
std::vector<u8> data; std::vector<u8> data;
@ -123,9 +123,12 @@ public:
bool isMovieMode; bool isMovieMode;
private: private:
void detect();
std::string filename; std::string filename;
bool write_enable; //is write enabled? bool write_enable; //is write enabled?
bool reset_command_state;
u32 com; //persistent command actually handled u32 com; //persistent command actually handled
u32 addr_size, addr_counter; u32 addr_size, addr_counter;
u32 addr; u32 addr;
@ -155,6 +158,8 @@ private:
void resize(u32 size); void resize(u32 size);
void resize(u32 size, u8 val); void resize(u32 size, u8 val);
void checkReset();
}; };