mirror of https://github.com/PCSX2/pcsx2.git
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
This commit is contained in:
parent
2a5a0b36c8
commit
74a4ecd559
|
@ -1013,6 +1013,17 @@ typedef struct _PS2E_ComponentAPI_GS
|
||||||
|
|
||||||
} 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
|
// PS2E_ComponentAPI_Mcd
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -1037,6 +1048,16 @@ typedef struct _PS2E_ComponentAPI_Mcd
|
||||||
//
|
//
|
||||||
BOOL (PS2E_CALLBACK* McdIsPresent)( PS2E_THISPTR thisptr, uint port, uint slot );
|
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
|
// McdRead
|
||||||
// Requests that a block of data be loaded from the memorycard into the specified dest
|
// 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
|
// buffer (which is allocated by the caller). Bytes read should match the requested
|
||||||
|
|
|
@ -36,6 +36,12 @@ bool SysPluginBindings::McdIsPresent( uint port, uint slot )
|
||||||
return !!Mcd->McdIsPresent( (PS2E_THISPTR) Mcd, port, 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 )
|
void SysPluginBindings::McdRead( uint port, uint slot, u8 *dest, u32 adr, int size )
|
||||||
{
|
{
|
||||||
Mcd->McdRead( (PS2E_THISPTR) Mcd, port, slot, dest, adr, size );
|
Mcd->McdRead( (PS2E_THISPTR) Mcd, port, slot, dest, adr, size );
|
||||||
|
|
|
@ -214,6 +214,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool McdIsPresent( uint port, uint slot );
|
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 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 McdSave( uint port, uint slot, const u8 *src, u32 adr, int size );
|
||||||
void McdEraseBlock( uint port, uint slot, u32 adr );
|
void McdEraseBlock( uint port, uint slot, u32 adr );
|
||||||
|
|
|
@ -23,8 +23,9 @@ _sio sio;
|
||||||
|
|
||||||
static const u8 cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d };
|
static const u8 cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d };
|
||||||
|
|
||||||
// Memory Card Specs : Sector size etc.
|
// Memory Card Specs for standard Sony 8mb carts:
|
||||||
static const mc_command_0x26_tag mc_command_0x26= {'+', 512, 16, 0x4000, 0x52, 0x5A};
|
// 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
|
// Ejection timeout management belongs in the MemoryCardFile plugin, except the plugin
|
||||||
// interface is not yet complete.
|
// interface is not yet complete.
|
||||||
|
@ -78,13 +79,15 @@ static void _EraseMCDBlock(u32 adr)
|
||||||
static u8 sio_xor( const u8 *buf, uint length )
|
static u8 sio_xor( const u8 *buf, uint length )
|
||||||
{
|
{
|
||||||
u8 i, x;
|
u8 i, x;
|
||||||
|
for (x=0, i=0; i<length; i++) x ^= buf[i];
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
for (x=0, i=0; i<length; i++) x ^= buf[i];
|
template< typename T >
|
||||||
return x & 0xFF;
|
static void apply_xor( u8& dest, const T& src )
|
||||||
|
{
|
||||||
/*u8 x = 0;
|
u8* buf = (u8*)&src;
|
||||||
for( uint i=0; i<length; ++i) { x ^= buf[i]; }
|
for (uint x=0; x<sizeof(src); x++) dest ^= buf[x];
|
||||||
return x;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sioInit()
|
void sioInit()
|
||||||
|
@ -220,13 +223,47 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
case 0x25:
|
case 0x25:
|
||||||
MEMCARDS_LOG("MC(%d) command 0x%02X", sio.GetMemcardIndex()+1, value);
|
MEMCARDS_LOG("MC(%d) command 0x%02X", sio.GetMemcardIndex()+1, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x26:
|
case 0x26:
|
||||||
|
{
|
||||||
|
const uint port = sio.GetMemcardIndex();
|
||||||
|
const uint slot = sio.activeMemcardSlot[port];
|
||||||
|
|
||||||
|
mc_command_0x26_tag cmd = mc_sizeinfo_8mb;
|
||||||
|
PS2E_McdSizeInfo info;
|
||||||
|
|
||||||
|
info.SectorSize = cmd.sectorSize;
|
||||||
|
info.EraseBlockSizeInSectors = cmd.eraseBlocks;
|
||||||
|
info.McdSizeInSectors = cmd.mcdSizeInSectors;
|
||||||
|
|
||||||
|
SysPlugins.McdGetSizeInfo( port, slot, info );
|
||||||
|
pxAssumeDev( cmd.mcdSizeInSectors >= 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;
|
sio.bufcount = 12; sio.mcdst = 99; sio2.packet.recvVal3 = 0x83;
|
||||||
memset8<0xff>(sio.buf);
|
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;
|
sio.buf[12]=sio.terminator;
|
||||||
MEMCARDS_LOG("MC(%d) command 0x%02X", sio.GetMemcardIndex()+1, value);
|
MEMCARDS_LOG("MC(%d) command 0x%02X", sio.GetMemcardIndex()+1, value);
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x27:
|
case 0x27:
|
||||||
case 0x28:
|
case 0x28:
|
||||||
case 0xBF:
|
case 0xBF:
|
||||||
|
@ -239,8 +276,6 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
case 0x42: // WRITE
|
case 0x42: // WRITE
|
||||||
case 0x43: // READ
|
case 0x43: // READ
|
||||||
case 0x82:
|
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==0x82 && sio.lastsector==sio.sector) sio.mode = 2;
|
||||||
if(value==0x42) sio.mode = 0;
|
if(value==0x42) sio.mode = 0;
|
||||||
if(value==0x43) sio.lastsector = sio.sector; // Reading
|
if(value==0x43) sio.lastsector = sio.sector; // Reading
|
||||||
|
|
|
@ -87,7 +87,7 @@ static bool HandlePluginError( Exception::BaseException& ex )
|
||||||
|
|
||||||
// TODO: Send a message to the panel to select the failed plugin.
|
// TODO: Send a message to the panel to select the failed plugin.
|
||||||
|
|
||||||
return AppOpenModalDialog<Dialogs::SysConfigDialog>() != wxID_CANCEL;
|
return AppOpenModalDialog<Dialogs::ComponentsConfigDialog>() != wxID_CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PluginErrorEvent : public pxExceptionEvent
|
class PluginErrorEvent : public pxExceptionEvent
|
||||||
|
|
|
@ -61,11 +61,12 @@ public:
|
||||||
void Open();
|
void Open();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
s32 IsPresent ( uint slot );
|
s32 IsPresent ( uint slot );
|
||||||
s32 Read ( uint slot, u8 *dest, u32 adr, int size );
|
void GetSizeInfo( uint slot, PS2E_McdSizeInfo& outways );
|
||||||
s32 Save ( uint slot, const u8 *src, u32 adr, int size );
|
s32 Read ( uint slot, u8 *dest, u32 adr, int size );
|
||||||
s32 EraseBlock ( uint slot, u32 adr );
|
s32 Save ( uint slot, const u8 *src, u32 adr, int size );
|
||||||
u64 GetCRC ( uint slot );
|
s32 EraseBlock ( uint slot, u32 adr );
|
||||||
|
u64 GetCRC ( uint slot );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Seek( wxFFile& f, u32 adr );
|
bool Seek( wxFFile& f, u32 adr );
|
||||||
|
@ -253,6 +254,17 @@ s32 FileMemoryCard::IsPresent( uint slot )
|
||||||
return m_file[slot].IsOpened();
|
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 )
|
s32 FileMemoryCard::Read( uint slot, u8 *dest, u32 adr, int size )
|
||||||
{
|
{
|
||||||
wxFFile& mcfp( m_file[slot] );
|
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 ) );
|
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 )
|
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 );
|
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.Base.EmuClose = FileMcd_EmuClose;
|
||||||
|
|
||||||
api.McdIsPresent = FileMcd_IsPresent;
|
api.McdIsPresent = FileMcd_IsPresent;
|
||||||
|
api.McdGetSizeInfo = FileMcd_GetSizeInfo;
|
||||||
api.McdRead = FileMcd_Read;
|
api.McdRead = FileMcd_Read;
|
||||||
api.McdSave = FileMcd_Save;
|
api.McdSave = FileMcd_Save;
|
||||||
api.McdEraseBlock = FileMcd_EraseBlock;
|
api.McdEraseBlock = FileMcd_EraseBlock;
|
||||||
|
|
|
@ -547,6 +547,8 @@ void Panels::MemoryCardListPanel_Simple::DoRefresh()
|
||||||
|
|
||||||
void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
|
void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
|
ScopedCoreThreadClose closed_core;
|
||||||
|
|
||||||
const int sel = m_listview->GetFirstSelected();
|
const int sel = m_listview->GetFirstSelected();
|
||||||
if( wxNOT_FOUND == sel ) return;
|
if( wxNOT_FOUND == sel ) return;
|
||||||
const uint slot = sel;
|
const uint slot = sel;
|
||||||
|
@ -574,9 +576,13 @@ void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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();
|
RefreshSelections();
|
||||||
|
closed_core.AllowResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void Panels::MemoryCardListPanel_Simple::OnSwapPorts(wxCommandEvent& evt)
|
/*void Panels::MemoryCardListPanel_Simple::OnSwapPorts(wxCommandEvent& evt)
|
||||||
|
|
|
@ -119,7 +119,7 @@ wxListItemAttr* MemoryCardListView_Simple::OnGetItemAttr(long item) const
|
||||||
|
|
||||||
m_ItemAttr = wxListItemAttr(); // Wipe it clean!
|
m_ItemAttr = wxListItemAttr(); // Wipe it clean!
|
||||||
|
|
||||||
if( !it.IsEnabled )
|
if( !it.IsPresent )
|
||||||
m_ItemAttr.SetTextColour( *wxLIGHT_GREY );
|
m_ItemAttr.SetTextColour( *wxLIGHT_GREY );
|
||||||
|
|
||||||
if( m_TargetedItem == item )
|
if( m_TargetedItem == item )
|
||||||
|
|
|
@ -225,10 +225,10 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow* parent )
|
||||||
DefEnableSizer += m_check_Enable | StdSpace().Align( wxALIGN_RIGHT );
|
DefEnableSizer += m_check_Enable | StdSpace().Align( wxALIGN_RIGHT );
|
||||||
|
|
||||||
*eeSliderPanel += m_slider_eecycle | sliderFlags;
|
*eeSliderPanel += m_slider_eecycle | sliderFlags;
|
||||||
*eeSliderPanel += m_msg_eecycle;
|
*eeSliderPanel += m_msg_eecycle | sliderFlags;
|
||||||
|
|
||||||
*vuSliderPanel += m_slider_vustealer | sliderFlags;
|
*vuSliderPanel += m_slider_vustealer | sliderFlags;
|
||||||
*vuSliderPanel += m_msg_vustealer;
|
*vuSliderPanel += m_msg_vustealer | sliderFlags;
|
||||||
|
|
||||||
*vuHacksPanel += m_check_vuFlagHack;
|
*vuHacksPanel += m_check_vuFlagHack;
|
||||||
*vuHacksPanel += m_check_vuMinMax;
|
*vuHacksPanel += m_check_vuMinMax;
|
||||||
|
|
|
@ -45,12 +45,12 @@ static const int
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
#endif
|
#endif
|
||||||
struct mc_command_0x26_tag{
|
struct mc_command_0x26_tag{
|
||||||
u8 field_151; //+02 flags
|
u8 field_151; //+02 flags
|
||||||
u16 sectorSize; //+03 divide to it
|
u16 sectorSize; //+03 Size of each sector(page), in bytes.
|
||||||
u16 field_2C; //+05 divide to it
|
u16 eraseBlocks; //+05 Number of sectors in the erase block
|
||||||
u32 mc_size; //+07
|
u32 mcdSizeInSectors; //+07 card size in sectors (pages).
|
||||||
u8 mc_xor; //+0b don't forget to recalculate it!!!
|
u8 mc_xor; //+0b XOR Checksum of the superblock? (minus format ident and version?)
|
||||||
u8 Z; //+0c
|
u8 Z; //+0c terminator? Appears to be overwritten/unused.
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
};
|
};
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
Loading…
Reference in New Issue