summaryrefslogtreecommitdiffstats
path: root/src/mame/drivers/megadriv_rad.cpp
blob: 4668d5a841b38164f19b142be0100df02726b335 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
// license:BSD-3-Clause
// copyright-holders:David Haywood

/*
    Radica 'Mega Drive' and 'Genesis' clones
    these were mini battery operated "TV Game" consoles with wired in controller and no cartslot
    fully licensed by Sega

    reproduction 'System on a Chip' hardware, not perfect, flaws will need emulating eventually.

    not dumped

    Genesis Volume 2
    Genesis SF2 / GnG (PAL one is locked to PAL)

    Outrun 2019 (probably identical ROM to MD version, just custom controller)

    more?

*/

#include "emu.h"
#include "includes/megadriv.h"
#include "includes/megadriv_rad.h"

// todo, use actual MD map, easier once maps are part of base class.
void megadriv_radica_state::megadriv_base_map(address_map &map)
{
	map(0x000000, 0x3fffff).r(FUNC(megadriv_radica_state::read)); /* Cartridge Program Rom */
	map(0xa00000, 0xa01fff).rw(FUNC(megadriv_radica_state::megadriv_68k_read_z80_ram), FUNC(megadriv_radica_state::megadriv_68k_write_z80_ram));
	map(0xa02000, 0xa03fff).w(FUNC(megadriv_radica_state::megadriv_68k_write_z80_ram));
	map(0xa04000, 0xa04003).rw(FUNC(megadriv_radica_state::megadriv_68k_YM2612_read), FUNC(megadriv_radica_state::megadriv_68k_YM2612_write));
	map(0xa06000, 0xa06001).w(FUNC(megadriv_radica_state::megadriv_68k_z80_bank_write));
	map(0xa10000, 0xa1001f).rw(FUNC(megadriv_radica_state::megadriv_68k_io_read), FUNC(megadriv_radica_state::megadriv_68k_io_write));
	map(0xa11100, 0xa11101).rw(FUNC(megadriv_radica_state::megadriv_68k_check_z80_bus), FUNC(megadriv_radica_state::megadriv_68k_req_z80_bus));
	map(0xa11200, 0xa11201).w(FUNC(megadriv_radica_state::megadriv_68k_req_z80_reset));
	map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w));
	map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram");
}

void megadriv_radica_state::megadriv_radica_map(address_map &map)
{
	megadriv_base_map(map);
	map(0xa13000, 0xa130ff).r(FUNC(megadriv_radica_state::read_a13));
}

uint16_t megadriv_dgunl_state::read_a16300(offs_t offset, uint16_t mem_mask)
{
	return 0x5a5a;
}

uint16_t megadriv_dgunl_state::read_a16302(offs_t offset, uint16_t mem_mask)
{
	return m_a1630a;
}

void megadriv_dgunl_state::write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask)
{
	m_a1630a = data;
	m_bank = (data & 0x07) * 8;
}


