mirror of https://github.com/PCSX2/pcsx2.git
(Patch by KrossX): Fixed multitap - Part 2 - (e.g. Timesplitters), New: support raw PSX
memcards (mcd/mcr), Fixed issues with pad 2 (e.g. issue 1326). These are changes which were left out at r5622, updated to pach v9 by KrossX from http://forums.pcsx2.net/Thread-Multitap-PCSX2 . - Please report any issues with memcards corruption/incompatibilities here. - Please feedback on multitap improvements here. Thanks, KrossX! :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5703 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
b912778a3c
commit
92487e2618
|
@ -1022,6 +1022,7 @@ 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)
|
||||
u8 Xor; // Checksum of previous data
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
1308
pcsx2/Sio.cpp
1308
pcsx2/Sio.cpp
File diff suppressed because it is too large
Load Diff
104
pcsx2/Sio.h
104
pcsx2/Sio.h
|
@ -19,6 +19,69 @@
|
|||
// Games are highly unlikely to need timed IRQ's for PAD and MemoryCard handling anyway (rama).
|
||||
#define SIO_INLINE_IRQS
|
||||
|
||||
struct _mcd
|
||||
{
|
||||
u8 term; // terminator value;
|
||||
|
||||
bool goodSector; // xor sector check
|
||||
u32 sectorAddr; // read/write sector address
|
||||
u32 transferAddr; // Transfer address
|
||||
|
||||
u8 FLAG; // for PSX;
|
||||
|
||||
u8 port; // port
|
||||
u8 slot; // and slot for this memcard
|
||||
|
||||
// Auto Eject
|
||||
u32 ForceEjection_Timeout; // in SIO checks
|
||||
wxDateTime ForceEjection_Timestamp;
|
||||
|
||||
|
||||
void GetSizeInfo(PS2E_McdSizeInfo &info)
|
||||
{
|
||||
SysPlugins.McdGetSizeInfo(port, slot, info);
|
||||
}
|
||||
|
||||
bool IsPSX()
|
||||
{
|
||||
return SysPlugins.McdIsPSX(port, slot);
|
||||
}
|
||||
|
||||
void EraseBlock()
|
||||
{
|
||||
SysPlugins.McdEraseBlock(port, slot, transferAddr);
|
||||
}
|
||||
|
||||
// Read from memorycard to dest
|
||||
void Read(u8 *dest, int size)
|
||||
{
|
||||
SysPlugins.McdRead(port, slot, dest, transferAddr, size);
|
||||
}
|
||||
|
||||
// Write to memorycard from src
|
||||
void Write(u8 *src, int size)
|
||||
{
|
||||
SysPlugins.McdSave(port, slot, src,transferAddr, size);
|
||||
}
|
||||
|
||||
bool IsPresent()
|
||||
{
|
||||
return SysPlugins.McdIsPresent(port, slot);
|
||||
}
|
||||
|
||||
u8 DoXor(const u8 *buf, uint length)
|
||||
{
|
||||
u8 i, x;
|
||||
for (x=0, i=0; i<length; i++) x ^= buf[i];
|
||||
return x;
|
||||
}
|
||||
|
||||
u64 GetChecksum()
|
||||
{
|
||||
return SysPlugins.McdGetCRC(port, slot);
|
||||
}
|
||||
};
|
||||
|
||||
struct _sio
|
||||
{
|
||||
u16 StatReg;
|
||||
|
@ -26,40 +89,25 @@ struct _sio
|
|||
u16 CtrlReg;
|
||||
u16 BaudReg;
|
||||
|
||||
u8 buf[256];
|
||||
u32 bufcount;
|
||||
u32 parp;
|
||||
u32 mcdst,rdwr;
|
||||
u8 adrH,adrL;
|
||||
u32 padst;
|
||||
u32 mtapst;
|
||||
u32 packetsize;
|
||||
u32 count; // old_sio remnant
|
||||
u32 packetsize;// old_sio remnant
|
||||
|
||||
u8 terminator;
|
||||
u8 mode;
|
||||
u8 mc_command;
|
||||
u32 lastsector;
|
||||
u32 sector;
|
||||
u32 k;
|
||||
u32 count;
|
||||
u8 buf[256];
|
||||
u8 ret; // default return value;
|
||||
|
||||
u16 bufCount; // current buffer counter
|
||||
u16 bufSize; // supposed buffer size
|
||||
|
||||
// Active pad slot for each port. Not sure if these automatically reset after each read or not.
|
||||
u8 activePadSlot[2];
|
||||
// Active memcard slot for each port. Not sure if these automatically reset after each read or not.
|
||||
u8 activeMemcardSlot[2];
|
||||
u8 port; // current port
|
||||
u8 slot[2]; // current slot
|
||||
|
||||
int GetMemcardIndex() const
|
||||
{
|
||||
return (CtrlReg&0x2000) >> 13;
|
||||
}
|
||||
|
||||
int GetMultitapPort() const
|
||||
{
|
||||
return (CtrlReg&0x2000) >> 13;
|
||||
}
|
||||
u8 GetPort() { return port; }
|
||||
u8 GetSlot() { return slot[port]; }
|
||||
};
|
||||
|
||||
extern _sio sio;
|
||||
extern _mcd mcds[2][4];
|
||||
extern _mcd *mcd;
|
||||
|
||||
extern void sioInit();
|
||||
extern u8 sioRead8();
|
||||
|
|
|
@ -49,6 +49,9 @@ protected:
|
|||
wxFFile m_file[8];
|
||||
u8 m_effeffs[528*16];
|
||||
SafeArray<u8> m_currentdata;
|
||||
u64 m_chksum[8];
|
||||
bool m_ispsx[8];
|
||||
u32 m_chkaddr;
|
||||
|
||||
public:
|
||||
FileMemoryCard();
|
||||
|
@ -199,13 +202,27 @@ void FileMemoryCard::Open()
|
|||
GetDisabledMessage( slot )
|
||||
);
|
||||
}
|
||||
else // Load checksum
|
||||
{
|
||||
m_ispsx[slot] = m_file[slot].Length() == 0x20000;
|
||||
m_chkaddr = 0x210;
|
||||
|
||||
if(!m_ispsx[slot] && !!m_file[slot].Seek( m_chkaddr ))
|
||||
m_file[slot].Read( &m_chksum[slot], 8 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileMemoryCard::Close()
|
||||
{
|
||||
for( int slot=0; slot<8; ++slot )
|
||||
{
|
||||
// Store checksum
|
||||
if(!m_ispsx[slot] && !!m_file[slot].Seek( m_chkaddr ))
|
||||
m_file[slot].Write( &m_chksum[slot], 8 );
|
||||
|
||||
m_file[slot].Close();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns FALSE if the seek failed (is outside the bounds of the file).
|
||||
|
@ -256,18 +273,22 @@ s32 FileMemoryCard::IsPresent( uint slot )
|
|||
|
||||
void FileMemoryCard::GetSizeInfo( uint slot, PS2E_McdSizeInfo& outways )
|
||||
{
|
||||
outways.SectorSize = 512;
|
||||
outways.EraseBlockSizeInSectors = 16;
|
||||
outways.SectorSize = 512; // 0x0200
|
||||
outways.EraseBlockSizeInSectors = 16; // 0x0010
|
||||
outways.Xor = 18; // 0x12, XOR 02 00 00 10
|
||||
|
||||
if( pxAssert( m_file[slot].IsOpened() ) )
|
||||
outways.McdSizeInSectors = m_file[slot].Length() / (outways.SectorSize + outways.EraseBlockSizeInSectors);
|
||||
else
|
||||
outways.McdSizeInSectors = 0x4000;
|
||||
|
||||
u8 *pdata = (u8*)&outways.McdSizeInSectors;
|
||||
outways.Xor ^= pdata[0] ^ pdata[1] ^ pdata[2] ^ pdata[3];
|
||||
}
|
||||
|
||||
bool FileMemoryCard::IsPSX( uint slot )
|
||||
{
|
||||
return m_file[slot].Length() == 0x20000;
|
||||
return m_ispsx[slot];
|
||||
}
|
||||
|
||||
s32 FileMemoryCard::Read( uint slot, u8 *dest, u32 adr, int size )
|
||||
|
@ -293,15 +314,36 @@ s32 FileMemoryCard::Save( uint slot, const u8 *src, u32 adr, int size )
|
|||
return 1;
|
||||
}
|
||||
|
||||
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_ispsx[slot])
|
||||
{
|
||||
if ((m_currentdata[i] & src[i]) != src[i])
|
||||
Console.Warning("(FileMcd) Warning: writing to uncleared data.");
|
||||
m_currentdata[i] &= src[i];
|
||||
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;
|
||||
|
@ -327,18 +369,27 @@ u64 FileMemoryCard::GetCRC( uint slot )
|
|||
wxFFile& mcfp( m_file[slot] );
|
||||
if( !mcfp.IsOpened() ) return 0;
|
||||
|
||||
if( !Seek( mcfp, 0 ) ) return 0;
|
||||
|
||||
// Process the file in 4k chunks. Speeds things up significantly.
|
||||
u64 retval = 0;
|
||||
u64 buffer[528*8]; // use 528 (sector size), ensures even divisibility
|
||||
|
||||
const uint filesize = mcfp.Length() / sizeof(buffer);
|
||||
for( uint i=filesize; i; --i )
|
||||
|
||||
if(m_ispsx[slot])
|
||||
{
|
||||
mcfp.Read( &buffer, sizeof(buffer) );
|
||||
for( uint t=0; t<ArraySize(buffer); ++t )
|
||||
retval ^= buffer[t];
|
||||
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;
|
||||
|
|
|
@ -41,6 +41,126 @@ static const int
|
|||
RTS = 0x0020,
|
||||
SIO_RESET = 0x0040;
|
||||
|
||||
//#define _KELOGS // Krossx's Enhanced LOGS, it has nothing to do with Kellogg's
|
||||
|
||||
#ifdef _KELOGS
|
||||
struct KELOGS
|
||||
{
|
||||
u8 number;
|
||||
u8 write;
|
||||
u8 read;
|
||||
};
|
||||
|
||||
extern KELOGS kelogs[];
|
||||
extern u32 kelogs_count;
|
||||
extern bool doKelogs;
|
||||
|
||||
void inline KelogsPrint()
|
||||
{
|
||||
if(doKelogs)
|
||||
{
|
||||
printf(" [##|");
|
||||
|
||||
for(u32 i = 0; i < kelogs_count; i++)
|
||||
printf("%02X|", kelogs[i].number);
|
||||
|
||||
printf("\nSIO [W8|");
|
||||
|
||||
for(u32 i = 0; i < kelogs_count; i++)
|
||||
printf("%02X|", kelogs[i].write);
|
||||
|
||||
printf("\n [R8|");
|
||||
|
||||
for(u32 i = 0; i < kelogs_count; i++)
|
||||
printf("%02X|", kelogs[i].read);
|
||||
|
||||
printf("\n\n");
|
||||
doKelogs = false;
|
||||
}
|
||||
|
||||
kelogs_count = 0;
|
||||
}
|
||||
|
||||
void inline KelogsWrite(u8 value)
|
||||
{
|
||||
kelogs[kelogs_count].number = sio.bufCount;
|
||||
kelogs[kelogs_count].write = value;
|
||||
}
|
||||
|
||||
void inline KelogsRead(u8 value)
|
||||
{
|
||||
kelogs[kelogs_count++].read = value;
|
||||
}
|
||||
|
||||
void inline KelogsEnable()
|
||||
{
|
||||
doKelogs = true;
|
||||
}
|
||||
|
||||
#define KELOGS_PRINT() KelogsPrint()
|
||||
#define KELOGS_WRITE(x) KelogsWrite(x)
|
||||
#define KELOGS_READ(x) KelogsRead(x)
|
||||
#define KELOGS_ENABLE() KelogsEnable()
|
||||
#else
|
||||
#define KELOGS_PRINT()
|
||||
#define KELOGS_WRITE(x)
|
||||
#define KELOGS_READ(x)
|
||||
#define KELOGS_ENABLE()
|
||||
#endif
|
||||
|
||||
|
||||
void inline SIO_STAT_READY()
|
||||
{
|
||||
sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty
|
||||
sio.StatReg |= RX_RDY; // Transfer is Ready
|
||||
}
|
||||
|
||||
void inline SIO_STAT_EMPTY()
|
||||
{
|
||||
sio.StatReg &= ~RX_RDY; // Receive is not Ready now?
|
||||
sio.StatReg |= TX_EMPTY; // Buffer is Empty
|
||||
}
|
||||
|
||||
void inline DEVICE_PLUGGED()
|
||||
{
|
||||
sio.ret = 0xFF;
|
||||
sio2.packet.recvVal1 = 0x01100;
|
||||
sio.bufSize = sio2.cmdlength;
|
||||
memset8<0xFF>(sio.buf);
|
||||
}
|
||||
|
||||
void inline DEVICE_UNPLUGGED()
|
||||
{
|
||||
sio.ret = 0x00;
|
||||
sio2.packet.recvVal1 = 0x1D100;
|
||||
sio.bufSize = sio2.cmdlength;
|
||||
memset8<0x00>(sio.buf);
|
||||
}
|
||||
|
||||
enum MEMCARD_TRANSFER
|
||||
{
|
||||
MEM_INVALID = 0,
|
||||
MEM_WRITE,
|
||||
MEM_READ,
|
||||
MEM_ERASE,
|
||||
MEM_COMMIT
|
||||
};
|
||||
|
||||
enum SIO_MODE
|
||||
{
|
||||
SIO_START = 0,
|
||||
SIO_CONTROLLER,
|
||||
SIO_MULTITAP,
|
||||
SIO_INFRARED,
|
||||
SIO_MEMCARD,
|
||||
SIO_MEMCARD_AUTH,
|
||||
SIO_MEMCARD_TRANSFER,
|
||||
SIO_MEMCARD_SECTOR,
|
||||
SIO_MEMCARD_PSX,
|
||||
SIO_DUMMY
|
||||
};
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
@ -57,3 +177,4 @@ struct mc_command_0x26_tag{
|
|||
#else
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue