Merge pull request #2067 from RedPanda4552/master

Add PSX memory card support
This commit is contained in:
ramapcsx2 2017-09-17 16:53:36 +02:00 committed by GitHub
commit af2278c3c2
6 changed files with 84 additions and 56 deletions

View File

@ -172,9 +172,8 @@ static __fi void _psxTestInterrupts()
IopTestEvent(IopEvt_SIF0, sif0Interrupt); // SIF0 IopTestEvent(IopEvt_SIF0, sif0Interrupt); // SIF0
IopTestEvent(IopEvt_SIF1, sif1Interrupt); // SIF1 IopTestEvent(IopEvt_SIF1, sif1Interrupt); // SIF1
IopTestEvent(IopEvt_SIF2, sif2Interrupt); // SIF2 IopTestEvent(IopEvt_SIF2, sif2Interrupt); // SIF2
#ifndef SIO_INLINE_IRQS // Originally controlled by a preprocessor define, now PSX dependent.
IopTestEvent(IopEvt_SIO, sioInterrupt); if (psxHu32(HW_ICFG) & (1 << 3)) IopTestEvent(IopEvt_SIO, sioInterruptR);
#endif
IopTestEvent(IopEvt_CdvdRead, cdvdReadInterrupt); IopTestEvent(IopEvt_CdvdRead, cdvdReadInterrupt);
// Profile-guided Optimization (sorta) // Profile-guided Optimization (sorta)

View File