void megadriv_ra145_state::write_a1630a(offs_t offset, uint16_t data, uint16_t mem_mask)
{
	// the banking must know how big each game is to get the base location, as it only writes a game number?!
	// it must also know to skip the unused copy of Golden Axe
	// there must be a table somewhere, or, if this is actually an emulation based system, it must be scanning
	// for headers somehow?

	m_a1630a = data;

	switch (data & 0xff)
	{


	//                  0x0000000           = Block of unknown data/code
	//                  0x0040000           = 145 in 1 menu
	//                  (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data)
	case 0x00: m_bank = 0x02c0000; break;// = Fantasia                               00
	case 0x01: m_bank = 0x0340000; break;// = Fire Shark                             01
	case 0x02: m_bank = 0x03c0000; break;// = James Bond 007 - The Duel              02  (BAD ROM)
	case 0x03: m_bank = 0x0440000; break;// = Sunset Riders                          03
	case 0x04: m_bank = 0x04c0000; break;// = Robocop 3                              04
	case 0x05: m_bank = 0x0540000; break;// = Hokuto no Ken                          05  (BAD ROM)
	case 0x06: m_bank = 0x05c0000; break;// = Alien 3                                06
	case 0x07: m_bank = 0x0640000; break;// = Batman                                 07  (BAD ROM)
	case 0x08: m_bank = 0x06c0000; break;// = Cat                                    08
	case 0x09: m_bank = 0x0740000; break;// = DJ Boy                                 09
	case 0x0a: m_bank = 0x07c0000; break;// = Rambo 3                                0a  (BAD ROM)
	case 0x0b: m_bank = 0x0840000; break;// = Wardner                                0b
	case 0x0c: m_bank = 0x08c0000; break;// = Paperboy                               0c
	case 0x0d: m_bank = 0x0940000; break;// = Streets of Rage                        0d
	case 0x0e: m_bank = 0x09c0000; break;// = Tiny Toon Adventures                   0e
	case 0x0f: m_bank = 0x0a40000; break;// = Super Battleship                       0f
	case 0x10: m_bank = 0x0ac0000; break;// = Burning Force                          10
	case 0x11: m_bank = 0x0b40000; break;// = Cadash                                 11
	case 0x12: m_bank = 0x0bc0000; break;// = Caesars Palace                         12
	case 0x13: m_bank = 0x0c40000; break;// = chase HQ 2                             13
	case 0x14: m_bank = 0x0cc0000; break;// = Wonderboy 3                            14
	case 0x15: m_bank = 0x0d40000; break;// = Fighting Master                        15
	case 0x16: m_bank = 0x0dc0000; break;// = The Flintstones                        16
	case 0x17: m_bank = 0x0e40000; break;// = Ariel the Little Mermaid               17
	case 0x18: m_bank = 0x0ec0000; break;// = Hellfire                               18
	case 0x19: m_bank = 0x0f40000; break;// = Arrow Flash                            19
	case 0x1a: m_bank = 0x0fc0000; break;// = Shove It                               1a
	case 0x1b: m_bank = 0x1040000; break;// = Donkey Kong 99                         1b
	case 0x1c: m_bank = 0x1240000; break;// = Turtles Tournament                     1c
	case 0x1d: m_bank = 0x1440000; break;// = Thunder Force 2                        1d  (This is meant to be Revenge of Shinobi according to the menu, but incorrect game was in the ROM)
	case 0x1e: m_bank = 0x14c0000; break;// = Wings of Wor                           1e
	case 0x1f: m_bank = 0x1540000; break;// = Wrestle War                            1f
	case 0x20: m_bank = 0x15c0000; break;// = Afterburner 2                          20
	case 0x21: m_bank = 0x1640000; break;// = Altered Beast                          21
	case 0x22: m_bank = 0x16c0000; break;// = Captain Planet                         22
	case 0x23: m_bank = 0x1740000; break;// = Bimimi Run                             23
	case 0x24: m_bank = 0x17c0000; break;// = Osomatsu                               24
	case 0x25: m_bank = 0x1840000; break;// = Castle of Illusion                     25
	case 0x26: m_bank = 0x18c0000; break;// = Crackdown                              26
	case 0x27: m_bank = 0x1940000; break;// = Crossfire                              27
	case 0x28: m_bank = 0x19c0000; break;// = Curse                                  28
	case 0x29: m_bank = 0x1a40000; break;// = Dangerous Seed                         29
	case 0x2a: m_bank = 0x1ac0000; break;// = Dark Castle                            2a
	case 0x2b: m_bank = 0x1b40000; break;// = Darwin                                 2b
	case 0x2c: m_bank = 0x1bc0000; break;// = Thunder Force 2 (duplicate?)           2c
	case 0x2d: m_bank = 0x1c40000; break;// = Dynamite Duke                          2d
	case 0x2e: m_bank = 0x1cc0000; break;// = EA Hockey                              2e
	case 0x2f: m_bank = 0x1d40000; break;// = Elemenal Master                        2f
	case 0x30: m_bank = 0x1dc0000; break;// = Super Thunder Blade                    30
	case 0x31: m_bank = 0x1e40000; break;// = Target Earth                           31
	case 0x32: m_bank = 0x1ec0000; break;// = Rastan Saga 2                          32
	case 0x33: m_bank = 0x1f40000; break;// = Ghostbusters                           33
	case 0x34: m_bank = 0x1fc0000; break;// = Mahjong cop                            34
	case 0x35: m_bank = 0x2040000; break;// = High School Soccer                     35
	case 0x36: m_bank = 0x20c0000; break;// = Insector X                             36
	case 0x37: m_bank = 0x2140000; break;// = Pheilos                                37
	case 0x38: m_bank = 0x21c0000; break;// = Runark                                 38
	case 0x39: m_bank = 0x2240000; break;// = Saint Sword                            39
	case 0x3a: m_bank = 0x22c0000; break;// = Shadow Dancer                          3a
	case 0x3b: m_bank = 0x2340000; break;// = Shiten Myooh                           3b
	case 0x3c: m_bank = 0x23c0000; break;// = Wani Wani World                        3c
	case 0x3d: m_bank = 0x2440000; break;// = Street Mmart                           3d
	case 0x3e: m_bank = 0x24c0000; break;// = Toki                                   3e
	case 0x3f: m_bank = 0x2540000; break;// = Trouble Shooter                        3f
	case 0x40: m_bank = 0x25c0000; break;// = Truxton                                40
	case 0x41: m_bank = 0x2640000; break;// = James Pond 2                           41
	case 0x42: m_bank = 0x26c0000; break;// = Twin Hawk                              42
	case 0x43: m_bank = 0x2740000; break;// = Syd of Valis                           43
	case 0x44: m_bank = 0x27c0000; break;// = Zoom                                   44
	case 0x45: m_bank = 0x2840000; break;// = Streets of Rage 2                      45
	case 0x46: m_bank = 0x2a40000; break;// = Sonic & Knuckles                       46
	case 0x47: m_bank = 0x2c40000; break;// = Comix Zone                             47
	case 0x48: m_bank = 0x2e40000; break;// = Rolling Thunder 2                      48
	case 0x49: m_bank = 0x2f40000; break;// = Bubble & Squeek                        49
	case 0x4a: m_bank = 0x2fc0000; break;// = Alex Kidd                              4a
	case 0x4b: m_bank = 0x3040000; break;// = Super Mario 2                          4b
	case 0x4c: m_bank = 0x3240000; break;// = NBA All Star                           4c
	case 0x4d: m_bank = 0x3340000; break;// = Bio Hazard Battle                      4d
	case 0x4e: m_bank = 0x3440000; break;// = Prince of Persia                       4e
	case 0x4f: m_bank = 0x3540000; break;// = Champions World Soccer                 4f
	case 0x50: m_bank = 0x3640000; break;// = Lotus 2                                50
	case 0x51: m_bank = 0x3740000; break;// = Grandia                                51
	case 0x52: m_bank = 0x37c0000; break;// = World Cup Soccer                       52
	case 0x53: m_bank = 0x3840000; break;// = Ultimate Mortal Kombat 3               53
	case 0x54: m_bank = 0x3c40000; break;// = Street Fighter II (hacked MSI version) 54
	case 0x55: m_bank = 0x3f40000; break;// = Verytex                                55
	case 0x56: m_bank = 0x3fc0000; break;// = Space Invaders 90                      56

	//This 32MBytes of the ROM has its own unused '666666 in 1 menu' and only references games
	//within this block; it was probably released as a standalone using this 32Mbytes of ROM
	//                  0x4000000 = Block of unknown data/code
	//                  0x4040000 = 666666 in 1 menu
	//                  (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data)
	//                  0x42c0000 - Golden Axe                             -- (not used by 145-in-1 menu, no assigned number either?!)
	case 0x57: m_bank = 0x4340000; break;// - Mega Bomberman                         57
	case 0x58: m_bank = 0x4440000; break;// - Dragon The Bruce Lee Story             58
	case 0x59: m_bank = 0x4640000; break;// - Twinkle Tale                           59
	case 0x5a: m_bank = 0x4740000; break;// - Jewel Master                           5a
	case 0x5b: m_bank = 0x47c0000; break;// - Pacmania                               5b
	case 0x5c: m_bank = 0x4840000; break;// - X-Men 2                                5c
	case 0x5d: m_bank = 0x4a40000; break;// - Top Gear 2                             5d
	case 0x5e: m_bank = 0x4b40000; break;// - Brian Lara Cricket                     5e
	case 0x5f: m_bank = 0x4c40000; break;// - Garfield                               5f
	case 0x60: m_bank = 0x4e40000; break;// - Raiden Trad                            60
	case 0x61: m_bank = 0x4f40000; break;// - James Pond                             61
	case 0x62: m_bank = 0x4fc0000; break;// - Mega Panel                             62
	case 0x63: m_bank = 0x5040000; break;// - James Pond 3                           63
	case 0x64: m_bank = 0x5240000; break;// - Contra Hardcorps                       64
	case 0x65: m_bank = 0x5440000; break;// - International Superstar Soccer Deluxe  65
	case 0x66: m_bank = 0x5640000; break;// - Double Dragon 3 (with Trainer)         66
	case 0x67: m_bank = 0x5740000; break;// - Micro Machines                         67
	case 0x68: m_bank = 0x57c0000; break;// - Hard Drivin'                           68
	case 0x69: m_bank = 0x5840000; break;// - Dragon Ball Z                          69
	case 0x6a: m_bank = 0x5a40000; break;// - F1 World Championship Edition          6a
	case 0x6b: m_bank = 0x5c40000; break;// - Megaman / Rockman                      -- (6b, but unused? probably due to save feature?)
	case 0x6c: m_bank = 0x5e40000; break;// - Operation Vapor Trail                  6c
	case 0x6d: m_bank = 0x5f40000; break;// - Roadblasters                           6d
	case 0x6e: m_bank = 0x5fc0000; break;// - Super Volleyball                       6e

	//The final 32MBytes of the ROM has its own unused '888888 in 1 menu' and only references games
	//within this block; it was probably released as a standalone using this 32Mbytes of ROM
	//                  0x6000000 = Block of unknown data/code
	//                  0x6040000 = 888888 in 1 menu
	//                  (includes unused Columns, Fatal Labyrinth, Blockout, Flicky, Shove It, Space Invaders 90 as part of menu data)
	case 0x6f: m_bank = 0x62c0000; break;// - Last Battle                            6f
	case 0x70: m_bank = 0x6340000; break;// - Shinobi III                            70
	case 0x71: m_bank = 0x6440000; break;// - Mickey Mania                           71
	case 0x72: m_bank = 0x6640000; break;// - Snow Bros                              72
	case 0x73: m_bank = 0x6740000; break;// - Space Harrier II                       73
	case 0x74: m_bank = 0x67c0000; break;// - Volfied                                74
	case 0x75: m_bank = 0x6840000; break;// - Goofy's Hysterical History Tour        75
	case 0x76: m_bank = 0x6940000; break;// - Mighty Max                             76
	case 0x77: m_bank = 0x6a40000; break;// - Mr Nutz                                77
	case 0x78: m_bank = 0x6b40000; break;// - Sonic 2                                78
	case 0x79: m_bank = 0x6c40000; break;// - Ecco Jr.                               79
	case 0x7a: m_bank = 0x6d40000; break;// - Desert Demolition                      7a
	case 0x7b: m_bank = 0x6e40000; break;// - Midnight Resistance                    7b
	case 0x7c: m_bank = 0x6f40000; break;// - Spiderman vs The Kingpin               7c
	case 0x7d: m_bank = 0x6fc0000; break;// - Trampoline Terror                      7d
	case 0x7e: m_bank = 0x7040000; break;// - MUSHA                                  7e
	case 0x7f: m_bank = 0x70c0000; break;// - Sonic                                  7f
	case 0x80: m_bank = 0x7140000; break;// - Thunder Force III                      80
	case 0x81: m_bank = 0x71c0000; break;// - Golden Axe (again)                     81
	//                  0x7240000; break;// - Controller Test Menu                   -- (unused)
	//                  0x7340000; break;// - Controller Test Menu (again)           -- (unused)
	case 0x82: m_bank = 0x7440000; break;// - Wacky Worlds                           82 (writes 93, incorrectly swapped in menu with Wacky Worlds)
	case 0x83: m_bank = 0x7540000; break;// - Bonkers                                83
	case 0x84: m_bank = 0x7640000; break;// - Alisia Dragoon                         84
	case 0x85: m_bank = 0x7740000; break;// - Super Hang On                          85
	case 0x86: m_bank = 0x77c0000; break;// - Dragon's Eye Shanghai 3                86
	case 0x87: m_bank = 0x7840000; break;// - Jimmy White's Whirlwind Snooker        87
	case 0x88: m_bank = 0x78c0000; break;// - Home Alone 2                           88
	case 0x89: m_bank = 0x7940000; break;// - Xenon 2 (with trainer)                 89
	case 0x8a: m_bank = 0x79c0000; break;// - Hit the Ice                            8a
	case 0x8b: m_bank = 0x7a40000; break;// - Tale Spin                              8b
	case 0x8c: m_bank = 0x7ac0000; break;// - Puyo Puyo                              8c
	case 0x8d: m_bank = 0x7b40000; break;// - Rampart (with trainer)                 8d
	case 0x8e: m_bank = 0x7bc0000; break;// - Crue Ball                              8e
	case 0x8f: m_bank = 0x7c40000; break;// - Marble Madness                         8f
	case 0x90: m_bank = 0x7cc0000; break;// - Patlabor                               90
	case 0x91: m_bank = 0x7d40000; break;// - The Aquatic Games                      91
	case 0x92: m_bank = 0x7dc0000; break;// - King Salmon                            92
	case 0x93: m_bank = 0x7e40000; break;// - Fun n Games                            93 (writes 82, incorrectly swapped in menu with Fun n Games)
	case 0x94: m_bank = 0x7f40000; break;// - Gynoug                                 94
	case 0x95: m_bank = 0x7fc0000; break;// - Ms. Pac-Man                            95
	default:   m_bank = 0x0040000; break;
	}

	m_bank = m_bank / 0x10000;
}


