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