mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
NES: Fixed UNIF TODOs
This commit is contained in:
parent
1f75992666
commit
588d284594
14 changed files with 497 additions and 169 deletions
|
@ -22,6 +22,8 @@
|
|||
<ClInclude Include="Debugger\Base6502Assembler.h" />
|
||||
<ClInclude Include="Debugger\CdlManager.h" />
|
||||
<ClInclude Include="NES\Debugger\NesCodeDataLogger.h" />
|
||||
<ClInclude Include="NES\Loaders\UnifBoards.h" />
|
||||
<ClInclude Include="NES\Loaders\UnifLoader.h" />
|
||||
<ClInclude Include="PCE\Debugger\PceAssembler.h" />
|
||||
<ClInclude Include="PCE\IPceMapper.h" />
|
||||
<ClInclude Include="PCE\PceArcadeCard.h" />
|
||||
|
@ -451,6 +453,7 @@
|
|||
<ClCompile Include="NES\Loaders\NsfLoader.cpp" />
|
||||
<ClCompile Include="NES\Loaders\RomLoader.cpp" />
|
||||
<ClCompile Include="NES\APU\BaseExpansionAudio.cpp" />
|
||||
<ClCompile Include="NES\Loaders\UnifLoader.cpp" />
|
||||
<ClCompile Include="NES\Mappers\FDS\Fds.cpp" />
|
||||
<ClCompile Include="NES\Mappers\FDS\FdsAudio.cpp" />
|
||||
<ClCompile Include="NES\Mappers\FDS\FdsInputButtons.cpp" />
|
||||
|
|
|
@ -1838,6 +1838,12 @@
|
|||
<ClInclude Include="Debugger\CdlManager.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NES\Loaders\UnifBoards.h">
|
||||
<Filter>NES\Loaders</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NES\Loaders\UnifLoader.h">
|
||||
<Filter>NES\Loaders</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Shared\Video\RotateFilter.cpp">
|
||||
|
@ -1933,6 +1939,9 @@
|
|||
<ClCompile Include="Debugger\CdlManager.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NES\Loaders\UnifLoader.cpp">
|
||||
<Filter>NES\Loaders</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="PCE">
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
#include "stdafx.h"
|
||||
#include "NES/RomData.h"
|
||||
#include "NES/GameDatabase.h"
|
||||
#include "NES/Loaders/UnifLoader.h"
|
||||
#include "NES/Loaders/UnifBoards.h"
|
||||
#include "Shared/MessageManager.h"
|
||||
#include "Utilities/CRC32.h"
|
||||
#include "Utilities/FolderUtilities.h"
|
||||
#include "Utilities/StringUtilities.h"
|
||||
#include "Utilities/HexUtilities.h"
|
||||
|
||||
//TODO NES
|
||||
//#include "EmulationSettings.h"
|
||||
//#include "UnifLoader.h"
|
||||
|
||||
std::unordered_map<uint32_t, GameInfo> GameDatabase::_gameDatabase;
|
||||
bool GameDatabase::_enabled = true;
|
||||
|
||||
|
@ -49,8 +47,7 @@ void GameDatabase::LoadGameDb(vector<string> data)
|
|||
gameInfo.VsPpuModel = (PpuModel)ToInt<uint32_t>(values[17]);
|
||||
|
||||
if(gameInfo.MapperID == 65000) {
|
||||
//TODO NES
|
||||
//gameInfo.MapperID = UnifLoader::GetMapperID(gameInfo.Board);
|
||||
gameInfo.MapperID = UnifLoader::GetMapperID(gameInfo.Board);
|
||||
}
|
||||
|
||||
_gameDatabase[gameInfo.Crc] = gameInfo;
|
||||
|
@ -116,16 +113,6 @@ GameSystem GameDatabase::GetGameSystem(string system)
|
|||
return GameSystem::NesNtsc;
|
||||
}
|
||||
|
||||
void GameDatabase::SetGameDatabaseState(bool enabled)
|
||||
{
|
||||
_enabled = enabled;
|
||||
}
|
||||
|
||||
bool GameDatabase::IsEnabled()
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
uint8_t GameDatabase::GetSubMapper(GameInfo &info)
|
||||
{
|
||||
if(!info.SubmapperID.empty()) {
|
||||
|
@ -232,13 +219,12 @@ void GameDatabase::SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRom
|
|||
|
||||
MessageManager::Log("[DB] Game found in database");
|
||||
|
||||
//TODO NES
|
||||
MessageManager::Log("[DB] Mapper: " + std::to_string(info.MapperID) + " Sub: " + std::to_string(GetSubMapper(info)));
|
||||
/*if(info.MapperID < UnifBoards::UnknownBoard) {
|
||||
if(info.MapperID < UnifBoards::UnknownBoard) {
|
||||
MessageManager::Log("[DB] Mapper: " + std::to_string(info.MapperID) + " Sub: " + std::to_string(GetSubMapper(info)));
|
||||
} else if(info.MapperID == UnifBoards::UnknownBoard) {
|
||||
MessageManager::DisplayMessage("Error", "UnsupportedMapper", "UNIF: " + info.Board);
|
||||
}*/
|
||||
}
|
||||
|
||||
MessageManager::Log("[DB] System : " + info.System);
|
||||
|
||||
|
|
|
@ -23,9 +23,6 @@ private:
|
|||
|
||||
public:
|
||||
static void LoadGameDb(std::istream & db);
|
||||
|
||||
static void SetGameDatabaseState(bool enabled);
|
||||
static bool IsEnabled();
|
||||
|
||||
static void SetGameInfo(uint32_t romCrc, RomData &romData, bool updateRomData, bool forHeaderlessRom);
|
||||
static bool GetiNesHeader(uint32_t romCrc, NesHeader &nesHeader);
|
||||
|
|
|
@ -11,54 +11,52 @@
|
|||
#include "NES/Loaders/FdsLoader.h"
|
||||
#include "NES/Loaders/NsfLoader.h"
|
||||
#include "NES/Loaders/NsfeLoader.h"
|
||||
#include "NES/Loaders/UnifLoader.h"
|
||||
#include "NES/NesHeader.h"
|
||||
#include "NES/GameDatabase.h"
|
||||
//#include "StudyBoxLoader.h"
|
||||
|
||||
/*
|
||||
//TODO NES
|
||||
#include "UnifLoader.h"
|
||||
#include "StudyBoxLoader.h"*/
|
||||
|
||||
bool RomLoader::LoadFile(VirtualFile &romFile)
|
||||
bool RomLoader::LoadFile(VirtualFile &romFile, RomData& romData, bool databaseEnabled)
|
||||
{
|
||||
if(!romFile.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<uint8_t>& fileData = _romData.RawData;
|
||||
romData = {};
|
||||
|
||||
vector<uint8_t>& fileData = romData.RawData;
|
||||
romFile.ReadFile(fileData);
|
||||
if(fileData.size() < 15) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_filename = romFile.GetFileName();
|
||||
string romName = FolderUtilities::GetFilename(_filename, true);
|
||||
|
||||
string filename = romFile.GetFileName();
|
||||
string romName = FolderUtilities::GetFilename(filename, true);
|
||||
|
||||
uint32_t crc = CRC32::GetCRC(fileData.data(), fileData.size());
|
||||
_romData.Info.Hash.Crc32 = crc;
|
||||
romData.Info.Hash.Crc32 = crc;
|
||||
|
||||
Log("");
|
||||
Log("Loading rom: " + romName);
|
||||
MessageManager::Log("");
|
||||
MessageManager::Log("Loading rom: " + romName);
|
||||
stringstream crcHex;
|
||||
crcHex << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << crc;
|
||||
Log("File CRC32: 0x" + crcHex.str());
|
||||
MessageManager::Log("File CRC32: 0x" + crcHex.str());
|
||||
|
||||
if(memcmp(fileData.data(), "NES\x1a", 4) == 0) {
|
||||
iNesLoader loader(_checkOnly);
|
||||
loader.LoadRom(_romData, fileData, nullptr);
|
||||
iNesLoader loader;
|
||||
loader.LoadRom(romData, fileData, nullptr, databaseEnabled);
|
||||
} else if(memcmp(fileData.data(), "FDS\x1a", 4) == 0 || memcmp(fileData.data(), "\x1*NINTENDO-HVC*", 15) == 0) {
|
||||
FdsLoader loader(_checkOnly);
|
||||
loader.LoadRom(_romData, fileData);
|
||||
FdsLoader loader;
|
||||
loader.LoadRom(romData, fileData);
|
||||
} else if(memcmp(fileData.data(), "NESM\x1a", 5) == 0) {
|
||||
NsfLoader loader(_checkOnly);
|
||||
loader.LoadRom(_romData, fileData);
|
||||
NsfLoader loader;
|
||||
loader.LoadRom(romData, fileData);
|
||||
} else if(memcmp(fileData.data(), "NSFE", 4) == 0) {
|
||||
NsfeLoader loader(_checkOnly);
|
||||
loader.LoadRom(_romData, fileData);
|
||||
NsfeLoader loader;
|
||||
loader.LoadRom(romData, fileData);
|
||||
} else if(memcmp(fileData.data(), "UNIF", 4) == 0) {
|
||||
//TODO NES
|
||||
//UnifLoader loader(_checkOnly);
|
||||
//loader.LoadRom(_romData, fileData);
|
||||
UnifLoader loader;
|
||||
loader.LoadRom(romData, fileData, databaseEnabled);
|
||||
} else if(memcmp(fileData.data(), "STBX", 4) == 0) {
|
||||
//TODO NES
|
||||
//StudyBoxLoader loader(_checkOnly);
|
||||
|
@ -67,107 +65,33 @@ bool RomLoader::LoadFile(VirtualFile &romFile)
|
|||
} else {
|
||||
NesHeader header = {};
|
||||
if(GameDatabase::GetiNesHeader(crc, header)) {
|
||||
Log("[DB] Headerless ROM file found - using game database data.");
|
||||
MessageManager::Log("[DB] Headerless ROM file found - using game database data.");
|
||||
iNesLoader loader;
|
||||
loader.LoadRom(_romData, fileData, &header);
|
||||
_romData.Info.IsHeaderlessRom = true;
|
||||
loader.LoadRom(romData, fileData, &header, true);
|
||||
romData.Info.IsHeaderlessRom = true;
|
||||
} else {
|
||||
Log("Invalid rom file.");
|
||||
_romData.Error = true;
|
||||
MessageManager::Log("Invalid rom file.");
|
||||
romData.Error = true;
|
||||
}
|
||||
}
|
||||
|
||||
_romData.Info.RomName = romName;
|
||||
_romData.Info.Filename = _filename;
|
||||
romData.Info.RomName = romName;
|
||||
romData.Info.Filename = filename;
|
||||
|
||||
if(_romData.Info.System == GameSystem::Unknown) {
|
||||
if(romData.Info.System == GameSystem::Unknown) {
|
||||
//Use filename to detect PAL/VS system games
|
||||
string name = _romData.Info.Filename;
|
||||
string name = romData.Info.Filename;
|
||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
||||
|
||||
if(name.find("(e)") != string::npos || name.find("(australia)") != string::npos || name.find("(europe)") != string::npos ||
|
||||
name.find("(germany)") != string::npos || name.find("(spain)") != string::npos) {
|
||||
_romData.Info.System = GameSystem::NesPal;
|
||||
romData.Info.System = GameSystem::NesPal;
|
||||
} else if(name.find("(vs)") != string::npos) {
|
||||
_romData.Info.System = GameSystem::VsSystem;
|
||||
romData.Info.System = GameSystem::VsSystem;
|
||||
} else {
|
||||
_romData.Info.System = GameSystem::NesNtsc;
|
||||
romData.Info.System = GameSystem::NesNtsc;
|
||||
}
|
||||
}
|
||||
|
||||
return !_romData.Error;
|
||||
return !romData.Error;
|
||||
}
|
||||
|
||||
RomData RomLoader::GetRomData()
|
||||
{
|
||||
return _romData;
|
||||
}
|
||||
|
||||
string RomLoader::FindMatchingRomInFile(string filePath, HashInfo hashInfo, int &iterationCount)
|
||||
{
|
||||
unique_ptr<ArchiveReader> reader = ArchiveReader::GetReader(filePath);
|
||||
if(reader) {
|
||||
for(string file : reader->GetFileList(VirtualFile::RomExtensions)) {
|
||||
RomLoader loader(true);
|
||||
vector<uint8_t> fileData;
|
||||
VirtualFile innerFile(filePath, file);
|
||||
if(loader.LoadFile(innerFile)) {
|
||||
if(hashInfo.Crc32 == loader._romData.Info.Hash.Crc32) {
|
||||
return innerFile;
|
||||
}
|
||||
|
||||
iterationCount++;
|
||||
if(iterationCount > RomLoader::MaxFilesToCheck) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RomLoader loader(true);
|
||||
VirtualFile file = filePath;
|
||||
if(loader.LoadFile(file)) {
|
||||
if(hashInfo.Crc32 == loader._romData.Info.Hash.Crc32) {
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
iterationCount++;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
string RomLoader::FindMatchingRom(vector<string> romFiles, string romFilename, HashInfo hashInfo, bool useFastSearch)
|
||||
{
|
||||
int iterationCount = 0;
|
||||
if(useFastSearch) {
|
||||
string lcRomFile = romFilename;
|
||||
std::transform(lcRomFile.begin(), lcRomFile.end(), lcRomFile.begin(), ::tolower);
|
||||
|
||||
for(string currentFile : romFiles) {
|
||||
//Quick search by filename
|
||||
string lcCurrentFile = currentFile;
|
||||
std::transform(lcCurrentFile.begin(), lcCurrentFile.end(), lcCurrentFile.begin(), ::tolower);
|
||||
if(lcCurrentFile.find(lcRomFile) != string::npos && FolderUtilities::GetFilename(lcRomFile, true) == FolderUtilities::GetFilename(lcCurrentFile, true)) {
|
||||
string match = RomLoader::FindMatchingRomInFile(currentFile, hashInfo, iterationCount);
|
||||
if(!match.empty()) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(string romFile : romFiles) {
|
||||
//Slower search by CRC value
|
||||
string match = RomLoader::FindMatchingRomInFile(romFile, hashInfo, iterationCount);
|
||||
if(!match.empty()) {
|
||||
return match;
|
||||
}
|
||||
iterationCount++;
|
||||
|
||||
if(iterationCount > RomLoader::MaxFilesToCheck) {
|
||||
MessageManager::Log("[RomLoader] Could not find a file matching the specified name/hash after 100 tries, giving up...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
|
@ -1,26 +1,11 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "NES/Loaders/BaseLoader.h"
|
||||
#include "NES/RomData.h"
|
||||
|
||||
class ArchiveReader;
|
||||
class VirtualFile;
|
||||
struct RomData;
|
||||
|
||||
class RomLoader : public BaseLoader
|
||||
class RomLoader
|
||||
{
|
||||
private:
|
||||
static constexpr int MaxFilesToCheck = 100;
|
||||
|
||||
RomData _romData;
|
||||
string _filename;
|
||||
|
||||
static string FindMatchingRomInFile(string filePath, HashInfo hashInfo, int &iterationCount);
|
||||
|
||||
public:
|
||||
using BaseLoader::BaseLoader;
|
||||
|
||||
bool LoadFile(VirtualFile &romFile);
|
||||
|
||||
RomData GetRomData();
|
||||
static string FindMatchingRom(vector<string> romFiles, string romFilename, HashInfo hashInfo, bool useFastSearch);
|
||||
static bool LoadFile(VirtualFile &romFile, RomData& romData, bool databaseEnabled);
|
||||
};
|
||||
|
|
22
Core/NES/Loaders/UnifBoards.h
Normal file
22
Core/NES/Loaders/UnifBoards.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
namespace UnifBoards {
|
||||
enum UnifBoards
|
||||
{
|
||||
UnknownBoard = 32768,
|
||||
Malee,
|
||||
Gs2013,
|
||||
Ghostbusters63in1,
|
||||
Super24in1Sc03,
|
||||
Cc21,
|
||||
Ac08,
|
||||
UnlPuzzle,
|
||||
Fk23C,
|
||||
Fk23Ca,
|
||||
Unl255in1,
|
||||
UnlVrc7,
|
||||
Unl8237A,
|
||||
SssNrom256,
|
||||
};
|
||||
}
|
375
Core/NES/Loaders/UnifLoader.cpp
Normal file
375
Core/NES/Loaders/UnifLoader.cpp
Normal file
|
@ -0,0 +1,375 @@
|
|||
#include "stdafx.h"
|
||||
#include "NES/Loaders/UnifLoader.h"
|
||||
#include "NES/Loaders/UnifBoards.h"
|
||||
#include "NES/RomData.h"
|
||||
#include "NES/GameDatabase.h"
|
||||
#include "Shared/MessageManager.h"
|
||||
#include "Utilities/CRC32.h"
|
||||
#include "Utilities/md5.h"
|
||||
#include "Utilities/HexUtilities.h"
|
||||
|
||||
void UnifLoader::Read(uint8_t*& data, uint8_t& dest)
|
||||
{
|
||||
dest = data[0];
|
||||
data++;
|
||||
}
|
||||
|
||||
void UnifLoader::Read(uint8_t*& data, uint32_t& dest)
|
||||
{
|
||||
dest = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
data += 4;
|
||||
}
|
||||
|
||||
void UnifLoader::Read(uint8_t*& data, uint8_t* dest, size_t len)
|
||||
{
|
||||
memcpy(dest, data, len);
|
||||
data += len;
|
||||
}
|
||||
|
||||
string UnifLoader::ReadString(uint8_t*& data, uint8_t* chunkEnd)
|
||||
{
|
||||
stringstream ss;
|
||||
while(data < chunkEnd) {
|
||||
if(data[0] == 0) {
|
||||
//end of string
|
||||
data = chunkEnd;
|
||||
break;
|
||||
} else {
|
||||
if(data[0] != ' ') {
|
||||
//Ignore spaces
|
||||
ss << (char)data[0];
|
||||
}
|
||||
}
|
||||
data++;
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string UnifLoader::ReadFourCC(uint8_t*& data)
|
||||
{
|
||||
stringstream ss;
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ss << (char)data[i];
|
||||
}
|
||||
data += 4;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool UnifLoader::ReadChunk(uint8_t*& data, uint8_t* dataEnd, RomData& romData)
|
||||
{
|
||||
if(data + 8 > dataEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string fourCC = ReadFourCC(data);
|
||||
|
||||
uint32_t length;
|
||||
Read(data, length);
|
||||
|
||||
uint8_t* chunkEnd = data + length;
|
||||
if(chunkEnd > dataEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fourCC.compare("MAPR") == 0) {
|
||||
_mapperName = ReadString(data, chunkEnd);
|
||||
if(_mapperName.size() > 0) {
|
||||
romData.Info.MapperID = GetMapperID(_mapperName);
|
||||
if(romData.Info.MapperID == UnifBoards::UnknownBoard) {
|
||||
Log("[UNIF] Error: Unknown board");
|
||||
}
|
||||
} else {
|
||||
romData.Error = true;
|
||||
return false;
|
||||
}
|
||||
} else if(fourCC.substr(0, 3).compare("PRG") == 0) {
|
||||
uint32_t chunkNumber;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << fourCC[3];
|
||||
ss >> chunkNumber;
|
||||
|
||||
_prgChunks[chunkNumber].resize(length);
|
||||
Read(data, _prgChunks[chunkNumber].data(), length);
|
||||
} else if(fourCC.substr(0, 3).compare("CHR") == 0) {
|
||||
uint32_t chunkNumber;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << fourCC[3];
|
||||
ss >> chunkNumber;
|
||||
|
||||
_chrChunks[chunkNumber].resize(length);
|
||||
Read(data, _chrChunks[chunkNumber].data(), length);
|
||||
} else if(fourCC.compare("TVCI") == 0) {
|
||||
uint8_t value;
|
||||
Read(data, value);
|
||||
romData.Info.System = value == 1 ? GameSystem::NesPal : GameSystem::NesNtsc;
|
||||
} else if(fourCC.compare("CTRL") == 0) {
|
||||
//not supported
|
||||
} else if(fourCC.compare("BATR") == 0) {
|
||||
uint8_t value;
|
||||
Read(data, value);
|
||||
romData.Info.HasBattery = value > 0;
|
||||
} else if(fourCC.compare("MIRR") == 0) {
|
||||
uint8_t value;
|
||||
Read(data, value);
|
||||
|
||||
switch(value) {
|
||||
default:
|
||||
case 0: romData.Info.Mirroring = MirroringType::Horizontal; break;
|
||||
case 1: romData.Info.Mirroring = MirroringType::Vertical; break;
|
||||
case 2: romData.Info.Mirroring = MirroringType::ScreenAOnly; break;
|
||||
case 3: romData.Info.Mirroring = MirroringType::ScreenBOnly; break;
|
||||
case 4: romData.Info.Mirroring = MirroringType::FourScreens; break;
|
||||
}
|
||||
} else {
|
||||
//Unsupported/unused FourCCs: PCKn, CCKn, NAME, WRTR, READ, DINF, VROR
|
||||
}
|
||||
|
||||
data = chunkEnd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t UnifLoader::GetMapperID(string mapperName)
|
||||
{
|
||||
string prefix = mapperName.substr(0, 4);
|
||||
if(prefix.compare("NES-") == 0 || prefix.compare("UNL-") == 0 || prefix.compare("HVC-") == 0 || prefix.compare("BTL-") == 0 || prefix.compare("BMC-") == 0) {
|
||||
mapperName = mapperName.substr(4);
|
||||
}
|
||||
|
||||
auto result = _boardMappings.find(mapperName);
|
||||
if(result != _boardMappings.end()) {
|
||||
return result->second;
|
||||
}
|
||||
|
||||
return UnifBoards::UnknownBoard;
|
||||
}
|
||||
|
||||
void UnifLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, bool databaseEnabled)
|
||||
{
|
||||
//Skip header, version & null bytes, start reading at first chunk
|
||||
uint8_t* data = romFile.data() + 32;
|
||||
uint8_t* endOfFile = romFile.data() + romFile.size();
|
||||
|
||||
while(ReadChunk(data, endOfFile, romData)) {
|
||||
//Read all chunks
|
||||
}
|
||||
|
||||
for(int i = 0; i < 16; i++) {
|
||||
romData.PrgRom.insert(romData.PrgRom.end(), _prgChunks[i].begin(), _prgChunks[i].end());
|
||||
romData.ChrRom.insert(romData.ChrRom.end(), _chrChunks[i].begin(), _chrChunks[i].end());
|
||||
}
|
||||
|
||||
if(romData.PrgRom.size() == 0 || _mapperName.empty()) {
|
||||
romData.Error = true;
|
||||
} else {
|
||||
vector<uint8_t> fullRom;
|
||||
fullRom.insert(fullRom.end(), romData.PrgRom.begin(), romData.PrgRom.end());
|
||||
fullRom.insert(fullRom.end(), romData.ChrRom.begin(), romData.ChrRom.end());
|
||||
|
||||
romData.Info.Format = RomFormat::Unif;
|
||||
romData.Info.Hash.PrgCrc32 = CRC32::GetCRC(romData.PrgRom.data(), romData.PrgRom.size());
|
||||
romData.Info.Hash.PrgChrCrc32 = CRC32::GetCRC(fullRom.data(), fullRom.size());
|
||||
|
||||
Log("PRG+CHR CRC32: 0x" + HexUtilities::ToHex(romData.Info.Hash.PrgChrCrc32));
|
||||
Log("[UNIF] Board Name: " + _mapperName);
|
||||
Log("[UNIF] PRG ROM: " + std::to_string(romData.PrgRom.size() / 1024) + " KB");
|
||||
Log("[UNIF] CHR ROM: " + std::to_string(romData.ChrRom.size() / 1024) + " KB");
|
||||
if(romData.ChrRom.size() == 0) {
|
||||
Log("[UNIF] CHR RAM: 8 KB");
|
||||
}
|
||||
|
||||
string mirroringType;
|
||||
switch(romData.Info.Mirroring) {
|
||||
case MirroringType::Horizontal: mirroringType = "Horizontal"; break;
|
||||
case MirroringType::Vertical: mirroringType = "Vertical"; break;
|
||||
case MirroringType::ScreenAOnly: mirroringType = "1-Screen (A)"; break;
|
||||
case MirroringType::ScreenBOnly: mirroringType = "1-Screen (B)"; break;
|
||||
case MirroringType::FourScreens: mirroringType = "Four Screens"; break;
|
||||
}
|
||||
|
||||
Log("[UNIF] Mirroring: " + mirroringType);
|
||||
Log("[UNIF] Battery: " + string(romData.Info.HasBattery ? "Yes" : "No"));
|
||||
|
||||
if(!_checkOnly) {
|
||||
GameDatabase::SetGameInfo(romData.Info.Hash.PrgChrCrc32, romData, databaseEnabled, false);
|
||||
}
|
||||
|
||||
if(romData.Info.MapperID == UnifBoards::UnknownBoard) {
|
||||
if(!_checkOnly) {
|
||||
MessageManager::DisplayMessage("Error", "UnsupportedMapper", "UNIF: " + _mapperName);
|
||||
}
|
||||
romData.Error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<string, int> UnifLoader::_boardMappings = std::unordered_map<string, int> {
|
||||
{ "11160", 299 },
|
||||
{ "12-IN-1", 331 },
|
||||
{ "13in1JY110", UnifBoards::UnknownBoard },
|
||||
{ "190in1", 300 },
|
||||
{ "22211", 132 },
|
||||
{ "255in1", UnifBoards::Unl255in1 }, //Doesn't actually exist as a UNIF file (used to assign a mapper to the 255-in-1 rom)
|
||||
{ "3D-BLOCK", UnifBoards::UnknownBoard },
|
||||
{ "411120-C", 287 },
|
||||
{ "42in1ResetSwitch", 226 },
|
||||
{ "43272", 227 },
|
||||
{ "603-5052", 238 },
|
||||
{ "64in1NoRepeat", 314 },
|
||||
{ "70in1", 236 },
|
||||
{ "70in1B", 236 },
|
||||
{ "810544-C-A1", 261 },
|
||||
{ "830425C-4391T", 320 },
|
||||
{ "8157", 301 },
|
||||
{ "8237", 215 },
|
||||
{ "8237A", UnifBoards::Unl8237A },
|
||||
{ "830118C", 348 },
|
||||
{ "A65AS", 285 },
|
||||
{ "AC08", UnifBoards::Ac08 },
|
||||
{ "ANROM", 7 },
|
||||
{ "AX5705", 530 },
|
||||
{ "BB", 108 },
|
||||
{ "BS-5", 286 },
|
||||
{ "CC-21", UnifBoards::Cc21 },
|
||||
{ "CITYFIGHT", 266 },
|
||||
{ "COOLBOY", 268 },
|
||||
{ "10-24-C-A1", UnifBoards::UnknownBoard },
|
||||
{ "CNROM", 3 },
|
||||
{ "CPROM", 13 },
|
||||
{ "D1038", 59 },
|
||||
{ "DANCE", UnifBoards::UnknownBoard },
|
||||
{ "DANCE2000", 518 },
|
||||
{ "DREAMTECH01", 521 },
|
||||
{ "EDU2000", 329 },
|
||||
{ "EKROM", 5 },
|
||||
{ "ELROM", 5 },
|
||||
{ "ETROM", 5 },
|
||||
{ "EWROM", 5 },
|
||||
{ "FARID_SLROM_8-IN-1", 323 },
|
||||
{ "FARID_UNROM_8-IN-1", 324 },
|
||||
{ "FK23C", 176 },
|
||||
{ "FK23CA", 176 },
|
||||
{ "FS304", 162 },
|
||||
{ "G-146", 349 },
|
||||
{ "GK-192", 58 },
|
||||
{ "GS-2004", 283 },
|
||||
{ "GS-2013", UnifBoards::Gs2013 },
|
||||
{ "Ghostbusters63in1", UnifBoards::Ghostbusters63in1 },
|
||||
{ "H2288", 123 },
|
||||
{ "HKROM", 4 },
|
||||
{ "KOF97", 263 },
|
||||
{ "KONAMI-QTAI", 190 },
|
||||
{ "K-3046", 336 },
|
||||
{ "KS7010", UnifBoards::UnknownBoard },
|
||||
{ "KS7012", 346 },
|
||||
{ "KS7013B", 312 },
|
||||
{ "KS7016", 306 },
|
||||
{ "KS7017", 303 },
|
||||
{ "KS7030", UnifBoards::UnknownBoard },
|
||||
{ "KS7031", 305 },
|
||||
{ "KS7032", 142 },
|
||||
{ "KS7037", 307 },
|
||||
{ "KS7057", 302 },
|
||||
{ "LE05", UnifBoards::UnknownBoard },
|
||||
{ "LH10", 522 },
|
||||
{ "LH32", 125 },
|
||||
{ "LH51", 309 },
|
||||
{ "LH53", UnifBoards::UnknownBoard },
|
||||
{ "MALISB", 325 },
|
||||
{ "MARIO1-MALEE2", UnifBoards::Malee },
|
||||
{ "MHROM", 66 },
|
||||
{ "N625092", 221 },
|
||||
{ "NROM", 0 },
|
||||
{ "NROM-128", 0 },
|
||||
{ "NROM-256", 0 },
|
||||
{ "NTBROM", 68 },
|
||||
{ "NTD-03", 290 },
|
||||
{ "NovelDiamond9999999in1", 201 },
|
||||
{ "OneBus", UnifBoards::UnknownBoard },
|
||||
{ "PEC-586", UnifBoards::UnknownBoard },
|
||||
{ "PUZZLE", UnifBoards::UnlPuzzle }, //Doesn't actually exist as a UNIF file (used to reassign a new mapper number to the Puzzle beta)
|
||||
{ "RESET-TXROM", 313 },
|
||||
{ "RET-CUFROM", 29 },
|
||||
{ "RROM", 0 },
|
||||
{ "RROM-128", 0 },
|
||||
{ "SA-002", 136 },
|
||||
{ "SA-0036", 149 },
|
||||
{ "SA-0037", 148 },
|
||||
{ "SA-009", 160 },
|
||||
{ "SA-016-1M", 146 },
|
||||
{ "SA-72007", 145 },
|
||||
{ "SA-72008", 133 },
|
||||
{ "SA-9602B", 513 },
|
||||
{ "SA-NROM", 143 },
|
||||
{ "SAROM", 1 },
|
||||
{ "SBROM", 1 },
|
||||
{ "SC-127", 35 },
|
||||
{ "SCROM", 1 },
|
||||
{ "SEROM", 1 },
|
||||
{ "SGROM", 1 },
|
||||
{ "SHERO", 262 },
|
||||
{ "SKROM", 1 },
|
||||
{ "SL12", 116 },
|
||||
{ "SL1632", 14 },
|
||||
{ "SL1ROM", 1 },
|
||||
{ "SLROM", 1 },
|
||||
{ "SMB2J", 304 },
|
||||
{ "SNROM", 1 },
|
||||
{ "SOROM", 1 },
|
||||
{ "SSS-NROM-256", UnifBoards::SssNrom256 },
|
||||
{ "SUNSOFT_UNROM", 93 },
|
||||
{ "Sachen-74LS374N", 150 },
|
||||
{ "Sachen-74LS374NA", 243 },
|
||||
{ "Sachen-8259A", 141 },
|
||||
{ "Sachen-8259B", 138 },
|
||||
{ "Sachen-8259C", 139 },
|
||||
{ "Sachen-8259D", 137 },
|
||||
{ "Super24in1SC03", 176 },
|
||||
{ "SuperHIK8in1", 45 },
|
||||
{ "Supervision16in1", 53 },
|
||||
{ "T-227-1", UnifBoards::UnknownBoard },
|
||||
{ "T-230", 529 },
|
||||
{ "T-262", 265 },
|
||||
{ "TBROM", 4 },
|
||||
{ "TC-U01-1.5M", 147 },
|
||||
{ "TEK90", 90 },
|
||||
{ "TEROM", 4 },
|
||||
{ "TF1201", 298 },
|
||||
{ "TFROM", 4 },
|
||||
{ "TGROM", 4 },
|
||||
{ "TKROM", 4 },
|
||||
{ "TKSROM", 4 },
|
||||
{ "TLROM", 4 },
|
||||
{ "TLSROM", 4 },
|
||||
{ "TQROM", 4 },
|
||||
{ "TR1ROM", 4 },
|
||||
{ "TSROM", 4 },
|
||||
{ "TVROM", 4 },
|
||||
{ "Transformer", UnifBoards::UnknownBoard },
|
||||
{ "UNROM", 2 },
|
||||
{ "UNROM-512-8", 30 },
|
||||
{ "UNROM-512-16", 30 },
|
||||
{ "UNROM-512-32", 30 },
|
||||
{ "UOROM", 2 },
|
||||
{ "VRC7", 85 },
|
||||
{ "YOKO", 264 },
|
||||
{ "SB-2000", UnifBoards::UnknownBoard },
|
||||
{ "158B", 258 },
|
||||
{ "DRAGONFIGHTER", 292 },
|
||||
{ "EH8813A", 519 },
|
||||
{ "HP898F", 319 },
|
||||
{ "F-15", 259 },
|
||||
{ "RT-01", 328 },
|
||||
{ "81-01-31-C", UnifBoards::UnknownBoard },
|
||||
{ "8-IN-1", 333 },
|
||||
{ "WS", 332 },
|
||||
{ "80013-B", 274 },
|
||||
{ "WAIXING-FW01", 227 },
|
||||
{ "WAIXING-FS005", UnifBoards::UnknownBoard },
|
||||
{ "HPxx", 260 },
|
||||
{ "HP2018A", 260 },
|
||||
{ "DRIPGAME", 284 },
|
||||
{ "60311C", 289 },
|
||||
{ "CHINA_ER_SAN2", 19 }, //Appears to be a mapper 19 hack specific for VirtuaNES (which adds chinese text on top of the PPU's output), unknown if a board actually exists
|
||||
};
|
29
Core/NES/Loaders/UnifLoader.h
Normal file
29
Core/NES/Loaders/UnifLoader.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include <unordered_map>
|
||||
#include "NES/Loaders/BaseLoader.h"
|
||||
|
||||
struct RomData;
|
||||
|
||||
class UnifLoader : public BaseLoader
|
||||
{
|
||||
private:
|
||||
static std::unordered_map<string, int> _boardMappings;
|
||||
|
||||
vector<uint8_t> _prgChunks[16];
|
||||
vector<uint8_t> _chrChunks[16];
|
||||
string _mapperName;
|
||||
|
||||
void Read(uint8_t*& data, uint8_t& dest);
|
||||
void Read(uint8_t*& data, uint32_t& dest);
|
||||
void Read(uint8_t*& data, uint8_t* dest, size_t len);
|
||||
string ReadString(uint8_t*& data, uint8_t* chunkEnd);
|
||||
string ReadFourCC(uint8_t*& data);
|
||||
bool ReadChunk(uint8_t*& data, uint8_t* dataEnd, RomData& romData);
|
||||
|
||||
public:
|
||||
using BaseLoader::BaseLoader;
|
||||
|
||||
static int32_t GetMapperID(string mapperName);
|
||||
void LoadRom(RomData& romData, vector<uint8_t>& romFile, bool databaseEnabled);
|
||||
};
|
|
@ -7,7 +7,7 @@
|
|||
#include "NES/GameDatabase.h"
|
||||
#include "Shared/RomInfo.h"
|
||||
|
||||
void iNesLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, NesHeader *preloadedHeader)
|
||||
void iNesLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, NesHeader *preloadedHeader, bool databaseEnabled)
|
||||
{
|
||||
NesHeader header;
|
||||
uint8_t* buffer = romFile.data();
|
||||
|
@ -63,7 +63,7 @@ void iNesLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, NesHeader *
|
|||
uint32_t prgSize = 0;
|
||||
uint32_t chrSize = 0;
|
||||
|
||||
if(!GameDatabase::IsEnabled() || !GameDatabase::GetDbRomSize(romData.Info.Hash.PrgChrCrc32, prgSize, chrSize)) {
|
||||
if(!databaseEnabled || !GameDatabase::GetDbRomSize(romData.Info.Hash.PrgChrCrc32, prgSize, chrSize)) {
|
||||
//Fallback on header sizes when game is not in DB (or DB is disabled)
|
||||
prgSize = header.GetPrgSize();
|
||||
chrSize = header.GetChrSize();
|
||||
|
@ -132,7 +132,7 @@ void iNesLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, NesHeader *
|
|||
}
|
||||
|
||||
if(!_checkOnly) {
|
||||
GameDatabase::SetGameInfo(romData.Info.Hash.PrgChrCrc32, romData, GameDatabase::IsEnabled(), preloadedHeader != nullptr);
|
||||
GameDatabase::SetGameInfo(romData.Info.Hash.PrgChrCrc32, romData, databaseEnabled, preloadedHeader != nullptr);
|
||||
}
|
||||
|
||||
if(romData.Info.System == GameSystem::VsSystem) {
|
||||
|
|
|
@ -10,5 +10,5 @@ class iNesLoader : public BaseLoader
|
|||
public:
|
||||
using BaseLoader::BaseLoader;
|
||||
|
||||
void LoadRom(RomData& romData, vector<uint8_t>& romFile, NesHeader *preloadedHeader);
|
||||
void LoadRom(RomData& romData, vector<uint8_t>& romFile, NesHeader *preloadedHeader, bool databaseEnabled);
|
||||
};
|
|
@ -668,11 +668,9 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
|
|||
|
||||
unique_ptr<BaseMapper> MapperFactory::InitializeFromFile(NesConsole* console, VirtualFile &romFile, RomData &romData, LoadRomResult& result)
|
||||
{
|
||||
RomLoader loader;
|
||||
|
||||
if(loader.LoadFile(romFile)) {
|
||||
romData = loader.GetRomData();
|
||||
|
||||
romData = {};
|
||||
bool databaseEnabled = !console->GetNesConfig().DisableGameDatabase;
|
||||
if(RomLoader::LoadFile(romFile, romData, databaseEnabled)) {
|
||||
if((romData.Info.IsInDatabase || romData.Info.IsNes20Header) && romData.Info.InputType != GameInputType::Unspecified) {
|
||||
//If in DB or a NES 2.0 file, auto-configure the inputs
|
||||
//TODO NES
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
class OekaKids : public BaseMapper
|
||||
{
|
||||
uint8_t _outerChrBank;
|
||||
uint8_t _innerChrBank;
|
||||
uint16_t _lastAddress;
|
||||
uint8_t _outerChrBank = 0;
|
||||
uint8_t _innerChrBank = 0;
|
||||
uint16_t _lastAddress = 0;
|
||||
|
||||
protected:
|
||||
virtual uint16_t GetPRGPageSize() override { return 0x8000; }
|
||||
|
|
|
@ -8,11 +8,11 @@ class SunsoftFme7 : public BaseMapper
|
|||
{
|
||||
private:
|
||||
unique_ptr<Sunsoft5bAudio> _audio;
|
||||
uint8_t _command;
|
||||
uint8_t _workRamValue;
|
||||
bool _irqEnabled;
|
||||
bool _irqCounterEnabled;
|
||||
uint16_t _irqCounter;
|
||||
uint8_t _command = 0;
|
||||
uint8_t _workRamValue = 0;
|
||||
bool _irqEnabled = false;
|
||||
bool _irqCounterEnabled = false;
|
||||
uint16_t _irqCounter = 0;
|
||||
|
||||
protected:
|
||||
virtual uint16_t GetPRGPageSize() override { return 0x2000; }
|
||||
|
|
Loading…
Add table
Reference in a new issue