Added preliminary hotswapping and "Memorycard Not Present" support to the SIO. Among other things, this fixes memcard problems when using savestates, where-by some games would fail to recognize that the memory card had changed. So those of you with savestates for games that refuse to save to a newly-formatted memcard, this *should* allow you to save now. :)

Added several new files to organize some large files: HwRead.cpp, HwWrite.cpp, MemoryCard.cpp, MemoryCard.h.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@459 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-02-09 17:53:35 +00:00
parent 098c38113a
commit 632b73ccad
8 changed files with 1542 additions and 1353 deletions

File diff suppressed because it is too large Load Diff

359
pcsx2/HwRead.cpp Normal file
View File

@ -0,0 +1,359 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "PrecompiledHeader.h"
#include "Common.h"
#include "iR5900.h"
#include "VUmicro.h"
#include "IopMem.h"
// The full suite of hardware APIs:
#include "IPU/IPU.h"
#include "GS.h"
#include "Counters.h"
#include "Vif.h"
#include "VifDma.h"
#include "SPR.h"
#include "Sif.h"
using namespace R5900;
/////////////////////////////////////////////////////////////////////////
// Hardware READ 8 bit
__forceinline u8 hwRead8(u32 mem)
{
u8 ret;
if( mem >= 0x10002000 && mem < 0x10008000 )
DevCon::Notice("Unexpected hwRead8 from 0x%x", params mem);
switch (mem)
{
case 0x10000000: ret = (u8)rcntRcount(0); break;
case 0x10000010: ret = (u8)counters[0].modeval; break;
case 0x10000020: ret = (u8)counters[0].target; break;
case 0x10000030: ret = (u8)counters[0].hold; break;
case 0x10000001: ret = (u8)(rcntRcount(0)>>8); break;
case 0x10000011: ret = (u8)(counters[0].modeval>>8); break;
case 0x10000021: ret = (u8)(counters[0].target>>8); break;
case 0x10000031: ret = (u8)(counters[0].hold>>8); break;
case 0x10000800: ret = (u8)rcntRcount(1); break;
case 0x10000810: ret = (u8)counters[1].modeval; break;
case 0x10000820: ret = (u8)counters[1].target; break;
case 0x10000830: ret = (u8)counters[1].hold; break;
case 0x10000801: ret = (u8)(rcntRcount(1)>>8); break;
case 0x10000811: ret = (u8)(counters[1].modeval>>8); break;
case 0x10000821: ret = (u8)(counters[1].target>>8); break;
case 0x10000831: ret = (u8)(counters[1].hold>>8); break;
case 0x10001000: ret = (u8)rcntRcount(2); break;
case 0x10001010: ret = (u8)counters[2].modeval; break;
case 0x10001020: ret = (u8)counters[2].target; break;
case 0x10001001: ret = (u8)(rcntRcount(2)>>8); break;
case 0x10001011: ret = (u8)(counters[2].modeval>>8); break;
case 0x10001021: ret = (u8)(counters[2].target>>8); break;
case 0x10001800: ret = (u8)rcntRcount(3); break;
case 0x10001810: ret = (u8)counters[3].modeval; break;
case 0x10001820: ret = (u8)counters[3].target; break;
case 0x10001801: ret = (u8)(rcntRcount(3)>>8); break;
case 0x10001811: ret = (u8)(counters[3].modeval>>8); break;
case 0x10001821: ret = (u8)(counters[3].target>>8); break;
default:
if ((mem & 0xffffff0f) == 0x1000f200)
{
if(mem == 0x1000f260) ret = 0;
else if(mem == 0x1000F240) {
ret = psHu32(mem);
//psHu32(mem) &= ~0x4000;
}
else ret = psHu32(mem);
return (u8)ret;
}
ret = psHu8(mem);
HW_LOG("Unknown Hardware Read 8 at %x\n",mem);
break;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 16 bit
__forceinline u16 hwRead16(u32 mem)
{
u16 ret;
if( mem >= 0x10002000 && mem < 0x10008000 )
Console::Notice("Unexpected hwRead16 from 0x%x", params mem);
switch (mem) {
case 0x10000000: ret = (u16)rcntRcount(0); break;
case 0x10000010: ret = (u16)counters[0].modeval; break;
case 0x10000020: ret = (u16)counters[0].target; break;
case 0x10000030: ret = (u16)counters[0].hold; break;
case 0x10000800: ret = (u16)rcntRcount(1); break;
case 0x10000810: ret = (u16)counters[1].modeval; break;
case 0x10000820: ret = (u16)counters[1].target; break;
case 0x10000830: ret = (u16)counters[1].hold; break;
case 0x10001000: ret = (u16)rcntRcount(2); break;
case 0x10001010: ret = (u16)counters[2].modeval; break;
case 0x10001020: ret = (u16)counters[2].target; break;
case 0x10001800: ret = (u16)rcntRcount(3); break;
case 0x10001810: ret = (u16)counters[3].modeval; break;
case 0x10001820: ret = (u16)counters[3].target; break;
default:
if ((mem & 0xffffff0f) == 0x1000f200) {
if(mem == 0x1000f260) ret = 0;
else if(mem == 0x1000F240) {
ret = psHu16(mem) | 0x0102;
psHu32(mem) &= ~0x4000;
}
else ret = psHu32(mem);
return (u16)ret;
}
ret = psHu16(mem);
HW_LOG("Hardware Read16 at 0x%x, value= 0x%x\n", ret, mem);
break;
}
return ret;
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 32 bit
// Reads hardware registers for page 0 (counters 0 and 1)
mem32_t __fastcall hwRead32_page_00(u32 mem)
{
mem &= 0xffff;
switch( mem )
{
case 0x00: return (u16)rcntRcount(0);
case 0x10: return (u16)counters[0].modeval;
case 0x20: return (u16)counters[0].target;
case 0x30: return (u16)counters[0].hold;
case 0x800: return (u16)rcntRcount(1);
case 0x810: return (u16)counters[1].modeval;
case 0x820: return (u16)counters[1].target;
case 0x830: return (u16)counters[1].hold;
}
return *((u32*)&PS2MEM_HW[mem]);
}
// Reads hardware registers for page 1 (counters 2 and 3)
mem32_t __fastcall hwRead32_page_01(u32 mem)
{
mem &= 0xffff;
switch( mem )
{
case 0x1000: return (u16)rcntRcount(2);
case 0x1010: return (u16)counters[2].modeval;
case 0x1020: return (u16)counters[2].target;
case 0x1800: return (u16)rcntRcount(3);
case 0x1810: return (u16)counters[3].modeval;
case 0x1820: return (u16)counters[3].target;
}
return *((u32*)&PS2MEM_HW[mem]);
}
// Reads hardware registers for page 15 (0x0F).
mem32_t __fastcall hwRead32_page_0F(u32 mem)
{
// *Performance Warning* This function is called -A-LOT. Be weary when making changes. It
// could impact FPS significantly.
mem &= 0xffff;
switch( mem )
{
case 0xf000:
// This one is checked alot, so leave it commented out unless you love 600 meg logfiles.
//HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010));
break;
case 0xf010:
HW_LOG("INTC_MASK Read32, value=0x%x", psHu32(INTC_MASK));
break;
case 0xf130: // 0x1000f130
case 0xf260: // 0x1000f260 SBUS?
case 0xf410: // 0x1000f410
case 0xf430: // MCH_RICM
return 0;
case 0xf240: // 0x1000f240: SBUS
return psHu32(0xf240) | 0xF0000102;
case 0xf440: // 0x1000f440: MCH_DRD
if( !((psHu32(0xf430) >> 6) & 0xF) )
{
switch ((psHu32(0xf430)>>16) & 0xFFF)
{
//MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
case 0x21://INIT
if(rdram_sdevid < rdram_devices)
{
rdram_sdevid++;
return 0x1F;
}
return 0;
case 0x23://CNFGA
return 0x0D0D; //PVER=3 | MVER=16 | DBL=1 | REFBIT=5
case 0x24://CNFGB
//0x0110 for PSX SVER=0 | CORG=8(5x9x7) | SPT=1 | DEVTYP=0 | BYTE=0
return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0
case 0x40://DEVID
return psHu32(0xf430) & 0x1F; // =SDEV
}
}
return 0;
}
return *((u32*)&PS2MEM_HW[mem]);
}
mem32_t __fastcall hwRead32_page_02(u32 mem)
{
return ipuRead32( mem );
}
// Used for all pages not explicitly specified above.
mem32_t __fastcall hwRead32_generic(u32 mem)
{
const u16 masked_mem = mem & 0xffff;
switch( masked_mem>>12 ) // switch out as according to the 4k page of the access.
{
///////////////////////////////////////////////////////
// Most of the following case handlers are for developer builds only (logging).
// It'll all optimize to ziltch in public release builds.
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
{
const char* regName = "Unknown";
switch( mem )
{
case D2_CHCR: regName = "DMA2_CHCR"; break;
case D2_MADR: regName = "DMA2_MADR"; break;
case D2_QWC: regName = "DMA2_QWC"; break;
case D2_TADR: regName = "DMA2_TADDR"; break;
case D2_ASR0: regName = "DMA2_ASR0"; break;
case D2_ASR1: regName = "DMA2_ASR1"; break;
case D2_SADR: regName = "DMA2_SADDR"; break;
}
HW_LOG( "Hardware Read32 at 0x%x (%s), value=0x%x\n", mem, regName, psHu32(mem) );
}
break;
case 0x0b:
if( mem == D4_CHCR )
HW_LOG("Hardware Read32 at 0x%x (IPU1:DMA4_CHCR), value=0x%x\n", mem, psHu32(mem));
break;
case 0x0c:
case 0x0d:
case 0x0e:
if( mem == DMAC_STAT )
HW_LOG("DMAC_STAT Read32, value=0x%x\n", psHu32(DMAC_STAT));
break;
jNO_DEFAULT;
}
return *((u32*)&PS2MEM_HW[masked_mem]);
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 64 bit
void __fastcall hwRead64_page_00(u32 mem, mem64_t* result )
{
*result = hwRead32_page_00( mem );
}
void __fastcall hwRead64_page_01(u32 mem, mem64_t* result )
{
*result = hwRead32_page_01( mem );
}
void __fastcall hwRead64_page_02(u32 mem, mem64_t* result )
{
*result = ipuRead64(mem);
}
void __fastcall hwRead64_generic(u32 mem, mem64_t* result )
{
*result = psHu64(mem);
HW_LOG("Unknown Hardware Read 64 at %x\n",mem);
}
/////////////////////////////////////////////////////////////////////////
// Hardware READ 128 bit
void __fastcall hwRead128_page_00(u32 mem, mem128_t* result )
{
result[0] = hwRead32_page_00( mem );
result[1] = 0;
}
void __fastcall hwRead128_page_01(u32 mem, mem128_t* result )
{
result[0] = hwRead32_page_01( mem );
result[1] = 0;
}
void __fastcall hwRead128_page_02(u32 mem, mem128_t* result )
{
// IPU is currently unhandled in 128 bit mode.
HW_LOG("Unknown Hardware Read 128 at %x (IPU)\n",mem);
}
void __fastcall hwRead128_generic(u32 mem, mem128_t* out)
{
out[0] = psHu64(mem);
out[1] = psHu64(mem+8);
HW_LOG("Unknown Hardware Read 128 at %x\n",mem);
}

880
pcsx2/HwWrite.cpp Normal file
View File

@ -0,0 +1,880 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "PrecompiledHeader.h"
#include "Common.h"
#include "iR5900.h"
#include "VUmicro.h"
#include "IopMem.h"
// The full suite of hardware APIs:
#include "IPU/IPU.h"
#include "GS.h"
#include "Counters.h"
#include "Vif.h"
#include "VifDma.h"
#include "SPR.h"
#include "Sif.h"
using namespace R5900;
/////////////////////////////////////////////////////////////////////////
// DMA Execution Interfaces
// dark cloud2 uses 8 bit DMAs register writes
static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
{
psHu8(mem) = (u8)value;
if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1))
{
/*SysPrintf("Running DMA 8 %x\n", psHu32(mem & ~0x1));*/
func();
}
}
static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
{
psHu16(mem) = (u16)value;
if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1))
{
//SysPrintf("16bit DMA Start\n");
func();
}
}
static void DmaExec( void (*func)(), u32 mem, u32 value )
{
/* Keep the old tag if in chain mode and hw doesnt set it*/
if( (value & 0xc) == 0x4 && (value & 0xffff0000) == 0)
psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value;
else /* Else (including Normal mode etc) write whatever the hardware sends*/
psHu32(mem) = (u32)value;
if ((psHu32(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1))
func();
}
/////////////////////////////////////////////////////////////////////////
// Hardware WRITE 8 bit
char sio_buffer[1024];
int sio_count;
void hwWrite8(u32 mem, u8 value) {
#ifdef PCSX2_DEVBUILD
if( mem >= 0x10002000 && mem < 0x10008000 )
SysPrintf("hwWrite8 to %x\n", mem);
#endif
switch (mem) {
case 0x10000000: rcntWcount(0, value); break;
case 0x10000010: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break;
case 0x10000011: rcntWmode(0, (counters[0].modeval & 0xff) | value << 8); break;
case 0x10000020: rcntWtarget(0, value); break;
case 0x10000030: rcntWhold(0, value); break;
case 0x10000800: rcntWcount(1, value); break;
case 0x10000810: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break;
case 0x10000811: rcntWmode(1, (counters[1].modeval & 0xff) | value << 8); break;
case 0x10000820: rcntWtarget(1, value); break;
case 0x10000830: rcntWhold(1, value); break;
case 0x10001000: rcntWcount(2, value); break;
case 0x10001010: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break;
case 0x10001011: rcntWmode(2, (counters[2].modeval & 0xff) | value << 8); break;
case 0x10001020: rcntWtarget(2, value); break;
case 0x10001800: rcntWcount(3, value); break;
case 0x10001810: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break;
case 0x10001811: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break;
case 0x10001820: rcntWtarget(3, value); break;
case 0x1000f180:
if (value == '\n') {
sio_buffer[sio_count] = 0;
Console::WriteLn( Color_Cyan, sio_buffer );
sio_count = 0;
} else {
if (sio_count < 1023) {
sio_buffer[sio_count++] = value;
}
}
break;
case 0x10003c02: //Tony Hawks Project 8 uses this
vif1Write32(mem & ~0x2, value << 16);
break;
case 0x10008001: // dma0 - vif0
DMA_LOG("VIF0dma %lx\n", value);
DmaExec8(dmaVIF0, mem, value);
break;
case 0x10009001: // dma1 - vif1
DMA_LOG("VIF1dma %lx\n", value);
DmaExec8(dmaVIF1, mem, value);
break;
case 0x1000a001: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite8: GSdma %lx 0x%lx\n", cpuRegs.cycle, value);
DmaExec8(dmaGIF, mem, value);
break;
case 0x1000b001: // dma3 - fromIPU
DMA_LOG("IPU0dma %lx\n", value);
DmaExec8(dmaIPU0, mem, value);
break;
case 0x1000b401: // dma4 - toIPU
DMA_LOG("IPU1dma %lx\n", value);
DmaExec8(dmaIPU1, mem, value);
break;
case 0x1000c001: // dma5 - sif0
DMA_LOG("SIF0dma %lx\n", value);
// if (value == 0) psxSu32(0x30) = 0x40000;
DmaExec8(dmaSIF0, mem, value);
break;
case 0x1000c401: // dma6 - sif1
DMA_LOG("SIF1dma %lx\n", value);
DmaExec8(dmaSIF1, mem, value);
break;
case 0x1000c801: // dma7 - sif2
DMA_LOG("SIF2dma %lx\n", value);
DmaExec8(dmaSIF2, mem, value);
break;
case 0x1000d001: // dma8 - fromSPR
DMA_LOG("fromSPRdma8 %lx\n", value);
DmaExec8(dmaSPR0, mem, value);
break;
case 0x1000d401: // dma9 - toSPR
DMA_LOG("toSPRdma8 %lx\n", value);
DmaExec8(dmaSPR1, mem, value);
break;
case 0x1000f592: // DMAC_ENABLEW
psHu8(0xf592) = value;
psHu8(0xf522) = value;
break;
case 0x1000f200: // SIF(?)
psHu8(mem) = value;
break;
case 0x1000f240:// SIF(?)
if(!(value & 0x100))
psHu32(mem) &= ~0x100;
break;
default:
assert( (mem&0xff0f) != 0xf200 );
switch(mem&~3) {
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu8(mem) = value;
}
HW_LOG("Unknown Hardware write 8 at %x with value %x\n", mem, value);
break;
}
}
__forceinline void hwWrite16(u32 mem, u16 value)
{
if( mem >= 0x10002000 && mem < 0x10008000 )
Console::Notice( "hwWrite16 to %x", params mem );
switch(mem)
{
case 0x10000000: rcntWcount(0, value); break;
case 0x10000010: rcntWmode(0, value); break;
case 0x10000020: rcntWtarget(0, value); break;
case 0x10000030: rcntWhold(0, value); break;
case 0x10000800: rcntWcount(1, value); break;
case 0x10000810: rcntWmode(1, value); break;
case 0x10000820: rcntWtarget(1, value); break;
case 0x10000830: rcntWhold(1, value); break;
case 0x10001000: rcntWcount(2, value); break;
case 0x10001010: rcntWmode(2, value); break;
case 0x10001020: rcntWtarget(2, value); break;
case 0x10001800: rcntWcount(3, value); break;
case 0x10001810: rcntWmode(3, value); break;
case 0x10001820: rcntWtarget(3, value); break;
case 0x10008000: // dma0 - vif0
DMA_LOG("VIF0dma %lx\n", value);
DmaExec16(dmaVIF0, mem, value);
break;
case 0x10009000: // dma1 - vif1 - chcr
DMA_LOG("VIF1dma CHCR %lx\n", value);
DmaExec16(dmaVIF1, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x10009010: // dma1 - vif1 - madr
HW_LOG("VIF1dma Madr %lx\n", value);
psHu16(mem) = value;//dma1 madr
break;
case 0x10009020: // dma1 - vif1 - qwc
HW_LOG("VIF1dma QWC %lx\n", value);
psHu16(mem) = value;//dma1 qwc
break;
case 0x10009030: // dma1 - vif1 - tadr
HW_LOG("VIF1dma TADR %lx\n", value);
psHu16(mem) = value;//dma1 tadr
break;
case 0x10009040: // dma1 - vif1 - asr0
HW_LOG("VIF1dma ASR0 %lx\n", value);
psHu16(mem) = value;//dma1 asr0
break;
case 0x10009050: // dma1 - vif1 - asr1
HW_LOG("VIF1dma ASR1 %lx\n", value);
psHu16(mem) = value;//dma1 asr1
break;
case 0x10009080: // dma1 - vif1 - sadr
HW_LOG("VIF1dma SADR %lx\n", value);
psHu16(mem) = value;//dma1 sadr
break;
#endif
// ---------------------------------------------------
case 0x1000a000: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value);
DmaExec16(dmaGIF, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000a010:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value);
break;
case 0x1000a020:
psHu16(mem) = value;//dma2 qwc
HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value);
break;
case 0x1000a030:
psHu16(mem) = value;//dma2 taddr
HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value);
break;
case 0x1000a040:
psHu16(mem) = value;//dma2 asr0
HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value);
break;
case 0x1000a050:
psHu16(mem) = value;//dma2 asr1
HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value);
break;
case 0x1000a080:
psHu16(mem) = value;//dma2 saddr
HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value);
break;
#endif
case 0x1000b000: // dma3 - fromIPU
DMA_LOG("IPU0dma %lx\n", value);
DmaExec16(dmaIPU0, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000b010:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value);
break;
case 0x1000b020:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value);
break;
case 0x1000b030:
psHu16(mem) = value;//dma2 tadr
HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value);
break;
case 0x1000b080:
psHu16(mem) = value;//dma2 saddr
HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value);
break;
#endif
case 0x1000b400: // dma4 - toIPU
DMA_LOG("IPU1dma %lx\n", value);
DmaExec16(dmaIPU1, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000b410:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value);
break;
case 0x1000b420:
psHu16(mem) = value;//dma2 madr
HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value);
break;
case 0x1000b430:
psHu16(mem) = value;//dma2 tadr
HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value);
break;
case 0x1000b480:
psHu16(mem) = value;//dma2 saddr
HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value);
break;
#endif
case 0x1000c000: // dma5 - sif0
DMA_LOG("SIF0dma %lx\n", value);
// if (value == 0) psxSu32(0x30) = 0x40000;
DmaExec16(dmaSIF0, mem, value);
break;
case 0x1000c002:
//?
break;
case 0x1000c400: // dma6 - sif1
DMA_LOG("SIF1dma %lx\n", value);
DmaExec16(dmaSIF1, mem, value);
break;
#ifdef PCSX2_DEVBUILD
case 0x1000c420: // dma6 - sif1 - qwc
HW_LOG("SIF1dma QWC = %lx\n", value);
psHu16(mem) = value;
break;
case 0x1000c430: // dma6 - sif1 - tadr
HW_LOG("SIF1dma TADR = %lx\n", value);
psHu16(mem) = value;
break;
#endif
case 0x1000c800: // dma7 - sif2
DMA_LOG("SIF2dma %lx\n", value);
DmaExec16(dmaSIF2, mem, value);
break;
case 0x1000c802:
//?
break;
case 0x1000d000: // dma8 - fromSPR
DMA_LOG("fromSPRdma %lx\n", value);
DmaExec16(dmaSPR0, mem, value);
break;
case 0x1000d400: // dma9 - toSPR
DMA_LOG("toSPRdma %lx\n", value);
DmaExec16(dmaSPR1, mem, value);
break;
case 0x1000f592: // DMAC_ENABLEW
psHu16(0xf592) = value;
psHu16(0xf522) = value;
break;
case 0x1000f130:
case 0x1000f132:
case 0x1000f410:
case 0x1000f412:
case 0x1000f430:
case 0x1000f432:
break;
case 0x1000f200:
psHu16(mem) = value;
break;
case 0x1000f220:
psHu16(mem) |= value;
break;
case 0x1000f230:
psHu16(mem) &= ~value;
break;
case 0x1000f240:
if(!(value & 0x100))
psHu16(mem) &= ~0x100;
else
psHu16(mem) |= 0x100;
break;
case 0x1000f260:
psHu16(mem) = 0;
break;
default:
psHu16(mem) = value;
HW_LOG("Unknown Hardware write 16 at %x with value %x\n",mem,value);
}
}
// Page 0 of HW memory houses registers for Counters 0 and 1
void __fastcall hwWrite32_page_00( u32 mem, u32 value )
{
mem &= 0xffff;
switch (mem)
{
case 0x000: rcntWcount(0, value); return;
case 0x010: rcntWmode(0, value); return;
case 0x020: rcntWtarget(0, value); return;
case 0x030: rcntWhold(0, value); return;
case 0x800: rcntWcount(1, value); return;
case 0x810: rcntWmode(1, value); return;
case 0x820: rcntWtarget(1, value); return;
case 0x830: rcntWhold(1, value); return;
}
*((u32*)&PS2MEM_HW[mem]) = value;
}
// Page 1 of HW memory houses registers for Counters 2 and 3
void __fastcall hwWrite32_page_01( u32 mem, u32 value )
{
mem &= 0xffff;
switch (mem)
{
case 0x1000: rcntWcount(2, value); return;
case 0x1010: rcntWmode(2, value); return;
case 0x1020: rcntWtarget(2, value); return;
case 0x1800: rcntWcount(3, value); return;
case 0x1810: rcntWmode(3, value); return;
case 0x1820: rcntWtarget(3, value); return;
}
*((u32*)&PS2MEM_HW[mem]) = value;
}
// page 2 is the IPU register space!
void __fastcall hwWrite32_page_02( u32 mem, u32 value )
{
ipuWrite32(mem, value);
}
// Page 3 contains writes to vif0 and vif1 registers, plus some GIF stuff!
void __fastcall hwWrite32_page_03( u32 mem, u32 value )
{
if(mem>=0x10003800)
{
if(mem<0x10003c00)
vif0Write32(mem, value);
else
vif1Write32(mem, value);
return;
}
switch (mem)
{
case GIF_CTRL:
psHu32(mem) = value & 0x8;
if (value & 0x1)
gsGIFReset();
else if( value & 8 )
psHu32(GIF_STAT) |= 8;
else
psHu32(GIF_STAT) &= ~8;
break;
case GIF_MODE:
{
// need to set GIF_MODE (hamster ball)
psHu32(GIF_MODE) = value;
// set/clear bits 0 and 2 as per the GIF_MODE value.
const u32 bitmask = 0x1 | 0x4;
psHu32(GIF_STAT) &= ~bitmask;
psHu32(GIF_STAT) |= (u32)value & bitmask;
}
break;
case GIF_STAT: // stat is readonly
DevCon::Notice("*PCSX2* GIFSTAT write value = 0x%x (readonly, ignored)", params value);
break;
default:
psHu32(mem) = value;
}
}
void __fastcall hwWrite32_page_0B( u32 mem, u32 value )
{
// Used for developer logging -- optimized away in Public Release.
const char* regName = "Unknown";
switch( mem )
{
case D3_CHCR: // dma3 - fromIPU
DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaIPU0, mem, value);
return;
case D3_MADR: regName = "IPU0DMA_MADR"; break;
case D3_QWC: regName = "IPU0DMA_QWC"; break;
case D3_TADR: regName = "IPU0DMA_TADR"; break;
case D3_SADR: regName = "IPU0DMA_SADDR"; break;
//------------------------------------------------------------------
case D4_CHCR: // dma4 - toIPU
DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaIPU1, mem, value);
return;
case D4_MADR: regName = "IPU1DMA_MADR"; break;
case D4_QWC: regName = "IPU1DMA_QWC"; break;
case D4_TADR: regName = "IPU1DMA_TADR"; break;
case D4_SADR: regName = "IPU1DMA_SADDR"; break;
}
HW_LOG( "Hardware Write32 at 0x%x (%s), value=0x%x\n", mem, regName, value );
psHu32(mem) = value;
}
void __fastcall hwWrite32_page_0E( u32 mem, u32 value )
{
if( mem == DMAC_CTRL )
{
HW_LOG("DMAC_CTRL Write 32bit %x\n", value);
}
else if( mem == DMAC_STAT )
{
HW_LOG("DMAC_STAT Write 32bit %x\n", value);
// lower 16 bits: clear on 1
// upper 16 bits: reverse on 1
psHu16(0xe010) &= ~(value & 0xffff);
psHu16(0xe012) ^= (u16)(value >> 16);
cpuTestDMACInts();
return;
}
psHu32(mem) = value;
}
void __fastcall hwWrite32_page_0F( u32 mem, u32 value )
{
// Shift the middle 8 bits (bits 4-12) into the lower 8 bits.
// This helps the compiler optimize the switch statement into a lookup table. :)
#define HELPSWITCH(m) (((m)>>4) & 0xff)
switch( HELPSWITCH(mem) )
{
case HELPSWITCH(INTC_STAT):
HW_LOG("INTC_STAT Write 32bit %x\n", value);
psHu32(INTC_STAT) &= ~value;
//cpuTestINTCInts();
break;
case HELPSWITCH(INTC_MASK):
HW_LOG("INTC_MASK Write 32bit %x\n", value);
psHu32(INTC_MASK) ^= (u16)value;
cpuTestINTCInts();
break;
//------------------------------------------------------------------
case HELPSWITCH(0x1000f430)://MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
if ((((value >> 16) & 0xFFF) == 0x21) && (((value >> 6) & 0xF) == 1) && (((psHu32(0xf440) >> 7) & 1) == 0))//INIT & SRP=0
rdram_sdevid = 0; // if SIO repeater is cleared, reset sdevid
psHu32(mem) = value & ~0x80000000; //kill the busy bit
break;
case HELPSWITCH(0x1000f200):
psHu32(mem) = value;
break;
case HELPSWITCH(0x1000f220):
psHu32(mem) |= value;
break;
case HELPSWITCH(0x1000f230):
psHu32(mem) &= ~value;
break;
case HELPSWITCH(0x1000f240):
if(!(value & 0x100))
psHu32(mem) &= ~0x100;
else
psHu32(mem) |= 0x100;
break;
case HELPSWITCH(0x1000f260):
psHu32(mem) = 0;
break;
case HELPSWITCH(0x1000f440)://MCH_DRD:
psHu32(mem) = value;
break;
case HELPSWITCH(0x1000f590): // DMAC_ENABLEW
HW_LOG("DMAC_ENABLEW Write 32bit %lx\n", value);
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
//------------------------------------------------------------------
case HELPSWITCH(0x1000f130):
case HELPSWITCH(0x1000f410):
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status.val);
break;
default:
psHu32(mem) = value;
}
}
void __fastcall hwWrite32_generic( u32 mem, u32 value )
{
// Used for developer logging -- optimized away in Public Release.
const char* regName = "Unknown";
switch (mem)
{
case D0_CHCR: // dma0 - vif0
DMA_LOG("VIF0dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaVIF0, mem, value);
return;
//------------------------------------------------------------------
case D1_CHCR: // dma1 - vif1 - chcr
DMA_LOG("VIF1dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaVIF1, mem, value);
return;
case D1_MADR: regName = "VIF1dma MADR"; break;
case D1_QWC: regName = "VIF1dma QWC"; break;
case D1_TADR: regName = "VIF1dma TADR"; break;
case D1_ASR0: regName = "VIF1dma ASR0"; break;
case D1_ASR1: regName = "VIF1dma ASR1"; break;
case D1_SADR: regName = "VIF1dma SADR"; break;
//------------------------------------------------------------------
case D2_CHCR: // dma2 - gif
DMA_LOG("GIFdma EXECUTE, value=0x%x", value);
DmaExec(dmaGIF, mem, value);
return;
case D2_MADR: regName = "GIFdma MADR"; break;
case D2_QWC: regName = "GIFdma QWC"; break;
case D2_TADR: regName = "GIFdma TADDR"; break;
case D2_ASR0: regName = "GIFdma ASR0"; break;
case D2_ASR1: regName = "GIFdma ASR1"; break;
case D2_SADR: regName = "GIFdma SADDR"; break;
//------------------------------------------------------------------
case 0x1000c000: // dma5 - sif0
DMA_LOG("SIF0dma EXECUTE, value=0x%x\n", value);
//if (value == 0) psxSu32(0x30) = 0x40000;
DmaExec(dmaSIF0, mem, value);
return;
//------------------------------------------------------------------
case 0x1000c400: // dma6 - sif1
DMA_LOG("SIF1dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaSIF1, mem, value);
return;
case 0x1000c420: regName = "SIF1dma QWC"; break;
case 0x1000c430: regName = "SIF1dma TADR"; break;
//------------------------------------------------------------------
case 0x1000c800: // dma7 - sif2
DMA_LOG("SIF2dma EXECUTE, value=0x%x\n", value);
DmaExec(dmaSIF2, mem, value);
return;
//------------------------------------------------------------------
case 0x1000d000: // dma8 - fromSPR
DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x\n", value);
DmaExec(dmaSPR0, mem, value);
return;
//------------------------------------------------------------------
case 0x1000d400: // dma9 - toSPR
DMA_LOG("SPR0dma EXECUTE (toSPR), value=0x%x\n", value);
DmaExec(dmaSPR1, mem, value);
return;
}
HW_LOG( "Hardware Write32 at 0x%x (%s), value=0x%x\n", mem, regName, value );
psHu32(mem) = value;
}
/////////////////////////////////////////////////////////////////////////
// HW Write 64 bit
void __fastcall hwWrite64_page_02( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
ipuWrite64( mem, *srcval );
}
void __fastcall hwWrite64_page_03( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
const u64 value = *srcval;
if(mem>=0x10003800)
{
if(mem<0x10003c00)
vif0Write32(mem, value);
else
vif1Write32(mem, value);
return;
}
switch (mem)
{
case GIF_CTRL:
DevCon::Status("GIF_CTRL write 64", params value);
psHu32(mem) = value & 0x8;
if(value & 0x1)
gsGIFReset();
else
{
if( value & 8 )
psHu32(GIF_STAT) |= 8;
else
psHu32(GIF_STAT) &= ~8;
}
return;
case GIF_MODE:
{
#ifdef GSPATH3FIX
Console::Status("GIFMODE64 %x\n", params value);
#endif
psHu64(GIF_MODE) = value;
// set/clear bits 0 and 2 as per the GIF_MODE value.
const u32 bitmask = 0x1 | 0x4;
psHu32(GIF_STAT) &= ~bitmask;
psHu32(GIF_STAT) |= (u32)value & bitmask;
}
case GIF_STAT: // stat is readonly
return;
}
}
void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
const u64 value = *srcval;
if( mem == DMAC_CTRL )
{
HW_LOG("DMAC_CTRL Write 64bit %x\n", value);
}
else if( mem == DMAC_STAT )
{
HW_LOG("DMAC_STAT Write 64bit %x\n", value);
// lower 16 bits: clear on 1
// upper 16 bits: reverse on 1
psHu16(0xe010) &= ~(value & 0xffff);
psHu16(0xe012) ^= (u16)(value >> 16);
cpuTestDMACInts();
return;
}
psHu64(mem) = value;
}
void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval )
{
//hwWrite64( mem, *srcval ); return;
const u64 value = *srcval;
switch (mem)
{
case 0x1000a000: // dma2 - gif
DMA_LOG("0x%8.8x hwWrite64: GSdma %x\n", cpuRegs.cycle, value);
DmaExec(dmaGIF, mem, value);
break;
case INTC_STAT:
HW_LOG("INTC_STAT Write 64bit %x\n", (u32)value);
psHu32(INTC_STAT) &= ~value;
//cpuTestINTCInts();
break;
case INTC_MASK:
HW_LOG("INTC_MASK Write 64bit %x\n", (u32)value);
psHu32(INTC_MASK) ^= (u16)value;
cpuTestINTCInts();
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = value;
psHu32(0xf520) = value;
break;
default:
psHu64(mem) = value;
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status.val);
break;
}
}
/////////////////////////////////////////////////////////////////////////
// HW Write 128 bit
void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval)
{
//hwWrite128( mem, srcval ); return;
switch (mem)
{
case INTC_STAT:
HW_LOG("INTC_STAT Write 64bit %x\n", (u32)srcval[0]);
psHu32(INTC_STAT) &= ~srcval[0];
//cpuTestINTCInts();
break;
case INTC_MASK:
HW_LOG("INTC_MASK Write 64bit %x\n", (u32)srcval[0]);
psHu32(INTC_MASK) ^= (u16)srcval[0];
cpuTestINTCInts();
break;
case 0x1000f590: // DMAC_ENABLEW
psHu32(0xf590) = srcval[0];
psHu32(0xf520) = srcval[0];
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu64(mem ) = srcval[0];
psHu64(mem+8) = srcval[1];
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, srcval[1], srcval[0], cpuRegs.CP0.n.Status.val);
break;
}
}

