1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /***********************************************************************************************************
4
5 A2600 VCS ROM cart emulation
6 Simple cart hardware with no additional hw
7
8 Mapper implementation based on the wonderful docs by Kevtris
9 http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt
10
11 (also inspired by previous work by Wilbert Pol et al.)
12
13 ***********************************************************************************************************/
14
15
16 #include "emu.h"
17 #include "rom.h"
18
19
20 //-------------------------------------------------
21 // a26_rom_*k_device - constructor
22 //-------------------------------------------------
23
24 DEFINE_DEVICE_TYPE(A26_ROM_2K, a26_rom_2k_device, "vcs_2k", "Atari VCS 2600 2K ROM Carts")
25 DEFINE_DEVICE_TYPE(A26_ROM_4K, a26_rom_4k_device, "vcs_4k", "Atari VCS 2600 4K ROM Carts")
26 DEFINE_DEVICE_TYPE(A26_ROM_F4, a26_rom_f4_device, "vcs_f4", "Atari VCS 2600 ROM Carts w/F4 bankswitch")
27 DEFINE_DEVICE_TYPE(A26_ROM_F6, a26_rom_f6_device, "vcs_f6", "Atari VCS 2600 ROM Carts w/F6 bankswitch")
28 DEFINE_DEVICE_TYPE(A26_ROM_F8, a26_rom_f8_device, "vcs_f8", "Atari VCS 2600 ROM Carts w/F8 bankswitch")
29 DEFINE_DEVICE_TYPE(A26_ROM_F8_SW, a26_rom_f8_sw_device, "vcs_f8_sw", "Atari VCS 2600 ROM Cart Snow White")
30 DEFINE_DEVICE_TYPE(A26_ROM_FA, a26_rom_fa_device, "vcs_fa", "Atari VCS 2600 ROM Carts w/FA bankswitch")
31 DEFINE_DEVICE_TYPE(A26_ROM_FE, a26_rom_fe_device, "vcs_fe", "Atari VCS 2600 ROM Carts w/FE bankswitch")
32 DEFINE_DEVICE_TYPE(A26_ROM_3E, a26_rom_3e_device, "vcs_3e", "Atari VCS 2600 ROM Carts w/3E bankswitch")
33 DEFINE_DEVICE_TYPE(A26_ROM_3F, a26_rom_3f_device, "vcs_3f", "Atari VCS 2600 ROM Carts w/3F bankswitch")
34 DEFINE_DEVICE_TYPE(A26_ROM_E0, a26_rom_e0_device, "vcs_e0", "Atari VCS 2600 ROM Carts w/E0 bankswitch")
35 DEFINE_DEVICE_TYPE(A26_ROM_E7, a26_rom_e7_device, "vcs_e7", "Atari VCS 2600 ROM Carts w/E7 bankswitch")
36 DEFINE_DEVICE_TYPE(A26_ROM_UA, a26_rom_ua_device, "vcs_ua", "Atari VCS 2600 ROM Carts w/UA bankswitch")
37 DEFINE_DEVICE_TYPE(A26_ROM_CV, a26_rom_cv_device, "vcs_cv", "Atari VCS 2600 ROM Carts w/Commavid bankswitch")
38 DEFINE_DEVICE_TYPE(A26_ROM_DC, a26_rom_dc_device, "vcs_dc", "Atari VCS 2600 ROM Carts w/Dynacom bankswitch")
39 DEFINE_DEVICE_TYPE(A26_ROM_FV, a26_rom_fv_device, "vcs_fv", "Atari VCS 2600 ROM Carts w/FV bankswitch")
40 DEFINE_DEVICE_TYPE(A26_ROM_JVP, a26_rom_jvp_device, "vcs_jvp", "Atari VCS 2600 ROM Carts w/JVP bankswitch")
41 DEFINE_DEVICE_TYPE(A26_ROM_4IN1, a26_rom_4in1_device, "vcs_4in1", "Atari VCS 2600 ROM Cart 4 in 1")
42 DEFINE_DEVICE_TYPE(A26_ROM_8IN1, a26_rom_8in1_device, "vcs_8in1", "Atari VCS 2600 ROM Cart 8 in 1")
43 DEFINE_DEVICE_TYPE(A26_ROM_32IN1, a26_rom_32in1_device, "vcs_32in1", "Atari VCS 2600 ROM Cart 32 in 1")
44 DEFINE_DEVICE_TYPE(A26_ROM_X07, a26_rom_x07_device, "vcs_x07", "Atari VCS 2600 ROM Carts w/X07 bankswitch")
45
46
a26_rom_2k_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)47 a26_rom_2k_device::a26_rom_2k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
48 : device_t(mconfig, type, tag, owner, clock), device_vcs_cart_interface(mconfig, *this)
49 {
50 }
51
a26_rom_2k_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)52 a26_rom_2k_device::a26_rom_2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
53 : a26_rom_2k_device(mconfig, A26_ROM_2K, tag, owner, clock)
54 {
55 }
56
57
a26_rom_4k_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)58 a26_rom_4k_device::a26_rom_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
59 : a26_rom_2k_device(mconfig, A26_ROM_4K, tag, owner, clock)
60 {
61 }
62
63
a26_rom_f6_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)64 a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
65 : a26_rom_2k_device(mconfig, type, tag, owner, clock)
66 , m_base_bank(-1) // set to -1 to help the Xin1 multicart...
67 {
68 }
69
a26_rom_f6_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)70 a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
71 : a26_rom_f6_device(mconfig, A26_ROM_F6, tag, owner, clock)
72 {
73 }
74
75
a26_rom_f4_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)76 a26_rom_f4_device::a26_rom_f4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
77 : a26_rom_f6_device(mconfig, A26_ROM_F4, tag, owner, clock)
78 {
79 }
80
81
a26_rom_f8_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)82 a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
83 : a26_rom_f6_device(mconfig, type, tag, owner, clock)
84 {
85 }
86
a26_rom_f8_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)87 a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
88 : a26_rom_f8_device(mconfig, A26_ROM_F8, tag, owner, clock)
89 {
90 }
91
a26_rom_f8_sw_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)92 a26_rom_f8_sw_device::a26_rom_f8_sw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
93 : a26_rom_f8_device(mconfig, A26_ROM_F8_SW, tag, owner, clock)
94 {
95 }
96
a26_rom_fa_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)97 a26_rom_fa_device::a26_rom_fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
98 : a26_rom_f6_device(mconfig, A26_ROM_FA, tag, owner, clock)
99 {
100 }
101
102
a26_rom_fe_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)103 a26_rom_fe_device::a26_rom_fe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
104 : a26_rom_2k_device(mconfig, A26_ROM_FE, tag, owner, clock), m_base_bank(0), m_trigger_on_next_access(0)
105 {
106 }
107
108
a26_rom_3e_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)109 a26_rom_3e_device::a26_rom_3e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
110 : a26_rom_f6_device(mconfig, A26_ROM_3E, tag, owner, clock), m_num_bank(0), m_ram_bank(0), m_ram_enable(0)
111 {
112 }
113
114
a26_rom_3f_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)115 a26_rom_3f_device::a26_rom_3f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
116 : a26_rom_f6_device(mconfig, A26_ROM_3F, tag, owner, clock), m_num_bank(0)
117 {
118 }
119
120
a26_rom_e0_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)121 a26_rom_e0_device::a26_rom_e0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
122 : a26_rom_f6_device(mconfig, A26_ROM_E0, tag, owner, clock)
123 {
124 }
125
126
a26_rom_e7_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)127 a26_rom_e7_device::a26_rom_e7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
128 : a26_rom_f6_device(mconfig, A26_ROM_E7, tag, owner, clock), m_ram_bank(0)
129 {
130 }
131
132
a26_rom_ua_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)133 a26_rom_ua_device::a26_rom_ua_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
134 : a26_rom_f6_device(mconfig, A26_ROM_UA, tag, owner, clock)
135 {
136 }
137
138
a26_rom_cv_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)139 a26_rom_cv_device::a26_rom_cv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
140 : a26_rom_2k_device(mconfig, A26_ROM_CV, tag, owner, clock)
141 {
142 }
143
144
a26_rom_dc_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)145 a26_rom_dc_device::a26_rom_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
146 : a26_rom_f6_device(mconfig, A26_ROM_DC, tag, owner, clock)
147 {
148 }
149
150
a26_rom_fv_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)151 a26_rom_fv_device::a26_rom_fv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
152 : a26_rom_f6_device(mconfig, A26_ROM_FV, tag, owner, clock), m_locked(0)
153 {
154 }
155
156
a26_rom_jvp_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)157 a26_rom_jvp_device::a26_rom_jvp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
158 : a26_rom_f6_device(mconfig, A26_ROM_JVP, tag, owner, clock)
159 {
160 }
161
162
a26_rom_4in1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)163 a26_rom_4in1_device::a26_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
164 : a26_rom_f6_device(mconfig, A26_ROM_4IN1, tag, owner, clock)
165 {
166 }
167
168
a26_rom_8in1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)169 a26_rom_8in1_device::a26_rom_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
170 : a26_rom_f8_device(mconfig, A26_ROM_8IN1, tag, owner, clock), m_reset_bank(0)
171 {
172 }
173
174
a26_rom_32in1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)175 a26_rom_32in1_device::a26_rom_32in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
176 : a26_rom_f6_device(mconfig, A26_ROM_32IN1, tag, owner, clock)
177 {
178 }
179
a26_rom_x07_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)180 a26_rom_x07_device::a26_rom_x07_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
181 : a26_rom_f6_device(mconfig, A26_ROM_X07, tag, owner, clock)
182 {
183 }
184
185
device_start()186 void a26_rom_2k_device::device_start()
187 {
188 }
189
device_reset()190 void a26_rom_2k_device::device_reset()
191 {
192 }
193
device_start()194 void a26_rom_f6_device::device_start()
195 {
196 save_item(NAME(m_base_bank));
197 }
198
device_reset()199 void a26_rom_f6_device::device_reset()
200 {
201 m_base_bank = 0;
202 }
203
device_reset()204 void a26_rom_f4_device::device_reset()
205 {
206 m_base_bank = 7;
207 }
208
device_reset()209 void a26_rom_f8_sw_device::device_reset()
210 {
211 // Snow White proto starts from bank 1!!!
212 m_base_bank = 1;
213 }
214
device_start()215 void a26_rom_fe_device::device_start()
216 {
217 save_item(NAME(m_base_bank));
218 save_item(NAME(m_trigger_on_next_access));
219 }
220
device_reset()221 void a26_rom_fe_device::device_reset()
222 {
223 m_base_bank = 0;
224 m_trigger_on_next_access = 0;
225 }
226
device_start()227 void a26_rom_3e_device::device_start()
228 {
229 save_item(NAME(m_base_bank));
230 save_item(NAME(m_ram_bank));
231 save_item(NAME(m_ram_enable));
232 }
233
device_reset()234 void a26_rom_3e_device::device_reset()
235 {
236 m_num_bank = m_rom_size / 0x800;
237 m_base_bank = m_num_bank - 1;
238 m_ram_bank = 0;
239 m_ram_enable = 0;
240 }
241
device_reset()242 void a26_rom_3f_device::device_reset()
243 {
244 m_num_bank = m_rom_size / 0x800;
245 m_base_bank = m_num_bank - 1;
246 }
247
device_start()248 void a26_rom_e0_device::device_start()
249 {
250 save_item(NAME(m_base_banks));
251 }
252
device_reset()253 void a26_rom_e0_device::device_reset()
254 {
255 m_base_banks[0] = 4;
256 m_base_banks[1] = 5;
257 m_base_banks[2] = 6;
258 m_base_banks[3] = 7;
259 }
260
device_start()261 void a26_rom_e7_device::device_start()
262 {
263 save_item(NAME(m_base_bank));
264 save_item(NAME(m_ram_bank));
265 }
266
device_reset()267 void a26_rom_e7_device::device_reset()
268 {
269 m_base_bank = 0;
270 m_ram_bank = 0;
271 }
272
device_reset()273 void a26_rom_ua_device::device_reset()
274 {
275 m_base_bank = 0;
276 }
277
device_start()278 void a26_rom_fv_device::device_start()
279 {
280 save_item(NAME(m_base_bank));
281 save_item(NAME(m_locked));
282 }
283
device_reset()284 void a26_rom_fv_device::device_reset()
285 {
286 m_base_bank = 0;
287 m_locked = 0;
288 }
289
290
device_reset()291 void a26_rom_4in1_device::device_reset()
292 {
293 m_base_bank++;
294 m_base_bank &= 3;
295 }
296
297
device_start()298 void a26_rom_8in1_device::device_start()
299 {
300 save_item(NAME(m_base_bank));
301 save_item(NAME(m_reset_bank));
302 }
303
device_reset()304 void a26_rom_8in1_device::device_reset()
305 {
306 // we use here two different bank counter: the main one for the 8x8K chunks,
307 // and the usual one (m_base_bank) for the 4K bank of the current game
308 m_reset_bank++;
309 m_reset_bank &= 7;
310 m_base_bank = 0;
311 }
312
313
device_reset()314 void a26_rom_32in1_device::device_reset()
315 {
316 m_base_bank++;
317 m_base_bank &= 0x1f;
318 }
319
320
321 /*-------------------------------------------------
322 mapper specific handlers
323 -------------------------------------------------*/
324
325 /*-------------------------------------------------
326 BASE 2K & 4K Carts:
327 no bankswitch
328
329 GAMES: a large majority
330 -------------------------------------------------*/
331
read_rom(offs_t offset)332 uint8_t a26_rom_2k_device::read_rom(offs_t offset)
333 {
334 // Super Chip RAM reads are mapped in 0x1080-0x10ff
335 if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
336 {
337 return m_ram[offset & (m_ram.size() - 1)];
338 }
339
340 return m_rom[offset & (m_rom_size - 1)];
341 }
342
343 /*-------------------------------------------------
344 "F4 Bankswitch" Carts:
345 read/write access to 0x1ff4-0x1ffb determines the
346 4K ROM bank to be read
347
348 GAMES: Fatal Run
349 -------------------------------------------------*/
350
read_rom(offs_t offset)351 uint8_t a26_rom_f4_device::read_rom(offs_t offset)
352 {
353 // Super Chip RAM reads are mapped in 0x1080-0x10ff
354 if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
355 {
356 return m_ram[offset & (m_ram.size() - 1)];
357 }
358
359 // update banks
360 if (!machine().side_effects_disabled())
361 {
362 switch (offset)
363 {
364 case 0x0ff4:
365 case 0x0ff5:
366 case 0x0ff6:
367 case 0x0ff7:
368 case 0x0ff8:
369 case 0x0ff9:
370 case 0x0ffa:
371 case 0x0ffb:
372 m_base_bank = offset - 0x0ff4;
373 break;
374 }
375 }
376
377 return m_rom[offset + (m_base_bank * 0x1000)];
378 }
379
write_bank(address_space & space,offs_t offset,uint8_t data)380 void a26_rom_f4_device::write_bank(address_space &space, offs_t offset, uint8_t data)
381 {
382 // Super Chip RAM writes are mapped in 0x1000-0x107f
383 if (!m_ram.empty() && offset < 0x80)
384 {
385 m_ram[offset & (m_ram.size() - 1)] = data;
386 return;
387 }
388
389 switch (offset)
390 {
391 case 0x0ff4:
392 case 0x0ff5:
393 case 0x0ff6:
394 case 0x0ff7:
395 case 0x0ff8:
396 case 0x0ff9:
397 case 0x0ffa:
398 case 0x0ffb:
399 m_base_bank = offset - 0x0ff4;
400 break;
401 default:
402 logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
403 break;
404 }
405 }
406
407 /*-------------------------------------------------
408 "F6 Bankswitch" Carts:
409 read/write access to 0x1ff6-0x1ff9 determines the
410 4K ROM bank to be read
411
412 GAMES: Atari 16K games, like Crossbow, Crystal
413 Castles and the 2-in-1 carts
414
415 -------------------------------------------------*/
416
read_rom(offs_t offset)417 uint8_t a26_rom_f6_device::read_rom(offs_t offset)
418 {
419 // Super Chip RAM reads are mapped in 0x1080-0x10ff
420 if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
421 {
422 return m_ram[offset & (m_ram.size() - 1)];
423 }
424
425 // update banks
426 if (!machine().side_effects_disabled())
427 {
428 switch (offset)
429 {
430 case 0x0ff6:
431 case 0x0ff7:
432 case 0x0ff8:
433 case 0x0ff9:
434 m_base_bank = offset - 0x0ff6;
435 break;
436 }
437 }
438
439 return m_rom[offset + (m_base_bank * 0x1000)];
440 }
441
write_bank(address_space & space,offs_t offset,uint8_t data)442 void a26_rom_f6_device::write_bank(address_space &space, offs_t offset, uint8_t data)
443 {
444 // Super Chip RAM writes are mapped in 0x1000-0x107f
445 if (!m_ram.empty() && offset < 0x80)
446 {
447 m_ram[offset & (m_ram.size() - 1)] = data;
448 return;
449 }
450
451 switch (offset)
452 {
453 case 0x0ff6:
454 case 0x0ff7:
455 case 0x0ff8:
456 case 0x0ff9:
457 m_base_bank = offset - 0x0ff6;
458 break;
459 default:
460 logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
461 break;
462 }
463 }
464
465 /*-------------------------------------------------
466 "F8 Bankswitch" Carts:
467 read/write access to 0x1ff8-0x1ff9 determines the
468 4K ROM bank to be read
469
470 GAMES: Atari 8K games, like Asteroids, Battlezone
471 and Taz
472
473 -------------------------------------------------*/
474
read_rom(offs_t offset)475 uint8_t a26_rom_f8_device::read_rom(offs_t offset)
476 {
477 // Super Chip RAM reads are mapped in 0x1080-0x10ff
478 if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
479 {
480 return m_ram[offset & (m_ram.size() - 1)];
481 }
482
483 // update banks
484 if (!machine().side_effects_disabled())
485 {
486 switch (offset)
487 {
488 case 0x0ff8:
489 case 0x0ff9:
490 m_base_bank = offset - 0x0ff8;
491 break;
492 }
493 }
494
495 return m_rom[offset + (m_base_bank * 0x1000)];
496 }
497
write_bank(address_space & space,offs_t offset,uint8_t data)498 void a26_rom_f8_device::write_bank(address_space &space, offs_t offset, uint8_t data)
499 {
500 // Super Chip RAM writes are mapped in 0x1000-0x107f
501 if (!m_ram.empty() && offset < 0x80)
502 {
503 m_ram[offset & (m_ram.size() - 1)] = data;
504 return;
505 }
506
507 switch (offset)
508 {
509 case 0x0ff8:
510 case 0x0ff9:
511 m_base_bank = offset - 0x0ff8;
512 break;
513 default:
514 logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
515 break;
516 }
517 }
518
519 /*-------------------------------------------------
520 "FA Bankswitch" Carts:
521 read/write access to 0x1ff8-0x1ffa determines the
522 4K ROM bank to be read
523 These games contained the CBS RAM+ chip (256bytes
524 of RAM)
525
526 GAMES: CBS RAM Plus games like Omega Race and Tunnel
527 Runner
528
529 -------------------------------------------------*/
530
read_rom(offs_t offset)531 uint8_t a26_rom_fa_device::read_rom(offs_t offset)
532 {
533 // CBS RAM+ reads are mapped in 0x1100-0x11ff
534 if (!m_ram.empty() && offset >= 0x100 && offset < 0x200)
535 {
536 return m_ram[offset & (m_ram.size() - 1)];
537 }
538
539 // update banks
540 if (!machine().side_effects_disabled())
541 {
542 switch (offset)
543 {
544 case 0x0ff8:
545 case 0x0ff9:
546 case 0x0ffa:
547 m_base_bank = offset - 0x0ff8;
548 break;
549 }
550 }
551
552 return m_rom[offset + (m_base_bank * 0x1000)];
553 }
554
write_bank(address_space & space,offs_t offset,uint8_t data)555 void a26_rom_fa_device::write_bank(address_space &space, offs_t offset, uint8_t data)
556 {
557 // CBS RAM+ writes are mapped in 0x1000-0x10ff
558 if (!m_ram.empty() && offset < 0x100)
559 {
560 m_ram[offset & (m_ram.size() - 1)] = data;
561 }
562
563 switch (offset)
564 {
565 case 0x0ff8:
566 case 0x0ff9:
567 case 0x0ffa:
568 m_base_bank = offset - 0x0ff8;
569 break;
570 default:
571 logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
572 break;
573 }
574 }
575
576 /*-------------------------------------------------
577 "FE Bankswitch" Carts:
578 read/write access to 0x01fe-0x1ff determines the
579 4K ROM bank to be read
580
581 GAMES: Activision 8K games like Decathlon
582
583 -------------------------------------------------*/
584 /*
585
586 There seems to be a kind of lag between the writing to address 0x1FE and the
587 Activision switcher springing into action. It waits for the next byte to arrive
588 on the data bus, which is the new PCH in the case of a JSR, and the PCH of the
589 stored PC on the stack in the case of an RTS.
590
591 depending on last byte & 0x20 -> 0x00 -> switch to bank #1
592 -> 0x20 -> switch to bank #0
593
594 */
595
read_rom(offs_t offset)596 uint8_t a26_rom_fe_device::read_rom(offs_t offset)
597 {
598 uint8_t data;
599
600 // Super Chip RAM reads are mapped in 0x1080-0x10ff
601 if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
602 {
603 return m_ram[offset & (m_ram.size() - 1)];
604 }
605
606 data = m_rom[offset + (m_base_bank * 0x1000)];
607
608 if (!machine().side_effects_disabled())
609 {
610 if (m_trigger_on_next_access)
611 {
612 m_base_bank = BIT(data, 5) ? 0 : 1;
613 m_trigger_on_next_access = 0;
614 }
615 }
616
617 return data;
618 }
619
write_ram(offs_t offset,uint8_t data)620 void a26_rom_fe_device::write_ram(offs_t offset, uint8_t data)
621 {
622 // Super Chip RAM writes are mapped in 0x1000-0x107f
623 if (!m_ram.empty() && offset < 0x80)
624 {
625 m_ram[offset & (m_ram.size() - 1)] = data;
626 }
627 }
628
read_bank(address_space & space,offs_t offset)629 uint8_t a26_rom_fe_device::read_bank(address_space &space, offs_t offset)
630 {
631 uint8_t data = space.read_byte(0xfe + offset);
632
633 if (!machine().side_effects_disabled())
634 {
635 switch (offset & 1)
636 {
637 case 0:
638 // The next byte on the data bus determines which bank to switch to
639 m_trigger_on_next_access = 1;
640 break;
641
642 case 1:
643 if (m_trigger_on_next_access)
644 {
645 m_base_bank = BIT(data, 5) ? 0 : 1;
646 m_trigger_on_next_access = 0;
647 }
648 break;
649 }
650 }
651 return data;
652 }
653
write_bank(address_space & space,offs_t offset,uint8_t data)654 void a26_rom_fe_device::write_bank(address_space &space, offs_t offset, uint8_t data)
655 {
656 space.write_byte(0xfe, data);
657 if (!machine().side_effects_disabled())
658 {
659 // The next byte on the data bus determines which bank to switch to
660 m_trigger_on_next_access = 1;
661 }
662 }
663
664 /*-------------------------------------------------
665 "3E Bankswitch" Carts:
666 write access to 0x3e determines the 2K ROM bank to
667 be read, write access to 0x3f determines the RAM bank
668 to be read
669
670 GAMES: Boulder Dash (Homebrew)
671
672 -------------------------------------------------*/
673
read_rom(offs_t offset)674 uint8_t a26_rom_3e_device::read_rom(offs_t offset)
675 {
676 if (!m_ram.empty() && m_ram_enable && offset < 0x400)
677 return m_ram[offset + (m_ram_bank * 0x400)];
678
679 if (offset >= 0x800)
680 return m_rom[(offset & 0x7ff) + (m_num_bank - 1) * 0x800];
681 else
682 return m_rom[offset + m_base_bank * 0x800];
683 }
684
write_bank(address_space & space,offs_t offset,uint8_t data)685 void a26_rom_3e_device::write_bank(address_space &space, offs_t offset, uint8_t data)
686 {
687 if (offset == 0x3f)
688 {
689 m_base_bank = data & (m_num_bank - 1);
690 m_ram_enable = 0;
691 }
692 else if (offset == 0x3e)
693 {
694 m_ram_bank = data & 0x1f;
695 m_ram_enable = 1;
696 }
697 }
698
write_ram(offs_t offset,uint8_t data)699 void a26_rom_3e_device::write_ram(offs_t offset, uint8_t data)
700 {
701 if (!m_ram.empty() && m_ram_enable && offset >= 0x400 && offset < 0x800)
702 m_ram[(offset & 0x3ff) + (m_ram_bank * 0x400)] = data;
703 }
704
705
706 /*-------------------------------------------------
707 "3F Bankswitch" Carts:
708 write access to 0x00-0x3f determines the 2K ROM bank
709 to be read
710
711 GAMES: Tigervision 8K games like Espial and Miner
712 2049er. Extended version with bankswitch up to 512K
713 shall be supported as well (but we lack a test case)
714
715 -------------------------------------------------*/
716
read_rom(offs_t offset)717 uint8_t a26_rom_3f_device::read_rom(offs_t offset)
718 {
719 if (offset >= 0x800)
720 return m_rom[(offset & 0x7ff) + (m_num_bank - 1) * 0x800];
721 else
722 return m_rom[offset + m_base_bank * 0x800];
723 }
724
write_bank(address_space & space,offs_t offset,uint8_t data)725 void a26_rom_3f_device::write_bank(address_space &space, offs_t offset, uint8_t data)
726 {
727 m_base_bank = data & (m_num_bank - 1);
728 }
729
730 /*-------------------------------------------------
731 "E0 Bankswitch" Carts:
732 read/write access to 0x1fe0-0x1ff8 determines the
733 1K ROM bank to be read in each 1K chunk (0x1c00-0x1fff
734 always points to the last 1K of the ROM)
735
736 GAMES: Parker Bros. 8K games like Gyruss and Popeye
737
738 -------------------------------------------------*/
739
read_rom(offs_t offset)740 uint8_t a26_rom_e0_device::read_rom(offs_t offset)
741 {
742 // update banks
743 if (!machine().side_effects_disabled())
744 {
745 if (offset >= 0xfe0 && offset <= 0xff8)
746 m_base_banks[(offset >> 3) & 3] = offset & 7;
747 }
748
749 return m_rom[(offset & 0x3ff) + (m_base_banks[(offset >> 10) & 3] * 0x400)];
750 }
751
write_bank(address_space & space,offs_t offset,uint8_t data)752 void a26_rom_e0_device::write_bank(address_space &space, offs_t offset, uint8_t data)
753 {
754 if (offset >= 0xfe0 && offset <= 0xff8)
755 m_base_banks[(offset >> 3) & 3] = offset & 7;
756 }
757
758
759 /*-------------------------------------------------
760 "E7 Bankswitch" Carts:
761 this PCB can handle up to 16K of ROM and 2K of RAM,
762 with the following layout
763 1000-17ff is selectable bank
764 1800-19ff is RAM
765 1a00-1fff is fixed to the last 0x600 of ROM
766
767 The selectable bank can be ROM (if selected by
768 0x1fe0-0x1fe6 access) or a first 1K of RAM (if
769 selected by 0x1fe7 access).
770 The other 256byte RAM bank can be one of the
771 four different chunks forming the other 1K of RAM
772 (the bank is selected by accessing 0x1fe8-0x1feb)
773
774 GAMES: M Network 16K games like Burgertime and
775 Bump'n Jump
776
777 -------------------------------------------------*/
778
read_rom(offs_t offset)779 uint8_t a26_rom_e7_device::read_rom(offs_t offset)
780 {
781 // update banks
782 if (!machine().side_effects_disabled())
783 {
784 if (offset >= 0xfe0 && offset <= 0xfe7)
785 m_base_bank = offset - 0xfe0;
786 if (offset >= 0xfe8 && offset <= 0xfeb)
787 m_ram_bank = offset - 0xfe8;
788 }
789
790 if (!m_ram.empty())
791 {
792 // 1K of RAM
793 if (m_base_bank == 0x07 && offset >= 0x400 && offset < 0x800)
794 return m_ram[0x400 + (offset & 0x3ff)];
795 // the other 1K of RAM
796 if (offset >= 0x900 && offset < 0xa00)
797 {
798 offset -= 0x900;
799 return m_ram[offset + (m_ram_bank * 0x100)];
800 }
801 }
802
803 if (offset > 0x800)
804 return m_rom[(offset & 0x7ff) + 0x3800];
805 else
806 return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)];
807 }
808
write_bank(address_space & space,offs_t offset,uint8_t data)809 void a26_rom_e7_device::write_bank(address_space &space, offs_t offset, uint8_t data)
810 {
811 if (offset >= 0xfe0 && offset <= 0xfe7)
812 m_base_bank = offset - 0xfe0;
813 if (offset >= 0xfe8 && offset <= 0xfeb)
814 m_ram_bank = offset - 0xfe8;
815
816 if (!m_ram.empty())
817 {
818 // 1K of RAM
819 if (m_base_bank == 0x07 && offset < 0x400)
820 m_ram[0x400 + (offset & 0x3ff)] = data;
821 // the other 1K of RAM
822 if (offset >= 0x800 && offset < 0x900)
823 {
824 offset -= 0x800;
825 m_ram[offset + (m_ram_bank * 0x100)] = data;
826 }
827 }
828 }
829
830 /*-------------------------------------------------
831 "UA Bankswitch" Carts:
832 read/write access to 0x200-0x27f determines the
833 4K ROM bank to be read (0x220-0x23f for low 4K,
834 0x240-0x27f for high 4K)
835
836 GAMES: UA Ltd. 8K games like Funky Flash and
837 Pleaides
838
839 -------------------------------------------------*/
840
read_rom(offs_t offset)841 uint8_t a26_rom_ua_device::read_rom(offs_t offset)
842 {
843 return m_rom[(offset + (m_base_bank * 0x1000)) & (m_rom_size - 1)];
844 }
845
read_bank(address_space & space,offs_t offset)846 uint8_t a26_rom_ua_device::read_bank(address_space &space, offs_t offset)
847 {
848 if (!machine().side_effects_disabled())
849 m_base_bank = offset >> 6;
850
851 return 0;
852 }
853
write_bank(address_space & space,offs_t offset,uint8_t data)854 void a26_rom_ua_device::write_bank(address_space &space, offs_t offset, uint8_t data)
855 {
856 m_base_bank = offset >> 6;
857 }
858
859
860 /*-------------------------------------------------
861 Commavid Carts:
862 It allows for both ROM and RAM on the cartridge,
863 without using bankswitching. There's 2K of ROM
864 and 1K of RAM.
865
866 GAMES: Magicard and Video Life by Commavid
867
868 -------------------------------------------------*/
869
read_rom(offs_t offset)870 uint8_t a26_rom_cv_device::read_rom(offs_t offset)
871 {
872 if (!m_ram.empty() && offset < 0x400)
873 {
874 return m_ram[offset & (m_ram.size() - 1)];
875 }
876
877 // games shall not read from 0x1400-0x17ff (RAM write)
878 // but we fall back to ROM just in case...
879 return m_rom[offset & 0x7ff];
880 }
881
write_bank(address_space & space,offs_t offset,uint8_t data)882 void a26_rom_cv_device::write_bank(address_space &space, offs_t offset, uint8_t data)
883 {
884 if (!m_ram.empty() && offset >= 0x400 && offset < 0x800)
885 {
886 m_ram[offset & (m_ram.size() - 1)] = data;
887 }
888 }
889
890
891 /*-------------------------------------------------
892 Dynacom Megaboy Carts (aka "F0 Banswitch"):
893 read/write access to 0x1ff0 determines the 4K ROM
894 bank to be read (each access increases the bank index
895 up to 16, since the cart was 64K wide)
896
897 GAMES: Megaboy by Dynacom
898
899 -------------------------------------------------*/
900
read_rom(offs_t offset)901 uint8_t a26_rom_dc_device::read_rom(offs_t offset)
902 {
903 if (!machine().side_effects_disabled())
904 {
905 if (offset == 0xff0)
906 m_base_bank = (m_base_bank + 1) & 0x0f;
907 }
908
909 if (offset == 0xfec)
910 return m_base_bank;
911
912 return m_rom[offset + (m_base_bank * 0x1000)];
913 }
914
write_bank(address_space & space,offs_t offset,uint8_t data)915 void a26_rom_dc_device::write_bank(address_space &space, offs_t offset, uint8_t data)
916 {
917 if (offset == 0xff0)
918 m_base_bank = (m_base_bank + 1) & 0x0f;
919 }
920
921
922 /*-------------------------------------------------
923 "FV Bankswitch" Carts:
924 The first access to 0x1fd0 switch the bank, but
925 only if pc() & 0x1f00 == 0x1f00!
926
927 GAMES: Challenge by HES
928
929 -------------------------------------------------*/
930
read_rom(offs_t offset)931 uint8_t a26_rom_fv_device::read_rom(offs_t offset)
932 {
933 if (!machine().side_effects_disabled())
934 {
935 if (offset == 0xfd0)
936 {
937 if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00)
938 {
939 m_locked = 1;
940 m_base_bank = m_base_bank ^ 0x01;
941 }
942 }
943 }
944
945 return m_rom[offset + (m_base_bank * 0x1000)];
946 }
947
write_bank(address_space & space,offs_t offset,uint8_t data)948 void a26_rom_fv_device::write_bank(address_space &space, offs_t offset, uint8_t data)
949 {
950 if (offset == 0xfd0)
951 {
952 if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00)
953 {
954 m_locked = 1;
955 m_base_bank = m_base_bank ^ 0x01;
956 }
957 }
958 }
959
960
961 /*-------------------------------------------------
962 "JVP Bankswitch" Carts:
963 read/write access to 0x0fa0-0x0fc0 determines the
964 4K ROM bank to be read (notice that this overlaps
965 the RIOT, currently handled in the main driver until
966 I can better investigate the behavior)
967
968 GAMES: No test case!?!
969
970 -------------------------------------------------*/
971
read_rom(offs_t offset)972 uint8_t a26_rom_jvp_device::read_rom(offs_t offset)
973 {
974 return m_rom[offset + (m_base_bank * 0x1000)];
975 }
976
write_bank(address_space & space,offs_t offset,uint8_t data)977 void a26_rom_jvp_device::write_bank(address_space &space, offs_t offset, uint8_t data)
978 {
979 switch (offset)
980 {
981 case 0x00:
982 case 0x20:
983 m_base_bank ^= 1;
984 break;
985 default:
986 //printf("%04X: write to unknown mapper address %02X\n", m_maincpu->pc(), 0xfa0 + offset);
987 break;
988 }
989 }
990
991
992 /*-------------------------------------------------
993 4 in 1 Carts (Reset based):
994 the 4K bank changes at each reset
995
996 GAMES: 4 in 1 carts
997
998 -------------------------------------------------*/
999
read_rom(offs_t offset)1000 uint8_t a26_rom_4in1_device::read_rom(offs_t offset)
1001 {
1002 return m_rom[offset + (m_base_bank * 0x1000)];
1003 }
1004
1005
1006 /*-------------------------------------------------
1007 8 in 1 Carts (Reset based):
1008 the 8K banks change at each reset, and internally
1009 each game runs as a F8-bankswitched cart
1010
1011 GAMES: 8 in 1 cart
1012
1013 -------------------------------------------------*/
1014
read_rom(offs_t offset)1015 uint8_t a26_rom_8in1_device::read_rom(offs_t offset)
1016 {
1017 if (!machine().side_effects_disabled())
1018 {
1019 switch (offset)
1020 {
1021 case 0x0ff8:
1022 case 0x0ff9:
1023 m_base_bank = offset - 0x0ff8;
1024 break;
1025 }
1026 }
1027
1028 return m_rom[offset + (m_base_bank * 0x1000) + (m_reset_bank * 0x2000)];
1029 }
1030
1031
1032 /*-------------------------------------------------
1033 32 in 1 Carts (Reset based):
1034 the 2K banks change at each reset
1035
1036 GAMES: 32 in 1 cart
1037
1038 -------------------------------------------------*/
1039
read_rom(offs_t offset)1040 uint8_t a26_rom_32in1_device::read_rom(offs_t offset)
1041 {
1042 return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)];
1043 }
1044
1045
1046 /*-------------------------------------------------
1047 "X07 Bankswitch" Carts:
1048 banking done with a PALC22V10B
1049 implementation based on information at
1050 http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt
1051 --------------------------------------------------*/
1052
read_rom(offs_t offset)1053 uint8_t a26_rom_x07_device::read_rom(offs_t offset)
1054 {
1055 return m_rom[offset + (m_base_bank * 0x1000)];
1056 }
1057
write_bank(address_space & space,offs_t offset,uint8_t data)1058 void a26_rom_x07_device::write_bank(address_space &space, offs_t offset, uint8_t data)
1059 {
1060 /*
1061 A13 A0
1062 ----------------
1063 0 1xxx nnnn 1101
1064 */
1065
1066 if ((offset & 0x180f) == 0x080d)
1067 {
1068 m_base_bank = (offset & 0x00f0) >> 4;
1069 }
1070 /*
1071 A13 A0
1072 ----------------
1073 0 0xxx 0nxx xxxx
1074 */
1075
1076 if ((offset & 0x1880) == 0x0000)
1077 {
1078 // only has an effect if bank is already 14 or 15
1079 if (m_base_bank == 14 || m_base_bank == 15)
1080 {
1081 if (offset & 0x0040)
1082 {
1083 m_base_bank = 15;
1084 }
1085 else
1086 {
1087 m_base_bank = 14;
1088 }
1089
1090 }
1091 }
1092 }
1093