2016-04-14 09:35:08 +00:00
|
|
|
/****************************************************************************
|
|
|
|
* *
|
|
|
|
* 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"
|
2016-04-16 09:55:32 +00:00
|
|
|
#include "RomList.h"
|
|
|
|
#include <Project64-core/3rdParty/zip.h>
|
|
|
|
#include <Project64-core/N64System/N64RomClass.h>
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <Project64-core/3rdParty/7zip.h>
|
|
|
|
#endif
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
static const char* ROM_extensions[] =
|
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
"7z",
|
|
|
|
#endif
|
|
|
|
"zip",
|
|
|
|
"v64",
|
|
|
|
"z64",
|
|
|
|
"n64",
|
|
|
|
"rom",
|
|
|
|
"jap",
|
|
|
|
"pal",
|
|
|
|
"usa",
|
|
|
|
"eur",
|
|
|
|
"bin",
|
2016-04-14 09:35:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
CRomList::CRomList() :
|
2016-04-18 06:57:49 +00:00
|
|
|
m_RefreshThread((CThread::CTHREAD_START_ROUTINE)RefreshRomListStatic),
|
2016-04-15 23:06:57 +00:00
|
|
|
m_StopRefresh(false),
|
2016-04-15 22:56:10 +00:00
|
|
|
m_GameDir(g_Settings->LoadStringVal(RomList_GameDir).c_str()),
|
2016-04-14 09:35:08 +00:00
|
|
|
m_NotesIniFile(NULL),
|
|
|
|
m_ExtIniFile(NULL),
|
2016-04-14 22:29:45 +00:00
|
|
|
#ifdef _WIN32
|
2016-04-14 09:35:08 +00:00
|
|
|
m_ZipIniFile(NULL),
|
2016-04-14 22:29:45 +00:00
|
|
|
#endif
|
2016-04-15 20:58:31 +00:00
|
|
|
m_RomIniFile(NULL)
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-15 23:06:57 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Start");
|
2016-04-14 09:35:08 +00:00
|
|
|
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());
|
2016-04-14 22:29:45 +00:00
|
|
|
#ifdef _WIN32
|
2016-04-14 09:35:08 +00:00
|
|
|
m_ZipIniFile = new CIniFile(g_Settings->LoadStringVal(RomList_7zipCache).c_str());
|
2016-04-14 22:29:45 +00:00
|
|
|
#endif
|
2016-04-15 23:06:57 +00:00
|
|
|
g_Settings->RegisterChangeCB(RomList_GameDir, this, (CSettings::SettingChangedFunc)RefreshSettings);
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
2016-04-15 23:06:57 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Done");
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CRomList::~CRomList()
|
|
|
|
{
|
2016-04-15 23:06:57 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Start");
|
2016-04-14 09:35:08 +00:00
|
|
|
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;
|
|
|
|
}
|
2016-04-14 22:29:45 +00:00
|
|
|
#ifdef _WIN32
|
2016-04-14 09:35:08 +00:00
|
|
|
if (m_ZipIniFile)
|
|
|
|
{
|
|
|
|
delete m_ZipIniFile;
|
|
|
|
m_ZipIniFile = NULL;
|
|
|
|
}
|
2016-04-14 22:29:45 +00:00
|
|
|
#endif
|
2016-04-15 23:06:57 +00:00
|
|
|
if (g_Settings)
|
|
|
|
{
|
|
|
|
g_Settings->UnregisterChangeCB(RomList_GameDir, this, (CSettings::SettingChangedFunc)RefreshSettings);
|
|
|
|
}
|
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Done");
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
|
2016-04-14 22:07:34 +00:00
|
|
|
void CRomList::RefreshRomList(void)
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-18 06:57:49 +00:00
|
|
|
if (m_RefreshThread.isRunning())
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-18 06:57:49 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "already refreshing, ignoring");
|
2016-04-14 09:35:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-04-15 23:06:57 +00:00
|
|
|
WriteTrace(TraceRomList, TraceDebug, "Starting thread");
|
2016-04-14 09:35:08 +00:00
|
|
|
m_StopRefresh = false;
|
2016-04-18 06:57:49 +00:00
|
|
|
m_RefreshThread.Start((void *)this);
|
2016-04-15 23:06:57 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Done");
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRomList::RefreshRomListThread(void)
|
|
|
|
{
|
2016-04-15 22:56:10 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Start");
|
2016-04-14 09:35:08 +00:00
|
|
|
//delete cache
|
|
|
|
CPath(g_Settings->LoadStringVal(RomList_RomListCache)).Delete();
|
2016-04-15 22:56:10 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Cache Deleted");
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
//clear all current items
|
|
|
|
RomListReset();
|
|
|
|
m_RomInfo.clear();
|
|
|
|
|
|
|
|
strlist FileNames;
|
2016-04-15 22:56:10 +00:00
|
|
|
FillRomList(FileNames, "");
|
|
|
|
RomListLoaded();
|
2016-04-14 09:35:08 +00:00
|
|
|
SaveRomList(FileNames);
|
2016-04-15 23:06:57 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Done");
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRomList::AddRomToList(const char * RomLocation)
|
|
|
|
{
|
2016-04-15 23:06:57 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Start (RomLocation: \"%s\")",RomLocation);
|
|
|
|
ROM_INFO RomInfo = { 0 };
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2016-04-15 23:06:57 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Failed to fill rom information, ignoring");
|
|
|
|
}
|
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Done");
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
|
2016-04-15 22:56:10 +00:00
|
|
|
void CRomList::FillRomList(strlist & FileList, const char * Directory)
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-15 22:56:10 +00:00
|
|
|
WriteTrace(TraceRomList, TraceDebug, "Start (m_GameDir = %s, Directory: %s)",(const char *)m_GameDir,Directory);
|
|
|
|
CPath SearchPath((const char *)m_GameDir, "*");
|
2016-04-14 09:35:08 +00:00
|
|
|
SearchPath.AppendDirectory(Directory);
|
|
|
|
|
2016-04-14 12:18:21 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "SearchPath: %s", (const char *)SearchPath);
|
2016-04-14 09:35:08 +00:00
|
|
|
if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES))
|
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "No files found");
|
|
|
|
WriteTrace(TraceRomList, TraceDebug, "Done (Directory: %s)",Directory);
|
2016-04-14 09:35:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Found: \"%s\" m_StopRefresh = %s", (const char *)SearchPath, m_StopRefresh ? "true" : "false");
|
|
|
|
if (m_StopRefresh)
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "stop refresh set, stopping");
|
|
|
|
break;
|
|
|
|
}
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
if (SearchPath.IsDirectory())
|
|
|
|
{
|
|
|
|
if (g_Settings->LoadBool(RomList_GameDirRecursive))
|
|
|
|
{
|
|
|
|
CPath CurrentDir(Directory);
|
|
|
|
CurrentDir.AppendDirectory(SearchPath.GetLastDirectory().c_str());
|
2016-04-15 22:56:10 +00:00
|
|
|
FillRomList(FileList, CurrentDir);
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
AddFileNameToList(FileList, Directory, SearchPath);
|
|
|
|
|
|
|
|
stdstr Extension = stdstr(SearchPath.GetExtension()).ToLower();
|
2016-04-14 12:18:21 +00:00
|
|
|
for (uint8_t i = 0; i < sizeof(ROM_extensions) / sizeof(ROM_extensions[0]); i++)
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
if (Extension != ROM_extensions[i])
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
continue;
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
2016-04-14 12:18:21 +00:00
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "File has matching extension: \"%s\"", ROM_extensions[i]);
|
|
|
|
if (Extension != "7z")
|
|
|
|
{
|
|
|
|
AddRomToList(SearchPath);
|
|
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WriteTrace(TraceRomList, TraceVerbose, "Looking at contents of 7z file");
|
|
|
|
try
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
C7zip ZipFile(SearchPath);
|
|
|
|
if (!ZipFile.OpenSuccess())
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2016-04-14 12:18:21 +00:00
|
|
|
char ZipFileName[260];
|
|
|
|
stdstr_f SectionName("%s-%d", ZipFile.FileName(ZipFileName, sizeof(ZipFileName)), ZipFile.FileSize());
|
|
|
|
SectionName.ToLower();
|
2016-04-14 09:35:08 +00:00
|
|
|
|
2016-04-14 12:18:21 +00:00
|
|
|
WriteTrace(TraceUserInterface, TraceDebug, "4 %s", SectionName.c_str());
|
|
|
|
for (int32_t i = 0; i < ZipFile.NumFiles(); i++)
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
CSzFileItem * f = ZipFile.FileItem(i);
|
|
|
|
if (f->IsDir)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ROM_INFO RomInfo;
|
2016-04-14 09:35:08 +00:00
|
|
|
|
2016-04-14 12:18:21 +00:00
|
|
|
std::wstring FileNameW = ZipFile.FileNameIndex(i);
|
|
|
|
if (FileNameW.length() == 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2016-04-14 09:35:08 +00:00
|
|
|
|
2016-04-14 12:18:21 +00:00
|
|
|
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)
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2016-04-14 12:18:21 +00:00
|
|
|
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());
|
2016-04-14 22:38:02 +00:00
|
|
|
int32_t CicChip = CN64Rom::GetCicChipID(RomData);
|
2016-04-14 12:18:21 +00:00
|
|
|
|
|
|
|
//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];
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
for (int32_t x = 0; x < 0x40; x += 4)
|
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
const size_t delimit_offset = sizeof("FFFFFFFF") - 1;
|
|
|
|
const char backup_character = szHeader[2 * x + delimit_offset];
|
2016-04-14 09:35:08 +00:00
|
|
|
|
2016-04-14 12:18:21 +00:00
|
|
|
szHeader[2 * x + delimit_offset] = '\0';
|
|
|
|
*(uint32_t *)&RomData[x] = strtoul(&szHeader[2 * x], NULL, 16);
|
|
|
|
szHeader[2 * x + delimit_offset] = backup_character;
|
|
|
|
}
|
2016-04-14 09:35:08 +00:00
|
|
|
|
2016-04-14 12:18:21 +00:00
|
|
|
WriteTrace(TraceUserInterface, TraceDebug, "14");
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
2016-04-14 12:18:21 +00:00
|
|
|
char InternalName[22];
|
|
|
|
memcpy(InternalName, (void *)(RomData + 0x20), 20);
|
2016-04-15 23:17:37 +00:00
|
|
|
CN64Rom::CleanRomName(InternalName);
|
2016-04-16 09:55:32 +00:00
|
|
|
strcpy(RomInfo.InternalName, InternalName);
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
2016-04-14 12:18:21 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
WriteTrace(TraceUserInterface, TraceDebug, "17");
|
|
|
|
int32_t ListPos = m_RomInfo.size();
|
|
|
|
m_RomInfo.push_back(RomInfo);
|
|
|
|
RomAddedToList(ListPos);
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
2016-04-14 12:18:21 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
WriteTrace(TraceUserInterface, TraceError, "execpetion processing %s", (LPCSTR)SearchPath);
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-14 12:18:21 +00:00
|
|
|
#endif
|
|
|
|
break;
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
} while (SearchPath.FindNext());
|
2016-04-14 12:18:21 +00:00
|
|
|
#ifdef _WIN32
|
2016-04-14 09:35:08 +00:00
|
|
|
m_ZipIniFile->FlushChanges();
|
2016-04-14 12:18:21 +00:00
|
|
|
#endif
|
|
|
|
WriteTrace(TraceRomList, TraceDebug, "Done (Directory: %s)",Directory);
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRomList::NotificationCB(const char * Status, CRomList * /*_this*/)
|
|
|
|
{
|
|
|
|
g_Notify->DisplayMessage(5, Status);
|
|
|
|
}
|
|
|
|
|
2016-04-14 22:07:34 +00:00
|
|
|
void CRomList::RefreshRomListStatic(CRomList * _this)
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
|
|
|
_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
|
|
|
|
{
|
2016-04-15 23:08:44 +00:00
|
|
|
CFile File;
|
|
|
|
if (!File.Open(FileName, CFileBase::modeRead))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
File.SeekToBegin();
|
|
|
|
if (!File.Read(Test,sizeof(Test)))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!CN64Rom::IsValidRomImage(Test))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
File.SeekToBegin();
|
|
|
|
if (!File.Read(Data,DataLen))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*RomSize = File.GetLength();
|
2016-04-14 09:35:08 +00:00
|
|
|
FileFormat = Format_Uncompressed;
|
|
|
|
}
|
|
|
|
ByteSwapRomData(Data, DataLen);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CRomList::FillRomInfo(ROM_INFO * pRomInfo)
|
|
|
|
{
|
|
|
|
uint8_t RomData[0x1000];
|
|
|
|
|
2016-04-14 12:18:21 +00:00
|
|
|
if (LoadDataFromRomFile(pRomInfo->szFullFileName, RomData, sizeof(RomData), &pRomInfo->RomSize, pRomInfo->FileFormat))
|
2016-04-14 09:35:08 +00:00
|
|
|
{
|
|
|
|
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);
|
2016-04-15 23:17:37 +00:00
|
|
|
CN64Rom::CleanRomName(InternalName);
|
2016-04-16 09:55:32 +00:00
|
|
|
strcpy(pRomInfo->InternalName, InternalName);
|
2016-04-14 09:35:08 +00:00
|
|
|
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);
|
2016-04-14 22:38:02 +00:00
|
|
|
pRomInfo->CicChip = CN64Rom::GetCicChipID(RomData);
|
2016-04-14 09:35:08 +00:00
|
|
|
FillRomExtensionInfo(pRomInfo);
|
|
|
|
return true;
|
|
|
|
}
|
2016-04-14 12:18:21 +00:00
|
|
|
return false;
|
2016-04-14 09:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CRomList::FillRomExtensionInfo(ROM_INFO * pRomInfo)
|
|
|
|
{
|
|
|
|
//Initialize the structure
|
2016-04-16 09:55:32 +00:00
|
|
|
pRomInfo->UserNotes[0] = '\0';
|
|
|
|
pRomInfo->Developer[0] = '\0';
|
|
|
|
pRomInfo->ReleaseDate[0] = '\0';
|
|
|
|
pRomInfo->Genre[0] = '\0';
|
2016-04-14 09:35:08 +00:00
|
|
|
pRomInfo->Players = 1;
|
2016-04-16 09:55:32 +00:00
|
|
|
pRomInfo->CoreNotes[0] = '\0';
|
|
|
|
pRomInfo->PluginNotes[0] = '\0';
|
|
|
|
strcpy(pRomInfo->GoodName, "#340#");
|
|
|
|
strcpy(pRomInfo->Status, "Unknown");
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
//Get File Identifier
|
|
|
|
char Identifier[100];
|
|
|
|
sprintf(Identifier, "%08X-%08X-C:%X", pRomInfo->CRC1, pRomInfo->CRC2, pRomInfo->Country);
|
|
|
|
|
|
|
|
//Rom Notes
|
2016-04-16 09:55:32 +00:00
|
|
|
strncpy(pRomInfo->UserNotes, m_NotesIniFile->GetString(Identifier, "Note", "").c_str(), sizeof(pRomInfo->UserNotes) / sizeof(char));
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
//Rom Extension info
|
2016-04-16 09:55:32 +00:00
|
|
|
strncpy(pRomInfo->Developer, m_ExtIniFile->GetString(Identifier, "Developer", "").c_str(), sizeof(pRomInfo->Developer) / sizeof(char));
|
|
|
|
strncpy(pRomInfo->ReleaseDate, m_ExtIniFile->GetString(Identifier, "ReleaseDate", "").c_str(), sizeof(pRomInfo->ReleaseDate) / sizeof(char));
|
|
|
|
strncpy(pRomInfo->Genre, m_ExtIniFile->GetString(Identifier, "Genre", "").c_str(), sizeof(pRomInfo->Genre) / sizeof(char));
|
2016-04-14 09:35:08 +00:00
|
|
|
m_ExtIniFile->GetNumber(Identifier, "Players", 1, (uint32_t &)pRomInfo->Players);
|
2016-04-16 09:55:32 +00:00
|
|
|
strncpy(pRomInfo->ForceFeedback, m_ExtIniFile->GetString(Identifier, "ForceFeedback", "unknown").c_str(), sizeof(pRomInfo->ForceFeedback) / sizeof(char));
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
//Rom Settings
|
2016-04-16 09:55:32 +00:00
|
|
|
strncpy(pRomInfo->GoodName, m_RomIniFile->GetString(Identifier, "Good Name", pRomInfo->GoodName).c_str(), sizeof(pRomInfo->GoodName) / sizeof(char));
|
|
|
|
strncpy(pRomInfo->Status, m_RomIniFile->GetString(Identifier, "Status", pRomInfo->Status).c_str(), sizeof(pRomInfo->Status) / sizeof(char));
|
|
|
|
strncpy(pRomInfo->CoreNotes, m_RomIniFile->GetString(Identifier, "Core Note", "").c_str(), sizeof(pRomInfo->CoreNotes) / sizeof(char));
|
|
|
|
strncpy(pRomInfo->PluginNotes, m_RomIniFile->GetString(Identifier, "Plugin Note", "").c_str(), sizeof(pRomInfo->PluginNotes) / sizeof(char));
|
2016-04-14 09:35:08 +00:00
|
|
|
|
|
|
|
//Get the text color
|
2016-04-16 09:55:32 +00:00
|
|
|
stdstr String = m_RomIniFile->GetString("Rom Status", pRomInfo->Status, "000000");
|
|
|
|
pRomInfo->TextColor = (strtoul(String.c_str(), 0, 16) & 0xFFFFFF);
|
2016-04-14 09:35:08 +00:00
|
|
|
pRomInfo->TextColor = (pRomInfo->TextColor & 0x00FF00) | ((pRomInfo->TextColor >> 0x10) & 0xFF) | ((pRomInfo->TextColor & 0xFF) << 0x10);
|
|
|
|
|
|
|
|
//Get the selected color
|
2016-04-16 09:55:32 +00:00
|
|
|
String.Format("%s.Sel", pRomInfo->Status);
|
2016-04-14 09:35:08 +00:00
|
|
|
String = m_RomIniFile->GetString("Rom Status", String.c_str(), "FFFFFFFF");
|
2016-04-16 09:55:32 +00:00
|
|
|
uint32_t selcol = strtoul(String.c_str(), NULL, 16);
|
2016-04-14 09:35:08 +00:00
|
|
|
if (selcol & 0x80000000)
|
|
|
|
{
|
|
|
|
pRomInfo->SelColor = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
selcol = (selcol & 0x00FF00) | ((selcol >> 0x10) & 0xFF) | ((selcol & 0xFF) << 0x10);
|
|
|
|
pRomInfo->SelColor = selcol;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Get the selected text color
|
2016-04-16 09:55:32 +00:00
|
|
|
String.Format("%s.Seltext", pRomInfo->Status);
|
2016-04-14 09:35:08 +00:00
|
|
|
String = m_RomIniFile->GetString("Rom Status", String.c_str(), "FFFFFF");
|
2016-04-16 09:55:32 +00:00
|
|
|
pRomInfo->SelTextColor = (strtoul(String.c_str(), 0, 16) & 0xFFFFFF);
|
2016-04-14 09:35:08 +00:00
|
|
|
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
|
2016-04-14 22:07:34 +00:00
|
|
|
RefreshRomList();
|
2016-04-14 09:35:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
unsigned char md5[16];
|
|
|
|
if (!file.Read(md5, sizeof(md5)))
|
|
|
|
{
|
|
|
|
file.Close();
|
2016-04-14 22:07:34 +00:00
|
|
|
RefreshRomList();
|
2016-04-14 09:35:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Read the size of ROM_INFO
|
|
|
|
int32_t RomInfoSize = 0;
|
|
|
|
if (!file.Read(&RomInfoSize, sizeof(RomInfoSize)) || RomInfoSize != sizeof(ROM_INFO))
|
|
|
|
{
|
|
|
|
file.Close();
|
2016-04-14 22:07:34 +00:00
|
|
|
RefreshRomList();
|
2016-04-14 09:35:08 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-04-15 22:56:10 +00:00
|
|
|
void CRomList::RefreshSettings(CRomList * _this)
|
|
|
|
{
|
|
|
|
_this->m_GameDir = g_Settings->LoadStringVal(RomList_GameDir).c_str();
|
|
|
|
}
|
|
|
|
|
2016-04-14 09:35:08 +00:00
|
|
|
void CRomList::AddFileNameToList(strlist & FileList, const stdstr & Directory, CPath & File)
|
|
|
|
{
|
|
|
|
uint8_t i;
|
|
|
|
|
|
|
|
if (FileList.size() > 3000)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-04-15 22:56:10 +00:00
|
|
|
stdstr Extension = stdstr(File.GetExtension()).ToLower();
|
2016-04-14 09:35:08 +00:00
|
|
|
for (i = 0; i < sizeof(ROM_extensions) / sizeof(ROM_extensions[0]); i++)
|
|
|
|
{
|
|
|
|
if (Extension == ROM_extensions[i])
|
|
|
|
{
|
2016-04-15 22:56:10 +00:00
|
|
|
stdstr FileName = Directory + File.GetNameExtension();
|
2016-04-14 09:35:08 +00:00
|
|
|
FileName.ToLower();
|
|
|
|
FileList.push_back(FileName);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|