@ -26,6 +26,7 @@ _mcd *mcd;
SIO_MODE siomode = SIO_START; SIO_MODE siomode = SIO_START;
static void sioWrite8inl(u8 data); static void sioWrite8inl(u8 data);
#define SIO_WRITE void inline #define SIO_WRITE void inline
#define SIO_FORCEINLINE __fi
// Magic psx values from nocash info // Magic psx values from nocash info
static const u8 memcard_psx[] = {0x5A, 0x5D, 0x5C, 0x5D, 0x04, 0x00, 0x00, 0x80}; static const u8 memcard_psx[] = {0x5A, 0x5D, 0x5C, 0x5D, 0x04, 0x00, 0x00, 0x80};
@ -79,21 +80,6 @@ void ClearMcdEjectTimeoutNow()
} }
} }
// SIO Inline'd IRQs : Calls the SIO interrupt handlers directly instead of
// feeding them through the IOP's branch test. (see SIO.H for details)
#ifdef SIO_INLINE_IRQS
#define SIO_INT() sioInterrupt()
#define SIO_FORCEINLINE __fi
#else
__fi void SIO_INT()
{
if( !(psxRegs.interrupt & (1<<IopEvt_SIO)) )
PSX_INT(IopEvt_SIO, 64 ); // PSXCLK/250000);
}
#define SIO_FORCEINLINE __fi
#endif
// Currently only check if pad wants mtap to be active. // Currently only check if pad wants mtap to be active.
// Could lets PCSX2 have its own options, if anyone ever // Could lets PCSX2 have its own options, if anyone ever
// wants to add support for using the extra memcard slots. // wants to add support for using the extra memcard slots.
@ -132,12 +118,32 @@ void sioInit()
sio.packetsize = 0; sio.packetsize = 0;
} }
void SIO_FORCEINLINE sioInterrupt() bool isR3000ATest = false;
{
PAD_LOG("Sio Interrupt"); // Check the active game's type, and fire the matching interrupt.
sio.StatReg|= IRQ; // The 3rd bit of the HW_IFCG register lets us know if PSX mode is active. 1 = PSX, 0 = PS2
iopIntcIrq(7); //Should this be used instead of the one below? // Note that the R3000A's call to interrupts only calls the PS2 based (lack of) delays.
//psxHu32(0x1070)|=0x80; SIO_FORCEINLINE void sioInterrupt() {
if ((psxHu32(HW_ICFG) & (1 << 3)) && !isR3000ATest) {
if (!(psxRegs.interrupt & (1 << IopEvt_SIO)))
PSX_INT(IopEvt_SIO, 64); // PSXCLK/250000);
} else {
PAD_LOG("Sio Interrupt");
sio.StatReg |= IRQ;
iopIntcIrq(7); //Should this be used instead of the one below?
//psxHu32(0x1070)|=0x80;
}
isR3000ATest = false;
}
// An offhand way for the R3000A to access the sioInterrupt function.
// Following the design of the old preprocessor system, the R3000A should
// never call the PSX delays (oddly enough), and only the PS2. So we need
// an extra layer here to help control that.
__fi void sioInterruptR() {
isR3000ATest = true;
sioInterrupt();
} }
SIO_WRITE sioWriteStart(u8 data) SIO_WRITE sioWriteStart(u8 data)
@ -202,7 +208,7 @@ SIO_WRITE sioWriteController(u8 data)
break; break;
} }
//Console.WriteLn( "SIO: sent = %02X From pad data = %02X bufCnt %08X ", data, sio.buf[sio.bufCount], sio.bufCount); //Console.WriteLn( "SIO: sent = %02X From pad data = %02X bufCnt %08X ", data, sio.buf[sio.bufCount], sio.bufCount);
SIO_INT(); //Don't all commands(transfers) cause an interrupt? sioInterrupt(); //Don't all commands(transfers) cause an interrupt?
} }
SIO_WRITE sioWriteMultitap(u8 data) SIO_WRITE sioWriteMultitap(u8 data)
@ -290,7 +296,7 @@ SIO_WRITE sioWriteMultitap(u8 data)
//default: sio.buf[sio.bufCount] = 0x00; break; //default: sio.buf[sio.bufCount] = 0x00; break;
} }
SIO_INT(); sioInterrupt();
} }
SIO_WRITE MemcardResponse() SIO_WRITE MemcardResponse()
@ -365,7 +371,7 @@ SIO_WRITE memcardErase(u8 data)
break; break;
} }
} }
SIO_INT(); sioInterrupt();
break; break;
default: default:
@ -427,7 +433,7 @@ SIO_WRITE memcardWrite(u8 data)
} }
} }
SIO_INT(); sioInterrupt();
break; break;
case 2: case 2:
@ -516,7 +522,7 @@ SIO_WRITE memcardRead(u8 data)
break; break;
} }
} }
SIO_INT(); sioInterrupt();
break; break;
case 2: case 2:
@ -629,7 +635,7 @@ SIO_WRITE sioWriteMemcard(u8 data)
case 0: case 0:
SIO_STAT_READY(); SIO_STAT_READY();
memcardInit(); memcardInit();
SIO_INT(); sioInterrupt();
break; break;
case 1: case 1:
@ -703,7 +709,7 @@ SIO_WRITE sioWriteMemcard(u8 data)
siomode = SIO_DUMMY; siomode = SIO_DUMMY;
break; break;
} }
SIO_INT(); sioInterrupt();
break; break;
case 2: case 2:
@ -725,7 +731,7 @@ SIO_WRITE sioWriteMemcardPSX(u8 data)
case 0: // Same init stuff... case 0: // Same init stuff...
SIO_STAT_READY(); SIO_STAT_READY();
memcardInit(); memcardInit();
SIO_INT(); sioInterrupt();
break; break;
case 1: case 1:
@ -756,7 +762,7 @@ SIO_WRITE sioWriteMemcardPSX(u8 data)
siomode = SIO_DUMMY; siomode = SIO_DUMMY;
break; break;
} }
SIO_INT(); sioInterrupt();
break; break;
case 2: break; case 2: break;
@ -831,7 +837,7 @@ SIO_WRITE sioWriteInfraRed(u8 data)
SIO_STAT_READY(); SIO_STAT_READY();
DEVICE_PLUGGED(); DEVICE_PLUGGED();
siomode = SIO_DUMMY; siomode = SIO_DUMMY;
SIO_INT(); sioInterrupt();
} }
//This bit-field in the STATUS register contains the (inveted) state of the /ACK linre from the Controller / MC. //This bit-field in the STATUS register contains the (inveted) state of the /ACK linre from the Controller / MC.
@ -856,12 +862,12 @@ SIO_WRITE sioWriteInfraRed(u8 data)
void chkTriggerInt() { void chkTriggerInt() {
//Conditions for triggerring an interrupt. //Conditions for triggerring an interrupt.
//this is not correct, but ... it can be fixed later //this is not correct, but ... it can be fixed later
SIO_INT(); return; sioInterrupt(); return;
if ((sio.StatReg & IRQ)) { SIO_INT(); return; } //The interrupt flag in the main INTR_STAT reg should go active on multiple occasions. Set it here for now (hack), until the correct mechanism is made. if ((sio.StatReg & IRQ)) { sioInterrupt(); return; } //The interrupt flag in the main INTR_STAT reg should go active on multiple occasions. Set it here for now (hack), until the correct mechanism is made.
if ((sio.CtrlReg & ACK_INT_EN) && ((sio.StatReg & TX_RDY) || (sio.StatReg & TX_EMPTY))) { SIO_INT(); return; } if ((sio.CtrlReg & ACK_INT_EN) && ((sio.StatReg & TX_RDY) || (sio.StatReg & TX_EMPTY))) { sioInterrupt(); return; }
if ((sio.CtrlReg & ACK_INT_EN) && (sio.StatReg & ACK_INP)) { SIO_INT(); return; } if ((sio.CtrlReg & ACK_INT_EN) && (sio.StatReg & ACK_INP)) { sioInterrupt(); return; }
//The following one may be incorrect. //The following one may be incorrect.
//if ((sio.CtrlReg & RX_INT_EN) && ((byteCnt >= (1<< ((sio.CtrlReg & RX_BYTES_INT) >>8))) ? 1:0) ) { SIO_INT(); return; } //if ((sio.CtrlReg & RX_INT_EN) && ((byteCnt >= (1<< ((sio.CtrlReg & RX_BYTES_INT) >>8))) ? 1:0) ) { sioInterrupt(); return; }
return; return;
} }
@ -889,7 +895,7 @@ static void sioWrite8inl(u8 data)
if (IS_LAST_BYTE_IN_PACKET != 1) //The following should be set after each byte transfer but the last one. if (IS_LAST_BYTE_IN_PACKET != 1) //The following should be set after each byte transfer but the last one.
sio.StatReg |= ACK_INP; //Signal that Controller (or MC) has brought the /ACK (Acknowledge) line active low. sio.StatReg |= ACK_INP; //Signal that Controller (or MC) has brought the /ACK (Acknowledge) line active low.
SIO_INT(); sioInterrupt();
//chkTriggerInt(); //chkTriggerInt();
//Console.WriteLn( "SIO0 WR DATA COMMON %02X INT_STAT= %08X IOPpc= %08X " , data, psxHu32(0x1070), psxRegs.pc); //Console.WriteLn( "SIO0 WR DATA COMMON %02X INT_STAT= %08X IOPpc= %08X " , data, psxHu32(0x1070), psxRegs.pc);
byteCnt++; byteCnt++;

