mirror of
https://github.com/libretro/Mesen.git
synced 2024-11-24 01:29:41 +00:00
170 lines
3.9 KiB
C++
170 lines
3.9 KiB
C++
#pragma once
|
|
#include "stdafx.h"
|
|
#include "RomLoader.h"
|
|
#include "iNesLoader.h"
|
|
#include "FdsLoader.h"
|
|
|
|
bool RomLoader::LoadFromZip(istream &zipFile)
|
|
{
|
|
bool result = false;
|
|
|
|
uint32_t fileSize;
|
|
uint8_t* buffer = ReadFile(zipFile, fileSize);
|
|
|
|
ZipReader reader;
|
|
reader.LoadZipArchive(buffer, fileSize);
|
|
|
|
vector<string> fileList = reader.GetFileList();
|
|
for(string filename : fileList) {
|
|
std::transform(filename.begin(), filename.end(), filename.begin(), ::tolower);
|
|
if(filename.length() > 4) {
|
|
if(filename.substr(filename.length() - 4, 4).compare(".nes") == 0 || filename.substr(filename.length() - 4, 4).compare(".fds") == 0) {
|
|
uint8_t* fileBuffer = nullptr;
|
|
size_t fileSize = 0;
|
|
reader.ExtractFile(filename, &fileBuffer, fileSize);
|
|
if(fileBuffer) {
|
|
result = LoadFromMemory(fileBuffer, fileSize);
|
|
delete[] fileBuffer;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
delete[] buffer;
|
|
return result;
|
|
}
|
|
|
|
bool RomLoader::LoadFromStream(istream &romFile)
|
|
{
|
|
uint32_t fileSize;
|
|
uint8_t* buffer = ReadFile(romFile, fileSize);
|
|
bool result = LoadFromMemory(buffer, fileSize);
|
|
delete[] buffer;
|
|
|
|
return result;
|
|
}
|
|
|
|
uint32_t RomLoader::GetFileSize(istream &file)
|
|
{
|
|
file.seekg(0, ios::end);
|
|
uint32_t fileSize = (uint32_t)file.tellg();
|
|
file.seekg(0, ios::beg);
|
|
|
|
return fileSize;
|
|
}
|
|
|
|
uint8_t* RomLoader::ReadFile(istream &file, uint32_t &fileSize)
|
|
{
|
|
fileSize = GetFileSize(file);
|
|
|
|
uint8_t* buffer = new uint8_t[fileSize];
|
|
file.read((char*)buffer, fileSize);
|
|
return buffer;
|
|
}
|
|
|
|
bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length)
|
|
{
|
|
vector<uint8_t> fileData(buffer, buffer + length);
|
|
|
|
if(!_ipsFilename.empty()) {
|
|
//Apply IPS patch
|
|
fileData = IpsPatcher::PatchBuffer(_ipsFilename, fileData);
|
|
}
|
|
|
|
if(memcmp(buffer, "NES\x1a", 4) == 0) {
|
|
iNesLoader loader;
|
|
_romData = loader.LoadRom(fileData);
|
|
} else if(memcmp(buffer, "FDS\x1a", 4) == 0 || memcmp(buffer, "\x1*NINTENDO-HVC*", 15) == 0) {
|
|
FdsLoader loader;
|
|
_romData = loader.LoadRom(fileData, _filename);
|
|
} else {
|
|
_romData.Error = true;
|
|
}
|
|
|
|
_romData.RawData = fileData;
|
|
_romData.Crc32 = CRC32::GetCRC(buffer, length);
|
|
|
|
return !_romData.Error;
|
|
}
|
|
|
|
bool RomLoader::LoadFile(string filename, istream *filestream, string ipsFilename)
|
|
{
|
|
_filename = filename;
|
|
_ipsFilename = ipsFilename;
|
|
|
|
ifstream file;
|
|
istream* input = nullptr;
|
|
if(!filestream) {
|
|
file.open(filename, ios::in | ios::binary);
|
|
if(file) {
|
|
input = &file;
|
|
}
|
|
} else {
|
|
input = filestream;
|
|
}
|
|
|
|
|
|
char header[15];
|
|
input->seekg(0, ios::beg);
|
|
input->read(header, 15);
|
|
input->seekg(0, ios::beg);
|
|
|
|
if(memcmp(header, "PK", 2) == 0) {
|
|
return LoadFromZip(*input);
|
|
} else if(memcmp(header, "NES\x1a", 4) == 0 || memcmp(header, "FDS\x1a", 4) == 0 || memcmp(header, "\x1*NINTENDO-HVC*", 15) == 0) {
|
|
return LoadFromStream(*input);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
RomData RomLoader::GetRomData()
|
|
{
|
|
_romData.Filename = _filename;
|
|
return _romData;
|
|
}
|
|
|
|
uint32_t RomLoader::GetCRC32(string filename)
|
|
{
|
|
RomLoader loader;
|
|
uint32_t crc = 0;
|
|
if(loader.LoadFile(filename)) {
|
|
crc = loader._romData.Crc32;
|
|
}
|
|
return crc;
|
|
}
|
|
|
|
string RomLoader::FindMatchingRomInFolder(string folder, string romFilename, uint32_t crc32Hash)
|
|
{
|
|
std::transform(romFilename.begin(), romFilename.end(), romFilename.begin(), ::tolower);
|
|
vector<string> validExtensions = { { "*.nes", "*.zip", "*.fds" } };
|
|
vector<string> romFiles;
|
|
|
|
for(string extension : validExtensions) {
|
|
for(string file : FolderUtilities::GetFilesInFolder(folder, extension, true)) {
|
|
romFiles.push_back(file);
|
|
}
|
|
}
|
|
|
|
for(string romFile : romFiles) {
|
|
//Quick search by filename
|
|
string originalFilename = romFile;
|
|
std::transform(romFile.begin(), romFile.end(), romFile.begin(), ::tolower);
|
|
if(FolderUtilities::GetFilename(romFile, true).compare(romFilename) == 0) {
|
|
if(RomLoader::GetCRC32(romFile) == crc32Hash) {
|
|
return originalFilename;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(string romFile : romFiles) {
|
|
//Slower search by CRC value
|
|
if(RomLoader::GetCRC32(romFile) == crc32Hash) {
|
|
//Matching ROM found
|
|
return romFile;
|
|
}
|
|
}
|
|
|
|
return "";
|
|
} |