#include "dip.h" u32 StreamBufferSize= 54*1024; u32 Streaming = 0; u32 StreamOffset = 0; u32 StreamDiscOffset= 0; s32 StreamSize = 0; u32 StreamRAMOffset = 0; u32 StreamTimer = 0; u32 StreamStopEnd = 0; u32 GameRun = 0; u32 DOLMinOff = 0; u32 DOLMaxOff = 0; u32 DOLSize = 0; u32 DOLOffset = 0; s32 ELFNumberOfSections = 0; u32 FSTMode = 0; u32 DiscChangeIRQ = 0; extern DML_CFG *DMLCfg; FIL GameFile; u32 read; u32 DiscRead=0; char *getfilenamebyoffset(u32 offset) { u32 fst_offset = read32(0x38) & ~0x80000000; u32 i; for (i = fst_offset + 12; i < 0x01800000; i+=12) { if (read8(i) == 0 && offset >= read32(i + 4) && offset < read32(i + 4) + read32(i + 8)) { return (char *)(fst_offset + read32(fst_offset+8)*12 + (read32(i) & 0x00ffffff)); } } return (char*)NULL; } void DIInit( void ) { memset32( (void*)DI_BASE, 0xdeadbeef, 0x30 ); memset32( (void*)(DI_SHADOW), 0, 0x30 ); write32( DI_SCONFIG, 0xFF ); write32( DI_SCOVER, 0 ); write32( HW_TIMER, 0 ); } u32 DIUpdateRegisters( void ) { u32 read,i,j; static u32 PatchState = 0; static u32 DOLReadSize = 0; static u32 PSOHack = 0; if( read32(DI_CONTROL) != 0xdeadbeef ) { write32( DI_SCONTROL, read32(DI_CONTROL) & 3 ); clear32( DI_SSTATUS, 0x14 ); write32( DI_CONTROL, 0xdeadbeef ); if( read32(DI_SCONTROL) & 1 ) { if( ConfigGetConfig(DML_CFG_ACTIVITY_LED) ) set32( HW_GPIO_OUT, 1<<5 ); if( read32(DI_CMD_0) != 0xdeadbeef ) { write32( DI_SCMD_0, read32(DI_CMD_0) ); write32( DI_CMD_0, 0xdeadbeef ); } if( read32(DI_CMD_1) != 0xdeadbeef ) { write32( DI_SCMD_1, read32(DI_CMD_1) ); write32( DI_CMD_1, 0xdeadbeef ); } if( read32(DI_CMD_2) != 0xdeadbeef ) { write32( DI_SCMD_2, read32(DI_CMD_2) ); write32( DI_CMD_2, 0xdeadbeef ); } if( read32(DI_DMA_ADR) != 0xdeadbeef ) { write32( DI_SDMA_ADR, read32(DI_DMA_ADR) ); write32( DI_DMA_ADR, 0xdeadbeef ); } if( read32(DI_DMA_LEN) != 0xdeadbeef ) { write32( DI_SDMA_LEN, read32(DI_DMA_LEN) ); write32( DI_DMA_LEN, 0xdeadbeef ); } if( read32(DI_IMM) != 0xdeadbeef ) { write32( DI_SIMM, read32(DI_IMM) ); write32( DI_IMM, 0xdeadbeef ); } switch( read32(DI_SCMD_0) >> 24 ) { case 0xE3: { dbgprintf("DIP:DVDLowStopMotor()\n"); u32 CDiscNumber = (read32(4) << 16 ) >> 24; dbgprintf("DIP:Current disc number:%u\n", CDiscNumber + 1 ); if( CDiscNumber ) { ConfigClearConfig(DML_CFG_BOOT_DISC2); } else { ConfigSetConfig(DML_CFG_BOOT_DISC2); } f_close( &GameFile ); dbgprintf("DVDSelectGame():%d\n", DVDSelectGame() ); DiscChangeIRQ = 1; while( read32(DI_SCONTROL) & 1 ) clear32( DI_SCONTROL, 1 ); set32( DI_SSTATUS, 0x3A ); write32( 0x0d80000C, (1<<0) | (1<<4) ); write32( HW_PPCIRQFLAG, read32(HW_PPCIRQFLAG) ); write32( HW_ARMIRQFLAG, read32(HW_ARMIRQFLAG) ); set32( 0x0d80000C, (1<<2) ); write32( HW_TIMER, 0 ); } break; case 0xA7: case 0xA9: //dbgprintf("DIP:Async!\n"); case 0xA8: { u32 Buffer = P2C(read32(DI_SDMA_ADR)); u32 Length = read32(DI_SCMD_2); u32 Offset = read32(DI_SCMD_1) << 2; // dbgprintf("DIP:DVDRead%02X( 0x%08x, 0x%08x, 0x%08x )\n", read32(DI_SCMD_0) >> 24, Offset, Length, Buffer|0x80000000 ); // udelay(250); if( FSTMode ) { FSTRead( (char*)Buffer, Length, Offset ); } else { if( GameFile.fptr != Offset ) if( f_lseek( &GameFile, Offset ) != FR_OK ) { EXIControl(1); dbgprintf("DIP:Failed to seek to 0x%08x\n", Offset ); while(1); } if( f_read( &GameFile, (char*)Buffer, Length, &read ) != FR_OK ) { EXIControl(1); dbgprintf("DIP:Failed to read from 0x%08x to 0x%08X\n", Offset, Buffer ); while(1); } } //if( ((read+31)&(~31)) != Length ) //{ // dbgprintf("DIP:DVDLowRead Offset:%08X Size:%08d Dst:%08X\n", Offset, Length, Buffer ); // dbgprintf("DIP:Failed to read %d bytes, only got %d\n", Length, read ); // break; //} if( (u32)Buffer == 0x01300000 ) { DoPatches( (char*)(0x01300000), Length, 0x80000000 ); } // PSO 1&2 if( (read32(0) >> 8) == 0x47504F ) { switch( Offset ) { case 0x56B8E7E0: // AppSwitcher [EUR] case 0x56C49600: // [USA] v1.1 case 0x56C4C980: // [USA] v1.0 { DMLCfg->Config &= ~(DML_CFG_CHEATS|DML_CFG_PADHOOK|DML_CFG_DEBUGGER|DML_CFG_DEBUGWAIT); DoPatches( (char*)Buffer, Length, 0x80000000 ); } break; case 0x5668FE20: // psov3.dol [EUR] case 0x56750660: // [USA] v1.1 case 0x56753EC0: // [USA] v1.0 { PSOHack = 1; } break; } } if( PatchState == 0 ) { if( Length == 0x100 || PSOHack ) { if( read32( (u32)Buffer ) == 0x100 ) { //quickly calc the size DOLSize = sizeof(dolhdr); dolhdr *dol = (dolhdr*)Buffer; for( i=0; i < 7; ++i ) DOLSize += dol->sizeText[i]; for( i=0; i < 11; ++i ) DOLSize += dol->sizeData[i]; DOLReadSize = Length; DOLMinOff=0x81800000; DOLMaxOff=0; for( i=0; i < 7; ++i ) { if( dol->addressText[i] == 0 ) continue; if( DOLMinOff > dol->addressText[i]) DOLMinOff = dol->addressText[i]; if( DOLMaxOff < dol->addressText[i] + dol->sizeText[i] ) DOLMaxOff = dol->addressText[i] + dol->sizeText[i]; } for( i=0; i < 11; ++i ) { if( dol->addressData[i] == 0 ) continue; if( DOLMinOff > dol->addressData[i]) DOLMinOff = dol->addressData[i]; if( DOLMaxOff < dol->addressData[i] + dol->sizeData[i] ) DOLMaxOff = dol->addressData[i] + dol->sizeData[i]; } DOLMinOff -= 0x80000000; DOLMaxOff -= 0x80000000; if( PSOHack ) { DOLMinOff = Buffer; DOLMaxOff = Buffer + DOLSize; } dbgprintf("DIP:DOLSize:%d DOLMinOff:0x%08X DOLMaxOff:0x%08X\n", DOLSize, DOLMinOff, DOLMaxOff ); PatchState = 1; } PSOHack = 0; } else if( read32(Buffer) == 0x7F454C46 ) { dbgprintf("DIP:Game is loading an ELF 0x%08x\n", Offset ); DOLOffset = Offset; DOLSize = 0; if( Length > 0x1000 ) { DOLReadSize = Length; DoPatches( (char*)(Buffer), Length, 0x80000000 ); } else DOLReadSize = 0; Elf32_Ehdr *ehdr = (Elf32_Ehdr*)Buffer; dbgprintf("DIP:ELF Programheader Entries:%u\n", ehdr->e_phnum ); for( i=0; i < ehdr->e_phnum; ++i ) { Elf32_Phdr phdr; if( FSTMode ) { FSTRead( (char*)&phdr, sizeof(Elf32_Phdr), DOLOffset + ehdr->e_phoff + i * sizeof(Elf32_Phdr) ); } else { f_lseek( &GameFile, DOLOffset + ehdr->e_phoff + i * sizeof(Elf32_Phdr) ); f_read( &GameFile, &phdr, sizeof(Elf32_Phdr), &read ); } DOLSize += (phdr.p_filesz+31) & (~31); // align by 32byte } dbgprintf("DIP:ELF size:%u\n", DOLSize ); PatchState = 2; } } else if ( PatchState == 1 ) { DOLReadSize += Length; //dbgprintf("DIP:DOL ize:%d DOL read:%d\n", DOLSize, DOLReadSize ); if( DOLReadSize >= DOLSize ) { DoPatches( (char*)(DOLMinOff), DOLMaxOff-DOLMinOff, 0x80000000 ); PatchState = 0; } } else if ( PatchState == 2 ) { DoPatches( (char*)(Buffer), Length, 0x80000000 ); if( Buffer > DOLMaxOff ) DOLMaxOff = Buffer; DOLReadSize += Length; //dbgprintf("DIP:ELF size:%d ELF read:%d\n", DOLSize, DOLReadSize ); if( DOLReadSize >= DOLSize ) { PatchState = 0; } } write32( DI_SDMA_LEN, 0 ); while( read32(DI_SCONTROL) & 1 ) clear32( DI_SCONTROL, 1 ); set32( DI_SSTATUS, 0x3A ); if( (read32(DI_SCMD_0) >> 24) == 0xA7 ) { write32( 0x0d80000C, (1<<0) | (1<<4) ); write32( HW_PPCIRQFLAG, read32(HW_PPCIRQFLAG) ); write32( HW_ARMIRQFLAG, read32(HW_ARMIRQFLAG) ); set32( 0x0d80000C, (1<<2) ); } write32( HW_TIMER, 0 ); } break; default: { EXIControl(1); dbgprintf("DIP:Unknown CMD:%08X %08X %08X %08X %08X %08X\n", read32(DI_SCMD_0), read32(DI_SCMD_1), read32(DI_SCMD_2), read32(DI_SIMM), read32(DI_SDMA_ADR), read32(DI_SDMA_LEN) ); while(1); } break; } if( ConfigGetConfig(DML_CFG_ACTIVITY_LED) ) clear32( HW_GPIO_OUT, 1<<5 ); return 1; } else { ;//dbgprintf("DIP:DI_CONTROL:%08X:%08X\n", read32(DI_CONTROL), read32(DI_CONTROL) ); } } if( (u64)read32(HW_TIMER) >= 25 * 243000000LL / 128 ) { USBStorage_Read_Sectors( (read32(HW_TIMER) << 3) & 0x000FFFFF, 1, (void*)0x1000 ); write32( HW_TIMER, 0 ); } return 0; }