void megadriv_dgunl_state::megadriv_dgunl_map(address_map &map)
{
	megadriv_base_map(map);

	map(0xa16300, 0xa16301).r(FUNC(megadriv_dgunl_state::read_a16300));
	map(0xa16302, 0xa16303).r(FUNC(megadriv_dgunl_state::read_a16302));

	map(0xa1630a, 0xa1630b).w(FUNC(megadriv_dgunl_state::write_a1630a));
}

uint16_t megadriv_radica_state::read(offs_t offset)
{
	return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (m_romsize - 1))/2];
}

uint16_t megadriv_radica_state::read_a13(offs_t offset)
{
	if (offset < 0x80)
		m_bank = offset & 0x3f;

	// low bit gets set when selecting cannon fodder or mega lo mania in the rad_ssoc set, pointing to the wrong area, but rad_gen1 needs it for the menu
	// as they're standalones it could just be different logic
	if (m_bank != 0x3f)
		m_bank &= 0x3e;

	return 0;
}

// controller is wired directly into unit, no controller slots
static INPUT_PORTS_START( megadriv_radica_3button )
	PORT_INCLUDE( md_common )

	PORT_MODIFY("PAD1")
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 )

	PORT_MODIFY("PAD2")
	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 )
INPUT_PORTS_END

