Skip to content

Commit 4e5cd96

Browse files
NovaSquirrelmkwong98
authored andcommitted
Merge pull request SourMesen#116 from negativeExponent/mesenx
Add Mapper 413
1 parent 11ab8a2 commit 4e5cd96

File tree

8 files changed

+175
-1
lines changed

8 files changed

+175
-1
lines changed

Core/BaseMapper.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,12 @@ void BaseMapper::Initialize(RomData &romData)
633633
}
634634
}
635635

636+
if(romData.Info.MiscRoms) {
637+
_miscRomSize = (uint32_t)romData.MiscRomsData.size();
638+
_miscRom = new uint8_t[_miscRomSize];
639+
memcpy(_miscRom, romData.MiscRomsData.data(), _miscRomSize);
640+
}
641+
636642
SetupDefaultWorkRam();
637643

638644
SetMirroringType(romData.Info.Mirroring);
@@ -655,6 +661,7 @@ BaseMapper::~BaseMapper()
655661
delete[] _saveRam;
656662
delete[] _workRam;
657663
delete[] _nametableRam;
664+
delete[] _miscRom;
658665
}
659666

660667
void BaseMapper::GetMemoryRanges(MemoryRanges &ranges)

Core/BaseMapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public IBattery
7272
bool _hasChrBattery = false;
7373
int16_t _vramOpenBusValue = -1;
7474

75+
uint8_t* _miscRom = nullptr;
76+
uint32_t _miscRomSize = 0;
77+
7578
virtual void InitMapper() = 0;
7679
virtual void InitMapper(RomData &romData);
7780
virtual uint16_t GetPRGPageSize() = 0;

Core/Mapper413.h

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#pragma once
2+
#include "stdafx.h"
3+
#include "BaseMapper.h"
4+
#include "CPU.h"
5+
#include "A12Watcher.h"
6+
7+
class Mapper413 : public BaseMapper
8+
{
9+
private:
10+
uint32_t _serialAddress;
11+
uint8_t _serialControl;
12+
13+
uint8_t _irqCounter;
14+
uint8_t _irqReloadValue;
15+
bool _irqEnabled;
16+
17+
A12Watcher _a12Watcher;
18+
19+
protected:
20+
virtual uint16_t GetPRGPageSize() override { return 0x1000; }
21+
virtual uint16_t GetCHRPageSize() override { return 0x1000; }
22+
virtual bool AllowRegisterRead() override { return true; }
23+
24+
void InitMapper() override
25+
{
26+
_serialAddress = 0;
27+
_serialControl = 0;
28+
29+
_irqCounter = 0;
30+
_irqReloadValue = 0;
31+
_irqEnabled = false;
32+
33+
SetCpuMemoryMapping(0x5000, 0x5FFF, 1, PrgMemoryType::PrgRom);
34+
SetCpuMemoryMapping(0x6000, 0x6FFF, 0, PrgMemoryType::PrgRom);
35+
SetCpuMemoryMapping(0x7000, 0x7FFF, 1, PrgMemoryType::PrgRom);
36+
37+
SelectPrgPage2x(0, 0);
38+
SelectPrgPage2x(1, 0);
39+
SelectPRGPage(5, 0x07);
40+
SelectPRGPage(6, 0x08);
41+
SelectPRGPage(7, 0x09);
42+
43+
SelectCHRPage(0, 0);
44+
SelectCHRPage(1, -3);
45+
46+
AddRegisterRange(0x4800, 0x4FFF, MemoryOperation::Read);
47+
RemoveRegisterRange(0x8000, 0xBFFF, MemoryOperation::Read);
48+
RemoveRegisterRange(0xD000, 0xFFFF, MemoryOperation::Read);
49+
}
50+
51+
void StreamState(bool saving) override
52+
{
53+
BaseMapper::StreamState(saving);
54+
Stream(_serialAddress, _serialControl,
55+
_irqCounter, _irqReloadValue, _irqEnabled);
56+
}
57+
58+
void NotifyVRAMAddressChange(uint16_t addr) override
59+
{
60+
switch(_a12Watcher.UpdateVramAddress(addr, _console->GetPpu()->GetFrameCycle())) {
61+
case A12StateChange::None:
62+
case A12StateChange::Fall:
63+
break;
64+
65+
case A12StateChange::Rise:
66+
if(_irqCounter == 0) {
67+
_irqCounter = _irqReloadValue;
68+
} else {
69+
_irqCounter--;
70+
}
71+
if (_irqCounter == 0 && _irqEnabled) {
72+
_console->GetCpu()->SetIrqSource(IRQSource::External);
73+
}
74+
}
75+
}
76+
77+
uint8_t ReadRegister(uint16_t addr) override
78+
{
79+
if(_serialControl & 0x02) {
80+
return (_miscRom[_serialAddress++ & (_miscRomSize - 1)]);
81+
} else {
82+
return (_miscRom[_serialAddress & (_miscRomSize - 1)]);
83+
}
84+
}
85+
86+
void WriteRegister(uint16_t addr, uint8_t value) override
87+
{
88+
switch (addr & 0xF000) {
89+
case 0x8000:
90+
_irqReloadValue = value;
91+
break;
92+
93+
case 0x9000:
94+
_irqCounter = 0;
95+
break;
96+
97+
case 0xA000:
98+
case 0xB000:
99+
_irqEnabled = (addr & 0x1000) != 0;
100+
if (_irqEnabled == 0) {
101+
_console->GetCpu()->ClearIrqSource(IRQSource::External);
102+
}
103+
break;
104+
105+
case 0xC000:
106+
_serialAddress = (_serialAddress << 1) | (value >> 7);
107+
break;
108+
109+
case 0xD000:
110+
_serialControl = value;
111+
break;
112+
113+
case 0xE000:
114+
case 0xF000:
115+
switch(value >> 6) {
116+
case 0:
117+
value <<= 1;
118+
SetCpuMemoryMapping(0x6000, 0x7FFF, value, PrgMemoryType::PrgRom);
119+
break;
120+
121+
case 1:
122+
value <<= 1;
123+
SelectPRGPage(0, value);
124+
SelectPRGPage(1, value + 1);
125+
break;
126+
127+
case 2:
128+
value <<= 1;
129+
SelectPRGPage(2, value);
130+
SelectPRGPage(3, value + 1);
131+
break;
132+
133+
case 3:
134+
SelectCHRPage(0, value);
135+
break;
136+
}
137+
break;
138+
}
139+
}
140+
};

