int read_safe(void* dst, uint64_t offset, int len) { int ol = len; int ret = 0; unsigned char* sector_buffer = (unsigned char*)memalign(32,32768); while (len) { ret |= DVD_LowRead64(sector_buffer, 32768, offset); uint32_t off = offset & 32767; int rl = 32768 - off; if (rl > len) rl = len; else rl = 32768; memcpy(dst, sector_buffer, rl); offset += rl; len -= rl; dst += rl; } free(sector_buffer); if(ret) return -1; if(dvd_get_error()) init_dvd(); return ol; }
int init_dvd() { // Gamecube Mode #ifdef HW_DOL if(mfpvr()!=GC_CPU_VERSION) //GC mode on Wii, modchip required { DVD_Reset(DVD_RESETHARD); dvd_read_id(); if(!dvd_get_error()) { return 0; //we're ok } } else //GC, no modchip even required :) { DVD_Reset(DVD_RESETHARD); DVD_Mount (); if(!dvd_get_error()) { return 0; //we're ok } } if(dvd_get_error()>>24) { return NO_DISC; } return -1; #endif // Wii (Wii mode) #ifdef HW_RVL if(!have_hw_access()) { return NO_HW_ACCESS; } if((dvd_get_error()>>24) == 1) { return NO_DISC; } if((!dvd_hard_init) || (dvd_get_error())) { DI_Mount(); while(DI_GetStatus() & DVD_INIT) usleep(20000); dvd_hard_init=1; } if((dvd_get_error()&0xFFFFFF)==0x053000) { read_cmd = DVDR; } else { read_cmd = NORMAL; } return 0; #endif }
int fileBrowser_DVD_readDir(fileBrowser_file* ffile, fileBrowser_file** dir){ int ret = 0; num_entries = 0; if(dvd_get_error() || !dvd_init) { //if some error ret = init_dvd(); if(ret) { //try init return ret; //fail } dvd_init = 1; } // Call the corresponding DVD function num_entries = dvd_read_directoryentries(ffile->discoffset,ffile->size); // If it was not successful, just return the error if(num_entries <= 0) return FILE_BROWSER_ERROR; // Convert the DVD "file" data to fileBrowser_files *dir = malloc( num_entries * sizeof(fileBrowser_file) ); int i; for(i=0; i<num_entries; ++i){ strcpy( (*dir)[i].name, &DVDToc.file[i].name[0] ); (*dir)[i].discoffset = (uint64_t)(((uint64_t)DVDToc.file[i].sector)*2048); (*dir)[i].offset = 0; (*dir)[i].size = DVDToc.file[i].size; (*dir)[i].attr = 0; if(DVDToc.file[i].flags == 2)//on DVD, 2 is a dir (*dir)[i].attr = FILE_BROWSER_ATTR_DIR; if((*dir)[i].name[strlen((*dir)[i].name)-1] == '/' ) (*dir)[i].name[strlen((*dir)[i].name)-1] = 0; //get rid of trailing '/' } if(strlen((*dir)[0].name) == 0) strcpy( (*dir)[0].name, ".." ); return num_entries; }
/**************************************************************************** * 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; }
char *dvd_error_str() { unsigned int err = dvd_get_error(); if(!err) return "OK"; memset(&error_str[0],0,256); switch(err>>24) { case 0: break; case 1: strcpy(&error_str[0],"Lid open"); break; case 2: strcpy(&error_str[0],"No disk/Disk changed"); break; case 3: strcpy(&error_str[0],"No disk"); break; case 4: strcpy(&error_str[0],"Motor off"); break; case 5: strcpy(&error_str[0],"Disk not initialized"); break; } switch(err&0xFFFFFF) { case 0: break; case 0x020400: strcat(&error_str[0]," Motor Stopped"); break; case 0x020401: strcat(&error_str[0]," Disk ID not read"); break; case 0x023A00: strcat(&error_str[0]," Medium not present / Cover opened"); break; case 0x030200: strcat(&error_str[0]," No Seek complete"); break; case 0x031100: strcat(&error_str[0]," UnRecoverd read error"); break; case 0x040800: strcat(&error_str[0]," Transfer protocol error"); break; case 0x052000: strcat(&error_str[0]," Invalid command operation code"); break; case 0x052001: strcat(&error_str[0]," Audio Buffer not set"); break; case 0x052100: strcat(&error_str[0]," Logical block address out of range"); break; case 0x052400: strcat(&error_str[0]," Invalid Field in command packet"); break; case 0x052401: strcat(&error_str[0]," Invalid audio command"); break; case 0x052402: strcat(&error_str[0]," Configuration out of permitted period"); break; case 0x053000: strcat(&error_str[0]," DVD-R"); //? break; case 0x053100: strcat(&error_str[0]," Wrong Read Type"); //? break; case 0x056300: strcat(&error_str[0]," End of user area encountered on this track"); break; case 0x062800: strcat(&error_str[0]," Medium may have changed"); break; case 0x0B5A01: strcat(&error_str[0]," Operator medium removal request"); break; } if(!error_str[0]) sprintf(&error_str[0],"Unknown %08X",err); return &error_str[0]; }
int fileBrowser_DVD_readDir(fileBrowser_file* ffile, fileBrowser_file** dir){ int num_entries = 0, ret = 0; if(dvd_get_error() || !dvd_init) { //if some error ret = init_dvd(); if(ret) { //try init return ret; //fail } dvd_init = 1; } if (!memcmp((void*)0x80000000, "D43U01", 6)) { //OoT+MQ bonus disc support. num_entries = 2; *dir = malloc( num_entries * sizeof(fileBrowser_file) ); strcpy( (*dir)[0].name, ZELDA_OOT_NAME); (*dir)[0].discoffset = 0x54FBEEF4ULL; (*dir)[0].offset = 0; (*dir)[0].size = 0x2000000; (*dir)[0].attr = 0; strcpy( (*dir)[1].name, ZELDA_MQ_NAME); (*dir)[1].discoffset = 0x52CCC5FCULL; (*dir)[1].offset = 0; (*dir)[1].size = 0x2000000; (*dir)[1].attr = 0; return num_entries; } else if (!memcmp((void*)0x80000000, "D43E01", 6)) { num_entries = 2; *dir = malloc( num_entries * sizeof(fileBrowser_file) ); strcpy( (*dir)[0].name, ZELDA_OOT_NAME); (*dir)[0].discoffset = 0x550569D8ULL; (*dir)[0].offset = 0; (*dir)[0].size = 0x2000000; (*dir)[0].attr = 0; strcpy( (*dir)[1].name, ZELDA_MQ_NAME); (*dir)[1].discoffset = 0x52FBC1E0ULL; (*dir)[1].offset = 0; (*dir)[1].size = 0x2000000; (*dir)[1].attr = 0; return num_entries; } else if (!memcmp((void*)0x80000000, "PZLP01", 6)) { //Zelda Collectors disc support. num_entries = 2; *dir = malloc( num_entries * sizeof(fileBrowser_file) ); strcpy( (*dir)[0].name, ZELDA_OOT_NAME); (*dir)[0].discoffset = 0x3B9D1FC0ULL; (*dir)[0].offset = 0; (*dir)[0].size = 0x2000000; (*dir)[0].attr = 0; strcpy( (*dir)[1].name, ZELDA_MM_NAME); (*dir)[1].discoffset = 0x0C4E1FC0ULL; (*dir)[1].offset = 0; (*dir)[1].size = 0x2000000; (*dir)[1].attr = 0; return num_entries; } // Call the corresponding DVD function num_entries = dvd_read_directoryentries(ffile->discoffset,ffile->size); // If it was not successful, just return the error if(num_entries <= 0) return FILE_BROWSER_ERROR; // Convert the DVD "file" data to fileBrowser_files *dir = malloc( num_entries * sizeof(fileBrowser_file) ); int i; for(i=0; i<num_entries; ++i){ strcpy( (*dir)[i].name, DVDToc->file[i].name ); (*dir)[i].discoffset = (uint64_t)(((uint64_t)DVDToc->file[i].sector)*2048); (*dir)[i].offset = 0; (*dir)[i].size = DVDToc->file[i].size; (*dir)[i].attr = 0; if(DVDToc->file[i].flags == 2)//on DVD, 2 is a dir (*dir)[i].attr = FILE_BROWSER_ATTR_DIR; if((*dir)[i].name[strlen((*dir)[i].name)-1] == '/' ) (*dir)[i].name[strlen((*dir)[i].name)-1] = 0; //get rid of trailing '/' } //kill the large TOC so we can have a lot more memory ingame (256k more) free(DVDToc); DVDToc = NULL; if(strlen((*dir)[0].name) == 0) strcpy( (*dir)[0].name, ".." ); return num_entries; }