Skip to content

Commit 511a1d1

Browse files
committed
Arcade Card. Fix #37
1 parent 4823878 commit 511a1d1

21 files changed

Lines changed: 623 additions & 40 deletions

platforms/libretro/Makefile.common

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ SOURCES_C := $(SOURCE_DIR)/miniz/miniz.c
33
SOURCES_CXX := $(CORE_DIR)/libretro.cpp \
44
$(SOURCE_DIR)/adpcm.cpp \
55
$(SOURCE_DIR)/audio.cpp \
6+
$(SOURCE_DIR)/arcade_card_mapper.cpp \
67
$(SOURCE_DIR)/media.cpp \
78
$(SOURCE_DIR)/cdrom_audio.cpp \
89
$(SOURCE_DIR)/cdrom_media.cpp \

platforms/shared/desktop/gui_menus.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ static void menu_emulator(void)
437437
ImGui::BeginTooltip();
438438
ImGui::Text("It is recommended to leave this option on Auto.");
439439
ImGui::Text("Many USA games will fail to start on Japanese systems.");
440+
ImGui::Text("Reset the emulator to apply changes.");
440441
ImGui::EndTooltip();
441442
}
442443

@@ -454,6 +455,7 @@ static void menu_emulator(void)
454455
{
455456
ImGui::BeginTooltip();
456457
ImGui::Text("It is recommended to leave this option on Auto.");
458+
ImGui::Text("Reset the emulator to apply changes.");
457459
ImGui::EndTooltip();
458460
}
459461

@@ -469,6 +471,7 @@ static void menu_emulator(void)
469471
ImGui::BeginTooltip();
470472
ImGui::Text("This otion will add backup RAM support to HuCard games.");
471473
ImGui::Text("It is recommended to leave this option enabled.");
474+
ImGui::Text("Reset the emulator to apply changes.");
472475
ImGui::EndTooltip();
473476
}
474477

platforms/shared/desktop/makefiles/Makefile.sources

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ SOURCES_CXX := \
4242
$(SRC_DIR)/geargrafx_core.cpp \
4343
$(SRC_DIR)/adpcm.cpp \
4444
$(SRC_DIR)/audio.cpp \
45+
$(SRC_DIR)/arcade_card_mapper.cpp \
4546
$(SRC_DIR)/cdrom_audio.cpp \
4647
$(SRC_DIR)/cdrom_media.cpp \
4748
$(SRC_DIR)/cdrom.cpp \

platforms/windows/Geargrafx.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<ClCompile Include="..\..\src\miniz\miniz.c" />
2323
<ClCompile Include="..\..\src\adpcm.cpp" />
2424
<ClCompile Include="..\..\src\audio.cpp" />
25+
<ClCompile Include="..\..\src\arcade_card_mapper.cpp" />
2526
<ClCompile Include="..\..\src\media.cpp" />
2627
<ClCompile Include="..\..\src\cdrom_audio.cpp" />
2728
<ClCompile Include="..\..\src\cdrom_media.cpp" />
@@ -82,6 +83,7 @@
8283
<ClInclude Include="..\..\src\adpcm_inline.h" />
8384
<ClInclude Include="..\..\src\audio_inline.h" />
8485
<ClInclude Include="..\..\src\audio.h" />
86+
<ClInclude Include="..\..\src\arcade_card_mapper.h" />
8587
<ClInclude Include="..\..\src\bit_ops.h" />
8688
<ClInclude Include="..\..\src\media.h" />
8789
<ClInclude Include="..\..\src\media_inline.h" />

platforms/windows/Geargrafx.vcxproj.filters

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@
169169
<ClCompile Include="..\..\src\huc6202.cpp">
170170
<Filter>src</Filter>
171171
</ClCompile>
172+
<ClCompile Include="..\..\src\arcade_card_mapper.cpp">
173+
<Filter>src</Filter>
174+
</ClCompile>
172175
</ItemGroup>
173176
<ItemGroup>
174177
<ClInclude Include="..\shared\desktop\application.h">
@@ -459,6 +462,12 @@
459462
<ClInclude Include="..\..\src\huc6202_inline.h">
460463
<Filter>src</Filter>
461464
</ClInclude>
465+
<ClInclude Include="..\..\src\arcade_card_mapper.h">
466+
<Filter>src</Filter>
467+
</ClInclude>
468+
<ClInclude Include="..\..\src\arcade_card_mapper_inline.h">
469+
<Filter>src</Filter>
470+
</ClInclude>
462471
</ItemGroup>
463472
<ItemGroup>
464473
<Filter Include="src">

