void HIDUpdateRegisters() { if(*(vu32*)HID_CHANGE == 0) return; unsigned int DeviceVID = *(vu32*)HID_CHANGE; unsigned int DevicePID = *(vu32*)HID_CFG_SIZE; gprintf("Trying to get VID%04x PID%04x\n", DeviceVID, DevicePID); /* I hope this covers all possible ini files */ char file_sd[40]; char file_usb[40]; snprintf(file_sd, sizeof(file_sd), "sd:/controllers/%04X_%04X.ini", DeviceVID, DevicePID); snprintf(file_usb, sizeof(file_usb), "usb:/controllers/%04X_%04X.ini", DeviceVID, DevicePID); const char *const filenames[6] = { file_sd, file_usb, "sd:/controller.ini", "sd:/controller.ini.ini", "usb:/controller.ini", "usb:/controller.ini.ini" }; int i; FIL f; FRESULT res = FR_DISK_ERR; for (i = 0; i < 6; i++) { res = f_open_char(&f, filenames[i], FA_READ|FA_OPEN_EXISTING); if (res == FR_OK) break; } if (res == FR_OK) { size_t fsize = f.obj.objsize; UINT read; f_read(&f, (void*)HID_CFG_FILE, fsize, &read); DCFlushRange((void*)HID_CFG_FILE, fsize); f_close(&f); *(vu32*)HID_CFG_SIZE = fsize; } else { // No controller configuration file. *(vu32*)HID_CFG_SIZE = 0; } *(vu32*)HID_CHANGE = 0; }
void ConfigInit( void ) { FIL cfg; u32 read; dbgprintf("CFGInit()\r\n"); ConfigSyncBeforeRead(); if (ncfg->Magicbytes != 0x01070CF6) { dbgprintf("Cfg not in memory, trying file\r\n"); if (f_open_char(&cfg, "/nincfg.bin", FA_OPEN_EXISTING | FA_READ) != FR_OK) { dbgprintf("CFG:Failed to open config\r\n"); Shutdown(); } f_read( &cfg, ncfg, sizeof(NIN_CFG), &read ); sync_after_write(ncfg, sizeof(NIN_CFG)); f_close( &cfg ); if( read != sizeof(NIN_CFG) ) { dbgprintf("CFG:Failed to read config\r\n"); Shutdown(); } ConfigSyncBeforeRead(); } if( IsWiiU() ) { //ncfg->Config |= NIN_CFG_HID; ncfg->MaxPads = 0; // Disable debugging and the drive access LED. ncfg->Config &= ~(NIN_CFG_DEBUGGER | NIN_CFG_DEBUGWAIT | NIN_CFG_LED); } //if( (read32(0) >> 8) == 0x47504F ) // PSO 1&2 disable cheats/debugging //{ // ncfg->Config &= ~(NIN_CFG_CHEATS|NIN_CFG_DEBUGGER|NIN_CFG_DEBUGWAIT); //} }
void TRIBackupSettings() { if(TRISettingsName == (char*)0 || TRISettingsLoc == 0 || TRISettingsSize == 0) return; void *GameSettingsLoc = (TRIGame == TRI_AX || TRIGame == TRI_YAK) ? (void*)TRISettingsLoc : (void*)P2C(read32(TRISettingsLoc)); sync_before_read_align32(GameSettingsLoc, TRISettingsSize); sync_before_read_align32(OUR_SETTINGS_LOC, TRISettingsSize); if((memcmp(OUR_SETTINGS_LOC, GameSettingsLoc, TRISettingsSize) != 0) && (memcmp(GameSettingsLoc, "SB", 2) == 0)) { dbgprintf("TRI:Writing Settings\r\n"); memcpy(OUR_SETTINGS_LOC, GameSettingsLoc, TRISettingsSize); FIL backup; if(f_open_char(&backup, TRISettingsName, FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) { u32 wrote; f_write(&backup, OUR_SETTINGS_LOC, TRISettingsSize, &wrote); f_close(&backup); } sync_after_write_align32(OUR_SETTINGS_LOC, TRISettingsSize); TRI_BackupAvailable = 1; } }
void TRIReadSettings() { if(TRISettingsName == (char*)0 || TRISettingsSize == 0) return; FIL backup; if (f_open_char(&backup, TRISettingsName, FA_OPEN_EXISTING | FA_READ) == FR_OK) { if(backup.obj.objsize == TRISettingsSize) { u32 read; u8 sbuf[TRISettingsSize]; f_read(&backup, sbuf, TRISettingsSize, &read); if(memcmp(sbuf, "SB", 2) == 0) { dbgprintf("TRI:Reading Settings\r\n"); memcpy(OUR_SETTINGS_LOC, sbuf, TRISettingsSize); sync_after_write_align32(OUR_SETTINGS_LOC, TRISettingsSize); TRI_BackupAvailable = 1; } } f_close(&backup); } }
static int do_extract_currentfile(unzFile uf,const int* popt_extract_without_path,int* popt_overwrite,const char* password) { char filename_inzip[256]; char* filename_withoutpath; char* p; int err=UNZ_OK; int res=FR_NO_FILE; void* buf; uInt size_buf; FIL f; unz_file_info file_info; err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); if (err!=UNZ_OK) { printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); return err; } size_buf = WRITEBUFFERSIZE; buf = (void*)malloc(size_buf); if (buf==NULL) { printf("Error allocating memory\n"); return UNZ_INTERNALERROR; } p = filename_withoutpath = filename_inzip; while ((*p) != '\0') { if (((*p)=='/') || ((*p)=='\\')) filename_withoutpath = p+1; p++; } if ((*filename_withoutpath)=='\0') { if ((*popt_extract_without_path)==0) { printf("creating directory: %s\n",filename_inzip); mymkdir(filename_inzip); } } else { char* write_filename; int skip=0; if ((*popt_extract_without_path)==0) write_filename = filename_inzip; else write_filename = filename_withoutpath; err = unzOpenCurrentFilePassword(uf,password); if (err!=UNZ_OK) { printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err); } if ((skip==0) && (err==UNZ_OK)) { res = f_open_char(&f,write_filename,FA_WRITE|FA_CREATE_ALWAYS); /* some zipfile don't contain directory alone before file */ if ((res != FR_OK) && ((*popt_extract_without_path)==0) && (filename_withoutpath!=(char*)filename_inzip)) { char c=*(filename_withoutpath-1); *(filename_withoutpath-1)='\0'; makedir(write_filename); *(filename_withoutpath-1)=c; res = f_open_char(&f,write_filename,FA_WRITE|FA_CREATE_ALWAYS); } if (res != FR_OK) { printf("error opening %s\n",write_filename); } } if (res == FR_OK) { printf(" extracting: %s\n",write_filename); do { err = unzReadCurrentFile(uf,buf,size_buf); if (err<0) { printf("error %d with zipfile in unzReadCurrentFile\n",err); break; } if (err>0) { UINT wrote; if (f_write(&f,buf,err,&wrote)!=FR_OK) { printf("error in writing extracted file\n"); err=UNZ_ERRNO; break; } } } while (err>0); if (res == FR_OK) { f_close(&f); res = FR_NO_FILE; } } if (err==UNZ_OK) { err = unzCloseCurrentFile (uf); if (err!=UNZ_OK) { printf("error %d with zipfile in unzCloseCurrentFile\n",err); } } else unzCloseCurrentFile(uf); /* don't lose the error */ } free(buf); return err; }
int _main( int argc, char *argv[] ) { //BSS is in DATA section so IOS doesnt touch it, we need to manually clear it //dbgprintf("memset32(%08x, 0, %08x)\n", &__bss_start, &__bss_end - &__bss_start); memset32(&__bss_start, 0, &__bss_end - &__bss_start); sync_after_write(&__bss_start, &__bss_end - &__bss_start); s32 ret = 0; u32 DI_Thread = 0; u8 MessageHeap[0x10]; BootStatus(0, 0, 0); thread_set_priority( 0, 0x79 ); // do not remove this, this waits for FS to be ready! thread_set_priority( 0, 0x50 ); thread_set_priority( 0, 0x79 ); //Disable AHBPROT EnableAHBProt(-1); //Load IOS Modules ES_Init( MessageHeap ); //Early HID for loader HIDInit(); //Enable DVD Access write32(HW_DIFLAGS, read32(HW_DIFLAGS) & ~DI_DISABLEDVD); dbgprintf("Sending signal to loader\r\n"); BootStatus(1, 0, 0); mdelay(10); //Loader running, selects games while(1) { sync_before_read((void*)RESET_STATUS, 0x20); vu32 reset_status = read32(RESET_STATUS); if(reset_status != 0) { if(reset_status == 0x0DEA) break; //game selected else if(reset_status == 0x1DEA) goto DoIOSBoot; //exit write32(RESET_STATUS, 0); sync_after_write((void*)RESET_STATUS, 0x20); } HIDUpdateRegisters(1); mdelay(10); } ConfigSyncBeforeRead(); u32 UseUSB = ConfigGetConfig(NIN_CFG_USB); SetDiskFunctions(UseUSB); BootStatus(2, 0, 0); if(UseUSB) { ret = USBStorage_Startup(); dbgprintf("USB:Drive size: %dMB SectorSize:%d\r\n", s_cnt / 1024 * s_size / 1024, s_size); } else { s_size = PAGE_SIZE512; //manually set s_size ret = SDHCInit(); } if(ret != 1) { dbgprintf("Device Init failed:%d\r\n", ret ); BootStatusError(-2, ret); mdelay(4000); Shutdown(); } //Verification if we can read from disc if(memcmp(ConfigGetGamePath(), "di", 3) == 0) RealDI_Init(); //will shutdown on fail BootStatus(3, 0, 0); fatfs = (FATFS*)malloca( sizeof(FATFS), 32 ); s32 res = f_mount( fatfs, fatDevName, 1 ); if( res != FR_OK ) { dbgprintf("ES:f_mount() failed:%d\r\n", res ); BootStatusError(-3, res); mdelay(4000); Shutdown(); } BootStatus(4, 0, 0); BootStatus(5, 0, 0); FIL fp; s32 fres = f_open_char(&fp, "/bladie", FA_READ|FA_OPEN_EXISTING); switch(fres) { case FR_OK: f_close(&fp); case FR_NO_PATH: case FR_NO_FILE: { fres = FR_OK; } break; default: case FR_DISK_ERR: { BootStatusError(-5, fres); mdelay(4000); Shutdown(); } break; } if(!UseUSB) //Use FAT values for SD s_cnt = fatfs->n_fatent * fatfs->csize; BootStatus(6, s_size, s_cnt); BootStatus(7, s_size, s_cnt); ConfigInit(); if (ConfigGetConfig(NIN_CFG_LOG)) SDisInit = 1; // Looks okay after threading fix dbgprintf("Game path: %s\r\n", ConfigGetGamePath()); BootStatus(8, s_size, s_cnt); memset32((void*)RESET_STATUS, 0, 0x20); sync_after_write((void*)RESET_STATUS, 0x20); memset32((void*)0x13002800, 0, 0x30); sync_after_write((void*)0x13002800, 0x30); memset32((void*)0x13160000, 0, 0x20); sync_after_write((void*)0x13160000, 0x20); memset32((void*)0x13026500, 0, 0x100); sync_after_write((void*)0x13026500, 0x100); BootStatus(9, s_size, s_cnt); DIRegister(); DI_Thread = thread_create(DIReadThread, NULL, ((u32*)&__di_stack_addr), ((u32)(&__di_stack_size)) / sizeof(u32), 0x78, 1); thread_continue(DI_Thread); DIinit(true); BootStatus(10, s_size, s_cnt); GCAMInit(); EXIInit(); BootStatus(11, s_size, s_cnt); SIInit(); StreamInit(); PatchInit(); //Tell PPC side we are ready! cc_ahbMemFlush(1); mdelay(1000); BootStatus(0xdeadbeef, s_size, s_cnt); mdelay(1000); //wait before hw flag changes dbgprintf("Kernel Start\r\n"); //write32( 0x1860, 0xdeadbeef ); // Clear OSReport area //sync_after_write((void*)0x1860, 0x20); u32 Now = read32(HW_TIMER); u32 PADTimer = Now; u32 DiscChangeTimer = Now; u32 ResetTimer = Now; u32 InterruptTimer = Now; USBReadTimer = Now; u32 Reset = 0; bool SaveCard = false; if( ConfigGetConfig(NIN_CFG_LED) ) { set32(HW_GPIO_ENABLE, GPIO_SLOT_LED); clear32(HW_GPIO_DIR, GPIO_SLOT_LED); clear32(HW_GPIO_OWNER, GPIO_SLOT_LED); } set32(HW_GPIO_ENABLE, GPIO_SENSOR_BAR); clear32(HW_GPIO_DIR, GPIO_SENSOR_BAR); clear32(HW_GPIO_OWNER, GPIO_SENSOR_BAR); set32(HW_GPIO_OUT, GPIO_SENSOR_BAR); //turn on sensor bar write32( HW_PPCIRQMASK, (1<<30) ); write32( HW_PPCIRQFLAG, read32(HW_PPCIRQFLAG) ); //This bit seems to be different on japanese consoles u32 ori_ppcspeed = read32(HW_PPCSPEED); if((ConfigGetGameID() & 0xFF) == 'J') set32(HW_PPCSPEED, (1<<17)); else clear32(HW_PPCSPEED, (1<<17)); u32 ori_widesetting = read32(0xd8006a0); if(IsWiiU) { if( ConfigGetConfig(NIN_CFG_WIIU_WIDE) ) write32(0xd8006a0, 0x30000004); else write32(0xd8006a0, 0x30000002); mask32(0xd8006a8, 0, 2); } while (1) { _ahbMemFlush(0); //Does interrupts again if needed if(TimerDiffTicks(InterruptTimer) > 15820) //about 120 times a second { sync_before_read((void*)INT_BASE, 0x80); if((read32(RSW_INT) & 2) || (read32(DI_INT) & 4) || (read32(SI_INT) & 8) || (read32(EXI_INT) & 0x10)) write32(HW_IPC_ARMCTRL, (1 << 0) | (1 << 4)); //throw irq InterruptTimer = read32(HW_TIMER); } #ifdef PATCHALL if (EXI_IRQ == true) { if(EXICheckTimer()) EXIInterrupt(); } #endif if (SI_IRQ != 0) { if ((TimerDiffTicks(PADTimer) > 7910) || (SI_IRQ & 0x2)) // about 240 times a second { SIInterrupt(); PADTimer = read32(HW_TIMER); } } if(DI_IRQ == true) { if(DiscCheckAsync()) DIInterrupt(); else udelay(200); //let the driver load data } else if(SaveCard == true) /* DI IRQ indicates we might read async, so dont write at the same time */ { if(TimerDiffSeconds(Now) > 2) /* after 3 second earliest */ { EXISaveCard(); SaveCard = false; } } else if(UseUSB && TimerDiffSeconds(USBReadTimer) > 149) /* Read random sector every 2 mins 30 secs */ { DIFinishAsync(); //if something is still running DI_CallbackMsg.result = -1; sync_after_write(&DI_CallbackMsg, 0x20); IOS_IoctlAsync( DI_Handle, 2, NULL, 0, NULL, 0, DI_MessageQueue, &DI_CallbackMsg ); DIFinishAsync(); USBReadTimer = read32(HW_TIMER); } udelay(10); //wait for other threads //Baten Kaitos save hax /*if( read32(0) == 0x474B4245 ) { if( read32( 0x0073E640 ) == 0xFFFFFFFF ) { write32( 0x0073E640, 0 ); } }*/ if( WaitForRealDisc == 1 ) { if(RealDI_NewDisc()) { DiscChangeTimer = read32(HW_TIMER); WaitForRealDisc = 2; //do another flush round, safety! } } else if( WaitForRealDisc == 2 ) { if(TimerDiffSeconds(DiscChangeTimer)) { //identify disc after flushing everything RealDI_Identify(false); //clear our fake regs again sync_before_read((void*)DI_BASE, 0x40); write32(DI_IMM, 0); write32(DI_COVER, 0); sync_after_write((void*)DI_BASE, 0x40); //mask and clear interrupts write32( DIP_STATUS, 0x54 ); //disable cover irq which DIP enabled write32( DIP_COVER, 4 ); DIInterrupt(); WaitForRealDisc = 0; } } if ( DiscChangeIRQ == 1 ) { DiscChangeTimer = read32(HW_TIMER); DiscChangeIRQ = 2; } else if ( DiscChangeIRQ == 2 ) { if ( TimerDiffSeconds(DiscChangeTimer) > 2 ) { DIInterrupt(); DiscChangeIRQ = 0; } } _ahbMemFlush(1); DIUpdateRegisters(); #ifdef PATCHALL EXIUpdateRegistersNEW(); GCAMUpdateRegisters(); BTUpdateRegisters(); HIDUpdateRegisters(0); if(DisableSIPatch == 0) SIUpdateRegisters(); #endif StreamUpdateRegisters(); CheckOSReport(); if(EXICheckCard()) { Now = read32(HW_TIMER); SaveCard = true; } sync_before_read((void*)RESET_STATUS, 0x20); vu32 reset_status = read32(RESET_STATUS); if (reset_status == 0x1DEA) { write32(RESET_STATUS, 0); sync_after_write((void*)RESET_STATUS, 0x20); DIFinishAsync(); break; } if (reset_status == 0x3DEA) { if (Reset == 0) { dbgprintf("Fake Reset IRQ\n"); write32( RSW_INT, 0x2 ); // Reset irq sync_after_write( (void*)RSW_INT, 0x20 ); write32(HW_IPC_ARMCTRL, (1 << 0) | (1 << 4)); //throw irq Reset = 1; } } else if (Reset == 1) { write32( RSW_INT, 0x10000 ); // send pressed sync_after_write( (void*)RSW_INT, 0x20 ); ResetTimer = read32(HW_TIMER); Reset = 2; } /* The cleanup is not connected to the button press */ if (Reset == 2) { if (TimerDiffTicks(ResetTimer) > 949219) //free after half a second { write32( RSW_INT, 0 ); // done, clear sync_after_write( (void*)RSW_INT, 0x20 ); Reset = 0; } } if(reset_status == 0x4DEA) PatchGame(); if(reset_status == 0x5DEA) { SetIPL(); PatchGame(); } if(reset_status == 0x6DEA) { SetIPL_TRI(); write32(RESET_STATUS, 0); sync_after_write((void*)RESET_STATUS, 0x20); } if(read32(HW_GPIO_IN) & GPIO_POWER) { DIFinishAsync(); #ifdef PATCHALL BTE_Shutdown(); #endif Shutdown(); } //sync_before_read( (void*)0x1860, 0x20 ); //if( read32(0x1860) != 0xdeadbeef ) //{ // if( read32(0x1860) != 0 ) // { // dbgprintf( (char*)(P2C(read32(0x1860))), // (char*)(P2C(read32(0x1864))), // (char*)(P2C(read32(0x1868))), // (char*)(P2C(read32(0x186C))), // (char*)(P2C(read32(0x1870))), // (char*)(P2C(read32(0x1874))) // ); // } // write32(0x1860, 0xdeadbeef); // sync_after_write( (void*)0x1860, 0x20 ); //} cc_ahbMemFlush(1); } //if( UseHID ) HIDClose(); IOS_Close(DI_Handle); //close game thread_cancel(DI_Thread, 0); DIUnregister(); /* reset time */ while(1) { sync_before_read( (void*)RESET_STATUS, 0x20 ); if(read32(RESET_STATUS) == 0x2DEA) break; wait_for_ppc(1); } if( ConfigGetConfig(NIN_CFG_LED) ) clear32(HW_GPIO_OUT, GPIO_SLOT_LED); if( ConfigGetConfig(NIN_CFG_MEMCARDEMU) ) EXIShutdown(); if (ConfigGetConfig(NIN_CFG_LOG)) closeLog(); #ifdef PATCHALL BTE_Shutdown(); #endif //unmount FAT device free(fatfs); fatfs = NULL; f_mount(NULL, fatDevName, 1); if(UseUSB) USBStorage_Shutdown(); else SDHCShutdown(); //make sure we set that back to the original write32(HW_PPCSPEED, ori_ppcspeed); if(IsWiiU) { write32(0xd8006a0, ori_widesetting); mask32(0xd8006a8, 0, 2); } DoIOSBoot: sync_before_read((void*)0x13003000, 0x420); IOSBoot((char*)0x13003020, 0, read32(0x13003000)); return 0; }
u32 TRISetupGames(char *Path, u32 CurDICMD, u32 ISOShift) { u32 res = 0; u32 DOLOffset = 0; FIL f; FIL *fp = NULL; UINT read; FRESULT fres = FR_DISK_ERR; if(CurDICMD) { ReadRealDisc((u8*)&DOLOffset, 0x420+ISOShift, 4, CurDICMD); DOLOffset+=ISOShift; } else { char FullPath[260]; snprintf(FullPath, sizeof(FullPath), "%s:%s", GetRootDevice(), Path); fres = f_open_char(&f, FullPath, FA_READ|FA_OPEN_EXISTING); if (fres == FR_OK) { f_lseek(&f, 0x420+ISOShift); f_read(&f, &DOLOffset, 4, &read); DOLOffset+=ISOShift; } else { char FSTPath[260]; snprintf(FSTPath, sizeof(FSTPath), "%ssys/main.dol", FullPath); fres = f_open_char(&f, FSTPath, FA_READ|FA_OPEN_EXISTING); } if (fres != FR_OK) return 0; fp = &f; } // Create the save file if it doesn't already exist. char SaveFile[128]; if(DOLRead32(0x210320, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Mario Kart Arcade GP (Feb 14 2006 13:09:48)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), CARD_NAME_GP1); CreateNewFile(SaveFile, 0x45); } else if(DOLRead32(0x25C0AC, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Mario Kart Arcade GP 2 (Feb 7 2007 02:47:24)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), CARD_NAME_GP2); CreateNewFile(SaveFile, 0x45); } else if(DOLRead32(0x181E60, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:F-Zero AX (Rev C)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), CARD_NAME_AX); CreateNewFile(SaveFile, 0xCF); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_AX_RVC); CreateNewFile(SaveFile, 0x2A); } else if(DOLRead32(0x1821C4, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:F-Zero AX (Rev D)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), CARD_NAME_AX); CreateNewFile(SaveFile, 0xCF); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_AX_RVD); CreateNewFile(SaveFile, 0x2A); } else if(DOLRead32(0x18275C, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:F-Zero AX (Rev E)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), CARD_NAME_AX); CreateNewFile(SaveFile, 0xCF); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_AX_RVE); CreateNewFile(SaveFile, 0x2A); } else if(DOLRead32(0x01C2DF4, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Virtua Striker 3 Ver 2002\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_VS3V02); CreateNewFile(SaveFile, 0x12); } else if(DOLRead32(0x01CF1C4, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Virtua Striker 4 (Japan)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_VS4JAP); CreateNewFile(SaveFile, 0x2B); } else if(DOLRead32(0x1C5514, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Virtua Striker 4 (Export)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_VS4EXP); CreateNewFile(SaveFile, 0x2B); } else if(DOLRead32(0x24B248, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Virtua Striker 4 Ver 2006 (Japan)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_VS4V06JAP); CreateNewFile(SaveFile, 0x2E); } else if(DOLRead32(0x20D7E8, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Virtua Striker 4 Ver 2006 (Export)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_VS4V06EXP); CreateNewFile(SaveFile, 0x2B); } else if(DOLRead32(0x26B3F4, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Gekitou Pro Yakyuu (Rev B)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_YAKRVB); CreateNewFile(SaveFile, 0xF5); } else if(DOLRead32(0x26D9B4, DOLOffset, fp, CurDICMD) == 0x386000A8) { res = 1; gprintf("TRI:Gekitou Pro Yakyuu (Rev C)\r\n"); snprintf(SaveFile, sizeof(SaveFile), "%s:%s", GetRootDevice(), SETTINGS_YAKRVC); CreateNewFile(SaveFile, 0x100); } if (fres == FR_OK) f_close(&f); return res; }
void GCAMCARDCommand( char *DataIn, char *DataOut ) { if( DataIn[DataPos] == 1 && DataIn[DataPos+1] == 0x05 ) { // dbgprintf("CARDGetReply(%02X)\n", CARDCommand ); if( CARDReadLength ) { res[resp++] = 0x32; u32 ReadLength = CARDReadLength - CARDRead; if( TRIGame == TRI_AX ) { if( ReadLength > 0x2F ) ReadLength = 0x2F; } res[resp++] = ReadLength; // 0x2F (max size per packet) memcpy( res+resp, CARDReadPacket+CARDRead, ReadLength ); resp += ReadLength; CARDRead += ReadLength; // dbgprintf("CARDRead: %u/%u\n", CARDRead, CARDReadLength ); if( CARDRead >= CARDReadLength ) CARDReadLength = 0; // hexdump( res, 0x80 ); DataPos += DataIn[DataPos] + 1; return; } res[resp++] = 0x32; u32 CMDLenO = resp; res[resp++] = 0x00; // len res[resp++] = 0x02; // u32 ChkStart = resp; res[resp++] = 0x00; // 0x00 len switch(CARDCommand) { case CARD_INIT: { res[resp++] = 0x10; // 0x01 res[resp++] = 0x00; // 0x02 res[resp++] = 0x30; // 0x03 } break; case CARD_IS_PRESENT: { res[resp++] = 0x40; // 0x01 res[resp++] = 0x22; // 0x02 res[resp++] = 0x30; // 0x03 } break; case CARD_GET_CARD_STATE: { res[resp++] = 0x20; // 0x01 res[resp++] = 0x20|CARDBit; // 0x02 /* bit 0: PLease take your card bit 1: endless waiting casues UNK_E to be called */ res[resp++] = 0x00; // 0x03 } break; case CARD_7A: { res[resp++] = 0x7A; // 0x01 res[resp++] = 0x00; // 0x02 res[resp++] = 0x00; // 0x03 } break; case CARD_78: { res[resp++] = 0x78; // 0x01 res[resp++] = 0x00; // 0x02 res[resp++] = 0x00; // 0x03 } break; case CARD_WRITE_INFO: { res[resp++] = 0x7C; // 0x01 res[resp++] = 0x02; // 0x02 res[resp++] = 0x00; // 0x03 } break; case CARD_D0: { res[resp++] = 0xD0; // 0x01 res[resp++] = 0x00; // 0x02 res[resp++] = 0x00; // 0x03 } break; case CARD_80: { res[resp++] = 0x80; // 0x01 if( TRIGame == TRI_AX ) res[resp++] = 0x01; // 0x02 else res[resp++] = 0x31; // 0x02 res[resp++] = 0x30; // 0x03 } break; case CARD_CLEAN_CARD: { res[resp++] = 0xA0; // 0x01 res[resp++] = 0x02; // 0x02 res[resp++] = 0x00; // 0x03 } break; case CARD_LOAD_CARD: { res[resp++] = 0xB0; // 0x01 res[resp++] = 0x02; // 0x02 res[resp++] = 0x30; // 0x03 } break; case CARD_WRITE: { res[resp++] = 0x53; // 0x01 res[resp++] = 0x02; // 0x02 res[resp++] = 0x00; // 0x03 } break; case CARD_READ: { res[resp++] = 0x33; // 0x01 res[resp++] = 0x02; // 0x02 res[resp++] = 0x53; // 0x03 } break; } res[resp++] = 0x30; // 0x04 res[resp++] = 0x00; // 0x05 res[resp++] = 0x03; // 0x06 res[ChkStart] = resp-ChkStart; // 0x00 len u32 i; res[resp] = 0; // 0x07 for( i=0; i < res[ChkStart]; ++i ) res[resp] ^= res[ChkStart+i]; resp++; res[CMDLenO] = res[ChkStart] + 2; } else { memcpy( CARDBuffer + CARDOffset, DataIn+DataPos+1, DataIn[DataPos] ); CARDOffset += DataIn[DataPos]; //Check if we got complete CMD if( CARDBuffer[0] == 0x02 ) { if( CARDBuffer[1] == CARDOffset - 2 ) { if( CARDBuffer[CARDOffset-2] == 0x03 ) { u32 cmd = CARDBuffer[2] << 24; cmd|= CARDBuffer[3] << 16; cmd|= CARDBuffer[4] << 8; cmd|= CARDBuffer[5] << 0; switch(cmd) { default: { // dbgprintf("CARD:Unhandled cmd!\n"); // dbgprintf("CARD:[%08X]\n", cmd ); // hexdump( CARDBuffer, CARDOffset ); } break; case 0x10000000: { #ifdef DEBUG_CARD dbgprintf("CARDInit()\n"); #endif CARDCommand = CARD_INIT; CARDWriteLength = 0; CARDBit = 0; CARDMemorySize = 0; CARDStateCallCount = 0; } break; case 0x20000000: { #ifdef DEBUG_CARD dbgprintf("CARDGetState(%02X)\n", CARDBit ); #endif CARDCommand = CARD_GET_CARD_STATE; if( TRIGame == TRI_AX && CARDMemorySize ) { CARDStateCallCount++; if( CARDStateCallCount > 10 ) { if( CARDBit & 2 ) CARDBit &= ~2; else CARDBit |= 2; CARDStateCallCount = 0; } } if( CARDClean == 1 ) { CARDClean = 2; } else if( CARDClean == 2 ) { DIFinishAsync(); //DONT ever try todo file i/o async FIL fi; if( f_open_char( &fi, GCAMGetCARDName(), FA_READ|FA_OPEN_EXISTING ) == FR_OK ) { if( fi.fsize > 0 ) { CARDMemorySize = fi.fsize; if( TRIGame == TRI_AX ) CARDBit = 2; else CARDBit = 1; } f_close(&fi); } CARDClean = 0; } } break; case 0x40000000: { #ifdef DEBUG_CARD dbgprintf("CARDIsPresent()\n"); #endif CARDCommand = CARD_IS_PRESENT; } break; case 0x7A000000: { #ifdef DEBUG_CARD dbgprintf("CARDUnknown7A()\n"); #endif CARDCommand = CARD_7A; //hexdump( CARDBuffer+2, CARDOffset-2 ); } break; case 0xB0000000: { #ifdef DEBUG_CARD dbgprintf("CARDLoadCard()\n"); #endif CARDCommand = CARD_LOAD_CARD; } break; case 0xA0000000: { #ifdef DEBUG_CARD dbgprintf("CARDIsCleanCard?()\n"); #endif CARDCommand = CARD_CLEAN_CARD; CARDClean = 1; } break; case 0x33000000: { #ifdef DEBUG_CARD dbgprintf("CARDRead()\n"); #endif CARDCommand = CARD_READ; //Prepare read packet memset( CARDReadPacket, 0, 0xDB ); u32 POff=0; DIFinishAsync(); //DONT ever try todo file i/o async FIL cf; if( f_open_char( &cf, GCAMGetCARDName(), FA_READ|FA_OPEN_EXISTING ) == FR_OK ) { if( CARDMemorySize == 0 ) CARDMemorySize = cf.fsize; u32 read; f_read( &cf, CARDMemory, CARDMemorySize, &read ); f_close( &cf ); sync_after_write(CARDMemory, CARDMemorySize); CARDIsInserted = 1; } CARDReadPacket[POff++] = 0x02; // SUB CMD CARDReadPacket[POff++] = 0x00; // SUB CMDLen CARDReadPacket[POff++] = 0x33; // CARD CMD if( CARDIsInserted ) { CARDReadPacket[POff++] = '1'; // CARD Status } else { CARDReadPacket[POff++] = '0'; // CARD Status } CARDReadPacket[POff++] = '0'; // CARDReadPacket[POff++] = '0'; // //Data reply sync_before_read(CARDMemory, CARDMemorySize); memcpy( CARDReadPacket + POff, CARDMemory, CARDMemorySize ); POff += CARDMemorySize; CARDReadPacket[POff++] = 0x03; CARDReadPacket[1] = POff-1; // SUB CMDLen u32 i; for( i=0; i < POff-1; ++i ) CARDReadPacket[POff] ^= CARDReadPacket[1+i]; POff++; // hexdump( CARDReadPacket, POff ); CARDReadLength = POff; CARDRead = 0; } break; case 0x53000000: { CARDCommand = CARD_WRITE; CARDMemorySize = CARDBuffer[1] - 9; memcpy( CARDMemory, CARDBuffer+9, CARDMemorySize ); #ifdef DEBUG_CARD dbgprintf("CARDWrite: %u\n", CARDMemorySize ); #endif u32 CARDIsValid; switch(TRIGame) { case TRI_GP1: case TRI_GP2: CARDIsValid = (memcmp(CARDMemory, "MKA", 3) == 0); break; case TRI_AX: CARDIsValid = (memcmp(CARDMemory+0x8A, "SEGABGG", 7) == 0); break; default: CARDIsValid = 0; break; } if(CARDIsValid) { DIFinishAsync(); //DONT ever try todo file i/o async FIL cf; if( f_open_char( &cf, GCAMGetCARDName(), FA_WRITE|FA_CREATE_ALWAYS ) == FR_OK ) { u32 wrote; f_write( &cf, CARDMemory, CARDMemorySize, &wrote ); f_close( &cf ); } } CARDBit = 2; sync_after_write(CARDMemory, CARDMemorySize); CARDStateCallCount = 0; } break; case 0x78000000: { #ifdef DEBUG_CARD dbgprintf("CARDUnknown78()\n"); #endif CARDCommand = CARD_78; } break; case 0x7C000000: { #ifdef DEBUG_CARD dbgprintf("CARDWriteCardInfo()\n"); #endif CARDCommand = CARD_WRITE_INFO; // hexdump( CARDBuffer, CARDOffset ); } break; case 0x7D000000: { #ifdef DEBUG_CARD dbgprintf("CARDPrint?()\n"); #endif CARDCommand = CARD_7D; } break; case 0x80000000: { #ifdef DEBUG_CARD dbgprintf("CARDUnknown80()\n"); #endif CARDCommand = CARD_80; if( TRIGame != TRI_AX ) CARDBit = 0; } break; case 0xD0000000: { #ifdef DEBUG_CARD dbgprintf("CARDUnknownD0()\n"); #endif CARDCommand = CARD_D0; if( TRIGame != TRI_AX ) CARDBit = 0; } break; } // hexdump( CARDBuffer, CARDOffset ); CARDOffset = 0; } } } res[resp++] = 0x32; res[resp++] = 0x01; // len res[resp++] = 0x06; // OK } }