- 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)
{
//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)
{
case 16:
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;
case 8:
switch(adr)
{
case 0:
T1WriteByte((u8*)&MMU.AUX_SPI_CNT, 0, val);
if (val == 0) slot1_device->auxspi_reset(proc);
break;
case 1:
T1WriteByte((u8*)&MMU.AUX_SPI_CNT, 1, val);
break;
}
T1WriteByte((u8*)&MMU.AUX_SPI_CNT, adr, val);
break;
}
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 (!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;
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;
}
}
@ -3788,7 +3785,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
}
case REG_AUXSPICNT:
write_auxspicnt(9, 16, 0, val);
write_auxspicnt(ARMCPU_ARM9, 16, 0, val);
return;
case REG_AUXSPIDATA:
@ -4835,7 +4832,7 @@ void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val)
case REG_AUXSPICNT:
case REG_AUXSPICNT+1:
write_auxspicnt(7, 8, adr & 1, val);
write_auxspicnt(ARMCPU_ARM7, 8, adr & 1, val);
return;
case REG_AUXSPIDATA:
@ -4946,7 +4943,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
case REG_AUXSPICNT:
write_auxspicnt(7, 16, 0, val);
write_auxspicnt(ARMCPU_ARM7, 16, 0, val);
return;
case REG_AUXSPIDATA:

View File

@ -26,7 +26,7 @@ Slot1Comp_MC g_Slot1Comp_MC;
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)
{

View File

@ -28,6 +28,7 @@
#include "NDSSystem.h"
#include "utils/advanscene.h"
//#define _ENABLE_MOTION
#define BM_CMD_AUTODETECT 0xFF
#define BM_CMD_WRITESTATUS 0x01
@ -106,7 +107,7 @@ void backup_setManualBackupType(int type)
bool BackupDevice::save_state(EMUFILE* os)
{
u32 version = 2;
u32 version = 3;
//v0
write32le(version,os);
write32le(write_enable,os);
@ -121,6 +122,8 @@ bool BackupDevice::save_state(EMUFILE* os)
//v2
write8le(motionInitState,os);
write8le(motionFlag,os);
//v3
writebool(reset_command_state,os);
return true;
}
@ -142,12 +145,18 @@ bool BackupDevice::load_state(EMUFILE* is)
}
if(version>=1)
read32le(&addr,is);
if(version>=2)
{
read8le(&motionInitState,is);
read8le(&motionFlag,is);
}
if(version>=3)
{
readbool(&reset_command_state,is);
}
return true;
}
@ -182,6 +191,7 @@ void BackupDevice::reset_hardware()
motionInitState = MOTION_INIT_STATE_IDLE;
motionFlag = MOTION_FLAG_NONE;
state = DETECTING;
reset_command_state = false;
flushPending = false;
lazyFlushPending = false;
}
@ -223,17 +233,9 @@ u8 BackupDevice::searchFileSaveType(u32 size)
return 0xFF;
}
void BackupDevice::reset_command()
void BackupDevice::detect()
{
//printf("MC RESET\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;
}
if (!reset_command_state) return;
if(state == DETECTING && data_autodetect.size()>0)
{
@ -285,13 +287,33 @@ void BackupDevice::reset_command()
data_autodetect.resize(0);
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)
{
//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
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;
}
#endif
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
data_autodetect.push_back(val);
val = 0;
detect();
}
else
{
@ -359,6 +383,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
}
addr++;
checkReset();
}
}
}
@ -366,6 +391,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
{
//handle request to read status
//LOG("Backup Memory Read Status: %02X\n", write_enable << 1);
checkReset();
return (write_enable << 1) | (3<<2);
}
else
@ -375,6 +401,7 @@ u8 BackupDevice::data_command(u8 val, int cpu)
{
case 0: break; //??
#ifdef _ENABLE_MOTION
case 0xFE:
if(motionInitState == MOTION_INIT_STATE_IDLE) { motionInitState = MOTION_INIT_STATE_FE; return 0; }
break;
@ -402,28 +429,36 @@ u8 BackupDevice::data_command(u8 val, int cpu)
return 0;
}
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);
val = 0xAA;
checkReset();
break;
case BM_CMD_WRITEDISABLE:
#ifdef _ENABLE_MOTION
switch(motionInitState)
{
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;
}
#endif
write_enable = FALSE;
checkReset();
break;
case BM_CMD_READSTATUS:
com = BM_CMD_READSTATUS;
val = (write_enable << 1) | (3<<2);
checkReset();
break;
case BM_CMD_WRITEENABLE:
write_enable = TRUE;
checkReset();
break;
case BM_CMD_WRITELOW:
@ -456,8 +491,10 @@ u8 BackupDevice::data_command(u8 val, int cpu)
break;
} //switch(val)
#ifdef _ENABLE_MOTION
//motion control state machine broke, return to ground
motionInitState = MOTION_INIT_STATE_IDLE;
#endif
}
return val;
}

View File

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