diff --git a/Source/Project64/Project64.vcxproj b/Source/Project64/Project64.vcxproj index 18cd3804f..34a28e729 100644 --- a/Source/Project64/Project64.vcxproj +++ b/Source/Project64/Project64.vcxproj @@ -67,6 +67,7 @@ + @@ -108,6 +109,7 @@ + diff --git a/Source/Project64/Project64.vcxproj.filters b/Source/Project64/Project64.vcxproj.filters index 74c85c08d..1df1b52f8 100644 --- a/Source/Project64/Project64.vcxproj.filters +++ b/Source/Project64/Project64.vcxproj.filters @@ -162,6 +162,9 @@ Source Files\Settings Files + + Source Files\User Interface Source + @@ -293,6 +296,9 @@ Header Files\Settings + + Header Files\User Interface Headers + diff --git a/Source/Project64/UserInterface/RomBrowser.h b/Source/Project64/UserInterface/RomBrowser.h index d13a06e1e..1b9190d0b 100644 --- a/Source/Project64/UserInterface/RomBrowser.h +++ b/Source/Project64/UserInterface/RomBrowser.h @@ -12,6 +12,7 @@ #include #include +#include "RomList.h" class CMainGui; class CPlugins; @@ -80,14 +81,14 @@ struct SORT_FIELD }; class C7zip; -class CRomBrowser +class CRomBrowser : + public CRomList { public: CRomBrowser(HWND & hMainWindow, HWND & StatusWindow); ~CRomBrowser(void); void HighLightLastRom(void); void HideRomList(void); - void RefreshRomBrowser(void); void ResetRomBrowserColomuns(void); void ResizeRomList(WORD nWidth, WORD nHeight); void RomBrowserToTop(void); @@ -116,85 +117,29 @@ private: RB_ForceFeedback = 18, RB_FileFormat = 19 }; - enum FILE_FORMAT - { - Format_Uncompressed, - Format_Zip, - Format_7zip, - }; - enum { NoOfSortKeys = 3 }; - struct ROM_INFO - { - char szFullFileName[300]; - FILE_FORMAT FileFormat; - wchar_t Status[60]; - char FileName[200]; - wchar_t InternalName[22]; - wchar_t GoodName[200]; - wchar_t CartID[3]; - wchar_t PluginNotes[250]; - wchar_t CoreNotes[250]; - wchar_t UserNotes[250]; - wchar_t Developer[30]; - wchar_t ReleaseDate[30]; - wchar_t Genre[15]; - int32_t Players; - uint32_t TextColor; - int32_t SelColor; - uint32_t SelTextColor; - uint32_t SelColorBrush; - int32_t RomSize; - uint8_t Manufacturer; - uint8_t Country; - uint32_t CRC1; - uint32_t CRC2; - int32_t CicChip; - wchar_t ForceFeedback[15]; - }; - - typedef std::vector ROMINFO_LIST; - - void AddFileNameToList(strlist & FileList, const stdstr & Directory, CPath & File); - void AddRomToList(const char * RomLocation, const char * lpLastRom); - void AddRomInfoToList(ROM_INFO &RomInfo, const char * lpLastRom); void AllocateBrushs(void); - static void ByteSwapRomData(uint8_t * Data, int DataLen); + void RomListReset(void); + void RomListLoaded(void); + void RomAddedToList(int32_t ListPos); int CalcSortPosition(uint32_t lParam); void CreateRomListControl(void); void DeallocateBrushs(void); - void FillRomExtensionInfo(ROM_INFO * pRomInfo); bool FillRomInfo(ROM_INFO * pRomInfo); - void FillRomList(strlist & FileList, const CPath & BaseDirectory, const char * Directory, const char * lpLastRom); void FixRomListWindow(void); - static int32_t GetCicChipID(uint8_t * RomData); - bool LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_t DataLen, int32_t * RomSize, FILE_FORMAT & FileFormat); - void LoadRomList(void); void MenuSetText(HMENU hMenu, int32_t MenuPos, const wchar_t * Title, char * ShortCut); - void SaveRomList(strlist & FileList); void RomList_ColoumnSortList(uint32_t pnmh); void RomList_GetDispInfo(uint32_t pnmh); void RomList_OpenRom(uint32_t pnmh); void RomList_PopupMenu(uint32_t pnmh); void RomList_SortList(void); - bool GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread); - MD5 RomListHash(strlist & FileList); - static void NotificationCB(const char * Status, CRomBrowser * _this); + void RomDirChanged(void); - //Watch Directory Changed function - HANDLE m_WatchThread, m_WatchStopEvent; - DWORD m_WatchThreadID; - stdstr m_WatchRomDir; - void WatchThreadStart(void); - void WatchThreadStop(void); - bool RomDirNeedsRefresh(void); // Called from watch thread - static void WatchRomDirChanged(CRomBrowser * _this); - static void RefreshRomBrowserStatic(CRomBrowser * _this); static void AddField(ROMBROWSER_FIELDS_LIST & Fields, const char * Name, int32_t Pos, int32_t ID, int32_t Width, LanguageStringID LangID, bool UseDefault); //Callback @@ -206,16 +151,10 @@ private: HWND m_hRomList; ROMBROWSER_FIELDS_LIST m_Fields; FIELD_TYPE_LIST m_FieldType; - ROMINFO_LIST m_RomInfo; std::string m_SelectedRom; bool m_Visible; bool m_ShowingRomBrowser; - HANDLE m_RefreshThread; - bool m_StopRefresh; - CIniFile * m_RomIniFile; - CIniFile * m_NotesIniFile; - CIniFile * m_ExtIniFile; - CIniFile * m_ZipIniFile; bool m_AllowSelectionLastRom; static std::wstring m_UnknownGoodName; + std::string m_LastRom; }; diff --git a/Source/Project64/UserInterface/RomBrowserClass.cpp b/Source/Project64/UserInterface/RomBrowserClass.cpp index 22492304d..86836af43 100644 --- a/Source/Project64/UserInterface/RomBrowserClass.cpp +++ b/Source/Project64/UserInterface/RomBrowserClass.cpp @@ -20,26 +20,10 @@ CRomBrowser::CRomBrowser(HWND & MainWindow, HWND & StatusWindow) : m_MainWindow(MainWindow), m_StatusWindow(StatusWindow), m_ShowingRomBrowser(false), - m_RefreshThread(NULL), - m_RomIniFile(NULL), - m_NotesIniFile(NULL), - m_ExtIniFile(NULL), - m_ZipIniFile(NULL), - m_AllowSelectionLastRom(true), - m_WatchThreadID(0) + m_AllowSelectionLastRom(true) { - if (g_Settings) - { - m_RomIniFile = new CIniFile(g_Settings->LoadStringVal(SupportFile_RomDatabase).c_str()); - m_NotesIniFile = new CIniFile(g_Settings->LoadStringVal(SupportFile_Notes).c_str()); - m_ExtIniFile = new CIniFile(g_Settings->LoadStringVal(SupportFile_ExtInfo).c_str()); - m_ZipIniFile = new CIniFile(g_Settings->LoadStringVal(RomList_7zipCache).c_str()); - } - m_hRomList = 0; m_Visible = false; - m_WatchThread = NULL; - m_WatchStopEvent = NULL; GetFieldInfo(m_Fields); m_FieldType.resize(m_Fields.size()); @@ -47,30 +31,7 @@ CRomBrowser::CRomBrowser(HWND & MainWindow, HWND & StatusWindow) : CRomBrowser::~CRomBrowser(void) { - m_StopRefresh = true; - WatchThreadStop(); DeallocateBrushs(); - - if (m_RomIniFile) - { - delete m_RomIniFile; - m_RomIniFile = NULL; - } - if (m_NotesIniFile) - { - delete m_NotesIniFile; - m_NotesIniFile = NULL; - } - if (m_ExtIniFile) - { - delete m_ExtIniFile; - m_ExtIniFile = NULL; - } - if (m_ZipIniFile) - { - delete m_ZipIniFile; - m_ZipIniFile = NULL; - } } void CRomBrowser::AddField(ROMBROWSER_FIELDS_LIST & Fields, LPCSTR Name, int32_t Pos, int32_t ID, int32_t Width, LanguageStringID LangID, bool UseDefault) @@ -290,33 +251,22 @@ int32_t CRomBrowser::CalcSortPosition(uint32_t lParam) return End + 1; } -void CRomBrowser::AddRomToList(const char * RomLocation, const char * lpLastRom) +void CRomBrowser::RomAddedToList(int32_t ListPos) { - ROM_INFO RomInfo; - - memset(&RomInfo, 0, sizeof(ROM_INFO)); - strncpy(RomInfo.szFullFileName, RomLocation, (sizeof(RomInfo.szFullFileName) / sizeof(RomInfo.szFullFileName[0])) - 1); - if (!FillRomInfo(&RomInfo)) { return; } - AddRomInfoToList(RomInfo, lpLastRom); -} - -void CRomBrowser::AddRomInfoToList(ROM_INFO &RomInfo, const char * lpLastRom) -{ - int32_t ListPos = m_RomInfo.size(); - m_RomInfo.push_back(RomInfo); + m_RomInfo[ListPos].SelColorBrush = NULL; LVITEMW lvItem; memset(&lvItem, 0, sizeof(lvItem)); lvItem.mask = LVIF_TEXT | LVIF_PARAM; - lvItem.iItem = CalcSortPosition(ListPos); + lvItem.iItem = ListView_GetItemCount(m_hRomList); lvItem.lParam = (LPARAM)ListPos; lvItem.pszText = LPSTR_TEXTCALLBACKW; - int32_t index = ListView_InsertItem(m_hRomList, &lvItem); + int32_t index = SendMessageW(m_hRomList, LVM_INSERTITEMW, 0, (LPARAM)&lvItem); int32_t iItem = ListView_GetNextItem(m_hRomList, -1, LVNI_SELECTED); //if the last rom then highlight the item - if (iItem < 0 && _stricmp(RomInfo.szFullFileName, lpLastRom) == 0) + if (iItem < 0 && _stricmp(m_RomInfo[ListPos].szFullFileName, m_LastRom.c_str()) == 0) { ListView_SetItemState(m_hRomList, index, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); } @@ -342,6 +292,18 @@ void CRomBrowser::AllocateBrushs(void) } } +void CRomBrowser::RomListReset(void) +{ + WriteTrace(TraceUserInterface, TraceDebug, "1"); + ListView_DeleteAllItems((HWND)m_hRomList); + DeallocateBrushs(); + WriteTrace(TraceUserInterface, TraceDebug, "2"); + InvalidateRect((HWND)m_hRomList, NULL, TRUE); + Sleep(100); + WriteTrace(TraceUserInterface, TraceDebug, "3"); + m_LastRom = UISettingsLoadStringIndex(File_RecentGameFileIndex, 0); +} + void CRomBrowser::CreateRomListControl(void) { m_hRomList = CreateWindowW(WC_LISTVIEWW, NULL, WS_TABSTOP | WS_VISIBLE | WS_CHILD | LVS_OWNERDRAWFIXED | LVS_SINGLESEL | LVS_REPORT, 0, 0, 0, 0, m_MainWindow, (HMENU)IDC_ROMLIST, GetModuleHandle(NULL), NULL); @@ -365,438 +327,15 @@ void CRomBrowser::DeallocateBrushs(void) } } -void CRomBrowser::FillRomExtensionInfo(ROM_INFO * pRomInfo) +void CRomBrowser::RomListLoaded(void) { - //Initialize the structure - pRomInfo->UserNotes[0] = 0; - pRomInfo->Developer[0] = 0; - pRomInfo->ReleaseDate[0] = 0; - pRomInfo->Genre[0] = 0; - pRomInfo->Players = 1; - pRomInfo->CoreNotes[0] = 0; - pRomInfo->PluginNotes[0] = 0; - wcscpy(pRomInfo->GoodName, L"#340#"); - wcscpy(pRomInfo->Status, L"Unknown"); - - //Get File Identifier - char Identifier[100]; - sprintf(Identifier, "%08X-%08X-C:%X", pRomInfo->CRC1, pRomInfo->CRC2, pRomInfo->Country); - - //Rom Notes - if (m_Fields[RB_UserNotes].Pos() >= 0) - { - wcsncpy(pRomInfo->UserNotes, m_NotesIniFile->GetString(Identifier, "Note", "").ToUTF16().c_str(), sizeof(pRomInfo->UserNotes) / sizeof(wchar_t)); - } - - //Rom Extension info - if (m_Fields[RB_Developer].Pos() >= 0) - { - wcsncpy(pRomInfo->Developer, m_ExtIniFile->GetString(Identifier, "Developer", "").ToUTF16().c_str(), sizeof(pRomInfo->Developer) / sizeof(wchar_t)); - } - if (m_Fields[RB_ReleaseDate].Pos() >= 0) - { - wcsncpy(pRomInfo->ReleaseDate, m_ExtIniFile->GetString(Identifier, "ReleaseDate", "").ToUTF16().c_str(), sizeof(pRomInfo->ReleaseDate) / sizeof(wchar_t)); - } - if (m_Fields[RB_Genre].Pos() >= 0) - { - wcsncpy(pRomInfo->Genre, m_ExtIniFile->GetString(Identifier, "Genre", "").ToUTF16().c_str(), sizeof(pRomInfo->Genre) / sizeof(wchar_t)); - } - if (m_Fields[RB_Players].Pos() >= 0) - { - m_ExtIniFile->GetNumber(Identifier, "Players", 1, (uint32_t &)pRomInfo->Players); - } - if (m_Fields[RB_ForceFeedback].Pos() >= 0) - { - wcsncpy(pRomInfo->ForceFeedback, m_ExtIniFile->GetString(Identifier, "ForceFeedback", "unknown").ToUTF16().c_str(), sizeof(pRomInfo->ForceFeedback) / sizeof(wchar_t)); - } - - //Rom Settings - if (m_Fields[RB_GoodName].Pos() >= 0) - { - wcsncpy(pRomInfo->GoodName, m_RomIniFile->GetString(Identifier, "Good Name", stdstr().FromUTF16(pRomInfo->GoodName).c_str()).ToUTF16().c_str(), sizeof(pRomInfo->GoodName) / sizeof(wchar_t)); - } - wcsncpy(pRomInfo->Status, m_RomIniFile->GetString(Identifier, "Status", stdstr().FromUTF16(pRomInfo->Status).c_str()).ToUTF16().c_str(), sizeof(pRomInfo->Status) / sizeof(wchar_t)); - if (m_Fields[RB_CoreNotes].Pos() >= 0) - { - wcsncpy(pRomInfo->CoreNotes, m_RomIniFile->GetString(Identifier, "Core Note", "").ToUTF16().c_str(), sizeof(pRomInfo->CoreNotes) / sizeof(wchar_t)); - } - if (m_Fields[RB_PluginNotes].Pos() >= 0) - { - wcsncpy(pRomInfo->PluginNotes, m_RomIniFile->GetString(Identifier, "Plugin Note", "").ToUTF16().c_str(), sizeof(pRomInfo->PluginNotes) / sizeof(wchar_t)); - } - - //Get the text color - stdstr String = m_RomIniFile->GetString("Rom Status", stdstr().FromUTF16(pRomInfo->Status).c_str(), "000000"); - pRomInfo->TextColor = (std::strtoul(String.c_str(), 0, 16) & 0xFFFFFF); - pRomInfo->TextColor = (pRomInfo->TextColor & 0x00FF00) | ((pRomInfo->TextColor >> 0x10) & 0xFF) | ((pRomInfo->TextColor & 0xFF) << 0x10); - - //Get the selected color - String.Format("%ws.Sel", pRomInfo->Status); - String = m_RomIniFile->GetString("Rom Status", String.c_str(), "FFFFFFFF"); - uint32_t selcol = std::strtoul(String.c_str(), NULL, 16); - if (selcol & 0x80000000) - { - pRomInfo->SelColor = -1; - } - else - { - selcol = (selcol & 0x00FF00) | ((selcol >> 0x10) & 0xFF) | ((selcol & 0xFF) << 0x10); - pRomInfo->SelColor = selcol; - } - - //Get the selected text color - String.Format("%ws.Seltext", pRomInfo->Status); - String = m_RomIniFile->GetString("Rom Status", String.c_str(), "FFFFFF"); - pRomInfo->SelTextColor = (std::strtoul(String.c_str(), 0, 16) & 0xFFFFFF); - pRomInfo->SelTextColor = (pRomInfo->SelTextColor & 0x00FF00) | ((pRomInfo->SelTextColor >> 0x10) & 0xFF) | ((pRomInfo->SelTextColor & 0xFF) << 0x10); + AllocateBrushs(); + RomList_SortList(); } -bool CRomBrowser::FillRomInfo(ROM_INFO * pRomInfo) +void CRomBrowser::RomDirChanged(void) { - int32_t count; - uint8_t RomData[0x1000]; - - if (!LoadDataFromRomFile(pRomInfo->szFullFileName, RomData, sizeof(RomData), &pRomInfo->RomSize, pRomInfo->FileFormat)) - { - return false; - } - else - { - if (strstr(pRomInfo->szFullFileName, "?") != NULL) - { - strcpy(pRomInfo->FileName, strstr(pRomInfo->szFullFileName, "?") + 1); - } - else - { - strncpy(pRomInfo->FileName, CPath(pRomInfo->szFullFileName).GetNameExtension().c_str(), sizeof(pRomInfo->FileName) / sizeof(pRomInfo->FileName[0])); - } - if (m_Fields[RB_InternalName].Pos() >= 0) - { - char InternalName[22]; - memcpy(InternalName, (void *)(RomData + 0x20), 20); - for (count = 0; count < 20; count += 4) - { - InternalName[count] ^= InternalName[count + 3]; - InternalName[count + 3] ^= InternalName[count]; - InternalName[count] ^= InternalName[count + 3]; - InternalName[count + 1] ^= InternalName[count + 2]; - InternalName[count + 2] ^= InternalName[count + 1]; - InternalName[count + 1] ^= InternalName[count + 2]; - } - InternalName[20] = '\0'; - wcscpy(pRomInfo->InternalName, stdstr(InternalName).ToUTF16(stdstr::CODEPAGE_932).c_str()); - } - pRomInfo->CartID[0] = *(RomData + 0x3F); - pRomInfo->CartID[1] = *(RomData + 0x3E); - pRomInfo->CartID[2] = '\0'; - pRomInfo->Manufacturer = *(RomData + 0x38); - pRomInfo->Country = *(RomData + 0x3D); - pRomInfo->CRC1 = *(uint32_t *)(RomData + 0x10); - pRomInfo->CRC2 = *(uint32_t *)(RomData + 0x14); - pRomInfo->CicChip = GetCicChipID(RomData); - - FillRomExtensionInfo(pRomInfo); - - if (pRomInfo->SelColor == -1) - { - pRomInfo->SelColorBrush = (uint32_t)((HBRUSH)(COLOR_HIGHLIGHT + 1)); - } - else - { - pRomInfo->SelColorBrush = (uint32_t)CreateSolidBrush(pRomInfo->SelColor); - } - - return true; - } -} - -bool CRomBrowser::GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread) -{ - if (!BaseDirectory.DirectoryExists()) - { - return false; - } - CPath SearchPath(BaseDirectory, "*.*"); - SearchPath.AppendDirectory(Directory.c_str()); - - if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES)) - { - return false; - } - - do - { - if (InWatchThread && WaitForSingleObject(m_WatchStopEvent, 0) != WAIT_TIMEOUT) - { - return false; - } - - if (SearchPath.IsDirectory()) - { - if (g_Settings->LoadBool(RomList_GameDirRecursive)) - { - CPath CurrentDir(Directory); - CurrentDir.AppendDirectory(SearchPath.GetLastDirectory().c_str()); - GetRomFileNames(FileList, BaseDirectory, CurrentDir, InWatchThread); - } - } - else - { - AddFileNameToList(FileList, Directory, SearchPath); - } - } while (SearchPath.FindNext()); - return true; -} - -void CRomBrowser::NotificationCB(const char * Status, CRomBrowser * /*_this*/) -{ - g_Notify->DisplayMessage(5, Status); -} - -static const char* ROM_extensions[] = -{ - "zip", "7z", "v64", "z64", "n64", "rom", "jap", "pal", "usa", "eur", "bin", -}; - -void CRomBrowser::AddFileNameToList(strlist & FileList, const stdstr & Directory, CPath & File) -{ - uint8_t i; - - if (FileList.size() > 3000) - { - return; - } - - stdstr Drive, Dir, Name, Extension; - File.GetComponents(NULL, &Dir, &Name, &Extension); - Extension.ToLower(); - for (i = 0; i < sizeof(ROM_extensions) / sizeof(ROM_extensions[0]); i++) - { - if (Extension == ROM_extensions[i]) - { - stdstr FileName = Directory + Name + Extension; - FileName.ToLower(); - FileList.push_back(FileName); - break; - } - } -} - -void CRomBrowser::FillRomList(strlist & FileList, const CPath & BaseDirectory, const char * Directory, const char * lpLastRom) -{ - CPath SearchPath(BaseDirectory, "*"); - SearchPath.AppendDirectory(Directory); - - WriteTrace(TraceUserInterface, TraceDebug, "1 %s", (const char *)SearchPath); - if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES)) - { - return; - } - - do - { - uint8_t ext_ID; - int8_t new_list_entry = 0; - const uint8_t exts = sizeof(ROM_extensions) / sizeof(ROM_extensions[0]); - - WriteTrace(TraceUserInterface, TraceDebug, ": 2 %s m_StopRefresh = %d", (const char *)SearchPath, m_StopRefresh); - if (m_StopRefresh) { break; } - - if (SearchPath.IsDirectory()) - { - if (g_Settings->LoadBool(RomList_GameDirRecursive)) - { - CPath CurrentDir(Directory); - CurrentDir.AppendDirectory(SearchPath.GetLastDirectory().c_str()); - FillRomList(FileList, BaseDirectory, CurrentDir, lpLastRom); - } - continue; - } - - AddFileNameToList(FileList, Directory, SearchPath); - - stdstr Extension = stdstr(SearchPath.GetExtension()).ToLower(); - - for (ext_ID = 0; ext_ID < exts; ext_ID++) - { - if (Extension == ROM_extensions[ext_ID] && Extension != "7z") - { - new_list_entry = 1; - break; - } - } - if (new_list_entry) - { - AddRomToList(SearchPath, lpLastRom); - continue; - } - - if (Extension == "7z") - { - try - { - C7zip ZipFile(SearchPath); - if (!ZipFile.OpenSuccess()) - { - continue; - } - char ZipFileName[260]; - stdstr_f SectionName("%s-%d", ZipFile.FileName(ZipFileName, sizeof(ZipFileName)), ZipFile.FileSize()); - SectionName.ToLower(); - - WriteTrace(TraceUserInterface, TraceDebug, "4 %s", SectionName.c_str()); - for (int32_t i = 0; i < ZipFile.NumFiles(); i++) - { - CSzFileItem * f = ZipFile.FileItem(i); - if (f->IsDir) - { - continue; - } - ROM_INFO RomInfo; - - std::wstring FileNameW = ZipFile.FileNameIndex(i); - if (FileNameW.length() == 0) - { - continue; - } - - stdstr FileName; - FileName.FromUTF16(FileNameW.c_str()); - WriteTrace(TraceUserInterface, TraceDebug, "5"); - char drive2[_MAX_DRIVE], dir2[_MAX_DIR], FileName2[MAX_PATH], ext2[_MAX_EXT]; - _splitpath(FileName.c_str(), drive2, dir2, FileName2, ext2); - - WriteTrace(TraceUserInterface, TraceDebug, ": 6 %s", ext2); - if (_stricmp(ext2, ".bin") == 0) - { - continue; - } - WriteTrace(TraceUserInterface, TraceDebug, "7"); - memset(&RomInfo, 0, sizeof(ROM_INFO)); - stdstr_f zipFileName("%s?%s", (LPCSTR)SearchPath, FileName.c_str()); - ZipFile.SetNotificationCallback((C7zip::LP7ZNOTIFICATION)NotificationCB, this); - - strncpy(RomInfo.szFullFileName, zipFileName.c_str(), sizeof(RomInfo.szFullFileName) - 1); - RomInfo.szFullFileName[sizeof(RomInfo.szFullFileName) - 1] = 0; - strcpy(RomInfo.FileName, strstr(RomInfo.szFullFileName, "?") + 1); - RomInfo.FileFormat = Format_7zip; - - WriteTrace(TraceUserInterface, TraceDebug, "8"); - char szHeader[0x90]; - if (m_ZipIniFile->GetString(SectionName.c_str(), FileName.c_str(), "", szHeader, sizeof(szHeader)) == 0) - { - uint8_t RomData[0x1000]; - if (!ZipFile.GetFile(i, RomData, sizeof(RomData))) - { - continue; - } - WriteTrace(TraceUserInterface, TraceDebug, "9"); - if (!CN64Rom::IsValidRomImage(RomData)) { continue; } - WriteTrace(TraceUserInterface, TraceDebug, "10"); - ByteSwapRomData(RomData, sizeof(RomData)); - WriteTrace(TraceUserInterface, TraceDebug, "11"); - - stdstr RomHeader; - for (int32_t x = 0; x < 0x40; x += 4) - { - RomHeader += stdstr_f("%08X", *((uint32_t *)&RomData[x])); - } - WriteTrace(TraceUserInterface, TraceDebug, "11a %s", RomHeader.c_str()); - int32_t CicChip = GetCicChipID(RomData); - - //save this info - WriteTrace(TraceUserInterface, TraceDebug, "12"); - m_ZipIniFile->SaveString(SectionName.c_str(), FileName.c_str(), RomHeader.c_str()); - m_ZipIniFile->SaveNumber(SectionName.c_str(), stdstr_f("%s-Cic", FileName.c_str()).c_str(), CicChip); - strcpy(szHeader, RomHeader.c_str()); - } - WriteTrace(TraceUserInterface, TraceDebug, "13"); - uint8_t RomData[0x40]; - - for (int32_t x = 0; x < 0x40; x += 4) - { - const size_t delimit_offset = sizeof("FFFFFFFF") - 1; - const char backup_character = szHeader[2 * x + delimit_offset]; - - szHeader[2 * x + delimit_offset] = '\0'; - *(uint32_t *)&RomData[x] = strtoul(&szHeader[2 * x], NULL, 16); - szHeader[2 * x + delimit_offset] = backup_character; - } - - WriteTrace(TraceUserInterface, TraceDebug, "14"); - { - char InternalName[22]; - memcpy(InternalName, (void *)(RomData + 0x20), 20); - for (int32_t count = 0; count < 20; count += 4) - { - InternalName[count] ^= InternalName[count + 3]; - InternalName[count + 3] ^= InternalName[count]; - InternalName[count] ^= InternalName[count + 3]; - InternalName[count + 1] ^= InternalName[count + 2]; - InternalName[count + 2] ^= InternalName[count + 1]; - InternalName[count + 1] ^= InternalName[count + 2]; - } - InternalName[20] = '\0'; - wcscpy(RomInfo.InternalName, stdstr(InternalName).ToUTF16(stdstr::CODEPAGE_932).c_str()); - } - RomInfo.RomSize = (int32_t)f->Size; - - WriteTrace(TraceUserInterface, TraceDebug, "15"); - RomInfo.CartID[0] = *(RomData + 0x3F); - RomInfo.CartID[1] = *(RomData + 0x3E); - RomInfo.CartID[2] = '\0'; - RomInfo.Manufacturer = *(RomData + 0x38); - RomInfo.Country = *(RomData + 0x3D); - RomInfo.CRC1 = *(uint32_t *)(RomData + 0x10); - RomInfo.CRC2 = *(uint32_t *)(RomData + 0x14); - m_ZipIniFile->GetNumber(SectionName.c_str(), stdstr_f("%s-Cic", FileName.c_str()).c_str(), (ULONG)-1, (uint32_t &)RomInfo.CicChip); - WriteTrace(TraceUserInterface, TraceDebug, "16"); - FillRomExtensionInfo(&RomInfo); - - if (RomInfo.SelColor == -1) - { - RomInfo.SelColorBrush = (uint32_t)((HBRUSH)(COLOR_HIGHLIGHT + 1)); - } - else - { - RomInfo.SelColorBrush = (uint32_t)CreateSolidBrush(RomInfo.SelColor); - } - WriteTrace(TraceUserInterface, TraceDebug, "17"); - AddRomInfoToList(RomInfo, lpLastRom); - } - } - catch (...) - { - WriteTrace(TraceUserInterface, TraceError, "execpetion processing %s", (LPCSTR)SearchPath); - } - continue; - } - } while (SearchPath.FindNext()); - m_ZipIniFile->FlushChanges(); -} - -int32_t CRomBrowser::GetCicChipID(uint8_t * RomData) -{ - __int64 CRC = 0; - int32_t count; - - for (count = 0x40; count < 0x1000; count += 4) - { - CRC += *(uint32_t *)(RomData + count); - } - switch (CRC) - { - case 0x000000D0027FDF31: return CIC_NUS_6101; - case 0x000000CFFB631223: return CIC_NUS_6101; - case 0x000000D057C85244: return CIC_NUS_6102; - case 0x000000D6497E414B: return CIC_NUS_6103; - case 0x0000011A49F60E96: return CIC_NUS_6105; - case 0x000000D6D5BE5580: return CIC_NUS_6106; - case 0x000001053BC19870: return CIC_NUS_5167; //64DD CONVERSION CIC - case 0x000000D2E53EF008: return CIC_NUS_8303; //64DD IPL - default: - return CIC_UNKNOWN; - } + PostMessage(m_MainWindow, WM_COMMAND, ID_FILE_REFRESHROMLIST, 0); } void CRomBrowser::HighLightLastRom(void) @@ -844,174 +383,6 @@ void CRomBrowser::HighLightLastRom(void) } } -bool CRomBrowser::LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_t DataLen, int32_t * RomSize, FILE_FORMAT & FileFormat) -{ - uint8_t Test[4]; - - if (_strnicmp(&FileName[strlen(FileName) - 4], ".ZIP", 4) == 0) - { - int32_t len, port = 0, FoundRom; - unz_file_info info; - char zname[132]; - unzFile file; - file = unzOpen(FileName); - if (file == NULL) { return false; } - - port = unzGoToFirstFile(file); - FoundRom = false; - while (port == UNZ_OK && FoundRom == false) - { - unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0); - if (unzLocateFile(file, zname, 1) != UNZ_OK) - { - unzClose(file); - return true; - } - if (unzOpenCurrentFile(file) != UNZ_OK) - { - unzClose(file); - return true; - } - unzReadCurrentFile(file, Test, 4); - if (CN64Rom::IsValidRomImage(Test)) - { - FoundRom = true; - memcpy(Data, Test, 4); - len = unzReadCurrentFile(file, &Data[4], DataLen - 4) + 4; - - if ((int32_t)DataLen != len) - { - unzCloseCurrentFile(file); - unzClose(file); - return false; - } - *RomSize = info.uncompressed_size; - if (unzCloseCurrentFile(file) == UNZ_CRCERROR) - { - unzClose(file); - return false; - } - unzClose(file); - } - if (FoundRom == false) - { - unzCloseCurrentFile(file); - port = unzGoToNextFile(file); - } - } - if (FoundRom == false) - { - return false; - } - FileFormat = Format_Zip; - } - else - { - HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); - if (hFile == INVALID_HANDLE_VALUE) { return false; } - SetFilePointer(hFile, 0, 0, FILE_BEGIN); - - DWORD dwRead; - ReadFile(hFile, Test, 4, &dwRead, NULL); - if (!CN64Rom::IsValidRomImage(Test)) { CloseHandle(hFile); return false; } - SetFilePointer(hFile, 0, 0, FILE_BEGIN); - if (!ReadFile(hFile, Data, DataLen, &dwRead, NULL)) { CloseHandle(hFile); return false; } - *RomSize = GetFileSize(hFile, NULL); - CloseHandle(hFile); - FileFormat = Format_Uncompressed; - } - ByteSwapRomData(Data, DataLen); - return true; -} - -void CRomBrowser::ByteSwapRomData(uint8_t * Data, int32_t DataLen) -{ - int32_t count; - - switch (*((uint32_t *)&Data[0])) - { - case 0x12408037: - for (count = 0; count < DataLen; count += 4) - { - Data[count] ^= Data[count + 2]; - Data[count + 2] ^= Data[count]; - Data[count] ^= Data[count + 2]; - Data[count + 1] ^= Data[count + 3]; - Data[count + 3] ^= Data[count + 1]; - Data[count + 1] ^= Data[count + 3]; - } - break; - case 0x40072780: //64DD IPL - case 0x40123780: - for (count = 0; count < DataLen; count += 4) - { - Data[count] ^= Data[count + 3]; - Data[count + 3] ^= Data[count]; - Data[count] ^= Data[count + 3]; - Data[count + 1] ^= Data[count + 2]; - Data[count + 2] ^= Data[count + 1]; - Data[count + 1] ^= Data[count + 2]; - } - break; - case 0x80371240: break; - } -} - -void CRomBrowser::LoadRomList(void) -{ - CPath FileName(g_Settings->LoadStringVal(RomList_RomListCache)); - CFile file(FileName, CFileBase::modeRead | CFileBase::modeNoTruncate); - - if (!file.IsOpen()) - { - //if file does not exist then refresh the data - RefreshRomBrowser(); - return; - } - unsigned char md5[16]; - if (!file.Read(md5, sizeof(md5))) - { - file.Close(); - RefreshRomBrowser(); - return; - } - - //Read the size of ROM_INFO - int32_t RomInfoSize = 0; - if (!file.Read(&RomInfoSize, sizeof(RomInfoSize)) || RomInfoSize != sizeof(ROM_INFO)) - { - file.Close(); - RefreshRomBrowser(); - return; - } - - //Read the Number of entries - int32_t Entries = 0; - file.Read(&Entries, sizeof(Entries)); - - //Read Every Entry - DeallocateBrushs(); - m_RomInfo.clear(); - for (int32_t count = 0; count < Entries; count++) - { - ROM_INFO RomInfo; - file.Read(&RomInfo, RomInfoSize); - RomInfo.SelColorBrush = NULL; - - LVITEMW lvItem; - memset(&lvItem, 0, sizeof(lvItem)); - lvItem.mask = LVIF_TEXT | LVIF_PARAM; - lvItem.iItem = ListView_GetItemCount(m_hRomList); - lvItem.lParam = (LPARAM)m_RomInfo.size(); - lvItem.pszText = LPSTR_TEXTCALLBACKW; - - SendMessageW(m_hRomList, LVM_INSERTITEMW, 0, (LPARAM)&lvItem); - m_RomInfo.push_back(RomInfo); - } - AllocateBrushs(); - RomList_SortList(); -} - void CRomBrowser::MenuSetText(HMENU hMenu, int32_t MenuPos, const wchar_t * Title, char * ShortCut) { MENUITEMINFOW MenuInfo; @@ -1034,68 +405,6 @@ void CRomBrowser::MenuSetText(HMENU hMenu, int32_t MenuPos, const wchar_t * Titl SetMenuItemInfoW(hMenu, MenuPos, TRUE, &MenuInfo); } -void CRomBrowser::RefreshRomBrowser(void) -{ - DWORD ThreadID; - - if (m_RefreshThread) - { - return; - } - WriteTrace(TraceUserInterface, TraceDebug, "1"); - m_StopRefresh = false; - m_RefreshThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RefreshRomBrowserStatic, (LPVOID)this, 0, &ThreadID); - WriteTrace(TraceUserInterface, TraceDebug, "2"); -} - -void CRomBrowser::RefreshRomBrowserStatic(CRomBrowser * _this) -{ - try - { - if (_this->m_hRomList == NULL) { return; } - - //delete cache - CPath(g_Settings->LoadStringVal(RomList_RomListCache)).Delete(); - - //clear all current items - WriteTrace(TraceUserInterface, TraceDebug, "1"); - ListView_DeleteAllItems((HWND)_this->m_hRomList); - _this->DeallocateBrushs(); - _this->m_RomInfo.clear(); - WriteTrace(TraceUserInterface, TraceDebug, "2"); - InvalidateRect((HWND)_this->m_hRomList, NULL, TRUE); - Sleep(100); - WriteTrace(TraceUserInterface, TraceDebug, "3"); - - if (_this->m_WatchRomDir != g_Settings->LoadStringVal(RomList_GameDir)) - { - WriteTrace(TraceUserInterface, TraceDebug, "4"); - _this->WatchThreadStop(); - WriteTrace(TraceUserInterface, TraceDebug, "5"); - _this->WatchThreadStart(); - WriteTrace(TraceUserInterface, TraceDebug, "6"); - } - - WriteTrace(TraceUserInterface, TraceDebug, "7"); - stdstr RomDir = g_Settings->LoadStringVal(RomList_GameDir); - stdstr LastRom = UISettingsLoadStringIndex(File_RecentGameFileIndex, 0); - WriteTrace(TraceUserInterface, TraceDebug, "8"); - - strlist FileNames; - _this->FillRomList(FileNames, CPath(RomDir), "", LastRom.c_str()); - WriteTrace(TraceUserInterface, TraceDebug, "9"); - _this->SaveRomList(FileNames); - WriteTrace(TraceUserInterface, TraceDebug, "10"); - CloseHandle(_this->m_RefreshThread); - _this->m_RefreshThread = NULL; - WriteTrace(TraceUserInterface, TraceDebug, "11"); - } - catch (...) - { - WriteTrace(TraceUserInterface, TraceError, "Unhandled Exception "); - } -} - void CRomBrowser::ResetRomBrowserColomuns(void) { size_t Coloumn, index; @@ -1481,7 +790,6 @@ void CRomBrowser::RomList_OpenRom(uint32_t /*pnmh*/) if (!pRomInfo) { return; } m_StopRefresh = true; - delete g_DDRom; g_DDRom = NULL; @@ -1589,36 +897,6 @@ void CRomBrowser::RomList_SortList(void) } } -/* -* SaveRomList - save all the rom information about the current roms in the rom brower -* to a cache file, so it is quick to reload the information -*/ -void CRomBrowser::SaveRomList(strlist & FileList) -{ - MD5 ListHash = RomListHash(FileList); - - CPath FileName(g_Settings->LoadStringVal(RomList_RomListCache)); - CFile file(FileName, CFileBase::modeWrite | CFileBase::modeCreate); - file.Write(ListHash.raw_digest(), 16); - - //Write the size of ROM_INFO - int32_t RomInfoSize = sizeof(ROM_INFO); - file.Write(&RomInfoSize, sizeof(RomInfoSize)); - - //Write the Number of entries - int32_t Entries = m_RomInfo.size(); - file.Write(&Entries, sizeof(Entries)); - - //Write Every Entry - for (int32_t count = 0; count < Entries; count++) - { - file.Write(&m_RomInfo[count], RomInfoSize); - } - - //Close the file handle - file.Close(); -} - void CRomBrowser::SaveRomListColoumnInfo(void) { WriteTrace(TraceUserInterface, TraceDebug, "Start"); @@ -1823,147 +1101,3 @@ void CRomBrowser::HideRomList(void) PostMessage(m_MainWindow, WM_MAKE_FOCUS, 0, 0); } -bool CRomBrowser::RomDirNeedsRefresh(void) -{ - bool InWatchThread = (m_WatchThreadID == GetCurrentThreadId()); - - //Get Old MD5 of file names - stdstr FileName = g_Settings->LoadStringVal(RomList_RomListCache); - HANDLE hFile = CreateFile(FileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - //if file does not exist then refresh the data - return true; - } - - DWORD dwRead; - unsigned char CurrentFileMD5[16]; - ReadFile(hFile, &CurrentFileMD5, sizeof(CurrentFileMD5), &dwRead, NULL); - CloseHandle(hFile); - - //Get Current MD5 of file names - strlist FileNames; - if (!GetRomFileNames(FileNames, CPath(g_Settings->LoadStringVal(RomList_GameDir)), stdstr(""), InWatchThread)) - { - return false; - } - FileNames.sort(); - - MD5 NewMd5 = RomListHash(FileNames); - if (memcmp(NewMd5.raw_digest(), CurrentFileMD5, sizeof(CurrentFileMD5)) != 0) - { - return true; - } - return false; -} - -MD5 CRomBrowser::RomListHash(strlist & FileList) -{ - stdstr NewFileNames; - FileList.sort(); - for (strlist::iterator iter = FileList.begin(); iter != FileList.end(); iter++) - { - NewFileNames += *iter; - NewFileNames += ";"; - } - MD5 md5Hash((const unsigned char *)NewFileNames.c_str(), NewFileNames.length()); - WriteTrace(TraceUserInterface, TraceDebug, "%s - %s", md5Hash.hex_digest(), NewFileNames.c_str()); - return md5Hash; -} - -void CRomBrowser::WatchRomDirChanged(CRomBrowser * _this) -{ - try - { - WriteTrace(TraceUserInterface, TraceDebug, "1"); - _this->m_WatchRomDir = g_Settings->LoadStringVal(RomList_GameDir); - WriteTrace(TraceUserInterface, TraceDebug, "2"); - if (_this->RomDirNeedsRefresh()) - { - WriteTrace(TraceUserInterface, TraceDebug, "2a"); - PostMessage((HWND)_this->m_MainWindow, WM_COMMAND, ID_FILE_REFRESHROMLIST, 0); - } - WriteTrace(TraceUserInterface, TraceDebug, "3"); - HANDLE hChange[] = - { - _this->m_WatchStopEvent, - FindFirstChangeNotification(_this->m_WatchRomDir.c_str(), g_Settings->LoadBool(RomList_GameDirRecursive), FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE), - }; - WriteTrace(TraceUserInterface, TraceDebug, "4"); - for (;;) - { - WriteTrace(TraceUserInterface, TraceDebug, "5"); - if (WaitForMultipleObjects(sizeof(hChange) / sizeof(hChange[0]), hChange, false, INFINITE) == WAIT_OBJECT_0) - { - WriteTrace(TraceUserInterface, TraceDebug, "5a"); - FindCloseChangeNotification(hChange[1]); - return; - } - WriteTrace(TraceUserInterface, TraceDebug, "5b"); - if (_this->RomDirNeedsRefresh()) - { - PostMessage((HWND)_this->m_MainWindow, WM_COMMAND, ID_FILE_REFRESHROMLIST, 0); - } - WriteTrace(TraceUserInterface, TraceDebug, "5c"); - if (!FindNextChangeNotification(hChange[1])) - { - FindCloseChangeNotification(hChange[1]); - return; - } - WriteTrace(TraceUserInterface, TraceDebug, "5d"); - } - } - catch (...) - { - WriteTrace(TraceUserInterface, TraceError, __FUNCTION__ ": Unhandled Exception"); - } -} - -void CRomBrowser::WatchThreadStart(void) -{ - WriteTrace(TraceUserInterface, TraceDebug, "1"); - WatchThreadStop(); - WriteTrace(TraceUserInterface, TraceDebug, "2"); - if (m_WatchStopEvent == NULL) - { - m_WatchStopEvent = CreateEvent(NULL, true, false, NULL); - } - WriteTrace(TraceUserInterface, TraceDebug, "3"); - m_WatchThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WatchRomDirChanged, this, 0, &m_WatchThreadID); - WriteTrace(TraceUserInterface, TraceDebug, "4"); -} - -void CRomBrowser::WatchThreadStop(void) -{ - if (m_WatchThread == NULL) - { - return; - } - WriteTrace(TraceUserInterface, TraceDebug, "1"); - SetEvent(m_WatchStopEvent); - DWORD ExitCode = 0; - for (int32_t count = 0; count < 20; count++) - { - WriteTrace(TraceUserInterface, TraceDebug, "2"); - GetExitCodeThread(m_WatchThread, &ExitCode); - if (ExitCode != STILL_ACTIVE) - { - break; - } - Sleep(200); - } - WriteTrace(TraceUserInterface, TraceDebug, "3"); - if (ExitCode == STILL_ACTIVE) - { - WriteTrace(TraceUserInterface, TraceDebug, "3a"); - TerminateThread(m_WatchThread, 0); - } - WriteTrace(TraceUserInterface, TraceDebug, "4"); - - CloseHandle(m_WatchThread); - CloseHandle(m_WatchStopEvent); - m_WatchStopEvent = NULL; - m_WatchThread = NULL; - m_WatchThreadID = 0; - WriteTrace(TraceUserInterface, TraceDebug, "5"); -} \ No newline at end of file diff --git a/Source/Project64/UserInterface/RomList.cpp b/Source/Project64/UserInterface/RomList.cpp new file mode 100644 index 000000000..41e9a6f9a --- /dev/null +++ b/Source/Project64/UserInterface/RomList.cpp @@ -0,0 +1,861 @@ +/**************************************************************************** +* * +* Project64 - A Nintendo 64 emulator. * +* http://www.pj64-emu.com/ * +* Copyright (C) 2012 Project64. All rights reserved. * +* * +* License: * +* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * +* * +****************************************************************************/ +#include "stdafx.h" + +static const char* ROM_extensions[] = +{ + "zip", "7z", "v64", "z64", "n64", "rom", "jap", "pal", "usa", "eur", "bin", +}; + +CRomList::CRomList() : + m_RefreshThread(NULL), + m_NotesIniFile(NULL), + m_ExtIniFile(NULL), + m_ZipIniFile(NULL), + m_RomIniFile(NULL), + m_WatchThreadID(0), + m_WatchThread(NULL), + m_WatchStopEvent(NULL) +{ + if (g_Settings) + { + m_NotesIniFile = new CIniFile(g_Settings->LoadStringVal(SupportFile_Notes).c_str()); + m_ExtIniFile = new CIniFile(g_Settings->LoadStringVal(SupportFile_ExtInfo).c_str()); + m_RomIniFile = new CIniFile(g_Settings->LoadStringVal(SupportFile_RomDatabase).c_str()); + m_ZipIniFile = new CIniFile(g_Settings->LoadStringVal(RomList_7zipCache).c_str()); + } +} + +CRomList::~CRomList() +{ + WatchThreadStop(); + m_StopRefresh = true; + if (m_NotesIniFile) + { + delete m_NotesIniFile; + m_NotesIniFile = NULL; + } + if (m_ExtIniFile) + { + delete m_ExtIniFile; + m_ExtIniFile = NULL; + } + if (m_RomIniFile) + { + delete m_RomIniFile; + m_RomIniFile = NULL; + } + if (m_ZipIniFile) + { + delete m_ZipIniFile; + m_ZipIniFile = NULL; + } +} + +void CRomList::RefreshRomBrowser(void) +{ + DWORD ThreadID; + + if (m_RefreshThread) + { + return; + } + WriteTrace(TraceUserInterface, TraceDebug, "1"); + m_StopRefresh = false; + m_RefreshThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RefreshRomBrowserStatic, (LPVOID)this, 0, &ThreadID); + WriteTrace(TraceUserInterface, TraceDebug, "2"); +} + +void CRomList::RefreshRomListThread(void) +{ + //delete cache + CPath(g_Settings->LoadStringVal(RomList_RomListCache)).Delete(); + + //clear all current items + RomListReset(); + m_RomInfo.clear(); + + if (m_WatchRomDir != g_Settings->LoadStringVal(RomList_GameDir)) + { + WriteTrace(TraceUserInterface, TraceDebug, "4"); + WatchThreadStop(); + WriteTrace(TraceUserInterface, TraceDebug, "5"); + WatchThreadStart(); + WriteTrace(TraceUserInterface, TraceDebug, "6"); + } + + WriteTrace(TraceUserInterface, TraceDebug, "7"); + stdstr RomDir = g_Settings->LoadStringVal(RomList_GameDir); + stdstr LastRom = UISettingsLoadStringIndex(File_RecentGameFileIndex, 0); + WriteTrace(TraceUserInterface, TraceDebug, "8"); + + strlist FileNames; + FillRomList(FileNames, CPath(RomDir), "", LastRom.c_str()); + WriteTrace(TraceUserInterface, TraceDebug, "9"); + SaveRomList(FileNames); + WriteTrace(TraceUserInterface, TraceDebug, "10"); + CloseHandle(m_RefreshThread); + m_RefreshThread = NULL; + WriteTrace(TraceUserInterface, TraceDebug, "11"); +} + +void CRomList::AddRomToList(const char * RomLocation) +{ + ROM_INFO RomInfo; + + memset(&RomInfo, 0, sizeof(ROM_INFO)); + strncpy(RomInfo.szFullFileName, RomLocation, (sizeof(RomInfo.szFullFileName) / sizeof(RomInfo.szFullFileName[0])) - 1); + if (FillRomInfo(&RomInfo)) + { + int32_t ListPos = m_RomInfo.size(); + m_RomInfo.push_back(RomInfo); + RomAddedToList(ListPos); + } +} + +void CRomList::FillRomList(strlist & FileList, const CPath & BaseDirectory, const char * Directory, const char * lpLastRom) +{ + CPath SearchPath(BaseDirectory, "*"); + SearchPath.AppendDirectory(Directory); + + WriteTrace(TraceUserInterface, TraceDebug, "1 %s", (const char *)SearchPath); + if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES)) + { + return; + } + + do + { + uint8_t ext_ID; + int8_t new_list_entry = 0; + const uint8_t exts = sizeof(ROM_extensions) / sizeof(ROM_extensions[0]); + + WriteTrace(TraceUserInterface, TraceDebug, ": 2 %s m_StopRefresh = %d", (const char *)SearchPath, m_StopRefresh); + if (m_StopRefresh) { break; } + + if (SearchPath.IsDirectory()) + { + if (g_Settings->LoadBool(RomList_GameDirRecursive)) + { + CPath CurrentDir(Directory); + CurrentDir.AppendDirectory(SearchPath.GetLastDirectory().c_str()); + FillRomList(FileList, BaseDirectory, CurrentDir, lpLastRom); + } + continue; + } + + AddFileNameToList(FileList, Directory, SearchPath); + + stdstr Extension = stdstr(SearchPath.GetExtension()).ToLower(); + + for (ext_ID = 0; ext_ID < exts; ext_ID++) + { + if (Extension == ROM_extensions[ext_ID] && Extension != "7z") + { + new_list_entry = 1; + break; + } + } + if (new_list_entry) + { + AddRomToList(SearchPath); + continue; + } + + if (Extension == "7z") + { + try + { + C7zip ZipFile(SearchPath); + if (!ZipFile.OpenSuccess()) + { + continue; + } + char ZipFileName[260]; + stdstr_f SectionName("%s-%d", ZipFile.FileName(ZipFileName, sizeof(ZipFileName)), ZipFile.FileSize()); + SectionName.ToLower(); + + WriteTrace(TraceUserInterface, TraceDebug, "4 %s", SectionName.c_str()); + for (int32_t i = 0; i < ZipFile.NumFiles(); i++) + { + CSzFileItem * f = ZipFile.FileItem(i); + if (f->IsDir) + { + continue; + } + ROM_INFO RomInfo; + + std::wstring FileNameW = ZipFile.FileNameIndex(i); + if (FileNameW.length() == 0) + { + continue; + } + + stdstr FileName; + FileName.FromUTF16(FileNameW.c_str()); + WriteTrace(TraceUserInterface, TraceDebug, "5"); + char drive2[_MAX_DRIVE], dir2[_MAX_DIR], FileName2[MAX_PATH], ext2[_MAX_EXT]; + _splitpath(FileName.c_str(), drive2, dir2, FileName2, ext2); + + WriteTrace(TraceUserInterface, TraceDebug, ": 6 %s", ext2); + if (_stricmp(ext2, ".bin") == 0) + { + continue; + } + WriteTrace(TraceUserInterface, TraceDebug, "7"); + memset(&RomInfo, 0, sizeof(ROM_INFO)); + stdstr_f zipFileName("%s?%s", (LPCSTR)SearchPath, FileName.c_str()); + ZipFile.SetNotificationCallback((C7zip::LP7ZNOTIFICATION)NotificationCB, this); + + strncpy(RomInfo.szFullFileName, zipFileName.c_str(), sizeof(RomInfo.szFullFileName) - 1); + RomInfo.szFullFileName[sizeof(RomInfo.szFullFileName) - 1] = 0; + strcpy(RomInfo.FileName, strstr(RomInfo.szFullFileName, "?") + 1); + RomInfo.FileFormat = Format_7zip; + + WriteTrace(TraceUserInterface, TraceDebug, "8"); + char szHeader[0x90]; + if (m_ZipIniFile->GetString(SectionName.c_str(), FileName.c_str(), "", szHeader, sizeof(szHeader)) == 0) + { + uint8_t RomData[0x1000]; + if (!ZipFile.GetFile(i, RomData, sizeof(RomData))) + { + continue; + } + WriteTrace(TraceUserInterface, TraceDebug, "9"); + if (!CN64Rom::IsValidRomImage(RomData)) { continue; } + WriteTrace(TraceUserInterface, TraceDebug, "10"); + ByteSwapRomData(RomData, sizeof(RomData)); + WriteTrace(TraceUserInterface, TraceDebug, "11"); + + stdstr RomHeader; + for (int32_t x = 0; x < 0x40; x += 4) + { + RomHeader += stdstr_f("%08X", *((uint32_t *)&RomData[x])); + } + WriteTrace(TraceUserInterface, TraceDebug, "11a %s", RomHeader.c_str()); + int32_t CicChip = GetCicChipID(RomData); + + //save this info + WriteTrace(TraceUserInterface, TraceDebug, "12"); + m_ZipIniFile->SaveString(SectionName.c_str(), FileName.c_str(), RomHeader.c_str()); + m_ZipIniFile->SaveNumber(SectionName.c_str(), stdstr_f("%s-Cic", FileName.c_str()).c_str(), CicChip); + strcpy(szHeader, RomHeader.c_str()); + } + WriteTrace(TraceUserInterface, TraceDebug, "13"); + uint8_t RomData[0x40]; + + for (int32_t x = 0; x < 0x40; x += 4) + { + const size_t delimit_offset = sizeof("FFFFFFFF") - 1; + const char backup_character = szHeader[2 * x + delimit_offset]; + + szHeader[2 * x + delimit_offset] = '\0'; + *(uint32_t *)&RomData[x] = strtoul(&szHeader[2 * x], NULL, 16); + szHeader[2 * x + delimit_offset] = backup_character; + } + WriteTrace(TraceUserInterface, TraceDebug, "14"); + { + char InternalName[22]; + memcpy(InternalName, (void *)(RomData + 0x20), 20); + for (int32_t count = 0; count < 20; count += 4) + { + InternalName[count] ^= InternalName[count + 3]; + InternalName[count + 3] ^= InternalName[count]; + InternalName[count] ^= InternalName[count + 3]; + InternalName[count + 1] ^= InternalName[count + 2]; + InternalName[count + 2] ^= InternalName[count + 1]; + InternalName[count + 1] ^= InternalName[count + 2]; + } + InternalName[20] = '\0'; + wcscpy(RomInfo.InternalName, stdstr(InternalName).ToUTF16(stdstr::CODEPAGE_932).c_str()); + } + RomInfo.RomSize = (int32_t)f->Size; + + WriteTrace(TraceUserInterface, TraceDebug, "15"); + RomInfo.CartID[0] = *(RomData + 0x3F); + RomInfo.CartID[1] = *(RomData + 0x3E); + RomInfo.CartID[2] = '\0'; + RomInfo.Manufacturer = *(RomData + 0x38); + RomInfo.Country = *(RomData + 0x3D); + RomInfo.CRC1 = *(uint32_t *)(RomData + 0x10); + RomInfo.CRC2 = *(uint32_t *)(RomData + 0x14); + m_ZipIniFile->GetNumber(SectionName.c_str(), stdstr_f("%s-Cic", FileName.c_str()).c_str(), (ULONG)-1, (uint32_t &)RomInfo.CicChip); + WriteTrace(TraceUserInterface, TraceDebug, "16"); + FillRomExtensionInfo(&RomInfo); + + if (RomInfo.SelColor == -1) + { + RomInfo.SelColorBrush = (uint32_t)((HBRUSH)(COLOR_HIGHLIGHT + 1)); + } + else + { + RomInfo.SelColorBrush = (uint32_t)CreateSolidBrush(RomInfo.SelColor); + } + WriteTrace(TraceUserInterface, TraceDebug, "17"); + int32_t ListPos = m_RomInfo.size(); + m_RomInfo.push_back(RomInfo); + RomAddedToList(ListPos); + } + } + catch (...) + { + WriteTrace(TraceUserInterface, TraceError, "execpetion processing %s", (LPCSTR)SearchPath); + } + continue; + } + } while (SearchPath.FindNext()); + m_ZipIniFile->FlushChanges(); +} + +void CRomList::NotificationCB(const char * Status, CRomList * /*_this*/) +{ + g_Notify->DisplayMessage(5, Status); +} + +void CRomList::RefreshRomBrowserStatic(CRomList * _this) +{ + _this->RefreshRomListThread(); +} + +bool CRomList::LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_t DataLen, int32_t * RomSize, FILE_FORMAT & FileFormat) +{ + uint8_t Test[4]; + + if (_strnicmp(&FileName[strlen(FileName) - 4], ".ZIP", 4) == 0) + { + int32_t len, port = 0, FoundRom; + unz_file_info info; + char zname[132]; + unzFile file; + file = unzOpen(FileName); + if (file == NULL) { return false; } + + port = unzGoToFirstFile(file); + FoundRom = false; + while (port == UNZ_OK && FoundRom == false) + { + unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0); + if (unzLocateFile(file, zname, 1) != UNZ_OK) + { + unzClose(file); + return true; + } + if (unzOpenCurrentFile(file) != UNZ_OK) + { + unzClose(file); + return true; + } + unzReadCurrentFile(file, Test, 4); + if (CN64Rom::IsValidRomImage(Test)) + { + FoundRom = true; + memcpy(Data, Test, 4); + len = unzReadCurrentFile(file, &Data[4], DataLen - 4) + 4; + + if ((int32_t)DataLen != len) + { + unzCloseCurrentFile(file); + unzClose(file); + return false; + } + *RomSize = info.uncompressed_size; + if (unzCloseCurrentFile(file) == UNZ_CRCERROR) + { + unzClose(file); + return false; + } + unzClose(file); + } + if (FoundRom == false) + { + unzCloseCurrentFile(file); + port = unzGoToNextFile(file); + } + } + if (FoundRom == false) + { + return false; + } + FileFormat = Format_Zip; + } + else + { + HANDLE hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { return false; } + SetFilePointer(hFile, 0, 0, FILE_BEGIN); + + DWORD dwRead; + ReadFile(hFile, Test, 4, &dwRead, NULL); + if (!CN64Rom::IsValidRomImage(Test)) { CloseHandle(hFile); return false; } + SetFilePointer(hFile, 0, 0, FILE_BEGIN); + if (!ReadFile(hFile, Data, DataLen, &dwRead, NULL)) { CloseHandle(hFile); return false; } + *RomSize = GetFileSize(hFile, NULL); + CloseHandle(hFile); + FileFormat = Format_Uncompressed; + } + ByteSwapRomData(Data, DataLen); + return true; +} + +bool CRomList::FillRomInfo(ROM_INFO * pRomInfo) +{ + int32_t count; + uint8_t RomData[0x1000]; + + if (!LoadDataFromRomFile(pRomInfo->szFullFileName, RomData, sizeof(RomData), &pRomInfo->RomSize, pRomInfo->FileFormat)) + { + return false; + } + else + { + if (strstr(pRomInfo->szFullFileName, "?") != NULL) + { + strcpy(pRomInfo->FileName, strstr(pRomInfo->szFullFileName, "?") + 1); + } + else + { + strncpy(pRomInfo->FileName, CPath(pRomInfo->szFullFileName).GetNameExtension().c_str(), sizeof(pRomInfo->FileName) / sizeof(pRomInfo->FileName[0])); + } + char InternalName[22]; + memcpy(InternalName, (void *)(RomData + 0x20), 20); + for (count = 0; count < 20; count += 4) + { + InternalName[count] ^= InternalName[count + 3]; + InternalName[count + 3] ^= InternalName[count]; + InternalName[count] ^= InternalName[count + 3]; + InternalName[count + 1] ^= InternalName[count + 2]; + InternalName[count + 2] ^= InternalName[count + 1]; + InternalName[count + 1] ^= InternalName[count + 2]; + } + InternalName[20] = '\0'; + wcscpy(pRomInfo->InternalName, stdstr(InternalName).ToUTF16(stdstr::CODEPAGE_932).c_str()); + pRomInfo->CartID[0] = *(RomData + 0x3F); + pRomInfo->CartID[1] = *(RomData + 0x3E); + pRomInfo->CartID[2] = '\0'; + pRomInfo->Manufacturer = *(RomData + 0x38); + pRomInfo->Country = *(RomData + 0x3D); + pRomInfo->CRC1 = *(uint32_t *)(RomData + 0x10); + pRomInfo->CRC2 = *(uint32_t *)(RomData + 0x14); + pRomInfo->CicChip = GetCicChipID(RomData); + + FillRomExtensionInfo(pRomInfo); + + if (pRomInfo->SelColor == -1) + { + pRomInfo->SelColorBrush = (uint32_t)((HBRUSH)(COLOR_HIGHLIGHT + 1)); + } + else + { + pRomInfo->SelColorBrush = (uint32_t)CreateSolidBrush(pRomInfo->SelColor); + } + + return true; + } +} + +void CRomList::FillRomExtensionInfo(ROM_INFO * pRomInfo) +{ + //Initialize the structure + pRomInfo->UserNotes[0] = 0; + pRomInfo->Developer[0] = 0; + pRomInfo->ReleaseDate[0] = 0; + pRomInfo->Genre[0] = 0; + pRomInfo->Players = 1; + pRomInfo->CoreNotes[0] = 0; + pRomInfo->PluginNotes[0] = 0; + wcscpy(pRomInfo->GoodName, L"#340#"); + wcscpy(pRomInfo->Status, L"Unknown"); + + //Get File Identifier + char Identifier[100]; + sprintf(Identifier, "%08X-%08X-C:%X", pRomInfo->CRC1, pRomInfo->CRC2, pRomInfo->Country); + + //Rom Notes + wcsncpy(pRomInfo->UserNotes, m_NotesIniFile->GetString(Identifier, "Note", "").ToUTF16().c_str(), sizeof(pRomInfo->UserNotes) / sizeof(wchar_t)); + + //Rom Extension info + wcsncpy(pRomInfo->Developer, m_ExtIniFile->GetString(Identifier, "Developer", "").ToUTF16().c_str(), sizeof(pRomInfo->Developer) / sizeof(wchar_t)); + wcsncpy(pRomInfo->ReleaseDate, m_ExtIniFile->GetString(Identifier, "ReleaseDate", "").ToUTF16().c_str(), sizeof(pRomInfo->ReleaseDate) / sizeof(wchar_t)); + wcsncpy(pRomInfo->Genre, m_ExtIniFile->GetString(Identifier, "Genre", "").ToUTF16().c_str(), sizeof(pRomInfo->Genre) / sizeof(wchar_t)); + m_ExtIniFile->GetNumber(Identifier, "Players", 1, (uint32_t &)pRomInfo->Players); + wcsncpy(pRomInfo->ForceFeedback, m_ExtIniFile->GetString(Identifier, "ForceFeedback", "unknown").ToUTF16().c_str(), sizeof(pRomInfo->ForceFeedback) / sizeof(wchar_t)); + + //Rom Settings + wcsncpy(pRomInfo->GoodName, m_RomIniFile->GetString(Identifier, "Good Name", stdstr().FromUTF16(pRomInfo->GoodName).c_str()).ToUTF16().c_str(), sizeof(pRomInfo->GoodName) / sizeof(wchar_t)); + wcsncpy(pRomInfo->Status, m_RomIniFile->GetString(Identifier, "Status", stdstr().FromUTF16(pRomInfo->Status).c_str()).ToUTF16().c_str(), sizeof(pRomInfo->Status) / sizeof(wchar_t)); + wcsncpy(pRomInfo->CoreNotes, m_RomIniFile->GetString(Identifier, "Core Note", "").ToUTF16().c_str(), sizeof(pRomInfo->CoreNotes) / sizeof(wchar_t)); + wcsncpy(pRomInfo->PluginNotes, m_RomIniFile->GetString(Identifier, "Plugin Note", "").ToUTF16().c_str(), sizeof(pRomInfo->PluginNotes) / sizeof(wchar_t)); + + //Get the text color + stdstr String = m_RomIniFile->GetString("Rom Status", stdstr().FromUTF16(pRomInfo->Status).c_str(), "000000"); + pRomInfo->TextColor = (std::strtoul(String.c_str(), 0, 16) & 0xFFFFFF); + pRomInfo->TextColor = (pRomInfo->TextColor & 0x00FF00) | ((pRomInfo->TextColor >> 0x10) & 0xFF) | ((pRomInfo->TextColor & 0xFF) << 0x10); + + //Get the selected color + String.Format("%ws.Sel", pRomInfo->Status); + String = m_RomIniFile->GetString("Rom Status", String.c_str(), "FFFFFFFF"); + uint32_t selcol = std::strtoul(String.c_str(), NULL, 16); + if (selcol & 0x80000000) + { + pRomInfo->SelColor = -1; + } + else + { + selcol = (selcol & 0x00FF00) | ((selcol >> 0x10) & 0xFF) | ((selcol & 0xFF) << 0x10); + pRomInfo->SelColor = selcol; + } + + //Get the selected text color + String.Format("%ws.Seltext", pRomInfo->Status); + String = m_RomIniFile->GetString("Rom Status", String.c_str(), "FFFFFF"); + pRomInfo->SelTextColor = (std::strtoul(String.c_str(), 0, 16) & 0xFFFFFF); + pRomInfo->SelTextColor = (pRomInfo->SelTextColor & 0x00FF00) | ((pRomInfo->SelTextColor >> 0x10) & 0xFF) | ((pRomInfo->SelTextColor & 0xFF) << 0x10); +} + +void CRomList::ByteSwapRomData(uint8_t * Data, int32_t DataLen) +{ + int32_t count; + + switch (*((uint32_t *)&Data[0])) + { + case 0x12408037: + for (count = 0; count < DataLen; count += 4) + { + Data[count] ^= Data[count + 2]; + Data[count + 2] ^= Data[count]; + Data[count] ^= Data[count + 2]; + Data[count + 1] ^= Data[count + 3]; + Data[count + 3] ^= Data[count + 1]; + Data[count + 1] ^= Data[count + 3]; + } + break; + case 0x40072780: //64DD IPL + case 0x40123780: + for (count = 0; count < DataLen; count += 4) + { + Data[count] ^= Data[count + 3]; + Data[count + 3] ^= Data[count]; + Data[count] ^= Data[count + 3]; + Data[count + 1] ^= Data[count + 2]; + Data[count + 2] ^= Data[count + 1]; + Data[count + 1] ^= Data[count + 2]; + } + break; + case 0x80371240: break; + } +} + +void CRomList::LoadRomList(void) +{ + CPath FileName(g_Settings->LoadStringVal(RomList_RomListCache)); + CFile file(FileName, CFileBase::modeRead | CFileBase::modeNoTruncate); + + if (!file.IsOpen()) + { + //if file does not exist then refresh the data + RefreshRomBrowser(); + return; + } + unsigned char md5[16]; + if (!file.Read(md5, sizeof(md5))) + { + file.Close(); + RefreshRomBrowser(); + return; + } + + //Read the size of ROM_INFO + int32_t RomInfoSize = 0; + if (!file.Read(&RomInfoSize, sizeof(RomInfoSize)) || RomInfoSize != sizeof(ROM_INFO)) + { + file.Close(); + RefreshRomBrowser(); + return; + } + + //Read the Number of entries + int32_t Entries = 0; + file.Read(&Entries, sizeof(Entries)); + + //Read Every Entry + m_RomInfo.clear(); + RomListReset(); + for (int32_t count = 0; count < Entries; count++) + { + ROM_INFO RomInfo; + file.Read(&RomInfo, RomInfoSize); + int32_t ListPos = m_RomInfo.size(); + m_RomInfo.push_back(RomInfo); + RomAddedToList(ListPos); + } + RomListLoaded(); +} + +/* +* SaveRomList - save all the rom information about the current roms in the rom brower +* to a cache file, so it is quick to reload the information +*/ +void CRomList::SaveRomList(strlist & FileList) +{ + MD5 ListHash = RomListHash(FileList); + + CPath FileName(g_Settings->LoadStringVal(RomList_RomListCache)); + CFile file(FileName, CFileBase::modeWrite | CFileBase::modeCreate); + file.Write(ListHash.raw_digest(), 16); + + //Write the size of ROM_INFO + int32_t RomInfoSize = sizeof(ROM_INFO); + file.Write(&RomInfoSize, sizeof(RomInfoSize)); + + //Write the Number of entries + int32_t Entries = m_RomInfo.size(); + file.Write(&Entries, sizeof(Entries)); + + //Write Every Entry + for (int32_t count = 0; count < Entries; count++) + { + file.Write(&m_RomInfo[count], RomInfoSize); + } + + //Close the file handle + file.Close(); +} + +void CRomList::WatchRomDirChanged(CRomList * _this) +{ + try + { + WriteTrace(TraceUserInterface, TraceDebug, "1"); + _this->m_WatchRomDir = g_Settings->LoadStringVal(RomList_GameDir); + WriteTrace(TraceUserInterface, TraceDebug, "2"); + if (_this->RomDirNeedsRefresh()) + { + WriteTrace(TraceUserInterface, TraceDebug, "2a"); + _this->RomDirChanged(); + } + WriteTrace(TraceUserInterface, TraceDebug, "3"); + HANDLE hChange[] = + { + _this->m_WatchStopEvent, + FindFirstChangeNotification(_this->m_WatchRomDir.c_str(), g_Settings->LoadBool(RomList_GameDirRecursive), FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE), + }; + WriteTrace(TraceUserInterface, TraceDebug, "4"); + for (;;) + { + WriteTrace(TraceUserInterface, TraceDebug, "5"); + if (WaitForMultipleObjects(sizeof(hChange) / sizeof(hChange[0]), hChange, false, INFINITE) == WAIT_OBJECT_0) + { + WriteTrace(TraceUserInterface, TraceDebug, "5a"); + FindCloseChangeNotification(hChange[1]); + return; + } + WriteTrace(TraceUserInterface, TraceDebug, "5b"); + if (_this->RomDirNeedsRefresh()) + { + _this->RomDirChanged(); + } + WriteTrace(TraceUserInterface, TraceDebug, "5c"); + if (!FindNextChangeNotification(hChange[1])) + { + FindCloseChangeNotification(hChange[1]); + return; + } + WriteTrace(TraceUserInterface, TraceDebug, "5d"); + } + } + catch (...) + { + WriteTrace(TraceUserInterface, TraceError, __FUNCTION__ ": Unhandled Exception"); + } +} + +bool CRomList::RomDirNeedsRefresh(void) +{ + bool InWatchThread = (m_WatchThreadID == GetCurrentThreadId()); + + //Get Old MD5 of file names + stdstr FileName = g_Settings->LoadStringVal(RomList_RomListCache); + HANDLE hFile = CreateFile(FileName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + //if file does not exist then refresh the data + return true; + } + + DWORD dwRead; + unsigned char CurrentFileMD5[16]; + ReadFile(hFile, &CurrentFileMD5, sizeof(CurrentFileMD5), &dwRead, NULL); + CloseHandle(hFile); + + //Get Current MD5 of file names + strlist FileNames; + if (!GetRomFileNames(FileNames, CPath(g_Settings->LoadStringVal(RomList_GameDir)), stdstr(""), InWatchThread)) + { + return false; + } + FileNames.sort(); + + MD5 NewMd5 = RomListHash(FileNames); + if (memcmp(NewMd5.raw_digest(), CurrentFileMD5, sizeof(CurrentFileMD5)) != 0) + { + return true; + } + return false; +} + +void CRomList::WatchThreadStart(void) +{ + WriteTrace(TraceUserInterface, TraceDebug, "1"); + WatchThreadStop(); + WriteTrace(TraceUserInterface, TraceDebug, "2"); + if (m_WatchStopEvent == NULL) + { + m_WatchStopEvent = CreateEvent(NULL, true, false, NULL); + } + WriteTrace(TraceUserInterface, TraceDebug, "3"); + m_WatchThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WatchRomDirChanged, this, 0, &m_WatchThreadID); + WriteTrace(TraceUserInterface, TraceDebug, "4"); +} + +void CRomList::WatchThreadStop(void) +{ + if (m_WatchThread == NULL) + { + return; + } + WriteTrace(TraceUserInterface, TraceDebug, "1"); + SetEvent(m_WatchStopEvent); + DWORD ExitCode = 0; + for (int32_t count = 0; count < 20; count++) + { + WriteTrace(TraceUserInterface, TraceDebug, "2"); + GetExitCodeThread(m_WatchThread, &ExitCode); + if (ExitCode != STILL_ACTIVE) + { + break; + } + Sleep(200); + } + WriteTrace(TraceUserInterface, TraceDebug, "3"); + if (ExitCode == STILL_ACTIVE) + { + WriteTrace(TraceUserInterface, TraceDebug, "3a"); + TerminateThread(m_WatchThread, 0); + } + WriteTrace(TraceUserInterface, TraceDebug, "4"); + + CloseHandle(m_WatchThread); + CloseHandle(m_WatchStopEvent); + m_WatchStopEvent = NULL; + m_WatchThread = NULL; + m_WatchThreadID = 0; + WriteTrace(TraceUserInterface, TraceDebug, "5"); +} + +MD5 CRomList::RomListHash(strlist & FileList) +{ + stdstr NewFileNames; + FileList.sort(); + for (strlist::iterator iter = FileList.begin(); iter != FileList.end(); iter++) + { + NewFileNames += *iter; + NewFileNames += ";"; + } + MD5 md5Hash((const unsigned char *)NewFileNames.c_str(), NewFileNames.length()); + WriteTrace(TraceUserInterface, TraceDebug, "%s - %s", md5Hash.hex_digest(), NewFileNames.c_str()); + return md5Hash; +} + +void CRomList::AddFileNameToList(strlist & FileList, const stdstr & Directory, CPath & File) +{ + uint8_t i; + + if (FileList.size() > 3000) + { + return; + } + + stdstr Drive, Dir, Name, Extension; + File.GetComponents(NULL, &Dir, &Name, &Extension); + Extension.ToLower(); + for (i = 0; i < sizeof(ROM_extensions) / sizeof(ROM_extensions[0]); i++) + { + if (Extension == ROM_extensions[i]) + { + stdstr FileName = Directory + Name + Extension; + FileName.ToLower(); + FileList.push_back(FileName); + break; + } + } +} + +bool CRomList::GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread) +{ + if (!BaseDirectory.DirectoryExists()) + { + return false; + } + CPath SearchPath(BaseDirectory, "*.*"); + SearchPath.AppendDirectory(Directory.c_str()); + + if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES)) + { + return false; + } + + do + { + if (InWatchThread && WaitForSingleObject(m_WatchStopEvent, 0) != WAIT_TIMEOUT) + { + return false; + } + + if (SearchPath.IsDirectory()) + { + if (g_Settings->LoadBool(RomList_GameDirRecursive)) + { + CPath CurrentDir(Directory); + CurrentDir.AppendDirectory(SearchPath.GetLastDirectory().c_str()); + GetRomFileNames(FileList, BaseDirectory, CurrentDir, InWatchThread); + } + } + else + { + AddFileNameToList(FileList, Directory, SearchPath); + } + } while (SearchPath.FindNext()); + return true; +} + +int32_t CRomList::GetCicChipID(uint8_t * RomData) +{ + __int64 CRC = 0; + int32_t count; + + for (count = 0x40; count < 0x1000; count += 4) + { + CRC += *(uint32_t *)(RomData + count); + } + switch (CRC) + { + case 0x000000D0027FDF31: return CIC_NUS_6101; + case 0x000000CFFB631223: return CIC_NUS_6101; + case 0x000000D057C85244: return CIC_NUS_6102; + case 0x000000D6497E414B: return CIC_NUS_6103; + case 0x0000011A49F60E96: return CIC_NUS_6105; + case 0x000000D6D5BE5580: return CIC_NUS_6106; + case 0x000001053BC19870: return CIC_NUS_5167; //64DD CONVERSION CIC + case 0x000000D2E53EF008: return CIC_NUS_8303; //64DD IPL + default: + return CIC_UNKNOWN; + } +} diff --git a/Source/Project64/UserInterface/RomList.h b/Source/Project64/UserInterface/RomList.h new file mode 100644 index 000000000..0d49ce523 --- /dev/null +++ b/Source/Project64/UserInterface/RomList.h @@ -0,0 +1,101 @@ +/**************************************************************************** +* * +* Project64 - A Nintendo 64 emulator. * +* http://www.pj64-emu.com/ * +* Copyright (C) 2012 Project64. All rights reserved. * +* * +* License: * +* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * +* * +****************************************************************************/ +#pragma once + +class CRomList +{ +public: + enum FILE_FORMAT + { + Format_Uncompressed, + Format_Zip, + Format_7zip, + }; + + struct ROM_INFO + { + char szFullFileName[300]; + FILE_FORMAT FileFormat; + wchar_t Status[60]; + char FileName[200]; + wchar_t InternalName[22]; + wchar_t GoodName[200]; + wchar_t CartID[3]; + wchar_t PluginNotes[250]; + wchar_t CoreNotes[250]; + wchar_t UserNotes[250]; + wchar_t Developer[30]; + wchar_t ReleaseDate[30]; + wchar_t Genre[15]; + int32_t Players; + uint32_t TextColor; + int32_t SelColor; + uint32_t SelTextColor; + uint32_t SelColorBrush; + int32_t RomSize; + uint8_t Manufacturer; + uint8_t Country; + uint32_t CRC1; + uint32_t CRC2; + int32_t CicChip; + wchar_t ForceFeedback[15]; + }; + + CRomList(); + virtual ~CRomList(); + + void RefreshRomBrowser(void); + void LoadRomList(void); + +protected: + typedef std::vector ROMINFO_LIST; + virtual void RomListReset(void) {} + virtual void RomAddedToList(int32_t /*ListPos*/) {} + virtual void RomListLoaded(void) {} + virtual void RomDirChanged(void) {} + + void WatchThreadStart(void); + void WatchThreadStop(void); + + ROMINFO_LIST m_RomInfo; + bool m_StopRefresh; + +private: + void AddRomToList(const char * RomLocation); + void FillRomList(strlist & FileList, const CPath & BaseDirectory, const char * Directory, const char * lpLastRom); + bool FillRomInfo(ROM_INFO * pRomInfo); + void FillRomExtensionInfo(ROM_INFO * pRomInfo); + bool LoadDataFromRomFile(const char * FileName, uint8_t * Data, int32_t DataLen, int32_t * RomSize, FILE_FORMAT & FileFormat); + void AddFileNameToList(strlist & FileList, const stdstr & Directory, CPath & File); + void SaveRomList(strlist & FileList); + void RefreshRomListThread(void); + bool GetRomFileNames(strlist & FileList, const CPath & BaseDirectory, const std::string & Directory, bool InWatchThread); + MD5 RomListHash(strlist & FileList); + + //Watch Directory Changed function + HANDLE m_WatchThread, m_WatchStopEvent; + DWORD m_WatchThreadID; + bool RomDirNeedsRefresh(void); // Called from watch thread + + static void NotificationCB(const char * Status, CRomList * _this); + static void WatchRomDirChanged(CRomList * _this); + static void RefreshRomBrowserStatic(CRomList * _this); + static void ByteSwapRomData(uint8_t * Data, int DataLen); + static int32_t GetCicChipID(uint8_t * RomData); + + CIniFile * m_NotesIniFile; + CIniFile * m_ExtIniFile; + CIniFile * m_RomIniFile; + CIniFile * m_ZipIniFile; + HANDLE m_RefreshThread; + stdstr m_WatchRomDir; + +};