158
pcsx2/MemoryCard.cpp Normal file
View File

@ -0,0 +1,158 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "PrecompiledHeader.h"
#include "Misc.h"
#include "MemoryCard.h"
#include "Paths.h"
#ifdef WIN32
extern void NTFS_CompressFile( const char* file );
#endif
static FILE* MemoryCard[2] = { NULL, NULL };
// Ensures memory card files are created/initialized.
void MemoryCard_Init()
{
for( int i=0; i<2; i++ )
{
if( MemoryCard[i] == NULL )
MemoryCard[i] = LoadMcd(i);
}
}
void MemoryCard_Shutdown()
{
for( int i=0; i<2; i++ )
{
if(MemoryCard[0]) fclose(MemoryCard[i]);
MemoryCard[0] = NULL;
}
}
bool TestMcdIsPresent( int mcd )
{
jASSUME( mcd == 0 || mcd == 1 );
return MemoryCard[mcd] != NULL;
}
FILE *LoadMcd(int mcd)
{
string str;
FILE *f;
jASSUME( mcd == 0 || mcd == 1 );
str = (mcd == 0) ? Config.Mcd1 : Config.Mcd2;
if( str.empty() )
Path::Combine( str, MEMCARDS_DIR, fmt_string( "Mcd00%d.ps2", mcd ) );
if( !Path::Exists(str) )
CreateMcd(str.c_str());
#ifdef WIN32
NTFS_CompressFile( str.c_str() );
#endif
f = fopen(str.c_str(), "r+b");
if (f == NULL) {
Msgbox::Alert("Failed loading MemCard from file: %hs", params &str);
return NULL;
}
return f;
}
void SeekMcd(FILE *f, u32 adr)
{
u32 size;
fseek(f, 0, SEEK_END); size = ftell(f);
if (size == MCD_SIZE + 64)
fseek(f, adr + 64, SEEK_SET);
else if (size == MCD_SIZE + 3904)
fseek(f, adr + 3904, SEEK_SET);
else
fseek(f, adr, SEEK_SET);
}
void ReadMcd(int mcd, u8 *data, u32 adr, int size)
{
jASSUME( mcd == 0 || mcd == 1 );
FILE* const mcfp = MemoryCard[mcd];
if (mcfp == NULL) {
memset(data, 0, size);
return;
}
SeekMcd(mcfp, adr);
fread(data, 1, size, mcfp);
}
void SaveMcd(int mcd, const u8 *data, u32 adr, int size)
{
jASSUME( mcd == 0 || mcd == 1 );
FILE* const mcfp = MemoryCard[mcd];
SeekMcd(mcfp, adr);
u8 *currentdata = (u8 *)malloc(size);
fread(currentdata, 1, size, mcfp);
for (int i=0; i<size; i++)
{
if ((currentdata[i] & data[i]) != data[i])
Console::Notice("MemoryCard : writing odd data");
currentdata[i] &= data[i];
}
SeekMcd(mcfp, adr);
fwrite(currentdata, 1, size, mcfp);
free(currentdata);
}
void EraseMcd(int mcd, u32 adr)
{
u8 data[528*16];
memset8_obj<0xff>(data); // clears to -1's
jASSUME( mcd == 0 || mcd == 1 );
FILE* const mcfp = MemoryCard[mcd];
SeekMcd(mcfp, adr);
fwrite(data, 1, 528*16, mcfp);
}
void CreateMcd(const char *mcd)
{
FILE *fp;
int i=0, j=0;
//int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0};
fp = fopen(mcd, "wb");
if (fp == NULL) return;
for(i=0; i < 16384; i++)
{
for(j=0; j < 528; j++) fputc(0xFF,fp);
// for(j=0; j < 16; j++) fputc(enc[j],fp);
}
fclose(fp);
}

