From 74a4ecd559e1481e65ddc93e2b33ac8c424b17af Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Wed, 26 May 2010 19:45:33 +0000 Subject: [PATCH] Completed support for various MemoryCard sizes (16, 32, 64 megs cards). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3084 96395faa-99c1-11dd-bbfe-3dabce05a288 --- common/include/PluginCallbacks.h | 21 +++++++++ pcsx2/PluginManager.cpp | 6 +++ pcsx2/Plugins.h | 1 + pcsx2/Sio.cpp | 59 +++++++++++++++++++----- pcsx2/gui/AppMain.cpp | 2 +- pcsx2/gui/MemoryCardFile.cpp | 28 +++++++++-- pcsx2/gui/Panels/MemoryCardListPanel.cpp | 8 +++- pcsx2/gui/Panels/MemoryCardListView.cpp | 2 +- pcsx2/gui/Panels/SpeedhacksPanel.cpp | 4 +- pcsx2/sio_internal.h | 12 ++--- 10 files changed, 115 insertions(+), 28 deletions(-) diff --git a/common/include/PluginCallbacks.h b/common/include/PluginCallbacks.h index 39c316cfe2..ccb3159b3a 100644 --- a/common/include/PluginCallbacks.h +++ b/common/include/PluginCallbacks.h @@ -1013,6 +1013,17 @@ typedef struct _PS2E_ComponentAPI_GS } PS2E_ComponentAPI_GS; + +// -------------------------------------------------------------------------------------- +// PS2E_McdSizeInfo +// -------------------------------------------------------------------------------------- +struct PS2E_McdSizeInfo +{ + u16 SectorSize; // Size of each sector, in bytes. (only 512 and 1024 are valid) + u16 EraseBlockSizeInSectors; // Size of the erase block, in sectors (max is 16) + u32 McdSizeInSectors; // Total size of the card, in sectors (no upper limit) +}; + // -------------------------------------------------------------------------------------- // PS2E_ComponentAPI_Mcd // -------------------------------------------------------------------------------------- @@ -1037,6 +1048,16 @@ typedef struct _PS2E_ComponentAPI_Mcd // BOOL (PS2E_CALLBACK* McdIsPresent)( PS2E_THISPTR thisptr, uint port, uint slot ); + // McdGetSectorSize (can be NULL) + // Requests memorycard formatting information from the Mcd provider. See the description of + // PS2E_McdSizeInfo for details on each field. If the Mcd provider supports only standard 8MB + // carts, then this function can be NULL. + // + // Returns: + // Assigned values for memorycard sector size and sector count in 'outways.' + // + void (PS2E_CALLBACK* McdGetSizeInfo)( PS2E_THISPTR thisptr, uint port, uint slot, PS2E_McdSizeInfo* outways ); + // McdRead // Requests that a block of data be loaded from the memorycard into the specified dest // buffer (which is allocated by the caller). Bytes read should match the requested diff --git a/pcsx2/PluginManager.cpp b/pcsx2/PluginManager.cpp index b81d0ff503..74b820b886 100644 --- a/pcsx2/PluginManager.cpp +++ b/pcsx2/PluginManager.cpp @@ -36,6 +36,12 @@ bool SysPluginBindings::McdIsPresent( uint port, uint slot ) return !!Mcd->McdIsPresent( (PS2E_THISPTR) Mcd, port, slot ); } +void SysPluginBindings::McdGetSizeInfo( uint port, uint slot, PS2E_McdSizeInfo& outways ) +{ + if( Mcd->McdGetSizeInfo ) + Mcd->McdGetSizeInfo( (PS2E_THISPTR) Mcd, port, slot, &outways ); +} + void SysPluginBindings::McdRead( uint port, uint slot, u8 *dest, u32 adr, int size ) { Mcd->McdRead( (PS2E_THISPTR) Mcd, port, slot, dest, adr, size ); diff --git a/pcsx2/Plugins.h b/pcsx2/Plugins.h index 2092fb0f90..3df57888ec 100644 --- a/pcsx2/Plugins.h +++ b/pcsx2/Plugins.h @@ -214,6 +214,7 @@ public: } bool McdIsPresent( uint port, uint slot ); + void McdGetSizeInfo( uint port, uint slot, PS2E_McdSizeInfo& outways ); void McdRead( uint port, uint slot, u8 *dest, u32 adr, int size ); void McdSave( uint port, uint slot, const u8 *src, u32 adr, int size ); void McdEraseBlock( uint port, uint slot, u32 adr ); diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index c170d1a9ec..6d13a8b432 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -23,8 +23,9 @@ _sio sio; static const u8 cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d }; -// Memory Card Specs : Sector size etc. -static const mc_command_0x26_tag mc_command_0x26= {'+', 512, 16, 0x4000, 0x52, 0x5A}; +// Memory Card Specs for standard Sony 8mb carts: +// Flags (magic sio '+' thingie!), Sector size, eraseBlockSize (in pages), card size (in pages), xor checksum (superblock?), terminator (unused?). +static const mc_command_0x26_tag mc_sizeinfo_8mb= {'+', 512, 16, 0x4000, 0x52, 0x5A}; // Ejection timeout management belongs in the MemoryCardFile plugin, except the plugin // interface is not yet complete. @@ -78,13 +79,15 @@ static void _EraseMCDBlock(u32 adr) static u8 sio_xor( const u8 *buf, uint length ) { u8 i, x; + for (x=0, i=0; i +static void apply_xor( u8& dest, const T& src ) +{ + u8* buf = (u8*)&src; + for (uint x=0; x= mc_sizeinfo_8mb.mcdSizeInSectors, + "Mcd plugin returned an invalid memorycard size: Cards smaller than 8MB are not supported." ); + + cmd.sectorSize = info.SectorSize; + cmd.eraseBlocks = info.EraseBlockSizeInSectors; + cmd.mcdSizeInSectors = info.McdSizeInSectors; + + // Recalculate the xor summation + // This uses a trick of removing the known xor values for a default 8mb memorycard (for which the XOR + // was calculated), and replacing it with our new values. + + apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.sectorSize ); + apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.eraseBlocks ); + apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.mcdSizeInSectors ); + + apply_xor( cmd.mc_xor, cmd.sectorSize ); + apply_xor( cmd.mc_xor, cmd.eraseBlocks ); + apply_xor( cmd.mc_xor, cmd.mcdSizeInSectors ); + sio.bufcount = 12; sio.mcdst = 99; sio2.packet.recvVal3 = 0x83; memset8<0xff>(sio.buf); - memcpy(&sio.buf[2], &mc_command_0x26, sizeof(mc_command_0x26)); + memcpy_fast(&sio.buf[2], &cmd, sizeof(cmd)); sio.buf[12]=sio.terminator; MEMCARDS_LOG("MC(%d) command 0x%02X", sio.GetMemcardIndex()+1, value); - break; + } + break; + case 0x27: case 0x28: case 0xBF: @@ -239,8 +276,6 @@ void SIO_CommandWrite(u8 value,int way) { case 0x42: // WRITE case 0x43: // READ case 0x82: - // fixme: THEORY! Clearing either sio.sector or sio.lastsector when loading from - // savestate may safely invalidate games' memorycard caches! -- air if(value==0x82 && sio.lastsector==sio.sector) sio.mode = 2; if(value==0x42) sio.mode = 0; if(value==0x43) sio.lastsector = sio.sector; // Reading diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 33873bc51e..411d0d3d7c 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -87,7 +87,7 @@ static bool HandlePluginError( Exception::BaseException& ex ) // TODO: Send a message to the panel to select the failed plugin. - return AppOpenModalDialog() != wxID_CANCEL; + return AppOpenModalDialog() != wxID_CANCEL; } class PluginErrorEvent : public pxExceptionEvent diff --git a/pcsx2/gui/MemoryCardFile.cpp b/pcsx2/gui/MemoryCardFile.cpp index 20d830eef1..bcde047ea4 100644 --- a/pcsx2/gui/MemoryCardFile.cpp +++ b/pcsx2/gui/MemoryCardFile.cpp @@ -61,11 +61,12 @@ public: void Open(); void Close(); - s32 IsPresent ( uint slot ); - s32 Read ( uint slot, u8 *dest, u32 adr, int size ); - s32 Save ( uint slot, const u8 *src, u32 adr, int size ); - s32 EraseBlock ( uint slot, u32 adr ); - u64 GetCRC ( uint slot ); + s32 IsPresent ( uint slot ); + void GetSizeInfo( uint slot, PS2E_McdSizeInfo& outways ); + s32 Read ( uint slot, u8 *dest, u32 adr, int size ); + s32 Save ( uint slot, const u8 *src, u32 adr, int size ); + s32 EraseBlock ( uint slot, u32 adr ); + u64 GetCRC ( uint slot ); protected: bool Seek( wxFFile& f, u32 adr ); @@ -253,6 +254,17 @@ s32 FileMemoryCard::IsPresent( uint slot ) return m_file[slot].IsOpened(); } +void FileMemoryCard::GetSizeInfo( uint slot, PS2E_McdSizeInfo& outways ) +{ + outways.SectorSize = 512; + outways.EraseBlockSizeInSectors = 16; + + if( pxAssert( m_file[slot].IsOpened() ) ) + outways.McdSizeInSectors = m_file[slot].Length() / (outways.SectorSize + outways.EraseBlockSizeInSectors); + else + outways.McdSizeInSectors = 0x4000; +} + s32 FileMemoryCard::Read( uint slot, u8 *dest, u32 adr, int size ) { wxFFile& mcfp( m_file[slot] ); @@ -359,6 +371,11 @@ static s32 PS2E_CALLBACK FileMcd_IsPresent( PS2E_THISPTR thisptr, uint port, uin return thisptr->impl.IsPresent( FileMcd_ConvertToSlot( port, slot ) ); } +static void PS2E_CALLBACK FileMcd_GetSizeInfo( PS2E_THISPTR thisptr, uint port, uint slot, PS2E_McdSizeInfo* outways ) +{ + thisptr->impl.GetSizeInfo( FileMcd_ConvertToSlot( port, slot ), *outways ); +} + static s32 PS2E_CALLBACK FileMcd_Read( PS2E_THISPTR thisptr, uint port, uint slot, u8 *dest, u32 adr, int size ) { return thisptr->impl.Read( FileMcd_ConvertToSlot( port, slot ), dest, adr, size ); @@ -387,6 +404,7 @@ Component_FileMcd::Component_FileMcd() api.Base.EmuClose = FileMcd_EmuClose; api.McdIsPresent = FileMcd_IsPresent; + api.McdGetSizeInfo = FileMcd_GetSizeInfo; api.McdRead = FileMcd_Read; api.McdSave = FileMcd_Save; api.McdEraseBlock = FileMcd_EraseBlock; diff --git a/pcsx2/gui/Panels/MemoryCardListPanel.cpp b/pcsx2/gui/Panels/MemoryCardListPanel.cpp index 11e53bb6c8..bcd43c4a2b 100644 --- a/pcsx2/gui/Panels/MemoryCardListPanel.cpp +++ b/pcsx2/gui/Panels/MemoryCardListPanel.cpp @@ -547,6 +547,8 @@ void Panels::MemoryCardListPanel_Simple::DoRefresh() void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt) { + ScopedCoreThreadClose closed_core; + const int sel = m_listview->GetFirstSelected(); if( wxNOT_FOUND == sel ) return; const uint slot = sel; @@ -574,9 +576,13 @@ void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt) } } else - Dialogs::CreateMemoryCardDialog( this, slot, m_FolderPicker->GetPath() ).ShowModal(); + { + wxWindowID result = Dialogs::CreateMemoryCardDialog( this, slot, m_FolderPicker->GetPath() ).ShowModal(); + m_Cards[slot].IsEnabled = (result != wxID_CANCEL); + } RefreshSelections(); + closed_core.AllowResume(); } /*void Panels::MemoryCardListPanel_Simple::OnSwapPorts(wxCommandEvent& evt) diff --git a/pcsx2/gui/Panels/MemoryCardListView.cpp b/pcsx2/gui/Panels/MemoryCardListView.cpp index c3940286d2..c9d3437791 100644 --- a/pcsx2/gui/Panels/MemoryCardListView.cpp +++ b/pcsx2/gui/Panels/MemoryCardListView.cpp @@ -119,7 +119,7 @@ wxListItemAttr* MemoryCardListView_Simple::OnGetItemAttr(long item) const m_ItemAttr = wxListItemAttr(); // Wipe it clean! - if( !it.IsEnabled ) + if( !it.IsPresent ) m_ItemAttr.SetTextColour( *wxLIGHT_GREY ); if( m_TargetedItem == item ) diff --git a/pcsx2/gui/Panels/SpeedhacksPanel.cpp b/pcsx2/gui/Panels/SpeedhacksPanel.cpp index 9b4ad912e5..e2f8f29456 100644 --- a/pcsx2/gui/Panels/SpeedhacksPanel.cpp +++ b/pcsx2/gui/Panels/SpeedhacksPanel.cpp @@ -225,10 +225,10 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent ) DefEnableSizer += m_check_Enable | StdSpace().Align( wxALIGN_RIGHT ); *eeSliderPanel += m_slider_eecycle | sliderFlags; - *eeSliderPanel += m_msg_eecycle; + *eeSliderPanel += m_msg_eecycle | sliderFlags; *vuSliderPanel += m_slider_vustealer | sliderFlags; - *vuSliderPanel += m_msg_vustealer; + *vuSliderPanel += m_msg_vustealer | sliderFlags; *vuHacksPanel += m_check_vuFlagHack; *vuHacksPanel += m_check_vuMinMax; diff --git a/pcsx2/sio_internal.h b/pcsx2/sio_internal.h index 59928ecd5c..0aab21dbac 100644 --- a/pcsx2/sio_internal.h +++ b/pcsx2/sio_internal.h @@ -45,12 +45,12 @@ static const int #pragma pack(1) #endif struct mc_command_0x26_tag{ - u8 field_151; //+02 flags - u16 sectorSize; //+03 divide to it - u16 field_2C; //+05 divide to it - u32 mc_size; //+07 - u8 mc_xor; //+0b don't forget to recalculate it!!! - u8 Z; //+0c + u8 field_151; //+02 flags + u16 sectorSize; //+03 Size of each sector(page), in bytes. + u16 eraseBlocks; //+05 Number of sectors in the erase block + u32 mcdSizeInSectors; //+07 card size in sectors (pages). + u8 mc_xor; //+0b XOR Checksum of the superblock? (minus format ident and version?) + u8 Z; //+0c terminator? Appears to be overwritten/unused. #ifdef _MSC_VER }; #pragma pack()