diff --git a/Source/Core/Common/Src/DriveUtil.cpp b/Source/Core/Common/Src/DriveUtil.cpp index 2d3cc7f8af..cac2a01738 100644 --- a/Source/Core/Common/Src/DriveUtil.cpp +++ b/Source/Core/Common/Src/DriveUtil.cpp @@ -29,7 +29,7 @@ void GetAllRemovableDrives(std::vector *drives) { HANDLE hDisk; DISK_GEOMETRY diskGeometry; - for (int i = 'A'; i < 'Z'; i++) + for (int i = 'D'; i < 'Z'; i++) { char path[MAX_PATH]; sprintf(path, "\\\\.\\%c:", i); @@ -55,4 +55,3 @@ void GetAllRemovableDrives(std::vector *drives) { // stat("/media/cdrom") or whatever etc etc #endif } - diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index 648d909e79..0edb09e330 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -69,6 +69,18 @@ bool Exists(const char *filename) return (result == 0); } +bool IsDisk(const char *filename) +{ +#ifdef _WIN32 + std::string copy = filename; + if (copy.size() < 4 && copy.c_str()[1] == ':') + return true; +#else + // TODO: add linux \ osx +#endif + return false; +} + bool IsDirectory(const char *filename) { struct stat file_info; diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index 52c99d660b..10bf33e3bc 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -40,6 +40,7 @@ bool Exists(const char *filename); void Launch(const char *filename); void Explore(const char *path); bool IsDirectory(const char *filename); +bool IsDisk(const char *filename); bool CreateDir(const char *filename); bool CreateDirectoryStructure(const std::string& _rFullPath); bool Delete(const char *filename); diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index 63ef71146d..c44da39e94 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -162,7 +162,7 @@ std::string* IniFile::GetLine(Section* section, const char* key, std::string* va std::string lineKey; ParseLine(line, &lineKey, valueOut, commentOut); - if (!stricmp(lineKey.c_str(), key)) + if (!strcasecmp(lineKey.c_str(), key)) { return &line; } diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index 30506e40f3..c205bfe79e 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -58,102 +58,106 @@ bool SCoreStartupParameter::AutoSetup(EBootBios _BootBios) { std::string Region(EUR_DIR); - switch (_BootBios) - { - case BOOT_DEFAULT: - { - /* Check if the file exist, we may have gotten it from a --elf command line - that gave an incorrect file name */ - if (!File::Exists(m_strFilename.c_str())) - { + switch (_BootBios) + { + case BOOT_DEFAULT: + { + bool bootDrive = File::IsDisk(m_strFilename.c_str()); + // Check if the file exist, we may have gotten it from a --elf command line + // that gave an incorrect file name + if (!bootDrive && !File::Exists(m_strFilename.c_str())) + { PanicAlert("The file you specified (%s) does not exists", m_strFilename.c_str()); return false; } - std::string Extension; - SplitPath(m_strFilename, NULL, NULL, &Extension); - if (!strcasecmp(Extension.c_str(), ".gcm") || + std::string Extension; + SplitPath(m_strFilename, NULL, NULL, &Extension); + if (!strcasecmp(Extension.c_str(), ".gcm") || !strcasecmp(Extension.c_str(), ".iso") || - !strcasecmp(Extension.c_str(), ".gcz") ) - { - m_BootType = BOOT_ISO; - DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(m_strFilename.c_str()); - if (pVolume == NULL) - { - PanicAlert("Your GCM/ISO file seems to be invalid, or not a GC/Wii ISO."); - return false; - } + !strcasecmp(Extension.c_str(), ".gcz") || + bootDrive) + { + m_BootType = BOOT_ISO; + DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(m_strFilename.c_str()); + if (pVolume == NULL) + { + + PanicAlert(bootDrive ? "Drive could not be mounted" : + "Your GCM/ISO file seems to be invalid, or not a GC/Wii ISO." ); + return false; + } m_strName = pVolume->GetName(); m_strUniqueID = pVolume->GetUniqueID(); // Check if we have a Wii disc bWii = DiscIO::IsVolumeWiiDisc(pVolume); - switch (pVolume->GetCountry()) - { + switch (pVolume->GetCountry()) + { case DiscIO::IVolume::COUNTRY_USA: - bNTSC = true; - Region = USA_DIR; - break; + bNTSC = true; + Region = USA_DIR; + break; - case DiscIO::IVolume::COUNTRY_JAP: - bNTSC = true; - Region = JAP_DIR; - break; + case DiscIO::IVolume::COUNTRY_JAP: + bNTSC = true; + Region = JAP_DIR; + break; - case DiscIO::IVolume::COUNTRY_EUROPE: - case DiscIO::IVolume::COUNTRY_FRANCE: - bNTSC = false; - Region = EUR_DIR; - break; + case DiscIO::IVolume::COUNTRY_EUROPE: + case DiscIO::IVolume::COUNTRY_FRANCE: + bNTSC = false; + Region = EUR_DIR; + break; - default: - PanicAlert("Your GCM/ISO file seems to be invalid (invalid country)."); - return false; - } + default: + PanicAlert("Your GCM/ISO file seems to be invalid (invalid country)."); + return false; + } - delete pVolume; - } - else if (!strcasecmp(Extension.c_str(), ".elf")) - { - bWii = CBoot::IsElfWii(m_strFilename.c_str()); - Region = USA_DIR; - m_BootType = BOOT_ELF; - bNTSC = true; - } - else if (!strcasecmp(Extension.c_str(), ".dol")) - { - bWii = CDolLoader::IsDolWii(m_strFilename.c_str()); - Region = USA_DIR; - m_BootType = BOOT_DOL; - bNTSC = true; - } + delete pVolume; + } + else if (!strcasecmp(Extension.c_str(), ".elf")) + { + bWii = CBoot::IsElfWii(m_strFilename.c_str()); + Region = USA_DIR; + m_BootType = BOOT_ELF; + bNTSC = true; + } + else if (!strcasecmp(Extension.c_str(), ".dol")) + { + bWii = CDolLoader::IsDolWii(m_strFilename.c_str()); + Region = USA_DIR; + m_BootType = BOOT_DOL; + bNTSC = true; + } else { PanicAlert("Could not recognize ISO file %s", m_strFilename.c_str()); return false; } - } - break; + } + break; - case BOOT_BIOS_USA: - Region = USA_DIR; - m_strFilename.clear(); - bNTSC = true; - break; - - case BOOT_BIOS_JAP: - Region = JAP_DIR; + case BOOT_BIOS_USA: + Region = USA_DIR; m_strFilename.clear(); - bNTSC = true; - break; + bNTSC = true; + break; - case BOOT_BIOS_EUR: - Region = EUR_DIR; - m_strFilename.clear(); - bNTSC = false; - break; - } + case BOOT_BIOS_JAP: + Region = JAP_DIR; + m_strFilename.clear(); + bNTSC = true; + break; + + case BOOT_BIOS_EUR: + Region = EUR_DIR; + m_strFilename.clear(); + bNTSC = false; + break; + } // Setup paths CheckMemcardPath(SConfig::GetInstance().m_strMemoryCardA, Region, true); diff --git a/Source/Core/Core/Src/HW/DVDInterface.h b/Source/Core/Core/Src/HW/DVDInterface.h index 5f6574d09f..52476e3eaa 100644 --- a/Source/Core/Core/Src/HW/DVDInterface.h +++ b/Source/Core/Core/Src/HW/DVDInterface.h @@ -32,7 +32,7 @@ void SetDiscInside(bool _DiscInside); void SwapDisc(const char * fileName); // Lid Functions -void SetLidOpen(bool open); +void SetLidOpen(bool open = true); bool IsLidOpen(); // DVD Access Functions diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp index 2d5c4164ae..aa3057172b 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp @@ -97,7 +97,6 @@ CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rF LOG(EXPANSIONINTERFACE, "No memory card found. Will create new."); Flush(); - Core::DisplayMessage(StringFromFormat("Wrote memory card %i contents to %s.", card_index + 1, m_strFilename.c_str()), 4000); } } @@ -132,7 +131,7 @@ void CEXIMemoryCard::Flush(bool exiting) if (!exiting) { - Core::DisplayMessage(StringFromFormat("Wrote memory card %i contents to %s.", card_index, m_strFilename.c_str()).c_str(), 4000); + Core::DisplayMessage(StringFromFormat("Wrote memory card %c contents to %s", card_index ? 'B' : 'A', m_strFilename.c_str()).c_str(), 4000); } } ////////////////////////////////////// diff --git a/Source/Core/DiscIO/Src/Blob.cpp b/Source/Core/DiscIO/Src/Blob.cpp index c592c61c33..4d0161a4ed 100644 --- a/Source/Core/DiscIO/Src/Blob.cpp +++ b/Source/Core/DiscIO/Src/Blob.cpp @@ -94,8 +94,8 @@ bool SectorReader::Read(u64 offset, u64 size, u8* out_ptr) IBlobReader* CreateBlobReader(const char* filename) { - //if (strlen(filename) < 4 && filename[1] == ':') // Drive, for sure. - // return DriveReader::Create(filename); + if(File::IsDisk(filename)) + return DriveReader::Create(filename); if (!File::Exists(filename)) return 0; diff --git a/Source/Core/DiscIO/Src/DriveBlob.cpp b/Source/Core/DiscIO/Src/DriveBlob.cpp index 11f99faada..edca16638b 100644 --- a/Source/Core/DiscIO/Src/DriveBlob.cpp +++ b/Source/Core/DiscIO/Src/DriveBlob.cpp @@ -16,10 +16,138 @@ // http://code.google.com/p/dolphin-emu/ #include "stdafx.h" - #include "DriveBlob.h" namespace DiscIO { + DriveReader::DriveReader(const char *drive) + { +#ifdef _WIN32 + char path[MAX_PATH]; + strncpy(path, drive, 3); + path[2] = 0; + sprintf(path, "\\\\.\\%s", drive); + + hDisc = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hDisc == INVALID_HANDLE_VALUE) + { + PanicAlert("Load from DVD backup failed"); + } + else + { + SetSectorSize(2048); + #ifdef _LOCKDRIVE + // Lock the compact disc in the CD-ROM drive to prevent accidental + // removal while reading from it. + pmrLockCDROM.PreventMediaRemoval = TRUE; + DeviceIoControl (hDisc, IOCTL_CDROM_MEDIA_REMOVAL, + &pmrLockCDROM, sizeof(pmrLockCDROM), NULL, + 0, &dwNotUsed, NULL); + #endif + } +#else + file_ = fopen(drive, "rb"); + if (!file_) + PanicAlert("Load from DVD backup failed"); + else + SetSectorSize(2048); +#endif + } // DriveReader::DriveReader + + DriveReader::~DriveReader() + { +#ifdef _WIN32 + #ifdef _LOCKDRIVE // Do we want to lock the drive? + // Unlock the disc in the CD-ROM drive. + pmrLockCDROM.PreventMediaRemoval = FALSE; + DeviceIoControl (hDisc, IOCTL_CDROM_MEDIA_REMOVAL, + &pmrLockCDROM, sizeof(pmrLockCDROM), NULL, + 0, &dwNotUsed, NULL); + #endif + CloseHandle(hDisc); +#else + fclose(file_); +#endif + } // DriveReader::~DriveReader + + + DriveReader * DriveReader::Create(const char *drive) + { + return new DriveReader(drive); + } + + bool DriveReader::Read(u64 offset, u64 nbytes, u8* out_ptr) + { + u64 startingBlock = offset / m_blocksize; + u64 remain = nbytes; + int positionInBlock = (int)(offset % m_blocksize); + u64 block = startingBlock; + + while (remain > 0) + { + const u8* data = GetBlockData(block); + if (!data) + return false; + + u32 toCopy = m_blocksize - positionInBlock; + if (toCopy >= remain) + { + // yay, we are done! + memcpy(out_ptr, data + positionInBlock, (size_t)remain); + return true; + } + else + { + memcpy(out_ptr, data + positionInBlock, toCopy); + out_ptr += toCopy; + remain -= toCopy; + positionInBlock = 0; + block++; + } + } + return true; + } // DriveReader::Read + + void DriveReader::GetBlock(u64 block_num, u8 *out_ptr) + { + u32 NotUsed; + u8 * lpSector = new u8[m_blocksize]; +#ifdef _WIN32 + // TODO: Fix for 64bit block_num, SetFilePointer uses LONG + SetFilePointer (hDisc, m_blocksize*block_num, NULL, FILE_BEGIN); + if(!ReadFile(hDisc, lpSector, m_blocksize, (LPDWORD)&NotUsed, NULL)) + PanicAlert("DRE"); +#else + fseek(file_, m_blocksize*block_num, SEEK_SET); + fread(lpSector, 1, m_blocksize, file_); +#endif + + memcpy(out_ptr, lpSector, m_blocksize); + delete lpSector; + } + + void DriveReader::SetSectorSize(int blocksize) + { + for (int i = 0; i < CACHE_SIZE; i++) + { + cache[i] = new u8[blocksize]; + cache_tags[i] = (u64)(s64) - 1; + } + m_blocksize = blocksize; + } + + const u8 *DriveReader::GetBlockData(u64 block_num) + { + if (cache_tags[0] == block_num) + { + return cache[0]; + } + else + { + GetBlock(block_num, cache[0]); + cache_tags[0] = block_num; + return cache[0]; + } + } } // namespace diff --git a/Source/Core/DiscIO/Src/DriveBlob.h b/Source/Core/DiscIO/Src/DriveBlob.h index 46154fe2fd..41aad2f09c 100644 --- a/Source/Core/DiscIO/Src/DriveBlob.h +++ b/Source/Core/DiscIO/Src/DriveBlob.h @@ -22,36 +22,41 @@ #ifdef _WIN32 #include +#include #endif namespace DiscIO { -#ifdef _WIN32 class DriveReader : public SectorReader { - HANDLE hDisc; - private: - DriveReader(const char *drive) { - /* - char path[MAX_PATH]; - strncpy(path, drive, 3); - path[2] = 0; - sprintf(path, "\\\\.\\%s", drive); - hDisc = CreateFile(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - SetSectorSize(2048); - */ - } - + DriveReader(const char *drive); + void DriveReader::SetSectorSize(int blocksize); + enum { CACHE_SIZE = 32 }; + int m_blocksize; + u8* cache[CACHE_SIZE]; + u64 cache_tags[CACHE_SIZE]; + int cache_age[CACHE_SIZE]; + void GetBlock(u64 block_num, u8 *out_ptr); +#ifdef _WIN32 + HANDLE hDisc; + PREVENT_MEDIA_REMOVAL pmrLockCDROM; +#else + FILE* file_; +#endif + s64 size; + u64 *block_pointers; public: - static DriveReader *Create(const char *drive) { - return NULL;// new DriveReader(drive); - } + static DriveReader *Create(const char *drive); + ~DriveReader(); + u64 GetDataSize() const { return size; } + u64 GetRawSize() const { return size; } + bool Read(u64 offset, u64 nbytes, u8* out_ptr); + const u8 *GetBlockData(u64 block_num); }; -#endif diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index 0b55650fdb..2b91717759 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -259,6 +259,7 @@ EVT_MENU(IDM_TOGGLE_TOOLBAR, CFrame::OnToggleToolbar) EVT_MENU(IDM_TOGGLE_STATUSBAR, CFrame::OnToggleStatusbar) EVT_MENU_RANGE(IDM_LOADSLOT1, IDM_LOADSLOT10, CFrame::OnLoadState) EVT_MENU_RANGE(IDM_SAVESLOT1, IDM_SAVESLOT10, CFrame::OnSaveState) +EVT_MENU_RANGE(IDM_DRIVE1, IDM_DRIVE24, CFrame::OnBootDrive) EVT_SIZE(CFrame::OnResize) EVT_LIST_ITEM_ACTIVATED(LIST_CTRL, CFrame::OnGameListCtrl_ItemActivated) diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h index 980e12066e..8cbec8e048 100644 --- a/Source/Core/DolphinWX/Src/Frame.h +++ b/Source/Core/DolphinWX/Src/Frame.h @@ -26,7 +26,7 @@ #include #include //////////////////////////////// - +#include "DriveUtil.h" ////////////////////////////////////////////////////////////////////////// // A shortcut to access the bitmaps @@ -97,6 +97,7 @@ class CFrame : public wxFrame wxToolBar* TheToolBar; wxToolBarToolBase* m_ToolPlay; + std::vector drives; ////////////////////////////////////////////////////////////////////////////////////// // Music mod @@ -173,6 +174,7 @@ class CFrame : public wxFrame void OnOpen(wxCommandEvent& event); void DoOpen(bool Boot); // File menu void OnRefresh(wxCommandEvent& event); void OnBrowse(wxCommandEvent& event); + void OnBootDrive(wxCommandEvent& event); void OnPlay(wxCommandEvent& event); // Emulation void OnChangeDisc(wxCommandEvent& event); diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 6af9108111..401349f43a 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -101,6 +101,16 @@ void CFrame::CreateMenu() m_pMenuItemOpen = fileMenu->Append(wxID_OPEN, _T("&Open...\tCtrl+O")); fileMenu->Append(wxID_REFRESH, _T("&Refresh")); fileMenu->Append(IDM_BROWSE, _T("&Browse for ISOs...")); +// change to test drive loading, currently very slow on win32, not tested on linux/os x +// works ok on a virtual drive with GC Games, Wii games do not load +#if 0 + wxMenu *externalDrive = new wxMenu; + fileMenu->AppendSubMenu(externalDrive, _T("&Load From Drive")); + GetAllRemovableDrives(&drives); + for (int i = 0; i < drives.size() && i < 24; i++) { + externalDrive->Append(IDM_DRIVE1 + i, wxString::Format(_T("%s"), drives.at(i).c_str())); + } +#endif fileMenu->AppendSeparator(); fileMenu->Append(wxID_EXIT, _T("E&xit"), _T("Alt+F4")); @@ -452,7 +462,7 @@ void CFrame::DoOpen(bool Boot) void CFrame::OnChangeDisc(wxCommandEvent& WXUNUSED (event)) { - DVDInterface::SetLidOpen(true); + DVDInterface::SetLidOpen(); DoOpen(false); DVDInterface::SetLidOpen(false); } @@ -461,6 +471,12 @@ void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) { BootGame(); } + +void CFrame::OnBootDrive(wxCommandEvent& event) +{ + BootManager::BootCore(drives.at(event.GetId()-IDM_DRIVE1).c_str()); +} + //////////////////////////////////////////////////// diff --git a/Source/Core/DolphinWX/Src/Globals.h b/Source/Core/DolphinWX/Src/Globals.h index 7ba9c0df7c..32e0f8449d 100644 --- a/Source/Core/DolphinWX/Src/Globals.h +++ b/Source/Core/DolphinWX/Src/Globals.h @@ -54,6 +54,8 @@ enum IDM_PLAY, IDM_STOP, IDM_BROWSE, + IDM_DRIVE1, + IDM_DRIVE24 = IDM_DRIVE1 + 23,//248, IDM_MEMCARD, // Misc menu IDM_CHEATS,