void populateArgv(int *argc, char *argv[], char *filename) { int i = 0; Parameters* params = getParameters(); print_gecko("There are %i parameters\r\n", params->num_params); for(i = 0; i < params->num_params; i++) { Parameter *param = ¶ms->parameters[i]; if(param->enable) { if(*argc == 0) { // Filename first argv[0] = filename; *argc += 1; } ParameterValue *arg = ¶m->arg; ParameterValue *val = ¶m->values[param->currentValueIdx]; //print_gecko("Arg: (%s) [%s] is enabled with value (%s) [%s]\r\n", // arg->value, arg->name, val->value, val->name); char *argvEntry = (char*)malloc((MAX_PARAM_STRING * 2) + 2); memset(argvEntry, 0, (MAX_PARAM_STRING * 2) + 2); if(!arg->value[0]) sprintf(argvEntry, "%s", val->value); else sprintf(argvEntry, "%s=%s", arg->value, val->value); print_gecko("Argv entry: [%s]\r\n", argvEntry); argv[*argc] = argvEntry; *argc+=1; } } print_gecko("Arg count: %i\r\n", *argc); }
int CARD_ReadUnaligned(card_file *cardfile, void *buffer, unsigned int length, unsigned int offset, int slot) { void *dst = buffer; u8 *read_buffer = (u8*)memalign(32,card_sectorsize[slot]); int ret = CARD_ERROR_READY; print_gecko("Unaligned read dst %08X offset %08X length %i\r\n", dst, offset, length); // Unaligned because we're in the middle of a sector, read partial ret = CARD_Read(cardfile, read_buffer, card_sectorsize[slot], offset-(offset&0x1ff)); print_gecko("CARD_Read offset %08X length %i\r\n", offset-(offset&0x1ff), card_sectorsize[slot]); if(ret != CARD_ERROR_READY) { free(read_buffer); return ret; } int amountRead = card_sectorsize[slot]-(offset&0x1ff); int amountToCopy = length > amountRead ? amountRead : length; memcpy(dst, read_buffer+(offset&0x1ff), amountToCopy); dst += amountToCopy; length -= amountToCopy; offset += amountToCopy; if(length != 0) { print_gecko("Unaligned read leftovers offset %08X length %i\r\n", offset, length); // At least this will be aligned ret = CARD_Read(cardfile, read_buffer, card_sectorsize[slot], offset); print_gecko("CARD_Read offset %08X length %i\r\n", offset, card_sectorsize[slot]); if(ret != CARD_ERROR_READY) { free(read_buffer); return ret; } memcpy(dst, read_buffer, length); } free(read_buffer); return ret; }
void scanFiles() { freeFiles(); // Read the directory/device TOC if(curDirEntries){ free(curDirEntries); curDirEntries = NULL; } print_gecko("Reading directory: %s\r\n",curFile.name); curDirEntryCount = devices[DEVICE_CUR]->readDir(&curFile, &curDirEntries, -1); memcpy(&curDir, &curFile, sizeof(file_handle)); sortFiles(curDirEntries, curDirEntryCount); print_gecko("Found %i entries\r\n",curDirEntryCount); }
void printCheats(void) { int i = 0, j = 0; print_gecko("There are %i cheats\r\n", _cheats.num_cheats); for(i = 0; i < _cheats.num_cheats; i++) { CheatEntry *cheat = &_cheats.cheat[i]; print_gecko("Cheat: (%i codes) %s\r\n", cheat->num_codes, cheat->name); for(j = 0; j < cheat->num_codes; j++) { print_gecko("%08X %08X\r\n", cheat->codes[j][0], cheat->codes[j][1]); } } }
void printParams(Parameters *params) { int i = 0, j = 0; print_gecko("There are %i parameters\r\n", params->num_params); for(i = 0; i < params->num_params; i++) { Parameter *param = ¶ms->parameters[i]; ParameterValue *arg = ¶m->arg; print_gecko("Argument: (%s) [%s]\r\n", arg->value, arg->name); print_gecko("This parameter has %i values\r\n", param->num_values); for(j = 0; j < params->parameters[i].num_values; j++) { print_gecko("Value: (%s) [%s]\r\n", params->parameters[i].values[j].value, params->parameters[i].values[j].name); } } }
int verify_findMD5Sum(const char * md5orig, int disc_type) { print_gecko("Looking for MD5 [%s]\r\n", md5orig); char *xmlPointer = (disc_type == IS_NGC_DISC) ? ngcDAT : wiiDAT; if(xmlPointer) { mxml_node_t *pointer = (disc_type == IS_NGC_DISC) ? ngcXML : wiiXML; pointer = mxmlLoadString(NULL, xmlPointer, MXML_TEXT_CALLBACK); print_gecko("Looking in the %s XML\r\n", pointer == ngcXML ? "GameCube" : "Wii"); if (pointer) { // open the <datafile> mxml_node_t *item = mxmlFindElement(pointer, pointer, "datafile", NULL, NULL, MXML_DESCEND); print_gecko("DataFile Pointer OK\r\n"); if (item) { mxml_index_t *iterator = mxmlIndexNew(item, "game", NULL); mxml_node_t *gameElem = NULL; //print_gecko("Item Pointer OK\r\n"); // iterate over all the <game> entries while ((gameElem = mxmlIndexEnum(iterator)) != NULL) { // get the md5 and compare it mxml_node_t *md5Elem = mxmlFindElement(gameElem, gameElem, NULL, "md5", NULL, MXML_DESCEND); // get the name too mxml_node_t *nameElem = mxmlFindElement(gameElem, gameElem, NULL, "name", NULL, MXML_DESCEND); char md5[64]; memset(&md5[0], 0, 64); strncpy(&md5[0], mxmlElementGetAttr(md5Elem, "md5"), 32); //print_gecko("Comparing game [%s] and md5 [%s]\r\n",mxmlElementGetAttr(nameElem, "name"),mxmlElementGetAttr(md5Elem, "md5")); if (!strnicmp(&md5[0], md5orig, 32)) { snprintf(&gameName[0], 128, "%s", mxmlElementGetAttr( nameElem, "name")); print_gecko("Found a match!\r\n"); return 1; } } } } } return 0; }
void trySlotB() { if (deviceHandler_FAT_init(&initial_SD1)) { forceSlot = 1; print_gecko("Detected SDGecko in Slot B for config\r\n"); } else { forceSlot = 0; } }
s32 deviceHandler_CARD_init(file_handle* file){ int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)); file->status = initialize_card(slot); s32 memSize = 0, sectSize = 0; int ret = CARD_ProbeEx(slot,&memSize,§Size); if(ret==CARD_ERROR_READY) { initial_CARD_info.totalSpaceInKB = (memSize<<7); } else { print_gecko("CARD_ProbeEx failed %i\r\n", ret); } initial_CARD_info.freeSpaceInKB = 0; return file->status == CARD_ERROR_READY ? 1 : 0; }
// Installs the GeckoOS (kenobiGC) cheats engine and sets up variables/copies cheats void kenobi_install_engine() { int isDebug = swissSettings.wiirdDebug; // If high memory is in use, we'll use low, otherwise high. u8 *ptr = isDebug ? kenobigc_dbg_bin : kenobigc_bin; u32 size = isDebug ? kenobigc_dbg_bin_size : kenobigc_bin_size; print_gecko("Copying kenobi%s to %08X\r\n", (isDebug?"_dbg":""),(u32)CHEATS_ENGINE); memcpy(CHEATS_ENGINE, ptr, size); memcpy(CHEATS_GAMEID, (void*)0x80000000, CHEATS_GAMEID_LEN); if(!isDebug) { CHEATS_ENABLE_CHEATS = CHEATS_TRUE; } CHEATS_START_PAUSED = isDebug ? CHEATS_TRUE : CHEATS_FALSE; memset(CHEATS_LOCATION(size), 0, kenobi_get_maxsize()); print_gecko("Copying %i bytes of cheats to %08X\r\n", getEnabledCheatsSize(),(u32)CHEATS_LOCATION(size)); u32 *cheatsLocation = (u32*)CHEATS_LOCATION(size); cheatsLocation[0] = 0x00D0C0DE; cheatsLocation[1] = 0x00D0C0DE; cheatsLocation+=2; int i = 0, j = 0; for(i = 0; i < _cheats.num_cheats; i++) { CheatEntry *cheat = &_cheats.cheat[i]; if(cheat->enabled) { for(j = 0; j < cheat->num_codes; j++) { // Copy & fix cheats that want to jump to the old cheat engine location 0x800018A8 -> CHEATS_ENGINE+0xA8 cheatsLocation[0] = cheat->codes[j][0]; cheatsLocation[1] = cheat->codes[j][1] == 0x800018A8 ? (u32)(CHEATS_ENGINE+0xA8) : cheat->codes[j][1]; cheatsLocation+=2; } } } cheatsLocation[0] = 0xFF000000; DCFlushRange((void*)CHEATS_ENGINE, WIIRD_ENGINE_SPACE); ICInvalidateRange((void*)CHEATS_ENGINE, WIIRD_ENGINE_SPACE); }
// Checks if devices are available, prints name of device being detected for slow init devices void populateDeviceAvailability() { if(PAD_ButtonsHeld(0) & PAD_BUTTON_B) { deviceHandler_setAllDevicesAvailable(); return; } uiDrawObj_t *msgBox = DrawPublish(DrawProgressBar(true, 0, "Detecting devices ...\nThis can be skipped by holding B next time")); int i; for(i = 0; i < MAX_DEVICES; i++) { if(allDevices[i] != NULL && !deviceHandler_getDeviceAvailable(allDevices[i])) { print_gecko("Checking device availability for device %s\r\n", allDevices[i]->deviceName); deviceHandler_setDeviceAvailable(allDevices[i], allDevices[i]->test()); } if(PAD_ButtonsHeld(0) & PAD_BUTTON_B) { deviceHandler_setAllDevicesAvailable(); break; } } DrawDispose(msgBox); }
s32 deviceHandler_CARD_deleteFile(file_handle* file) { int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)); char *filename = getRelativeName(file->name); card_dir* cd = (card_dir*)&file->other; CARD_SetCompany((const char*)cd->company); CARD_SetGamecode((const char*)cd->gamecode); print_gecko("Deleting: %s from slot %i\r\n", filename, slot); int ret = CARD_DeleteEntry(slot, cd); if(ret != CARD_ERROR_READY) { uiDrawObj_t *msgBox = DrawMessageBox(D_FAIL,cardError(ret)); DrawPublish(msgBox); wait_press_A(); DrawDispose(msgBox); } return ret; }
// If there was some new files obtained, return 1, else 0 void verify_download(char *mountPath) { if(dontAskAgain) { return; } int res = 0; // Ask the user if they want to update from the web if(verify_initialized) { char *line1 = "Redump.org DAT files found"; char *line2 = "Check for updated DAT files?"; res = DrawYesNoDialog(line1, line2); } else { char *line1 = "Redump.org DAT files not found"; char *line2 = "Download them now?"; res = DrawYesNoDialog(line1, line2); } // If yes, lets download an update if(res) { // Initialize the network if(!net_initialized) { char ip[16]; DrawMessageBox(D_INFO, "Checking for DAT updates\n \nInitializing Network..."); res = if_config(ip, NULL, NULL, true); if(res >= 0) { sprintf(txtbuffer, "Checking for DAT updates\nNetwork Initialized!\nIP: %s", ip); DrawMessageBox(D_INFO, txtbuffer); net_initialized = 1; print_gecko("Network Initialized!\r\n"); } else { DrawMessageBox(D_FAIL, "Checking for DAT updates\nNetwork failed to Initialize!"); sleep(5); net_initialized = 0; print_gecko("Network Failed to Initialize!\r\n"); return; } } // Download the GC DAT char datFilePath[64]; sprintf(datFilePath, "%sgc.dat",mountPath); u8 *xmlFile = (u8*)memalign(32, 1*1024*1024); if((res = http_request("www.gc-forever.com","/datfile/gc.dat", xmlFile, (1*1024*1024), 0, 0)) > 0) { remove(datFilePath); FILE *fp = fopen(datFilePath, "wb"); if(fp) { DrawMessageBox(D_INFO, "Checking for updates\nSaving GC DAT..."); fwrite(xmlFile, 1, res, fp); fclose(fp); verify_initialized = 0; print_gecko("Saved GameCube DAT! %i Bytes\r\n", res); } else { DrawMessageBox(D_FAIL, "Checking for updates\nFailed to save GC DAT..."); sleep(5); } } else { sprintf(txtbuffer, "Error: %i", res); print_gecko("Error Saving GC DAT %i\r\n", res); DrawMessageBox(D_FAIL, "Checking for updates\nCouldn't find file on gc-forever.com"); sleep(5); } // Download the Wii DAT sprintf(datFilePath, "%swii.dat",mountPath); if((res = http_request("www.gc-forever.com","/datfile/wii.dat", xmlFile, (1*1024*1024), 0, 0)) > 0) { remove(datFilePath); FILE *fp = fopen(datFilePath, "wb"); if(fp) { DrawMessageBox(D_INFO, "Checking for updates\nSaving Wii DAT..."); fwrite(xmlFile, 1, res, fp); fclose(fp); verify_initialized = 0; print_gecko("Saved Wii DAT! %i Bytes\r\n", res); } else { DrawMessageBox(D_FAIL, "Checking for updates\nFailed to save Wii DAT..."); sleep(5); } } else { sprintf(txtbuffer, "Error: %i", res); print_gecko("Error Saving Wii DAT %i\r\n", res); DrawMessageBox(D_FAIL, "Checking for updates\nCouldn't find file on gc-forever.com"); sleep(5); } free(xmlFile); dontAskAgain = 1; } else { dontAskAgain = 1; } }
void config_parse(char *configData) { // Parse each entry and put it into our array char *line, *linectx = NULL; int first = 1; line = strtok_r( configData, "\r\n", &linectx ); while( line != NULL ) { //print_gecko("Line [%s]\r\n", line); if(line[0] != '#') { // Is this line a new game entry? char *name, *namectx = NULL; char *value = NULL; name = strtok_r(line, "=", &namectx); if(name != NULL) value = strtok_r(NULL, "=", &namectx); if(value != NULL) { //print_gecko("Name [%s] Value [%s]\r\n", name, value); if(!strcmp("ID", name)) { if(!first) { configEntriesCount++; } strncpy(&configEntries[configEntriesCount].game_id[0], value, 4); first = 0; // Fill this entry with defaults incase some values are missing.. strcpy(&configEntries[configEntriesCount].comment[0],"No Comment"); strcpy(&configEntries[configEntriesCount].status[0],"Unknown"); configEntries[configEntriesCount].gameVMode = 0; configEntries[configEntriesCount].softProgressive = 0; configEntries[configEntriesCount].muteAudioStreaming = 1; configEntries[configEntriesCount].forceWidescreen = 0; configEntries[configEntriesCount].forceAnisotropy = 0; configEntries[configEntriesCount].forceEncoding = 0; } else if(!strcmp("Name", name)) { strncpy(&configEntries[configEntriesCount].game_name[0], value, 64); } else if(!strcmp("Comment", name)) { strncpy(&configEntries[configEntriesCount].comment[0], value, 128); } else if(!strcmp("Status", name)) { strncpy(&configEntries[configEntriesCount].status[0], value, 32); } else if(!strcmp("Force Video Mode", name)) { if(!strcmp(uiVModeStr[0], value)) configEntries[configEntriesCount].gameVMode = 0; else if(!strcmp(uiVModeStr[1], value)) configEntries[configEntriesCount].gameVMode = 1; else if(!strcmp(uiVModeStr[2], value)) configEntries[configEntriesCount].gameVMode = 2; else if(!strcmp(uiVModeStr[3], value)) configEntries[configEntriesCount].gameVMode = 3; else if(!strcmp(uiVModeStr[4], value)) configEntries[configEntriesCount].gameVMode = 4; else if(!strcmp(uiVModeStr[5], value)) configEntries[configEntriesCount].gameVMode = 5; else if(!strcmp(uiVModeStr[6], value)) configEntries[configEntriesCount].gameVMode = 6; } else if(!strcmp("Soft Progressive", name)) { if(!strcmp(softProgressiveStr[0], value)) configEntries[configEntriesCount].softProgressive = 0; else if(!strcmp(softProgressiveStr[1], value)) configEntries[configEntriesCount].softProgressive = 1; else if(!strcmp(softProgressiveStr[2], value)) configEntries[configEntriesCount].softProgressive = 2; } else if(!strcmp("Mute Audio Streaming", name)) { configEntries[configEntriesCount].muteAudioStreaming = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("Force Widescreen", name)) { if(!strcmp(forceWidescreenStr[0], value)) configEntries[configEntriesCount].forceWidescreen = 0; else if(!strcmp(forceWidescreenStr[1], value)) configEntries[configEntriesCount].forceWidescreen = 1; else if(!strcmp(forceWidescreenStr[2], value)) configEntries[configEntriesCount].forceWidescreen = 2; } else if(!strcmp("Force Anisotropy", name)) { configEntries[configEntriesCount].forceAnisotropy = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("Force Encoding", name)) { if(!strcmp(forceEncodingStr[0], value)) configEntries[configEntriesCount].forceEncoding = 0; else if(!strcmp(forceEncodingStr[1], value)) configEntries[configEntriesCount].forceEncoding = 1; else if(!strcmp(forceEncodingStr[2], value)) configEntries[configEntriesCount].forceEncoding = 2; } // Swiss settings else if(!strcmp("Default Device", name)) { configSwissSettings.defaultDevice = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("SD/IDE Speed", name)) { configSwissSettings.exiSpeed = !strcmp("32MHz", value) ? 1:0; } else if(!strcmp("Enable Debug", name)) { configSwissSettings.debugUSB = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("Force No DVD Drive Mode", name)) { configSwissSettings.hasDVDDrive = !strcmp("No", value) ? 1:0; } else if(!strcmp("Hide Unknown file types", name)) { configSwissSettings.hideUnknownFileTypes = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("Stop DVD Motor on startup", name)) { configSwissSettings.stopMotor = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("Enable WiiRD debug", name)) { configSwissSettings.wiirdDebug = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("Enable File Management", name)) { configSwissSettings.enableFileManagement = !strcmp("Yes", value) ? 1:0; } else if(!strcmp("Swiss Video Mode", name)) { if(!strcmp(uiVModeStr[0], value)) configSwissSettings.uiVMode = 0; else if(!strcmp(uiVModeStr[1], value)) configSwissSettings.uiVMode = 1; else if(!strcmp(uiVModeStr[2], value)) configSwissSettings.uiVMode = 2; else if(!strcmp(uiVModeStr[3], value)) configSwissSettings.uiVMode = 3; else if(!strcmp(uiVModeStr[4], value)) configSwissSettings.uiVMode = 4; else if(!strcmp(uiVModeStr[5], value)) configSwissSettings.uiVMode = 5; else if(!strcmp(uiVModeStr[6], value)) configSwissSettings.uiVMode = 6; } else if(!strcmp("SMBUserName", name)) { strncpy(configSwissSettings.smbUser, value, 20); } else if(!strcmp("SMBPassword", name)) { strncpy(configSwissSettings.smbPassword, value, 16); } else if(!strcmp("SMBShareName", name)) { strncpy(configSwissSettings.smbShare, value, 80); } else if(!strcmp("SMBHostIP", name)) { strncpy(configSwissSettings.smbServerIp, value, 80); } } } // And round we go again line = strtok_r( NULL, "\r\n", &linectx); } if(configEntriesCount > 0 || !first) configEntriesCount++; print_gecko("Found %i entries in the config file\r\n",configEntriesCount); }
// This function should always be called for the FULL length cause CARD is lame like that. s32 deviceHandler_CARD_writeFile(file_handle* file, void* data, u32 length) { if(gciInfo == NULL) { // Swiss ID for this CARD_SetGameAndCompany(); } else { // Game specific char company[4], gamecode[8]; memset(company, 0, 4); memset(gamecode, 0, 8); memcpy(gamecode, gciInfo->gamecode, 4); memcpy(company, gciInfo->company, 2); CARD_SetCompany(company); CARD_SetGamecode(gamecode); } card_file cardfile; unsigned int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)), ret = 0; unsigned int adj_length = (length % 8192 == 0 ? length : (length + (8192-length%8192)))+8192; char *filename = NULL; char fname[CARD_FILENAMELEN+1]; if(gciInfo != NULL) { memset(fname, 0, CARD_FILENAMELEN+1); memcpy(fname, gciInfo->filename, CARD_FILENAMELEN); filename = &fname[0]; adj_length = gciInfo->filesize8*8192; } else { filename = getRelativeName(file->name); } // Open the file based on the slot & file name ret = CARD_Open(slot,filename, &cardfile); print_gecko("Tried to open: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret == CARD_ERROR_NOFILE) { // If the file doesn't exist, create it. ret = CARD_Create(slot, filename,adj_length,&cardfile); print_gecko("Tried to create: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret != CARD_ERROR_READY) { return ret; } ret = CARD_Open(slot,filename, &cardfile); print_gecko("Tried to open after create: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); } if(ret != CARD_ERROR_READY) { // Something went wrong return -1; } // Write the icon, comment, etc. time_t gc_time = time (NULL); char *tmpBuffer = memalign(32,adj_length); memset(tmpBuffer,0,adj_length); if(gciInfo == NULL) { strcpy(tmpBuffer, filename); strcpy(tmpBuffer+0x20, ctime (&gc_time)); memcpy(tmpBuffer+0x40, gamecube_rgb, sizeof(gamecube_rgb)); // Copy icon memcpy(tmpBuffer+0x2000, data, length); // Copy data } else { data+=sizeof(GCI); memcpy(tmpBuffer, data, length); // Copy data } // The file exists by now, write at offset. int amount_written = 0; while(amount_written != adj_length) { ret = CARD_Write(&cardfile, tmpBuffer+amount_written, card_sectorsize[slot], file->offset); file->offset += card_sectorsize[slot]; amount_written += card_sectorsize[slot]; print_gecko("Tried to write: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret != CARD_ERROR_READY) break; } card_stat cardstat; if(gciInfo == NULL) { // Swiss memset(&cardstat, 0, sizeof(card_stat)); memcpy(&cardstat.filename, filename, CARD_FILENAMELEN-1); cardstat.time = gc_time; cardstat.comment_addr = 0; cardstat.icon_addr = 0x40; cardstat.icon_speed = CARD_SPEED_FAST; cardstat.banner_fmt = CARD_BANNER_NONE; cardstat.icon_fmt = CARD_ICON_RGB; } else { // Info is coming from a GCI cardstat.banner_fmt = gciInfo->banner_fmt; cardstat.time = gciInfo->time; cardstat.icon_addr = gciInfo->icon_addr; cardstat.icon_fmt = gciInfo->icon_fmt; cardstat.icon_speed = gciInfo->icon_speed; cardstat.comment_addr = gciInfo->comment_addr; } CARD_SetStatus (slot, cardfile.filenum, &cardstat); free(tmpBuffer); CARD_Close(&cardfile); return ret == CARD_ERROR_READY ? length : ret; }
/**************************************************************************** * Main ****************************************************************************/ int main () { // Setup defaults (if no config is found) memset(&swissSettings, 0 , sizeof(SwissSettings)); void *fb; fb = Initialise(); if(!fb) { return -1; } // Sane defaults refreshSRAM(); swissSettings.debugUSB = 1; swissSettings.gameVMode = 0; // Auto video mode swissSettings.exiSpeed = 1; // 32MHz swissSettings.uiVMode = 0; // Auto UI mode swissSettings.enableFileManagement = 0; config_copy_swiss_settings(&swissSettings); needsDeviceChange = 1; needsRefresh = 1; //debugging stuff if(swissSettings.debugUSB) { if(usb_isgeckoalive(1)) { usb_flush(1); } print_gecko("Arena Size: %iKb\r\n",(SYS_GetArena1Hi()-SYS_GetArena1Lo())/1024); print_gecko("DVD Drive Present? %s\r\n",swissSettings.hasDVDDrive?"Yes":"No"); print_gecko("GIT Commit: %s\r\n", GITREVISION); print_gecko("GIT Revision: %s\r\n", GITVERSION); } // Detect devices populateDeviceAvailability(); curDevice = -1; // Are we working with a Wiikey Fusion? if(__wkfSpiReadId() != 0 && __wkfSpiReadId() != 0xFFFFFFFF) { print_gecko("Detected Wiikey Fusion with SPI Flash ID: %08X\r\n",__wkfSpiReadId()); // Set real device back curDevice = WKF; // SlotB hack trySlotB(); } else { deviceHandler_setStatEnabled(0); // Try to init SD cards here and load config deviceHandler_initial = &initial_SD0; deviceHandler_init = deviceHandler_FAT_init; deviceHandler_deinit = deviceHandler_FAT_deinit; if(deviceHandler_init(deviceHandler_initial)) { print_gecko("Detected SDGecko in Slot A\r\n"); load_auto_dol(); curDevice = SD_CARD; } else { deviceHandler_deinit(deviceHandler_initial); deviceHandler_initial = &initial_SD1; if(deviceHandler_init(deviceHandler_initial)) { print_gecko("Detected SDGecko in Slot B\r\n"); load_auto_dol(); curDevice = SD_CARD; } } deviceHandler_setStatEnabled(1); } // If no device has been selected yet to browse .. if(curDevice < 0) { print_gecko("No default boot device detected, trying DVD!\r\n"); // Do we have a DVD drive with a ready medium we can perhaps browse then? u8 driveReallyExists[8]; drive_version(&driveReallyExists[0]); if(*(u32*)&driveReallyExists[0]) { dvd_read_id(); if(!dvd_get_error()) { print_gecko("DVD Medium is up, using it as default device\r\n"); curDevice = DVD_DISC; // If we have a GameCube (single image) bootable disc, show the banner screen here dvdDiscTypeInt = gettype_disc(); if(dvdDiscTypeInt == GAMECUBE_DISC) { select_device(1); // Setup curFile and load it memset(&curFile, 0, sizeof(file_handle)); strcpy(&curFile.name[0], "game.gcm"); curFile.size = DISC_SIZE; curFile.fileAttrib = IS_FILE; populate_meta(&curFile); load_file(); curDevice = -1; deviceHandler_initial = NULL; } } } } if(curDevice) { needsDeviceChange = 0; select_device(1); // to setup deviceHandler_ ptrs load_config(forceSlot); } // Start up the BBA if it exists init_network_thread(); init_httpd_thread(); // DVD Motor off if(swissSettings.stopMotor && swissSettings.hasDVDDrive) { dvd_motor_off(); } // Swiss video mode force GXRModeObj *forcedMode = getModeFromSwissSetting(swissSettings.uiVMode); if((forcedMode != NULL) && (forcedMode != vmode)) { initialise_video(forcedMode); vmode = forcedMode; } while(1) { main_loop(); } return 0; }
void main_loop() { while(PAD_ButtonsHeld(0) & PAD_BUTTON_A) { VIDEO_WaitVSync (); } // We don't care if a subsequent device is "default" if(needsDeviceChange) { free_files(); if(deviceHandler_deinit) { deviceHandler_deinit(deviceHandler_initial); } if (forceSlot) { deviceHandler_FAT_deinit(&initial_SD1); } curDevice = -1; needsDeviceChange = 0; deviceHandler_initial = NULL; needsRefresh = 1; curMenuLocation = ON_FILLIST; select_device(0); if (curDevice == WKF) { trySlotB(); } curMenuLocation = ON_OPTIONS; } if(deviceHandler_initial) { // If the user selected a device, make sure it's ready before we browse the filesystem deviceHandler_deinit( deviceHandler_initial ); sdgecko_setSpeed(EXI_SPEED32MHZ); if(!deviceHandler_init( deviceHandler_initial )) { if(((deviceHandler_initial->name[0] == 's')&&(deviceHandler_initial->name[1] == 'd'))||(deviceHandler_initial->name[0] == 'i')) { print_gecko("SD/IDE-EXI Device Failed to initialize @ 32MHz!\r\nTrying again once @ 16MHz...\r\n"); sdgecko_setSpeed(EXI_SPEED16MHZ); if(!deviceHandler_init(deviceHandler_initial)) { // Try the alternate slot for SDGecko or IDE-EXI if(deviceHandler_initial->name[0] == 's') deviceHandler_initial = (deviceHandler_initial == &initial_SD0) ? &initial_SD1:&initial_SD0; else deviceHandler_initial = (deviceHandler_initial == &initial_IDE0) ? &initial_IDE1:&initial_IDE0; memcpy(&curFile, deviceHandler_initial, sizeof(file_handle)); } print_gecko("Trying alternate slot @ 32MHz...\r\n"); sdgecko_setSpeed(EXI_SPEED32MHZ); if(!deviceHandler_init( deviceHandler_initial )) { print_gecko("Alternate slot failed once @ 16MHz... \r\n"); sdgecko_setSpeed(EXI_SPEED16MHZ); if(!deviceHandler_init( deviceHandler_initial )) { print_gecko("Both slots failed twice\r\n"); needsDeviceChange = 1; return; } } } } if(curDevice==SD_CARD || curDevice==WKF || curDevice==IDEEXI) { load_config(forceSlot); } } else { curMenuLocation=ON_OPTIONS; } // If a previously undetected device has been successfully init'd, mark it as available from now on if(!deviceHandler_getDeviceAvailable(curDevice)) { deviceHandler_setDeviceAvailable(curDevice, 1); } while(1) { if(deviceHandler_initial && needsRefresh) { curMenuLocation=ON_OPTIONS; free_files(); curSelection=0; files=0; curMenuSelection=0; // Read the directory/device TOC if(allFiles){ free(allFiles); allFiles = NULL; } print_gecko("Reading directory: %s\r\n",curFile.name); files = deviceHandler_readDir(&curFile, &allFiles, -1); memcpy(&curDir, &curFile, sizeof(file_handle)); sortFiles(allFiles, files); print_gecko("Found %i entries\r\n",files); if(files<1) { deviceHandler_deinit(deviceHandler_initial); needsDeviceChange=1; break;} needsRefresh = 0; curMenuLocation=ON_FILLIST; } while(PAD_ButtonsHeld(0) & PAD_BUTTON_A) { VIDEO_WaitVSync (); } drawFiles(&allFiles, files); u16 btns = PAD_ButtonsHeld(0); if(curMenuLocation==ON_OPTIONS) { if(btns & PAD_BUTTON_LEFT){ curMenuSelection = (--curMenuSelection < 0) ? (MENU_MAX-1) : curMenuSelection;} else if(btns & PAD_BUTTON_RIGHT){curMenuSelection = (curMenuSelection + 1) % MENU_MAX; } } if(deviceHandler_initial && ((btns & PAD_BUTTON_B)||(curMenuLocation==ON_FILLIST))) { while(PAD_ButtonsHeld(0) & PAD_BUTTON_B){ VIDEO_WaitVSync (); } curMenuLocation=ON_FILLIST; renderFileBrowser(&allFiles, files); } else if(btns & PAD_BUTTON_A) { //handle menu event switch(curMenuSelection) { case 0: // Device change needsDeviceChange = 1; //Change from SD->DVD or vice versa break; case 1: // Settings show_settings(NULL, NULL); break; case 2: // Credits show_info(); break; case 3: if(deviceHandler_initial) { memcpy(&curFile, deviceHandler_initial, sizeof(file_handle)); if(curDevice == WKF) { wkfReinit(); deviceHandler_deinit(deviceHandler_initial); } } needsRefresh=1; break; case 4: __libogc_exit(0); break; } } while (!(!(PAD_ButtonsHeld(0) & PAD_BUTTON_B) && !(PAD_ButtonsHeld(0) & PAD_BUTTON_A) && !(PAD_ButtonsHeld(0) & PAD_BUTTON_RIGHT) && !(PAD_ButtonsHeld(0) & PAD_BUTTON_LEFT))) { VIDEO_WaitVSync(); } if(needsDeviceChange) { break; } } }
int patch_gcm(file_handle *file, ExecutableFile *filesToPatch, int numToPatch, int multiDol) { int i, num_patched = 0; // If the current device isn't SD Gecko, init SD Gecko Slot A or B to write patches. if(deviceHandler_initial != &initial_SD0 && deviceHandler_initial != &initial_SD1) { deviceHandler_setStatEnabled(0); if(deviceHandler_FAT_init(&initial_SD0)) { savePatchDevice = 0; } else if(deviceHandler_FAT_init(&initial_SD1)) { savePatchDevice = 1; } deviceHandler_setStatEnabled(1); } // Already using SD Gecko if(deviceHandler_initial == &initial_SD0) savePatchDevice = 0; else if(deviceHandler_initial == &initial_SD1) savePatchDevice = 1; if(savePatchDevice == -1) { DrawFrameStart(); DrawMessageBox(D_FAIL, "No writable device present\nA SD Gecko must be inserted in\n order to utilise patches for this game."); DrawFrameFinish(); sleep(5); return 0; } char patchFileName[256]; char patchDirName[256]; char patchBaseDirName[256]; char gameID[8]; memset(&gameID, 0, 8); memset(&patchDirName, 0, 256); memset(&patchBaseDirName, 0, 256); strncpy((char*)&gameID, (char*)&GCMDisk, 4); sprintf(&patchDirName[0],"%s:/swiss_patches/%s",(savePatchDevice ? "sdb":"sda"), &gameID[0]); sprintf(&patchBaseDirName[0],"%s:/swiss_patches",(savePatchDevice ? "sdb":"sda")); print_gecko("Patch dir will be: %s if required\r\n", patchDirName); *(u32*)VAR_EXECD_OFFSET = 0xFFFFFFFF; // Go through all the possible files we think need patching.. for(i = 0; i < numToPatch; i++) { u32 patched = 0, crc32 = 0; sprintf(txtbuffer, "Patching File %i/%i",i+1,numToPatch); DrawFrameStart(); DrawProgressBar((int)(((float)(i+1)/(float)numToPatch)*100), txtbuffer); DrawFrameFinish(); // Round up to 32 bytes if(filesToPatch[i].size % 0x20) { filesToPatch[i].size += (0x20-(filesToPatch[i].size%0x20)); } if(filesToPatch[i].size > 8*1024*1024) { print_gecko("Skipping %s %iKB too large\r\n", filesToPatch[i].name, filesToPatch[i].size/1024); continue; } print_gecko("Checking %s %iKb\r\n", filesToPatch[i].name, filesToPatch[i].size/1024); if(strstr(filesToPatch[i].name, "execD.")) { *(u32*)VAR_EXECD_OFFSET = filesToPatch[i].offset; } if(strstr(filesToPatch[i].name, "iwanagaD.dol") || strstr(filesToPatch[i].name, "switcherD.dol")) { continue; // skip unused PSO files } int sizeToRead = filesToPatch[i].size; u8 *buffer = (u8*)memalign(32, sizeToRead); deviceHandler_seekFile(file,filesToPatch[i].offset, DEVICE_HANDLER_SEEK_SET); if(deviceHandler_readFile(file,buffer,sizeToRead)!= sizeToRead) { DrawFrameStart(); DrawMessageBox(D_FAIL, "Failed to read!"); DrawFrameFinish(); sleep(5); return 0; } if(curDevice != DVD_DISC) { u32 ret = Patch_DVDLowLevelRead(buffer, sizeToRead, filesToPatch[i].type); if(READ_PATCHED_ALL != ret) { DrawFrameStart(); DrawMessageBox(D_FAIL, "Failed to find necessary functions for patching!"); DrawFrameFinish(); sleep(5); } else patched += 1; } if(swissSettings.debugUSB && usb_isgeckoalive(1) && !swissSettings.wiirdDebug) { patched += Patch_Fwrite(buffer, sizeToRead); } if(swissSettings.wiirdDebug || getEnabledCheatsSize() > 0) { Patch_CheatsHook(buffer, sizeToRead, filesToPatch[i].type); } if(curDevice == DVD_DISC && is_gamecube()) { patched += Patch_DVDLowLevelReadForDVD(buffer, sizeToRead, filesToPatch[i].type); patched += Patch_DVDReset(buffer, sizeToRead); } patched += Patch_VidMode(buffer, sizeToRead, filesToPatch[i].type); patched += Patch_FontEnc(buffer, sizeToRead); if(swissSettings.forceWidescreen) Patch_WideAspect(buffer, sizeToRead, filesToPatch[i].type); if(swissSettings.forceAnisotropy) Patch_TexFilt(buffer, sizeToRead, filesToPatch[i].type); if(patched) { // File handle for a patch we might need to write FILE *patchFile = 0; memset(patchFileName, 0, 256); // Make a base patches dir if we don't have one already if(mkdir(&patchBaseDirName[0], 0777) != 0) { if(errno != EEXIST) { return -2; } } if(mkdir(&patchDirName[0], 0777) != 0) { if(errno != EEXIST) { return -2; } } sprintf(patchFileName, "%s/%i",patchDirName, num_patched); // Work out the crc32 crc32 = Crc32_ComputeBuf( 0, buffer, (u32) sizeToRead); // See if this file already exists, if it does, match crc patchFile = fopen( patchFileName, "rb" ); if(patchFile) { //print_gecko("Old Patch exists\r\n"); u32 oldCrc32 = 0; fseek(patchFile, 0L, SEEK_END); u32 file_size = ftell(patchFile); fseek(patchFile, file_size-4, SEEK_SET); fread(&oldCrc32, 1, 4, patchFile); if(oldCrc32 == crc32) { num_patched++; fclose(patchFile); free(buffer); print_gecko("CRC matched, no need to patch again\r\n"); continue; } else { remove(patchFileName); fclose(patchFile); print_gecko("CRC mismatch, writing patch again\r\n"); } } // Otherwise, write a file out for this game with the patched buffer inside. print_gecko("Writing patch file: %s %i bytes (disc offset %08X)\r\n", patchFileName, sizeToRead, filesToPatch[i].offset); patchFile = fopen(patchFileName, "wb"); fwrite(buffer, 1, sizeToRead, patchFile); u32 magic = SWISS_MAGIC; fwrite(&filesToPatch[i].offset, 1, 4, patchFile); fwrite(&filesToPatch[i].size, 1, 4, patchFile); fwrite(&magic, 1, 4, patchFile); fwrite(&crc32, 1, 4, patchFile); fclose(patchFile); num_patched++; } free(buffer); } return num_patched; }
// This is only called where length = file.size int deviceHandler_CARD_readFile(file_handle* file, void* buffer, unsigned int length){ unsigned int slot = file->fileBase>>24, ret = 0, file_no = file->fileBase&0xFFFFFF; void *dst = buffer; // Get the sector size u32 SectorSize = 0; CARD_GetSectorSize (slot, &SectorSize); // Create the .gci header card_stat CardStat; GCI gci; CARD_GetStatus(slot,file_no,&CardStat); memset(&gci, 0xFF, sizeof(GCI)); /*** Populate the GCI ***/ memcpy(&gci.gamecode, &CardStat.gamecode, 4); memcpy(&gci.company, &CardStat.company, 2); gci.banner_fmt = CardStat.banner_fmt; memcpy(&gci.filename, &CardStat.filename, 0x20); gci.time = CardStat.time; gci.icon_addr = CardStat.icon_addr; gci.icon_fmt = CardStat.icon_fmt; gci.icon_speed = CardStat.icon_speed; gci.unknown1 = gci.unknown2 = 0; gci.index = 32; gci.filesize8 = (CardStat.len / 8192); gci.comment_addr = CardStat.comment_addr; memcpy(dst, &gci, sizeof(GCI)); dst+= sizeof(GCI); // Re-init the card with the original file gamecode & company char game_code[16]; memcpy(&game_code[0],&gci.gamecode, 4); game_code[4] = 0; CARD_SetGamecode((const char *)&game_code[0]); memcpy(&game_code[0],&gci.company, 2); game_code[2] = 0; CARD_SetCompany((const char *)&game_code[0]); // Use the original file name char file_name[CARD_FILENAMELEN]; memset(&file_name[0],0,CARD_FILENAMELEN); memcpy(&file_name[0], file->name,strlen(file->name)-4); print_gecko("Try to open: [%s]\r\n",&file_name[0]); // Read the actual file data now char *read_buffer = NULL; card_file *memcard_file = NULL; memcard_file = (card_file*)memalign(32,sizeof(card_file)); if(!memcard_file) { return -2; } memset(memcard_file, 0, sizeof(card_file)); // Open the Entry if((ret = CARD_Open(slot, (const char*)&file_name[0], memcard_file)) != CARD_ERROR_NOFILE){ /* Allocate the read buffer */ u32 readSize = ((memcard_file->len % SectorSize) != 0) ? ((memcard_file->len/SectorSize)+1) * SectorSize : memcard_file->len; read_buffer = memalign(32,SectorSize); if(!read_buffer) { free(memcard_file); return -2; } print_gecko("Reading: [%i] bytes\r\n",readSize); /* Read the file */ int i = 0; for(i=0;i<(readSize/SectorSize);i++) { ret = CARD_Read(memcard_file,read_buffer, SectorSize, i*SectorSize); if(!ret) { memcpy(dst,read_buffer,(i==(readSize/SectorSize)-1) ? (memcard_file->len % SectorSize):SectorSize); } dst+=SectorSize; print_gecko("Read: [%i] bytes ret [%i]\r\n",SectorSize,ret); } } else { print_gecko("ret: [%i]\r\n",ret); } CARD_Close(memcard_file); free(read_buffer); free(memcard_file); return !ret ? length : ret; }
// Returns the number of filesToPatch and fills out the filesToPatch array passed in (pre-allocated) int read_fst(file_handle *file, file_handle** dir, u32 *usedSpace) { print_gecko("Read dir for directory: %s\r\n",file->name); DiskHeader header; char *FST; char filename[256]; int numFiles = 1, idx = 0; int isRoot = (file->name[0] == '\\'); // Grab disc header memset(&header,0,sizeof(DiskHeader)); DVD_Read(&header,0,sizeof(DiskHeader)); // Alloc and read FST FST=(char*)memalign(32,header.FSTSize); if(!FST) { return -1; } // Read the FST DVD_Read(FST,header.FSTOffset,header.FSTSize); // Get the space taken up by this disc if(usedSpace) *usedSpace = calc_fst_entries_size(FST); // Add the disc itself as a "file" *dir = malloc( numFiles * sizeof(file_handle) ); DVD_Read((*dir)[idx].name, 32, 128); strcat((*dir)[idx].name, ".gcm"); (*dir)[idx].fileBase = 0; (*dir)[idx].offset = 0; (*dir)[idx].size = DISC_SIZE; (*dir)[idx].fileAttrib = IS_FILE; (*dir)[idx].meta = 0; idx++; u32 entries=*(unsigned int*)&FST[8]; u32 string_table_offset=FST_ENTRY_SIZE*entries; int i; // Go through the FST and find our DIR (or ROOT) int parent_dir_offset = (u32)file->fileBase; int dir_end_offset = isRoot ? *(u32*)&FST[8] : 0; isRoot = parent_dir_offset==0; u32 filename_offset=((*(u32*)&FST[parent_dir_offset*0x0C]) & 0x00FFFFFF); memset(&filename[0],0,256); memcpy(&filename[0],&FST[string_table_offset+filename_offset],255); dir_end_offset = *(u32*)&FST[(parent_dir_offset*0x0C) + 8]; if(!isRoot) { // Add a special ".." dir which will take us back up a dir if(idx == numFiles){ ++numFiles; *dir = realloc( *dir, numFiles * sizeof(file_handle) ); } strcpy((*dir)[idx].name, ".."); (*dir)[idx].fileBase = *(u32*)&FST[(parent_dir_offset*0x0C)+4]; (*dir)[idx].offset = 0; (*dir)[idx].size = 0; (*dir)[idx].fileAttrib = IS_DIR; (*dir)[idx].meta = 0; idx++; } //print_gecko("Found DIR [%03i]:%s\r\n",parent_dir_offset,isRoot ? "ROOT":filename); // Traverse the FST now adding all the files which come under our DIR for (i=parent_dir_offset;i<dir_end_offset;i++) { if(i==0) continue; u32 offset=i*0x0c; u32 file_offset,size = 0; u32 filename_offset=((*(unsigned int*)&FST[offset]) & 0x00FFFFFF); memset(&filename[0],0,256); memcpy(&filename[0],&FST[string_table_offset+filename_offset],255); memcpy(&file_offset,&FST[offset+4],4); memcpy(&size,&FST[offset+8],4); // Is this a sub dir of our dir? if(FST[offset]) { if(file_offset == parent_dir_offset) { //print_gecko("Adding: [%03i]%s:%s offset %08X length %08X\r\n",i,!FST[offset] ? "File" : "Dir",filename,file_offset,size); if(idx == numFiles){ ++numFiles; *dir = realloc( *dir, numFiles * sizeof(file_handle) ); } memcpy((*dir)[idx].name, &filename[0], 255); (*dir)[idx].fileBase = i; (*dir)[idx].offset = 0; (*dir)[idx].size = size; (*dir)[idx].fileAttrib = IS_DIR; (*dir)[idx].meta = 0; idx++; // Skip the entries that sit in this dir i = size-1; } } else { // File, add it. //print_gecko("Adding: [%03i]%s:%s offset %08X length %08X\r\n",i,!FST[offset] ? "File" : "Dir",filename,file_offset,size); if(idx == numFiles){ ++numFiles; *dir = realloc( *dir, numFiles * sizeof(file_handle) ); } memcpy((*dir)[idx].name, &filename[0], 255); (*dir)[idx].fileBase = file_offset; (*dir)[idx].offset = 0; (*dir)[idx].size = size; (*dir)[idx].fileAttrib = IS_FILE; (*dir)[idx].meta = 0; idx++; } } free(FST); return numFiles; }
s32 deviceHandler_CARD_readFile(file_handle* file, void* buffer, u32 length){ card_file cardfile; void *dst = buffer; card_dir* cd = (card_dir*)&file->other; char *filename = getRelativeName(file->name); unsigned int slot = (!strncmp((const char*)initial_CARDB.name, file->name, 7)), ret = 0; if(cd->company[0] == '\0' && cd->gamecode[0] == '\0') { // Find the file we don't know about and populate this file_handle if we find it. if(!findFile(file)) { return CARD_ERROR_NOFILE; } CARD_SetCompany((const char*)cd->company); CARD_SetGamecode((const char*)cd->gamecode); } else { CARD_SetCompany((const char*)cd->company); CARD_SetGamecode((const char*)cd->gamecode); } int swissFile = !strncmp((const char*)cd->gamecode, "SWIS", 4) && !strncmp((const char*)cd->company, "S0", 2); // Open the file based on the slot & file name ret = CARD_Open(slot,filename, &cardfile); print_gecko("Tried to open: [%s] in slot %s got res: %i\r\n",filename, slot ? "B":"A", ret); if(ret != CARD_ERROR_READY) return ret; u8 *read_buffer = (u8*)memalign(32,card_sectorsize[slot]); if(!read_buffer) { return -1; } /* Read from the file */ u32 amountRead = 0; // If this file was put here by swiss, then skip the first 8192 bytes if(swissFile && !isCopyGCIMode) { print_gecko("Swiss copied file detected, skipping icon\r\n"); file->offset += 8192; } if(isCopyGCIMode) { // Write out a .GCI card_stat cardstat; GCI gci; CARD_GetStatus(slot, cardfile.filenum, &cardstat); memset(&gci, 0, sizeof(GCI)); memcpy(&gci.gamecode,cd->gamecode,4); memcpy(&gci.company,cd->company,2); memcpy(&gci.filename,file->name,CARD_FILENAMELEN); gci.reserved01 = 0xFF; gci.banner_fmt = cardstat.banner_fmt; gci.time = cardstat.time; gci.icon_addr = cardstat.icon_addr; gci.icon_fmt = cardstat.icon_fmt; gci.icon_speed = cardstat.icon_speed; gci.unknown1 = cd->permissions; gci.filesize8 = cardstat.len / 8192; gci.reserved02 = 0xFFFF; gci.comment_addr = cardstat.comment_addr; memcpy(dst, &gci, sizeof(GCI)); dst+=sizeof(GCI); length-=sizeof(GCI); amountRead += sizeof(GCI); } while(length > 0 && file->offset < file->size) { int readsize = length > card_sectorsize[slot] ? card_sectorsize[slot] : length; print_gecko("Need to read: [%i] more bytes\r\n", length); if(file->offset&0x1ff) { ret = CARD_ReadUnaligned(&cardfile, read_buffer, card_sectorsize[slot], file->offset, slot); } else { ret = CARD_Read(&cardfile, read_buffer, card_sectorsize[slot], file->offset); // Sometimes reads fail the first time stupidly, retry at least once. print_gecko("Read: [%i] bytes ret [%i] from offset [%i]\r\n",card_sectorsize[slot],ret, file->offset); if(ret == CARD_ERROR_BUSY) { print_gecko("Read retry\r\n"); usleep(2000); ret = CARD_Read(&cardfile, read_buffer, card_sectorsize[slot], file->offset); } } if(ret == CARD_ERROR_READY) memcpy(dst,read_buffer,readsize); else return ret; dst+=readsize; file->offset += readsize; length -= readsize; amountRead += readsize; } // For swiss adjusted files, don't trail off the end. if(swissFile && length != 0) { amountRead+= length; } DCFlushRange(dst, amountRead); CARD_Close(&cardfile); free(read_buffer); return amountRead; }
/**************************************************************************** * Main ****************************************************************************/ int main () { // Setup defaults (if no config is found) memset(&swissSettings, 0 , sizeof(SwissSettings)); // Register all devices supported (order matters for boot devices) int i = 0; for(i = 0; i < MAX_DEVICES; i++) allDevices[i] = NULL; i = 0; allDevices[i++] = &__device_wkf; allDevices[i++] = &__device_wode; allDevices[i++] = &__device_sd_a; allDevices[i++] = &__device_sd_b; allDevices[i++] = &__device_card_a; allDevices[i++] = &__device_card_b; allDevices[i++] = &__device_dvd; allDevices[i++] = &__device_ide_a; allDevices[i++] = &__device_ide_b; allDevices[i++] = &__device_qoob; allDevices[i++] = &__device_smb; allDevices[i++] = &__device_sys; allDevices[i++] = &__device_usbgecko; allDevices[i++] = &__device_ftp; allDevices[i++] = &__device_fsp; allDevices[i++] = NULL; // Set current devices devices[DEVICE_CUR] = NULL; devices[DEVICE_DEST] = NULL; devices[DEVICE_TEMP] = NULL; devices[DEVICE_CONFIG] = NULL; devices[DEVICE_PATCHES] = NULL; Initialise(); // Sane defaults refreshSRAM(&swissSettings); swissSettings.debugUSB = 0; swissSettings.gameVMode = 0; // Auto video mode swissSettings.exiSpeed = 1; // 32MHz swissSettings.uiVMode = 0; // Auto UI mode swissSettings.aveCompat = 1; swissSettings.enableFileManagement = 0; needsDeviceChange = 1; needsRefresh = 1; //debugging stuff if(swissSettings.debugUSB) { if(usb_isgeckoalive(1)) { usb_flush(1); } print_gecko("Arena Size: %iKb\r\n",(SYS_GetArena1Hi()-SYS_GetArena1Lo())/1024); print_gecko("DVD Drive Present? %s\r\n",swissSettings.hasDVDDrive?"Yes":"No"); print_gecko("GIT Commit: %s\r\n", GITREVISION); print_gecko("GIT Revision: %s\r\n", GITVERSION); } // Go through all devices with FEAT_BOOT_DEVICE feature and set it as current if one is available for(i = 0; i < MAX_DEVICES; i++) { if(allDevices[i] != NULL && (allDevices[i]->features & FEAT_BOOT_DEVICE)) { print_gecko("Testing device %s\r\n", allDevices[i]->deviceName); if(allDevices[i]->test()) { deviceHandler_setDeviceAvailable(allDevices[i], true); devices[DEVICE_CUR] = allDevices[i]; break; } } } if(devices[DEVICE_CUR] != NULL) { print_gecko("Detected %s\r\n", devices[DEVICE_CUR]->deviceName); if(devices[DEVICE_CUR]->init(devices[DEVICE_CUR]->initial)) { if(devices[DEVICE_CUR]->features & FEAT_AUTOLOAD_DOL) { load_auto_dol(); } memcpy(&curFile, devices[DEVICE_CUR]->initial, sizeof(file_handle)); needsDeviceChange = 0; } } // Scan here since some devices would already be initialised (faster) populateDeviceAvailability(); // If there's no default config device, set it to the first writable device available if(swissSettings.configDeviceId == DEVICE_ID_UNK) { for(int i = 0; i < MAX_DEVICES; i++) { if(allDevices[i] != NULL && (allDevices[i]->features & FEAT_WRITE) && deviceHandler_getDeviceAvailable(allDevices[i])) { swissSettings.configDeviceId = allDevices[i]->deviceUniqueId; print_gecko("No default config device found, using [%s]\r\n", allDevices[i]->deviceName); syssramex* sramex = __SYS_LockSramEx(); sramex->__padding0 = swissSettings.configDeviceId; __SYS_UnlockSramEx(1); while(!__SYS_SyncSram()); break; } } } // Try to open up the config .ini in case it hasn't been opened already if(config_init()) { // TODO notification area this print_gecko("Loaded %i entries from the config file\r\n",config_get_count()); } if(swissSettings.initNetworkAtStart) { // Start up the BBA if it exists uiDrawObj_t *msgBox = DrawPublish(DrawProgressBar(true, 0, "Initialising Network")); init_network(); init_httpd_thread(); DrawDispose(msgBox); } // DVD Motor off setting; Always stop the drive if we only started it to read the ID out if((swissSettings.stopMotor && swissSettings.hasDVDDrive) || (swissSettings.hasDVDDrive == 2)) { dvd_motor_off(); } // Swiss video mode force GXRModeObj *forcedMode = getVideoModeFromSwissSetting(swissSettings.uiVMode); if((forcedMode != NULL) && (forcedMode != getVideoMode())) { setVideoMode(forcedMode); } while(1) { menu_loop(); } return 0; }
void verify_init(char *mountPath) { if (verify_initialized) { return; } if(ngcDAT) { if(ngcXML) { mxmlDelete(ngcXML); free(ngcXML); } free(ngcDAT); } if(wiiDAT) { free(wiiDAT); if(wiiXML) { mxmlDelete(wiiXML); free(wiiXML); } } mxmlSetErrorCallback(print_gecko); FILE *fp = NULL; // Check for the Gamecube Redump.org DAT and read it sprintf(txtbuffer, "%sgc.dat", mountPath); fp = fopen(txtbuffer, "rb"); if (fp) { fseek(fp, 0, SEEK_END); int size = ftell(fp); fseek(fp, 0, SEEK_SET); if (size > 0) { ngcDAT = (char*) memalign(32, size); if (ngcDAT) { fread(ngcDAT, 1, size, fp); } } fclose(fp); fp = NULL; } // Check for the Wii Redump.org DAT and read it sprintf(txtbuffer, "%swii.dat", mountPath); fp = fopen(txtbuffer, "rb"); if (fp) { fseek(fp, 0L, SEEK_END); int size = ftell(fp); fseek(fp, 0, SEEK_SET); if (size > 0) { wiiDAT = (char*) memalign(32, size); if (wiiDAT) { fread(wiiDAT, 1, size, fp); } } fclose(fp); fp = NULL; } if (ngcDAT) { ngcXML = mxmlLoadString(NULL, ngcDAT, MXML_TEXT_CALLBACK); } if (wiiDAT) { wiiXML = mxmlLoadString(NULL, wiiDAT, MXML_TEXT_CALLBACK); } print_gecko("DAT Files [NGC: %s] [Wii: %s]\r\n", ngcDAT ? "YES":"NO", wiiDAT ? "YES":"NO"); verify_initialized = ((ngcDAT&&ngcXML) && (wiiDAT&&wiiXML)); }
int findCheats(bool silent) { char trimmedGameId[8], testBuffer[8]; memset(trimmedGameId, 0, 8); memcpy(trimmedGameId, (char*)&GCMDisk, 6); file_handle *cheatsFile = memalign(32,sizeof(file_handle)); memset(cheatsFile, 0, sizeof(file_handle)); sprintf(cheatsFile->name, "%s/cheats/%s.txt", devices[DEVICE_CUR]->initial->name, trimmedGameId); print_gecko("Looking for cheats file @ [%s]\r\n", cheatsFile->name); devices[DEVICE_TEMP] = devices[DEVICE_CUR]; // Check SD in both slots if we're not already running from SD, or if we fail from current device if(devices[DEVICE_TEMP]->readFile(cheatsFile, &testBuffer, 8) != 8) { // Try SD slots now if(devices[DEVICE_CUR] != &__device_sd_a) { devices[DEVICE_TEMP] = &__device_sd_a; } else { devices[DEVICE_TEMP] = &__device_sd_b; } file_handle *slotFile = devices[DEVICE_TEMP]->initial; memset(cheatsFile, 0, sizeof(file_handle)); sprintf(cheatsFile->name, "%s/cheats/%s.txt", slotFile->name, trimmedGameId); print_gecko("Looking for cheats file @ [%s]\r\n", cheatsFile->name); deviceHandler_setStatEnabled(0); devices[DEVICE_TEMP]->init(cheatsFile); if(devices[DEVICE_TEMP]->readFile(cheatsFile, &testBuffer, 8) != 8) { if(devices[DEVICE_TEMP] == &__device_sd_b) { devices[DEVICE_TEMP] = NULL; // We already tried this & failed. } else { devices[DEVICE_TEMP] = &__device_sd_b; slotFile = devices[DEVICE_TEMP]->initial; memset(cheatsFile, 0, sizeof(file_handle)); sprintf(cheatsFile->name, "%s/cheats/%s.txt", slotFile->name, trimmedGameId); print_gecko("Looking for cheats file @[%s]\r\n", cheatsFile->name); devices[DEVICE_TEMP]->init(cheatsFile); if(devices[DEVICE_TEMP]->readFile(cheatsFile, &testBuffer, 8) != 8) { devices[DEVICE_TEMP] = NULL; } } } deviceHandler_setStatEnabled(1); } // Still fail? if(devices[DEVICE_TEMP] == NULL) { if(!silent) { while(PAD_ButtonsHeld(0) & PAD_BUTTON_Y); uiDrawObj_t *msgBox = DrawMessageBox(D_INFO,"No cheats file found.\nPress A to continue."); DrawPublish(msgBox); while(!(PAD_ButtonsHeld(0) & PAD_BUTTON_A)); while(PAD_ButtonsHeld(0) & PAD_BUTTON_A); DrawDispose(msgBox); } free(cheatsFile); return 0; } print_gecko("Cheats file found with size %i\r\n", cheatsFile->size); char *cheats_buffer = memalign(32, cheatsFile->size); if(cheats_buffer) { devices[DEVICE_TEMP]->seekFile(cheatsFile, 0, DEVICE_HANDLER_SEEK_SET); devices[DEVICE_TEMP]->readFile(cheatsFile, cheats_buffer, cheatsFile->size); parseCheats(cheats_buffer); free(cheats_buffer); free(cheatsFile); } return _cheats.num_cheats; }