// the 6-in-1 and Sonic Gold units really only have a single wired controller, and no way to connect a 2nd one, despite having some 2 player games!
static INPUT_PORTS_START( megadriv_radica_3button_1player )
	PORT_INCLUDE( megadriv_radica_3button )

	PORT_MODIFY("PAD2")
	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END

static INPUT_PORTS_START( megadriv_radica_6button )
	PORT_INCLUDE( megadriv_radica_3button )

	PORT_START("EXTRA1")    /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START("EXTRA2")    /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START("IN0")
	PORT_START("UNK")
INPUT_PORTS_END

static INPUT_PORTS_START( megadriv_msi_6button )
	PORT_INCLUDE( megadriv_radica_3button )

	PORT_START("EXTRA1")    /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */
	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1)
	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1)
	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START("EXTRA2") // no 2nd pad
	PORT_BIT( 0x000f, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_MODIFY("PAD2") // no 2nd pad
	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )

	PORT_START("IN0")
	PORT_START("UNK")
INPUT_PORTS_END

static INPUT_PORTS_START( megadriv_dgunl_1player )
	PORT_INCLUDE( megadriv_radica_3button )

	PORT_MODIFY("PAD1") // the unit only has 2 buttons, A and C, strings are changed to remove references to C, even if behavior in Pac-Mania still exists and differs between them
	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED ) // disable 'C'
	//PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) // disable 'A'

	PORT_MODIFY("PAD2")
	PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END

void megadriv_radica_6button_state::machine_start()
{
	md_base_state::machine_start();
	m_vdp->stop_timers();

	m_io_pad_6b[0] = ioport("EXTRA1");
	m_io_pad_6b[1] = ioport("EXTRA2");
	m_io_pad_6b[2] = ioport("IN0");
	m_io_pad_6b[3] = ioport("UNK");

	// setup timers for 6 button pads
	for (int i = 0; i < 3; i++)
		m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this);

	save_item(NAME(m_bank));
}

void megadriv_radica_3button_state::machine_start()
{
	md_base_state::machine_start();
	m_vdp->stop_timers();
	save_item(NAME(m_bank));
}


void megadriv_dgunl_state::machine_start()
{
	megadriv_radica_3button_state::machine_start();
	m_a1630a = 0;
	save_item(NAME(m_a1630a));
}

void megadriv_ra145_state::machine_start()
{
	md_base_state::machine_start();
	m_vdp->stop_timers();

	m_io_pad_6b[0] = ioport("EXTRA1");
	m_io_pad_6b[1] = ioport("EXTRA2");
	m_io_pad_6b[2] = ioport("IN0");
	m_io_pad_6b[3] = ioport("UNK");

	// setup timers for 6 button pads
	for (int i = 0; i < 3; i++)
		m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this);

	m_a1630a = 0;
	save_item(NAME(m_a1630a));
	save_item(NAME(m_bank));
}

void megadriv_ra145_state::machine_reset()
{
	m_bank = 4;
	md_base_state::machine_reset();
}


void megadriv_radica_3button_state::machine_reset()
{
	m_bank = 0;
	md_base_state::machine_reset();
}

void megadriv_radica_3button_state::megadriv_radica_3button_ntsc(machine_config &config)
{
	md_ntsc(config);
	m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map);
}

void megadriv_radica_3button_state::megadriv_radica_3button_pal(machine_config &config)
{
	md_pal(config);
	m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map);
}

void megadriv_radica_6button_state::megadriv_radica_6button_pal(machine_config &config)
{
	md_pal(config);
	m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map);
}

void megadriv_radica_6button_state::megadriv_radica_6button_ntsc(machine_config &config)
{
	md_ntsc(config);
	m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_radica_state::megadriv_radica_map);
}

void megadriv_dgunl_state::megadriv_dgunl_ntsc(machine_config &config)
{
	md_ntsc(config);
	m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_dgunl_state::megadriv_dgunl_map);
}

ROM_START( rad_sf2 )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_megadrive_streetfighter2_usa.bin", 0x000000, 0x400000, CRC(a4426df8) SHA1(091f2a95ebd091141de5bcb83562c6087708cb32) )
ROM_END

ROM_START( rad_sf2p )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_megadrive_streetfighter2_uk.bin", 0x000000, 0x400000,  CRC(868afb44) SHA1(f4339e36272c18b1d49aa4095127ed18e0961df6) )
ROM_END

