(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:
avihal@gmail.com 2013-07-19 13:43:33 +00:00
parent b912778a3c
commit 92487e2618
5 changed files with 923 additions and 704 deletions

View File

@ -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
};
// --------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -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();

View File

@ -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;

View File

@ -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