1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli,Cowering
3 /***********************************************************************************************************
4
5
6 Atari VCS 2600 cart emulation
7 (through slot devices)
8
9 Emulation of the cartslot for Atari 2600
10 Several banking schemes have been used for larger roms,
11 and some carts contained RAM (so called "Special Chip")
12
13 Mapper identification routines based on Cowering's code.
14
15 ***********************************************************************************************************/
16
17
18 #include "emu.h"
19 #include "vcs_slot.h"
20
21 //**************************************************************************
22 // GLOBAL VARIABLES
23 //**************************************************************************
24
25 DEFINE_DEVICE_TYPE(VCS_CART_SLOT, vcs_cart_slot_device, "vcs_cart_slot", "Atari VCS 2600 Cartridge Slot")
26
27
28 //-------------------------------------------------
29 // device_vcs_cart_interface - constructor
30 //-------------------------------------------------
31
device_vcs_cart_interface(const machine_config & mconfig,device_t & device)32 device_vcs_cart_interface::device_vcs_cart_interface(const machine_config &mconfig, device_t &device) :
33 device_interface(device, "vcscart"),
34 m_rom(nullptr),
35 m_rom_size(0)
36 {
37 }
38
39
40 //-------------------------------------------------
41 // ~device_vcs_cart_interface - destructor
42 //-------------------------------------------------
43
~device_vcs_cart_interface()44 device_vcs_cart_interface::~device_vcs_cart_interface()
45 {
46 }
47
48 //-------------------------------------------------
49 // rom_alloc - alloc the space for the cart
50 //-------------------------------------------------
51
rom_alloc(uint32_t size,const char * tag)52 void device_vcs_cart_interface::rom_alloc(uint32_t size, const char *tag)
53 {
54 if (m_rom == nullptr)
55 {
56 m_rom = device().machine().memory().region_alloc(std::string(tag).append(A26SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
57 m_rom_size = size;
58 }
59 }
60
61 //-------------------------------------------------
62 // ram_alloc - alloc the space for the on-cart RAM
63 //-------------------------------------------------
64
ram_alloc(uint32_t size)65 void device_vcs_cart_interface::ram_alloc(uint32_t size)
66 {
67 m_ram.resize(size);
68 device().save_item(NAME(m_ram));
69 }
70
71
72
73 //**************************************************************************
74 // LIVE DEVICE
75 //**************************************************************************
76
77 //-------------------------------------------------
78 // vcs_cart_slot_device - constructor
79 //-------------------------------------------------
vcs_cart_slot_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)80 vcs_cart_slot_device::vcs_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
81 device_t(mconfig, VCS_CART_SLOT, tag, owner, clock),
82 device_image_interface(mconfig, *this),
83 device_single_card_slot_interface<device_vcs_cart_interface>(mconfig, *this),
84 m_cart(nullptr), m_type(0)
85 {
86 }
87
88
89 //-------------------------------------------------
90 // vcs_cart_slot_device - destructor
91 //-------------------------------------------------
92
~vcs_cart_slot_device()93 vcs_cart_slot_device::~vcs_cart_slot_device()
94 {
95 }
96
97 //-------------------------------------------------
98 // device_start - device-specific startup
99 //-------------------------------------------------
100
device_start()101 void vcs_cart_slot_device::device_start()
102 {
103 m_cart = get_card_device();
104 }
105
106
107
108 /*-------------------------------------------------
109 call load
110 -------------------------------------------------*/
111
112 //-------------------------------------------------
113 // VCS PCBs
114 //-------------------------------------------------
115
116 struct vcs_slot
117 {
118 int pcb_id;
119 const char *slot_option;
120 };
121
122 // Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
123 static const vcs_slot slot_list[] =
124 {
125 { A26_2K, "a26_2k" },
126 { A26_4K, "a26_4k" },
127 { A26_F4, "a26_f4" },
128 { A26_F6, "a26_f6" },
129 { A26_F8, "a26_f8" },
130 { A26_F8SW, "a26_f8sw" },
131 { A26_FA, "a26_fa" },
132 { A26_FE, "a26_fe" },
133 { A26_E0, "a26_e0" },
134 { A26_E7, "a26_e7" },
135 { A26_3E, "a26_3e" },
136 { A26_3F, "a26_3f" },
137 { A26_UA, "a26_ua" },
138 { A26_CV, "a26_cv" },
139 { A26_DC, "a26_dc" },
140 { A26_FV, "a26_fv" },
141 { A26_JVP, "a26_jvp" },
142 { A26_CM, "a26_cm" },
143 { A26_SS, "a26_ss" },
144 { A26_DPC, "a26_dpc" },
145 { A26_4IN1, "a26_4in1" },
146 { A26_8IN1, "a26_8in1" },
147 { A26_32IN1, "a26_32in1" },
148 { A26_X07, "a26_x07" },
149 { A26_HARMONY, "a26_harmony" },
150 };
151
vcs_get_pcb_id(const char * slot)152 static int vcs_get_pcb_id(const char *slot)
153 {
154 for (auto & elem : slot_list)
155 {
156 if (!core_stricmp(elem.slot_option, slot))
157 return elem.pcb_id;
158 }
159
160 return 0;
161 }
162
vcs_get_slot(int type)163 static const char *vcs_get_slot(int type)
164 {
165 for (auto & elem : slot_list)
166 {
167 if (elem.pcb_id == type)
168 return elem.slot_option;
169 }
170
171 return "a26_4k";
172 }
173
call_load()174 image_init_result vcs_cart_slot_device::call_load()
175 {
176 if (m_cart)
177 {
178 uint8_t *ROM;
179 uint32_t len;
180
181 if (loaded_through_softlist())
182 len = get_software_region_length("rom");
183 else
184 len = length();
185
186 //printf("Size: 0x%X\n", len);
187
188 // check that filesize is among the supported ones
189 switch (len)
190 {
191 case 0x00800:
192 case 0x01000:
193 case 0x02000:
194 case 0x028ff:
195 case 0x02900:
196 case 0x03000:
197 case 0x04000:
198 case 0x08000:
199 case 0x10000:
200 case 0x80000:
201 break;
202
203 default:
204 seterror(IMAGE_ERROR_UNSUPPORTED, "Invalid rom file size" );
205 return image_init_result::FAIL;
206 }
207
208 m_cart->rom_alloc(len, tag());
209 ROM = m_cart->get_rom_base();
210
211 if (loaded_through_softlist())
212 {
213 const char *pcb_name;
214 bool has_ram = get_software_region("ram") ? true : false;
215 memcpy(ROM, get_software_region("rom"), len);
216
217 if ((pcb_name = get_feature("slot")) != nullptr)
218 m_type = vcs_get_pcb_id(pcb_name);
219 else
220 {
221 // identify type based on size
222 switch (len)
223 {
224 case 0x800:
225 m_type = A26_2K;
226 break;
227 case 0x1000:
228 m_type = A26_4K;
229 break;
230 case 0x2000:
231 m_type = A26_F8;
232 break;
233 case 0x28ff:
234 case 0x2900:
235 m_type = A26_DPC;
236 break;
237 case 0x3000:
238 m_type = A26_FA;
239 break;
240 case 0x4000:
241 m_type = A26_F6;
242 break;
243 case 0x8000:
244 m_type = A26_F4;
245 break;
246 case 0x10000:
247 m_type = A26_32IN1;
248 break;
249 case 0x80000:
250 m_type = A26_3F;
251 break;
252 default:
253 m_type = A26_4K;
254 printf("Unrecognized cart type!\n");
255 break;
256 }
257 }
258
259 if (has_ram)
260 m_cart->ram_alloc(get_software_region_length("ram"));
261 }
262 else
263 {
264 fread(ROM, len);
265 m_type = identify_cart_type(ROM, len);
266
267 // check for Special Chip (128bytes of RAM)
268 if (len == 0x2000 || len == 0x4000 || len == 0x8000)
269 if (detect_super_chip(ROM, len))
270 {
271 m_cart->ram_alloc(0x80);
272 //printf("Super Chip detected!\n");
273 }
274 // Super chip games:
275 // dig dig, crystal castles, millipede, stargate, defender ii, jr. Pac Man,
276 // desert falcon, dark chambers, super football, sprintmaster, fatal run,
277 // off the wall, shooting arcade, secret quest, radar lock, save mary, klax
278
279 // add CBS RAM+ (256bytes of RAM)
280 if (m_type == A26_FA)
281 m_cart->ram_alloc(0x100);
282 // add M Network RAM
283 else if (m_type == A26_E7)
284 m_cart->ram_alloc(0x800);
285 // add Commavid RAM
286 else if (m_type == A26_CV)
287 m_cart->ram_alloc(0x400);
288 // add Starpath Superchager RAM
289 else if (m_type == A26_SS)
290 m_cart->ram_alloc(0x1800);
291 // add Boulder Dash RAM
292 else if (m_type == A26_3E)
293 m_cart->ram_alloc(0x8000);
294 }
295
296 //printf("Type: %s\n", vcs_get_slot(m_type));
297
298 // pass a pointer to the now allocated ROM for the DPC chip
299 if (m_type == A26_DPC)
300 m_cart->setup_addon_ptr((uint8_t *)m_cart->get_rom_base() + 0x2000);
301
302 return image_init_result::PASS;
303 }
304
305 return image_init_result::PASS;
306 }
307
308
309 /*-------------------------------------------------
310 call_unload
311 -------------------------------------------------*/
312
call_unload()313 void vcs_cart_slot_device::call_unload()
314 {
315 }
316
317
318
319 /*-------------------------------------------------
320 detection helper routines
321 -------------------------------------------------*/
322
detect_modeDC(const uint8_t * cart,uint32_t len)323 bool vcs_cart_slot_device::detect_modeDC(const uint8_t *cart, uint32_t len)
324 {
325 int numfound = 0;
326 // signature is also in 'video reflex'.. maybe figure out that controller port someday...
327 static const unsigned char signature[3] = { 0x8d, 0xf0, 0xff };
328
329 if (len == 0x10000)
330 {
331 for (int i = 0; i < len - sizeof signature; i++)
332 {
333 if (!memcmp(&cart[i], signature, sizeof signature))
334 {
335 numfound = 1;
336 }
337 }
338 }
339 if (numfound)
340 return 1;
341 return 0;
342 }
343
detect_modeF6(const uint8_t * cart,uint32_t len)344 bool vcs_cart_slot_device::detect_modeF6(const uint8_t *cart, uint32_t len)
345 {
346 int numfound = 0;
347 static const unsigned char signature[3] = { 0x8d, 0xf6, 0xff };
348
349 if (len == 0x4000)
350 {
351 for (int i = 0; i < len - sizeof signature; i++)
352 {
353 if (!memcmp(&cart[i], signature, sizeof signature))
354 {
355 numfound = 1;
356 }
357 }
358 }
359 if (numfound)
360 return 1;
361 return 0;
362 }
363
detect_snowhite(const uint8_t * cart,uint32_t len)364 bool vcs_cart_slot_device::detect_snowhite(const uint8_t *cart, uint32_t len)
365 {
366 static const unsigned char snowwhite[] = { 0x10, 0xd0, 0xff, 0xff }; // Snow White Proto
367
368 if (len == 0x2000 && !memcmp(&cart[0x1ffc], snowwhite, sizeof(snowwhite)))
369 return 1;
370 return 0;
371 }
372
detect_mode3E(const uint8_t * cart,uint32_t len)373 bool vcs_cart_slot_device::detect_mode3E(const uint8_t *cart, uint32_t len)
374 {
375 // this one is a little hacky... looks for STY $3e, which is unique to
376 // 'not boulderdash', but is the only example I have (cow)
377 // Would have used STA $3e, but 'Alien' and 'Star Raiders' do that for unknown reasons
378 int numfound = 0;
379 static const unsigned char signature[3] = { 0x84, 0x3e, 0x9d };
380
381 if (len == 0x0800 || len == 0x1000)
382 {
383 for (int i = 0; i < len - sizeof signature; i++)
384 {
385 if (!memcmp(&cart[i], signature, sizeof signature))
386 {
387 numfound = 1;
388 }
389 }
390 }
391 if (numfound)
392 return 1;
393 return 0;
394 }
395
detect_modeSS(const uint8_t * cart,uint32_t len)396 bool vcs_cart_slot_device::detect_modeSS(const uint8_t *cart, uint32_t len)
397 {
398 int numfound = 0;
399 static const unsigned char signature[5] = { 0xbd, 0xe5, 0xff, 0x95, 0x81 };
400
401 if (len == 0x0800 || len == 0x1000)
402 {
403 for (int i = 0; i < len - sizeof signature; i++)
404 {
405 if (!memcmp(&cart[i], signature, sizeof signature))
406 {
407 numfound = 1;
408 }
409 }
410 }
411 if (numfound)
412 return 1;
413 return 0;
414 }
415
detect_modeFE(const uint8_t * cart,uint32_t len)416 bool vcs_cart_slot_device::detect_modeFE(const uint8_t *cart, uint32_t len)
417 {
418 int numfound = 0;
419 static const unsigned char signatures[][5] = {
420 { 0x20, 0x00, 0xd0, 0xc6, 0xc5 },
421 { 0x20, 0xc3, 0xf8, 0xa5, 0x82 },
422 { 0xd0, 0xfb, 0x20, 0x73, 0xfe },
423 { 0x20, 0x00, 0xf0, 0x84, 0xd6 }
424 };
425
426 if (len == 0x2000)
427 {
428 for (int i = 0; i < len - sizeof signatures[0]; i++)
429 {
430 for (int j = 0; j < (sizeof signatures/sizeof signatures[0]) && !numfound; j++)
431 {
432 if (!memcmp(&cart[i], &signatures[j], sizeof signatures[0]))
433 {
434 numfound = 1;
435 }
436 }
437 }
438 }
439 if (numfound)
440 return 1;
441 return 0;
442 }
443
detect_modeE0(const uint8_t * cart,uint32_t len)444 bool vcs_cart_slot_device::detect_modeE0(const uint8_t *cart, uint32_t len)
445 {
446 int numfound = 0;
447 static const unsigned char signatures[][3] = {
448 { 0x8d, 0xe0, 0x1f },
449 { 0x8d, 0xe0, 0x5f },
450 { 0x8d, 0xe9, 0xff },
451 { 0xad, 0xe9, 0xff },
452 { 0xad, 0xed, 0xff },
453 { 0xad, 0xf3, 0xbf }
454 };
455
456 if (len == 0x2000)
457 {
458 for (int i = 0; i < len - sizeof signatures[0]; i++)
459 {
460 for (int j = 0; j < (sizeof signatures/sizeof signatures[0]) && !numfound; j++)
461 {
462 if (!memcmp(&cart[i], &signatures[j], sizeof signatures[0]))
463 {
464 numfound = 1;
465 }
466 }
467 }
468 }
469 if (numfound)
470 return 1;
471 return 0;
472 }
473
detect_modeCV(const uint8_t * cart,uint32_t len)474 bool vcs_cart_slot_device::detect_modeCV(const uint8_t *cart, uint32_t len)
475 {
476 int numfound = 0;
477 static const unsigned char signatures[][3] = {
478 { 0x9d, 0xff, 0xf3 },
479 { 0x99, 0x00, 0xf4 }
480 };
481
482 if (len == 0x0800 || len == 0x1000)
483 {
484 for (int i = 0; i < len - sizeof signatures[0]; i++)
485 {
486 for (int j = 0; j < (sizeof signatures/sizeof signatures[0]) && !numfound; j++)
487 {
488 if (!memcmp(&cart[i], &signatures[j], sizeof signatures[0]))
489 {
490 numfound = 1;
491 }
492 }
493 }
494 }
495 if (numfound)
496 return 1;
497 return 0;
498 }
499
detect_modeFV(const uint8_t * cart,uint32_t len)500 bool vcs_cart_slot_device::detect_modeFV(const uint8_t *cart, uint32_t len)
501 {
502 int numfound = 0;
503 static const unsigned char signatures[][3] = { { 0x2c, 0xd0, 0xff } };
504
505 if (len == 0x2000)
506 {
507 for (int i = 0; i < len - sizeof signatures[0]; i++)
508 {
509 for (int j = 0; j < (sizeof signatures/sizeof signatures[0]) && !numfound; j++)
510 {
511 if (!memcmp(&cart[i], &signatures[j], sizeof signatures[0]))
512 {
513 numfound = 1;
514 }
515 }
516 }
517 }
518 if (numfound)
519 return 1;
520 return 0;
521 }
522
detect_modeJVP(const uint8_t * cart,uint32_t len)523 bool vcs_cart_slot_device::detect_modeJVP(const uint8_t *cart, uint32_t len)
524 {
525 int numfound = 0;
526 static const unsigned char signatures[][4] = {
527 { 0x2c, 0xc0, 0xef, 0x60 },
528 { 0x8d, 0xa0, 0x0f, 0xf0 }
529 };
530
531 if (len == 0x4000 || len == 0x2000)
532 {
533 for (int i = 0; i < len - sizeof signatures[0]; i++)
534 {
535 for (int j = 0; j < (sizeof signatures/sizeof signatures[0]) && !numfound; j++)
536 {
537 if (!memcmp(&cart[i], &signatures[j], sizeof signatures[0]))
538 {
539 numfound = 1;
540 }
541 }
542 }
543 }
544 if (numfound)
545 return 1;
546 return 0;
547 }
548
detect_modeE7(const uint8_t * cart,uint32_t len)549 bool vcs_cart_slot_device::detect_modeE7(const uint8_t *cart, uint32_t len)
550 {
551 int numfound = 0;
552 static const unsigned char signatures[][3] = {
553 { 0xad, 0xe5, 0xff },
554 { 0x8d, 0xe7, 0xff }
555 };
556
557 if (len == 0x2000 || len == 0x4000)
558 {
559 for (int i = 0; i < len - sizeof signatures[0]; i++)
560 {
561 for (int j = 0; j < (sizeof signatures/sizeof signatures[0]) && !numfound; j++)
562 {
563 if (!memcmp(&cart[i], &signatures[j], sizeof signatures[0]))
564 {
565 numfound = 1;
566 }
567 }
568 }
569 }
570 if (numfound)
571 return 1;
572 return 0;
573 }
574
detect_modeUA(const uint8_t * cart,uint32_t len)575 bool vcs_cart_slot_device::detect_modeUA(const uint8_t *cart, uint32_t len)
576 {
577 int numfound = 0;
578 static const unsigned char signature[3] = { 0x8d, 0x40, 0x02 };
579
580 if (len == 0x2000)
581 {
582 for (int i = 0; i < len - sizeof signature; i++)
583 {
584 if (!memcmp(&cart[i], signature, sizeof signature))
585 {
586 numfound = 1;
587 }
588 }
589 }
590 if (numfound)
591 return 1;
592 return 0;
593 }
594
detect_8K_mode3F(const uint8_t * cart,uint32_t len)595 bool vcs_cart_slot_device::detect_8K_mode3F(const uint8_t *cart, uint32_t len)
596 {
597 int numfound = 0;
598 static const unsigned char signature1[4] = { 0xa9, 0x01, 0x85, 0x3f };
599 static const unsigned char signature2[4] = { 0xa9, 0x02, 0x85, 0x3f };
600 // have to look for two signatures because 'not boulderdash' gives false positive otherwise
601
602 if (len == 0x2000)
603 {
604 for (int i = 0; i < len - sizeof signature1; i++)
605 {
606 if (!memcmp(&cart[i], signature1, sizeof signature1))
607 {
608 numfound |= 0x01;
609 }
610 if (!memcmp(&cart[i], signature2, sizeof signature2))
611 {
612 numfound |= 0x02;
613 }
614 }
615 }
616 if (numfound == 0x03)
617 return 1;
618 return 0;
619 }
620
detect_32K_mode3F(const uint8_t * cart,uint32_t len)621 bool vcs_cart_slot_device::detect_32K_mode3F(const uint8_t *cart, uint32_t len)
622 {
623 int numfound = 0;
624 static const unsigned char signature[4] = { 0xa9, 0x0e, 0x85, 0x3f };
625
626 if (len >= 0x8000)
627 {
628 for (int i = 0; i < len - sizeof signature; i++)
629 {
630 if (!memcmp(&cart[i], signature, sizeof signature))
631 {
632 numfound++;
633 }
634 }
635 }
636 if (numfound > 1)
637 return 1;
638 return 0;
639 }
640
detect_super_chip(const uint8_t * cart,uint32_t len)641 bool vcs_cart_slot_device::detect_super_chip(const uint8_t *cart, uint32_t len)
642 {
643 static const unsigned char signatures[][5] = {
644 { 0xa2, 0x7f, 0x9d, 0x00, 0xf0 }, // dig dug
645 { 0xae, 0xf6, 0xff, 0x4c, 0x00 } // off the wall
646 };
647
648 if (len == 0x4000)
649 {
650 for (int i = 0; i < len - sizeof signatures[0]; i++)
651 {
652 for (auto & signature : signatures)
653 {
654 if (!memcmp(&cart[i], &signature, sizeof signatures[0]))
655 {
656 return 1;
657 }
658 }
659 }
660 }
661 for (int i = 0x1000; i < len; i += 0x1000)
662 {
663 if (memcmp(cart, cart + i, 0x100))
664 {
665 return 0;
666 }
667 }
668 /* Check the reset vector does not point into the super chip RAM area */
669 if ((((cart[0x0ffd] << 8) | cart[0x0ffc]) & 0x0fff) < 0x0100)
670 {
671 return 0;
672 }
673 return 1;
674 }
675
676
677 /*-------------------------------------------------
678 identify_cart_type - code to detect cart type from
679 fullpath
680 -------------------------------------------------*/
681
682 // 4in1 & 8in1 are not currently detected from fullpath...
identify_cart_type(const uint8_t * ROM,uint32_t len)683 int vcs_cart_slot_device::identify_cart_type(const uint8_t *ROM, uint32_t len)
684 {
685 int type = 0xff;
686
687 // auto-detect bank mode
688 if (detect_modeDC(ROM, len))
689 type = A26_DC;
690 else if (detect_mode3E(ROM, len))
691 type = A26_3E;
692 else if (detect_modeFE(ROM, len))
693 type = A26_FE;
694 else if (detect_modeSS(ROM, len))
695 type = A26_SS;
696 else if (detect_modeE0(ROM, len))
697 type = A26_E0;
698 else if (detect_modeCV(ROM, len))
699 type = A26_CV;
700 else if (detect_modeFV(ROM, len))
701 type = A26_FV;
702 else if (detect_modeJVP(ROM, len))
703 type = A26_JVP;
704 else if (detect_modeUA(ROM, len))
705 type = A26_UA;
706 else if (detect_8K_mode3F(ROM, len))
707 type = A26_3F;
708 else if (detect_32K_mode3F(ROM, len))
709 type = A26_3F;
710 else if (detect_modeE7(ROM, len))
711 type = A26_E7;
712 else if (detect_snowhite(ROM, len))
713 type = A26_F8SW;
714
715 // otherwise, choose based on size
716 if (type == 0xff)
717 {
718 switch (len)
719 {
720 case 0x800:
721 type = A26_2K;
722 break;
723 case 0x1000:
724 type = A26_4K;
725 break;
726 case 0x2000:
727 type = A26_F8;
728 break;
729 case 0x28ff:
730 case 0x2900:
731 type = A26_DPC;
732 break;
733 case 0x3000:
734 type = A26_FA;
735 break;
736 case 0x4000:
737 type = A26_F6;
738 break;
739 case 0x8000:
740 type = A26_F4;
741 break;
742 case 0x10000:
743 type = A26_32IN1;
744 break;
745 case 0x80000:
746 type = A26_3F;
747 break;
748 default:
749 type = A26_4K;
750 printf("Unrecognized cart type!\n");
751 break;
752 }
753 }
754
755 return type;
756 }
757
758 /*-------------------------------------------------
759 get default card software
760 -------------------------------------------------*/
761
get_default_card_software(get_default_card_software_hook & hook) const762 std::string vcs_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
763 {
764 if (hook.image_file())
765 {
766 const char *slot_string;
767 uint32_t len = hook.image_file()->size();
768 std::vector<uint8_t> rom(len);
769 int type;
770
771 hook.image_file()->read(&rom[0], len);
772
773 type = identify_cart_type(&rom[0], len);
774 slot_string = vcs_get_slot(type);
775
776 return std::string(slot_string);
777 }
778 else
779 return software_get_default_slot("a26_4k");
780 }
781
782
783 /*-------------------------------------------------
784 read
785 -------------------------------------------------*/
786
read_rom(offs_t offset)787 uint8_t vcs_cart_slot_device::read_rom(offs_t offset)
788 {
789 if (m_cart)
790 return m_cart->read_rom(offset);
791 else
792 return 0xff;
793 }
794
read_bank(address_space & space,offs_t offset)795 uint8_t vcs_cart_slot_device::read_bank(address_space &space, offs_t offset)
796 {
797 if (m_cart)
798 return m_cart->read_bank(space, offset);
799 else
800 return 0xff;
801 }
802
803
804 /*-------------------------------------------------
805 write
806 -------------------------------------------------*/
807
write_bank(address_space & space,offs_t offset,uint8_t data)808 void vcs_cart_slot_device::write_bank(address_space &space, offs_t offset, uint8_t data)
809 {
810 if (m_cart)
811 m_cart->write_bank(space, offset, data);
812 }
813
write_ram(offs_t offset,uint8_t data)814 void vcs_cart_slot_device::write_ram(offs_t offset, uint8_t data)
815 {
816 if (m_cart)
817 m_cart->write_ram(offset, data);
818 }
819