mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
098c38113a
commit
632b73ccad
1171
pcsx2/Hw.cpp
1171
pcsx2/Hw.cpp
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
221
pcsx2/Sio.cpp
221
pcsx2/Sio.cpp
|
@ -19,17 +19,17 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#include "PsxCommon.h"
|
#include "PsxCommon.h"
|
||||||
#include "Paths.h"
|
#include "MemoryCard.h"
|
||||||
|
|
||||||
_sio sio;
|
_sio sio;
|
||||||
|
|
||||||
static FILE * MemoryCard1=NULL, * MemoryCard2=NULL;
|
|
||||||
|
|
||||||
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 : Sector size etc.
|
||||||
static const mc_command_0x26_tag mc_command_0x26= {'+', 512, 16, 0x4000, 0x52, 0x5A};
|
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
|
// 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)
|
// feeding them through the IOP's branch test. (see SIO.H for details)
|
||||||
|
|
||||||
|
@ -46,18 +46,18 @@ __forceinline void SIO_INT()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void _ReadMcd(u8 *data, u32 adr, int size) {
|
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) {
|
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) {
|
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;
|
u8 i, x;
|
||||||
|
|
||||||
for (x=0, i=0; i<length; i++) x ^= buf[i];
|
for (x=0, i=0; i<length; i++) x ^= buf[i];
|
||||||
|
@ -68,25 +68,17 @@ void sioInit()
|
||||||
{
|
{
|
||||||
memzero_obj(sio);
|
memzero_obj(sio);
|
||||||
|
|
||||||
if( MemoryCard1 == NULL )
|
|
||||||
MemoryCard1 = LoadMcd(1);
|
|
||||||
|
|
||||||
if( MemoryCard2 == NULL )
|
|
||||||
MemoryCard2 = LoadMcd(2);
|
|
||||||
|
|
||||||
// Transfer(?) Ready and the Buffer is Empty
|
// Transfer(?) Ready and the Buffer is Empty
|
||||||
sio.StatReg = TX_RDY | TX_EMPTY;
|
sio.StatReg = TX_RDY | TX_EMPTY;
|
||||||
sio.packetsize = 0;
|
sio.packetsize = 0;
|
||||||
sio.terminator =0x55; // Command terminator 'U'
|
sio.terminator =0x55; // Command terminator 'U'
|
||||||
|
|
||||||
|
MemoryCard_Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void psxSIOShutdown()
|
void psxSIOShutdown()
|
||||||
{
|
{
|
||||||
if(MemoryCard1) fclose(MemoryCard1);
|
MemoryCard_Shutdown();
|
||||||
if(MemoryCard2) fclose(MemoryCard2);
|
|
||||||
|
|
||||||
MemoryCard1 = NULL;
|
|
||||||
MemoryCard2 = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 sioRead8() {
|
u8 sioRead8() {
|
||||||
|
@ -173,7 +165,7 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
sio.mcdst = 99;
|
sio.mcdst = 99;
|
||||||
|
|
||||||
sio2.packet.recvVal3 = 0x8c;
|
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;
|
break;
|
||||||
case 0x81: // COMMIT
|
case 0x81: // COMMIT
|
||||||
sio.bufcount = 8;
|
sio.bufcount = 8;
|
||||||
|
@ -187,7 +179,7 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
sio2.packet.recvVal1 = 0x1600; // Writing
|
sio2.packet.recvVal1 = 0x1600; // Writing
|
||||||
else if(sio.mc_command==0x43) sio2.packet.recvVal1 = 0x1700; // Reading
|
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;
|
break;
|
||||||
case 0x21:
|
case 0x21:
|
||||||
case 0x22:
|
case 0x22:
|
||||||
|
@ -197,20 +189,20 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
sio2.packet.recvVal3 = 0x8c;
|
sio2.packet.recvVal3 = 0x8c;
|
||||||
sio.buf[8]=sio.terminator;
|
sio.buf[8]=sio.terminator;
|
||||||
sio.buf[7]='+';
|
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;
|
break;
|
||||||
case 0x24:
|
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;
|
break;
|
||||||
case 0x25:
|
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;
|
break;
|
||||||
case 0x26:
|
case 0x26:
|
||||||
sio.bufcount = 12; sio.mcdst = 99; sio2.packet.recvVal3 = 0x83;
|
sio.bufcount = 12; sio.mcdst = 99; sio2.packet.recvVal3 = 0x83;
|
||||||
memset8_obj<0xff>(sio.buf);
|
memset8_obj<0xff>(sio.buf);
|
||||||
memcpy(&sio.buf[2], &mc_command_0x26, sizeof(mc_command_0x26));
|
memcpy(&sio.buf[2], &mc_command_0x26, sizeof(mc_command_0x26));
|
||||||
sio.buf[12]=sio.terminator;
|
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;
|
break;
|
||||||
case 0x27:
|
case 0x27:
|
||||||
case 0x28:
|
case 0x28:
|
||||||
|
@ -219,7 +211,7 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
memset8_obj<0xff>(sio.buf);
|
memset8_obj<0xff>(sio.buf);
|
||||||
sio.buf[4]=sio.terminator;
|
sio.buf[4]=sio.terminator;
|
||||||
sio.buf[3]='+';
|
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;
|
break;
|
||||||
case 0x42: // WRITE
|
case 0x42: // WRITE
|
||||||
case 0x43: // READ
|
case 0x43: // READ
|
||||||
|
@ -232,13 +224,13 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
memset8_obj<0xff>(sio.buf);
|
memset8_obj<0xff>(sio.buf);
|
||||||
sio.buf[133]=sio.terminator;
|
sio.buf[133]=sio.terminator;
|
||||||
sio.buf[132]='+';
|
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;
|
break;
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
case 0xf1:
|
case 0xf1:
|
||||||
case 0xf2:
|
case 0xf2:
|
||||||
sio.mcdst = 99;
|
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;
|
break;
|
||||||
case 0xf3:
|
case 0xf3:
|
||||||
case 0xf7:
|
case 0xf7:
|
||||||
|
@ -246,23 +238,23 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
memset8_obj<0xff>(sio.buf);
|
memset8_obj<0xff>(sio.buf);
|
||||||
sio.buf[4]=sio.terminator;
|
sio.buf[4]=sio.terminator;
|
||||||
sio.buf[3]='+';
|
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;
|
break;
|
||||||
case 0x52:
|
case 0x52:
|
||||||
sio.rdwr = 1; memset8_obj<0xff>(sio.buf);
|
sio.rdwr = 1; memset8_obj<0xff>(sio.buf);
|
||||||
sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
|
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;
|
break;
|
||||||
case 0x57:
|
case 0x57:
|
||||||
sio.rdwr = 2; memset8_obj<0xff>(sio.buf);
|
sio.rdwr = 2; memset8_obj<0xff>(sio.buf);
|
||||||
sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
sio.mcdst = 0;
|
sio.mcdst = 0;
|
||||||
memset8_obj<0xff>(sio.buf);
|
memset8_obj<0xff>(sio.buf);
|
||||||
sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+';
|
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;
|
sio.mc_command=value;
|
||||||
return;
|
return;
|
||||||
|
@ -286,10 +278,10 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
{
|
{
|
||||||
if (sio_xor((u8 *)&sio.sector, 4) == value)
|
if (sio_xor((u8 *)&sio.sector, 4) == value)
|
||||||
MEMCARDS_LOG("MC(%d) SET PAGE sio.sector 0x%04X\n",
|
MEMCARDS_LOG("MC(%d) SET PAGE sio.sector 0x%04X\n",
|
||||||
((sio.CtrlReg&0x2000)>>13)+1, sio.sector);
|
sio.GetMemcardIndex()+1, sio.sector);
|
||||||
else
|
else
|
||||||
MEMCARDS_LOG("MC(%d) SET PAGE XOR value ERROR 0x%02X != ^0x%02X\n",
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -298,7 +290,7 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
if(sio.parp==2) {
|
if(sio.parp==2) {
|
||||||
sio.terminator = value;
|
sio.terminator = value;
|
||||||
sio.buf[4] = 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;
|
break;
|
||||||
|
@ -312,7 +304,7 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
|
|
||||||
//if(value == 0) sio.buf[4] = 0xFF;
|
//if(value == 0) sio.buf[4] = 0xFF;
|
||||||
sio.buf[4] = 0x55;
|
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;
|
break;
|
||||||
// WRITE DATA
|
// WRITE DATA
|
||||||
|
@ -322,12 +314,12 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
memset8_obj<0xff>(sio.buf);
|
memset8_obj<0xff>(sio.buf);
|
||||||
sio.buf[sio.bufcount-1]='+';
|
sio.buf[sio.bufcount-1]='+';
|
||||||
sio.buf[sio.bufcount]=sio.terminator;
|
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
|
else
|
||||||
if ((sio.parp>2) && (sio.parp<sio.bufcount-2)) {
|
if ((sio.parp>2) && (sio.parp<sio.bufcount-2)) {
|
||||||
sio.buf[sio.parp]=value;
|
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
|
} else
|
||||||
if (sio.parp==sio.bufcount-2) {
|
if (sio.parp==sio.bufcount-2) {
|
||||||
if (sio_xor(&sio.buf[3], sio.bufcount-5)==value) {
|
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;
|
sio.k+=sio.bufcount-5;
|
||||||
}else {
|
}else {
|
||||||
MEMCARDS_LOG("MC(%d) write XOR value error 0x%02X != ^0x%02X\n",
|
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;
|
break;
|
||||||
|
@ -346,7 +338,7 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
//int i;
|
//int i;
|
||||||
sio.bufcount=value+5;
|
sio.bufcount=value+5;
|
||||||
sio.buf[3]='+';
|
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);
|
_ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value);
|
||||||
/*if(sio.mode==2)
|
/*if(sio.mode==2)
|
||||||
{
|
{
|
||||||
|
@ -377,14 +369,14 @@ void SIO_CommandWrite(u8 value,int way) {
|
||||||
sio.buf[2]='+';
|
sio.buf[2]='+';
|
||||||
sio.buf[3]=sio.terminator;*/
|
sio.buf[3]=sio.terminator;*/
|
||||||
//sio.buf[sio.bufcount] = 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;
|
break;
|
||||||
// CARD AUTHENTICATION CHECKS
|
// CARD AUTHENTICATION CHECKS
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
if (sio.parp==2)
|
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){
|
switch(value){
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -487,6 +479,7 @@ void InitializeSIO(u8 value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x81: // start memcard
|
case 0x81: // start memcard
|
||||||
|
{
|
||||||
sio.StatReg &= ~TX_EMPTY;
|
sio.StatReg &= ~TX_EMPTY;
|
||||||
sio.StatReg |= RX_RDY;
|
sio.StatReg |= RX_RDY;
|
||||||
memcpy(sio.buf, cardh, 4);
|
memcpy(sio.buf, cardh, 4);
|
||||||
|
@ -495,10 +488,34 @@ void InitializeSIO(u8 value)
|
||||||
sio.mcdst = 1;
|
sio.mcdst = 1;
|
||||||
sio.packetsize = 1;
|
sio.packetsize = 1;
|
||||||
sio.rdwr = 0;
|
sio.rdwr = 0;
|
||||||
sio2.packet.recvVal1 = 0x1100; // Memcards are present
|
|
||||||
sio.count = 0;
|
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();
|
SIO_INT();
|
||||||
PAD_LOG("START MEMORY CARD\n");
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -534,118 +551,14 @@ void SaveState::sioFreeze()
|
||||||
{
|
{
|
||||||
Freeze( sio );
|
Freeze( sio );
|
||||||
|
|
||||||
//if( IsLoading() )
|
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());
|
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
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])
|
// Note: TOTA works with values as low as 20 here.
|
||||||
Console::Notice("MemoryCard : writing odd data");
|
// It "times out" with values around 1800 (forces user to check the memcard
|
||||||
currentdata[i] &= data[i];
|
// twice to find it). Other games could be different. :|
|
||||||
|
|
||||||
|
m_PostSavestateCards[0] = 64;
|
||||||
|
m_PostSavestateCards[1] = 64;
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
39
pcsx2/Sio.h
39
pcsx2/Sio.h
|
@ -60,13 +60,15 @@ struct _sio {
|
||||||
u32 sector;
|
u32 sector;
|
||||||
u32 k;
|
u32 k;
|
||||||
u32 count;
|
u32 count;
|
||||||
|
|
||||||
|
int GetMemcardIndex() const
|
||||||
|
{
|
||||||
|
return (CtrlReg&0x2000) >> 13;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern _sio sio;
|
extern _sio sio;
|
||||||
|
|
||||||
#define MCD_SIZE (1024 * 8 * 16)
|
|
||||||
#define MC2_SIZE (1024 * 528 * 16)
|
|
||||||
|
|
||||||
// Status Flags
|
// Status Flags
|
||||||
#define TX_RDY 0x0001
|
#define TX_RDY 0x0001
|
||||||
#define RX_RDY 0x0002
|
#define RX_RDY 0x0002
|
||||||
|
@ -88,29 +90,14 @@ extern _sio sio;
|
||||||
#define RTS 0x0020
|
#define RTS 0x0020
|
||||||
#define SIO_RESET 0x0040
|
#define SIO_RESET 0x0040
|
||||||
|
|
||||||
void sioInit();
|
extern void sioInit();
|
||||||
void sioShutdown();
|
extern void sioShutdown();
|
||||||
void psxSIOShutdown();
|
extern void psxSIOShutdown();
|
||||||
u8 sioRead8();
|
extern u8 sioRead8();
|
||||||
void sioWrite8(u8 value);
|
extern void sioWrite8(u8 value);
|
||||||
void sioWriteCtrl16(u16 value);
|
extern void sioWriteCtrl16(u16 value);
|
||||||
extern void sioInterrupt();
|
extern void sioInterrupt();
|
||||||
void InitializeSIO(u8 value);
|
extern 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
@ -129,6 +116,4 @@ struct mc_command_0x26_tag{
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void GetMcdBlockInfo(int mcd, int block, McdBlock *info);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1673,6 +1673,14 @@
|
||||||
RelativePath="..\..\x86\BaseblockEx.h"
|
RelativePath="..\..\x86\BaseblockEx.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\MemoryCard.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\MemoryCard.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
Name="EE"
|
Name="EE"
|
||||||
>
|
>
|
||||||
|
@ -2413,6 +2421,14 @@
|
||||||
RelativePath="..\..\Hw.h"
|
RelativePath="..\..\Hw.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\HwRead.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\HwWrite.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\IopHw.cpp"
|
RelativePath="..\..\IopHw.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue