From 632b73ccadeedebd072260641d69e5c028aab863 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Mon, 9 Feb 2009 17:53:35 +0000 Subject: [PATCH] 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 --- pcsx2/Hw.cpp | 1171 -------------------- pcsx2/HwRead.cpp | 359 ++++++ pcsx2/HwWrite.cpp | 880 +++++++++++++++ pcsx2/MemoryCard.cpp | 158 +++ pcsx2/MemoryCard.h | 49 + pcsx2/Sio.cpp | 223 ++-- pcsx2/Sio.h | 39 +- pcsx2/windows/VCprojects/pcsx2_2008.vcproj | 16 + 8 files changed, 1542 insertions(+), 1353 deletions(-) create mode 100644 pcsx2/HwRead.cpp create mode 100644 pcsx2/HwWrite.cpp create mode 100644 pcsx2/MemoryCard.cpp create mode 100644 pcsx2/MemoryCard.h diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index 257386a4a3..0c8617f6f4 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -71,1176 +71,6 @@ void hwReset() ipuReset(); } -///////////////////////////////////////////////////////////////////////// -// Hardware READ 8 bit - -__forceinline u8 hwRead8(u32 mem) -{ - u8 ret; - - if( mem >= 0x10002000 && mem < 0x10008000 ) - DevCon::Notice("hwRead8 to %x", params mem); - - SPR_LOG("Hardware read 8bit at %lx, ret %lx\n", mem, psHu8(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("hwRead16 to %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); -} - -///////////////////////////////////////////////////////////////////////// -// 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; - } -} - __forceinline void intcInterrupt() { if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return; @@ -1317,7 +147,6 @@ int hwMFIFOWrite(u32 addr, u8 *data, u32 size) { Cpu->Clear(addr, size/4); memcpy_fast(dst, data, size); } - return 0; } diff --git a/pcsx2/HwRead.cpp b/pcsx2/HwRead.cpp new file mode 100644 index 0000000000..125c7aa172 --- /dev/null +++ b/pcsx2/HwRead.cpp @@ -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); +} diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp new file mode 100644 index 0000000000..66d69c2f1d --- /dev/null +++ b/pcsx2/HwWrite.cpp @@ -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; + } +} diff --git a/pcsx2/MemoryCard.cpp b/pcsx2/MemoryCard.cpp new file mode 100644 index 0000000000..79fc6f799e --- /dev/null +++ b/pcsx2/MemoryCard.cpp @@ -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(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); +} + diff --git a/pcsx2/MemoryCard.h b/pcsx2/MemoryCard.h new file mode 100644 index 0000000000..17e6a87fdf --- /dev/null +++ b/pcsx2/MemoryCard.h @@ -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 diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index 5dffc2da4b..887c2b13a7 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -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>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>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(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); -} - - - diff --git a/pcsx2/Sio.h b/pcsx2/Sio.h index c23acad523..0def944d7b 100644 --- a/pcsx2/Sio.h +++ b/pcsx2/Sio.h @@ -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 diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 29d65f83ea..10f1a246c0 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -1673,6 +1673,14 @@ RelativePath="..\..\x86\BaseblockEx.h" > + + + + @@ -2413,6 +2421,14 @@ RelativePath="..\..\Hw.h" > + + + +