View File

@ -15,10 +15,6 @@
#pragma once #pragma once
// Let's enable this to free the IOP event handler of some considerable load.
// Games are highly unlikely to need timed IRQ's for PAD and MemoryCard handling anyway (rama).
#define SIO_INLINE_IRQS
#include "MemoryCardFile.h" #include "MemoryCardFile.h"
struct _mcd struct _mcd
@ -125,6 +121,7 @@ extern u8 sioRead8();
extern void sioWrite8(u8 value); extern void sioWrite8(u8 value);
extern void sioWriteCtrl16(u16 value); extern void sioWriteCtrl16(u16 value);
extern void sioInterrupt(); extern void sioInterrupt();
extern void sioInterruptR();
extern void InitializeSIO(u8 value); extern void InitializeSIO(u8 value);
extern void SetForceMcdEjectTimeoutNow(); extern void SetForceMcdEjectTimeoutNow();
extern void ClearMcdEjectTimeoutNow(); extern void ClearMcdEjectTimeoutNow();

View File

@ -198,13 +198,14 @@ namespace Dialogs
#ifdef __WXMSW__ #ifdef __WXMSW__
pxCheckBox* m_check_CompressNTFS; pxCheckBox* m_check_CompressNTFS;
#endif #endif
pxCheckBox* m_check_psx;
public: public:
virtual ~CreateMemoryCardDialog() = default; virtual ~CreateMemoryCardDialog() = default;
CreateMemoryCardDialog( wxWindow* parent, const wxDirName& mcdpath, const wxString& suggested_mcdfileName); CreateMemoryCardDialog( wxWindow* parent, const wxDirName& mcdpath, const wxString& suggested_mcdfileName);
//duplicate of MemoryCardFile::Create. Don't know why the existing method isn't used. - avih //duplicate of MemoryCardFile::Create. Don't know why the existing method isn't used. - avih
static bool CreateIt( const wxString& mcdFile, uint sizeInMB ); static bool CreateIt( const wxString& mcdFile, uint sizeInMB, bool isPSX );
wxString result_createdMcdFilename; wxString result_createdMcdFilename;
//wxDirName GetPathToMcds() const; //wxDirName GetPathToMcds() const;

View File

