Namco 129/163/175/340 (Mapper 19 & 210) support (including audio)

This commit is contained in:
Souryo 2016-06-11 13:18:47 -04:00
parent 76600d31a9
commit d04551b0ae
13 changed files with 532 additions and 19 deletions

View file

@ -199,7 +199,13 @@ void BaseMapper::SelectCHRPage(uint16_t slot, uint16_t page, ChrMemoryType memor
uint16_t startAddr = slot * InternalGetChrPageSize();
uint16_t endAddr = startAddr + InternalGetChrPageSize() - 1;
SetPpuMemoryMapping(startAddr, endAddr, page, memoryType);
if(page == ChrSpecialPage::NametableA) {
SetPpuMemoryMapping(startAddr, endAddr, GetNametable(0));
} else if(page == ChrSpecialPage::NametableB) {
SetPpuMemoryMapping(startAddr, endAddr, GetNametable(1));
} else {
SetPpuMemoryMapping(startAddr, endAddr, page, memoryType);
}
}
bool BaseMapper::HasBattery()
@ -261,17 +267,27 @@ void BaseMapper::InitializeChrRam()
}
}
void BaseMapper::AddRegisterRange(uint16_t startAddr, uint16_t endAddr)
void BaseMapper::AddRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation)
{
for(int i = startAddr; i <= endAddr; i++) {
_isRegisterAddr[i] = true;
if((int)operation & (int)MemoryOperation::Read) {
_isReadRegisterAddr[i] = true;
}
if((int)operation & (int)MemoryOperation::Write) {
_isWriteRegisterAddr[i] = true;
}
}
}
void BaseMapper::RemoveRegisterRange(uint16_t startAddr, uint16_t endAddr)
void BaseMapper::RemoveRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation)
{
for(int i = startAddr; i <= endAddr; i++) {
_isRegisterAddr[i] = false;
if((int)operation & (int)MemoryOperation::Read) {
_isReadRegisterAddr[i] = false;
}
if((int)operation & (int)MemoryOperation::Write) {
_isWriteRegisterAddr[i] = false;
}
}
}
@ -315,8 +331,9 @@ void BaseMapper::Initialize(RomData &romData)
_allowRegisterRead = AllowRegisterRead();
memset(_isRegisterAddr, 0, sizeof(_isRegisterAddr));
AddRegisterRange(RegisterStartAddress(), RegisterEndAddress());
memset(_isReadRegisterAddr, 0, sizeof(_isReadRegisterAddr));
memset(_isWriteRegisterAddr, 0, sizeof(_isWriteRegisterAddr));
AddRegisterRange(RegisterStartAddress(), RegisterEndAddress(), MemoryOperation::Any);
_mirroringType = romData.MirroringType;
@ -513,7 +530,7 @@ MirroringType BaseMapper::GetMirroringType()
uint8_t BaseMapper::ReadRAM(uint16_t addr)
{
if(_allowRegisterRead && _isRegisterAddr[addr]) {
if(_allowRegisterRead && _isReadRegisterAddr[addr]) {
return ReadRegister(addr);
} else if(_prgPageAccessType[addr >> 8] & MemoryAccessType::Read) {
return _prgPages[addr >> 8][addr & 0xFF];
@ -525,7 +542,7 @@ uint8_t BaseMapper::ReadRAM(uint16_t addr)
void BaseMapper::WriteRAM(uint16_t addr, uint8_t value)
{
if(_isRegisterAddr[addr]) {
if(_isWriteRegisterAddr[addr]) {
if(_hasBusConflicts) {
value &= _prgPages[addr >> 8][addr & 0xFF];
}

View file

@ -29,6 +29,12 @@ enum MemoryAccessType
ReadWrite = 0x03
};
enum ChrSpecialPage
{
NametableA = 0x7000,
NametableB = 0x7001
};
class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificationListener
{
private:
@ -52,7 +58,8 @@ private:
string _romFilename;
bool _allowRegisterRead = false;
uint8_t _isRegisterAddr[0x10000];
uint8_t _isReadRegisterAddr[0x10000];
uint8_t _isWriteRegisterAddr[0x10000];
vector<uint8_t*> _prgPages;
vector<uint8_t*> _chrPages;
@ -67,7 +74,7 @@ private:
vector<uint8_t> _originalPrgRom;
protected:
uint8_t _mapperID;
uint16_t _mapperID;
uint8_t _subMapperID;
uint8_t* _prgRom = nullptr;
@ -135,8 +142,8 @@ protected:
void RestoreOriginalPrgRam();
void InitializeChrRam();
void AddRegisterRange(uint16_t startAddr, uint16_t endAddr);
void RemoveRegisterRange(uint16_t startAddr, uint16_t endAddr);
void AddRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any);
void RemoveRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any);
virtual void StreamState(bool saving);

View file

@ -439,6 +439,8 @@
<ClInclude Include="MMC3_52.h" />
<ClInclude Include="MMC3_ChrRam.h" />
<ClInclude Include="ModChannel.h" />
<ClInclude Include="Namco163.h" />
<ClInclude Include="Namco163Audio.h" />
<ClInclude Include="PlayerListMessage.h" />
<ClInclude Include="ReverbFilter.h" />
<ClInclude Include="RomData.h" />

View file

@ -598,6 +598,12 @@
<ClInclude Include="Vrc6Saw.h">
<Filter>Nes\Mappers\VRC</Filter>
</ClInclude>
<ClInclude Include="Namco163.h">
<Filter>Nes\Mappers\Namco</Filter>
</ClInclude>
<ClInclude Include="Namco163Audio.h">
<Filter>Nes\Mappers\Namco</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">

View file

@ -4,8 +4,9 @@
enum class MemoryOperation
{
Read = 0,
Write = 1,
Read = 1,
Write = 2,
Any = 3
};
class MemoryRanges

View file

@ -63,6 +63,7 @@
#include "Namco108_88.h"
#include "Namco108_95.h"
#include "Namco108_154.h"
#include "Namco163.h"
#include "Nanjing.h"
#include "Nina01.h"
#include "Nina03_06.h"
@ -115,7 +116,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
case 15: return new Mapper15();
case 16: break; //18 games
case 18: return new JalecoSs88006();
case 19: break; //16 games
case 19: return new Namco163();
case 21: return new VRC2_4(VRCVariant::VRC4a); //Conflicts: VRC4c
case 22: return new VRC2_4(VRCVariant::VRC2a);
case 23: return new VRC2_4(VRCVariant::VRC2b); //Conflicts: VRC4e
@ -203,6 +204,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
case 205: return new MMC3_205();
case 206: return new Namco108();
case 207: return new TaitoX1005(true);
case 210: return new Namco163();
case 225: return new Mapper225();
case 226: return new Mapper226();
case 230: return new Mapper230();

237
Core/Namco163.h Normal file
View file

@ -0,0 +1,237 @@
#pragma once
#include "stdafx.h"
#include "BaseMapper.h"
#include "Namco163Audio.h"
enum class NamcoVariant
{
Namco163,
Namco175,
Namco340,
Unknown,
};
class Namco163 : public BaseMapper
{
private:
Namco163Audio _audio;
NamcoVariant _variant;
bool _notNamco340;
bool _autoDetectVariant;
uint8_t _writeProtect;
bool _lowChrNtMode;
bool _highChrNtMode;
uint16_t _irqCounter;
void SetVariant(NamcoVariant variant)
{
if(_autoDetectVariant) {
if(!_notNamco340 || variant != NamcoVariant::Namco340) {
_variant = variant;
}
}
}
void UpdateSaveRamAccess()
{
PrgMemoryType memType = HasBattery() ? PrgMemoryType::SaveRam : PrgMemoryType::WorkRam;
if(_variant == NamcoVariant::Namco163) {
bool globalWriteEnable = (_writeProtect & 0x40) == 0x40;
SetCpuMemoryMapping(0x6000, 0x67FF, 0, memType, globalWriteEnable && (_writeProtect & 0x01) == 0x00 ? MemoryAccessType::ReadWrite : MemoryAccessType::Read);
SetCpuMemoryMapping(0x6800, 0x6FFF, 1, memType, globalWriteEnable && (_writeProtect & 0x02) == 0x00 ? MemoryAccessType::ReadWrite : MemoryAccessType::Read);
SetCpuMemoryMapping(0x7000, 0x77FF, 2, memType, globalWriteEnable && (_writeProtect & 0x04) == 0x00 ? MemoryAccessType::ReadWrite : MemoryAccessType::Read);
SetCpuMemoryMapping(0x7800, 0x7FFF, 3, memType, globalWriteEnable && (_writeProtect & 0x08) == 0x00 ? MemoryAccessType::ReadWrite : MemoryAccessType::Read);
} else if(_variant == NamcoVariant::Namco175) {
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, memType, (_writeProtect & 0x01) == 0x01 ? MemoryAccessType::ReadWrite : MemoryAccessType::Read);
} else {
SetCpuMemoryMapping(0x6000, 0x7FFF, 0, memType, MemoryAccessType::NoAccess);
}
}
protected:
virtual uint16_t GetPRGPageSize() { return 0x2000; }
virtual uint16_t GetCHRPageSize() { return 0x400; }
virtual uint32_t GetSaveRamPageSize() { return 0x800; }
virtual bool AllowRegisterRead() { return true; }
void InitMapper()
{
switch(_mapperID) {
case 19: _variant = NamcoVariant::Namco163; _autoDetectVariant = true; break;
case 210:
switch(_subMapperID) {
case 0: _variant = NamcoVariant::Unknown; _autoDetectVariant = true; break;
case 1: _variant = NamcoVariant::Namco175; _autoDetectVariant = false; break;
case 2: _variant = NamcoVariant::Namco340; _autoDetectVariant = false; break;
}
break;
}
_notNamco340 = false;
_writeProtect = 0;
_lowChrNtMode = false;
_highChrNtMode = false;
_irqCounter = 0;
AddRegisterRange(0x4800, 0x5FFF, MemoryOperation::Any);
RemoveRegisterRange(0x6000, 0xFFFF, MemoryOperation::Read);
SelectPRGPage(3, -1);
UpdateSaveRamAccess();
}
void StreamState(bool saving)
{
BaseMapper::StreamState(saving);
SnapshotInfo audio{ &_audio };
Stream(_variant, _notNamco340, _autoDetectVariant, _writeProtect, _lowChrNtMode, _highChrNtMode, _irqCounter, audio);
if(!saving) {
UpdateSaveRamAccess();
}
}
void ProcessCpuClock()
{
if(_irqCounter & 0x8000 && (_irqCounter & 0x7FFF) != 0x7FFF) {
_irqCounter++;
if((_irqCounter & 0x7FFF) == 0x7FFF) {
CPU::SetIRQSource(IRQSource::External);
}
}
if(_variant == NamcoVariant::Namco163) {
_audio.ProcessCpuClock();
}
}
void WriteRAM(uint16_t addr, uint8_t value)
{
if(addr >= 0x6000 && addr <= 0x7FFF) {
_notNamco340 = true;
if(_variant == NamcoVariant::Namco340) {
SetVariant(NamcoVariant::Unknown);
}
}
BaseMapper::WriteRAM(addr, value);
}
uint8_t ReadRegister(uint16_t addr)
{
switch(addr & 0xF800) {
case 0x4800: return _audio.ReadRegister(addr);
case 0x5000: return _irqCounter & 0xFF;
case 0x5800: return (_irqCounter >> 8);
default: return BaseMapper::ReadRegister(addr);
}
}
void WriteRegister(uint16_t addr, uint8_t value)
{
addr &= 0xF800;
switch(addr) {
case 0x4800:
SetVariant(NamcoVariant::Namco163);
_audio.WriteRegister(addr, value);
break;
case 0x5000:
SetVariant(NamcoVariant::Namco163);
_irqCounter = (_irqCounter & 0xFF00) | value;
CPU::ClearIRQSource(IRQSource::External);
break;
case 0x5800:
SetVariant(NamcoVariant::Namco163);
_irqCounter = (_irqCounter & 0x00FF) | (value << 8);
CPU::ClearIRQSource(IRQSource::External);
break;
case 0x8000: case 0x8800: case 0x9000: case 0x9800: {
uint8_t bankNumber = (addr - 0x8000) >> 11;
if(!_lowChrNtMode && value >= 0xE0 && _variant == NamcoVariant::Namco163) {
SelectCHRPage(bankNumber, (value & 0x01) == 0x01 ? ChrSpecialPage::NametableB : ChrSpecialPage::NametableA);
} else {
SelectCHRPage(bankNumber, value);
}
break;
}
case 0xA000: case 0xA800: case 0xB000: case 0xB800: {
uint8_t bankNumber = ((addr - 0xA000) >> 11) + 4;
if(!_highChrNtMode && value >= 0xE0 && _variant == NamcoVariant::Namco163) {
SelectCHRPage(bankNumber, (value & 0x01) == 0x01 ? ChrSpecialPage::NametableB : ChrSpecialPage::NametableA);
} else {
SelectCHRPage(bankNumber, value);
}
break;
}
case 0xC000: case 0xC800: case 0xD000: case 0xD800:
if(addr >= 0xC8000) {
SetVariant(NamcoVariant::Namco163);
} else if(_variant != NamcoVariant::Namco163) {
SetVariant(NamcoVariant::Namco175);
}
if(_variant == NamcoVariant::Namco175) {
_writeProtect = value;
UpdateSaveRamAccess();
} else {
uint8_t bankNumber = ((addr - 0xC000) >> 11) + 8;
if(value >= 0xE0) {
SelectCHRPage(bankNumber, (value & 0x01) == 0x01 ? ChrSpecialPage::NametableB : ChrSpecialPage::NametableA);
} else {
SelectCHRPage(bankNumber, value);
}
}
break;
case 0xE000:
if((value & 0x80) == 0x80) {
SetVariant(NamcoVariant::Namco340);
} else if((value & 0x40) == 0x40 && _variant != NamcoVariant::Namco163) {
SetVariant(NamcoVariant::Namco340);
}
SelectPRGPage(0, value & 0x3F);
if(_variant == NamcoVariant::Namco340) {
switch((value & 0xC0) >> 6) {
case 0: SetMirroringType(MirroringType::ScreenAOnly); break;
case 1: SetMirroringType(MirroringType::Vertical); break;
case 2: SetMirroringType(MirroringType::Horizontal); break;
case 3: SetMirroringType(MirroringType::ScreenBOnly); break;
}
} else if(_variant == NamcoVariant::Namco163) {
_audio.WriteRegister(addr, value);
}
break;
case 0xE800:
SelectPRGPage(1, value & 0x3F);
if(_variant == NamcoVariant::Namco163) {
_lowChrNtMode = (value & 0x40) == 0x40;
_highChrNtMode = (value & 0x80) == 0x80;
}
break;
case 0xF000:
SelectPRGPage(2, value & 0x3F);
break;
case 0xF800:
SetVariant(NamcoVariant::Namco163);
if(_variant == NamcoVariant::Namco163) {
_writeProtect = value;
UpdateSaveRamAccess();
_audio.WriteRegister(addr, value);
}
break;
}
}
};

185
Core/Namco163Audio.h Normal file
View file

@ -0,0 +1,185 @@
#pragma once
#include "stdafx.h"
#include "Snapshotable.h"
#include "APU.h"
class Namco163Audio : public Snapshotable
{
private:
uint8_t _internalRam[0x80];
int16_t _channelOutput[8];
uint8_t _ramPosition;
bool _autoIncrement;
uint8_t _updateCounter;
int8_t _currentChannel;
int16_t _lastOutput;
bool _disableSound;
enum SoundReg
{
FrequencyLow = 0x00,
PhaseLow = 0x01,
FrequencyMid = 0x02,
PhaseMid = 0x03,
FrequencyHigh = 0x04,
WaveLength = 0x04,
PhaseHigh = 0x05,
WaveAddress = 0x06,
Volume = 0x07
};
uint32_t GetFrequency(int channel)
{
uint8_t baseAddr = 0x40 + channel * 0x08;
return ((_internalRam[baseAddr + SoundReg::FrequencyHigh] & 0x03) << 16) | (_internalRam[baseAddr + SoundReg::FrequencyMid] << 8) | _internalRam[baseAddr + SoundReg::FrequencyLow];
}
uint32_t GetPhase(int channel)
{
uint8_t baseAddr = 0x40 + channel * 0x08;
return (_internalRam[baseAddr + SoundReg::PhaseHigh] << 16) | (_internalRam[baseAddr + SoundReg::PhaseMid] << 8) | _internalRam[baseAddr + SoundReg::PhaseLow];
}
void SetPhase(int channel, uint32_t phase)
{
uint8_t baseAddr = 0x40 + channel * 0x08;
_internalRam[baseAddr + SoundReg::PhaseHigh] = (phase >> 16) & 0xFF;
_internalRam[baseAddr + SoundReg::PhaseMid] = (phase >> 8) & 0xFF;
_internalRam[baseAddr + SoundReg::PhaseLow] = phase & 0xFF;
}
uint8_t GetWaveAddress(int channel)
{
uint8_t baseAddr = 0x40 + channel * 0x08;
return _internalRam[baseAddr + SoundReg::WaveAddress];
}
uint8_t GetWaveLength(int channel)
{
uint8_t baseAddr = 0x40 + channel * 0x08;
return 256 - (_internalRam[baseAddr + SoundReg::WaveLength] & 0xFC);
}
uint8_t GetVolume(int channel)
{
uint8_t baseAddr = 0x40 + channel * 0x08;
return _internalRam[baseAddr + SoundReg::Volume] & 0x0F;
}
uint8_t GetNumberOfChannels()
{
return (_internalRam[0x7F] >> 4) & 0x07;
}
void UpdateChannel(int channel)
{
uint32_t phase = GetPhase(channel);
uint32_t freq = GetFrequency(channel);
uint8_t length = GetWaveLength(channel);
uint8_t offset = GetWaveAddress(channel);
uint8_t volume = GetVolume(channel);
if(length == 0) {
phase = 0;
} else {
phase = (phase + freq) % (length << 16);
}
uint8_t samplePosition = ((phase >> 16) + offset) & 0xFF;
int8_t sample;
if((samplePosition & 0x01)) {
sample = _internalRam[samplePosition / 2] >> 4;
} else {
sample = _internalRam[samplePosition / 2] & 0x0F;
}
_channelOutput[channel] = (sample - 8) * volume;
UpdateOutputLevel();
SetPhase(channel, phase);
}
void UpdateOutputLevel()
{
int16_t summedOutput = 0;
for(int i = 7, min = 7 - GetNumberOfChannels(); i >= min; i--) {
summedOutput += _channelOutput[i];
}
summedOutput /= GetNumberOfChannels();
APU::AddExpansionAudioDelta(AudioChannel::Namco163, summedOutput - _lastOutput);
_lastOutput = summedOutput;
}
protected:
void StreamState(bool saving)
{
ArrayInfo<uint8_t> internalRam{ _internalRam, 0x80 };
ArrayInfo<int16_t> channelOutput{ _channelOutput, 8 };
Stream(internalRam, channelOutput, _ramPosition, _autoIncrement, _updateCounter, _currentChannel, _lastOutput);
}
public:
Namco163Audio()
{
memset(_internalRam, 0, sizeof(_internalRam));
memset(_channelOutput, 0, sizeof(_channelOutput));
_ramPosition = 0;
_autoIncrement = false;
_updateCounter = 0;
_currentChannel = 7;
_lastOutput = 0;
_disableSound = false;
}
void ProcessCpuClock()
{
if(!_disableSound && GetNumberOfChannels()) {
_updateCounter++;
if(_updateCounter == 15) {
UpdateChannel(_currentChannel);
_updateCounter = 0;
_currentChannel--;
if(_currentChannel < 7 - GetNumberOfChannels()) {
_currentChannel = 7;
}
}
}
}
void WriteRegister(uint16_t addr, uint8_t value)
{
switch(addr & 0xF800) {
case 0x4800:
_internalRam[_ramPosition] = value;
if(_autoIncrement) {
_ramPosition = (_ramPosition + 1) & 0x7F;
}
break;
case 0xE000:
_disableSound = (value & 0x40) == 0x40;
break;
case 0xF800:
_ramPosition = value & 0x7F;
_autoIncrement = (value & 0x80) == 0x80;
break;
}
}
uint8_t ReadRegister(uint16_t addr)
{
uint8_t value = 0;
switch(addr & 0xF800) {
case 0x4800: {
value = _internalRam[_ramPosition];
if(_autoIncrement) {
_ramPosition = (_ramPosition + 1) & 0x7F;
}
break;
}
}
return value;
}
};

View file

@ -2,6 +2,8 @@
#include "stdafx.h"
class Snapshotable;
template<typename T>
struct ArrayInfo
{
@ -16,6 +18,11 @@ struct ValueInfo
T DefaultValue;
};
struct SnapshotInfo
{
Snapshotable* Entity;
};
template<typename T>
struct EmptyInfo
{
@ -103,6 +110,12 @@ private:
StreamElement<T>(value);
}
template<>
void InternalStream(SnapshotInfo &info)
{
Stream(info.Entity);
}
void RecursiveStream()
{
}

View file

@ -152,6 +152,7 @@ int16_t SoundMixer::GetOutputVolume()
switch(_expansionAudioType) {
case AudioChannel::FDS: expansionOutput = (int16_t)(_currentOutput[ExpansionAudioIndex] * _volumes[ExpansionAudioIndex] * 20); break;
case AudioChannel::VRC6: expansionOutput = (int16_t)(_currentOutput[ExpansionAudioIndex] * _volumes[ExpansionAudioIndex] * 75); break;
case AudioChannel::Namco163: expansionOutput = (int16_t)(_currentOutput[ExpansionAudioIndex] * _volumes[ExpansionAudioIndex] * 20); break;
}
return squareVolume + tndVolume + expansionOutput;
}

View file

@ -3,6 +3,24 @@
#include "../Utilities/CRC32.h"
#include "MessageManager.h"
std::unordered_map<uint32_t, uint8_t> iNesLoader::_mapperByCrc = {
//Namco 175 games that are marked as mapper 19 but should be 210, submapper 1
{ 0x0C47946D, 210 }, //Chibi Maruko-chan: Uki Uki Shopping
{ 0x808606F0, 210 }, //Famista 91'
{ 0x81B7F1A8, 210 }, //Heisei Tensai Bakabon
{ 0x46FD7843, 210 }, //Splatterhouse: Wanpaku Graffiti
{ 0x1DC0F740, 210 }, //Wagyan Land 2
//Namco 340 games that are marked as mapper 19 but should be 210, submapper 2
{ 0xBD523011, 210 }, //Dream Master
{ 0xC247CC80, 210 }, //Family Circuit '91
{ 0x6EC51DE5, 210 }, //Famista '92
{ 0xADFFD64F, 210 }, //Famista '93
{ 0x429103C9, 210 }, //Famista '94
{ 0x2447E03B, 210 }, //Top Striker
{ 0xD323B806, 210 }, //Wagnyan Land 3
};
std::unordered_map<uint32_t, uint8_t> iNesLoader::_submapperByCrc = {
//MC-ACC Games (MMC3 variant) - Mapper 4, SubMapper 3
{ 0xC527C297, 3 }, //Alien 3
@ -27,6 +45,22 @@ std::unordered_map<uint32_t, uint8_t> iNesLoader::_submapperByCrc = {
//CAMERICA-BF9097 - Mapper 71, SubMapper 1
{ 0x1BC686A8, 1 }, //Fire Hawk
//Namco 175 games that are marked as mapper 19 but should be 210, submapper 1
{ 0x0C47946D, 1 }, //Chibi Maruko-chan: Uki Uki Shopping
{ 0x808606F0, 1 }, //Famista 91'
{ 0x81B7F1A8, 1 }, //Heisei Tensai Bakabon
{ 0x46FD7843, 1 }, //Splatterhouse: Wanpaku Graffiti
{ 0x1DC0F740, 1 }, //Wagyan Land 2
//Namco 340 games that are marked as mapper 19 but should be 210, submapper 2
{ 0xBD523011, 2 }, //Dream Master
{ 0xC247CC80, 2 }, //Family Circuit '91
{ 0x6EC51DE5, 2 }, //Famista '92
{ 0xADFFD64F, 2 }, //Famista '93
{ 0x429103C9, 2 }, //Famista '94
{ 0x2447E03B, 2 }, //Top Striker
{ 0xD323B806, 2 }, //Wagnyan Land 3
};
RomData iNesLoader::LoadRom(vector<uint8_t>& romFile)
@ -58,11 +92,19 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile)
if(header.GetRomHeaderVersion() != RomHeaderVersion::Nes2_0) {
//Check rom CRC to set submapper as needed
uint32_t romCrc = CRC32::GetCRC(buffer, header.GetPrgSize() + header.GetChrSize());
auto crcCheckResult = _submapperByCrc.find(romCrc);
auto crcCheckResult = _mapperByCrc.find(romCrc);
if(crcCheckResult != _mapperByCrc.end()) {
romData.MapperID = crcCheckResult->second;
#ifdef _DEBUG
MessageManager::DisplayMessage("GameInfo", "Mapper number corrected.");
#endif
}
crcCheckResult = _submapperByCrc.find(romCrc);
if(crcCheckResult != _submapperByCrc.end()) {
romData.SubMapperID = crcCheckResult->second;
#ifdef _DEBUG
MessageManager::DisplayMessage("GameInfo", "Header information corrected.");
MessageManager::DisplayMessage("GameInfo", "Submapper number corrected.");
#endif
}
}

View file

@ -6,6 +6,7 @@
class iNesLoader
{
private:
static std::unordered_map<uint32_t, uint8_t> _mapperByCrc;
static std::unordered_map<uint32_t, uint8_t> _submapperByCrc;
public:

View file

@ -298,7 +298,6 @@
// trkNamco163Vol
//
this.trkNamco163Vol.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.trkNamco163Vol.Enabled = false;
this.trkNamco163Vol.Location = new System.Drawing.Point(306, 160);
this.trkNamco163Vol.Margin = new System.Windows.Forms.Padding(0);
this.trkNamco163Vol.Maximum = 100;