ROM_START( rad_gen1 )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol1_blue_usa.bin", 0x000000, 0x400000,  CRC(3b4c8438) SHA1(5ed9c053f9ebc8d4bf571d57e562cf347585d158) )
ROM_END

ROM_START( rad_md1 )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol1_blue_europe.bin", 0x000000, 0x400000, CRC(85867db1) SHA1(ddc596e2e68dc872bc0679a2de7a295b4c6d6b8e) )
ROM_END

ROM_START( rad_gen2 )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_genesis_vol2_red_usa.bin", 0x000000, 0x400000, CRC(7c1a0f0e) SHA1(a6441f75a4cd48f1563aeafdfbdde00202d4067c) )
ROM_END

ROM_START( rad_md2 )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_megadrive_vol2_red_uk.bin", 0x000000, 0x400000, CRC(b68fd025) SHA1(b8f9c505653d6dd2b62840f078f828360faf8abc) )
ROM_END

ROM_START( rad_ssoc )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD( "radica_sensiblesoccer_uk.bin", 0x000000, 0x400000,  CRC(b8745ab3) SHA1(0ab3f26e5ffd288e5a3a5db676951b9095299eb0) ) // should be byteswapped?
ROM_END

ROM_START( rad_sonic )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_supersonicgold_usa.bin", 0x000000, 0x400000, CRC(853c9140) SHA1(cf70a9cdd3be4d8d1b6195698db3a941f4908791) )
ROM_END

ROM_START( rad_sonicp )
	ROM_REGION( 0x400000, "maincpu", 0 )
	ROM_LOAD16_WORD_SWAP( "radica_supersonicgold_uk.bin", 0x000000, 0x400000, CRC(ed774018) SHA1(cc2f7183e128c947463e3a43a0184b835ea16db8) )
ROM_END

// once byteswapped this matches "outrun 2019 (usa) (beta).bin  megadriv:outr2019up Out Run 2019 (USA, Prototype)"
// this was dumped from a PAL/UK unit, so maybe that 'beta' is really an alt Euro release, or was simply dumped from one of these Radica units and mislabeled?
ROM_START( rad_orun )
	ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASEFF )
	ROM_LOAD16_WORD_SWAP( "outrun.bin", 0x000000, 0x100000, CRC(4fd6d653) SHA1(57f0e4550ff883e4bb7857caef2c893c21f80b42) )
ROM_END

ROM_START( msi_sf2 )
	ROM_REGION( 0x400000, "maincpu", 0 )
	// The first part of the ROM seems to be a boot ROM for the enhanced MD clone menus, even if it does nothing here
	// and is probably leftover from one of the multigame systems, hacked to only launch one game. We should emulate it...
	// .. but the game ROM starts at 0xc8000 so we can cheat for now
	ROM_LOAD16_WORD_SWAP( "29lv320.bin", 0x000000, 0xc8000, CRC(465b12f0) SHA1(7a058f6feb4f08f56ae0f7369c2ca9a9fe2ed40e) )
	ROM_CONTINUE(0x00000,0x338000)
ROM_END

ROM_START( dgunl3227 )
	ROM_REGION( 0x400000, "maincpu", ROMREGION_ERASE00 )
	// populated in init function

	ROM_REGION( 0x400000, "rom", 0 )
	ROM_LOAD16_WORD_SWAP( "myarcadepacman_s99jl032hbt1_9991227e_as_s29jl032h55tai01.bin", 0x000000, 0x400000, CRC(ecead966) SHA1(971e8da6eb720f670f4148c7e07922e4f24eb609) )
ROM_END



ROM_START( ra145 )
	/*
	Data for the following games is corrupt (ranges approximate, based on areas of inconsistent readout)

	3c0000 - 43ffff - James Bond 007 - The Duel   (400171 - 41c600 is corrupt)
	4c0000 - 53ffff - Robocop 3                   (507bd4 - 50ad43 is corrupt)
	540000 - 5bffff - Hokuto no Ken               (540006 - 55fff2 is corrupt)
	640000 - 6bffff - Batman                      (640042 - 65ffaf is corrupt)
	7c0000 - 7fffff - Rambo 3                     (7e031a - 7fffb9 is corrupt)

	Unfortunately as many of the games in this unit have been hacked, or are using pirate versions of the games
	from the mid 90s (in a few cases, complete with trainers) that seem to have dropped out of circulation it
	is not possible to repair the data in dump from the damaged unit.

	The unit also includes a duplicate copy of Thunder Force II instead of Revenge of Shinobi, this however
	is not a dump issue, nor is Wacky Worlds being swapped with Fun and Games in the menu
	*/

	ROM_REGION( 0x8000000, "maincpu", ROMREGION_ERASE00 )
	ROM_LOAD16_WORD_SWAP( "ra145.bin", 0x000000, 0x8000000, BAD_DUMP CRC(30583950) SHA1(855eae232e3830a505f9bc1a26edb3a7d15ce4d1) )
