#include #include #include #include #include #include #include "patches/fst.h" #include "patches/gamepatches.h" #include "patches/wip.h" #include "apploader.h" #include "disc.h" #include "video.h" #include "wdvd.h" #include "alternatedol.h" #include "memory.h" #include "wbfs.h" #include "../gecko.h" #include "../fatmounter.h" /* Constants */ #define PTABLE_OFFSET 0x40000 #define WII_MAGIC 0x5D1C9EA3 //appentrypoint u32 appentrypoint; /* Disc pointers */ static u32 *buffer = ( u32 * )0x93000000; static u8 *diskid = ( u8 * )Disc_ID; void __Disc_SetLowMem( void ) { *Sys_Magic = 0x0D15EA5E; // Standard Boot Code *Version = 0x00000001; // Version *Arena_L = 0x00000000; // Arena Low *BI2 = 0x817E5480; // BI2 *Bus_Speed = 0x0E7BE2C0; // Console Bus Speed *CPU_Speed = 0x2B73A840; // Console CPU Speed /* Setup low memory */ *Assembler = 0x38A00040; // Assembler *( u32 * )0x800000E4 = 0x80431A80; *Dev_Debugger = 0x81800000; // Dev Debugger Monitor Address *Simulated_Mem = 0x01800000; // Simulated Memory Size *( vu32 * )0xCD00643C = 0x00000000; // 32Mhz on Bus //If the game is sam & max: season 1 put this shit in char gameid[8]; memset( gameid, 0, 8 ); memcpy( gameid, ( char* )Disc_ID, 6 ); if ( ( strcmp( gameid, "R3XE6U" ) == 0 ) || ( strcmp( gameid, "R3XP6V" ) == 0 ) ) { *GameID_Address = 0x80000000; // Game ID Address } /* Copy disc ID */ memcpy( ( void * )Online_Check, ( void * )Disc_ID, 4 ); /* Flush cache */ DCFlushRange( ( void * )Disc_ID, 0x3F00 ); } void __Disc_SetVMode( u8 videoselected ) { GXRModeObj *vmode = NULL; u32 progressive, tvmode, vmode_reg = 0; /* Get video mode configuration */ progressive = ( CONF_GetProgressiveScan() > 0 ) && VIDEO_HaveComponentCable(); tvmode = CONF_GetVideo(); /* Select video mode register */ switch ( tvmode ) { case CONF_VIDEO_PAL: vmode_reg = ( CONF_GetEuRGB60() > 0 ) ? 5 : 1; break; case CONF_VIDEO_MPAL: vmode_reg = 4; break; case CONF_VIDEO_NTSC: vmode_reg = 0; break; } switch ( videoselected ) { case 0: /* Select video mode */ switch ( diskid[3] ) { /* PAL */ case 'P': case 'D': case 'F': case 'I': case 'S': case 'H': case 'X': case 'Y': case 'Z': if ( tvmode != CONF_VIDEO_PAL ) { vmode_reg = 5; vmode = ( progressive ) ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf; } break; /* NTSC or unknown */ case 'E': case 'J': case 'K': case 'W': if ( tvmode != CONF_VIDEO_NTSC ) { vmode_reg = 0; vmode = ( progressive ) ? &TVNtsc480Prog : &TVNtsc480IntDf; } break; } break; case 1: vmode = &TVPal528IntDf; vmode_reg = ( vmode->viTVMode ) >> 2; break; case 2: progressive = ( CONF_GetProgressiveScan() > 0 ) && VIDEO_HaveComponentCable(); vmode = ( progressive ) ? &TVNtsc480Prog : &TVEurgb60Hz480IntDf; vmode_reg = ( vmode->viTVMode ) >> 2; break; case 3: progressive = ( CONF_GetProgressiveScan() > 0 ) && VIDEO_HaveComponentCable(); vmode = ( progressive ) ? &TVNtsc480Prog : &TVNtsc480IntDf; vmode_reg = ( vmode->viTVMode ) >> 2; break; case 4: // vmode = VIDEO_GetPreferredMode(NULL); break; } /* Set video mode register */ *Video_Mode = vmode_reg; /* Set video mode */ if ( vmode ) { VIDEO_Configure( vmode ); /* Setup video */ VIDEO_SetBlack( FALSE ); VIDEO_Flush(); VIDEO_WaitVSync(); if ( vmode->viTVMode & VI_NON_INTERLACE ) VIDEO_WaitVSync(); } gprintf( "\nVideo mode - %s", ( ( progressive ) ? "progressive" : "interlaced" ) ); } void __Disc_SetTime( void ) { /* Extern */ extern void settime( u64 ); /* Set proper time */ settime( secs_to_ticks( time( NULL ) - 946684800 ) ); } s32 __Disc_FindPartition( u64 *outbuf ) { u64 offset = 0, table_offset = 0; u32 cnt, nb_partitions; s32 ret; /* Read partition info */ ret = WDVD_UnencryptedRead( buffer, 0x20, PTABLE_OFFSET ); if ( ret < 0 ) return ret; /* Get data */ nb_partitions = buffer[0]; table_offset = buffer[1] << 2; /* Read partition table */ ret = WDVD_UnencryptedRead( buffer, 0x20, table_offset ); if ( ret < 0 ) return ret; /* Find game partition */ for ( cnt = 0; cnt < nb_partitions; cnt++ ) { u32 type = buffer[cnt * 2 + 1]; /* Game partition */ if ( !type ) offset = buffer[cnt * 2] << 2; } /* No game partition found */ if ( !offset ) return -1; /* Set output buffer */ *outbuf = offset; return 0; } s32 Disc_Init( void ) { /* Init DVD subsystem */ return WDVD_Init(); } s32 Disc_Open( void ) { s32 ret; /* Reset drive */ ret = WDVD_Reset(); if ( ret < 0 ) return ret; /* Read disc ID */ return WDVD_ReadDiskId( diskid ); } s32 Disc_Wait( void ) { u32 cover = 0; s32 ret; /* Wait for disc */ while ( !( cover & 0x2 ) ) { /* Get cover status */ ret = WDVD_GetCoverStatus( &cover ); if ( ret < 0 ) return ret; } return 0; } s32 Disc_SetUSB( const u8 *id ) { u32 part = 0; if ( wbfs_part_fs ) { part = wbfs_part_lba; } else { part = wbfs_part_idx ? wbfs_part_idx - 1 : 0; } /* Set USB mode */ return WDVD_SetUSBMode( id, part ); } s32 Disc_ReadHeader( void *outbuf ) { /* Read disc header */ return WDVD_UnencryptedRead( outbuf, sizeof( struct discHdr ), 0 ); } s32 Disc_IsWii( void ) { struct discHdr *header = ( struct discHdr * )buffer; s32 ret; /* Read disc header */ ret = Disc_ReadHeader( header ); if ( ret < 0 ) return ret; /* Check magic word */ if ( header->magic != WII_MAGIC ) return -1; return 0; } s32 Disc_BootPartition( u64 offset, u8 videoselected, u8 cheat, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset, u32 returnTo ) { entry_point p_entry; s32 ret; /* Open specified partition */ ret = WDVD_OpenPartition( offset ); if ( ret < 0 ) return ret; /* Setup low memory */ __Disc_SetLowMem(); char gameid[8]; memset( gameid, 0, 8 ); memcpy( gameid, ( char* )Disc_ID, 6 ); load_wip_code( ( u8 * ) &gameid ); /* If a wip file is loaded for this game this does nothing - Dimok */ PoPPatch(); /* Run apploader */ ret = Apploader_Run( &p_entry, cheat, videoselected, vipatch, patchcountrystring, error002fix, alternatedol, alternatedoloffset, returnTo ); if ( ret < 0 ) return ret; free_wip(); bool cheatloaded = false; if ( cheat ) { /* OCARINA STUFF - FISHEARS*/ if ( ocarina_load_code( ( u8 * ) gameid ) > 0 ) { ocarina_do_code(); cheatloaded = true; } } //kill the USB and SD USBDevice_deInit(); SDCard_deInit(); /* Set an appropiate video mode */ __Disc_SetVMode( videoselected ); /* Set time */ __Disc_SetTime(); //gprintf("\n\tDe-init SD & USB"); /* Disconnect Wiimote */ WPAD_Flush( 0 ); WPAD_Disconnect( 0 ); WPAD_Shutdown(); // Anti-green screen fix VIDEO_SetBlack( TRUE ); VIDEO_Flush(); VIDEO_WaitVSync(); gprintf( "\n\nUSB Loader GX is done.\n\n" ); /* Shutdown IOS subsystems */ // fix for PeppaPig (from NeoGamma) extern void __exception_closeall(); IRQ_Disable(); __IOS_ShutdownSubsystems(); __exception_closeall(); appentrypoint = ( u32 ) p_entry; if ( cheat == 1 && cheatloaded ) { __asm__( "lis %r3, appentrypoint@h\n" "ori %r3, %r3, appentrypoint@l\n" "lwz %r3, 0(%r3)\n" "mtlr %r3\n" "lis %r3, 0x8000\n" "ori %r3, %r3, 0x18A8\n" "mtctr %r3\n" "bctr\n" ); } else { __asm__( "lis %r3, appentrypoint@h\n" "ori %r3, %r3, appentrypoint@l\n" "lwz %r3, 0(%r3)\n" "mtlr %r3\n" "blr\n" ); } return 0; } s32 Disc_WiiBoot( u8 videoselected, u8 cheat, u8 vipatch, u8 patchcountrystring, u8 error002fix, u8 alternatedol, u32 alternatedoloffset, u32 returnTo ) { u64 offset; s32 ret; /* Find game partition offset */ ret = __Disc_FindPartition( &offset ); if ( ret < 0 ) return ret; /* Boot partition */ return Disc_BootPartition( offset, videoselected, cheat, vipatch, patchcountrystring, error002fix, alternatedol, alternatedoloffset, returnTo ); } void PatchCountryStrings( void *Address, int Size ) { u8 SearchPattern[4] = { 0x00, 0x00, 0x00, 0x00 }; u8 PatchData[4] = { 0x00, 0x00, 0x00, 0x00 }; u8 *Addr = ( u8* )Address; int wiiregion = CONF_GetRegion(); switch ( wiiregion ) { case CONF_REGION_JP: SearchPattern[0] = 0x00; SearchPattern[1] = 0x4A; // J SearchPattern[2] = 0x50; // P break; case CONF_REGION_EU: SearchPattern[0] = 0x02; SearchPattern[1] = 0x45; // E SearchPattern[2] = 0x55; // U break; case CONF_REGION_KR: SearchPattern[0] = 0x04; SearchPattern[1] = 0x4B; // K SearchPattern[2] = 0x52; // R break; case CONF_REGION_CN: SearchPattern[0] = 0x05; SearchPattern[1] = 0x43; // C SearchPattern[2] = 0x4E; // N break; case CONF_REGION_US: default: SearchPattern[0] = 0x01; SearchPattern[1] = 0x55; // U SearchPattern[2] = 0x53; // S } switch ( diskid[3] ) { case 'J': PatchData[1] = 0x4A; // J PatchData[2] = 0x50; // P break; case 'D': case 'F': case 'P': case 'X': case 'Y': PatchData[1] = 0x45; // E PatchData[2] = 0x55; // U break; case 'E': default: PatchData[1] = 0x55; // U PatchData[2] = 0x53; // S } while ( Size >= 4 ) { if ( Addr[0] == SearchPattern[0] && Addr[1] == SearchPattern[1] && Addr[2] == SearchPattern[2] && Addr[3] == SearchPattern[3] ) { //*Addr = PatchData[0]; Addr += 1; *Addr = PatchData[1]; Addr += 1; *Addr = PatchData[2]; Addr += 1; //*Addr = PatchData[3]; Addr += 1; Size -= 4; } else { Addr += 4; Size -= 4; } } }