u64 FileMemoryCard::GetCRC( uint slot ) { wxFFile& mcfp( m_file[slot] ); if( !mcfp.IsOpened() ) return 0; u64 retval = 0; if(m_ispsx[slot]) { if( !Seek( mcfp, 0 ) ) return 0; // Process the file in 4k chunks. Speeds things up significantly. u64 buffer[528*8]; // use 528 (sector size), ensures even divisibility const uint filesize = mcfp.Length() / sizeof(buffer); for( uint i=filesize; i; --i ) { mcfp.Read( &buffer, sizeof(buffer) ); for( uint t=0; t<ArraySize(buffer); ++t ) retval ^= buffer[t]; } } else { retval = m_chksum[slot]; } return retval; }
s32 FileMemoryCard::Read( uint slot, u8 *dest, u32 adr, int size ) { wxFFile& mcfp( m_file[slot] ); if( !mcfp.IsOpened() ) { DevCon.Error( "(FileMcd) Ignoring attempted read from disabled slot." ); memset(dest, 0, size); return 1; } if( !Seek(mcfp, adr) ) return 0; return mcfp.Read( dest, size ) != 0; }
s32 FileMemoryCard::EraseBlock( uint slot, u32 adr ) { wxFFile& mcfp( m_file[slot] ); if( !mcfp.IsOpened() ) { DevCon.Error( "MemoryCard: Ignoring erase for disabled slot." ); return 1; } if( !Seek(mcfp, adr) ) return 0; return mcfp.Write( m_effeffs, sizeof(m_effeffs) ) != 0; }
s32 FileMemoryCard::Save( uint slot, const u8 *src, u32 adr, int size ) { wxFFile& mcfp( m_file[slot] ); if( !mcfp.IsOpened() ) { DevCon.Error( "(FileMcd) Ignoring attempted save/write to disabled slot." ); return 1; } if(m_ispsx[slot]) { m_currentdata.MakeRoomFor( size ); for (int i=0; i<size; i++) m_currentdata[i] = src[i]; } else { if( !Seek(mcfp, adr) ) return 0; m_currentdata.MakeRoomFor( size ); mcfp.Read( m_currentdata.GetPtr(), size); for (int i=0; i<size; i++) { if ((m_currentdata[i] & src[i]) != src[i]) Console.Warning("(FileMcd) Warning: writing to uncleared data. (%d) [%08X]", slot, adr); m_currentdata[i] &= src[i]; } // Checksumness { if(adr == m_chkaddr) Console.Warning("(FileMcd) Warning: checksum sector overwritten. (%d)", slot); u64 *pdata = (u64*)&m_currentdata[0]; u32 loops = size / 8; for(u32 i = 0; i < loops; i++) m_chksum[slot] ^= pdata[i]; } } if( !Seek(mcfp, adr) ) return 0; return mcfp.Write( m_currentdata.GetPtr(), size ) != 0; }
s32 FileMemoryCard::Save( uint slot, const u8 *src, u32 adr, int size ) { wxFFile& mcfp( m_file[slot] ); if( !mcfp.IsOpened() ) { DevCon.Error( "(FileMcd) Ignoring attempted save/write to disabled slot." ); return 1; } if(m_ispsx[slot]) { m_currentdata.MakeRoomFor( size ); for (int i=0; i<size; i++) m_currentdata[i] = src[i]; } else { if( !Seek(mcfp, adr) ) return 0; m_currentdata.MakeRoomFor( size ); mcfp.Read( m_currentdata.GetPtr(), size); for (int i=0; i<size; i++) { if ((m_currentdata[i] & src[i]) != src[i]) Console.Warning("(FileMcd) Warning: writing to uncleared data. (%d) [%08X]", slot, adr); m_currentdata[i] &= src[i]; } // Checksumness { if(adr == m_chkaddr) Console.Warning("(FileMcd) Warning: checksum sector overwritten. (%d)", slot); u64 *pdata = (u64*)&m_currentdata[0]; u32 loops = size / 8; for(u32 i = 0; i < loops; i++) m_chksum[slot] ^= pdata[i]; } } if( !Seek(mcfp, adr) ) return 0; int status = mcfp.Write( m_currentdata.GetPtr(), size ); if( status ) { static auto last = std::chrono::time_point<std::chrono::system_clock>(); std::chrono::duration<float> elapsed = std::chrono::system_clock::now() - last; if(elapsed > std::chrono::seconds(5)) { wxString name, ext; wxFileName::SplitPath(m_file[slot].GetName(), NULL, NULL, &name, &ext); OSDlog( Color_StrongYellow, false, "Memory Card %s written.", (const char *)(name + "." + ext).c_str() ); last = std::chrono::system_clock::now(); } return 1; } return 0; }