Core/MapperFactory.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@
193193
#include "Mapper417.h"
194194
#include "Mapper416.h"
195195
#include "Mapper415.h"
196+
#include "Mapper413.h"
196197
#include "Mapper414.h"
197198
#include "Mapper409.h"
198199
#include "Mapper403.h"
@@ -820,7 +821,7 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
820821
case 410: return new MMC3_410();
821822
case 411: return new MMC3_411();
822823
case 412: return new MMC3_412();
823-
//413
824+
case 413: return new Mapper413();
824825
case 414: return new Mapper414();
825826
case 415: return new Mapper415();
826827
case 416: return new Mapper416();

Core/NESHeader.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,12 @@ PpuModel NESHeader::GetVsSystemPpuModel()
239239
}
240240
return PpuModel::Ppu2C03;
241241
}
242+
243+
uint8_t NESHeader::GetMiscRoms()
244+
{
245+
if(GetRomHeaderVersion() == RomHeaderVersion::Nes2_0) {
246+
return (Byte14 & 0x03);
247+
} else {
248+
return 0;
249+
}
250+
}

Core/NESHeader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ struct NESHeader
4848
GameInputType GetInputType();
4949
VsSystemType GetVsSystemType();
5050
PpuModel GetVsSystemPpuModel();
51+
uint8_t GetMiscRoms();
5152
};

Core/RomData.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct RomInfo
8383
bool HasChrRam = false;
8484
bool HasBattery = false;
8585
bool HasTrainer = false;
86+
uint8_t MiscRoms = 0;
8687
MirroringType Mirroring = MirroringType::Horizontal;
8788
BusConflictType BusConflicts = BusConflictType::Default;
8889

@@ -119,6 +120,7 @@ struct RomData
119120
vector<uint8_t> PrgRom;
120121
vector<uint8_t> ChrRom;
121122
vector<uint8_t> TrainerData;
123+
vector<uint8_t> MiscRomsData;
122124
vector<vector<uint8_t>> FdsDiskData;
123125
vector<vector<uint8_t>> FdsDiskHeaders;
124126
StudyBoxData StudyBox;

Core/iNesLoader.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ void iNesLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, NESHeader *
3434
romData.Info.VsPpuModel = header.GetVsSystemPpuModel();
3535
romData.Info.InputType = header.GetInputType();
3636
romData.Info.HasTrainer = header.HasTrainer();
37+
romData.Info.MiscRoms = header.GetMiscRoms();
38+
3739
romData.Info.NesHeader = header;
3840

3941
romData.ChrRamSize = header.GetChrRamSize();
@@ -81,6 +83,12 @@ void iNesLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, NESHeader *
8183
romData.PrgRom.insert(romData.PrgRom.end(), buffer, buffer + prgSize);
8284
buffer += prgSize;
8385
romData.ChrRom.insert(romData.ChrRom.end(), buffer, buffer + chrSize);
86+
buffer += chrSize;
87+
88+
if(romData.Info.MiscRoms) {
89+
// Misc roms occupies the remaining bytes
90+
romData.MiscRomsData.insert(romData.MiscRomsData.end(), buffer, buffer + (dataSize - (prgSize + chrSize)));
91+
}
8492

8593
romData.Info.Hash.PrgCrc32 = CRC32::GetCRC(romData.PrgRom.data(), romData.PrgRom.size());
8694

@@ -125,6 +133,9 @@ void iNesLoader::LoadRom(RomData& romData, vector<uint8_t>& romFile, NESHeader *
125133
if(romData.Info.HasTrainer) {
126134
Log("[iNes] Trainer: Yes");
127135
}
136+
if(romData.MiscRomsData.size() > 0) {
137+
Log("[iNes] Misc ROMS: " + std::to_string((romData.MiscRomsData.size() / 1024)) + " KB");
138+
}
128139

129140
if(!_checkOnly) {
130141
GameDatabase::SetGameInfo(romData.Info.Hash.PrgChrCrc32, romData, GameDatabase::IsEnabled(), preloadedHeader != nullptr);

0 commit comments

Comments
 (0)