ROM_END




void megadriv_radica_6button_state::init_megadriv_radica_6button_pal()
{
	init_megadrie();
	// 6 button game, so overwrite 3 button io handlers
	m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button));
	m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button));
}

void megadriv_radica_6button_state::init_megadriv_radica_6button_ntsc()
{
	init_megadriv();
	// 6 button game, so overwrite 3 button io handlers
	m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button));
	m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button));
}

void megadriv_dgunl_state::init_dgunl3227()
{
	uint8_t* rom = memregion("rom")->base();
	uint8_t* dst = memregion("maincpu")->base();
	size_t len = memregion("rom")->bytes();

	std::vector<u8> buffer(len);

	for (int i = 0; i < len; i++)
		buffer[i] = rom[i ^ 3];

	std::copy(buffer.begin(), buffer.end(), &rom[0]);

	int baseaddr, size, dstaddr;
	//baseaddr = 0x200000; size = 0x40000; // unknown data (unused menu data maybe?)
	//baseaddr = 0x240000; size = 0x20000; // 'sample' program with UWOL header later too (lower part of menu program)
	//baseaddr = 0x260000; size = 0x20000; // pirate version of Columns with Sega text removed
	//baseaddr = 0x280000; size = 0x20000; // Fatal Labyrinth
	//baseaddr = 0x2a0000; size = 0x20000; // pirate version of Block Out with EA logo and text removed
	//baseaddr = 0x2c0000; size = 0x20000; // Flicky
	//baseaddr = 0x2e0000; size = 0x20000; // Shove It
	//baseaddr = 0x300000; size = 0x40000; // pirate version of Space Invaders 90 with Taito logos and copyright removed (also upper part of menu program - has extra header + bits of code for '202 in 1' menu which has been hacked to run the 3-in-1 menu)

	// the following 3 games are available to select from the menu on this system
	//baseaddr = 0x340000; size = 0x40000; // Pac-Attack / Pac-Panic (used by this unit)
	//baseaddr = 0x380000; size = 0x40000; // Pac-Mania (used by this unit)
	//baseaddr = 0x3c0000; size = 0x40000; // Pac-Man (used by this unit) (2nd copy of header about halfway through?)

	// copy 1st part of menu code
	baseaddr = 0x240000;
	size     = 0x020000;
	dstaddr  = 0x000000;
	for (int i = 0; i < size; i++)
	{
		dst[i + dstaddr] = rom[baseaddr + i];
	}

	// copy 2nd part of menu code
	baseaddr = 0x300000;
	size =     0x040000;
	dstaddr =  0x0c0000;
	for (int i = 0; i < size; i++)
	{
		dst[i + dstaddr] = rom[baseaddr + i];
	}

	// copy pac-panic to first bank
	baseaddr = 0x340000;
	size =     0x040000;
	dstaddr =  0x100000;
	for (int i = 0; i < size; i++)
	{
		dst[i + dstaddr] = rom[baseaddr + i];
	}

	// copy pac-mania to 2nd bank
	baseaddr = 0x380000;
	size =     0x040000;
	dstaddr =  0x180000;
	for (int i = 0; i < size; i++)
	{
		dst[i + dstaddr] = rom[baseaddr + i];
	}

	// copy pac-man to 3nd bank
	baseaddr = 0x3c0000;
	size =     0x040000;
	dstaddr =  0x200000;
	for (int i = 0; i < size; i++)
	{
		dst[i + dstaddr] = rom[baseaddr + i];
	}

	// other data isn't copied because it's never referenced, therefore we don't know how it gets accessed

	init_megadriv();
}

void megadriv_ra145_state::init_ra145()
{
	m_romsize = 0x8000000;
	init_megadriv();
	// 6 button game, so overwrite 3 button io handlers
	m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button));
	m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button));
}

// US versions show 'Genesis' on the menu,    show a www.radicagames.com splash screen, and use NTSC versions of the ROMs, sometimes region locked
// EU versions show 'Mega Drive' on the menu, show a www.radicagames.com splash screen, and use PAL versions of the ROMs, sometimes region locked
// UK versions show "Mega Drive' on the menu, show a www.radicauk.com splash screen,    and use PAL versions of the ROMs, sometimes region locked


CONS( 2004, rad_gen1,  0,        0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv,                    "Radica / Sega",                     "Genesis Collection Volume 1 (Radica, Arcade Legends) (USA)", 0)
CONS( 2004, rad_md1,   rad_gen1, 0, megadriv_radica_3button_pal,  megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie,                    "Radica / Sega",                     "Mega Drive Collection Volume 1 (Radica, Arcade Legends) (Europe)", 0)
// A UK version exists, showing the Radica UK boot screen