@ -87,6 +87,8 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, const
s_padding += m_check_CompressNTFS | StdExpand(); s_padding += m_check_CompressNTFS | StdExpand();
#endif #endif
s_padding += m_check_psx;
s_padding += 12; s_padding += 12;
s_padding += s_buttons | StdCenter(); s_padding += s_buttons | StdCenter();
@ -110,24 +112,44 @@ wxDirName Dialogs::CreateMemoryCardDialog::GetPathToMcds() const
// When this GUI is moved into the FileMemoryCard plugin (where it eventually belongs), // When this GUI is moved into the FileMemoryCard plugin (where it eventually belongs),
// this function will be removed and the MemoryCardFile::Create() function will be used // this function will be removed and the MemoryCardFile::Create() function will be used
// instead. // instead.
bool Dialogs::CreateMemoryCardDialog::CreateIt( const wxString& mcdFile, uint sizeInMB ) bool Dialogs::CreateMemoryCardDialog::CreateIt( const wxString& mcdFile, uint sizeInMB, bool isPSX )
{ {
//int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; //int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0};
u8 m_effeffs[528*16]; // PS2 Memory Card
memset8<0xff>( m_effeffs ); u8 m_effeffs[528 * 16];
memset8<0xff>(m_effeffs);
Console.WriteLn( L"(FileMcd) Creating new %uMB memory card: '%s'", sizeInMB, WX_STR(mcdFile) ); // PSX Memory Card; 8192 is the size in bytes of a single block of a PSX memory card (8 KiB).
u8 m_effeffs_psx[8192];
memset8<0xff>(m_effeffs_psx);
// Since isPSX will have a default false state, it makes more sense to check "not PSX" first
if (!isPSX) {
Console.WriteLn(L"(FileMcd) Creating new PS2 %uMB memory card: '%s'", sizeInMB, WX_STR(mcdFile));
}
else {
Console.WriteLn(L"(FileMcd) Creating new PSX 128 KiB memory card: '%s'", WX_STR(mcdFile));
}
wxFFile fp( mcdFile, L"wb" ); wxFFile fp( mcdFile, L"wb" );
if( !fp.IsOpened() ) return false; if( !fp.IsOpened() ) return false;
static const int MC2_MBSIZE = 1024 * 528 * 2; // Size of a single megabyte of card data static const int MC2_MBSIZE = 1024 * 528 * 2; // Size of a single megabyte of card data
for( uint i=0; i<(MC2_MBSIZE*sizeInMB)/sizeof(m_effeffs); i++ ) if (!isPSX) {
{ for (uint i = 0; i<(MC2_MBSIZE*sizeInMB) / sizeof(m_effeffs); i++) {
if( fp.Write( m_effeffs, sizeof(m_effeffs) ) == 0 ) if (fp.Write(m_effeffs, sizeof(m_effeffs)) == 0) {
return false; return false;
}
}
} else {
// PSX cards consist of 16 blocks, each 8 KiB in size.
for (uint i = 0; i < 16; i++) {
if (fp.Write(m_effeffs_psx, sizeof(m_effeffs_psx)) == 0) {
return false;
}
}
} }
return true; return true;
@ -170,9 +192,10 @@ void Dialogs::CreateMemoryCardDialog::OnOk_Click( wxCommandEvent& evt )
} }
} else { } else {
// otherwise create a file // otherwise create a file
if ( !CreateIt( if (!CreateIt(
fullPath, fullPath,
m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8 m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8,
m_check_psx->GetValue()
) ) { ) ) {
Msgbox::Alert( Msgbox::Alert(
_( "Error: The memory card could not be created." ), _( "Error: The memory card could not be created." ),
@ -230,5 +253,7 @@ void Dialogs::CreateMemoryCardDialog::CreateControls()
m_radio_CardSize = new pxRadioPanel( this, tbl_CardSizes ); m_radio_CardSize = new pxRadioPanel( this, tbl_CardSizes );
m_radio_CardSize->SetDefaultItem(0); m_radio_CardSize->SetDefaultItem(0);
m_check_psx = new pxCheckBox(this, "Make this a PSX card (128 KiB only, no folders!)");
} }

View File

@ -551,7 +551,7 @@ void Panels::MemoryCardListPanel_Simple::AppStatusEvent_OnSettingsApplied()
wxString errMsg; wxString errMsg;
if (isValidNewFilename(m_Cards[slot].Filename.GetFullName(), GetMcdPath(), errMsg, 5)) if (isValidNewFilename(m_Cards[slot].Filename.GetFullName(), GetMcdPath(), errMsg, 5))
{ {
if ( !Dialogs::CreateMemoryCardDialog::CreateIt(targetFile, 8) ) if ( !Dialogs::CreateMemoryCardDialog::CreateIt(targetFile, 8, false) )
Console.Error( L"Automatic createion of MCD '%s' failed. Hope for the best...", WX_STR(targetFile) ); Console.Error( L"Automatic createion of MCD '%s' failed. Hope for the best...", WX_STR(targetFile) );
else else
Console.WriteLn( L"memcard created: '%s'.", WX_STR(targetFile) ); Console.WriteLn( L"memcard created: '%s'.", WX_STR(targetFile) );