src/arcade_card_mapper.cpp

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
/*
2+
* Geargrafx - PC Engine / TurboGrafx Emulator
3+
* Copyright (C) 2024 Ignacio Sanchez
4+
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* any later version.
9+
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/
17+
*
18+
*/
19+
20+
#include "arcade_card_mapper.h"
21+
#include "media.h"
22+
#include "memory.h"
23+
24+
ArcadeCardMapper::ArcadeCardMapper(Media* media, Memory* memory) : Mapper(media, memory)
25+
{
26+
Reset();
27+
InitPointer(m_card_memory);
28+
m_card_memory = new u8[0x200000];
29+
}
30+
31+
ArcadeCardMapper::~ArcadeCardMapper()
32+
{
33+
SafeDeleteArray(m_card_memory);
34+
}
35+
36+
u8 ArcadeCardMapper::Read(u8 bank, u16 address)
37+
{
38+
if (bank >= 0x40 && bank <= 0x43)
39+
return ReadPortData(bank - 0x40);
40+
else
41+
return m_memory->GetMemoryMap()[bank][address];
42+
}
43+
44+
void ArcadeCardMapper::Write(u8 bank, u16 address, u8 value)
45+
{
46+
if (bank >= 0x40 && bank <= 0x43)
47+
WritePortData(bank - 0x40, value);
48+
else if (m_memory->GetMemoryMapWrite()[bank])
49+
m_memory->GetMemoryMap()[bank][address] = value;
50+
}
51+
52+
u8 ArcadeCardMapper::ReadHardware(u16 address)
53+
{
54+
if (address < 0x1A40)
55+
{
56+
u8 port = (address >> 4) & 0x03;
57+
u8 reg = address & 0x0F;
58+
return ReadPortRegister(port, reg);
59+
}
60+
else if (address < 0x1B00)
61+
return ReadRegister(address & 0xFF);
62+
else
63+
{
64+
Debug("Invalid Arcade Card hardware read at %04X", address);
65+
return 0xFF;
66+
}
67+
}
68+
69+
void ArcadeCardMapper::WriteHardware(u16 address, u8 value)
70+
{
71+
if (address < 0x1A40)
72+
{
73+
u8 port = (address >> 4) & 0x03;
74+
u8 reg = address & 0x0F;
75+
WritePortRegister(port, reg, value);
76+
}
77+
else if (address < 0x1B00)
78+
WriteRegister(address & 0xFF, value);
79+
else
80+
{
81+
Debug("Invalid Arcade Card hardware write at %04X, value=%02X", address, value);
82+
}
83+
}
84+
85+
void ArcadeCardMapper::Reset()
86+
{
87+
m_register = 0;
88+
m_shift_amount = 0;
89+
m_rotate_amount = 0;
90+
91+
for (int i = 0; i < 4; ++i)
92+
{
93+
m_ports[i].base = 0;
94+
m_ports[i].offset = 0;
95+
m_ports[i].increment = 0;
96+
m_ports[i].control = 0;
97+
m_ports[i].add_offset = false;
98+
m_ports[i].auto_increment = false;
99+
m_ports[i].signed_offset = false;
100+
m_ports[i].increment_base = false;
101+
m_ports[i].offset_trigger = OFFSET_TRIGGER_NONE;
102+
}
103+
}
104+
105+
u8 ArcadeCardMapper::ReadPortRegister(u8 port, u8 reg)
106+
{
107+
switch (reg)
108+
{
109+
case 0x00:
110+
case 0x01:
111+
return ReadPortData(port);
112+
case 0x02:
113+
return m_ports[port].base & 0xFF;
114+
case 0x03:
115+
return (m_ports[port].base >> 8) & 0xFF;
116+
case 0x04:
117+
return (m_ports[port].base >> 16) & 0xFF;
118+
case 0x05:
119+
return m_ports[port].offset & 0xFF;
120+
case 0x06:
121+
return (m_ports[port].offset >> 8) & 0xFF;
122+
case 0x07:
123+
return m_ports[port].increment & 0xFF;
124+
case 0x08:
125+
return (m_ports[port].increment >> 8) & 0xFF;
126+
case 0x09:
127+
return m_ports[port].control;
128+
case 0x0A:
129+
return 0;
130+
default:
131+
Debug("Invalid Arcade Card port register read at %02X:%02X", port, reg);
132+
return 0xFF;
133+
}
134+
}
135+
136+
void ArcadeCardMapper::WritePortRegister(u8 port, u8 reg, u8 value)
137+
{
138+
switch (reg)
139+
{
140+
case 0x00:
141+
case 0x01:
142+
WritePortData(port, value);
143+
break;
144+
case 0x02:
145+
m_ports[port].base = (m_ports[port].base & 0xFFFF00) | value;
146+
break;
147+
case 0x03:
148+
m_ports[port].base = (m_ports[port].base & 0xFF00FF) | (value << 8);
149+
break;
150+
case 0x04:
151+
m_ports[port].base = (m_ports[port].base & 0x00FFFF) | (value << 16);
152+
break;
153+
case 0x05:
154+
m_ports[port].offset = (m_ports[port].offset & 0xFF00) | value;
155+
if (m_ports[port].offset_trigger == OFFSET_TRIGGER_LOW__BYTE)
156+
AddOffset(port);
157+
break;
158+
case 0x06:
159+
m_ports[port].offset = (m_ports[port].offset & 0x00FF) | (value << 8);
160+
if (m_ports[port].offset_trigger == OFFSET_TRIGGER_HIGH_BYTE)
161+
AddOffset(port);
162+
break;
163+
case 0x07:
164+
m_ports[port].increment = (m_ports[port].increment & 0xFF00) | value;
165+
break;
166+
case 0x08:
167+
m_ports[port].increment = (m_ports[port].increment & 0x00FF) | (value << 8);
168+
break;
169+
case 0x09:
170+
WriteControlRegister(port, value);
171+
break;
172+
case 0x0A:
173+
if (m_ports[port].offset_trigger == OFFSET_TRIGGER_REG_0A)
174+
AddOffset(port);
175+
break;
176+
default:
177+
Debug("Invalid Arcade Card port register write at %02X:%02X, value=%02X", port, reg, value);
178+
break;
179+
}
180+
}
181+
182+
u8 ArcadeCardMapper::ReadRegister(u8 reg)
183+
{
184+
switch (reg)
185+
{
186+
case 0xE0:
187+
case 0xE1:
188+
case 0xE2:
189+
case 0xE3:
190+
{
191+
int dis = (reg & 0x03) << 3;
192+
return (m_register >> dis) & 0xFF;
193+
}
194+
case 0xE4:
195+
return m_shift_amount;
196+
case 0xE5:
197+
return m_rotate_amount;
198+
case 0xEC:
199+
case 0xED:
200+
return 0x00;
201+
case 0xFE:
202+
return 0x10;
203+
case 0xFF:
204+
return 0x51;
205+
default:
206+
Debug("Invalid Arcade Card register read at %02X", reg);
207+
return 0xFF;
208+
}
209+
}
210+
211+
void ArcadeCardMapper::WriteRegister(u8 reg, u8 value)
212+
{
213+
switch (reg)
214+
{
215+
case 0xE0:
216+
case 0xE1:
217+
case 0xE2:
218+
case 0xE3:
219+
{
220+
int dis = (reg & 0x03) << 3;
221+
m_register = (m_register & ~(0xFF << dis)) | (value << dis);
222+
break;
223+
}
224+
case 0xE4:
225+
m_shift_amount = value;
226+
if(value != 0)
227+
{
228+
s8 signed_amount = (s8)(value << 4) >> 4;
229+
230+
if (signed_amount > 0)
231+
{
232+
u8 n = (u8)(signed_amount);
233+
m_register <<= n;
234+
}
235+
else if (signed_amount < 0)
236+
{
237+
u8 n = (u8)(-signed_amount);
238+
m_register >>= n;
239+
}
240+
}
241+
break;
242+
case 0xE5:
243+
m_rotate_amount = value;
244+
if (value != 0)
245+
{
246+
s8 signed_amount = (s8)(value << 4) >> 4;
247+
248+
if (signed_amount > 0)
249+
{
250+
u8 n = (u8)(signed_amount);
251+
m_register = (m_register << n) | (m_register >> (32 - n));
252+
}
253+
else if (signed_amount < 0)
254+
{
255+
u8 n = (u8)(-signed_amount);
256+
m_register = (m_register >> n) | (m_register << (32 - n));
257+
}
258+
}
259+
break;
260+
default:
261+
Debug("Invalid Arcade Card register write at %02X, value=%02X", reg, value);
262+
break;
263+
}
264+
}
265+
266+
void ArcadeCardMapper::SaveState(std::ostream& stream)
267+
{
268+
using namespace std;
269+
stream.write(reinterpret_cast<const char*> (&m_register), sizeof(m_register));
270+
stream.write(reinterpret_cast<const char*> (&m_shift_amount), sizeof(m_shift_amount));
271+
stream.write(reinterpret_cast<const char*> (&m_rotate_amount), sizeof(m_rotate_amount));
272+
273+
for (int i = 0; i < 4; ++i)
274+
{
275+
stream.write(reinterpret_cast<const char*> (&m_ports[i].base), sizeof(m_ports[i].base));
276+
stream.write(reinterpret_cast<const char*> (&m_ports[i].offset), sizeof(m_ports[i].offset));
277+
stream.write(reinterpret_cast<const char*> (&m_ports[i].increment), sizeof(m_ports[i].increment));
278+
stream.write(reinterpret_cast<const char*> (&m_ports[i].control), sizeof(m_ports[i].control));
279+
stream.write(reinterpret_cast<const char*> (&m_ports[i].add_offset), sizeof(m_ports[i].add_offset));
280+
stream.write(reinterpret_cast<const char*> (&m_ports[i].auto_increment), sizeof(m_ports[i].auto_increment));
281+
stream.write(reinterpret_cast<const char*> (&m_ports[i].signed_offset), sizeof(m_ports[i].signed_offset));
282+
stream.write(reinterpret_cast<const char*> (&m_ports[i].increment_base), sizeof(m_ports[i].increment_base));
283+
stream.write(reinterpret_cast<const char*> (&m_ports[i].offset_trigger), sizeof(m_ports[i].offset_trigger));
284+
}
285+
286+
stream.write(reinterpret_cast<const char*>(m_card_memory), 0x200000);
287+
}
288+
289+
void ArcadeCardMapper::LoadState(std::istream& stream)
290+
{
291+
using namespace std;
292+
stream.read(reinterpret_cast<char*> (&m_register), sizeof(m_register));
293+
stream.read(reinterpret_cast<char*> (&m_shift_amount), sizeof(m_shift_amount));
294+
stream.read(reinterpret_cast<char*> (&m_rotate_amount), sizeof(m_rotate_amount));
295+
296+
for (int i = 0; i < 4; ++i)
297+
{
298+
stream.read(reinterpret_cast<char*> (&m_ports[i].base), sizeof(m_ports[i].base));
299+
stream.read(reinterpret_cast<char*> (&m_ports[i].offset), sizeof(m_ports[i].offset));
300+
stream.read(reinterpret_cast<char*> (&m_ports[i].increment), sizeof(m_ports[i].increment));
301+
stream.read(reinterpret_cast<char*> (&m_ports[i].control), sizeof(m_ports[i].control));
302+
stream.read(reinterpret_cast<char*> (&m_ports[i].add_offset), sizeof(m_ports[i].add_offset));
303+
stream.read(reinterpret_cast<char*> (&m_ports[i].auto_increment), sizeof(m_ports[i].auto_increment));
304+
stream.read(reinterpret_cast<char*> (&m_ports[i].signed_offset), sizeof(m_ports[i].signed_offset));
305+
stream.read(reinterpret_cast<char*> (&m_ports[i].increment_base), sizeof(m_ports[i].increment_base));
306+
stream.read(reinterpret_cast<char*> (&m_ports[i].offset_trigger), sizeof(m_ports[i].offset_trigger));
307+
}
308+
309+
stream.read(reinterpret_cast<char*>(m_card_memory), 0x200000);
310+
}

0 commit comments

Comments
 (0)