49
pcsx2/MemoryCard.h Normal file
View File

@ -0,0 +1,49 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _MEMORYCARD_H_
#define _MEMORYCARD_H_
static const int MCD_SIZE = 1024 * 8 * 16;
static const int MC2_SIZE = 1024 * 528 * 16;
extern void MemoryCard_Init();
extern void MemoryCard_Shutdown();
extern bool TestMcdIsPresent(int mcd);
extern FILE *LoadMcd(int mcd);
extern void ReadMcd(int mcd, u8 *data, u32 adr, int size);
extern void SaveMcd(int mcd, const u8 *data, u32 adr, int size);
extern void EraseMcd(int mcd, u32 adr);
extern void CreateMcd(const char *mcd);
#if 0 // unused code?
struct McdBlock
{
s8 Title[48];
s8 ID[14];
s8 Name[16];
int IconCount;
u16 Icon[16*16*3];
u8 Flags;
};
void GetMcdBlockInfo(int mcd, int block, McdBlock *info);
#endif
#endif

View File

@ -19,17 +19,17 @@
#include "PrecompiledHeader.h"
#include "PsxCommon.h"
#include "Paths.h"
#include "MemoryCard.h"
_sio sio;
static FILE * MemoryCard1=NULL, * MemoryCard2=NULL;
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};
static int m_PostSavestateCards[2] = { 0, 0 };
// 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)
@ -46,18 +46,18 @@ __forceinline void SIO_INT()
#endif
static void _ReadMcd(u8 *data, u32 adr, int size) {
ReadMcd(sio.CtrlReg&0x2000?2:1, data, adr, size);
ReadMcd(sio.GetMemcardIndex(), data, adr, size);
}
static void _SaveMcd(const u8 *data, u32 adr, int size) {
SaveMcd(sio.CtrlReg&0x2000?2:1, data, adr, size);
SaveMcd(sio.GetMemcardIndex(), data, adr, size);
}
static void _EraseMCDBlock(u32 adr) {
EraseMcd(sio.CtrlReg&0x2000?2:1, adr);
EraseMcd(sio.GetMemcardIndex(), adr);
}
u8 sio_xor(u8 *buf, unsigned int length){
u8 sio_xor(u8 *buf, uint length){
u8 i, x;
for (x=0, i=0; i<length; i++) x ^= buf[i];
@ -67,26 +67,18 @@ u8 sio_xor(u8 *buf, unsigned int length){
void sioInit()
{
memzero_obj(sio);
if( MemoryCard1 == NULL )
MemoryCard1 = LoadMcd(1);
if( MemoryCard2 == NULL )
MemoryCard2 = LoadMcd(2);
// Transfer(?) Ready and the Buffer is Empty
sio.StatReg = TX_RDY | TX_EMPTY;
sio.packetsize = 0;
sio.terminator =0x55; // Command terminator 'U'
MemoryCard_Init();
}
void psxSIOShutdown()
{
if(MemoryCard1) fclose(MemoryCard1);
if(MemoryCard2) fclose(MemoryCard2);
MemoryCard1 = NULL;
MemoryCard2 = NULL;
MemoryCard_Shutdown();
}
u8 sioRead8() {
@ -173,7 +165,7 @@ void SIO_CommandWrite(u8 value,int way) {
sio.mcdst = 99;
sio2.packet.recvVal3 = 0x8c;
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x81: // COMMIT
sio.bufcount = 8;
@ -187,7 +179,7 @@ void SIO_CommandWrite(u8 value,int way) {
sio2.packet.recvVal1 = 0x1600; // Writing
else if(sio.mc_command==0x43) sio2.packet.recvVal1 = 0x1700; // Reading
}
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x21:
case 0x22:
@ -197,20 +189,20 @@ void SIO_CommandWrite(u8 value,int way) {
sio2.packet.recvVal3 = 0x8c;
sio.buf[8]=sio.terminator;
sio.buf[7]='+';
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x24:
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x25:
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x26:
sio.bufcount = 12; sio.mcdst = 99; sio2.packet.recvVal3 = 0x83;
memset8_obj<0xff>(sio.buf);
memcpy(&sio.buf[2], &mc_command_0x26, sizeof(mc_command_0x26));
sio.buf[12]=sio.terminator;
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x27:
case 0x28:
@ -219,7 +211,7 @@ void SIO_CommandWrite(u8 value,int way) {
memset8_obj<0xff>(sio.buf);
sio.buf[4]=sio.terminator;
sio.buf[3]='+';
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x42: // WRITE
case 0x43: // READ
@ -232,13 +224,13 @@ void SIO_CommandWrite(u8 value,int way) {
memset8_obj<0xff>(sio.buf);
sio.buf[133]=sio.terminator;
sio.buf[132]='+';
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0xf0:
case 0xf1:
case 0xf2:
sio.mcdst = 99;
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0xf3:
case 0xf7:
@ -246,23 +238,23 @@ void SIO_CommandWrite(u8 value,int way) {
memset8_obj<0xff>(sio.buf);
sio.buf[4]=sio.terminator;
sio.buf[3]='+';
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x52:
sio.rdwr = 1; memset8_obj<0xff>(sio.buf);
sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
case 0x57:
sio.rdwr = 2; memset8_obj<0xff>(sio.buf);
sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
MEMCARDS_LOG("MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
break;
default:
sio.mcdst = 0;
memset8_obj<0xff>(sio.buf);
sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
MEMCARDS_LOG("Unknown MC(%d) command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("Unknown MC(%d) command 0x%02X\n", sio.GetMemcardIndex()+1, value);
}
sio.mc_command=value;
return;
@ -286,10 +278,10 @@ void SIO_CommandWrite(u8 value,int way) {
{
if (sio_xor((u8 *)&sio.sector, 4) == value)
MEMCARDS_LOG("MC(%d) SET PAGE sio.sector 0x%04X\n",
((sio.CtrlReg&0x2000)>>13)+1, sio.sector);
sio.GetMemcardIndex()+1, sio.sector);
else
MEMCARDS_LOG("MC(%d) SET PAGE XOR value ERROR 0x%02X != ^0x%02X\n",
((sio.CtrlReg&0x2000)>>13)+1, value, sio_xor((u8 *)&sio.sector, 4));
sio.GetMemcardIndex()+1, value, sio_xor((u8 *)&sio.sector, 4));
}
break;
@ -298,7 +290,7 @@ void SIO_CommandWrite(u8 value,int way) {
if(sio.parp==2) {
sio.terminator = value;
sio.buf[4] = value;
MEMCARDS_LOG("MC(%d) SET TERMINATOR command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) SET TERMINATOR command 0x%02X\n", sio.GetMemcardIndex()+1, value);
}
break;
@ -312,7 +304,7 @@ void SIO_CommandWrite(u8 value,int way) {
//if(value == 0) sio.buf[4] = 0xFF;
sio.buf[4] = 0x55;
MEMCARDS_LOG("MC(%d) GET TERMINATOR command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) GET TERMINATOR command 0x%02X\n", sio.GetMemcardIndex()+1, value);
}
break;
// WRITE DATA
@ -322,12 +314,12 @@ void SIO_CommandWrite(u8 value,int way) {
memset8_obj<0xff>(sio.buf);
sio.buf[sio.bufcount-1]='+';
sio.buf[sio.bufcount]=sio.terminator;
MEMCARDS_LOG("MC(%d) WRITE command 0x%02X\n\n\n\n\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) WRITE command 0x%02X\n\n\n\n\n", sio.GetMemcardIndex()+1, value);
}
else
if ((sio.parp>2) && (sio.parp<sio.bufcount-2)) {
sio.buf[sio.parp]=value;
//MEMCARDS_LOG("MC(%d) WRITING 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
//MEMCARDS_LOG("MC(%d) WRITING 0x%02X\n", sio.GetMemcardIndex()+1, value);
} else
if (sio.parp==sio.bufcount-2) {
if (sio_xor(&sio.buf[3], sio.bufcount-5)==value) {
@ -336,7 +328,7 @@ void SIO_CommandWrite(u8 value,int way) {
sio.k+=sio.bufcount-5;
}else {
MEMCARDS_LOG("MC(%d) write XOR value error 0x%02X != ^0x%02X\n",
((sio.CtrlReg&0x2000)>>13)+1, value, sio_xor(&sio.buf[3], sio.bufcount-5));
sio.GetMemcardIndex()+1, value, sio_xor(&sio.buf[3], sio.bufcount-5));
}
}
break;
@ -346,7 +338,7 @@ void SIO_CommandWrite(u8 value,int way) {
//int i;
sio.bufcount=value+5;
sio.buf[3]='+';
MEMCARDS_LOG("MC(%d) READ command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) READ command 0x%02X\n", sio.GetMemcardIndex()+1, value);
_ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value);
/*if(sio.mode==2)
{
@ -377,14 +369,14 @@ void SIO_CommandWrite(u8 value,int way) {
sio.buf[2]='+';
sio.buf[3]=sio.terminator;*/
//sio.buf[sio.bufcount] = sio.terminator;
MEMCARDS_LOG("MC(%d) INTERNAL ERASE command 0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) INTERNAL ERASE command 0x%02X\n", sio.GetMemcardIndex()+1, value);
}
break;
// CARD AUTHENTICATION CHECKS
case 0xF0:
if (sio.parp==2)
{
MEMCARDS_LOG("MC(%d) CARD AUTH :0x%02X\n", ((sio.CtrlReg&0x2000)>>13)+1, value);
MEMCARDS_LOG("MC(%d) CARD AUTH :0x%02X\n", sio.GetMemcardIndex()+1, value);
switch(value){
case 1:
case 2:
@ -487,6 +479,7 @@ void InitializeSIO(u8 value)
return;
case 0x81: // start memcard
{
sio.StatReg &= ~TX_EMPTY;
sio.StatReg |= RX_RDY;
memcpy(sio.buf, cardh, 4);
@ -495,11 +488,35 @@ void InitializeSIO(u8 value)
sio.mcdst = 1;
sio.packetsize = 1;
sio.rdwr = 0;
sio2.packet.recvVal1 = 0x1100; // Memcards are present
sio.count = 0;
// Memcard presence reporting!
// In addition to checking the presence of MemoryCard1/2 file handles, we check a
// variable which force-disables all memory cards after a savestate recovery. This
// is needed to inform certain games to clear their cached memorycard indexes.
// Note:
// 0x01100 means Memcard is present
// 0x1D100 means Memcard is missing.
const int mcidx = sio.GetMemcardIndex();
if( m_PostSavestateCards[mcidx] )
{
m_PostSavestateCards[mcidx]--;
sio2.packet.recvVal1 = 0x1D100;
PAD_LOG( "START MEMCARD[%d] - post-savestate - reported as missing!\n", sio.GetMemcardIndex() );
}
else
{
sio2.packet.recvVal1 = TestMcdIsPresent( sio.GetMemcardIndex() ) ? 0x1100 : 0x1D100;
PAD_LOG("START MEMCARD [%d] - %s\n",
sio.GetMemcardIndex(), TestMcdIsPresent( sio.GetMemcardIndex() ) ? "Present" : "Missing" );
}
SIO_INT();
PAD_LOG("START MEMORY CARD\n");
return;
}
return;
}
}
@ -534,118 +551,14 @@ void SaveState::sioFreeze()
{
Freeze( sio );
//if( IsLoading() )
// sio.count = 0;
}
/*******************************************************************
*******************************************************************
*************** MEMORY CARD SPECIFIC FUNCTIONS *****************
*******************************************************************
*******************************************************************/
#ifdef WIN32
extern void NTFS_CompressFile( const char* file );
#endif
FILE *LoadMcd(int mcd)
{
string str;
FILE *f;
str = (mcd == 1) ? Config.Mcd1 : Config.Mcd2;
if( str.empty() )
Path::Combine( str, MEMCARDS_DIR, fmt_string( "Mcd00%d.ps2", mcd ) );
if( !Path::Exists(str) )
CreateMcd(str.c_str());
if( IsLoading() )
{
// Note: TOTA works with values as low as 20 here.
// It "times out" with values around 1800 (forces user to check the memcard
// twice to find it). Other games could be different. :|
#ifdef WIN32
NTFS_CompressFile( str.c_str() );
#endif
f = fopen(str.c_str(), "r+b");
if (f == NULL) {
Msgbox::Alert("Failed loading MemCard from file: %hs", params &str);
return NULL;
m_PostSavestateCards[0] = 64;
m_PostSavestateCards[1] = 64;
}
return f;
}
void SeekMcd(FILE *f, u32 adr) {
u32 size;
fseek(f, 0, SEEK_END); size = ftell(f);
if (size == MCD_SIZE + 64)
fseek(f, adr + 64, SEEK_SET);
else if (size == MCD_SIZE + 3904)
fseek(f, adr + 3904, SEEK_SET);
else
fseek(f, adr, SEEK_SET);
}
void ReadMcd(int mcd, u8 *data, u32 adr, int size)
{
FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2;
if (mcfp == NULL) {
memset(data, 0, size);
return;
}
SeekMcd(mcfp, adr);
fread(data, 1, size, mcfp);
}
void SaveMcd(int mcd, const u8 *data, u32 adr, int size)
{
FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2;
SeekMcd(mcfp, adr);
u8 *currentdata = (u8 *)malloc(size);
fread(currentdata, 1, size, mcfp);
for (int i=0; i<size; i++)
{
if ((currentdata[i] & data[i]) != data[i])
Console::Notice("MemoryCard : writing odd data");
currentdata[i] &= data[i];
}
SeekMcd(mcfp, adr);
fwrite(currentdata, 1, size, mcfp);
free(currentdata);
}
void EraseMcd(int mcd, u32 adr)
{
u8 data[528*16];
memset8_obj<0xff>(data); // clears to -1's
FILE* const mcfp = (mcd == 1) ? MemoryCard1 : MemoryCard2;
SeekMcd(mcfp, adr);
fwrite(data, 1, 528*16, mcfp);
}
void CreateMcd(const char *mcd)
{
FILE *fp;
int i=0, j=0;
//int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0};
fp = fopen(mcd, "wb");
if (fp == NULL) return;
for(i=0; i < 16384; i++)
{
for(j=0; j < 528; j++) fputc(0xFF,fp);
// for(j=0; j < 16; j++) fputc(enc[j],fp);
}
fclose(fp);
}

View File

@ -60,13 +60,15 @@ struct _sio {
u32 sector;
u32 k;
u32 count;
int GetMemcardIndex() const
{
return (CtrlReg&0x2000) >> 13;
}
};
extern _sio sio;
#define MCD_SIZE (1024 * 8 * 16)
#define MC2_SIZE (1024 * 528 * 16)
// Status Flags
#define TX_RDY 0x0001
#define RX_RDY 0x0002
@ -88,29 +90,14 @@ extern _sio sio;
#define RTS 0x0020
#define SIO_RESET 0x0040
void sioInit();
void sioShutdown();
void psxSIOShutdown();
u8 sioRead8();
void sioWrite8(u8 value);
void sioWriteCtrl16(u16 value);
extern void sioInit();
extern void sioShutdown();
extern void psxSIOShutdown();
extern u8 sioRead8();
extern void sioWrite8(u8 value);
extern void sioWriteCtrl16(u16 value);
extern void sioInterrupt();
void InitializeSIO(u8 value);
FILE *LoadMcd(int mcd);
void ReadMcd(int mcd, u8 *data, u32 adr, int size);
void SaveMcd(int mcd, const u8 *data, u32 adr, int size);
void EraseMcd(int mcd, u32 adr);
void CreateMcd(const char *mcd);
struct McdBlock {
char Title[48];
char ID[14];
char Name[16];
int IconCount;
u16 Icon[16*16*3];
u8 Flags;
};
extern void InitializeSIO(u8 value);
#ifdef _MSC_VER
#pragma pack(1)
@ -129,6 +116,4 @@ struct mc_command_0x26_tag{
} __attribute__((packed));
#endif
void GetMcdBlockInfo(int mcd, int block, McdBlock *info);
#endif

View File

@ -1673,6 +1673,14 @@
RelativePath="..\..\x86\BaseblockEx.h"
>
</File>
<File
RelativePath="..\..\MemoryCard.cpp"
>
</File>
<File
RelativePath="..\..\MemoryCard.h"
>
</File>
<Filter
Name="EE"
>
@ -2413,6 +2421,14 @@
RelativePath="..\..\Hw.h"
>
</File>
<File
RelativePath="..\..\HwRead.cpp"
>
</File>
<File
RelativePath="..\..\HwWrite.cpp"
>
</File>
<File
RelativePath="..\..\IopHw.cpp"
>