CONS( 2004, rad_gen2,  0,        0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv,                    "Radica / Sega",                     "Genesis Collection Volume 2 (Radica, Arcade Legends) (USA)", 0)
CONS( 2004, rad_md2,   rad_gen2, 0, megadriv_radica_3button_pal,  megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie,                    "Radica / Sega",                     "Mega Drive Collection Volume 2 (Radica, Arcade Legends) (UK)", 0)
// is there a Europe version with Radica Games boot screen and Mega Drive text?

// box calls this Volume 3
CONS( 2004, rad_sonic, 0,        0, megadriv_radica_3button_ntsc, megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadriv,                    "Radica / Sega",                     "Super Sonic Gold (Radica Plug & Play) (USA)", 0)
CONS( 2004, rad_sonicp,rad_sonic,0, megadriv_radica_3button_pal,  megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie,                    "Radica / Sega",                     "Super Sonic Gold (Radica Plug & Play) (UK)", 0)
// is there a Europe version with Radica Games boot screen and Mega Drive text?

CONS( 2004, rad_sf2,   0,        0, megadriv_radica_6button_ntsc, megadriv_radica_6button,         megadriv_radica_6button_state, init_megadriv_radica_6button_ntsc,"Radica / Capcom / Sega",            "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (USA)", 0)
CONS( 2004, rad_sf2p,  rad_sf2,  0, megadriv_radica_6button_pal,  megadriv_radica_6button,         megadriv_radica_6button_state, init_megadriv_radica_6button_pal, "Radica / Capcom / Sega",            "Street Fighter II: Special Champion Edition [Ghouls'n Ghosts] (Radica, Arcade Legends) (UK)", 0)
// is there a Europe version with Radica Games boot screen and Mega Drive text?

// still branded as Arcade Legends even if none of these were ever arcade games, European exclusive
CONS( 2004, rad_ssoc,  0,        0, megadriv_radica_3button_pal,  megadriv_radica_3button,         megadriv_radica_3button_state, init_megadrie,                    "Radica / Sensible Software / Sega", "Sensible Soccer plus [Cannon Fodder, Mega lo Mania] (Radica, Arcade Legends) (UK)", 0)
// is there a Europe version with Radica Games boot screen and Mega Drive text?

// not region locked, no Radica logos, uncertain if other regions would differ
CONS( 2004, rad_orun,  0,        0, megadriv_radica_3button_pal,  megadriv_radica_3button_1player, megadriv_radica_3button_state, init_megadrie,                    "Radica / Sega",                     "Out Run 2019 (Radica Plug & Play, UK)", 0)

// From a European unit but NTSC? - code is hacked from original USA Genesis game with region check still intact? (does the clone hardware always identify as such? or does the bypassed boot code skip the check?)
// TODO: move out of here eventually once the enhanced MD part is emulated rather than bypassed (it's probably the same as the 145-in-1 multigame unit, but modified to only include this single game)
CONS( 2018, msi_sf2,   0,        0, megadriv_radica_6button_ntsc, megadriv_msi_6button,         megadriv_radica_6button_state, init_megadriv_radica_6button_ntsc,    "MSI / Capcom / Sega",            "Street Fighter II: Special Champion Edition (MSI Plug & Play) (Europe)", 0)

// Are these (dgunl3227, ra145) actually emulation based? there is a block of 0x40000 bytes at the start of the ROM that doesn't
// appear to be used, very similar in both units.  Banking also seems entirely illogical unless something else is managing it.
// The menu code in both seems to have the same origin, containing a bunch of unused pirate versions of MD games.
// The version of SF2 in the 'ra145' unit is the same as the one in the MSI unit above, and expects region to report US even
// when some of the units run at PAL speed?
// It is also confirmed from real hardware videos that these units do not have the usual sprite limits (so masking effect on Sonic title screen fails)

// this is the only 'Pocket Player' unit to use Genesis on a Chip tech, the others are NES on a chip.
// some versions of this unit have an additional "Add Credits with 'A' or 'B'" screen after you select Pac-Man, this version does not.
CONS( 2018, dgunl3227, 0,        0, megadriv_dgunl_ntsc, megadriv_dgunl_1player,         megadriv_dgunl_state, init_dgunl3227,    "dreamGEAR",            "My Arcade Pac-Man Pocket Player (DGUNL-3227)", 0 )

CONS( 2018, ra145,     0,        0, megadriv_dgunl_ntsc, megadriv_msi_6button,           megadriv_ra145_state, init_ra145,        "<unknown>",            "Retro Arcade 16 Bits Classic Edition Mini TV Game Console - 145 Classic Games - TV Arcade Plug and Play (Mega Drive bootlegs)", MACHINE_NOT_WORKING )